MDJ File Format
Posted: Mon Apr 02, 2007 1:25 pm
Anyone interested in a description of Xenimus's MDJ file format along with some source code to load MDJ models?
Karl
Karl
header[52] = { 50, 0, [[0, 17, 26, 35, 44, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,]] 53, }
// the first two entires are actually the file-type indicator!!!
// The header component specified inside [[...]] specifies one more than the maximum vertex index used by the subset of its index. there are ***50*** maximum subsets
// For example, the maximum vertex of subset 0 is -1 (it doesn't exist)
// the maximum vertex of subset 1 is 16, 2 is 25, 3 is 34, 4 is 43, 5 is 48, 6 is 54
// note that the first subset includes the 128-tagged quads...
// the last number specifies the number of vertices - 1 (or the maximum vertex index...)
Reading 54 vertices...success!
Reading 48 quads...success!
vertices[54] = {
[0]: { -32.34, 183.00, 19.14, 0x4B48C8C8, 0x0 }
[1]: { 49.09, 193.00, 52.57, 0x4B48C8C8, 0x0 }
[2]: { 51.98, 193.00, -55.40, 0x4B48C8C8, 0x0 }
[3]: { -33.65, 183.00, -19.89, 0x4B48C8C8, 0x0 }
[4]: { 170.42, 156.00, -22.33, 0x4B48C8C8, 0x0 }
[5]: { 168.77, 156.00, 14.65, 0x4B48C8C8, 0x0 }
[6]: { 42.20, 63.00, 46.45, 0x4B48C8C8, 0x0 }
[7]: { -50.37, 101.00, 20.83, 0x4B48C8C8, 0x0 }
[8]: { 39.05, 63.00, -59.62, 0x4B48C8C8, 0x0 }
[9]: { -55.72, 101.00, -16.27, 0x4B48C8C8, 0x0 }
[10]: { 154.71, 126.00, 18.41, 0x4B48C8C8, 0x0 }
[11]: { 152.46, 126.00, -24.64, 0x4B48C8C8, 0x0 }
[12]: { 34.56, 85.44, -37.73, 0x4B48C8C8, 0x4 }
[13]: { 38.75, 84.09, 26.33, 0x4B48C8C8, 0x3 }
[14]: { -31.15, 161.00, -20.30, 0x4B48C8C8, 0x6 }
[15]: { -32.19, 161.00, 15.88, 0x4B48C8C8, 0x5 }
[16]: { -43.02, 142.00, 0.95, 0x4B48C8C8, 0x2 }
[17]: { -44.33, 89.00, 18.53, 0x4B48C8C8, 0x0 }
[18]: { -52.26, 40.00, 14.39, 0x4B48C8C8, 0x0 }
[19]: { -80.05, 64.00, 1.90, 0x4B48C8C8, 0x0 }
[20]: { -69.02, 51.00, 0.09, 0x4B48C8C8, 0x0 }
[21]: { -78.89, 64.00, -7.08, 0x4B48C8C8, 0x0 }
[22]: { -40.65, 89.00, -20.42, 0x4B48C8C8, 0x0 }
[23]: { -95.98, 56.00, -2.38, 0x4B48C8C8, 0x0 }
[24]: { -67.93, 51.00, -4.89, 0x4B48C8C8, 0x0 }
[25]: { -53.62, 40.00, -22.64, 0x4B48C8C8, 0x0 }
[26]: { -3.74, -80.09, 2.38, 0x4B48C8C8, 0x0 }
[27]: { 2.26, -80.09, 4.38, 0x4B48C8C8, 0x0 }
[28]: { 12.26, -0.09, 10.38, 0x4B48C8C8, 0x0 }
[29]: { -9.74, -0.09, 5.38, 0x4B48C8C8, 0x0 }
[30]: { 0.26, -80.09, -4.62, 0x4B48C8C8, 0x0 }
[31]: { 8.26, -0.09, -5.62, 0x4B48C8C8, 0x0 }
[32]: { -34.74, -79.09, -9.62, 0x4B48C8C8, 0x0 }
[33]: { -29.74, -80.09, 27.38, 0x4B48C8C8, 0x0 }
[34]: { -51.74, -80.09, 15.38, 0x4B48C8C8, 0x0 }
[35]: { -3.53, -81.44, -0.30, 0x4B48C8C8, 0x0 }
[36]: { 2.54, -81.44, -2.09, 0x4B48C8C8, 0x0 }
[37]: { 12.74, -1.44, -7.73, 0x4B48C8C8, 0x0 }
[38]: { -9.42, -1.44, -3.50, 0x4B48C8C8, 0x0 }
[39]: { 8.19, -1.44, 8.12, 0x4B48C8C8, 0x0 }
[40]: { 0.23, -81.44, 6.84, 0x4B48C8C8, 0x0 }
[41]: { -33.82, -80.44, 9.72, 0x4B48C8C8, 0x0 }
[42]: { -27.75, -81.44, -25.02, 0x4B48C8C8, 0x0 }
[43]: { -52.08, -81.44, -15.79, 0x4B48C8C8, 0x0 }
[44]: { -1.40, -30.00, 10.26, 0x4B48C8C8, 0x0 }
[45]: { 55.14, -54.00, 59.57, 0x4B48C8C8, 0x0 }
[46]: { 144.93, 13.00, 73.10, 0x4B48C8C8, 0x0 }
[47]: { 125.79, -9.00, 78.90, 0x4B48C8C8, 0x0 }
[48]: { 63.84, 32.00, 62.27, 0x4B48C8C8, 0x0 }
[49]: { -1.56, -30.00, -3.79, 0x4B48C8C8, 0x0 }
[50]: { 50.18, -54.00, -64.80, 0x4B48C8C8, 0x0 }
[51]: { 125.79, -9.00, -85.75, 0x4B48C8C8, 0x0 }
[52]: { 145.30, 13.00, -77.79, 0x4B48C8C8, 0x0 }
[53]: { 66.11, 32.00, -61.42, 0x4B48C8C8, 0x0 }
}
// there is a DWORD here that specifies the number of quads - 1
quads[48] = {
[0]: { 0, 1, 2, 3, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[1]: { 5, 4, 2, 1, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[2]: { 22, 17, 0, 3, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 2, 0}
[3]: { 7, 6, 1, 0, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[4]: { 9, 8, 6, 7, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[5]: { 9, 3, 2, 8, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[6]: { 10, 5, 1, 6, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[7]: { 17, 18, 7, 0, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 2, 0}
[8]: { 3, 9, 25, 22, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 2, 0}
[9]: { 11, 8, 2, 4, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[10]: { 5, 10, 11, 4, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[11]: { 11, 10, 6, 8, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 1, 0}
[12]: { 18, 25, 9, 7, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 2, 0}
[13]: { 21, 19, 17, 22, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 2, 0}
[14]: { 19, 20, 18, 17, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 2, 0}
[15]: { 20, 24, 25, 18, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 2, 0}
[16]: { 24, 21, 22, 25, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 2, 0}
[17]: { 23, 23, 19, 21, (0.35, 0.56), (0.39,0.56), (0.39,0.58), (0.35,0.58) 1, 2, 0}
[18]: { 23, 23, 21, 24, (0.35, 0.56), (0.39,0.56), (0.39,0.58), (0.35,0.58) 1, 2, 0}
[19]: { 23, 23, 20, 19, (0.35, 0.56), (0.39,0.56), (0.39,0.58), (0.35,0.58) 1, 2, 0}
[20]: { 26, 27, 28, 29, (0.36, 0.57), (0.37,0.57), (0.37,0.56), (0.36,0.56) 1, 3, 0}
[21]: { 31, 30, 26, 29, (0.36, 0.56), (0.36,0.57), (0.36,0.57), (0.36,0.56) 1, 3, 0}
[22]: { 28, 27, 30, 31, (0.37, 0.56), (0.37,0.57), (0.36,0.57), (0.36,0.56) 1, 3, 0}
[23]: { 32, 32, 26, 30, (0.36, 0.57), (0.36,0.57), (0.36,0.57), (0.36,0.57) 1, 3, 0}
[24]: { 33, 33, 27, 26, (0.36, 0.57), (0.36,0.57), (0.37,0.57), (0.36,0.57) 1, 3, 0}
[25]: { 34, 34, 26, 30, (0.37, 0.57), (0.37,0.57), (0.36,0.57), (0.36,0.57) 1, 3, 0}
[26]: { 34, 34, 27, 26, (0.37, 0.57), (0.37,0.57), (0.37,0.57), (0.36,0.57) 1, 3, 0}
[27]: { 36, 35, 38, 37, (0.37, 0.58), (0.37,0.58), (0.37,0.55), (0.37,0.55) 1, 4, 0}
[28]: { 40, 39, 38, 35, (0.37, 0.58), (0.37,0.55), (0.37,0.55), (0.37,0.58) 1, 4, 0}
[29]: { 36, 37, 39, 40, (0.37, 0.58), (0.37,0.55), (0.37,0.55), (0.37,0.58) 1, 4, 0}
[30]: { 41, 41, 40, 35, (0.38, 0.58), (0.38,0.58), (0.37,0.58), (0.37,0.58) 1, 4, 0}
[31]: { 42, 42, 35, 36, (0.37, 0.58), (0.37,0.58), (0.37,0.58), (0.37,0.58) 1, 4, 0}
[32]: { 43, 43, 40, 35, (0.37, 0.58), (0.37,0.58), (0.37,0.58), (0.37,0.58) 1, 4, 0}
[33]: { 43, 43, 35, 36, (0.37, 0.58), (0.37,0.58), (0.37,0.58), (0.37,0.58) 1, 4, 0}
[34]: { 23, 23, 24, 20, (0.35, 0.56), (0.39,0.56), (0.39,0.58), (0.35,0.58) 1, 2, 0}
[35]: { 44, 45, 48, 0, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 5, 0}
[36]: { 47, 46, 48, 45, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 5, 0}
[37]: { 45, 48, 46, 47, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 5, 0}
[38]: { 44, 0, 48, 45, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 5, 0}
[39]: { 50, 49, 3, 53, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 6, 0}
[40]: { 53, 50, 51, 52, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 6, 0}
[41]: { 3, 49, 50, 53, (0.00, 0.00), (0.24,0.00), (0.24,0.49), (0.00,0.49) 0, 6, 0}
[42]: { 12, 12, 12, 12, (0.00, 0.00), (4.00,0.00), (4.00,4.00), (4.00,0.00) 0, 1, 128}
[43]: { 13, 13, 13, 13, (0.00, 0.00), (4.00,0.00), (4.00,4.00), (4.00,0.00) 0, 1, 128}
[44]: { 50, 53, 52, 51, (0.24, 0.00), (0.00,0.00), (0.00,0.49), (0.24,0.49) 0, 6, 0}
[45]: { 14, 14, 14, 14, (0.00, 0.00), (4.00,0.00), (4.00,4.00), (4.00,0.00) 0, 1, 128}
[46]: { 15, 15, 15, 15, (0.00, 0.00), (4.00,0.00), (4.00,4.00), (4.00,0.00) 0, 1, 128}
[47]: { 16, 16, 16, 16, (0.00, 0.00), (4.00,0.00), (4.00,4.00), (4.00,0.00) 0, 1, 128}
}
Summary: 3500 total bytes, 0 bytes left (should be 0)
54 vertices, 48 quads
Saving X-format file as "C:\Documents and Settings\Karl\My Documents\Volucris\Projects\MDJViewer\Debug\chicken.X"
#include "mdjview.h"
FILE* g_pOutputFile;
void output( char* pFormat, ... )
{
va_list args;
va_start( args, pFormat );
char string[1024];
vsprintf_s( string, sizeof(string), pFormat, args );
va_end( args );
printf( "%s", string );
fprintf( g_pOutputFile, "%s", string );
fflush( g_pOutputFile );
}
int run( int nArgs, char** ppArgs )
{
printf( "MDJ Viewer by Karl is loading...\n" );
// Check the number of arguments
if( nArgs < 2 )
{
printf( "No file specified.\n" );
return -1;
}
// debug line
ppArgs[1] = "C:\\Documents and Settings\\Karl\\My Documents\\Volucris\\Projects\\MDJViewer\\Debug\\cauld.MDJ";
// Print the name of the file being processed
printf( "Reading MDJ model file \"%s\"\n", ppArgs[1] );
// Create an X-file to save this as
char xName[MAX_PATH];
strcpy_s( xName, sizeof(xName), ppArgs[1] );
int len = strlen(xName);
xName[len-3]='X';
xName[len-2]='\0';
// Open the output file
fopen_s( &g_pOutputFile, "output.txt", "wt" );
// Open this file
FILE* pFile;
fopen_s( &pFile, ppArgs[1], "rb" );
if( pFile == NULL )
{
output( "Unable to open file.\n" );
return -1;
}
// Read the ID info
DWORD fileType;
fread( &fileType, sizeof(DWORD), 1, pFile );
// Right now, only this file type can be decoded
if( fileType == 50 )
{
DWORD header[52];
fread( &header[1], sizeof(DWORD), 51, pFile );
header[0] = fileType;
pMDJHeader = header;
// Print the header
output( "header[52] = { " );
for( DWORD i = 0; i < 52; ++i )
output( "%i, ", header[i] );
output( "}\n\n" );
// Discover how many vertices there are
DWORD vertices = header[51] + 1;
// Create and fill in the vertex buffer
output( "Reading %i vertices...", vertices );
MDJVertex* pVB = new MDJVertex[vertices];
fread( pVB, sizeof(MDJVertex), vertices, pFile );
output( "success!\n" );
// Read the number of quads ***note this might be a WORD followed by a WORD that is usually 0***
DWORD quads;
fread( &quads, sizeof(DWORD), 1, pFile );
quads++; // This number is 1 less than it should be
// Create and fill in the quad buffer
output( "Reading %i quads...", quads );
MDJQuad* pQB = new MDJQuad[quads];
fread( pQB, sizeof(MDJQuad), quads, pFile );
output( "success!\n" );
// Print all of the information about the model's vertices
output( "\n\nvertices[%i] = {\n", vertices );
for( DWORD v = 0; v < vertices; ++v )
output( "\t[%i]: { %.02f,\t%.02f,\t%.02f,\t0x%X,\t0x%X }\n", v, pVB[v].x, pVB[v].y, pVB[v].z, pVB[v].color, pVB[v].childBone );
output( "}\n" );
// Print all of the information about the model's quads
output( "\n\nquads[%i] = {\n", quads );
for( DWORD q = 0; q < quads; ++q )
output("\t[%i]:\t{ %i,\t%i,\t%i,\t%i,\t"
"(%.02f, %.02f),\t(%.02f,%.02f),\t(%.02f,%.02f),\t(%.02f,%.02f)\t"
"%i,\t%i,\t%i}\n", q,
pQB[q].indices[0], pQB[q].indices[1], pQB[q].indices[2], pQB[q].indices[3],
pQB[q].texcoords[0], pQB[q].texcoords[1], pQB[q].texcoords[2], pQB[q].texcoords[3],
pQB[q].texcoords[4], pQB[q].texcoords[5], pQB[q].texcoords[6], pQB[q].texcoords[7],
pQB[q].tail[0], pQB[q].tail[1], pQB[q].tail[2] );
output( "}\n" );
// Output information about those interesting quad-tails!
{
DWORD numSubsets = 0, numTail0s = 0;
for( DWORD q = 0; q <quads> numSubsets )
numSubsets = pQB[q].tail[1];
if( pQB[q].tail[0] > numTail0s )
numTail0s = pQB[q].tail[0];
}
// Print bindings for the tail0-subsets (and just for kicks, print that index in the header)
for( DWORD t0 = 0; t0 < numTail0s+1; ++t0 )
{
bool printedHeader = false;
for( DWORD s = 0; s < numSubsets; ++s )
{
DWORD occurances = 0;
for( DWORD q = 0; q <quads> 0 )
{
if( !printedHeader )
{
output( "\ntail[%i] = { ", t0 );
printedHeader = true;
}
output( "%i (%i), ", s, occurances );
}
}
}
}
// Print bytes left
int readEnd = ftell( pFile );
fseek( pFile, 0, SEEK_END );
int end = ftell( pFile );
output( "\n\nSummary: %i total bytes, %i bytes left (should be 0)\n%i vertices, %i quads\n\n", end, end - readEnd, vertices, quads );
output( "Saving X-format file as \"%s\"\n", xName );
// Show the model
display( xName, vertices, pVB, quads, pQB );
// Erase the buffers
delete[] pQB;
delete[] pVB;
}
else if( fileType == 12866L )
{
// Start reading the header after we've read the type indicator
MDJHeaderItem66 header[51];
fread( header, sizeof(MDJHeaderItem66), 51, pFile );
// Print the header
output( "header[51] = { " );
for( DWORD i = 0; i < 51; ++i )
output( "0x%x 0x%X, ", header[i].value1byte, header[i].value4byte );
output( "}\n\n" );
// Discover how many vertices there are
DWORD vertices = header[50].value4byte + 1;
// Create and fill in the vertex buffer
output( "Reading %i vertices...", vertices );
MDJVertex66* pVB66 = new MDJVertex66[vertices];
fread( pVB66, sizeof(MDJVertex66), vertices, pFile );
output( "success!\n" );
// Print all of the information about the model's vertices
output( "\n\nvertices[%i] = {\n", vertices );
for( DWORD v = 0; v < vertices; ++v )
output( "\t[%i]: { %.02f,\t%.02f,\t%.02f,\t0x%X,\t0x%X, \t0x%X }\n", v, pVB66[v].x, pVB66[v].y, pVB66[v].z, pVB66[v].color, pVB66[v].zero, pVB66[v].value );
output( "}\n" );
// Convert to the normal vertex type (we might lose data here)
MDJVertex* pVB = new MDJVertex[vertices];
for( DWORD v = 0; v < vertices; ++v )
{
memcpy( &pVB[v], &pVB66[v], sizeof(MDJVertex) );
}
delete[] pVB66;
// Read the number of quads ***note this might be a WORD followed by a WORD that is usually 0***
DWORD quads;
fread( &quads, sizeof(DWORD), 1, pFile );
quads++; // This number is 1 less than it should be
// Create and fill in the quad buffer
output( "Reading %i quads...", quads );
MDJQuad* pQB = new MDJQuad[quads];
fread( pQB, sizeof(MDJQuad), quads, pFile );
output( "success!\n" );
// Print all of the information about the model's quads
output( "\n\nquads[%i] = {\n", quads );
for( DWORD q = 0; q < quads; ++q )
output( "\t[%i]:\t{%i,\t%i,\t%i,\t%i, "
"\t(%.02f,%.02f), (%.02f,%.02f), (%.02f,%.02f), (%.02f,%.02f)"
" \t%i,\t%i,\t%i}\n", q, pQB[q].indices[0], pQB[q].indices[1], pQB[q].indices[2], pQB[q].indices[3],
pQB[q].texcoords[0], pQB[q].texcoords[1], pQB[q].texcoords[2], pQB[q].texcoords[3],
pQB[q].texcoords[4], pQB[q].texcoords[5], pQB[q].texcoords[6], pQB[q].texcoords[7],
pQB[q].tail[0], pQB[q].tail[1], pQB[q].tail[2] );
output( "}\n" );
// Print bytes left
int readEnd = ftell( pFile );
fseek( pFile, 0, SEEK_END );
int end = ftell( pFile );
output( "\n\nSummary: %i total bytes, %i bytes left (should be 0)\n%i vertices, %i quads\n\n", end, end - readEnd, vertices, quads );
output( "Saving X-format file as \"%s\"\n", xName );
// Show the model
display( xName, vertices, pVB, quads, pQB );
// Erase buffers
delete[] pVB;
delete[] pQB;
}
else
{
output( "Header indicates this is an unsupported file type.\n" );
return -1;
}
// Close the file
fclose( pFile );
fclose( g_pOutputFile );
// Success
return 0;
}
#include <d3dx9>
// Entry point to the application
int main( int nArgs, char** ppArgs )
{
// Execute the app
int c = run( nArgs, ppArgs );
// Wait for something to happen
system("PAUSE");
// Return the code
return c;
}
#include <windows>
#include <stdio>
#pragma pack( push, 1 ) // Don't pack here--we need these sizes to be exact
struct MDJVertex
{
FLOAT x, y, z;
DWORD color;
DWORD childBone;
};
struct MDJQuad
{
WORD indices[4];
FLOAT texcoords[8];
WORD tail[3]; // tail[0] is the TEXTURE FOR THIS MESH
// tail[1] is the animation subset for the mesh
// tail[2] is ?
};
struct MDJHeaderItem66
{
BYTE value1byte;
DWORD value4byte;
};
struct MDJVertex66
{
FLOAT x, y, z;
DWORD color;
DWORD zero;
BYTE value;
};
#pragma pack(pop)
extern DWORD* pMDJHeader;
void output( char* pFormat, ... );
void display( const char* pFileNameX, DWORD vertices, MDJVertex* pVertices, DWORD quads, MDJQuad* pQuads );
#include "mdjview.h"
#include <Windows>
#include <mmsystem>
#include <d3dx9>
#pragma warning( disable : 4996 ) // disable deprecated warning
#include <strsafe>
#pragma warning( default : 4996 )
#include <string>
#include <vector>
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
LPD3DXMESH g_pMesh = NULL; // Our mesh object in sysmem
D3DMATERIAL9* g_pMeshMaterials = NULL; // Materials for our mesh
LPDIRECT3DTEXTURE9* g_pMeshTextures = NULL; // Textures for our mesh
DWORD g_dwNumTextures = 0L; // Number of mesh materials
DWORD* pMDJHeader = NULL;
FLOAT g_Height = 1.0f;
DWORD g_CurrentSubset = 0;
bool g_bShowAll = true;
DWORD g_CurrentTexture = 0;
struct MeshVertex
{
FLOAT x, y, z;
D3DCOLOR color;
FLOAT u, v;
};
#define D3DFVF_MESHVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
// Create the D3D object.
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
// Set up the structure used to create the D3DDevice. Since we are now
// using more complex geometry, we will create a device with a zbuffer.
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// Create the D3DDevice
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
// Turn on the zbuffer
g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
// Turn on ambient lighting
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: Load the mesh and build the material and texture arrays
//-----------------------------------------------------------------------------
HRESULT InitGeometry( const char* pFileNameX, DWORD vertices, MDJVertex* pVertices, DWORD quads, MDJQuad* pQuads, FLOAT* pRadius )
{
FLOAT maxRadiusSq = 0.0f;
// Find all of the texture files in the directory
{
std::vector<std> textures;
WIN32_FIND_DATA data;
ZeroMemory( &data, sizeof(data) );
HANDLE hFind = FindFirstFile( "*.png", &data );
if( data.nFileSizeLow > 0 )
{
do
{
textures.push_back( data.cFileName );
}
while( FindNextFile( hFind, &data ) );
// Create a texture bank
g_pMeshTextures = new LPDIRECT3DTEXTURE9[textures.size()];
g_dwNumTextures = (DWORD)textures.size();
// Load each texture
DWORD index = 0;
for( std::vector<std>::iterator i = textures.begin(); i != textures.end(); ++i, ++index )
{
D3DXCreateTextureFromFile( g_pd3dDevice, i->c_str(), &g_pMeshTextures[index] );
}
}
}
/*
// Generate the mesh vertex structure
if( FAILED( D3DXCreateMeshFVF( quads * 2, vertices, 0, D3DFVF_MESHVERTEX, g_pd3dDevice, &g_pMesh ) ) )
return E_FAIL;
// Lock the buffers
MeshVertex* pMeshVertices = NULL;
WORD* pMeshIndices = NULL;
if( SUCCEEDED( g_pMesh->LockVertexBuffer( 0, (VOID**)&pMeshVertices ) ) &&
SUCCEEDED( g_pMesh->LockIndexBuffer( 0, (VOID**)&pMeshIndices ) ) )
{
// Build the vertices
for( DWORD v = 0; v <vertices> maxRadiusSq )
maxRadiusSq = radiusSq;
pMeshVertices[v].color = pVertices[v].color;
pMeshVertices[v].u = 0.0f;
pMeshVertices[v].v = 0.0f;
}
WORD* p = pMeshIndices;
// Build the indices
for( DWORD q = 0; q <quads>UnlockIndexBuffer();
g_pMesh->UnlockVertexBuffer();
}
else
return E_FAIL;
*/
// Generate the mesh vertex structure
if( FAILED( D3DXCreateMeshFVF( quads * 2, quads * 4, 0, D3DFVF_MESHVERTEX, g_pd3dDevice, &g_pMesh ) ) )
return E_FAIL;
// Lock the buffers
MeshVertex* pMeshVertices = NULL;
WORD* pMeshIndices = NULL;
if( SUCCEEDED( g_pMesh->LockVertexBuffer( 0, (VOID**)&pMeshVertices ) ) &&
SUCCEEDED( g_pMesh->LockIndexBuffer( 0, (VOID**)&pMeshIndices ) ) )
{
DWORD currentVertexIndex = 0;
MeshVertex* pMeshVerticesStart = pMeshVertices;
WORD* pMeshIndicesStart = pMeshIndices;
// Build the vertices
for( DWORD q = 0; q < quads; ++q )
{
DWORD startIndex = currentVertexIndex;
// Repeat for each vertex in the quad
for( DWORD v = 0; v <4>x = pVertex->x;
pMeshVertices->y = pVertex->y;
pMeshVertices->z = pVertex->z;
// Keep track of the radius of the model (assuming origin-centric)
FLOAT radiusSq = pMeshVertices->x * pMeshVertices->x + pMeshVertices->y * pMeshVertices->y + pMeshVertices->z * pMeshVertices->z;
if( radiusSq > maxRadiusSq )
maxRadiusSq = radiusSq;
pMeshVertices->color = 0xFFFFFFFF;//pVertex->color;
pMeshVertices->u = pQuads[q].texcoords[v*2+0];
pMeshVertices->v = pQuads[q].texcoords[v*2+1];
currentVertexIndex++;
pMeshVertices++;
}
pMeshIndices[0] = startIndex + 0;
pMeshIndices[1] = startIndex + 1;
pMeshIndices[2] = startIndex + 2;
pMeshIndices[3] = startIndex + 0;
pMeshIndices[4] = startIndex + 2;
pMeshIndices[5] = startIndex + 3;
pMeshIndices += 6;
}
// Save this file as a .X mesh using a fake material
D3DXMATERIAL mtrl;
ZeroMemory( &mtrl, sizeof(mtrl) );
if( FAILED( D3DXSaveMeshToX( pFileNameX, g_pMesh, NULL, &mtrl, NULL, 1, D3DXF_FILEFORMAT_TEXT ) ) )
{
output( "NOTE: Unable to save mesh" );
}
DWORD* pMeshAttr = NULL;
if( SUCCEEDED( g_pMesh->LockAttributeBuffer( 0, &pMeshAttr ) ) )
{
DWORD* pMeshAttrStart = pMeshAttr;
// Assign mesh attributes based on data from the quad info
for( DWORD q = 0; q < quads; ++q )
{
// Weeee
pMeshAttr[0] = pQuads[q].tail[0];
pMeshAttr[1] = pQuads[q].tail[0];
pMeshAttr+=2;
}
// Woot! Bone Matrices!
//D3DXMATRIXA16 bones[50];
//for( int i = 0; i < 50; ++i )
// D3DXMatrixIdentity( &bones[i] );
// Go through and find quads with the last tail component set to 128
// With these, look in the vertices they reference for transformation coordinates
// Find attributes (bones) with the same last-value as those vertices and transform them accordingly
if( false ) // this only works for the chicken, because it has no recursion and is SLOPPY
for( DWORD q = 0; q <quads> 1 ) g_CurrentSubset--; else { if( g_CurrentSubset == 0 ) g_bShowAll = true; else g_CurrentSubset = 0; }
if( wParam == 'q' ) if( g_CurrentTexture > 1 ) g_CurrentTexture--; else g_CurrentTexture = 0;
if( wParam == 'e' ) if( g_CurrentTexture + 1 <g_dwNumTextures>GetDeviceCaps( &caps );
DWORD v = caps.MaxVertexShaderConst;
v = v;
FLOAT modelRadius = 0.0f;
// Create the scene geometry
if( SUCCEEDED( InitGeometry( pFileNameX, vertices, pVertices, quads, pQuads, &modelRadius ) ) )
{
// Show the window
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
// Enter the message loop
MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
Render( modelRadius );
}
}
Cleanup();
}
UnregisterClass( "D3D Tutorial", wc.hInstance );
}