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 + -
显示快捷键?