00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <celengine/modelfile.h>
00013 #include <celengine/tokenizer.h>
00014 #include <celengine/texmanager.h>
00015 #include <cel3ds/3dsread.h>
00016 #include <celmath/mathlib.h>
00017 #include <cstring>
00018 #include <cassert>
00019 #include <cmath>
00020 #include <cstdio>
00021 #include <algorithm>
00022 #include <vector>
00023 #ifdef TRISTRIP
00024 #include <NvTriStrip.h>
00025 #endif
00026
00027 using namespace std;
00028
00029 string inputFilename;
00030 string outputFilename;
00031 bool outputBinary = false;
00032 bool uniquify = false;
00033 bool genNormals = false;
00034 bool genTangents = false;
00035 bool weldVertices = false;
00036 bool mergeMeshes = false;
00037 bool stripify = false;
00038 unsigned int vertexCacheSize = 16;
00039 float smoothAngle = 60.0f;
00040
00041
00042 void usage()
00043 {
00044 cerr << "Usage: cmodfix [options] [input cmod file [output cmod file]]\n";
00045 cerr << " --binary (or -b) : output a binary .cmod file\n";
00046 cerr << " --ascii (or -a) : output an ASCII .cmod file\n";
00047 cerr << " --uniquify (or -u) : eliminate duplicate vertices\n";
00048 cerr << " --tangents (or -t) : generate tangents\n";
00049 cerr << " --normals (or -n) : generate normals\n";
00050 cerr << " --smooth (or -s) <angle> : smoothing angle for normal generation\n";
00051 cerr << " --weld (or -w) : join identical vertices before normal generation\n";
00052 cerr << " --merge (or -m) : merge submeshes to improve rendering performance\n";
00053 #ifdef TRISTRIP
00054 cerr << " --optimize (or -o) : optimize by converting triangle lists to strips\n";
00055 #endif
00056 }
00057
00058
00059 struct Vertex
00060 {
00061 Vertex() :
00062 index(0), attributes(NULL) {};
00063
00064 Vertex(uint32 _index, const void* _attributes) :
00065 index(_index), attributes(_attributes) {};
00066
00067 uint32 index;
00068 const void* attributes;
00069 };
00070
00071
00072 struct Face
00073 {
00074 Vec3f normal;
00075 uint32 i[3];
00076 uint32 vi[3];
00077 };
00078
00079
00080 typedef public std::binary_function<const Vertex&, const Vertex&, bool> VertexComparator;
00081
00082
00083 class FullComparator : public VertexComparator
00084 {
00085 public:
00086 FullComparator(int _vertexSize) :
00087 vertexSize(_vertexSize)
00088 {
00089 }
00090
00091 bool operator()(const Vertex& a, const Vertex& b) const
00092 {
00093 const char* s0 = reinterpret_cast<const char*>(a.attributes);
00094 const char* s1 = reinterpret_cast<const char*>(b.attributes);
00095 for (int i = 0; i < vertexSize; i++)
00096 {
00097 if (s0[i] < s1[i])
00098 return true;
00099 else if (s0[i] > s1[i])
00100 return false;
00101 }
00102
00103 return false;
00104 }
00105
00106 private:
00107 int vertexSize;
00108 };
00109
00110
00111 class PointComparator : public VertexComparator
00112 {
00113 public:
00114 PointComparator()
00115 {
00116 }
00117
00118 bool operator()(const Vertex& a, const Vertex& b) const
00119 {
00120 const Point3f* p0 = reinterpret_cast<const Point3f*>(a.attributes);
00121 const Point3f* p1 = reinterpret_cast<const Point3f*>(b.attributes);
00122
00123 if (p0->x < p1->x)
00124 {
00125 return true;
00126 }
00127 else if (p0->x > p1->x)
00128 {
00129 return false;
00130 }
00131 else
00132 {
00133 if (p0->y < p1->y)
00134 return true;
00135 else if (p0->y > p1->y)
00136 return false;
00137 else
00138 return p0->z < p1->z;
00139 }
00140 }
00141
00142 private:
00143 int ignore;
00144 };
00145
00146
00147 class PointTexCoordComparator : public VertexComparator
00148 {
00149 public:
00150 PointTexCoordComparator(uint32 _posOffset,
00151 uint32 _texCoordOffset,
00152 bool _wrap) :
00153 posOffset(_posOffset),
00154 texCoordOffset(_texCoordOffset),
00155 wrap(_wrap)
00156 {
00157 }
00158
00159 bool operator()(const Vertex& a, const Vertex& b) const
00160 {
00161 const char* adata = reinterpret_cast<const char*>(a.attributes);
00162 const char* bdata = reinterpret_cast<const char*>(b.attributes);
00163 const Point3f* p0 = reinterpret_cast<const Point3f*>(adata + posOffset);
00164 const Point3f* p1 = reinterpret_cast<const Point3f*>(bdata + posOffset);
00165 const Point2f* tc0 = reinterpret_cast<const Point2f*>(adata + posOffset);
00166 const Point2f* tc1 = reinterpret_cast<const Point2f*>(bdata + posOffset);
00167 if (p0->x < p1->x)
00168 {
00169 return true;
00170 }
00171 else if (p0->x > p1->x)
00172 {
00173 return false;
00174 }
00175 else
00176 {
00177 if (p0->y < p1->y)
00178 {
00179 return true;
00180 }
00181 else if (p0->y > p1->y)
00182 {
00183 return false;
00184 }
00185 else
00186 {
00187 if (p0->z < p1->z)
00188 {
00189 return true;
00190 }
00191 else if (p0->z > p1->z)
00192 {
00193 return false;
00194 }
00195 else
00196 {
00197 if (tc0->x < tc1->x)
00198 return true;
00199 else if (tc0->x > tc1->x)
00200 return false;
00201 else
00202 return tc0->y < tc1->y;
00203 }
00204 }
00205 }
00206 }
00207
00208 private:
00209 uint32 posOffset;
00210 uint32 texCoordOffset;
00211 bool wrap;
00212 };
00213
00214
00215 bool equal(const Vertex& a, const Vertex& b, uint32 vertexSize)
00216 {
00217 const char* s0 = reinterpret_cast<const char*>(a.attributes);
00218 const char* s1 = reinterpret_cast<const char*>(b.attributes);
00219
00220 for (uint32 i = 0; i < vertexSize; i++)
00221 {
00222 if (s0[i] != s1[i])
00223 return false;
00224 }
00225
00226 return true;
00227 }
00228
00229
00230 bool equalPoint(const Vertex& a, const Vertex& b)
00231 {
00232 const Point3f* p0 = reinterpret_cast<const Point3f*>(a.attributes);
00233 const Point3f* p1 = reinterpret_cast<const Point3f*>(b.attributes);
00234
00235 return *p0 == *p1;
00236 }
00237
00238
00239 bool operator==(const Mesh::VertexAttribute& a,
00240 const Mesh::VertexAttribute& b)
00241 {
00242 return (a.semantic == b.semantic &&
00243 a.format == b.format &&
00244 a.offset == b.offset);
00245 }
00246
00247
00248 bool operator<(const Mesh::VertexAttribute& a,
00249 const Mesh::VertexAttribute& b)
00250 {
00251 if (a.semantic < b.semantic)
00252 {
00253 return true;
00254 }
00255 else if (b.semantic < a.semantic)
00256 {
00257 return false;
00258 }
00259 else
00260 {
00261 if (a.format < b.format)
00262 return true;
00263 else if (b.format < a.format)
00264 return false;
00265 else
00266 return a.offset < b.offset;
00267 }
00268 }
00269
00270
00271 bool operator==(const Mesh::VertexDescription& a,
00272 const Mesh::VertexDescription& b)
00273 {
00274 if (a.stride != b.stride || a.nAttributes != b.nAttributes)
00275 return false;
00276
00277 for (uint32 i = 0; i < a.nAttributes; i++)
00278 {
00279 if (!(a.attributes[i] == b.attributes[i]))
00280 return false;
00281 }
00282
00283 return true;
00284 }
00285
00286
00287 bool operator<(const Mesh::VertexDescription& a,
00288 const Mesh::VertexDescription& b)
00289 {
00290 if (a.stride < b.stride)
00291 return true;
00292 else if (b.stride < a.stride)
00293 return false;
00294
00295 if (a.nAttributes < b.nAttributes)
00296 return true;
00297 else if (b.nAttributes < b.nAttributes)
00298 return false;
00299
00300 for (uint32 i = 0; i < a.nAttributes; i++)
00301 {
00302 if (a.attributes[i] < b.attributes[i])
00303 return true;
00304 else if (b.attributes[i] < a.attributes[i])
00305 return false;
00306 }
00307
00308 return false;
00309 }
00310
00311
00312 class MeshVertexDescComparator :
00313 public std::binary_function<const Mesh*, const Mesh*, bool>
00314 {
00315 public:
00316 MeshVertexDescComparator()
00317 {
00318 }
00319
00320 bool operator()(const Mesh* a, const Mesh* b) const
00321 {
00322 return a->getVertexDescription() < b->getVertexDescription();
00323 }
00324
00325 private:
00326 int ignore;
00327 };
00328
00329
00330
00331 bool uniquifyVertices(Mesh& mesh)
00332 {
00333 uint32 nVertices = mesh.getVertexCount();
00334 const Mesh::VertexDescription& desc = mesh.getVertexDescription();
00335
00336 if (nVertices == 0)
00337 return false;
00338
00339 const char* vertexData = reinterpret_cast<const char*>(mesh.getVertexData());
00340 if (vertexData == NULL)
00341 return false;
00342
00343
00344 vector<Vertex> vertices(nVertices);
00345 uint32 i;
00346 for (i = 0; i < nVertices; i++)
00347 {
00348 vertices[i] = Vertex(i, vertexData + i * desc.stride);
00349 }
00350
00351
00352 sort(vertices.begin(), vertices.end(), FullComparator(desc.stride));
00353
00354
00355 uint32 uniqueVertexCount = 0;
00356 for (i = 0; i < nVertices; i++)
00357 {
00358 if (i == 0 || !equal(vertices[i - 1], vertices[i], desc.stride))
00359 uniqueVertexCount++;
00360 }
00361
00362
00363 if (uniqueVertexCount == nVertices)
00364 return true;
00365
00366
00367 vector<uint32> vertexMap(nVertices);
00368 char* newVertexData = new char[uniqueVertexCount * desc.stride];
00369 const char* oldVertexData = reinterpret_cast<const char*>(mesh.getVertexData());
00370 uint32 j = 0;
00371 for (i = 0; i < nVertices; i++)
00372 {
00373 if (i == 0 || !equal(vertices[i - 1], vertices[i], desc.stride))
00374 {
00375 if (i != 0)
00376 j++;
00377 assert(j < uniqueVertexCount);
00378 memcpy(newVertexData + j * desc.stride,
00379 oldVertexData + vertices[i].index * desc.stride,
00380 desc.stride);
00381 }
00382 vertexMap[vertices[i].index] = j;
00383 }
00384
00385
00386 delete mesh.getVertexData();
00387 mesh.setVertices(uniqueVertexCount, newVertexData);
00388
00389 mesh.remapIndices(vertexMap);
00390
00391 return true;
00392 }
00393
00394
00395 Point3f
00396 getVertex(const void* vertexData,
00397 int positionOffset,
00398 uint32 stride,
00399 uint32 index)
00400 {
00401 const float* fdata = reinterpret_cast<const float*>(reinterpret_cast<const char*>(vertexData) + stride * index + positionOffset);
00402
00403 return Point3f(fdata[0], fdata[1], fdata[2]);
00404 }
00405
00406
00407 Point2f
00408 getTexCoord(const void* vertexData,
00409 int texCoordOffset,
00410 uint32 stride,
00411 uint32 index)
00412 {
00413 const float* fdata = reinterpret_cast<const float*>(reinterpret_cast<const char*>(vertexData) + stride * index + texCoordOffset);
00414
00415 return Point2f(fdata[0], fdata[1]);
00416 }
00417
00418
00419 Vec3f
00420 averageFaceVectors(const vector<Face>& faces,
00421 uint32 thisFace,
00422 uint32* vertexFaces,
00423 uint32 vertexFaceCount,
00424 float cosSmoothingAngle)
00425 {
00426 const Face& face = faces[thisFace];
00427
00428 Vec3f v = Vec3f(0, 0, 0);
00429 for (uint32 i = 0; i < vertexFaceCount; i++)
00430 {
00431 uint32 f = vertexFaces[i];
00432 float cosAngle = face.normal * faces[f].normal;
00433 if (f == thisFace || cosAngle > cosSmoothingAngle)
00434 v += faces[f].normal;
00435 }
00436
00437 if (v * v == 0.0f)
00438 v = Vec3f(1.0f, 0.0f, 0.0f);
00439 else
00440 v.normalize();
00441
00442 return v;
00443 }
00444
00445
00446 void
00447 copyVertex(void* newVertexData,
00448 const Mesh::VertexDescription& newDesc,
00449 const void* oldVertexData,
00450 const Mesh::VertexDescription& oldDesc,
00451 uint32 oldIndex,
00452 const uint32 fromOffsets[])
00453 {
00454 const char* oldVertex = reinterpret_cast<const char*>(oldVertexData) +
00455 oldDesc.stride * oldIndex;
00456 char* newVertex = reinterpret_cast<char*>(newVertexData);
00457
00458 for (uint32 i = 0; i < newDesc.nAttributes; i++)
00459 {
00460 if (fromOffsets[i] != ~0)
00461 {
00462 memcpy(newVertex + newDesc.attributes[i].offset,
00463 oldVertex + fromOffsets[i],
00464 Mesh::getVertexAttributeSize(newDesc.attributes[i].format));
00465 }
00466 }
00467 }
00468
00469
00470 void
00471 augmentVertexDescription(Mesh::VertexDescription& desc,
00472 Mesh::VertexAttributeSemantic semantic,
00473 Mesh::VertexAttributeFormat format)
00474 {
00475 Mesh::VertexAttribute* attributes = new Mesh::VertexAttribute[desc.nAttributes + 1];
00476 uint32 stride = 0;
00477 uint32 nAttributes = 0;
00478 bool foundMatch = false;
00479
00480 for (uint32 i = 0; i < desc.nAttributes; i++)
00481 {
00482 if (semantic == desc.attributes[i].semantic &&
00483 format != desc.attributes[i].format)
00484 {
00485
00486
00487 }
00488 else
00489 {
00490 if (semantic == desc.attributes[i].semantic)
00491 foundMatch = true;
00492
00493 attributes[nAttributes] = desc.attributes[i];
00494 attributes[nAttributes].offset = stride;
00495 stride += Mesh::getVertexAttributeSize(desc.attributes[i].format);
00496 nAttributes++;
00497 }
00498 }
00499
00500 if (!foundMatch)
00501 {
00502 attributes[nAttributes++] = Mesh::VertexAttribute(semantic,
00503 format,
00504 stride);
00505 stride += Mesh::getVertexAttributeSize(format);
00506 }
00507
00508 delete[] desc.attributes;
00509 desc.attributes = attributes;
00510 desc.nAttributes = nAttributes;
00511 desc.stride = stride;
00512 }
00513
00514
00515 template <typename T> void
00516 joinVertices(vector<Face>& faces,
00517 const void* vertexData,
00518 const Mesh::VertexDescription& desc,
00519 T& comparator)
00520 {
00521
00522 if (faces.size() == 0)
00523 return;
00524
00525
00526 assert(desc.getAttribute(Mesh::Position).format == Mesh::Float3);
00527
00528 uint32 posOffset = desc.getAttribute(Mesh::Position).offset;
00529 const char* vertexPoints = reinterpret_cast<const char*>(vertexData) +
00530 posOffset;
00531 uint32 nVertices = faces.size() * 3;
00532
00533
00534 vector<Vertex> vertices(nVertices);
00535 uint32 f;
00536 for (f = 0; f < faces.size(); f++)
00537 {
00538 for (uint32 j = 0; j < 3; j++)
00539 {
00540 uint32 index = faces[f].i[j];
00541 vertices[f * 3 + j] = Vertex(index,
00542 vertexPoints + desc.stride * index);
00543
00544 }
00545 }
00546
00547
00548 sort(vertices.begin(), vertices.end(), comparator);
00549
00550
00551 vector<uint32> mergeMap(nVertices);
00552 uint32 lastUnique = 0;
00553 for (uint32 i = 0; i < nVertices; i++)
00554 {
00555 if (i == 0 ||
00556 comparator.operator()(vertices[i - 1], vertices[i]) ||
00557 comparator.operator()(vertices[i], vertices[i - 1]))
00558 {
00559 lastUnique = i;
00560 }
00561 mergeMap[vertices[i].index] = vertices[lastUnique].index;
00562 }
00563
00564
00565 for (f = 0; f < faces.size(); f++)
00566 {
00567 for (uint32 k= 0; k < 3; k++)
00568 faces[f].vi[k] = mergeMap[faces[f].i[k]];
00569 }
00570 }
00571
00572
00573 Mesh*
00574 generateNormals(Mesh& mesh,
00575 float smoothAngle,
00576 bool weld)
00577 {
00578 uint32 nVertices = mesh.getVertexCount();
00579 float cosSmoothAngle = (float) cos(smoothAngle);
00580
00581 const Mesh::VertexDescription& desc = mesh.getVertexDescription();
00582
00583 if (desc.getAttribute(Mesh::Position).format != Mesh::Float3)
00584 {
00585 cerr << "Vertex position must be a float3\n";
00586 return NULL;
00587 }
00588 uint32 posOffset = desc.getAttribute(Mesh::Position).offset;
00589
00590 uint32 nFaces = 0;
00591 uint32 i;
00592 for (i = 0; mesh.getGroup(i) != NULL; i++)
00593 {
00594 const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
00595
00596 switch (group->prim)
00597 {
00598 case Mesh::TriList:
00599 if (group->nIndices < 3 || group->nIndices % 3 != 0)
00600 {
00601 cerr << "Triangle list has invalid number of indices\n";
00602 return NULL;
00603 }
00604 nFaces += group->nIndices / 3;
00605 break;
00606
00607 case Mesh::TriStrip:
00608 case Mesh::TriFan:
00609 if (group->nIndices < 3)
00610 {
00611 cerr << "Error: tri strip or fan has less than three indices\n";
00612 return NULL;
00613 }
00614 nFaces += group->nIndices - 2;
00615 break;
00616
00617 default:
00618 cerr << "Cannot generate normals for non-triangle primitives\n";
00619 return NULL;
00620 }
00621 }
00622
00623
00624
00625 vector<Face> faces(nFaces);
00626
00627 uint32 f = 0;
00628 for (i = 0; mesh.getGroup(i) != NULL; i++)
00629 {
00630 const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
00631
00632 switch (group->prim)
00633 {
00634 case Mesh::TriList:
00635 {
00636 for (uint32 j = 0; j < group->nIndices / 3; j++)
00637 {
00638 assert(f < nFaces);
00639 faces[f].i[0] = group->indices[j * 3];
00640 faces[f].i[1] = group->indices[j * 3 + 1];
00641 faces[f].i[2] = group->indices[j * 3 + 2];
00642 f++;
00643 }
00644 }
00645 break;
00646
00647 case Mesh::TriStrip:
00648 {
00649 for (uint32 j = 2; j < group->nIndices; j++)
00650 {
00651 assert(f < nFaces);
00652 if (j % 2 == 0)
00653 {
00654 faces[f].i[0] = group->indices[j - 2];
00655 faces[f].i[1] = group->indices[j - 1];
00656 faces[f].i[2] = group->indices[j];
00657 }
00658 else
00659 {
00660 faces[f].i[0] = group->indices[j - 1];
00661 faces[f].i[1] = group->indices[j - 2];
00662 faces[f].i[2] = group->indices[j];
00663 }
00664 f++;
00665 }
00666 }
00667 break;
00668
00669 case Mesh::TriFan:
00670 {
00671 for (uint32 j = 2; j < group->nIndices; j++)
00672 {
00673 assert(f < nFaces);
00674 faces[f].i[0] = group->indices[0];
00675 faces[f].i[1] = group->indices[j - 1];
00676 faces[f].i[2] = group->indices[j];
00677 f++;
00678 }
00679 }
00680 break;
00681
00682 default:
00683 assert(0);
00684 break;
00685 }
00686 }
00687 assert(f == nFaces);
00688
00689 const void* vertexData = mesh.getVertexData();
00690
00691
00692 for (f = 0; f < nFaces; f++)
00693 {
00694 Face& face = faces[f];
00695 Point3f p0 = getVertex(vertexData, posOffset, desc.stride, face.i[0]);
00696 Point3f p1 = getVertex(vertexData, posOffset, desc.stride, face.i[1]);
00697 Point3f p2 = getVertex(vertexData, posOffset, desc.stride, face.i[2]);
00698 face.normal = cross(p1 - p0, p2 - p1);
00699 if (face.normal * face.normal > 0.0f)
00700 face.normal.normalize();
00701 }
00702
00703
00704 uint32* faceCounts = new uint32[nVertices];
00705 uint32** vertexFaces = new uint32*[nVertices];
00706
00707
00708 for (i = 0; i < nVertices; i++)
00709 {
00710 faceCounts[i] = 0;
00711 vertexFaces[i] = NULL;
00712 }
00713
00714
00715
00716
00717 if (weld)
00718 {
00719 joinVertices(faces, vertexData, desc, PointComparator());
00720 }
00721 else
00722 {
00723 for (f = 0; f < nFaces; f++)
00724 {
00725 faces[f].vi[0] = faces[f].i[0];
00726 faces[f].vi[1] = faces[f].i[1];
00727 faces[f].vi[2] = faces[f].i[2];
00728 }
00729 }
00730
00731
00732 for (f = 0; f < nFaces; f++)
00733 {
00734 Face& face = faces[f];
00735 faceCounts[face.vi[0]]++;
00736 faceCounts[face.vi[1]]++;
00737 faceCounts[face.vi[2]]++;
00738 }
00739
00740
00741 for (i = 0; i < nVertices; i++)
00742 {
00743 if (faceCounts[i] > 0)
00744 {
00745 vertexFaces[i] = new uint32[faceCounts[i] + 1];
00746 vertexFaces[i][0] = faceCounts[i];
00747 }
00748 }
00749
00750
00751 for (f = 0; f < nFaces; f++)
00752 {
00753 Face& face = faces[f];
00754 vertexFaces[face.vi[0]][faceCounts[face.vi[0]]--] = f;
00755 vertexFaces[face.vi[1]][faceCounts[face.vi[1]]--] = f;
00756 vertexFaces[face.vi[2]][faceCounts[face.vi[2]]--] = f;
00757 }
00758
00759
00760 vector<Vec3f> vertexNormals(nFaces * 3);
00761 for (f = 0; f < nFaces; f++)
00762 {
00763 Face& face = faces[f];
00764 for (uint32 j = 0; j < 3; j++)
00765 {
00766 vertexNormals[f * 3 + j] =
00767 averageFaceVectors(faces, f,
00768 &vertexFaces[face.vi[j]][1],
00769 vertexFaces[face.vi[j]][0],
00770 cosSmoothAngle);
00771 }
00772 }
00773
00774
00775
00776
00777 Mesh::VertexDescription newDesc(desc);
00778 augmentVertexDescription(newDesc, Mesh::Normal, Mesh::Float3);
00779
00780
00781
00782
00783
00784 uint32 normalOffset = 0;
00785 uint32 fromOffsets[16];
00786 for (i = 0; i < newDesc.nAttributes; i++)
00787 {
00788 fromOffsets[i] = ~0;
00789
00790 if (newDesc.attributes[i].semantic == Mesh::Normal)
00791 {
00792 normalOffset = newDesc.attributes[i].offset;
00793 }
00794 else
00795 {
00796 for (uint32 j = 0; j < desc.nAttributes; j++)
00797 {
00798 if (desc.attributes[j].semantic == newDesc.attributes[i].semantic)
00799 {
00800 assert(desc.attributes[j].format == newDesc.attributes[i].format);
00801 fromOffsets[i] = desc.attributes[j].offset;
00802 break;
00803 }
00804 }
00805 }
00806 }
00807
00808
00809
00810 void* newVertexData = new char[newDesc.stride * nFaces * 3];
00811 for (f = 0; f < nFaces; f++)
00812 {
00813 Face& face = faces[f];
00814
00815 for (uint32 j = 0; j < 3; j++)
00816 {
00817 char* newVertex = reinterpret_cast<char*>(newVertexData) +
00818 (f * 3 + j) * newDesc.stride;
00819 copyVertex(newVertex, newDesc,
00820 vertexData, desc,
00821 face.i[j],
00822 fromOffsets);
00823 memcpy(newVertex + normalOffset, &vertexNormals[f * 3 + j],
00824 Mesh::getVertexAttributeSize(Mesh::Float3));
00825 }
00826 }
00827
00828
00829 Mesh* newMesh = new Mesh();
00830 newMesh->setVertexDescription(newDesc);
00831 newMesh->setVertices(nFaces * 3, newVertexData);
00832
00833
00834 uint32* indices = new uint32[nFaces * 3];
00835 for (i = 0; i < nFaces * 3; i++)
00836 indices[i] = i;
00837
00838
00839
00840 uint32 materialIndex = mesh.getGroup(0)->materialIndex;
00841 newMesh->addGroup(Mesh::TriList, materialIndex, nFaces * 3, indices);
00842
00843
00844 delete[] faceCounts;
00845 for (i = 0; i < nVertices; i++)
00846 {
00847 if (vertexFaces[i] != NULL)
00848 delete[] vertexFaces[i];
00849 }
00850 delete[] vertexFaces;
00851
00852 return newMesh;
00853 }
00854
00855
00856 Mesh*
00857 generateTangents(Mesh& mesh,
00858 bool weld)
00859 {
00860 uint32 nVertices = mesh.getVertexCount();
00861
00862
00863
00864 const Mesh::VertexDescription& desc = mesh.getVertexDescription();
00865 if (desc.getAttribute(Mesh::Position).format != Mesh::Float3)
00866 {
00867 cerr << "Vertex position must be a float3\n";
00868 return NULL;
00869 }
00870
00871 if (desc.getAttribute(Mesh::Normal).format != Mesh::Float3)
00872 {
00873 cerr << "float3 format vertex normal required\n";
00874 return NULL;
00875 }
00876
00877 if (desc.getAttribute(Mesh::Texture0).format == Mesh::InvalidFormat)
00878 {
00879 cerr << "Texture coordinates must be present in mesh to generate tangents\n";
00880 return NULL;
00881 }
00882
00883 if (desc.getAttribute(Mesh::Texture0).format != Mesh::Float2)
00884 {
00885 cerr << "Texture coordinate must be a float2\n";
00886 return NULL;
00887 }
00888
00889
00890
00891 uint32 i;
00892 uint32 nFaces = 0;
00893 for (i = 0; mesh.getGroup(i) != NULL; i++)
00894 {
00895 const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
00896 if (group->prim == Mesh::TriList)
00897 {
00898 assert(group->nIndices % 3 == 0);
00899 nFaces += group->nIndices / 3;
00900 }
00901 else
00902 {
00903 cerr << "Mesh should contain just triangle lists\n";
00904 return NULL;
00905 }
00906 }
00907
00908
00909
00910 vector<Face> faces(nFaces);
00911
00912 uint32 f = 0;
00913 for (i = 0; mesh.getGroup(i) != NULL; i++)
00914 {
00915 const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
00916
00917 switch (group->prim)
00918 {
00919 case Mesh::TriList:
00920 {
00921 for (uint32 j = 0; j < group->nIndices / 3; j++)
00922 {
00923 assert(f < nFaces);
00924 faces[f].i[0] = group->indices[j * 3];
00925 faces[f].i[1] = group->indices[j * 3 + 1];
00926 faces[f].i[2] = group->indices[j * 3 + 2];
00927 f++;
00928 }
00929 }
00930 break;
00931 }
00932 }
00933
00934 uint32 posOffset = desc.getAttribute(Mesh::Position).offset;
00935 uint32 normOffset = desc.getAttribute(Mesh::Normal).offset;
00936 uint32 texCoordOffset = desc.getAttribute(Mesh::Texture0).offset;
00937
00938 const void* vertexData = mesh.getVertexData();
00939
00940
00941 for (f = 0; f < nFaces; f++)
00942 {
00943 Face& face = faces[f];
00944 Point3f p0 = getVertex(vertexData, posOffset, desc.stride, face.i[0]);
00945 Point3f p1 = getVertex(vertexData, posOffset, desc.stride, face.i[1]);
00946 Point3f p2 = getVertex(vertexData, posOffset, desc.stride, face.i[2]);
00947 Point2f tc0 = getTexCoord(vertexData, texCoordOffset, desc.stride, face.i[0]);
00948 Point2f tc1 = getTexCoord(vertexData, texCoordOffset, desc.stride, face.i[1]);
00949 Point2f tc2 = getTexCoord(vertexData, texCoordOffset, desc.stride, face.i[2]);
00950 float s1 = tc1.x - tc0.x;
00951 float s2 = tc2.x - tc0.x;
00952 float t1 = tc1.y - tc0.y;
00953 float t2 = tc2.y - tc0.y;
00954 float a = s1 * t2 - s2 * t1;
00955 if (a != 0.0f)
00956 face.normal = (t2 * (p1 - p0) - t1 * (p2 - p0)) * (1.0f / a);
00957 else
00958 face.normal = Vec3f(0.0f, 0.0f, 0.0f);
00959 }
00960
00961
00962 uint32* faceCounts = new uint32[nVertices];
00963 uint32** vertexFaces = new uint32*[nVertices];
00964
00965
00966 for (i = 0; i < nVertices; i++)
00967 {
00968 faceCounts[i] = 0;
00969 vertexFaces[i] = NULL;
00970 }
00971
00972
00973
00974
00975 if (weld)
00976 {
00977 joinVertices(faces, vertexData, desc, PointTexCoordComparator(0, 0, true));
00978 }
00979 else
00980 {
00981 for (f = 0; f < nFaces; f++)
00982 {
00983 faces[f].vi[0] = faces[f].i[0];
00984 faces[f].vi[1] = faces[f].i[1];
00985 faces[f].vi[2] = faces[f].i[2];
00986 }
00987 }
00988
00989
00990 for (f = 0; f < nFaces; f++)
00991 {
00992 Face& face = faces[f];
00993 faceCounts[face.vi[0]]++;
00994 faceCounts[face.vi[1]]++;
00995 faceCounts[face.vi[2]]++;
00996 }
00997
00998
00999 for (i = 0; i < nVertices; i++)
01000 {
01001 if (faceCounts[i] > 0)
01002 {
01003 vertexFaces[i] = new uint32[faceCounts[i] + 1];
01004 vertexFaces[i][0] = faceCounts[i];
01005 }
01006 }
01007
01008
01009 for (f = 0; f < nFaces; f++)
01010 {
01011 Face& face = faces[f];
01012 vertexFaces[face.vi[0]][faceCounts[face.vi[0]]--] = f;
01013 vertexFaces[face.vi[1]][faceCounts[face.vi[1]]--] = f;
01014 vertexFaces[face.vi[2]][faceCounts[face.vi[2]]--] = f;
01015 }
01016
01017
01018 vector<Vec3f> vertexTangents(nFaces * 3);
01019 for (f = 0; f < nFaces; f++)
01020 {
01021 Face& face = faces[f];
01022 for (uint32 j = 0; j < 3; j++)
01023 {
01024 vertexTangents[f * 3 + j] =
01025 averageFaceVectors(faces, f,
01026 &vertexFaces[face.vi[j]][1],
01027 vertexFaces[face.vi[j]][0],
01028 0.0f);
01029 }
01030 }
01031
01032
01033 Mesh::VertexDescription newDesc(desc);
01034 augmentVertexDescription(newDesc, Mesh::Tangent, Mesh::Float3);
01035
01036
01037
01038
01039
01040 uint32 tangentOffset = 0;
01041 uint32 fromOffsets[16];
01042 for (i = 0; i < newDesc.nAttributes; i++)
01043 {
01044 fromOffsets[i] = ~0;
01045
01046 if (newDesc.attributes[i].semantic == Mesh::Tangent)
01047 {
01048 tangentOffset = newDesc.attributes[i].offset;
01049 }
01050 else
01051 {
01052 for (uint32 j = 0; j < desc.nAttributes; j++)
01053 {
01054 if (desc.attributes[j].semantic == newDesc.attributes[i].semantic)
01055 {
01056 assert(desc.attributes[j].format == newDesc.attributes[i].format);
01057 fromOffsets[i] = desc.attributes[j].offset;
01058 break;
01059 }
01060 }
01061 }
01062 }
01063
01064
01065
01066 void* newVertexData = new char[newDesc.stride * nFaces * 3];
01067 for (f = 0; f < nFaces; f++)
01068 {
01069 Face& face = faces[f];
01070
01071 for (uint32 j = 0; j < 3; j++)
01072 {
01073 char* newVertex = reinterpret_cast<char*>(newVertexData) +
01074 (f * 3 + j) * newDesc.stride;
01075 copyVertex(newVertex, newDesc,
01076 vertexData, desc,
01077 face.i[j],
01078 fromOffsets);
01079 memcpy(newVertex + tangentOffset, &vertexTangents[f * 3 + j],
01080 Mesh::getVertexAttributeSize(Mesh::Float3));
01081 }
01082 }
01083
01084
01085 Mesh* newMesh = new Mesh();
01086 newMesh->setVertexDescription(newDesc);
01087 newMesh->setVertices(nFaces * 3, newVertexData);
01088
01089
01090 uint32* indices = new uint32[nFaces * 3];
01091 for (i = 0; i < nFaces * 3; i++)
01092 indices[i] = i;
01093
01094
01095
01096 uint32 materialIndex = mesh.getGroup(0)->materialIndex;
01097 newMesh->addGroup(Mesh::TriList, materialIndex, nFaces * 3, indices);
01098
01099
01100 delete[] faceCounts;
01101 for (i = 0; i < nVertices; i++)
01102 {
01103 if (vertexFaces[i] != NULL)
01104 delete[] vertexFaces[i];
01105 }
01106 delete[] vertexFaces;
01107
01108 return newMesh;
01109 }
01110
01111
01112 void
01113 addGroupWithOffset(Mesh& mesh,
01114 const Mesh::PrimitiveGroup& group,
01115 uint32 offset)
01116 {
01117 if (group.nIndices == 0)
01118 return;
01119
01120 uint32* newIndices = new uint32[group.nIndices];
01121 for (uint32 i = 0; i < group.nIndices; i++)
01122 newIndices[i] = group.indices[i] + offset;
01123
01124 mesh.addGroup(group.prim, group.materialIndex,
01125 group.nIndices, newIndices);
01126 }
01127
01128
01129
01130 Model*
01131 mergeModelMeshes(const Model& model)
01132 {
01133 vector<Mesh*> meshes;
01134
01135 for (uint32 i = 0; model.getMesh(i) != NULL; i++)
01136 {
01137 meshes.push_back(model.getMesh(i));
01138 }
01139
01140
01141 sort(meshes.begin(), meshes.end(), MeshVertexDescComparator());
01142
01143 Model* newModel = new Model();
01144
01145
01146 for (i = 0; model.getMaterial(i) != NULL; i++)
01147 {
01148 newModel->addMaterial(model.getMaterial(i));
01149 }
01150
01151 uint32 meshIndex = 0;
01152 while (meshIndex < meshes.size())
01153 {
01154 const Mesh::VertexDescription& desc =
01155 meshes[meshIndex]->getVertexDescription();
01156
01157
01158 uint32 nMatchingMeshes;
01159 for (nMatchingMeshes = 1;
01160 meshIndex + nMatchingMeshes < meshes.size();
01161 nMatchingMeshes++)
01162 {
01163 if (!(meshes[meshIndex + nMatchingMeshes]->getVertexDescription() == desc))
01164 {
01165 break;
01166 }
01167 }
01168
01169
01170 uint32 totalVertices = 0;
01171 uint32 j;
01172 for (j = meshIndex; j < meshIndex + nMatchingMeshes; j++)
01173 {
01174 totalVertices += meshes[j]->getVertexCount();
01175 }
01176
01177 char* vertexData = new char[totalVertices * desc.stride];
01178
01179
01180 Mesh* mergedMesh = new Mesh();
01181 mergedMesh->setVertexDescription(desc);
01182 mergedMesh->setVertices(totalVertices, vertexData);
01183
01184
01185 uint32 vertexCount = 0;
01186 for (j = meshIndex; j < meshIndex + nMatchingMeshes; j++)
01187 {
01188 const Mesh* mesh = meshes[j];
01189 memcpy(vertexData + vertexCount * desc.stride,
01190 mesh->getVertexData(),
01191 mesh->getVertexCount() * desc.stride);
01192
01193 for (uint32 k = 0; mesh->getGroup(k) != NULL; k++)
01194 {
01195 addGroupWithOffset(*mergedMesh, *mesh->getGroup(k),
01196 vertexCount);
01197 }
01198
01199 vertexCount += mesh->getVertexCount();
01200 }
01201 assert(vertexCount == totalVertices);
01202
01203 newModel->addMesh(mergedMesh);
01204
01205 meshIndex += nMatchingMeshes;
01206 }
01207
01208 return newModel;
01209 }
01210
01211
01212 #ifdef TRISTRIP
01213 bool
01214 convertToStrips(Mesh& mesh)
01215 {
01216 vector<Mesh::PrimitiveGroup*> groups;
01217
01218
01219 if (mesh.getVertexCount() >= 0x10000)
01220 {
01221 return true;
01222 }
01223
01224
01225 uint32 i;
01226 for (i = 0; mesh.getGroup(i) != NULL; i++)
01227 {
01228 if (mesh.getGroup(i)->prim != Mesh::TriList)
01229 return true;
01230 }
01231
01232
01233 for (i = 0; mesh.getGroup(i) != NULL; i++)
01234 {
01235 const Mesh::PrimitiveGroup* group = mesh.getGroup(i);
01236
01237
01238 unsigned short* indices = new unsigned short[group->nIndices];
01239 uint32 j;
01240 for (j = 0; j < group->nIndices; j++)
01241 {
01242 indices[j] = (unsigned short) group->indices[j];
01243 }
01244
01245 PrimitiveGroup* strips = NULL;
01246 unsigned short nGroups;
01247 bool r = GenerateStrips(indices,
01248 group->nIndices,
01249 &strips,
01250 &nGroups,
01251 false);
01252 if (!r || strips == NULL)
01253 {
01254 cerr << "Generate tri strips failed\n";
01255 return false;
01256 }
01257
01258
01259
01260
01261
01262 for (j = 0; j < nGroups; j++)
01263 {
01264 Mesh::PrimitiveGroupType prim = Mesh::InvalidPrimitiveGroupType;
01265 switch (strips[j].type)
01266 {
01267 case PT_LIST:
01268 prim = Mesh::TriList;
01269 break;
01270 case PT_STRIP:
01271 prim = Mesh::TriStrip;
01272 break;
01273 case PT_FAN:
01274 prim = Mesh::TriFan;
01275 break;
01276 }
01277
01278 if (prim != Mesh::InvalidPrimitiveGroupType &&
01279 strips[j].numIndices != 0)
01280 {
01281 Mesh::PrimitiveGroup* newGroup = new Mesh::PrimitiveGroup();
01282 newGroup->prim = prim;
01283 newGroup->materialIndex = group->materialIndex;
01284 newGroup->nIndices = strips[j].numIndices;
01285 newGroup->indices = new uint32[newGroup->nIndices];
01286 for (uint32 k = 0; k < newGroup->nIndices; k++)
01287 newGroup->indices[k] = strips[j].indices[k];
01288
01289 groups.push_back(newGroup);
01290 }
01291 }
01292
01293 delete[] strips;
01294 }
01295
01296 mesh.clearGroups();
01297
01298
01299 for (vector<Mesh::PrimitiveGroup*>::const_iterator iter = groups.begin();
01300 iter != groups.end(); iter++)
01301 {
01302 mesh.addGroup(*iter);
01303 }
01304
01305 return true;
01306 }
01307 #endif
01308
01309
01310 bool parseCommandLine(int argc, char* argv[])
01311 {
01312 int i = 1;
01313 int fileCount = 0;
01314
01315 while (i < argc)
01316 {
01317 if (argv[i][0] == '-')
01318 {
01319 if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--binary"))
01320 {
01321 outputBinary = true;
01322 }
01323 else if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--ascii"))
01324 {
01325 outputBinary = false;
01326 }
01327 else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uniquify"))
01328 {
01329 uniquify = true;
01330 }
01331 else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--normals"))
01332 {
01333 genNormals = true;
01334 }
01335 else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "--tangents"))
01336 {
01337 genTangents = true;
01338 }
01339 else if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--weld"))
01340 {
01341 weldVertices = true;
01342 }
01343 else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--merge"))
01344 {
01345 mergeMeshes = true;
01346 }
01347 else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--optimize"))
01348 {
01349 stripify = true;
01350 }
01351 else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--smooth"))
01352 {
01353 if (i == argc - 1)
01354 {
01355 return false;
01356 }
01357 else
01358 {
01359 if (sscanf(argv[i + 1], " %f", &smoothAngle) != 1)
01360 return false;
01361 i++;
01362 }
01363 }
01364 else
01365 {
01366 return false;
01367 }
01368 i++;
01369 }
01370 else
01371 {
01372 if (fileCount == 0)
01373 {
01374
01375 inputFilename = string(argv[i]);
01376 fileCount++;
01377 }
01378 else if (fileCount == 1)
01379 {
01380
01381 outputFilename = string(argv[i]);
01382 fileCount++;
01383 }
01384 else
01385 {
01386
01387 return false;
01388 }
01389 i++;
01390 }
01391 }
01392
01393 return true;
01394 }
01395
01396
01397 int main(int argc, char* argv[])
01398 {
01399 if (!parseCommandLine(argc, argv))
01400 {
01401 usage();
01402 return 1;
01403 }
01404
01405 Model* model = NULL;
01406 if (!inputFilename.empty())
01407 {
01408 ifstream in(inputFilename.c_str(), ios::in | ios::binary);
01409 if (!in.good())
01410 {
01411 cerr << "Error opening " << inputFilename << "\n";
01412 return 1;
01413 }
01414 model = LoadModel(in);
01415 }
01416 else
01417 {
01418 model = LoadModel(cin);
01419 }
01420
01421 if (model == NULL)
01422 return 1;
01423
01424 if (genNormals || genTangents)
01425 {
01426 Model* newModel = new Model();
01427 uint32 i;
01428
01429
01430 for (i = 0; model->getMaterial(i) != NULL; i++)
01431 {
01432 newModel->addMaterial(model->getMaterial(i));
01433 }
01434
01435
01436 for (i = 0; model->getMesh(i) != NULL; i++)
01437 {
01438 Mesh* mesh = model->getMesh(i);
01439 Mesh* newMesh = NULL;
01440
01441 if (genNormals)
01442 {
01443 newMesh = generateNormals(*mesh,
01444 degToRad(smoothAngle),
01445 weldVertices);
01446 if (newMesh == NULL)
01447 {
01448 cerr << "Error generating normals!\n";
01449 return 1;
01450 }
01451
01452 mesh = newMesh;
01453 }
01454
01455 if (genTangents)
01456 {
01457 newMesh = generateTangents(*mesh, weldVertices);
01458 if (newMesh == NULL)
01459 {
01460 cerr << "Error generating tangents!\n";
01461 return 1;
01462 }
01463
01464 mesh = newMesh;
01465 }
01466
01467 newModel->addMesh(mesh);
01468 }
01469
01470
01471 model = newModel;
01472 }
01473
01474 if (mergeMeshes)
01475 {
01476 model = mergeModelMeshes(*model);
01477 }
01478
01479 if (uniquify)
01480 {
01481 for (uint32 i = 0; model->getMesh(i) != NULL; i++)
01482 {
01483 Mesh* mesh = model->getMesh(i);
01484 uniquifyVertices(*mesh);
01485 }
01486 }
01487
01488 #ifdef TRISTRIP
01489 if (stripify)
01490 {
01491 SetCacheSize(vertexCacheSize);
01492 for (uint32 i = 0; model->getMesh(i) != NULL; i++)
01493 {
01494 Mesh* mesh = model->getMesh(i);
01495 convertToStrips(*mesh);
01496 }
01497 }
01498 #endif
01499
01500 if (outputFilename.empty())
01501 {
01502 if (outputBinary)
01503 SaveModelBinary(model, cout);
01504 else
01505 SaveModelAscii(model, cout);
01506 }
01507 else
01508 {
01509 ofstream out(outputFilename.c_str(),
01510 ios::out | (outputBinary ? ios::binary : 0));
01511 if (!out.good())
01512 {
01513 cerr << "Error opening output file " << outputFilename << "\n";
01514 return 1;
01515 }
01516
01517 if (outputBinary)
01518 SaveModelBinary(model, out);
01519 else
01520 SaveModelAscii(model, out);
01521 }
01522
01523 return 0;
01524 }