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

OpenGL

开发平台:

Visual C++

  1. // cmodfix.cpp
  2. //
  3. // Copyright (C) 2004, Chris Laurel <claurel@shatters.net>
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. //
  10. // Perform various adjustments to a cmod file
  11. #include <celengine/modelfile.h>
  12. #include <celengine/tokenizer.h>
  13. #include <celengine/texmanager.h>
  14. #include <cel3ds/3dsread.h>
  15. #include <celmath/mathlib.h>
  16. #include <cstring>
  17. #include <cassert>
  18. #include <cmath>
  19. #include <cstdio>
  20. #include <algorithm>
  21. #include <vector>
  22. #ifdef TRISTRIP
  23. #include <NvTriStrip.h>
  24. #endif
  25. using namespace std;
  26. string inputFilename;
  27. string outputFilename;
  28. bool outputBinary = false;
  29. bool uniquify = false;
  30. bool genNormals = false;
  31. bool genTangents = false;
  32. bool weldVertices = false;
  33. bool mergeMeshes = false;
  34. bool stripify = false;
  35. unsigned int vertexCacheSize = 16;
  36. float smoothAngle = 60.0f;
  37. void usage()
  38. {
  39.     cerr << "Usage: cmodfix [options] [input cmod file [output cmod file]]n";
  40.     cerr << "   --binary (or -b)      : output a binary .cmod filen";
  41.     cerr << "   --ascii (or -a)       : output an ASCII .cmod filen";
  42.     cerr << "   --uniquify (or -u)    : eliminate duplicate verticesn";
  43.     cerr << "   --tangents (or -t)    : generate tangentsn";
  44.     cerr << "   --normals (or -n)     : generate normalsn";
  45.     cerr << "   --smooth (or -s) <angle> : smoothing angle for normal generationn";
  46.     cerr << "   --weld (or -w)        : join identical vertices before normal generationn";
  47.     cerr << "   --merge (or -m)       : merge submeshes to improve rendering performancen";
  48. #ifdef TRISTRIP
  49.     cerr << "   --optimize (or -o)    : optimize by converting triangle lists to stripsn";
  50. #endif
  51. }
  52. struct Vertex
  53. {
  54.     Vertex() :
  55.         index(0), attributes(NULL) {};
  56.     Vertex(uint32 _index, const void* _attributes) :
  57.         index(_index), attributes(_attributes) {};
  58.     uint32 index;
  59.     const void* attributes;
  60. };
  61. struct Face
  62. {
  63.     Vec3f normal;
  64.     uint32 i[3];    // vertex attribute indices
  65.     uint32 vi[3];   // vertex point indices -- same as above unless welding
  66. };
  67. typedef std::binary_function<const Vertex&, const Vertex&, bool> VertexComparator;
  68. class FullComparator : public VertexComparator
  69. {
  70. public:
  71.     FullComparator(int _vertexSize) :
  72.         vertexSize(_vertexSize)
  73.     {
  74.     }
  75.     bool operator()(const Vertex& a, const Vertex& b) const
  76.     {
  77.         const char* s0 = reinterpret_cast<const char*>(a.attributes);
  78.         const char* s1 = reinterpret_cast<const char*>(b.attributes);
  79.         for (int i = 0; i < vertexSize; i++)
  80.         {
  81.             if (s0[i] < s1[i])
  82.                 return true;
  83.             else if (s0[i] > s1[i])
  84.                 return false;
  85.         }
  86.         return false;
  87.     }
  88. private:
  89.     int vertexSize;
  90. };
  91. class PointComparator : public VertexComparator
  92. {
  93. public:
  94.     PointComparator()
  95.     {
  96.     }
  97.     bool operator()(const Vertex& a, const Vertex& b) const
  98.     {
  99.         const Point3f* p0 = reinterpret_cast<const Point3f*>(a.attributes);
  100.         const Point3f* p1 = reinterpret_cast<const Point3f*>(b.attributes);
  101.         if (p0->x < p1->x)
  102.         {
  103.             return true;
  104.         }
  105.         else if (p0->x > p1->x)
  106.         {
  107.             return false;
  108.         }
  109.         else
  110.         {
  111.             if (p0->y < p1->y)
  112.                 return true;
  113.             else if (p0->y > p1->y)
  114.                 return false;
  115.             else
  116.                 return p0->z < p1->z;
  117.         }
  118.     }
  119. private:
  120.     int ignore;
  121. };
  122. class PointTexCoordComparator : public VertexComparator
  123. {
  124. public:
  125.     PointTexCoordComparator(uint32 _posOffset,
  126.                             uint32 _texCoordOffset,
  127.                             bool _wrap) :
  128.         posOffset(_posOffset),
  129.         texCoordOffset(_texCoordOffset),
  130.         wrap(_wrap)
  131.     {
  132.     }
  133.     bool operator()(const Vertex& a, const Vertex& b) const
  134.     {
  135.         const char* adata = reinterpret_cast<const char*>(a.attributes);
  136.         const char* bdata = reinterpret_cast<const char*>(b.attributes);
  137.         const Point3f* p0 = reinterpret_cast<const Point3f*>(adata + posOffset);
  138.         const Point3f* p1 = reinterpret_cast<const Point3f*>(bdata + posOffset);
  139.         const Point2f* tc0 = reinterpret_cast<const Point2f*>(adata + posOffset);
  140.         const Point2f* tc1 = reinterpret_cast<const Point2f*>(bdata + posOffset);
  141.         if (p0->x < p1->x)
  142.         {
  143.             return true;
  144.         }
  145.         else if (p0->x > p1->x)
  146.         {
  147.             return false;
  148.         }
  149.         else
  150.         {
  151.             if (p0->y < p1->y)
  152.             {
  153.                 return true;
  154.             }
  155.             else if (p0->y > p1->y)
  156.             {
  157.                 return false;
  158.             }
  159.             else
  160.             {
  161.                 if (p0->z < p1->z)
  162.                 {
  163.                     return true;
  164.                 }
  165.                 else if (p0->z > p1->z)
  166.                 {
  167.                     return false;
  168.                 }
  169.                 else
  170.                 {
  171.                     if (tc0->x < tc1->x)
  172.                         return true;
  173.                     else if (tc0->x > tc1->x)
  174.                         return false;
  175.                     else
  176.                         return tc0->y < tc1->y;
  177.                 }
  178.             }
  179.         }
  180.     }
  181. private:
  182.     uint32 posOffset;
  183.     uint32 texCoordOffset;
  184.     bool wrap;
  185. };
  186. bool equal(const Vertex& a, const Vertex& b, uint32 vertexSize)
  187. {
  188.     const char* s0 = reinterpret_cast<const char*>(a.attributes);
  189.     const char* s1 = reinterpret_cast<const char*>(b.attributes);
  190.     for (uint32 i = 0; i < vertexSize; i++)
  191.     {
  192.         if (s0[i] != s1[i])
  193.             return false;
  194.     }
  195.     return true;
  196. }
  197. bool equalPoint(const Vertex& a, const Vertex& b)
  198. {
  199.     const Point3f* p0 = reinterpret_cast<const Point3f*>(a.attributes);
  200.     const Point3f* p1 = reinterpret_cast<const Point3f*>(b.attributes);
  201.     return *p0 == *p1;
  202. }
  203. bool operator==(const Mesh::VertexAttribute& a,
  204.                 const Mesh::VertexAttribute& b)
  205. {
  206.     return (a.semantic == b.semantic &&
  207.             a.format   == b.format &&
  208.             a.offset   == b.offset);
  209. }
  210. bool operator<(const Mesh::VertexAttribute& a,
  211.                const Mesh::VertexAttribute& b)
  212. {
  213.     if (a.semantic < b.semantic)
  214.     {
  215.         return true;
  216.     }
  217.     else if (b.semantic < a.semantic)
  218.     {
  219.         return false;
  220.     }
  221.     else
  222.     {
  223.         if (a.format < b.format)
  224.             return true;
  225.         else if (b.format < a.format)
  226.             return false;
  227.         else
  228.             return a.offset < b.offset;
  229.     }
  230. }
  231. bool operator==(const Mesh::VertexDescription& a,
  232.                 const Mesh::VertexDescription& b)
  233. {
  234.     if (a.stride != b.stride || a.nAttributes != b.nAttributes)
  235.         return false;
  236.     for (uint32 i = 0; i < a.nAttributes; i++)
  237.     {
  238.         if (!(a.attributes[i] == b.attributes[i]))
  239.             return false;
  240.     }
  241.     return true;
  242. }
  243. bool operator<(const Mesh::VertexDescription& a,
  244.                const Mesh::VertexDescription& b)
  245. {
  246.     if (a.stride < b.stride)
  247.         return true;
  248.     else if (b.stride < a.stride)
  249.         return false;
  250.     if (a.nAttributes < b.nAttributes)
  251.         return true;
  252.     else if (b.nAttributes < b.nAttributes)
  253.         return false;
  254.     for (uint32 i = 0; i < a.nAttributes; i++)
  255.     {
  256.         if (a.attributes[i] < b.attributes[i])
  257.             return true;
  258.         else if (b.attributes[i] < a.attributes[i])
  259.             return false;
  260.     }
  261.     return false;
  262. }
  263. class MeshVertexDescComparator :
  264.     public std::binary_function<const Mesh*, const Mesh*, bool>
  265. {
  266. public:
  267.     MeshVertexDescComparator()
  268.     {
  269.     }
  270.     bool operator()(const Mesh* a, const Mesh* b) const
  271.     {
  272.         return a->getVertexDescription() < b->getVertexDescription();
  273.     }
  274. private:
  275.     int ignore;
  276. };
  277. bool uniquifyVertices(Mesh& mesh)
  278. {
  279.     uint32 nVertices = mesh.getVertexCount();
  280.     const Mesh::VertexDescription& desc = mesh.getVertexDescription();
  281.     if (nVertices == 0)
  282.         return false;
  283.     const char* vertexData = reinterpret_cast<const char*>(mesh.getVertexData());
  284.     if (vertexData == NULL)
  285.         return false;
  286.     // Initialize the array of vertices
  287.     vector<Vertex> vertices(nVertices);
  288.     uint32 i;
  289.     for (i = 0; i < nVertices; i++)
  290.     {
  291.         vertices[i] = Vertex(i, vertexData + i * desc.stride);
  292.     }
  293.     // Sort the vertices so that identical ones will be ordered consecutively
  294.     sort(vertices.begin(), vertices.end(), FullComparator(desc.stride));
  295.     // Count the number of unique vertices
  296.     uint32 uniqueVertexCount = 0;
  297.     for (i = 0; i < nVertices; i++)
  298.     {
  299.         if (i == 0 || !equal(vertices[i - 1], vertices[i], desc.stride))
  300.             uniqueVertexCount++;
  301.     }
  302.     // No work left to do if we couldn't eliminate any vertices
  303.     if (uniqueVertexCount == nVertices)
  304.         return true;
  305.     // Build the vertex map and the uniquified vertex data
  306.     vector<uint32> vertexMap(nVertices);
  307.     char* newVertexData = new char[uniqueVertexCount * desc.stride];
  308.     const char* oldVertexData = reinterpret_cast<const char*>(mesh.getVertexData());
  309.     uint32 j = 0;
  310.     for (i = 0; i < nVertices; i++)
  311.     {
  312.         if (i == 0 || !equal(vertices[i - 1], vertices[i], desc.stride))
  313.         {
  314.             if (i != 0)
  315.                 j++;
  316.             assert(j < uniqueVertexCount);
  317.             memcpy(newVertexData + j * desc.stride,
  318.                    oldVertexData + vertices[i].index * desc.stride,
  319.                    desc.stride);
  320.         }
  321.         vertexMap[vertices[i].index] = j;
  322.     }
  323.     // Replace the vertex data with the compacted data
  324.     delete mesh.getVertexData();
  325.     mesh.setVertices(uniqueVertexCount, newVertexData);
  326.     mesh.remapIndices(vertexMap);
  327.     return true;
  328. }
  329. Point3f
  330. getVertex(const void* vertexData,
  331.           int positionOffset,
  332.           uint32 stride,
  333.           uint32 index)
  334. {
  335.     const float* fdata = reinterpret_cast<const float*>(reinterpret_cast<const char*>(vertexData) + stride * index + positionOffset);
  336.     
  337.     return Point3f(fdata[0], fdata[1], fdata[2]);
  338. }
  339. Point2f
  340. getTexCoord(const void* vertexData,
  341.             int texCoordOffset,
  342.             uint32 stride,
  343.             uint32 index)
  344. {
  345.     const float* fdata = reinterpret_cast<const float*>(reinterpret_cast<const char*>(vertexData) + stride * index + texCoordOffset);
  346.     
  347.     return Point2f(fdata[0], fdata[1]);
  348. }
  349. Vec3f
  350. averageFaceVectors(const vector<Face>& faces,
  351.                    uint32 thisFace,
  352.                    uint32* vertexFaces,
  353.                    uint32 vertexFaceCount,
  354.                    float cosSmoothingAngle)
  355. {
  356.     const Face& face = faces[thisFace];
  357.     Vec3f v = Vec3f(0, 0, 0);
  358.     for (uint32 i = 0; i < vertexFaceCount; i++)
  359.     {
  360.         uint32 f = vertexFaces[i];
  361.         float cosAngle = face.normal * faces[f].normal;
  362.         if (f == thisFace || cosAngle > cosSmoothingAngle)
  363.             v += faces[f].normal;
  364.     }
  365.     if (v * v == 0.0f)
  366.         v = Vec3f(1.0f, 0.0f, 0.0f);
  367.     else
  368.         v.normalize();
  369.     return v;
  370. }
  371. void
  372. copyVertex(void* newVertexData,
  373.            const Mesh::VertexDescription& newDesc,
  374.            const void* oldVertexData,
  375.            const Mesh::VertexDescription& oldDesc,
  376.            uint32 oldIndex,
  377.            const uint32 fromOffsets[])
  378. {
  379.     const char* oldVertex = reinterpret_cast<const char*>(oldVertexData) +
  380.         oldDesc.stride * oldIndex;
  381.     char* newVertex = reinterpret_cast<char*>(newVertexData);
  382.     for (uint32 i = 0; i < newDesc.nAttributes; i++)
  383.     {
  384.         if (fromOffsets[i] != ~0)
  385.         {
  386.             memcpy(newVertex + newDesc.attributes[i].offset,
  387.                    oldVertex + fromOffsets[i],
  388.                    Mesh::getVertexAttributeSize(newDesc.attributes[i].format));
  389.         }
  390.     }
  391. }
  392. void
  393. augmentVertexDescription(Mesh::VertexDescription& desc,
  394.                          Mesh::VertexAttributeSemantic semantic,
  395.                          Mesh::VertexAttributeFormat format)
  396. {
  397.     Mesh::VertexAttribute* attributes = new Mesh::VertexAttribute[desc.nAttributes + 1];
  398.     uint32 stride = 0;
  399.     uint32 nAttributes = 0;
  400.     bool foundMatch = false;
  401.     
  402.     for (uint32 i = 0; i < desc.nAttributes; i++)
  403.     {
  404.         if (semantic == desc.attributes[i].semantic &&
  405.             format != desc.attributes[i].format)
  406.         {
  407.             // The semantic matches, but the format does not; skip this
  408.             // item.
  409.         }
  410.         else
  411.         {
  412.             if (semantic == desc.attributes[i].semantic)
  413.                 foundMatch = true;
  414.             attributes[nAttributes] = desc.attributes[i];
  415.             attributes[nAttributes].offset = stride;
  416.             stride += Mesh::getVertexAttributeSize(desc.attributes[i].format);
  417.             nAttributes++;
  418.         }
  419.     }
  420.     if (!foundMatch)
  421.     {
  422.         attributes[nAttributes++] = Mesh::VertexAttribute(semantic,
  423.                                                           format,
  424.                                                           stride);
  425.         stride += Mesh::getVertexAttributeSize(format);
  426.     }
  427.     delete[] desc.attributes;
  428.     desc.attributes = attributes;
  429.     desc.nAttributes = nAttributes;
  430.     desc.stride = stride;
  431. }
  432. template <typename T> void
  433. joinVertices(vector<Face>& faces,
  434.              const void* vertexData,
  435.              const Mesh::VertexDescription& desc,
  436.              const T& comparator)
  437. {
  438.     // Don't do anything if we're given no data
  439.     if (faces.size() == 0)
  440.         return;
  441.     // Must have a position
  442.     assert(desc.getAttribute(Mesh::Position).format == Mesh::Float3);
  443.     uint32 posOffset = desc.getAttribute(Mesh::Position).offset;
  444.     const char* vertexPoints = reinterpret_cast<const char*>(vertexData) +
  445.         posOffset;
  446.     uint32 nVertices = faces.size() * 3;
  447.     // Initialize the array of vertices
  448.     vector<Vertex> vertices(nVertices);
  449.     uint32 f;
  450.     for (f = 0; f < faces.size(); f++)
  451.     {
  452.         for (uint32 j = 0; j < 3; j++)
  453.         {
  454.             uint32 index = faces[f].i[j];
  455.             vertices[f * 3 + j] = Vertex(index,
  456.                                          vertexPoints + desc.stride * index);
  457.                                          
  458.         }
  459.     }
  460.     // Sort the vertices so that identical ones will be ordered consecutively
  461.     sort(vertices.begin(), vertices.end(), comparator);
  462.     // Build the vertex merge map
  463.     vector<uint32> mergeMap(nVertices);
  464.     uint32 lastUnique = 0;
  465.     for (uint32 i = 0; i < nVertices; i++)
  466.     {
  467.         if (i == 0 ||
  468.             comparator.operator()(vertices[i - 1], vertices[i]) ||
  469.             comparator.operator()(vertices[i], vertices[i - 1]))
  470.         {
  471.             lastUnique = i;
  472.         }
  473.         mergeMap[vertices[i].index] = vertices[lastUnique].index;
  474.     }
  475.     // Remap the vertex indices
  476.     for (f = 0; f < faces.size(); f++)
  477.     {
  478.         for (uint32 k= 0; k < 3; k++)
  479.             faces[f].vi[k] = mergeMap[faces[f].i[k]];
  480.     }
  481. }
  482. Mesh*
  483. generateNormals(Mesh& mesh,
  484.                 float smoothAngle,
  485.                 bool weld)
  486. {
  487.     uint32 nVertices = mesh.getVertexCount();
  488.     float cosSmoothAngle = (float) cos(smoothAngle);
  489.     const Mesh::VertexDescription& desc = mesh.getVertexDescription();
  490.     if (desc.getAttribute(Mesh::Position).format != Mesh::Float3)
  491.     {
  492.         cerr << "Vertex position must be a float3n";
  493.         return NULL;
  494.     }
  495.     uint32 posOffset = desc.getAttribute(Mesh::Position).offset;
  496.  
  497.     uint32 nFaces = 0;
  498.     uint32 i;
  499.     for (i = 0; mesh.getGroup(i) != NULL; i++)
  500.     {
  501.         const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
  502.         
  503.         switch (group->prim)
  504.         {
  505.         case Mesh::TriList:
  506.             if (group->nIndices < 3 || group->nIndices % 3 != 0)
  507.             {
  508.                 cerr << "Triangle list has invalid number of indicesn";
  509.                 return NULL;
  510.             }
  511.             nFaces += group->nIndices / 3;
  512.             break;
  513.         case Mesh::TriStrip:
  514.         case Mesh::TriFan:
  515.             if (group->nIndices < 3)
  516.             {
  517.                 cerr << "Error: tri strip or fan has less than three indicesn";
  518.                 return NULL;
  519.             }
  520.             nFaces += group->nIndices - 2;
  521.             break;
  522.         default:
  523.             cerr << "Cannot generate normals for non-triangle primitivesn";
  524.             return NULL;
  525.         }
  526.     }
  527.     // Build the array of faces; this may require decomposing triangle strips
  528.     // and fans into triangle lists.
  529.     vector<Face> faces(nFaces);
  530.     uint32 f = 0;
  531.     for (i = 0; mesh.getGroup(i) != NULL; i++)
  532.     {
  533.         const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
  534.         
  535.         switch (group->prim)
  536.         {
  537.         case Mesh::TriList:
  538.             {
  539.                 for (uint32 j = 0; j < group->nIndices / 3; j++)
  540.                 {
  541.                     assert(f < nFaces);
  542.                     faces[f].i[0] = group->indices[j * 3];
  543.                     faces[f].i[1] = group->indices[j * 3 + 1];
  544.                     faces[f].i[2] = group->indices[j * 3 + 2];
  545.                     f++;
  546.                 }
  547.             }
  548.             break;
  549.         case Mesh::TriStrip:
  550.             {
  551.                 for (uint32 j = 2; j < group->nIndices; j++)
  552.                 {
  553.                     assert(f < nFaces);
  554.                     if (j % 2 == 0)
  555.                     {
  556.                         faces[f].i[0] = group->indices[j - 2];
  557.                         faces[f].i[1] = group->indices[j - 1];
  558.                         faces[f].i[2] = group->indices[j];
  559.                     }
  560.                     else
  561.                     {
  562.                         faces[f].i[0] = group->indices[j - 1];
  563.                         faces[f].i[1] = group->indices[j - 2];
  564.                         faces[f].i[2] = group->indices[j];
  565.                     }
  566.                     f++;
  567.                 }
  568.             }
  569.             break;
  570.         case Mesh::TriFan:
  571.             {
  572.                 for (uint32 j = 2; j < group->nIndices; j++)
  573.                 {
  574.                     assert(f < nFaces);
  575.                     faces[f].i[0] = group->indices[0];
  576.                     faces[f].i[1] = group->indices[j - 1];
  577.                     faces[f].i[2] = group->indices[j];
  578.                     f++;
  579.                 }
  580.             }
  581.             break;
  582.         default:
  583.             assert(0);
  584.             break;
  585.         }
  586.     }
  587.     assert(f == nFaces);
  588.     const void* vertexData = mesh.getVertexData();
  589.     // Compute normals for the faces
  590.     for (f = 0; f < nFaces; f++)
  591.     {
  592.         Face& face = faces[f];
  593.         Point3f p0 = getVertex(vertexData, posOffset, desc.stride, face.i[0]);
  594.         Point3f p1 = getVertex(vertexData, posOffset, desc.stride, face.i[1]);
  595.         Point3f p2 = getVertex(vertexData, posOffset, desc.stride, face.i[2]);
  596.         face.normal = cross(p1 - p0, p2 - p1);
  597.         if (face.normal * face.normal > 0.0f)
  598.             face.normal.normalize();
  599.     }
  600.     // For each vertex, create a list of faces that contain it
  601.     uint32* faceCounts = new uint32[nVertices];
  602.     uint32** vertexFaces = new uint32*[nVertices];
  603.     // Initialize the lists
  604.     for (i = 0; i < nVertices; i++)
  605.     {
  606.         faceCounts[i] = 0;
  607.         vertexFaces[i] = NULL;
  608.     }
  609.     // If we're welding vertices before generating normals, find identical
  610.     // points and merge them.  Otherwise, the point indices will be the same
  611.     // as the attribute indices.
  612.     if (weld)
  613.     {
  614.         joinVertices(faces, vertexData, desc, PointComparator());
  615.     }
  616.     else
  617.     {
  618.         for (f = 0; f < nFaces; f++)
  619.         {
  620.             faces[f].vi[0] = faces[f].i[0];
  621.             faces[f].vi[1] = faces[f].i[1];
  622.             faces[f].vi[2] = faces[f].i[2];
  623.         }
  624.     }
  625.     // Count the number of faces in which each vertex appears
  626.     for (f = 0; f < nFaces; f++)
  627.     {
  628.         Face& face = faces[f];
  629.         faceCounts[face.vi[0]]++;
  630.         faceCounts[face.vi[1]]++;
  631.         faceCounts[face.vi[2]]++;
  632.     }
  633.     // Allocate space for the per-vertex face lists
  634.     for (i = 0; i < nVertices; i++)
  635.     {
  636.         if (faceCounts[i] > 0)
  637.         {
  638.             vertexFaces[i] = new uint32[faceCounts[i] + 1];
  639.             vertexFaces[i][0] = faceCounts[i];
  640.         }
  641.     }
  642.     // Fill in the vertex/face lists
  643.     for (f = 0; f < nFaces; f++)
  644.     {
  645.         Face& face = faces[f];
  646.         vertexFaces[face.vi[0]][faceCounts[face.vi[0]]--] = f;
  647.         vertexFaces[face.vi[1]][faceCounts[face.vi[1]]--] = f;
  648.         vertexFaces[face.vi[2]][faceCounts[face.vi[2]]--] = f;
  649.     }
  650.     // Compute the vertex normals by averaging
  651.     vector<Vec3f> vertexNormals(nFaces * 3);
  652.     for (f = 0; f < nFaces; f++)
  653.     {
  654.         Face& face = faces[f];
  655.         for (uint32 j = 0; j < 3; j++)
  656.         {
  657.             vertexNormals[f * 3 + j] =
  658.                 averageFaceVectors(faces, f,
  659.                                    &vertexFaces[face.vi[j]][1],
  660.                                    vertexFaces[face.vi[j]][0],
  661.                                    cosSmoothAngle);
  662.         }
  663.     }
  664.     // Finally, create a new mesh with normals included
  665.     // Create the new vertex description
  666.     Mesh::VertexDescription newDesc(desc);
  667.     augmentVertexDescription(newDesc, Mesh::Normal, Mesh::Float3);
  668.     // We need to convert the copy the old vertex attributes to the new
  669.     // mesh.  In order to do this, we need the old offset of each attribute
  670.     // in the new vertex description.  The fromOffsets array will contain
  671.     // this mapping.
  672.     uint32 normalOffset = 0;
  673.     uint32 fromOffsets[16];
  674.     for (i = 0; i < newDesc.nAttributes; i++)
  675.     {
  676.         fromOffsets[i] = ~0;
  677.         if (newDesc.attributes[i].semantic == Mesh::Normal)
  678.         {
  679.             normalOffset = newDesc.attributes[i].offset;
  680.         }
  681.         else
  682.         {
  683.             for (uint32 j = 0; j < desc.nAttributes; j++)
  684.             {
  685.                 if (desc.attributes[j].semantic == newDesc.attributes[i].semantic)
  686.                 {
  687.                     assert(desc.attributes[j].format == newDesc.attributes[i].format);
  688.                     fromOffsets[i] = desc.attributes[j].offset;
  689.                     break;
  690.                 }
  691.             }
  692.         }
  693.     }
  694.     // Copy the old vertex data along with the generated normals to the
  695.     // new vertex data buffer.
  696.     void* newVertexData = new char[newDesc.stride * nFaces * 3];
  697.     for (f = 0; f < nFaces; f++)
  698.     {
  699.         Face& face = faces[f];
  700.         for (uint32 j = 0; j < 3; j++)
  701.         {
  702.             char* newVertex = reinterpret_cast<char*>(newVertexData) +
  703.                 (f * 3 + j) * newDesc.stride;
  704.             copyVertex(newVertex, newDesc,
  705.                        vertexData, desc,
  706.                        face.i[j],
  707.                        fromOffsets);
  708.             memcpy(newVertex + normalOffset, &vertexNormals[f * 3 + j],
  709.                    Mesh::getVertexAttributeSize(Mesh::Float3));
  710.         }
  711.     }
  712.     // Create the Celestia mesh
  713.     Mesh* newMesh = new Mesh();
  714.     newMesh->setVertexDescription(newDesc);
  715.     newMesh->setVertices(nFaces * 3, newVertexData);
  716.     // Create a trivial index list
  717.     uint32* indices = new uint32[nFaces * 3];
  718.     for (i = 0; i < nFaces * 3; i++)
  719.         indices[i] = i;
  720.     // TODO: This assumes that the mesh uses only one material.  Normal
  721.     // generation should really be done one primitive group at a time.
  722.     uint32 materialIndex = mesh.getGroup(0)->materialIndex;
  723.     newMesh->addGroup(Mesh::TriList, materialIndex, nFaces * 3, indices);
  724.     // Clean up
  725.     delete[] faceCounts;
  726.     for (i = 0; i < nVertices; i++)
  727.     {
  728.         if (vertexFaces[i] != NULL)
  729.             delete[] vertexFaces[i];
  730.     }
  731.     delete[] vertexFaces;
  732.     return newMesh;
  733. }
  734. Mesh*
  735. generateTangents(Mesh& mesh,
  736.                  bool weld)
  737. {
  738.     uint32 nVertices = mesh.getVertexCount();
  739.     // In order to generate tangents, we require positions, normals, and
  740.     // 2D texture coordinates in the vertex description.
  741.     const Mesh::VertexDescription& desc = mesh.getVertexDescription();
  742.     if (desc.getAttribute(Mesh::Position).format != Mesh::Float3)
  743.     {
  744.         cerr << "Vertex position must be a float3n";
  745.         return NULL;
  746.     }
  747.     if (desc.getAttribute(Mesh::Normal).format != Mesh::Float3)
  748.     {
  749.         cerr << "float3 format vertex normal requiredn";
  750.         return NULL;
  751.     }
  752.     if (desc.getAttribute(Mesh::Texture0).format == Mesh::InvalidFormat)
  753.     {
  754.         cerr << "Texture coordinates must be present in mesh to generate tangentsn";
  755.         return NULL;
  756.     }
  757.     if (desc.getAttribute(Mesh::Texture0).format != Mesh::Float2)
  758.     {
  759.         cerr << "Texture coordinate must be a float2n";
  760.         return NULL;
  761.     }
  762.     // Count the number of faces in the mesh.
  763.     // (All geometry should already converted to triangle lists)
  764.     uint32 i;
  765.     uint32 nFaces = 0;
  766.     for (i = 0; mesh.getGroup(i) != NULL; i++)
  767.     {
  768.         const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
  769.         if (group->prim == Mesh::TriList)
  770.         {
  771.             assert(group->nIndices % 3 == 0);
  772.             nFaces += group->nIndices / 3;
  773.         }
  774.         else
  775.         {
  776.             cerr << "Mesh should contain just triangle listsn";
  777.             return NULL;
  778.         }
  779.     }
  780.     
  781.     // Build the array of faces; this may require decomposing triangle strips
  782.     // and fans into triangle lists.
  783.     vector<Face> faces(nFaces);
  784.     uint32 f = 0;
  785.     for (i = 0; mesh.getGroup(i) != NULL; i++)
  786.     {
  787.         const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
  788.         
  789.         switch (group->prim)
  790.         {
  791.         case Mesh::TriList:
  792.             {
  793.                 for (uint32 j = 0; j < group->nIndices / 3; j++)
  794.                 {
  795.                     assert(f < nFaces);
  796.                     faces[f].i[0] = group->indices[j * 3];
  797.                     faces[f].i[1] = group->indices[j * 3 + 1];
  798.                     faces[f].i[2] = group->indices[j * 3 + 2];
  799.                     f++;
  800.                 }
  801.             }
  802.             break;
  803.         }
  804.     }
  805.     uint32 posOffset = desc.getAttribute(Mesh::Position).offset;
  806.     uint32 normOffset = desc.getAttribute(Mesh::Normal).offset;
  807.     uint32 texCoordOffset = desc.getAttribute(Mesh::Texture0).offset;
  808.     const void* vertexData = mesh.getVertexData();
  809.     
  810.     // Compute tangents for faces
  811.     for (f = 0; f < nFaces; f++)
  812.     {
  813.         Face& face = faces[f];
  814.         Point3f p0 = getVertex(vertexData, posOffset, desc.stride, face.i[0]);
  815.         Point3f p1 = getVertex(vertexData, posOffset, desc.stride, face.i[1]);
  816.         Point3f p2 = getVertex(vertexData, posOffset, desc.stride, face.i[2]);
  817.         Point2f tc0 = getTexCoord(vertexData, texCoordOffset, desc.stride, face.i[0]);
  818.         Point2f tc1 = getTexCoord(vertexData, texCoordOffset, desc.stride, face.i[1]);
  819.         Point2f tc2 = getTexCoord(vertexData, texCoordOffset, desc.stride, face.i[2]);
  820.         float s1 = tc1.x - tc0.x;
  821.         float s2 = tc2.x - tc0.x;
  822.         float t1 = tc1.y - tc0.y;
  823.         float t2 = tc2.y - tc0.y;
  824.         float a = s1 * t2 - s2 * t1;
  825.         if (a != 0.0f)
  826.             face.normal = (t2 * (p1 - p0) - t1 * (p2 - p0)) * (1.0f / a);
  827.         else
  828.             face.normal = Vec3f(0.0f, 0.0f, 0.0f);
  829.     }
  830.     // For each vertex, create a list of faces that contain it
  831.     uint32* faceCounts = new uint32[nVertices];
  832.     uint32** vertexFaces = new uint32*[nVertices];
  833.     // Initialize the lists
  834.     for (i = 0; i < nVertices; i++)
  835.     {
  836.         faceCounts[i] = 0;
  837.         vertexFaces[i] = NULL;
  838.     }
  839.     // If we're welding vertices before generating normals, find identical
  840.     // points and merge them.  Otherwise, the point indices will be the same
  841.     // as the attribute indices.
  842.     if (weld)
  843.     {
  844.         joinVertices(faces, vertexData, desc, PointTexCoordComparator(0, 0, true));
  845.     }
  846.     else
  847.     {
  848.         for (f = 0; f < nFaces; f++)
  849.         {
  850.             faces[f].vi[0] = faces[f].i[0];
  851.             faces[f].vi[1] = faces[f].i[1];
  852.             faces[f].vi[2] = faces[f].i[2];
  853.         }
  854.     }
  855.     // Count the number of faces in which each vertex appears
  856.     for (f = 0; f < nFaces; f++)
  857.     {
  858.         Face& face = faces[f];
  859.         faceCounts[face.vi[0]]++;
  860.         faceCounts[face.vi[1]]++;
  861.         faceCounts[face.vi[2]]++;
  862.     }
  863.     // Allocate space for the per-vertex face lists
  864.     for (i = 0; i < nVertices; i++)
  865.     {
  866.         if (faceCounts[i] > 0)
  867.         {
  868.             vertexFaces[i] = new uint32[faceCounts[i] + 1];
  869.             vertexFaces[i][0] = faceCounts[i];
  870.         }
  871.     }
  872.     // Fill in the vertex/face lists
  873.     for (f = 0; f < nFaces; f++)
  874.     {
  875.         Face& face = faces[f];
  876.         vertexFaces[face.vi[0]][faceCounts[face.vi[0]]--] = f;
  877.         vertexFaces[face.vi[1]][faceCounts[face.vi[1]]--] = f;
  878.         vertexFaces[face.vi[2]][faceCounts[face.vi[2]]--] = f;
  879.     }
  880.     // Compute the vertex tangents by averaging
  881.     vector<Vec3f> vertexTangents(nFaces * 3);
  882.     for (f = 0; f < nFaces; f++)
  883.     {
  884.         Face& face = faces[f];
  885.         for (uint32 j = 0; j < 3; j++)
  886.         {
  887.             vertexTangents[f * 3 + j] =
  888.                 averageFaceVectors(faces, f,
  889.                                    &vertexFaces[face.vi[j]][1],
  890.                                    vertexFaces[face.vi[j]][0],
  891.                                    0.0f);
  892.         }
  893.     }
  894.     // Create the new vertex description
  895.     Mesh::VertexDescription newDesc(desc);
  896.     augmentVertexDescription(newDesc, Mesh::Tangent, Mesh::Float3);
  897.     // We need to convert the copy the old vertex attributes to the new
  898.     // mesh.  In order to do this, we need the old offset of each attribute
  899.     // in the new vertex description.  The fromOffsets array will contain
  900.     // this mapping.
  901.     uint32 tangentOffset = 0;
  902.     uint32 fromOffsets[16];
  903.     for (i = 0; i < newDesc.nAttributes; i++)
  904.     {
  905.         fromOffsets[i] = ~0;
  906.         if (newDesc.attributes[i].semantic == Mesh::Tangent)
  907.         {
  908.             tangentOffset = newDesc.attributes[i].offset;
  909.         }
  910.         else
  911.         {
  912.             for (uint32 j = 0; j < desc.nAttributes; j++)
  913.             {
  914.                 if (desc.attributes[j].semantic == newDesc.attributes[i].semantic)
  915.                 {
  916.                     assert(desc.attributes[j].format == newDesc.attributes[i].format);
  917.                     fromOffsets[i] = desc.attributes[j].offset;
  918.                     break;
  919.                 }
  920.             }
  921.         }
  922.     }
  923.     // Copy the old vertex data along with the generated tangents to the
  924.     // new vertex data buffer.
  925.     void* newVertexData = new char[newDesc.stride * nFaces * 3];
  926.     for (f = 0; f < nFaces; f++)
  927.     {
  928.         Face& face = faces[f];
  929.         for (uint32 j = 0; j < 3; j++)
  930.         {
  931.             char* newVertex = reinterpret_cast<char*>(newVertexData) +
  932.                 (f * 3 + j) * newDesc.stride;
  933.             copyVertex(newVertex, newDesc,
  934.                        vertexData, desc,
  935.                        face.i[j],
  936.                        fromOffsets);
  937.             memcpy(newVertex + tangentOffset, &vertexTangents[f * 3 + j],
  938.                    Mesh::getVertexAttributeSize(Mesh::Float3));
  939.         }
  940.     }
  941.     // Create the Celestia mesh
  942.     Mesh* newMesh = new Mesh();
  943.     newMesh->setVertexDescription(newDesc);
  944.     newMesh->setVertices(nFaces * 3, newVertexData);
  945.     // Create a trivial index list
  946.     uint32* indices = new uint32[nFaces * 3];
  947.     for (i = 0; i < nFaces * 3; i++)
  948.         indices[i] = i;
  949.     // TODO: This assumes that the mesh uses only one material.  Tangent
  950.     // generation should really be done one primitive group at a time.
  951.     uint32 materialIndex = mesh.getGroup(0)->materialIndex;
  952.     newMesh->addGroup(Mesh::TriList, materialIndex, nFaces * 3, indices);
  953.     // Clean up
  954.     delete[] faceCounts;
  955.     for (i = 0; i < nVertices; i++)
  956.     {
  957.         if (vertexFaces[i] != NULL)
  958.             delete[] vertexFaces[i];
  959.     }
  960.     delete[] vertexFaces;
  961.     return newMesh;
  962. }
  963. void
  964. addGroupWithOffset(Mesh& mesh,
  965.                    const Mesh::PrimitiveGroup& group,
  966.                    uint32 offset)
  967. {
  968.     if (group.nIndices == 0)
  969.         return;
  970.     uint32* newIndices = new uint32[group.nIndices];
  971.     for (uint32 i = 0; i < group.nIndices; i++)
  972.         newIndices[i] = group.indices[i] + offset;
  973.     mesh.addGroup(group.prim, group.materialIndex,
  974.                   group.nIndices, newIndices);
  975. }
  976. // Merge all meshes that share the same vertex description
  977. Model*
  978. mergeModelMeshes(const Model& model)
  979. {
  980.     vector<Mesh*> meshes;
  981.     uint32 i;
  982.     for (i = 0; model.getMesh(i) != NULL; i++)
  983.     {
  984.         meshes.push_back(model.getMesh(i));
  985.     }
  986.     // Sort the meshes by vertex description
  987.     sort(meshes.begin(), meshes.end(), MeshVertexDescComparator());
  988.     Model* newModel = new Model();
  989.     // Copy materials into the new model
  990.     for (i = 0; model.getMaterial(i) != NULL; i++)
  991.     {
  992.         newModel->addMaterial(model.getMaterial(i));
  993.     }
  994.     uint32 meshIndex = 0;
  995.     while (meshIndex < meshes.size())
  996.     {
  997.         const Mesh::VertexDescription& desc =
  998.             meshes[meshIndex]->getVertexDescription();
  999.         
  1000.         // Count the number of matching meshes
  1001.         uint32 nMatchingMeshes;
  1002.         for (nMatchingMeshes = 1;
  1003.              meshIndex + nMatchingMeshes < meshes.size();
  1004.              nMatchingMeshes++)
  1005.         {
  1006.             if (!(meshes[meshIndex + nMatchingMeshes]->getVertexDescription() == desc))
  1007.             {
  1008.                 break;
  1009.             }
  1010.         }
  1011.         // Count the number of vertices in all matching meshes
  1012.         uint32 totalVertices = 0;
  1013.         uint32 j;
  1014.         for (j = meshIndex; j < meshIndex + nMatchingMeshes; j++)
  1015.         {
  1016.             totalVertices += meshes[j]->getVertexCount();
  1017.         }
  1018.         char* vertexData = new char[totalVertices * desc.stride];
  1019.         // Create the new empty mesh
  1020.         Mesh* mergedMesh = new Mesh();
  1021.         mergedMesh->setVertexDescription(desc);
  1022.         mergedMesh->setVertices(totalVertices, vertexData);
  1023.         
  1024.         // Copy the vertex data and reindex and add primitive groups
  1025.         uint32 vertexCount = 0;
  1026.         for (j = meshIndex; j < meshIndex + nMatchingMeshes; j++)
  1027.         {
  1028.             const Mesh* mesh = meshes[j];
  1029.             memcpy(vertexData + vertexCount * desc.stride,
  1030.                    mesh->getVertexData(),
  1031.                    mesh->getVertexCount() * desc.stride);
  1032.             for (uint32 k = 0; mesh->getGroup(k) != NULL; k++)
  1033.             {
  1034.                 addGroupWithOffset(*mergedMesh, *mesh->getGroup(k),
  1035.                                    vertexCount);
  1036.             }
  1037.             vertexCount += mesh->getVertexCount();
  1038.         }
  1039.         assert(vertexCount == totalVertices);
  1040.         newModel->addMesh(mergedMesh);
  1041.         meshIndex += nMatchingMeshes;
  1042.     }
  1043.     return newModel;
  1044. }
  1045. #ifdef TRISTRIP
  1046. bool
  1047. convertToStrips(Mesh& mesh)
  1048. {
  1049.     vector<Mesh::PrimitiveGroup*> groups;
  1050.     // NvTriStrip library can only handle 16-bit indices
  1051.     if (mesh.getVertexCount() >= 0x10000)
  1052.     {
  1053.         return true;
  1054.     }
  1055.     // Verify that the mesh contains just tri strips
  1056.     uint32 i;
  1057.     for (i = 0; mesh.getGroup(i) != NULL; i++)
  1058.     {
  1059.         if (mesh.getGroup(i)->prim != Mesh::TriList)
  1060.             return true;
  1061.     }
  1062.     // Convert the existing groups to triangle strips
  1063.     for (i = 0; mesh.getGroup(i) != NULL; i++)
  1064.     {
  1065.         const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
  1066.         // Convert the vertex indices to shorts for the TriStrip library
  1067.         unsigned short* indices = new unsigned short[group->nIndices];
  1068.         uint32 j;
  1069.         for (j = 0; j < group->nIndices; j++)
  1070.         {
  1071.             indices[j] = (unsigned short) group->indices[j];
  1072.         }
  1073.         PrimitiveGroup* strips = NULL;
  1074.         unsigned short nGroups;
  1075.         bool r = GenerateStrips(indices,
  1076.                                 group->nIndices,
  1077.                                 &strips,
  1078.                                 &nGroups,
  1079.                                 false);
  1080.         if (!r || strips == NULL)
  1081.         {
  1082.             cerr << "Generate tri strips failedn";
  1083.             return false;
  1084.         }
  1085.         // Call the tristrip library to convert the lists to strips.  Then,
  1086.         // convert from the NvTriStrip's primitive group structure to the
  1087.         // CMOD one and add it to the collection that will be added once
  1088.         // the mesh's original primitive groups are cleared.
  1089.         for (j = 0; j < nGroups; j++)
  1090.         {
  1091.             Mesh::PrimitiveGroupType prim = Mesh::InvalidPrimitiveGroupType;
  1092.             switch (strips[j].type)
  1093.             {
  1094.             case PT_LIST:
  1095.                 prim = Mesh::TriList;
  1096.                 break;
  1097.             case PT_STRIP:
  1098.                 prim = Mesh::TriStrip;
  1099.                 break;
  1100.             case PT_FAN:
  1101.                 prim = Mesh::TriFan;
  1102.                 break;
  1103.             }
  1104.             if (prim != Mesh::InvalidPrimitiveGroupType &&
  1105.                 strips[j].numIndices != 0)
  1106.             {
  1107.                 Mesh::PrimitiveGroup* newGroup = new Mesh::PrimitiveGroup();
  1108.                 newGroup->prim = prim;
  1109.                 newGroup->materialIndex = group->materialIndex;
  1110.                 newGroup->nIndices = strips[j].numIndices;
  1111.                 newGroup->indices = new uint32[newGroup->nIndices];
  1112.                 for (uint32 k = 0; k < newGroup->nIndices; k++)
  1113.                     newGroup->indices[k] = strips[j].indices[k];
  1114.                 
  1115.                 groups.push_back(newGroup);
  1116.             }
  1117.         }
  1118.         delete[] strips;
  1119.     }
  1120.     mesh.clearGroups();
  1121.     // Add the stripified groups to the mesh
  1122.     for (vector<Mesh::PrimitiveGroup*>::const_iterator iter = groups.begin();
  1123.          iter != groups.end(); iter++)
  1124.     {
  1125.         mesh.addGroup(*iter);
  1126.     }
  1127.     return true;
  1128. }
  1129. #endif
  1130. bool parseCommandLine(int argc, char* argv[])
  1131. {
  1132.     int i = 1;
  1133.     int fileCount = 0;
  1134.     while (i < argc)
  1135.     {
  1136.         if (argv[i][0] == '-')
  1137.         {
  1138.             if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--binary"))
  1139.             {
  1140.                 outputBinary = true;
  1141.             }
  1142.             else if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--ascii"))
  1143.             {
  1144.                 outputBinary = false;
  1145.             }
  1146.             else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uniquify"))
  1147.             {
  1148.                 uniquify = true;
  1149.             }
  1150.             else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--normals"))
  1151.             {
  1152.                 genNormals = true;
  1153.             }
  1154.             else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "--tangents"))
  1155.             {
  1156.                 genTangents = true;
  1157.             }
  1158.             else if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--weld"))
  1159.             {
  1160.                 weldVertices = true;
  1161.             }
  1162.             else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--merge"))
  1163.             {
  1164.                 mergeMeshes = true;
  1165.             }
  1166.             else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--optimize"))
  1167.             {
  1168.                 stripify = true;
  1169.             }
  1170.             else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--smooth"))
  1171.             {
  1172.                 if (i == argc - 1)
  1173.                 {
  1174.                     return false;
  1175.                 }
  1176.                 else
  1177.                 {
  1178.                     if (sscanf(argv[i + 1], " %f", &smoothAngle) != 1)
  1179.                         return false;
  1180.                     i++;
  1181.                 }
  1182.             }
  1183.             else
  1184.             {
  1185.                 return false;
  1186.             }
  1187.             i++;
  1188.         }
  1189.         else
  1190.         {
  1191.             if (fileCount == 0)
  1192.             {
  1193.                 // input filename first
  1194.                 inputFilename = string(argv[i]);
  1195.                 fileCount++;
  1196.             }
  1197.             else if (fileCount == 1)
  1198.             {
  1199.                 // output filename second
  1200.                 outputFilename = string(argv[i]);
  1201.                 fileCount++;
  1202.             }
  1203.             else
  1204.             {
  1205.                 // more than two filenames on the command line is an error
  1206.                 return false;
  1207.             }
  1208.             i++;
  1209.         }
  1210.     }
  1211.     return true;
  1212. }
  1213. int main(int argc, char* argv[])
  1214. {
  1215.     if (!parseCommandLine(argc, argv))
  1216.     {
  1217.         usage();
  1218.         return 1;
  1219.     }
  1220.     Model* model = NULL;
  1221.     if (!inputFilename.empty())
  1222.     {
  1223.         ifstream in(inputFilename.c_str(), ios::in | ios::binary);
  1224.         if (!in.good())
  1225.         {
  1226.             cerr << "Error opening " << inputFilename << "n";
  1227.             return 1;
  1228.         }
  1229.         model = LoadModel(in);
  1230.     }
  1231.     else
  1232.     {
  1233.         model = LoadModel(cin);
  1234.     }
  1235.     
  1236.     if (model == NULL)
  1237.         return 1;
  1238.     
  1239.     if (genNormals || genTangents)
  1240.     {
  1241.         Model* newModel = new Model();
  1242.         uint32 i;
  1243.         // Copy materials
  1244.         for (i = 0; model->getMaterial(i) != NULL; i++)
  1245.         {
  1246.             newModel->addMaterial(model->getMaterial(i));
  1247.         }
  1248.         // Generate normals and/or tangents for each model in the mesh
  1249.         for (i = 0; model->getMesh(i) != NULL; i++)
  1250.         {
  1251.             Mesh* mesh = model->getMesh(i);
  1252.             Mesh* newMesh = NULL;
  1253.             if (genNormals)
  1254.             {
  1255.                 newMesh = generateNormals(*mesh,
  1256.                                           degToRad(smoothAngle),
  1257.                                           weldVertices);
  1258.                 if (newMesh == NULL)
  1259.                 {
  1260.                     cerr << "Error generating normals!n";
  1261.                     return 1;
  1262.                 }
  1263.                 // TODO: clean up old mesh
  1264.                 mesh = newMesh;
  1265.             }
  1266.             if (genTangents)
  1267.             {
  1268.                 newMesh = generateTangents(*mesh, weldVertices);
  1269.                 if (newMesh == NULL)
  1270.                 {
  1271.                     cerr << "Error generating tangents!n";
  1272.                     return 1;
  1273.                 }
  1274.                 // TODO: clean up old mesh
  1275.                 mesh = newMesh;
  1276.             }
  1277.             newModel->addMesh(mesh);
  1278.         }
  1279.         // delete model;
  1280.         model = newModel;
  1281.     }
  1282.     if (mergeMeshes)
  1283.     {
  1284.         model = mergeModelMeshes(*model);
  1285.     }
  1286.     if (uniquify)
  1287.     {
  1288.         for (uint32 i = 0; model->getMesh(i) != NULL; i++)
  1289.         {
  1290.             Mesh* mesh = model->getMesh(i);
  1291.             uniquifyVertices(*mesh);
  1292.         }
  1293.     }
  1294. #ifdef TRISTRIP
  1295.     if (stripify)
  1296.     {
  1297.         SetCacheSize(vertexCacheSize);
  1298.         for (uint32 i = 0; model->getMesh(i) != NULL; i++)
  1299.         {
  1300.             Mesh* mesh = model->getMesh(i);
  1301.             convertToStrips(*mesh);
  1302.         }
  1303.     }
  1304. #endif
  1305.     if (outputFilename.empty())
  1306.     {
  1307.         if (outputBinary)
  1308.             SaveModelBinary(model, cout);
  1309.         else
  1310.             SaveModelAscii(model, cout);
  1311.     }
  1312.     else
  1313.     {
  1314.         ofstream out(outputFilename.c_str(),
  1315.                      outputBinary ? (ios::binary|ios::out) : ios::out);
  1316.         if (!out.good())
  1317.         {
  1318.             cerr << "Error opening output file " << outputFilename << "n";
  1319.             return 1;
  1320.         }
  1321.         if (outputBinary)
  1322.             SaveModelBinary(model, out);
  1323.         else
  1324.             SaveModelAscii(model, out);
  1325.     }
  1326.     return 0;
  1327. }