xtocmod.cpp

来自「celestia源代码」· C++ 代码 · 共 896 行 · 第 1/2 页

CPP
896
字号
#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 + =
减小字号Ctrl + -
显示快捷键?