?? xtocmod.cpp
字號:
#include <iostream>#include <fstream>#include <iomanip>#include <algorithm>#include <cstdio>#include <cassert>#include <cstring>#include <d3dx9.h>using namespace std;static IDirect3D9* g_d3d = NULL;static IDirect3DDevice9* g_d3dDev = NULL;static HWND g_mainWindow = NULL;char* D3DErrorString(HRESULT); void ShowD3DErrorMessage(char* info, HRESULT hr);struct VertexAttribute{ enum { Position = 0, Color0 = 1, Color1 = 2, Normal = 3, Tangent = 4, Texture0 = 5, Texture1 = 6, Texture2 = 7, Texture3 = 8, MaxAttribute = 9, InvalidAttribute = -1, }; enum Format { Float1 = 0, Float2 = 1, Float3 = 2, Float4 = 3, UByte4 = 4, InvalidFormat = -1, }; unsigned int offset; Format format;};char* AttribFormatNames[] ={ "f1", "f2", "f3", "f4", "ub4" };char* AttribNames[] = { "position", "color0", "color1", "normal", "tangent", "texcoord0", "texcoord1", "texcoord2", "texcoord3"};bool operator==(const D3DCOLORVALUE& c0, const D3DCOLORVALUE& c1){ return (c0.r == c1.r && c0.g == c1.g && c0.b == c1.b && c0.a == c1.a);}bool operator<(const D3DCOLORVALUE& c0, const D3DCOLORVALUE& c1){ if (c0.r == c1.r) { if (c0.g == c1.g) { if (c0.b == c1.b) return c0.a < c1.a; else return c0.b < c1.b; } else { return c0.g < c1.g; } } else { return c0.r < c1.r; }}bool operator==(const D3DXMATERIAL& mat0, const D3DXMATERIAL& mat1){ // Compare the texture filenames for equality, safely handling // null filenames. bool sameTex; if (mat0.pTextureFilename == NULL) { sameTex = (mat1.pTextureFilename == NULL); } else if (mat1.pTextureFilename == NULL) { sameTex = false; } else { sameTex = (strcmp(mat0.pTextureFilename, mat1.pTextureFilename) == 0); } return (mat0.MatD3D.Diffuse == mat1.MatD3D.Diffuse && mat0.MatD3D.Ambient == mat1.MatD3D.Ambient && mat0.MatD3D.Specular == mat1.MatD3D.Specular && mat0.MatD3D.Emissive == mat1.MatD3D.Emissive && mat0.MatD3D.Power == mat1.MatD3D.Power && sameTex);}ostream& operator<<(ostream& o, const D3DCOLORVALUE& c){ return (o << c.r << ' ' << c.g << ' ' << c.b);}static void render(){ g_d3dDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 0, 0, 192), // color 0.0f, // z 0); // stencil value}template<class T> int checkForFan(DWORD nTris, T* indices){ // Even number of triangles required; pairs of triangles can always // be just as efficiently represented as strips, so skip them. if (nTris % 2 == 1 || nTris <= 2) return -1; DWORD i; T anchor = indices[0]; bool isFan = true; for (i = 1; i < nTris / 2 && isFan; i++) { if (indices[i * 2] != anchor) isFan = false; } if (isFan) return 0; isFan = true; anchor = indices[1]; for (i = 1; i < nTris / 2 && isFan; i++) { if (indices[i * 2 + 1] != anchor) isFan = false; } if (isFan) cout << "fan: nTris=" << nTris << ", anchor=" << anchor << '\n'; return isFan ? 1 : -1;}template<class T> int DumpTriStrip(DWORD nTris, T* indices, int materialIndex, ostream& meshfile){ meshfile << "tristrip "; meshfile << materialIndex << ' ' << (nTris + 2) << '\n'; DWORD indexCount = nTris + 2; for (DWORD j = 0; j < indexCount; j++) { meshfile << indices[j] << ' '; if (j == indexCount - 1 || j % 12 == 11) meshfile << '\n'; }}// The D3DX tristrip converter only produces strips, not fans. It dumps// fans as strips where every other triangle is degenerate. We detect such// strips and output them as fans instead, thus eliminating a bunch of// degenerate triangles.template<class T> void DumpTriStripAsFan(DWORD nTris, T* indices, int materialIndex, DWORD anchorOffset, ostream& meshfile){ meshfile << "trifan "; meshfile << materialIndex << ' ' << (nTris / 2 + 3) << '\n'; DWORD indexCount = nTris + 2; T anchor = indices[anchorOffset]; meshfile << anchor << ' '; if (anchorOffset == 1) { for (int j = (int) indexCount - 1; j >= 0; j--) { if (indices[j] != anchor) meshfile << indices[j] << ' '; if (j == 0 || j % 12 == 11) meshfile << '\n'; } } else if (anchorOffset == 0) { // D3DX never seems to produce strips where the first vertex is // the anchor, but we'll handle it just in case. for (int j = 1; j < (int) indexCount; j++) { if (indices[j] != anchor) meshfile << indices[j] << ' '; if (j == indexCount - 1 || j % 12 == 11) meshfile << '\n'; } }}bool StripifyMeshSubset(ID3DXMesh* mesh, DWORD attribId, ostream& meshfile){ // TODO: Fall back to tri lists if the strip size is too small // TODO: Detect when a tri fan should be used instead of a tri list // Convert to tri strips IDirect3DIndexBuffer9* indices = NULL; DWORD numIndices = 0; ID3DXBuffer* strips = NULL; DWORD numStrips = 0; HRESULT hr; hr = D3DXConvertMeshSubsetToStrips(mesh, attribId, 0, &indices, &numIndices, &strips, &numStrips); if (FAILED(hr)) { cout << "Stripify failed\n"; return false; } cout << "Converted to " << numStrips << " strips\n"; cout << "Strip buffer size: " << strips->GetBufferSize() << '\n'; if (numStrips != strips->GetBufferSize() / 4) { cout << "Strip count is incorrect!\n"; return false; } bool index32 = false; { D3DINDEXBUFFER_DESC desc; indices->GetDesc(&desc); if (desc.Format == D3DFMT_INDEX32) { index32 = true; } else if (desc.Format == D3DFMT_INDEX16) { index32 = false; } else { cout << "Bad index format. Strange.\n"; return false; } } void* indexData = NULL; hr = indices->Lock(0, 0, &indexData, D3DLOCK_READONLY); if (FAILED(hr)) { cout << "Failed to lock index buffer: " << D3DErrorString(hr) << '\n'; return false; } { DWORD* stripLengths = reinterpret_cast<DWORD*>(strips->GetBufferPointer()); int k = 0; for (int i = 0; i < numStrips; i++) { if (stripLengths[i] == 0) { cout << "Bad triangle strip (length == 0) in mesh!\n"; return false; } if (index32) { DWORD* indices = reinterpret_cast<DWORD*>(indexData) + k; int fanStart = checkForFan(stripLengths[i], indices); if (fanStart != 1) { DumpTriStrip(stripLengths[i], indices, (int) attribId, meshfile); } else { DumpTriStripAsFan(stripLengths[i], indices, (int) attribId, fanStart, meshfile); } } else { WORD* indices = reinterpret_cast<WORD*>(indexData) + k; int fanStart = checkForFan(stripLengths[i], indices); if (fanStart != 1) { DumpTriStrip(stripLengths[i], indices, (int) attribId, meshfile); } else { DumpTriStripAsFan(stripLengths[i], indices, (int) attribId, fanStart, meshfile); } } k += stripLengths[i] + 2; } cout << "k=" << k << ", numIndices=" << numIndices; if (index32) cout << ", 32-bit indices\n"; else cout << ", 16-bit indices\n"; } return true;}void DumpVertexDescription(VertexAttribute vertexMap[], ostream& meshfile){ meshfile << "vertexdesc\n"; for (int i = 0; i < VertexAttribute::MaxAttribute; i++) { if (vertexMap[i].format != VertexAttribute::InvalidFormat) { meshfile << AttribNames[i] << " " << AttribFormatNames[vertexMap[i].format] << " " << '\n'; } } meshfile << "end_vertexdesc\n\n";}bool DumpMeshVertices(ID3DXMesh* mesh, VertexAttribute vertexMap[], DWORD stride, ostream& meshfile){ IDirect3DVertexBuffer9* vb = NULL; HRESULT hr = mesh->GetVertexBuffer(&vb); if (FAILED(hr)) { ShowD3DErrorMessage("Getting vertex buffer", hr); return false; } char* vertexData = NULL; hr = vb->Lock(0, 0, reinterpret_cast<void**>(&vertexData), D3DLOCK_READONLY); if (FAILED(hr) || vertexData == NULL) { ShowD3DErrorMessage("Locking vertex buffer", hr); return false; } DWORD numVertices = mesh->GetNumVertices(); meshfile << "vertices " << numVertices << '\n'; for (DWORD i = 0; i < numVertices; i++) { for (int attr = 0; attr < VertexAttribute::MaxAttribute; attr++) { if (vertexMap[attr].format != VertexAttribute::InvalidFormat) { char* chardata = vertexData + i * stride + vertexMap[attr].offset; float* floatdata = reinterpret_cast<float*>(chardata); switch (vertexMap[attr].format) { case VertexAttribute::Float1: meshfile << floatdata[0] << ' '; break; case VertexAttribute::Float2: meshfile << floatdata[0] << ' ' << floatdata[1] << ' '; break; case VertexAttribute::Float3: meshfile << floatdata[0] << ' ' << floatdata[1] << ' '; meshfile << floatdata[2] << ' '; break; case VertexAttribute::Float4: meshfile << floatdata[0] << ' ' << floatdata[1] << ' '; meshfile << floatdata[2] << ' ' << floatdata[3]; break; case VertexAttribute::UByte4: meshfile << (unsigned int) chardata[0] << ' ' << (unsigned int) chardata[1] << ' ' << (unsigned int) chardata[2] << ' ' << (unsigned int) chardata[3] << ' '; break; default: break; } } } meshfile << '\n'; } vb->Unlock(); meshfile << '\n'; return true;}bool CreateVertexAttributeMap(D3DVERTEXELEMENT9 declElements[], VertexAttribute vertexMap[]){ int i = 0; for (i = 0; i < VertexAttribute::MaxAttribute; i++) { vertexMap[i].offset = 0; vertexMap[i].format = VertexAttribute::InvalidFormat;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -