xtocmod.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:25k
源码类别:

OpenGL

开发平台:

Visual C++

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