NOGDUS

Welcome to NOGDUS => Newbie Corner => Topic started by: jearca on April 30, 2010, 02:26:24 PM



Title: Creation Custom Mesh (c++, directx)
Post by: jearca on April 30, 2010, 02:26:24 PM
hi,i make a litle motor 3d , i want to learn all about directx and c++ , i from peru in my country i can not find any help, i search for all webs about directx in my natal lenguaje (spanish), but i can not found, i know a litle english, and I was studying from books in English. but now i have a problem, i can load a mesh from .x file, but for security and to safeguard the essence of the game,i need to know how i can load from custom mesh format.
I was looking for in the web  and I found that this could be done with Get / setIndexbuffer and Get / SetVertexbuffer, but I could not find any function.

Please help me. Sorry for my bad English.


Title: Re: Creation Custom Mesh (c++, directx)
Post by: Richard Marks on April 30, 2010, 10:34:06 PM
First, Welcome to NOGDUS jearca!

Okay, I need to start by saying that you sound like you are trying to do more than you are ready to do.

You do not need to worry about security and safeguarding your game assets unless you are working on a commercial game, in which case you would not even be here. So throw that entire idea out.

You are a beginner, and as such you should not worry about such advanced topics such as implementations of custom mesh formats and keeping your game assets from being edited.

But, I can however provide a little light on the subject that you ask about.
But right now I need to call it a night, its late.
I'll write something up for you tomorrow.





Title: Re: Creation Custom Mesh (c++, directx)
Post by: jearca on April 30, 2010, 11:00:22 PM
First, Welcome to NOGDUS jearca!

Okay, I need to start by saying that you sound like you are trying to do more than you are ready to do.

You do not need to worry about security and safeguarding your game assets unless you are working on a commercial game, in which case you would not even be here. So throw that entire idea out.

You are a beginner, and as such you should not worry about such advanced topics such as implementations of custom mesh formats and keeping your game assets from being edited.

But, I can however provide a little light on the subject that you ask about.
But right now I need to call it a night, its late.
I'll write something up for you tomorrow.

Hi and thanks for the welcome, it is true that my question is rather complex, but like any student, we always create doubts, I think not only for a commercial game is necessary to protect the integrity of files. that did not really seem fair that someone modify my application, at your convenience (I'm sure it would happen).
My question on this subject is more by a desire to learn, since my current program only depends on the most important functions, took more than two years trying to learn every day more about this very powerful tool and would appreciate any help.
I say goodbye and I am grateful infinitely help me in this issue


Title: Re: Creation Custom Mesh (c++, directx)
Post by: Richard Marks on May 01, 2010, 12:03:47 PM
OK, here you go. A complete example on using VertexBuffers and a custom mesh file.

The mesh file format right now is obscenely simple. Just a list of float vertex data.

The program needs to be run twice. The first time you run the program it will generate the mesh data file.
The second time you run the program, you should see a cube textured and rotating.

If you've got questions, post them.

Note: To run the code, you will need to supply a texture.bmp file that is 128x128 and 24bit.

Code:
// D3DMeshDemo.cpp
// Direct3D Mesh Demo
// (C) 2010, Richard Marks ccpsceo@gmail.com
// www.ccpssolutions.com

#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "winmm.lib")

#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <windows.h>
#include <mmsystem.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <string>
#include <vector>
#include <sstream>

// ===================================================

// vertex position and texture coordinates
DWORD CustomVertexFVF = (D3DFVF_XYZ | D3DFVF_TEX1);
struct CustomVertex
{
float X, Y, Z, U, V;
};

// ===================================================

class Mesh
{
public:
CustomVertex* Vertices;
unsigned int VertexCount;

Mesh();
Mesh(std::string fileName);
~Mesh();

bool Load(std::string fileName);
void Destroy();

private:
int CalculateBufferSize(std::string fileName);
};

Mesh::Mesh()
{
this->Vertices = 0;
this->VertexCount = 0;
}

Mesh::Mesh(std::string fileName)
{
this->Vertices = 0;
this->VertexCount = 0;
this->Load(fileName);
}

Mesh::~Mesh(){}

bool Mesh::Load(std::string fileName)
{
this->Destroy();

this->VertexCount = this->CalculateBufferSize(fileName);
if (!this->VertexCount)
{
std::stringstream s;
s << "Unable to load " << fileName << "!\n\nVertex Count is Zero!";
::MessageBox(0, s.str().c_str(), "Mesh::Load Error", MB_OK | MB_ICONEXCLAMATION);
return false;
}

FILE* fp = fopen(fileName.c_str(), "rb");
if (!fp)
{
std::stringstream s;
s << "Unable to load " << fileName << "!\n\nUnable to Open File!";
::MessageBox(0, s.str().c_str(), "Mesh::Load Error", MB_OK | MB_ICONEXCLAMATION);
return false;
}

this->Vertices = new CustomVertex [this->VertexCount];
int i = 0;
while(!feof(fp))
{
fread(&this->Vertices[i++], sizeof(CustomVertex), 1, fp);
}

fclose(fp);
return true;
}

int Mesh::CalculateBufferSize(std::string fileName)
{
FILE* fp = fopen(fileName.c_str(), "rb");
if (!fp)
{
std::stringstream s;
s << "Unable to load " << fileName << "!\n\nUnable to Open File!";
::MessageBox(0, s.str().c_str(), "Mesh::Load Error", MB_OK | MB_ICONEXCLAMATION);
return 0;
}
int bufferSize = 0;
fseek(fp, 0, SEEK_END);
long fileSize = ftell(fp);
fclose(fp);
bufferSize = (fileSize / sizeof(CustomVertex));
return bufferSize;
}

void Mesh::Destroy()
{
if (this->Vertices)
{
delete [] this->Vertices;
this->VertexCount = 0;
}
}

// ===================================================

// ===================================================

class MeshDemo
{
public:
MeshDemo(HWND windowHandle);
~MeshDemo();

bool Initialize();
void Run();

private:

void Render();

HWND windowHandle_;
LPDIRECT3D9 d3d_;
LPDIRECT3DDEVICE9 d3dDevice_;
LPDIRECT3DVERTEXBUFFER9 vertexBuffer_;
LPDIRECT3DTEXTURE9 texture_;

float elapsedTime_;
double currentTime_;
double lastTime_;

Mesh mesh_;
};

bool MeshDemo::Initialize()
{
if (!mesh_.Load("cube.model"))
{
return false;
}

unsigned int vBufferSize = mesh_.VertexCount * sizeof(CustomVertex);
d3dDevice_->CreateVertexBuffer(vBufferSize, 0, CustomVertexFVF, D3DPOOL_DEFAULT, &vertexBuffer_, 0);
void* vb = 0;
vertexBuffer_->Lock(0, 0, (void**)&vb, 0);
memcpy(vb, mesh_.Vertices, vBufferSize);
vertexBuffer_->Unlock();

D3DXMATRIX projectionMatrix;
D3DXMatrixPerspectiveFovLH(&projectionMatrix, D3DXToRadian(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
d3dDevice_->SetTransform(D3DTS_PROJECTION, &projectionMatrix);

    d3dDevice_->SetRenderState(D3DRS_LIGHTING, FALSE);
    d3dDevice_->SetRenderState(D3DRS_ZENABLE, TRUE);

return true;
}

MeshDemo::MeshDemo(HWND windowHandle)
{
currentTime_ = (double)timeGetTime();
elapsedTime_ = (float)((currentTime_ - lastTime_) * 0.001);
lastTime_ = currentTime_;

windowHandle_ = windowHandle;

d3d_ = Direct3DCreate9(D3D_SDK_VERSION);

D3DDISPLAYMODE displayMode;
d3d_->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode);

D3DPRESENT_PARAMETERS params;
memset((void*)&params, 0, sizeof(params));

params.Windowed = TRUE;
params.EnableAutoDepthStencil = TRUE;
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
params.BackBufferFormat = displayMode.Format;
params.AutoDepthStencilFormat = D3DFMT_D16;
params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

d3d_->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, windowHandle_,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&params, &d3dDevice_);

D3DXCreateTextureFromFile(d3dDevice_, "texture.bmp", &texture_);
d3dDevice_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
d3dDevice_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}

MeshDemo::~MeshDemo()
{
if (texture_)
{
texture_->Release();
}

if (vertexBuffer_)
{
vertexBuffer_->Release();
}

if (d3dDevice_)
{
d3dDevice_->Release();
}

if (d3d_)
{
d3d_->Release();
}
}

void MeshDemo::Run()
{
currentTime_ = (double)timeGetTime();
elapsedTime_ = (float)((currentTime_ - lastTime_) * 0.001);
lastTime_ = currentTime_;

this->Render();
}

void MeshDemo::Render()
{
d3dDevice_->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_COLORVALUE(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, 0);

const float rotationSpeed = 7.0f;

static float rotateX = 0.0f;
static float rotateY = 0.0f;
static float rotateZ = 0.0f;

rotateX += rotationSpeed * elapsedTime_;
rotateY += rotationSpeed * elapsedTime_;
rotateZ += rotationSpeed * elapsedTime_;

D3DXMATRIX worldMatrix;
D3DXMATRIX translationMatrix;
D3DXMATRIX rotationMatrix;

D3DXMatrixTranslation(&translationMatrix, 0.0f, 0.0f, 5.0f);
D3DXMatrixRotationYawPitchRoll(&rotationMatrix,
D3DXToRadian(rotateX),
D3DXToRadian(rotateY),
D3DXToRadian(rotateZ));

worldMatrix = rotationMatrix * translationMatrix;

IDirect3DDevice9& graphicsDevice = *d3dDevice_;

graphicsDevice.SetTransform(D3DTS_WORLD, &worldMatrix);
graphicsDevice.BeginScene();

graphicsDevice.SetTexture(0, texture_);
graphicsDevice.SetStreamSource(0, vertexBuffer_, 0, sizeof(CustomVertex));
graphicsDevice.SetFVF(CustomVertexFVF);

// NOTE: this demo assumes that a 24 vertice cube model is loaded
// You should update this to use index buffers and update the mesh code
// to handle loading mesh data as needed.
graphicsDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,  0, 2);
graphicsDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,  4, 2);
graphicsDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,  8, 2);
graphicsDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2);
graphicsDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2);
graphicsDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2);

graphicsDevice.EndScene();
graphicsDevice.Present(0, 0, 0, 0);
}


// The Ugly Window Procedure
LRESULT CALLBACK MainWindowProcedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
case WM_CLOSE:
{
PostQuitMessage(0);
} break;
case WM_KEYDOWN:
{
if (VK_ESCAPE == wParam)
{
PostQuitMessage(0);
}
} break;
default:
{
return DefWindowProc(handle, message, wParam, lParam);
} break;
}
return 0;
}

// The Ugly WinMain
int WINAPI WinMain(
HINSTANCE instance,
HINSTANCE perviousInstance,
LPSTR commandLine,
int commandShow)
{
// the first time the program is run, it creates the mesh file and exits
FILE* fp = fopen("cube.model", "rb");
if (!fp)
{
fp = fopen("cube.model", "wb");
if (!fp)
{
// cannot open file for writing
return 1;
}
// write mesh data
CustomVertex meshData[] =
{
{-1.0f, 1.0f,-1.0f,  0.0f,0.0f },
{ 1.0f, 1.0f,-1.0f,  1.0f,0.0f },
{-1.0f,-1.0f,-1.0f,  0.0f,1.0f },
{ 1.0f,-1.0f,-1.0f,  1.0f,1.0f },
{-1.0f, 1.0f, 1.0f,  1.0f,0.0f },
{-1.0f,-1.0f, 1.0f,  1.0f,1.0f },
{ 1.0f, 1.0f, 1.0f,  0.0f,0.0f },
{ 1.0f,-1.0f, 1.0f,  0.0f,1.0f },
{-1.0f, 1.0f, 1.0f,  0.0f,0.0f },
{ 1.0f, 1.0f, 1.0f,  1.0f,0.0f },
{-1.0f, 1.0f,-1.0f,  0.0f,1.0f },
{ 1.0f, 1.0f,-1.0f,  1.0f,1.0f },
{-1.0f,-1.0f, 1.0f,  0.0f,0.0f },
{-1.0f,-1.0f,-1.0f,  1.0f,0.0f },
{ 1.0f,-1.0f, 1.0f,  0.0f,1.0f },
{ 1.0f,-1.0f,-1.0f,  1.0f,1.0f },
{ 1.0f, 1.0f,-1.0f,  0.0f,0.0f },
{ 1.0f, 1.0f, 1.0f,  1.0f,0.0f },
{ 1.0f,-1.0f,-1.0f,  0.0f,1.0f },
{ 1.0f,-1.0f, 1.0f,  1.0f,1.0f },
{-1.0f, 1.0f,-1.0f,  1.0f,0.0f },
{-1.0f,-1.0f,-1.0f,  1.0f,1.0f },
{-1.0f, 1.0f, 1.0f,  0.0f,0.0f },
{-1.0f,-1.0f, 1.0f,  0.0f,1.0f }
};
int vertexCount = sizeof(meshData) / sizeof(CustomVertex);
for (int i = 0; i < vertexCount; i++)
{
fwrite(&meshData[i].X, sizeof(float), 1, fp);
fwrite(&meshData[i].Y, sizeof(float), 1, fp);
fwrite(&meshData[i].Z, sizeof(float), 1, fp);
fwrite(&meshData[i].U, sizeof(float), 1, fp);
fwrite(&meshData[i].V, sizeof(float), 1, fp);
}
fclose(fp);
::MessageBox(0, "Created cube.model\n - Run this program again",
"First Run - resource generation", MB_OK);
return 0;
}
//

WNDCLASSEX wc;
MSG message;
memset(&message, 0, sizeof(message));

wc.lpszClassName = "D3DMeshDemo";
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = MainWindowProcedure;
wc.hInstance = instance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;

if (!RegisterClassEx(&wc))
{
return 1;
}

HWND windowHandle = CreateWindowEx(0, "D3DMeshDemo",
"D3D Mesh Demo", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, 0, 0, instance, 0);
if (!windowHandle)
{
return 1;
}

ShowWindow(windowHandle, commandShow);
UpdateWindow(windowHandle);

MeshDemo* demo = new MeshDemo(windowHandle);

if (!demo->Initialize())
{
return 1;
}

while(message.message != WM_QUIT)
{
if (PeekMessage(&message, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
else
{
demo->Run();
}
}

delete demo;

return (int)message.wParam;
}


Title: Re: Creation Custom Mesh (c++, directx)
Post by: RedSlash on May 02, 2010, 04:35:41 PM
Welcome!

Quote
You are a beginner, and as such you should not worry about such advanced topics such as implementations of custom mesh formats and keeping your game assets from being edited.
I agree. Don't bother locking an essay you wrote in grade 1 in a vault. Even if you left it on your front lawn, it has no value to anyone.

Defining a custom mesh format for the purpose of protection is a waste of time. If the only purpose is protection, then encrypt the .x file. But even that won't protect you from the determined hacker.

The only reason to define a custom format is if there is a feature you need that is not available in the .X format. Once you define your format, you will need to write an export plugin for a 3D modeling program that will output that format.

My suggestion for you is to learn the basics first. Build your game using .x files and when the time comes that you need to define your own format, then modify your code to use the new loader. Hope that helps!