cmodfix.cpp

来自「celestia源代码」· C++ 代码 · 共 1,525 行 · 第 1/3 页

CPP
1,525
字号
// cmodfix.cpp//// Copyright (C) 2004, Chris Laurel <claurel@shatters.net>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; either version 2// of the License, or (at your option) any later version.//// Perform various adjustments to a cmod file#include <celengine/modelfile.h>#include <celengine/tokenizer.h>#include <celengine/texmanager.h>#include <cel3ds/3dsread.h>#include <celmath/mathlib.h>#include <cstring>#include <cassert>#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#ifdef TRISTRIP#include <NvTriStrip.h>#endifusing namespace std;string inputFilename;string outputFilename;bool outputBinary = false;bool uniquify = false;bool genNormals = false;bool genTangents = false;bool weldVertices = false;bool mergeMeshes = false;bool stripify = false;unsigned int vertexCacheSize = 16;float smoothAngle = 60.0f;void usage(){    cerr << "Usage: cmodfix [options] [input cmod file [output cmod file]]\n";    cerr << "   --binary (or -b)      : output a binary .cmod file\n";    cerr << "   --ascii (or -a)       : output an ASCII .cmod file\n";    cerr << "   --uniquify (or -u)    : eliminate duplicate vertices\n";    cerr << "   --tangents (or -t)    : generate tangents\n";    cerr << "   --normals (or -n)     : generate normals\n";    cerr << "   --smooth (or -s) <angle> : smoothing angle for normal generation\n";    cerr << "   --weld (or -w)        : join identical vertices before normal generation\n";    cerr << "   --merge (or -m)       : merge submeshes to improve rendering performance\n";#ifdef TRISTRIP    cerr << "   --optimize (or -o)    : optimize by converting triangle lists to strips\n";#endif}struct Vertex{    Vertex() :        index(0), attributes(NULL) {};    Vertex(uint32 _index, const void* _attributes) :        index(_index), attributes(_attributes) {};    uint32 index;    const void* attributes;};struct Face{    Vec3f normal;    uint32 i[3];    // vertex attribute indices    uint32 vi[3];   // vertex point indices -- same as above unless welding};typedef public std::binary_function<const Vertex&, const Vertex&, bool> VertexComparator;class FullComparator : public VertexComparator{public:    FullComparator(int _vertexSize) :        vertexSize(_vertexSize)    {    }    bool operator()(const Vertex& a, const Vertex& b) const    {        const char* s0 = reinterpret_cast<const char*>(a.attributes);        const char* s1 = reinterpret_cast<const char*>(b.attributes);        for (int i = 0; i < vertexSize; i++)        {            if (s0[i] < s1[i])                return true;            else if (s0[i] > s1[i])                return false;        }        return false;    }private:    int vertexSize;};class PointComparator : public VertexComparator{public:    PointComparator()    {    }    bool operator()(const Vertex& a, const Vertex& b) const    {        const Point3f* p0 = reinterpret_cast<const Point3f*>(a.attributes);        const Point3f* p1 = reinterpret_cast<const Point3f*>(b.attributes);        if (p0->x < p1->x)        {            return true;        }        else if (p0->x > p1->x)        {            return false;        }        else        {            if (p0->y < p1->y)                return true;            else if (p0->y > p1->y)                return false;            else                return p0->z < p1->z;        }    }private:    int ignore;};class PointTexCoordComparator : public VertexComparator{public:    PointTexCoordComparator(uint32 _posOffset,                            uint32 _texCoordOffset,                            bool _wrap) :        posOffset(_posOffset),        texCoordOffset(_texCoordOffset),        wrap(_wrap)    {    }    bool operator()(const Vertex& a, const Vertex& b) const    {        const char* adata = reinterpret_cast<const char*>(a.attributes);        const char* bdata = reinterpret_cast<const char*>(b.attributes);        const Point3f* p0 = reinterpret_cast<const Point3f*>(adata + posOffset);        const Point3f* p1 = reinterpret_cast<const Point3f*>(bdata + posOffset);        const Point2f* tc0 = reinterpret_cast<const Point2f*>(adata + posOffset);        const Point2f* tc1 = reinterpret_cast<const Point2f*>(bdata + posOffset);        if (p0->x < p1->x)        {            return true;        }        else if (p0->x > p1->x)        {            return false;        }        else        {            if (p0->y < p1->y)            {                return true;            }            else if (p0->y > p1->y)            {                return false;            }            else            {                if (p0->z < p1->z)                {                    return true;                }                else if (p0->z > p1->z)                {                    return false;                }                else                {                    if (tc0->x < tc1->x)                        return true;                    else if (tc0->x > tc1->x)                        return false;                    else                        return tc0->y < tc1->y;                }            }        }    }private:    uint32 posOffset;    uint32 texCoordOffset;    bool wrap;};bool equal(const Vertex& a, const Vertex& b, uint32 vertexSize){    const char* s0 = reinterpret_cast<const char*>(a.attributes);    const char* s1 = reinterpret_cast<const char*>(b.attributes);    for (uint32 i = 0; i < vertexSize; i++)    {        if (s0[i] != s1[i])            return false;    }    return true;}bool equalPoint(const Vertex& a, const Vertex& b){    const Point3f* p0 = reinterpret_cast<const Point3f*>(a.attributes);    const Point3f* p1 = reinterpret_cast<const Point3f*>(b.attributes);    return *p0 == *p1;}bool operator==(const Mesh::VertexAttribute& a,                const Mesh::VertexAttribute& b){    return (a.semantic == b.semantic &&            a.format   == b.format &&            a.offset   == b.offset);}bool operator<(const Mesh::VertexAttribute& a,               const Mesh::VertexAttribute& b){    if (a.semantic < b.semantic)    {        return true;    }    else if (b.semantic < a.semantic)    {        return false;    }    else    {        if (a.format < b.format)            return true;        else if (b.format < a.format)            return false;        else            return a.offset < b.offset;    }}bool operator==(const Mesh::VertexDescription& a,                const Mesh::VertexDescription& b){    if (a.stride != b.stride || a.nAttributes != b.nAttributes)        return false;    for (uint32 i = 0; i < a.nAttributes; i++)    {        if (!(a.attributes[i] == b.attributes[i]))            return false;    }    return true;}bool operator<(const Mesh::VertexDescription& a,               const Mesh::VertexDescription& b){    if (a.stride < b.stride)        return true;    else if (b.stride < a.stride)        return false;    if (a.nAttributes < b.nAttributes)        return true;    else if (b.nAttributes < b.nAttributes)        return false;    for (uint32 i = 0; i < a.nAttributes; i++)    {        if (a.attributes[i] < b.attributes[i])            return true;        else if (b.attributes[i] < a.attributes[i])            return false;    }    return false;}class MeshVertexDescComparator :    public std::binary_function<const Mesh*, const Mesh*, bool>{public:    MeshVertexDescComparator()    {    }    bool operator()(const Mesh* a, const Mesh* b) const    {        return a->getVertexDescription() < b->getVertexDescription();    }private:    int ignore;};bool uniquifyVertices(Mesh& mesh){    uint32 nVertices = mesh.getVertexCount();    const Mesh::VertexDescription& desc = mesh.getVertexDescription();    if (nVertices == 0)        return false;    const char* vertexData = reinterpret_cast<const char*>(mesh.getVertexData());    if (vertexData == NULL)        return false;    // Initialize the array of vertices    vector<Vertex> vertices(nVertices);    uint32 i;    for (i = 0; i < nVertices; i++)    {        vertices[i] = Vertex(i, vertexData + i * desc.stride);    }    // Sort the vertices so that identical ones will be ordered consecutively    sort(vertices.begin(), vertices.end(), FullComparator(desc.stride));    // Count the number of unique vertices    uint32 uniqueVertexCount = 0;    for (i = 0; i < nVertices; i++)    {        if (i == 0 || !equal(vertices[i - 1], vertices[i], desc.stride))            uniqueVertexCount++;    }    // No work left to do if we couldn't eliminate any vertices    if (uniqueVertexCount == nVertices)        return true;    // Build the vertex map and the uniquified vertex data    vector<uint32> vertexMap(nVertices);    char* newVertexData = new char[uniqueVertexCount * desc.stride];    const char* oldVertexData = reinterpret_cast<const char*>(mesh.getVertexData());    uint32 j = 0;    for (i = 0; i < nVertices; i++)    {        if (i == 0 || !equal(vertices[i - 1], vertices[i], desc.stride))        {            if (i != 0)                j++;            assert(j < uniqueVertexCount);            memcpy(newVertexData + j * desc.stride,                   oldVertexData + vertices[i].index * desc.stride,                   desc.stride);        }        vertexMap[vertices[i].index] = j;    }    // Replace the vertex data with the compacted data    delete mesh.getVertexData();    mesh.setVertices(uniqueVertexCount, newVertexData);    mesh.remapIndices(vertexMap);    return true;}Point3fgetVertex(const void* vertexData,          int positionOffset,          uint32 stride,          uint32 index){    const float* fdata = reinterpret_cast<const float*>(reinterpret_cast<const char*>(vertexData) + stride * index + positionOffset);        return Point3f(fdata[0], fdata[1], fdata[2]);}Point2fgetTexCoord(const void* vertexData,            int texCoordOffset,            uint32 stride,            uint32 index){    const float* fdata = reinterpret_cast<const float*>(reinterpret_cast<const char*>(vertexData) + stride * index + texCoordOffset);        return Point2f(fdata[0], fdata[1]);}Vec3faverageFaceVectors(const vector<Face>& faces,                   uint32 thisFace,                   uint32* vertexFaces,                   uint32 vertexFaceCount,                   float cosSmoothingAngle){    const Face& face = faces[thisFace];    Vec3f v = Vec3f(0, 0, 0);    for (uint32 i = 0; i < vertexFaceCount; i++)    {        uint32 f = vertexFaces[i];        float cosAngle = face.normal * faces[f].normal;        if (f == thisFace || cosAngle > cosSmoothingAngle)            v += faces[f].normal;    }    if (v * v == 0.0f)        v = Vec3f(1.0f, 0.0f, 0.0f);    else        v.normalize();    return v;}voidcopyVertex(void* newVertexData,           const Mesh::VertexDescription& newDesc,           const void* oldVertexData,           const Mesh::VertexDescription& oldDesc,           uint32 oldIndex,           const uint32 fromOffsets[]){    const char* oldVertex = reinterpret_cast<const char*>(oldVertexData) +        oldDesc.stride * oldIndex;    char* newVertex = reinterpret_cast<char*>(newVertexData);    for (uint32 i = 0; i < newDesc.nAttributes; i++)    {        if (fromOffsets[i] != ~0)        {            memcpy(newVertex + newDesc.attributes[i].offset,                   oldVertex + fromOffsets[i],                   Mesh::getVertexAttributeSize(newDesc.attributes[i].format));        }    }}voidaugmentVertexDescription(Mesh::VertexDescription& desc,                         Mesh::VertexAttributeSemantic semantic,                         Mesh::VertexAttributeFormat format){    Mesh::VertexAttribute* attributes = new Mesh::VertexAttribute[desc.nAttributes + 1];    uint32 stride = 0;    uint32 nAttributes = 0;    bool foundMatch = false;        for (uint32 i = 0; i < desc.nAttributes; i++)    {        if (semantic == desc.attributes[i].semantic &&            format != desc.attributes[i].format)        {            // The semantic matches, but the format does not; skip this            // item.        }        else        {            if (semantic == desc.attributes[i].semantic)                foundMatch = true;            attributes[nAttributes] = desc.attributes[i];            attributes[nAttributes].offset = stride;            stride += Mesh::getVertexAttributeSize(desc.attributes[i].format);            nAttributes++;        }    }    if (!foundMatch)    {        attributes[nAttributes++] = Mesh::VertexAttribute(semantic,                                                          format,                                                          stride);        stride += Mesh::getVertexAttributeSize(format);    }    delete[] desc.attributes;    desc.attributes = attributes;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?