I am trying to build a tool to export and import binary models from an old DX9 game. The models are packed in a single file and I have managed to extract the relevant parts in hexadecimal.
By analyzing the Vertex buffer, I have concluded that it was using the following format. Basically the stride is 24 bytes.
struct CUSTOMVERTEX
{
CUSTOMVERTEX(FLOAT fx, FLOAT fy, FLOAT fz, DWORD dwcolor, FLOAT fu, FLOAT fv) :
X(fx), Y(fy), Z(fz), COLOR(dwcolor), U(fu), V(fv) {}
FLOAT X, Y, Z;
DWORD COLOR;
FLOAT U, V;
};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
I wrote the following program to get the model to show up in DX9
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;
LPDIRECT3DINDEXBUFFER9 i_buffer = NULL;
struct CUSTOMVERTEX
{
CUSTOMVERTEX(FLOAT fx, FLOAT fy, FLOAT fz, DWORD dwcolor, FLOAT fu, FLOAT fv) :
X(fx), Y(fy), Z(fz), COLOR(dwcolor), U(fu), V(fv) {}
FLOAT X, Y, Z;
DWORD COLOR;
FLOAT U, V;
};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
init_graphics();
d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE); // turn off the 3D lighting
d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // turn off culling
d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
}
void render_frame(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
d3ddev->SetFVF(CUSTOMFVF);
// set the view transform
D3DXMATRIX matView; // the view transform matrix
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3(0.0f, 0.0f, 15.0f), // the camera position
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), // the look-at position
&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); // the up direction
d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView
// set the projection transform
D3DXMATRIX matProjection; // the projection transform matrix
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45), // the horizontal field of view
(FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
1.0f, // the near view-plane
100.0f); // the far view-plane
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection
// set the world transform
static float index = 0.0f; index += 0.03f; // an ever-increasing float value
D3DXMATRIX matRotateY; // a matrix to store the rotation for each triangle
D3DXMatrixRotationY(&matRotateY, index); // the rotation matrix
d3ddev->SetTransform(D3DTS_WORLD, &(matRotateY)); // set the world transform
// select the vertex buffer to display
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
d3ddev->SetIndices(i_buffer);
d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 1);
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
void init_graphics(void)
{
const int buffer_size = 96;
char buffer[buffer_size];
std::ifstream myFile;
myFile.open("Vertices.dat", std::ios::in | std::ios::binary);
myFile.read(buffer, buffer_size);
// create a vertex buffer interface called v_buffer
d3ddev->CreateVertexBuffer(buffer_size,
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);
VOID* pVoid;
// lock v_buffer and load the vertices into it
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, buffer, buffer_size);
v_buffer->Unlock();
const int indices_size = 12;
char indices[indices_size];
std::ifstream myFile1;
myFile1.open("Indexes.dat", std::ios::in | std::ios::binary);
myFile1.read(indices, indices_size);
// create a index buffer interface called i_buffer
d3ddev->CreateIndexBuffer(indices_size,
0,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&i_buffer,
NULL);
// lock i_buffer and load the indices into it
i_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, indices, indices_size);
i_buffer->Unlock();
}
However, when running the program, I just get a black screen. I had hooked the D3D9::SetStreamSource function in the game and dumped the vertex buffer. I could confirm that the vertex and the indices buffer was the exact same as it was present in the binary format in the file.
I also noticed that few of the vertex buffer cordinates are NaN. I am not sure where the problem lies. Is there any chance that the vertex buffer co-ordinates could be of a different type other than float?