1 #include <iostream>
2 #include <fstream>
3 #include <iomanip>
4 #include <algorithm>
5 #include <cstdio>
6 #include <cassert>
7 #include <cstring>
8 #include <d3dx9.h>
9
10 using namespace std;
11
12 static IDirect3D9* g_d3d = NULL;
13 static IDirect3DDevice9* g_d3dDev = NULL;
14 static HWND g_mainWindow = NULL;
15
16 char* D3DErrorString(HRESULT);
17 void ShowD3DErrorMessage(char* info, HRESULT hr);
18
19
20 struct VertexAttribute
21 {
22 enum {
23 Position = 0,
24 Color0 = 1,
25 Color1 = 2,
26 Normal = 3,
27 Tangent = 4,
28 Texture0 = 5,
29 Texture1 = 6,
30 Texture2 = 7,
31 Texture3 = 8,
32 MaxAttribute = 9,
33 InvalidAttribute = -1,
34 };
35
36 enum Format
37 {
38 Float1 = 0,
39 Float2 = 1,
40 Float3 = 2,
41 Float4 = 3,
42 UByte4 = 4,
43 InvalidFormat = -1,
44 };
45
46 unsigned int offset;
47 Format format;
48 };
49
50 char* AttribFormatNames[] =
51 { "f1", "f2", "f3", "f4", "ub4" };
52
53 char* AttribNames[] = {
54 "position",
55 "color0",
56 "color1",
57 "normal",
58 "tangent",
59 "texcoord0",
60 "texcoord1",
61 "texcoord2",
62 "texcoord3"
63 };
64
65
operator ==(const D3DCOLORVALUE & c0,const D3DCOLORVALUE & c1)66 bool operator==(const D3DCOLORVALUE& c0, const D3DCOLORVALUE& c1)
67 {
68 return (c0.r == c1.r && c0.g == c1.g && c0.b == c1.b && c0.a == c1.a);
69 }
70
71
operator <(const D3DCOLORVALUE & c0,const D3DCOLORVALUE & c1)72 bool operator<(const D3DCOLORVALUE& c0, const D3DCOLORVALUE& c1)
73 {
74 if (c0.r == c1.r)
75 {
76 if (c0.g == c1.g)
77 {
78 if (c0.b == c1.b)
79 return c0.a < c1.a;
80 else
81 return c0.b < c1.b;
82 }
83 else
84 {
85 return c0.g < c1.g;
86 }
87 }
88 else
89 {
90 return c0.r < c1.r;
91 }
92 }
93
94
operator ==(const D3DXMATERIAL & mat0,const D3DXMATERIAL & mat1)95 bool operator==(const D3DXMATERIAL& mat0, const D3DXMATERIAL& mat1)
96 {
97 // Compare the texture filenames for equality, safely handling
98 // null filenames.
99 bool sameTex;
100 if (mat0.pTextureFilename == NULL)
101 {
102 sameTex = (mat1.pTextureFilename == NULL);
103 }
104 else if (mat1.pTextureFilename == NULL)
105 {
106 sameTex = false;
107 }
108 else
109 {
110 sameTex = (strcmp(mat0.pTextureFilename, mat1.pTextureFilename) == 0);
111 }
112
113 return (mat0.MatD3D.Diffuse == mat1.MatD3D.Diffuse &&
114 mat0.MatD3D.Ambient == mat1.MatD3D.Ambient &&
115 mat0.MatD3D.Specular == mat1.MatD3D.Specular &&
116 mat0.MatD3D.Emissive == mat1.MatD3D.Emissive &&
117 mat0.MatD3D.Power == mat1.MatD3D.Power &&
118 sameTex);
119 }
120
121
operator <<(ostream & o,const D3DCOLORVALUE & c)122 ostream& operator<<(ostream& o, const D3DCOLORVALUE& c)
123 {
124 return (o << c.r << ' ' << c.g << ' ' << c.b);
125 }
126
127
render()128 static void render()
129 {
130 g_d3dDev->Clear(0, NULL,
131 D3DCLEAR_TARGET,
132 D3DCOLOR_ARGB(255, 0, 0, 192), // color
133 0.0f, // z
134 0); // stencil value
135 }
136
137
checkForFan(DWORD nTris,T * indices)138 template<class T> int checkForFan(DWORD nTris, T* indices)
139 {
140 // Even number of triangles required; pairs of triangles can always
141 // be just as efficiently represented as strips, so skip them.
142 if (nTris % 2 == 1 || nTris <= 2)
143 return -1;
144
145 DWORD i;
146 T anchor = indices[0];
147 bool isFan = true;
148 for (i = 1; i < nTris / 2 && isFan; i++)
149 {
150 if (indices[i * 2] != anchor)
151 isFan = false;
152 }
153
154 if (isFan)
155 return 0;
156
157 isFan = true;
158 anchor = indices[1];
159 for (i = 1; i < nTris / 2 && isFan; i++)
160 {
161 if (indices[i * 2 + 1] != anchor)
162 isFan = false;
163 }
164
165 if (isFan)
166 cout << "fan: nTris=" << nTris << ", anchor=" << anchor << '\n';
167
168 return isFan ? 1 : -1;
169 }
170
171
DumpTriStrip(DWORD nTris,T * indices,int materialIndex,ostream & meshfile)172 template<class T> int DumpTriStrip(DWORD nTris,
173 T* indices,
174 int materialIndex,
175 ostream& meshfile)
176 {
177 meshfile << "tristrip ";
178 meshfile << materialIndex << ' ' << (nTris + 2) << '\n';
179
180 DWORD indexCount = nTris + 2;
181
182 for (DWORD j = 0; j < indexCount; j++)
183 {
184 meshfile << indices[j] << ' ';
185 if (j == indexCount - 1 || j % 12 == 11)
186 meshfile << '\n';
187 }
188 }
189
190
191
192 // The D3DX tristrip converter only produces strips, not fans. It dumps
193 // fans as strips where every other triangle is degenerate. We detect such
194 // strips and output them as fans instead, thus eliminating a bunch of
195 // degenerate triangles.
DumpTriStripAsFan(DWORD nTris,T * indices,int materialIndex,DWORD anchorOffset,ostream & meshfile)196 template<class T> void DumpTriStripAsFan(DWORD nTris,
197 T* indices,
198 int materialIndex,
199 DWORD anchorOffset,
200 ostream& meshfile)
201 {
202 meshfile << "trifan ";
203 meshfile << materialIndex << ' ' << (nTris / 2 + 3) << '\n';
204
205 DWORD indexCount = nTris + 2;
206
207 T anchor = indices[anchorOffset];
208 meshfile << anchor << ' ';
209
210 if (anchorOffset == 1)
211 {
212 for (int j = (int) indexCount - 1; j >= 0; j--)
213 {
214 if (indices[j] != anchor)
215 meshfile << indices[j] << ' ';
216 if (j == 0 || j % 12 == 11)
217 meshfile << '\n';
218 }
219 }
220 else if (anchorOffset == 0)
221 {
222 // D3DX never seems to produce strips where the first vertex is
223 // the anchor, but we'll handle it just in case.
224 for (int j = 1; j < (int) indexCount; j++)
225 {
226 if (indices[j] != anchor)
227 meshfile << indices[j] << ' ';
228 if (j == indexCount - 1 || j % 12 == 11)
229 meshfile << '\n';
230 }
231 }
232 }
233
234
StripifyMeshSubset(ID3DXMesh * mesh,DWORD attribId,ostream & meshfile)235 bool StripifyMeshSubset(ID3DXMesh* mesh,
236 DWORD attribId,
237 ostream& meshfile)
238 {
239 // TODO: Fall back to tri lists if the strip size is too small
240 // TODO: Detect when a tri fan should be used instead of a tri list
241
242 // Convert to tri strips
243 IDirect3DIndexBuffer9* indices = NULL;
244 DWORD numIndices = 0;
245 ID3DXBuffer* strips = NULL;
246 DWORD numStrips = 0;
247 HRESULT hr;
248 hr = D3DXConvertMeshSubsetToStrips(mesh,
249 attribId,
250 0,
251 &indices,
252 &numIndices,
253 &strips,
254 &numStrips);
255 if (FAILED(hr))
256 {
257 cout << "Stripify failed\n";
258 return false;
259 }
260
261 cout << "Converted to " << numStrips << " strips\n";
262 cout << "Strip buffer size: " << strips->GetBufferSize() << '\n';
263 if (numStrips != strips->GetBufferSize() / 4)
264 {
265 cout << "Strip count is incorrect!\n";
266 return false;
267 }
268
269 bool index32 = false;
270 {
271 D3DINDEXBUFFER_DESC desc;
272 indices->GetDesc(&desc);
273 if (desc.Format == D3DFMT_INDEX32)
274 {
275 index32 = true;
276 }
277 else if (desc.Format == D3DFMT_INDEX16)
278 {
279 index32 = false;
280 }
281 else
282 {
283 cout << "Bad index format. Strange.\n";
284 return false;
285 }
286 }
287
288 void* indexData = NULL;
289 hr = indices->Lock(0, 0, &indexData, D3DLOCK_READONLY);
290 if (FAILED(hr))
291 {
292 cout << "Failed to lock index buffer: " << D3DErrorString(hr) << '\n';
293 return false;
294 }
295
296 {
297 DWORD* stripLengths = reinterpret_cast<DWORD*>(strips->GetBufferPointer());
298 int k = 0;
299 for (int i = 0; i < numStrips; i++)
300 {
301 if (stripLengths[i] == 0)
302 {
303 cout << "Bad triangle strip (length == 0) in mesh!\n";
304 return false;
305 }
306
307 if (index32)
308 {
309 DWORD* indices = reinterpret_cast<DWORD*>(indexData) + k;
310 int fanStart = checkForFan(stripLengths[i], indices);
311 if (fanStart != 1)
312 {
313 DumpTriStrip(stripLengths[i], indices, (int) attribId,
314 meshfile);
315 }
316 else
317 {
318 DumpTriStripAsFan(stripLengths[i], indices, (int) attribId,
319 fanStart, meshfile);
320 }
321 }
322 else
323 {
324 WORD* indices = reinterpret_cast<WORD*>(indexData) + k;
325 int fanStart = checkForFan(stripLengths[i], indices);
326 if (fanStart != 1)
327 {
328 DumpTriStrip(stripLengths[i], indices, (int) attribId,
329 meshfile);
330 }
331 else
332 {
333 DumpTriStripAsFan(stripLengths[i], indices, (int) attribId,
334 fanStart, meshfile);
335 }
336 }
337
338 k += stripLengths[i] + 2;
339 }
340
341 cout << "k=" << k << ", numIndices=" << numIndices;
342 if (index32)
343 cout << ", 32-bit indices\n";
344 else
345 cout << ", 16-bit indices\n";
346 }
347
348 return true;
349 }
350
351
DumpVertexDescription(VertexAttribute vertexMap[],ostream & meshfile)352 void DumpVertexDescription(VertexAttribute vertexMap[],
353 ostream& meshfile)
354 {
355 meshfile << "vertexdesc\n";
356 for (int i = 0; i < VertexAttribute::MaxAttribute; i++)
357 {
358 if (vertexMap[i].format != VertexAttribute::InvalidFormat)
359 {
360 meshfile << AttribNames[i] << " " <<
361 AttribFormatNames[vertexMap[i].format] << " " << '\n';
362 }
363 }
364 meshfile << "end_vertexdesc\n\n";
365 }
366
367
DumpMeshVertices(ID3DXMesh * mesh,VertexAttribute vertexMap[],DWORD stride,ostream & meshfile)368 bool DumpMeshVertices(ID3DXMesh* mesh,
369 VertexAttribute vertexMap[],
370 DWORD stride,
371 ostream& meshfile)
372 {
373 IDirect3DVertexBuffer9* vb = NULL;
374 HRESULT hr = mesh->GetVertexBuffer(&vb);
375 if (FAILED(hr))
376 {
377 ShowD3DErrorMessage("Getting vertex buffer", hr);
378 return false;
379 }
380
381 char* vertexData = NULL;
382 hr = vb->Lock(0, 0, reinterpret_cast<void**>(&vertexData), D3DLOCK_READONLY);
383 if (FAILED(hr) || vertexData == NULL)
384 {
385 ShowD3DErrorMessage("Locking vertex buffer", hr);
386 return false;
387 }
388
389 DWORD numVertices = mesh->GetNumVertices();
390
391 meshfile << "vertices " << numVertices << '\n';
392
393 for (DWORD i = 0; i < numVertices; i++)
394 {
395 for (int attr = 0; attr < VertexAttribute::MaxAttribute; attr++)
396 {
397 if (vertexMap[attr].format != VertexAttribute::InvalidFormat)
398 {
399 char* chardata = vertexData + i * stride + vertexMap[attr].offset;
400 float* floatdata = reinterpret_cast<float*>(chardata);
401
402 switch (vertexMap[attr].format)
403 {
404 case VertexAttribute::Float1:
405 meshfile << floatdata[0] << ' ';
406 break;
407 case VertexAttribute::Float2:
408 meshfile << floatdata[0] << ' ' << floatdata[1] << ' ';
409 break;
410 case VertexAttribute::Float3:
411 meshfile << floatdata[0] << ' ' << floatdata[1] << ' ';
412 meshfile << floatdata[2] << ' ';
413 break;
414 case VertexAttribute::Float4:
415 meshfile << floatdata[0] << ' ' << floatdata[1] << ' ';
416 meshfile << floatdata[2] << ' ' << floatdata[3];
417 break;
418 case VertexAttribute::UByte4:
419 meshfile << (unsigned int) chardata[0] << ' ' <<
420 (unsigned int) chardata[1] << ' ' <<
421 (unsigned int) chardata[2] << ' ' <<
422 (unsigned int) chardata[3] << ' ';
423 break;
424 default:
425 break;
426 }
427 }
428 }
429
430 meshfile << '\n';
431 }
432
433 vb->Unlock();
434
435 meshfile << '\n';
436
437 return true;
438 }
439
440
CreateVertexAttributeMap(D3DVERTEXELEMENT9 declElements[],VertexAttribute vertexMap[])441 bool CreateVertexAttributeMap(D3DVERTEXELEMENT9 declElements[],
442 VertexAttribute vertexMap[])
443 {
444 int i = 0;
445 for (i = 0; i < VertexAttribute::MaxAttribute; i++)
446 {
447 vertexMap[i].offset = 0;
448 vertexMap[i].format = VertexAttribute::InvalidFormat;
449 }
450
451 unsigned int outputOffset = 0;
452 for (i = 0; i < MAX_FVF_DECL_SIZE && declElements[i].Stream != 255; i++)
453 {
454 int attr = VertexAttribute::InvalidAttribute;
455 VertexAttribute::Format format = VertexAttribute::InvalidFormat;
456 unsigned int formatSize = 0;
457
458 if (declElements[i].Stream == 0)
459 {
460 switch (declElements[i].Type)
461 {
462 case D3DDECLTYPE_FLOAT1:
463 format = VertexAttribute::Float1;
464 formatSize = 4;
465 break;
466 case D3DDECLTYPE_FLOAT2:
467 format = VertexAttribute::Float2;
468 formatSize = 8;
469 break;
470 case D3DDECLTYPE_FLOAT3:
471 format = VertexAttribute::Float3;
472 formatSize = 12;
473 break;
474 case D3DDECLTYPE_FLOAT4:
475 format = VertexAttribute::Float4;
476 formatSize = 16;
477 break;
478 case D3DDECLTYPE_UBYTE4:
479 case D3DDECLTYPE_UBYTE4N:
480 format = VertexAttribute::UByte4;
481 formatSize = 4;
482 break;
483 }
484
485 switch (declElements[i].Usage)
486 {
487 case D3DDECLUSAGE_POSITION:
488 if (declElements[i].UsageIndex == 0)
489 {
490 attr = VertexAttribute::Position;
491 }
492 break;
493 case D3DDECLUSAGE_NORMAL:
494 if (declElements[i].UsageIndex == 0)
495 {
496 attr = VertexAttribute::Normal;
497 }
498 break;
499 case D3DDECLUSAGE_TEXCOORD:
500 if (declElements[i].UsageIndex < 4)
501 {
502 if (declElements[i].UsageIndex == 0)
503 attr = VertexAttribute::Texture0;
504 else if (declElements[i].UsageIndex == 1)
505 attr = VertexAttribute::Texture1;
506 else if (declElements[i].UsageIndex == 2)
507 attr = VertexAttribute::Texture2;
508 else
509 attr = VertexAttribute::Texture3;
510 }
511 break;
512 case D3DDECLUSAGE_COLOR:
513 if (declElements[i].UsageIndex < 2)
514 {
515 if (declElements[i].UsageIndex == 0)
516 attr = VertexAttribute::Color0;
517 else
518 attr = VertexAttribute::Color1;
519 }
520 break;
521 case D3DDECLUSAGE_TANGENT:
522 if (declElements[i].UsageIndex == 0)
523 {
524 attr = VertexAttribute::Tangent;
525 }
526 break;
527 }
528
529 if (attr != VertexAttribute::InvalidAttribute)
530 {
531 vertexMap[attr].offset = declElements[i].Offset;
532 vertexMap[attr].format = format;
533 }
534 }
535 }
536
537 return true;
538 }
539
540
MainWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)541 static LRESULT CALLBACK MainWindowProc(HWND hWnd,
542 UINT uMsg,
543 WPARAM wParam,
544 LPARAM lParam)
545 {
546 switch (uMsg)
547 {
548 case WM_CREATE:
549 break;
550
551 case WM_DESTROY:
552 PostQuitMessage(0);
553 break;
554
555 case WM_PAINT:
556 if (g_d3dDev != NULL)
557 {
558 //render();
559 //g_d3dDev->Present(NULL, NULL, NULL, NULL);
560 }
561 break;
562
563 default:
564 return DefWindowProc(hWnd, uMsg, wParam, lParam);
565 }
566
567 return 0;
568 }
569
570
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)571 int APIENTRY WinMain(HINSTANCE hInstance,
572 HINSTANCE hPrevInstance,
573 LPSTR lpCmdLine,
574 int nCmdShow)
575 {
576 WNDCLASS wc;
577
578 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
579 wc.lpfnWndProc = (WNDPROC) MainWindowProc;
580 wc.cbClsExtra = 0;
581 wc.cbWndExtra = 0;
582 wc.hInstance = hInstance;
583 wc.hIcon = NULL;
584 wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
585 wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
586 wc.lpszMenuName = NULL;
587 wc.lpszClassName = "xtocmod";
588 if (RegisterClass(&wc) == 0)
589 {
590 MessageBox(NULL,
591 "Failed to register the window class.", "Fatal Error",
592 MB_OK | MB_ICONERROR);
593 return NULL;
594 }
595
596 DWORD windowStyle = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
597 WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
598 g_mainWindow = CreateWindow("xtocmod",
599 "xtocmod",
600 windowStyle,
601 CW_USEDEFAULT,
602 CW_USEDEFAULT,
603 300, 300,
604 NULL,
605 NULL,
606 hInstance,
607 NULL);
608 if (g_mainWindow == NULL)
609 {
610 MessageBox(NULL,
611 "Error creating application window.", "Fatal Error",
612 MB_OK | MB_ICONERROR);
613 }
614
615 //ShowWindow(g_mainWindow, SW_SHOW);
616 SetForegroundWindow(g_mainWindow);
617 SetFocus(g_mainWindow);
618
619 // Initialize D3D
620 g_d3d = Direct3DCreate9(D3D_SDK_VERSION);
621 if (g_d3d == NULL)
622 {
623 ShowD3DErrorMessage("Initializing D3D", 0);
624 return 1;
625 }
626
627 D3DPRESENT_PARAMETERS presentParams;
628 ZeroMemory(&presentParams, sizeof(presentParams));
629 presentParams.Windowed = TRUE;
630 presentParams.SwapEffect = D3DSWAPEFFECT_COPY;
631 #if 0
632 presentParams.BackBufferWidth = 300;
633 presentParams.BackBufferHeight = 300;
634 presentParams.BackBufferCount = 1;
635 presentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
636 presentParams.Windowed = TRUE;
637 #endif
638
639 HRESULT hr = g_d3d->CreateDevice(D3DADAPTER_DEFAULT,
640 D3DDEVTYPE_HAL,
641 g_mainWindow,
642 D3DCREATE_HARDWARE_VERTEXPROCESSING,
643 &presentParams,
644 &g_d3dDev);
645 if (FAILED(hr))
646 {
647 ShowD3DErrorMessage("Creating D3D device", hr);
648 //return 1;
649 }
650
651 string inputFilename(lpCmdLine);
652 string outputFilename(inputFilename, 0, inputFilename.rfind('.'));
653 outputFilename += ".cmod";
654
655 ID3DXMesh* mesh = NULL;
656 ID3DXBuffer* adjacency = NULL;
657 ID3DXBuffer* materialBuf = NULL;
658 ID3DXBuffer* effects = NULL;
659 DWORD numMaterials;
660
661 hr = D3DXLoadMeshFromX(inputFilename.c_str(),
662 0,
663 g_d3dDev,
664 &adjacency,
665 &materialBuf,
666 &effects,
667 &numMaterials,
668 &mesh);
669 if (FAILED(hr))
670 {
671 ShowD3DErrorMessage("Loading mesh from X file", hr);
672 return 1;
673 }
674
675
676 DWORD numVertices = mesh->GetNumVertices();
677 DWORD numFaces = mesh->GetNumFaces();
678
679 cout << "vertices: " << numVertices << '\n';
680 cout << "faces: " << numFaces << '\n';
681
682 cout << "adjacency buffer size: " << adjacency->GetBufferSize() << '\n';
683
684 ofstream meshfile(outputFilename.c_str());
685
686 // Output the header
687 meshfile << "#celmodel__ascii\n\n";
688
689 cout << "numMaterials=" << numMaterials << '\n';
690 D3DXMATERIAL* materials = reinterpret_cast<D3DXMATERIAL*>(materialBuf->GetBufferPointer());
691 for (DWORD mat = 0; mat < numMaterials; mat++)
692 {
693 meshfile << "material\n";
694 meshfile << "diffuse " << materials[mat].MatD3D.Diffuse << '\n';
695 //meshfile << "emissive " << materials[mat].MatD3D.Emissive << '\n';
696 meshfile << "specular " << materials[mat].MatD3D.Specular << '\n';
697 meshfile << "specpower " << materials[mat].MatD3D.Power << '\n';
698 meshfile << "opacity " << materials[mat].MatD3D.Diffuse.a << '\n';
699 meshfile << "end_material\n\n";
700 }
701
702 // Vertex format
703 D3DVERTEXELEMENT9 declElements[MAX_FVF_DECL_SIZE];
704 hr = mesh->GetDeclaration(declElements);
705 if (FAILED(hr))
706 {
707 ShowD3DErrorMessage("Checking vertex declaration", hr);
708 return 1;
709 }
710
711 DWORD stride = D3DXGetDeclVertexSize(declElements, 0);
712
713 VertexAttribute vertexMap[VertexAttribute::MaxAttribute];
714 CreateVertexAttributeMap(declElements, vertexMap);
715
716 meshfile << "mesh\n\n";
717
718 DumpVertexDescription(vertexMap, meshfile);
719
720 ID3DXMesh* optMesh = NULL;
721 ID3DXBuffer* vertexRemap = NULL;
722 DWORD* faceRemap = new DWORD[numFaces];
723 DWORD* optAdjacency = new DWORD[numFaces * 3];
724 hr = mesh->Optimize(D3DXMESHOPT_COMPACT | D3DXMESHOPT_STRIPREORDER,
725 //D3DXMESHOPT_VERTEXCACHE |
726 reinterpret_cast<DWORD*>(adjacency->GetBufferPointer()),
727 optAdjacency,
728 faceRemap,
729 &vertexRemap,
730 &optMesh);
731 if (FAILED(hr))
732 {
733 ShowD3DErrorMessage("Optimize failed: ", hr);
734 return 1;
735 }
736
737 // Attribute table
738 DWORD attribTableSize = 0;
739 hr = optMesh->GetAttributeTable(NULL, &attribTableSize);
740 if (FAILED(hr))
741 {
742 ShowD3DErrorMessage("Querying attribute table size", hr);
743 return 1;
744 }
745
746 D3DXATTRIBUTERANGE* attribTable = NULL;
747 if (attribTableSize > 0)
748 {
749 attribTable = new D3DXATTRIBUTERANGE[attribTableSize];
750 hr = optMesh->GetAttributeTable(attribTable, &attribTableSize);
751 if (FAILED(hr))
752 {
753 ShowD3DErrorMessage("Getting attribute table", hr);
754 return 1;
755 }
756 }
757
758 cout << "Attribute table size: " << attribTableSize << '\n';
759 if (attribTableSize == 1)
760 {
761 cout << "Attribute id: " << attribTable[0].AttribId << '\n';
762 }
763
764 if (!DumpMeshVertices(optMesh, vertexMap, stride, meshfile))
765 return 1;
766
767 // output the indices
768 for (DWORD attr = 0; attr < attribTableSize; attr++)
769 {
770 StripifyMeshSubset(optMesh, attr, meshfile);
771 }
772 meshfile << "\nend_mesh\n";
773
774 #if 0
775 IDirect3DIndexBuffer9* indices = NULL;
776 hr = mesh->GetIndexBuffer(&indices);
777 #endif
778
779 #if 0
780 // No message loop required for this app
781 MSG msg;
782 GetMessage(&msg, NULL, 0u, 0u);
783 while (msg.message != WM_QUIT)
784 {
785 GetMessage(&msg, NULL, 0u, 0u);
786 TranslateMessage(&msg);
787 DispatchMessage(&msg);
788 }
789 #endif
790
791 return 0;
792 }
793
794
main(int argc,char * argv[])795 int main(int argc, char* argv[])
796 {
797 if (argc != 2)
798 {
799 cerr << "Usage: xtocmod <meshfile.x>\n";
800 return 1;
801 }
802
803 ID3DXMesh* mesh = NULL;
804 ID3DXBuffer* adjacency = NULL;
805 ID3DXBuffer* materials = NULL;
806 ID3DXBuffer* effects = NULL;
807
808 return 0;
809 }
810
811
D3DErrorString(HRESULT hr)812 char* D3DErrorString(HRESULT hr)
813 {
814 switch (hr)
815 {
816 case D3DERR_WRONGTEXTUREFORMAT:
817 return "D3DERR_WRONGTEXTUREFORMAT";
818 case D3DERR_UNSUPPORTEDCOLOROPERATION:
819 return "D3DERR_UNSUPPORTEDCOLOROPERATION";
820 case D3DERR_UNSUPPORTEDCOLORARG:
821 return "D3DERR_UNSUPPORTEDCOLORARG";
822 case D3DERR_UNSUPPORTEDALPHAOPERATION:
823 return "D3DERR_UNSUPPORTEDALPHAOPERATION";
824 case D3DERR_UNSUPPORTEDALPHAARG:
825 return "D3DERR_UNSUPPORTEDALPHAARG";
826 case D3DERR_TOOMANYOPERATIONS:
827 return "D3DERR_TOOMANYOPERATIONS";
828 case D3DERR_CONFLICTINGTEXTUREFILTER:
829 return "D3DERR_CONFLICTINGTEXTUREFILTER";
830 case D3DERR_UNSUPPORTEDFACTORVALUE:
831 return "D3DERR_UNSUPPORTEDFACTORVALUE";
832 case D3DERR_CONFLICTINGRENDERSTATE:
833 return "D3DERR_CONFLICTINGRENDERSTATE";
834 case D3DERR_UNSUPPORTEDTEXTUREFILTER:
835 return "D3DERR_UNSUPPORTEDTEXTUREFILTER";
836 case D3DERR_CONFLICTINGTEXTUREPALETTE:
837 return "D3DERR_CONFLICTINGTEXTUREPALETTE";
838 case D3DERR_DRIVERINTERNALERROR:
839 return "D3DERR_DRIVERINTERNALERROR";
840 case D3DERR_NOTFOUND:
841 return "D3DERR_NOTFOUND";
842 case D3DERR_MOREDATA:
843 return "D3DERR_MOREDATA";
844 case D3DERR_DEVICELOST:
845 return "D3DERR_DEVICELOST";
846 case D3DERR_DEVICENOTRESET:
847 return "D3DERR_DEVICENOTRESET";
848 case D3DERR_NOTAVAILABLE:
849 return "D3DERR_NOTAVAILABLE";
850 case D3DERR_OUTOFVIDEOMEMORY:
851 return "D3DERR_OUTOFVIDEOMEMORY";
852 case D3DERR_INVALIDDEVICE:
853 return "D3DERR_INVALIDDEVICE";
854 case D3DERR_INVALIDCALL:
855 return "D3DERR_INVALIDCALL";
856 case D3DERR_DRIVERINVALIDCALL:
857 return "D3DERR_DRIVERINVALIDCALL";
858 case D3DERR_WASSTILLDRAWING:
859 return "D3DERR_WASSTILLDRAWING";
860 case D3DOK_NOAUTOGEN:
861 return "D3DOK_NOAUTOGEN";
862
863 case D3DXERR_CANNOTMODIFYINDEXBUFFER:
864 return "D3DXERR_CANNOTMODIFYINDEXBUFFER";
865 case D3DXERR_INVALIDMESH:
866 return "D3DXERR_INVALIDMESH";
867 case D3DXERR_CANNOTATTRSORT:
868 return "D3DXERR_CANNOTATTRSORT";
869 case D3DXERR_SKINNINGNOTSUPPORTED:
870 return "D3DXERR_SKINNINGNOTSUPPORTED";
871 case D3DXERR_TOOMANYINFLUENCES:
872 return "D3DXERR_TOOMANYINFLUENCES";
873 case D3DXERR_INVALIDDATA:
874 return "D3DXERR_INVALIDDATA";
875 case D3DXERR_LOADEDMESHASNODATA:
876 return "D3DXERR_LOADEDMESHASNODATA";
877 case D3DXERR_DUPLICATENAMEDFRAGMENT:
878 return "D3DXERR_DUPLICATENAMEDFRAGMENT";
879
880 default:
881 return "Unkown D3D Error";
882 }
883 }
884
885
ShowD3DErrorMessage(char * info,HRESULT hr)886 void ShowD3DErrorMessage(char* info, HRESULT hr)
887 {
888 char buf[1024];
889
890 sprintf(buf, "%s - %s", info, D3DErrorString(hr));
891 MessageBox(g_mainWindow,
892 buf, "Fatal Error",
893 MB_OK | MB_ICONERROR);
894 }
895
896