source: GTP/trunk/Lib/Geom/shared/GTGeometry/src/GeoMeshLoader.cpp @ 1098

Revision 1098, 42.7 KB checked in by gumbau, 18 years ago (diff)

Actualize LodStrips? Faces and scale bug fixed

Line 
1/*==========================================================================
2 *      (C) 2005 Universitat Jaume I
3 *==========================================================================
4 *      PROYECT:        GAME TOOLS
5 *==========================================================================*/
6/*      CONTENT:       
7 *
8 *
9 *      @file   GeoMeshLoader.cpp
10 *==========================================================================*/
11
12#include        "GeoMeshLoader.h"
13#include        <algorithm>
14#include        <cctype>
15#include        <map>
16
17using namespace Geometry;
18using   namespace       std;
19
20//---------------------------------------------------------------------------
21//      Jump a chunk.
22//---------------------------------------------------------------------------
23void GeoMeshLoader::jumpChunk(FILE      *f)
24{
25        fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
26
27        //      Return to the begin of the chunk.
28        fseek(f,long_actual,SEEK_CUR);
29}
30
31//---------------------------------------------------------------------------
32//      Read a chunk.
33//---------------------------------------------------------------------------
34unsigned short GeoMeshLoader::readChunk(FILE    *f)
35{
36        unsigned        short   id;
37
38        fread(&id,sizeof(unsigned short),1,f);
39        fread(&long_actual,sizeof(unsigned long),1,f);
40                                                                       
41        return id;
42}
43
44//---------------------------------------------------------------------------
45//      Read geometry vertex element.
46//---------------------------------------------------------------------------
47void GeoMeshLoader::readGeometryVertexElement(FILE      *f, Mesh        *geoMesh)
48{
49        unsigned        short           source;
50        GeometryElement         aux;
51        int                                                             i;
52        bool                                                    found;
53        VertexElementType       vType;
54
55        i                                               =       0;
56        found   =       false;
57
58        //              VertexElementSemantic vSemantic;
59        // unsigned short source;       // buffer bind source
60        fread(&source,sizeof(unsigned short),1,f);
61
62        // unsigned short type;         // VertexElementType
63        fread(&aux.type,sizeof(unsigned short),1,f);
64
65        vType   =       static_cast<VertexElementType>(aux.type);
66
67        // unsigned short semantic; // VertexElementSemantic
68        fread(&aux.semantic,sizeof(unsigned short),1,f);
69
70        //      vSemantic = static_cast<VertexElementSemantic>(tmp);
71        //      unsigned short offset;  // start offset in buffer in bytes
72        fread(&aux.offset,sizeof(unsigned short),1,f);
73
74        // unsigned short index;        // index of the semantic
75        /*
76        VES_POSITION  Position, 3 reals per vertex. 
77        VES_BLEND_WEIGHTS  Blending weights. 
78        VES_BLEND_INDICES  Blending indices. 
79        VES_NORMAL  Normal, 3 reals per vertex. 
80        VES_DIFFUSE  Diffuse colours. 
81        VES_SPECULAR  Specular colours. 
82        VES_TEXTURE_COORDINATES  Texture coordinates. 
83        VES_BINORMAL  Binormal (Y axis if normal is Z). 
84        VES_TANGENT  Tangent (X axis if normal is Z). 
85        */
86        fread(&aux.index,sizeof(unsigned short),1,f);
87
88        while ((i < list.size()) && (!found))
89        {
90                if (list[i].source==source)
91                {
92                        found   =       true;
93                }
94                else
95                {
96                        i++;
97                }
98        }
99
100        if (found)
101        {
102                list[i].list.push_back(aux);
103        }
104        else
105        {
106                GT      aux2;
107               
108                aux2.source     =       source;
109                aux2.list.push_back(aux);
110                list.push_back(aux2);
111        }
112}
113
114//---------------------------------------------------------------------------
115//      Read geometry vertex declaration.
116//---------------------------------------------------------------------------
117void GeoMeshLoader::readGeometryVertexDeclaration(FILE  *f, Mesh        *geoMesh)
118{
119        unsigned short chunkID;
120  // Find optional geometry chunks
121  if (!feof(f))
122  {
123    chunkID     =       readChunk(f);
124
125    while(!feof(f) && (chunkID == M_GEOMETRY_VERTEX_ELEMENT ))
126    {
127      switch (chunkID)
128      {
129                                case M_GEOMETRY_VERTEX_ELEMENT:
130
131                                        //      Debug.
132                                        cout    <<      "               M_GEOMETRY_VERTEX_ELEMENT"
133                                                                <<      endl;
134                                       
135          readGeometryVertexElement(f, geoMesh);
136
137          break;
138      }
139
140      // Get next chunk
141      if (!feof(f))
142      {
143                                chunkID = readChunk(f);
144      }
145    }// End while.
146
147    if (!feof(f))
148    {
149                        // Backpedal back to start of non-submesh chunk
150                        fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
151    }
152
153  }//   End if (!feof(f))
154}//     End readGeometryVertexDeclaration.
155
156//---------------------------------------------------------------------------
157//      Read geometry vertex buffer.
158//---------------------------------------------------------------------------
159void GeoMeshLoader::readGeometryVertexBuffer(FILE       *f, Mesh        *geoMesh, int option)
160{
161        unsigned        short   bindIndex;
162        unsigned        short   vertexSize;
163        unsigned        short   headerID;
164        int                                                     i;
165        float                                           aux;
166        int                                                     k;
167        bool                                            found;
168        float                                           x,y,z;
169        SubMesh                                 *geoSubMesh;
170        VertexBuffer            *vertex_buffer;
171
172        i                                               =       0;
173        k                                               =       0;
174        found   =       false;
175       
176        if (option == GEOMESH_BUILD)
177        {
178                //      If is the main mesh.
179                if (currentSubMesh == -1)
180                {
181                        vertex_buffer   =       geoMesh->mVertexBuffer;
182                }
183                //      If is a submesh.
184                else
185                {
186                        //      Gets the current submesh
187                        geoSubMesh              =       &geoMesh->mSubMesh[currentSubMesh];
188                        vertex_buffer   =       geoSubMesh->mVertexBuffer;
189                }
190        }
191       
192        // Index to bind this buffer to
193        fread(&bindIndex,sizeof(unsigned short),1,f);
194
195        // Per-vertex size, must agree with declaration at this index
196        fread(&vertexSize,sizeof(unsigned short),1,f);
197
198        // Check for vertex data header
199        headerID        =       readChunk(f);
200
201        if (headerID != M_GEOMETRY_VERTEX_BUFFER_DATA)
202        {
203                cout    <<      "Can't find vertex buffer data area"
204                                        <<      endl;
205        }
206        else
207        {
208                //      Debug.
209                cout    <<      "               M_GEOMETRY_VERTEX_BUFFER_DATA"
210                                        <<      endl;
211        }
212
213        while ((i<list.size())&&(!found))
214        {
215                if (list[i].source      ==      bindIndex)
216                {
217                        found   =       true;
218                }
219                else
220                {
221                        i++;
222                }
223        }
224
225        if (found)
226        {
227                for (k  =       0;      k < numVertices;        k++)
228                {
229                        //      For each element in this source.
230                        for(int j       =       0;      j < list[i].list.size();        j++)
231                        {
232                                //      Positions.
233                                if (list[i].list[j].semantic == 1)
234                                {
235                                        fread(&x,sizeof(float),1,f);
236                                        fread(&y,sizeof(float),1,f);
237                                        fread(&z,sizeof(float),1,f);
238
239                                        if (option == GEOMESH_BUILD)
240                                        {
241                                                vertex_buffer->mVertexInfo              |=      VERTEX_POSITION;
242                                                vertex_buffer->mPosition[k].x   =               x;
243                                                vertex_buffer->mPosition[k].y   =               y;
244                                                vertex_buffer->mPosition[k].z   =               z;
245                                        }
246                                }
247                                //      If are not vertices.
248                                else
249                                {
250                                        if (list[i].list[j].type == 2)
251                                        {
252                                                fread(&x,sizeof(float),1,f);
253                                                fread(&y,sizeof(float),1,f);
254                                                fread(&z,sizeof(float),1,f);
255
256                                                if (option == GEOMESH_BUILD)
257                                                {
258                                                        vertex_buffer->mVertexInfo      |=      VERTEX_NORMAL;
259                                                        vertex_buffer->mNormal[k].x     =               x;
260                                                        vertex_buffer->mNormal[k].y     =               y;
261                                                        vertex_buffer->mNormal[k].z     =               z;
262                                                }
263                                        }
264                                        if (list[i].list[j].type == 1)
265                                        {
266                                                fread(&x,sizeof(float),1,f);
267                                                fread(&y,sizeof(float),1,f);
268                                               
269                                                if (option == GEOMESH_BUILD)
270                                                {
271                                                        vertex_buffer->mVertexInfo                      |=      VERTEX_TEXCOORDS;
272                                                        vertex_buffer->mTexCoords[k].x  =               x;
273                                                        vertex_buffer->mTexCoords[k].y  =               y;
274                                                }
275                                        }
276                                }
277                        }
278                }
279        }
280        else
281        {
282                //      Debug.
283                cout    <<      "Error: Source not found."
284                                        <<      endl;
285
286                //      Error.
287                mError  =       true;
288        }
289
290}
291
292//---------------------------------------------------------------------------
293//      Read Geometry.
294//---------------------------------------------------------------------------
295void GeoMeshLoader::readGeometry(FILE   *f, Mesh        *geoMesh, int option)
296{
297        SubMesh                         *geoSubMesh;
298        VertexBuffer    *vertex_buffer;
299       
300        fread(&numVertices,sizeof(unsigned int),1,f);
301
302        if (option == GEOMESH_BUILD)
303        {
304                if (currentSubMesh == -1)
305                {
306                        //      Get the current vertex buffer.
307                        vertex_buffer   =       geoMesh->mVertexBuffer;
308                }
309                else
310                {
311                        //      Get the current submesh.
312                        geoSubMesh              =       &geoMesh->mSubMesh[currentSubMesh];
313
314                        //      Create the VertexBuffer of the submesh.
315                        geoSubMesh->mVertexBuffer       =       new VertexBuffer();
316
317                        //      Get the current vertex buffer.
318                        vertex_buffer   =       geoSubMesh->mVertexBuffer;
319                }
320
321                //      Initialize the VertexBuffer of the current submesh.
322                vertex_buffer->mVertexCount     =       numVertices;
323
324                //      Initialize the position array.
325                vertex_buffer->mPosition        =       new Vector3[numVertices];
326
327                //      Initialize the normal array.
328                vertex_buffer->mNormal          =       new Vector3[numVertices];
329
330                //      Initialize the texture coords array.
331                vertex_buffer->mTexCoords       =       new Vector2[numVertices];
332        }
333
334        // Find optional geometry chunks
335        if (!feof(f))
336        {
337                unsigned short chunkID = readChunk(f);
338       
339                while(!feof(f) &&
340                                        (chunkID == M_GEOMETRY_VERTEX_DECLARATION ||
341                                        chunkID == M_GEOMETRY_VERTEX_BUFFER ))
342                {
343                        switch (chunkID)
344                        {
345                                case M_GEOMETRY_VERTEX_DECLARATION:
346
347                                        //      Debug.
348                                        cout    <<      "               M_GEOMETRY_VERTEX_DECLARATION"
349                                                                <<      endl;
350                                       
351                                        readGeometryVertexDeclaration(f, geoMesh);
352                                       
353                                        break;
354                                       
355                                case M_GEOMETRY_VERTEX_BUFFER:
356                                       
357                                        //      Debug.
358                                        cout    <<      "               M_GEOMETRY_VERTEX_BUFFER"
359                                                                <<      endl;
360                                       
361                                        readGeometryVertexBuffer(f, geoMesh,option);
362                                       
363                                        break;
364                        }
365               
366                        // Get next chunk.
367                        if (!feof(f))
368                        {
369                                chunkID = readChunk(f);
370                        }
371                }
372
373                if (!feof(f))
374                {
375                        // Backpedal back to start of non-submesh chunk.
376                        fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
377                }
378        }
379}
380
381//---------------------------------------------------------------------------
382//      Read a submesh operation.
383//---------------------------------------------------------------------------
384void GeoMeshLoader::readSubMeshOperation(       FILE    *f,
385                                                                                                                                                                        Mesh    *geoMesh,
386                                                                                                                                                                        int     option)
387{
388        unsigned        short   opType;
389       
390        fread(&opType,sizeof(unsigned short),1,f);
391
392        if (option == GEOMESH_BUILD)
393        {
394                if (opType == 5)
395                {
396                        geoMesh->mSubMesh[currentSubMesh].mType =       GEO_TRIANGLE_STRIPS;
397                }
398                else
399                {
400                        geoMesh->mSubMesh[currentSubMesh].mType =       GEO_TRIANGLE_LIST;
401                }
402        }
403}
404
405//---------------------------------------------------------------------------
406//      Read a submesh.
407//---------------------------------------------------------------------------
408void GeoMeshLoader::readSubMesh(FILE    *f, Mesh        *geoMesh, int option)
409{
410        SubMesh                                 *geoSubMesh;
411        unsigned        short   chunkID;
412        char                                            materialName[255];
413        bool                                            useSharedVertices;
414        unsigned        int             numIndices;
415        bool                                            idx32bit;
416
417        switch  (option)
418        {
419                case    SUBMESH_COUNT:
420                        geoMesh->mSubMeshCount++;
421                        break;
422                case    GEOMESH_BUILD:
423
424                        //      Initialize the new subMesh.
425                        geoSubMesh      =       &geoMesh->mSubMesh[currentSubMesh];
426        }
427       
428        list.clear();
429
430        //      Gets material name.
431        fgets(materialName,255,f);
432        materialName[strlen(materialName) - 1]  =       '\0';
433
434        fread(&useSharedVertices,sizeof(bool),1,f);
435       
436        if (option      ==      GEOMESH_BUILD)
437        {
438                //      Obtain the material name.
439                strcpy(geoSubMesh->mMaterialName,materialName);
440               
441                //      Obtain the flag of vertex shared.
442                geoSubMesh->mSharedVertexBuffer =       useSharedVertices;
443               
444                if (useSharedVertices)
445                {
446                        //      The VB of the submesh points to the VB of the mesh.
447                        geoSubMesh->mVertexBuffer       =       geoMesh->mVertexBuffer;
448                }
449        }
450
451        fread(&numIndices,sizeof(unsigned int),1,f);
452        fread(&idx32bit,sizeof(bool),1,f);
453       
454        if (option == GEOMESH_BUILD)
455        {
456                        //      Sets the index count of the submesh.
457                        geoSubMesh->mIndexCount =       numIndices;
458       
459                        //      Create the index arrar for this submesh.
460                        geoSubMesh->mIndex      =       new Index[numIndices];
461        }
462       
463
464        if (idx32bit)
465        {
466                unsigned int aux;
467
468                for (int i = 0; i < numIndices; i++)
469                {
470                        fread(&aux,sizeof(unsigned int),1,f);
471
472                        if (option == GEOMESH_BUILD)
473                        {
474                                        geoSubMesh->mIndex[i]   =       aux;
475                        }
476                }
477        }
478        else
479        {
480                unsigned short aux;
481
482                for (int i = 0; i < numIndices; i++)
483                {
484                        fread(&aux,sizeof(unsigned short),1,f);
485                       
486                        if (option == GEOMESH_BUILD)
487                        {
488                                geoSubMesh->mIndex[i]   =       aux;
489                        }
490                }
491        }
492
493  // M_GEOMETRY chunk
494        // (Optional: present only if useSharedVertices = false)
495  if (!useSharedVertices)
496        {
497                chunkID = readChunk(f);
498               
499                if (chunkID != M_GEOMETRY)
500                {
501                        //      Debug.
502                        cout    <<      "Error: Missing mesh geometry."
503                                                <<      endl;
504
505                        //      Error.
506                        mError  =       true;
507                }
508               
509                readGeometry(f, geoMesh, option);
510        }
511
512        // Find all bone assignments (if present)
513        if (!feof(f))
514        {
515                chunkID = readChunk(f);
516                while(!feof(f) &&
517                                        (chunkID == M_SUBMESH_BONE_ASSIGNMENT ||
518                                        chunkID == M_SUBMESH_OPERATION))
519                {
520                        switch(chunkID)
521                        {
522                                case M_SUBMESH_OPERATION:
523                                                               
524                                        //      Debug.
525                                        cout    <<      "               M_SUBMESH_OPERATION"
526                                                                <<      endl;
527
528                                        readSubMeshOperation(f, geoMesh, option);
529                                       
530                                        break;
531                                       
532                                case M_SUBMESH_BONE_ASSIGNMENT:
533                                       
534                                        //      Debug.
535                                        //cout  <<      "               M_SUBMESH_BONE_ASSIGNMENT"
536                                        //                      <<      endl;
537                                       
538                                        if (option      ==      GEOMESH_BUILD)
539                                        {
540                                                readSubMeshBoneAssignment(f, geoSubMesh, option);
541                                        }
542                                        else
543                                        {
544                                                jumpChunk(f);
545                                        }
546                                       
547                                        break;
548                        }
549
550                        if (!feof(f))
551                        {
552                                chunkID =       readChunk(f);
553                        }
554
555                }
556                if (!feof(f))
557                {
558                        // Backpedal back to start of chunk.
559                        fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
560                }
561        }
562
563}
564
565//---------------------------------------------------------------------------
566//      Read a mesh lod information.
567//---------------------------------------------------------------------------
568void GeoMeshLoader::readMeshLodInfo(FILE        *f, Mesh        *geoMesh)
569{
570        unsigned        short   chunkID;
571        unsigned        short   i;
572        unsigned        short   aux;
573        bool                                            aux2;
574
575  // unsigned short numLevels;
576        fread(&aux,sizeof(unsigned short),1,f);
577        // bool manual;
578        // (true for manual alternate meshes, false for generated)
579        fread(&aux2,sizeof(bool),1,f);
580
581        // Loop from 1 rather than 0 (full detail index is not in file)
582        for (i = 1; i < aux; ++i)
583        {
584                chunkID = readChunk(f);
585                if (chunkID != M_MESH_LOD_USAGE)
586                {
587                        //      Debug.
588                        cout    <<      "Error: Missing M_MESH_LOD_USAGE chunk"
589                                                <<      endl;
590                }
591                else
592                {
593                        cout    <<      "               M_MESH_LOD_USAGE"
594                                                <<      endl;
595                }
596               
597                jumpChunk(f);
598
599        }
600}
601
602//---------------------------------------------------------------------------
603//      Read a submesh name table.
604//---------------------------------------------------------------------------
605void GeoMeshLoader::readSubMeshNameTable(FILE   *f, Mesh        *geoMesh)
606{
607                unsigned        short   chunkID;
608                unsigned        short   subMeshIndex;
609                char                                            string[255];
610
611                if (!feof(f))
612                {
613                        chunkID =       readChunk(f);
614                       
615                        while   (!feof(f) && (chunkID == M_SUBMESH_NAME_TABLE_ELEMENT ))
616                        {
617                                //      Debug.
618                                cout    <<      "               M_SUBMESH_NAME_TABLE_ELEMENT"
619                                                        <<      endl;
620                               
621                                // Read in the index of the submesh.
622                                fread(&subMeshIndex,sizeof(unsigned short),1,f);
623                               
624                                // Read in the String and map it to its index.
625                                fgets(string,255,f);
626
627                                // If we're not end of file get the next chunk ID.
628                                if (!feof(f))
629                                {
630                                        chunkID = readChunk(f);
631                                }
632                        }
633                        if (!feof(f))
634                        {
635                                // Backpedal back to start of chunk.
636                                fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
637                        }
638                }
639}
640
641//---------------------------------------------------------------------------
642//      Read a mesh file.
643//---------------------------------------------------------------------------
644
645#include "GeoLodStripsLibrary.h"
646#include "GeoLodStripsConstructor.h"
647
648void GeoMeshLoader::readMesh(FILE       *f, Mesh        *geoMesh, int option)
649{
650        unsigned        short   chunkID;
651        bool                                            nada;
652
653        //      Create the VertexBuffer of the mesh.
654        geoMesh->mVertexBuffer  =       new     VertexBuffer();
655        geoMesh->mVertexBuffer->mVertexCount    =       0;
656
657        //La vacio antes de leer el mesh
658        list.clear();
659
660        // bool skeletallyAnimated
661        fread(&nada,sizeof(bool),1,f);
662
663  // Find all subchunks
664        if (!feof(f))
665        {
666                chunkID =       readChunk(f);
667
668                while(!feof(f) &&
669                                (chunkID == M_GEOMETRY ||
670                                 chunkID == M_SUBMESH ||
671                                 chunkID == M_MESH_SKELETON_LINK ||
672                                 chunkID == M_MESH_BONE_ASSIGNMENT ||
673                                 chunkID == M_MESH_LOD ||
674                                 chunkID == M_MESH_BOUNDS ||
675                                 chunkID == M_SUBMESH_NAME_TABLE ||
676                                 chunkID == M_EDGE_LISTS ||
677                                 chunkID == 0xabcd ||
678                                 chunkID == 0xdcba))
679                {
680                        switch(chunkID)
681                        {
682                                case 0xabcd:
683                                        cout << "LODSTRIPS_Chunk" << endl;
684                                        lodstripsdata = new Geometry::LodStripsLibraryData;
685
686                                        int                             aux,v,c;
687                                        LODRegisterType lod_register;
688                                        LODData                 dataaux;
689                                        int                             tam;
690
691                                        fread(&tam, sizeof(int), 1, f);
692                                        lodstripsdata->mFileVertices.clear();
693                                        for (v=0; v<tam; v++)
694                                        {
695                                                fread(&aux, sizeof(int), 1, f);
696                                                lodstripsdata->mFileVertices.push_back(aux);
697                                        }
698
699                                        lodstripsdata->mFileChangesLOD.clear();
700                                        fread(&tam, sizeof(int), 1, f);
701                                        for (c=0; c<tam; c++)
702                                        {
703                                                fread(&dataaux, sizeof(LODData), 1, f);
704                                                lod_register.strip= dataaux.strip;
705                                                lod_register.position= dataaux.nP;
706                                                lod_register.vertexRepetition= dataaux.nL1;
707                                                lod_register.edgeRepetition= dataaux.nL2;
708                                                //lod_register.obligatory=false;
709                                                //lod_register.obligatory= dataaux.obligatory;
710
711                                                lodstripsdata->mFileChangesLOD.push_back(lod_register);
712                                        }
713                                       
714                                        lodstripsdata->mData.clear();
715                                        fread(&tam, sizeof(int), 1, f);
716                                        for (int b=0; b<tam; b++)
717                                        {
718                                                fread(&aux, sizeof(int), 1, f);
719                                                lodstripsdata->mData.push_back(aux);
720                                        }
721
722                                        lodstripsdata->p_changes.clear();
723                                        fread(&tam, sizeof(int), 1, f);
724                                        for (int p=0; p<tam; p++)
725                                        {
726                                                fread(&aux, sizeof(int), 1, f);
727                                                lodstripsdata->p_changes.push_back(aux);
728                                        }                                       
729
730                                        break;
731
732                                case 0xdcba:
733                                        cout << "LODTREES_Chunk" << endl;
734                                        treesimpseq = new Geometry::TreeSimplificationSequence;
735
736                                        int size;
737                                        fread(&size, sizeof(int), 1, f);
738                                        treesimpseq->mSteps.clear();
739                                        for (int i=0; i<size; i++)
740                                        {
741                                                Geometry::TreeSimplificationSequence::Step auxstep;
742                                                fread(&auxstep.mV0,sizeof(int),1,f);
743                                                fread(&auxstep.mV1,sizeof(int),1,f);
744                                                fread(&auxstep.mT0,sizeof(int),1,f);
745                                                fread(&auxstep.mT1,sizeof(int),1,f);
746                                                fread(auxstep.mNewQuad,sizeof(int),4,f);
747                                                treesimpseq->mSteps.push_back(auxstep);
748                                        }
749
750                                        break;
751
752
753                                case M_GEOMETRY:
754
755                                        //      Debug.
756                                        cout    <<      "               M_GEOMETRY"
757                                                                <<      endl;
758
759                                        readGeometry(f, geoMesh, option);
760                                        break;
761
762                                case M_SUBMESH:
763
764                                        //      Debug.
765                                        cout    <<      "               M_SUBMESH"
766                                                                <<      endl;
767
768                                        if (option == GEOMESH_BUILD)
769                                        {
770                                                //      Increments the current submesh.
771                                                currentSubMesh++;
772                                        }
773
774                                        readSubMesh(f, geoMesh, option);
775
776                                        break;
777
778                                case M_MESH_SKELETON_LINK:
779
780                                        //      Debug.
781                                        cout    <<      "               M_MESH_SKELETON_LINK  "
782                                                                <<      endl;
783                                                               
784
785                                        readSkeletonLink(f, geoMesh, option);
786
787                                        break;
788
789                                case M_MESH_BONE_ASSIGNMENT:
790
791                                        //      Debug.
792                                        //cout  <<      "               M_MESH_BONE_ASSIGNMENT  "
793                                        //                      <<      endl;
794
795                                        readMeshBoneAssignment(f, geoMesh, option);
796
797                                        break;
798
799                                case M_MESH_LOD:
800
801                                        //      Debug.
802                                        cout    <<      "               M_MESH_LOD"
803                                                                <<      endl;
804                                       
805                                        readMeshLodInfo(f, geoMesh);
806                                        break;
807
808                                case M_MESH_BOUNDS:
809
810                                        //      Debug.
811                                        cout    <<      "               M_MESH_BOUNDS "
812                                                                <<      endl;
813
814                                        //jumpChunk(f);
815                                        readMeshBounds(f, geoMesh, option);
816                                        break;
817
818                                case M_SUBMESH_NAME_TABLE:
819
820                                        //      Debug.
821                                        cout    <<      "               M_SUBMESH_NAME_TABLE "
822                                                                <<      endl;
823
824                                        readSubMeshNameTable(f, geoMesh);
825                                        break;
826
827                                case M_EDGE_LISTS:
828
829                                        //      Debug.
830                                        cout    <<      "               M_EDGE_LISTS "
831                                                                <<      endl;
832
833                                        jumpChunk(f);
834                                        break;
835                        }
836
837                        if (!feof(f))
838                        {
839                                chunkID =       readChunk(f);
840                        }
841
842                }
843
844                if (!feof(f))
845                {
846                        // Backpedal back to start of chunk
847                        fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
848
849                        //      Debug.
850                        cout    <<      "Error: Reading failure."
851                                                <<      endl;
852
853                        //      Error.
854                        mError  =       true;
855                }
856        }
857
858}
859
860
861//---------------------------------------------------------------------------
862//      Allocate memory to the array of strips
863//---------------------------------------------------------------------------
864SubMesh* GeoMeshLoader::BuildStripsGeoSubMesh(SubMesh* geoSubMesh)
865{
866        bool            head_found;
867        bool            tail_found;
868        int                     strip_count;
869        int                     tailIndex;
870        size_t  tail;
871
872
873        head_found                                                      =       false;
874        tail_found                                                      =       false;
875        geoSubMesh->mStripCount =       1;
876
877        //      Foreachone of the indices.
878        //      Obtains the number of triangle strips.
879        for (int i = 0; i < (geoSubMesh->mIndexCount - 1); i++)
880        {
881                if (geoSubMesh->mIndex[i] == geoSubMesh->mIndex[i+1])
882                {
883                        if (head_found)
884                        {
885                                tail_found      =       true;
886                        }
887                        else
888                        {
889                                head_found      =       true;
890                        }
891
892                        //      Jump one index.
893                        i++;
894                }
895                else
896                {
897                        //      Increments the number of triangle strips.
898                        if (tail_found)
899                        {
900                                geoSubMesh->mStripCount++;
901                        }
902
903                        head_found      =       false;
904                        tail_found      =       false;
905                }
906        }
907
908        geoSubMesh->mStrip              =       (Index**) malloc(       sizeof(Index*)
909                        *
910                        geoSubMesh->mStripCount);
911
912        //      Number of strips. Initially there is one triangle strip.
913        strip_count     =       1;
914
915        head_found                                              =       false;
916        tail_found                                              =       false;
917
918        //      Initialize the fist triangle strip.
919        geoSubMesh->mStrip[0]   =       &geoSubMesh->mIndex[0];
920
921        //      Foreachone of the indices.
922        //      Assigns the beginning of the triangle strips.
923        for(int i = 0;i < (geoSubMesh->mIndexCount - 1); i++)
924        {
925                if(geoSubMesh->mIndex[i] == geoSubMesh->mIndex[i+1])
926                {
927                        if(head_found)
928                        {
929                                if (!tail_found)
930                                {
931                                        tailIndex               =       i;
932                                }
933
934                                tail_found      =       true;
935                        }
936                        else
937                        {
938                                head_found      =       true;
939                        }
940
941                        //      Jump one index.
942                        i++;
943                }
944                else
945                {
946                        //      Increments the number of triangle strips.
947                        if(tail_found)
948                        {
949                                geoSubMesh->mStrip[strip_count++]       =       &geoSubMesh->mIndex[tailIndex];
950                        }
951
952                        head_found      =       false;
953                        tail_found      =       false;
954                }
955        }
956
957        //      Remove degenerate triangles of a submesh given.
958        //geoSubMesh    =       removeDegenerateTriangles(geoSubMesh);
959
960        return  geoSubMesh;
961}
962
963//---------------------------------------------------------------------------
964//      Remove degenerate triangles of a submesh given.
965//---------------------------------------------------------------------------
966SubMesh *       GeoMeshLoader::removeDegenerateTriangles(SubMesh        *geoSubMesh)
967{
968        Index           *indices;
969        Index           *index;
970        Index           *indexBegin;
971        Index           *indexEnd;
972        Index           *new_strip_starts;
973        size_t  new_index_count;
974        size_t  current_index;
975
976        //      Stores the new starts of strips.
977        new_strip_starts        =       new     Index[geoSubMesh->mStripCount];
978       
979        //      Calculate the new index count.
980        new_index_count =       geoSubMesh->mIndexCount
981                -
982                (2 * geoSubMesh->mStripCount)
983                +
984                2;
985
986        //      Auxiliar index array.
987        indices =       new     Index[new_index_count];
988
989        //      Initialize the current index.
990        current_index   =       0;
991       
992        //      For each one of the strips.
993        for (int strip = 0; strip < geoSubMesh->mStripCount; strip++)
994        {
995                //      Stars of strip without degenerate triangles.
996                new_strip_starts[strip] =       current_index;
997               
998                //      First index of the strip.
999                indexBegin      =       geoSubMesh->mStrip[strip];
1000
1001                //      If is the final strip
1002                if (strip       == (geoSubMesh->mStripCount - 1))
1003                {
1004                        //      The end of the index array.
1005                        indexEnd        = &geoSubMesh->mIndex[geoSubMesh->mIndexCount];
1006                }
1007                else
1008                {
1009                        //      The beginning of the next strip.
1010                        indexEnd        = geoSubMesh->mStrip[strip + 1];
1011                }
1012
1013                int i;
1014                i       = 0;
1015
1016                //      If is not the first strip.
1017                if (strip != 0)
1018                {
1019                        indexBegin++;
1020                }
1021
1022                //      If is not the last strip.
1023                if (strip       != (geoSubMesh->mStripCount - 1))
1024                {
1025                        indexEnd--;
1026                }
1027
1028                //      For each index of the strip.
1029                for (index = indexBegin; index < indexEnd; index++)
1030                {
1031                        indices[current_index++]        =       indexBegin[i];
1032
1033                        //      Increments i.
1034                        i++;
1035                }
1036
1037        }
1038
1039        //      Free Index memory.
1040        delete  []geoSubMesh->mIndex;
1041
1042        //      Update index count.
1043        geoSubMesh->mIndexCount =       new_index_count;
1044
1045        geoSubMesh->mIndex      =       new     Index[new_index_count];
1046
1047        //      Store new index array without degenerate triangles.
1048        for (size_t     i       =       0;      i       <       geoSubMesh->mIndexCount; i++)
1049        {
1050                geoSubMesh->mIndex[i]   =       indices[i];
1051        }
1052
1053        //      Free auxiliar index array;
1054        delete  []indices;
1055
1056        //      Update start of the strip.
1057        for (int        strip   =       0; strip < geoSubMesh->mStripCount; strip++)
1058        {
1059                geoSubMesh->mStrip[strip]       =       &geoSubMesh->mIndex[new_strip_starts[strip]];
1060        }
1061
1062        //      Free auxiliar strip starts.
1063        delete  []new_strip_starts;
1064       
1065        return  geoSubMesh;
1066}
1067
1068//---------------------------------------------------------------------------
1069//      Loads a mesh.
1070//---------------------------------------------------------------------------
1071Mesh* GeoMeshLoader::load(char  *nameFileMesh)
1072{
1073        unsigned        short   uno;
1074        unsigned        short   chunkID;
1075        char            version[255];
1076        char            kk;
1077        FILE            *pFile;
1078        SubMesh         *geosubmesh;
1079
1080        //      Debug.
1081        cout    <<      "---------------------------------"
1082                                <<      endl
1083                                <<      "\t LOAD MESH"
1084                                <<      endl
1085                                <<      "---------------------------------"
1086                                <<      endl;
1087
1088        // retrieve the extension of the file
1089        std::string fileExt;
1090        std::string completeFileName(nameFileMesh);
1091        for (std::string::reverse_iterator it = completeFileName.rbegin(); it!=completeFileName.rend(); it++)
1092                if (*it=='.')
1093                        break;
1094                else
1095                        fileExt += *it;
1096
1097        std::transform(fileExt.begin(), fileExt.end(), fileExt.begin(), std::toupper);
1098        reverse(fileExt.begin(),fileExt.end());
1099       
1100        geoMesh =       NULL;
1101        if (lodstripsdata)
1102                delete lodstripsdata;
1103        lodstripsdata=NULL;
1104
1105        if (treesimpseq)
1106                delete treesimpseq;
1107        treesimpseq=NULL;
1108
1109        //      Open the mesh file.
1110        pFile   =       fopen(nameFileMesh, "rb");
1111
1112        if (pFile)
1113        {
1114                //      Initialize the current submesh;
1115                currentSubMesh  =       -1;
1116
1117                //      Initialize the return value.
1118                geoMesh =       new     Mesh();
1119
1120                if (fileExt==std::string("OBJ"))
1121                {
1122                        mError  =       false;
1123                        importOBJ(pFile,geoMesh);
1124                }
1125                else
1126                {
1127                        //      Count the submeshes
1128                        //      and next build the geomesh.
1129                        for (int option = 0; option < 2;option++)
1130                        {
1131                                //      Initialize Error.
1132                                mError  =       false;
1133               
1134                                fread(&uno,sizeof(unsigned short),1,pFile);
1135
1136                                if (uno != M_HEADER)
1137                                {
1138                                        //      Debug.
1139                                        cout    <<      "Error: Header not found."
1140                                                <<      endl;
1141
1142                                        //      Error.
1143                                        mError  =       true;
1144                                }
1145
1146                                // Read version.
1147                                fgets(version,255,pFile);
1148
1149                                cout    <<      version <<      endl;
1150
1151                                if (strcmp(version,"[MeshSerializer_v1.30]\n"))
1152                                {
1153                                        //      Debug.
1154                                        cout    <<      "Error: Wrong mesh version."
1155                                                <<      endl
1156                                                <<      "Only version 1.3 or older allowed."
1157                                                <<      endl;
1158
1159                                        //      Error.
1160                                        mError  =       true;
1161                                }
1162
1163                                while(!feof(pFile))
1164                                {
1165                                        chunkID = readChunk(pFile);
1166
1167                                        switch (chunkID)
1168                                        {
1169                                                case M_MESH:
1170                                                        readMesh(pFile, geoMesh, option);
1171                                                        break;
1172                                        }
1173                                }
1174
1175                                //      Create the submesh array.
1176                                if (option == SUBMESH_COUNT)
1177                                {
1178                                        geoMesh->mSubMesh       = new SubMesh[geoMesh->mSubMeshCount];
1179                                }
1180
1181                                //      Move the curso to the begining of the file.
1182                                fseek(pFile,0,SEEK_SET);
1183                        }
1184
1185                        //      Goes to the end of the file.
1186                        fseek(pFile,0,SEEK_END);
1187
1188                        //      Gets the size of the file.
1189                        mFileSize       =       ftell(pFile);
1190                }
1191
1192                // Close the mesh file.
1193                fclose(pFile);
1194
1195                //      If no error.
1196                if (!mError)
1197                {
1198                        for (int submesh = 0;   submesh < geoMesh->mSubMeshCount; submesh++)
1199                        {
1200                                //      Gets the actual submesh.
1201                                geosubmesh      =       &geoMesh->mSubMesh[submesh];
1202
1203                                if (geosubmesh->mType == Geometry::GEO_TRIANGLE_STRIPS)
1204                                {
1205                                        //      Fill the strips list.
1206                                        geosubmesh      =       BuildStripsGeoSubMesh(geosubmesh);
1207                                }
1208                        }
1209
1210                        //      Sets coods between -1 and 1.
1211                        normalizeModel(geoMesh);
1212                }
1213        }
1214        else
1215        {
1216                //      Debug.
1217                cout    <<      "Error: File not found."
1218                                        <<      endl;
1219
1220                //      File not found.
1221                mError  =       true;
1222        }
1223
1224        //      If an error happens.
1225        if (mError)
1226        {
1227                delete  geoMesh;
1228               
1229                geoMesh =       NULL;
1230        }
1231       
1232        return  geoMesh;
1233}
1234
1235//---------------------------------------------------------------------------
1236//      Sets coords between -1 and 1.
1237//---------------------------------------------------------------------------
1238void    GeoMeshLoader::normalizeModel(Mesh      *geoMesh)
1239{
1240        unsigned        int     i;
1241        float                                   maxx, minx, maxy, miny, maxz, minz;
1242        float                                   cx, cy, cz, w, h, d, max;
1243        float                                   scale;
1244        VertexBuffer    *vertex_buffer;
1245
1246        //      Gets vertex buffer.
1247        vertex_buffer   =       geoMesh->mSubMesh[0].mVertexBuffer;
1248       
1249        //      Get the max/mins.
1250        maxx = minx = vertex_buffer->mPosition[0].x;
1251        maxy = miny = vertex_buffer->mPosition[0].y;
1252        maxz = minz = vertex_buffer->mPosition[0].z;
1253       
1254        //      For each submesh.
1255        for (int submesh = 0; submesh < geoMesh->mSubMeshCount; submesh++)
1256        {
1257                //      Gets the actual submesh.
1258                vertex_buffer   =       geoMesh->mSubMesh[submesh].mVertexBuffer;
1259
1260                //      For each index of the strip.
1261                for (int i = 0; i < vertex_buffer->mVertexCount; i++)
1262                {
1263                        if (maxx < vertex_buffer->mPosition[i].x)
1264                        {
1265                                maxx = vertex_buffer->mPosition[i].x;
1266                        }
1267
1268                        if (minx > vertex_buffer->mPosition[i].x)
1269                        {
1270                                minx = vertex_buffer->mPosition[i].x;
1271                        }
1272
1273                        if (maxy < vertex_buffer->mPosition[i].y)
1274                        {
1275                                maxy = vertex_buffer->mPosition[i].y;
1276                        }
1277
1278                        if (miny > vertex_buffer->mPosition[i].y)
1279                        {
1280                                miny = vertex_buffer->mPosition[i].y;
1281                        }
1282
1283                        if (maxz < vertex_buffer->mPosition[i].z)
1284                        {
1285                                maxz = vertex_buffer->mPosition[i].z;
1286                        }
1287
1288                        if (minz > vertex_buffer->mPosition[i].z)
1289                        {
1290                                minz = vertex_buffer->mPosition[i].z;
1291                        }
1292                }
1293
1294                //      If is a shared vertex Buffer.
1295                if (geoMesh->mSubMesh[submesh].mSharedVertexBuffer)
1296                {
1297                        break;
1298                }
1299        }
1300       
1301        //      Calculate model width, height, and depth.
1302        w = fabs(maxx) + fabs(minx);
1303        h = fabs(maxy) + fabs(miny);
1304        d = fabs(maxz) + fabs(minz);
1305
1306        //      Calculate center of the model.
1307        cx = (maxx + minx) / 2.0;
1308        cy = (maxy + miny) / 2.0;
1309        cz = (maxz + minz) / 2.0;
1310
1311
1312        //      Calculate max dimension.
1313        if (w > h)
1314        {
1315                max     =       w;
1316        }
1317        else
1318        {
1319                max     =       h;
1320        }
1321
1322        if (d > max)
1323        {
1324                max     =       d;
1325        }
1326       
1327        //      Calculate unitizing scale factor.
1328        scale = 1.0 / max;
1329
1330        geoMesh->mMeshBounds.scaleFactor                =       scale;
1331
1332
1333        bool *sharedmesh;
1334        sharedmesh= new bool[geoMesh->mSubMeshCount];
1335        bool firstsharedmesh= true;
1336        for (int submesh = 0; submesh < geoMesh->mSubMeshCount; submesh++)
1337        {
1338                if (geoMesh->mSubMesh[submesh].mSharedVertexBuffer)
1339                        sharedmesh[submesh]= true;
1340                else
1341                        sharedmesh[submesh]= false;
1342        }
1343
1344        //      Translate around center then scale.
1345        //      For each submesh.
1346        for (int submesh = 0; submesh < geoMesh->mSubMeshCount; submesh++)
1347        {
1348
1349                //      If is a shared vertex Buffer.
1350                if (geoMesh->mSubMesh[submesh].mSharedVertexBuffer)
1351                {
1352                        if (!firstsharedmesh)
1353                                continue;
1354                        else
1355                                firstsharedmesh= false;
1356                }
1357
1358                //      Gets the actual submesh.
1359                vertex_buffer   =       geoMesh->mSubMesh[submesh].mVertexBuffer;
1360
1361                //      For each index of the strip.
1362                for (int i = 0; i < vertex_buffer->mVertexCount; i++)
1363                {
1364                        vertex_buffer->mPosition[i].x -= cx;
1365                        vertex_buffer->mPosition[i].y -= cy;
1366                        vertex_buffer->mPosition[i].z -= cz;
1367                        vertex_buffer->mPosition[i].x *= scale;
1368                        vertex_buffer->mPosition[i].y *= scale;
1369                        vertex_buffer->mPosition[i].z *= scale;
1370                }
1371
1372        }
1373
1374        delete[] sharedmesh;
1375}
1376
1377//---------------------------------------------------------------------------
1378//      Get the size in bytes of the file.
1379//---------------------------------------------------------------------------
1380size_t  GeoMeshLoader::getFileSize()
1381{
1382        return  mFileSize;
1383}
1384
1385//---------------------------------------------------------------------------
1386//      Constructor
1387//---------------------------------------------------------------------------
1388GeoMeshLoader::GeoMeshLoader()
1389{
1390        geoMesh                 =       NULL;
1391        mFileSize               =       0;
1392        lodstripsdata   =       NULL;
1393        treesimpseq             =       NULL;
1394}
1395
1396//---------------------------------------------------------------------------
1397//      Destroyer.
1398//---------------------------------------------------------------------------
1399GeoMeshLoader::~GeoMeshLoader()
1400{
1401        if (geoMesh)
1402                delete  geoMesh;
1403        if (lodstripsdata)
1404                delete lodstripsdata;
1405        if (treesimpseq)
1406                delete treesimpseq;
1407}
1408
1409//---------------------------------------------------------------------------
1410//      Read bones of the submesh.
1411//---------------------------------------------------------------------------
1412void GeoMeshLoader::readSubMeshBoneAssignment(FILE* f, SubMesh* geoSubMesh,int option)
1413{
1414        if (option == GEOMESH_BUILD)
1415        {
1416                VertexBoneAssignment assign;
1417
1418                // unsigned int vertexIndex;
1419                fread(&(assign.vertexIndex),sizeof(unsigned int),1,f);
1420                // unsigned short boneIndex;
1421                fread(&(assign.boneIndex),sizeof(unsigned short),1,f);
1422                // float weight
1423                fread(&(assign.weight),sizeof(float),1,f);
1424
1425                geoSubMesh->mBones.push_back(assign);
1426        }
1427}
1428
1429//---------------------------------------------------------------------------
1430//      Read bones of the main mesh.
1431//---------------------------------------------------------------------------
1432void GeoMeshLoader::readMeshBoneAssignment(FILE* f, Mesh* geoMesh,int option)
1433{
1434        if (option == GEOMESH_BUILD)
1435        {
1436                VertexBoneAssignment assign;
1437
1438                // unsigned int vertexIndex;
1439                fread(&(assign.vertexIndex),sizeof(unsigned int),1,f);
1440                // unsigned short boneIndex;
1441                fread(&(assign.boneIndex),sizeof(unsigned short),1,f);
1442                // float weight
1443                fread(&(assign.weight),sizeof(float),1,f);
1444
1445
1446                geoMesh->mBones.push_back(assign);
1447        }
1448}
1449
1450//---------------------------------------------------------------------------
1451//      Read skeleton link.
1452//---------------------------------------------------------------------------
1453void GeoMeshLoader::readSkeletonLink(FILE* f, Mesh* geoMesh,int option)
1454{
1455        if (option == GEOMESH_BUILD)
1456        {
1457                fgets(geoMesh->mSkeletonName,255,f);
1458               
1459                geoMesh->hasSkeleton    =       true;
1460
1461                //      Debug.
1462                cout    <<      "Skeleton Name: "
1463                                        <<      geoMesh->mSkeletonName
1464                                        <<      endl;
1465        }
1466}
1467
1468//---------------------------------------------------------------------------
1469//      Read bounding box settings.
1470//---------------------------------------------------------------------------
1471void    GeoMeshLoader::readMeshBounds(FILE      *f, Mesh        *geoMesh,       int     option)
1472{
1473        if (option == GEOMESH_BUILD)
1474        {
1475                fread(&(geoMesh->mMeshBounds.minX),sizeof(float),1,f);
1476                fread(&(geoMesh->mMeshBounds.minY),sizeof(float),1,f);
1477                fread(&(geoMesh->mMeshBounds.minZ),sizeof(float),1,f);
1478                fread(&(geoMesh->mMeshBounds.maxX),sizeof(float),1,f);
1479                fread(&(geoMesh->mMeshBounds.maxY),sizeof(float),1,f);
1480                fread(&(geoMesh->mMeshBounds.maxZ),sizeof(float),1,f);
1481                fread(&(geoMesh->mMeshBounds.radius),sizeof(float),1,f);
1482        }
1483}
1484
1485struct face_t
1486{
1487        int v1,v2,v3;
1488        int t1,t2,t3;
1489        int n1,n2,n3;
1490};
1491
1492class VertexArranger
1493{
1494public:
1495        VertexArranger(Geometry::Mesh *m){
1496                mesh=m;
1497                current_submesh=0;
1498                current_tris=new int[m->mSubMeshCount];
1499                for (int i=0; i<m->mSubMeshCount; i++)
1500                        current_tris[i] = 0;
1501        }
1502        ~VertexArranger(void){
1503                delete[] current_tris;
1504        }
1505
1506        void AddFace(int v1, int v2, int v3, int t1, int t2, int t3, int n1, int n2, int n3){
1507                Geometry::SubMesh *submesh = mesh->mSubMesh + current_submesh;
1508
1509                vertex_arranger_node vertex1(v1,n1,t1);
1510                vertex_arranger_node vertex2(v2,n2,t2);
1511                vertex_arranger_node vertex3(v3,n3,t3);
1512               
1513                int j = current_tris[current_submesh];
1514
1515                std::map<vertex_arranger_node,int>::iterator res;
1516                res=vertex_map.find(vertex1);
1517                if (res==vertex_map.end())
1518                {
1519                        int val = vertex_map.size();
1520                        vertex_map[vertex1] = val;
1521                        submesh->mIndex[j*3+0] = val;
1522                }
1523                else
1524                        submesh->mIndex[j*3+0] = res->second;
1525
1526                res=vertex_map.find(vertex2);
1527                if (res==vertex_map.end())
1528                {
1529                        int val = vertex_map.size();
1530                        vertex_map[vertex2] = val;
1531                        submesh->mIndex[j*3+1] = val;
1532                }
1533                else
1534                        submesh->mIndex[j*3+1] = res->second;
1535
1536                res=vertex_map.find(vertex3);
1537                if (res==vertex_map.end())
1538                {
1539                        int val = vertex_map.size();
1540                        vertex_map[vertex3] = val;
1541                        submesh->mIndex[j*3+2] = val;
1542                }
1543                else
1544                        submesh->mIndex[j*3+2] = res->second;
1545
1546                current_tris[current_submesh] ++;
1547        }
1548
1549        int GetVertexCount(void) const { return vertex_map.size(); }
1550
1551        void SetCurrentSubMesh(int i){ current_submesh = i; }
1552       
1553        class vertex_arranger_node
1554        {
1555        public:
1556                int v, n, t;
1557
1558                vertex_arranger_node(void){
1559                        v=n=t=-1;
1560                }
1561                vertex_arranger_node(int iv, int in=-1, int it=-1){
1562                        v=iv;
1563                        n=in;
1564                        t=it;
1565                }
1566
1567                bool operator<(const vertex_arranger_node &vu) const {
1568                        if (v<vu.v) return true;
1569                        if (v>vu.v) return false;
1570                        if (n<vu.n) return true;
1571                        if (n>vu.n) return false;
1572                        if (t<vu.t) return true;
1573                        if (t>vu.t) return false;
1574                        return false;
1575                }
1576                bool operator==(const vertex_arranger_node &vu) const {
1577                        return (v==vu.v && v==vu.v && n==vu.n && n==vu.n && t==vu.t && t==vu.t);
1578                }       
1579        };
1580
1581/*      VertexArranger::vertex_arranger_node *GetVertexInfo(void) const {
1582                vertex_arranger_node * vertex_list = new vertex_arranger_node[GetVertexCount()];
1583                for (std::map<vertex_arranger_node,int>::const_iterator it=vertex_map.begin(); it!=vertex_map.end(); it++)
1584                        vertex_list[it->second] = it->first;
1585                return vertex_list;
1586        }
1587
1588        const std::vector<int> GetIndexInfo(void) const { return indices; }*/
1589
1590        void Arrange( const std::vector<Geometry::Vector3> & vertices,
1591                                  const std::vector<Geometry::Vector3> & normals,
1592                                  const std::vector<Geometry::Vector2> & texcoords){
1593
1594                mesh->mVertexBuffer=new Geometry::VertexBuffer;
1595                mesh->mVertexBuffer->mVertexCount = GetVertexCount();
1596                mesh->mVertexBuffer->mPosition = new Geometry::Vector3[mesh->mVertexBuffer->mVertexCount];
1597                mesh->mVertexBuffer->mTexCoords = texcoords.empty()?NULL:new Geometry::Vector2[mesh->mVertexBuffer->mVertexCount];
1598                mesh->mVertexBuffer->mNormal = normals.empty()?NULL:new Geometry::Vector3[mesh->mVertexBuffer->mVertexCount];
1599                mesh->mVertexBuffer->mVertexInfo = Geometry::VERTEX_POSITION | (texcoords.empty()?0:Geometry::VERTEX_TEXCOORDS) | (normals.empty()?0:Geometry::VERTEX_NORMAL);
1600
1601                // sort the calculated vertices
1602               
1603                vertex_arranger_node * vertex_list = new vertex_arranger_node[mesh->mVertexBuffer->mVertexCount];
1604                for (std::map<vertex_arranger_node,int>::iterator it=vertex_map.begin(); it!=vertex_map.end(); it++)
1605                        vertex_list[it->second] = it->first;
1606
1607                for (int i=0; i<mesh->mSubMeshCount; i++)
1608                        mesh->mSubMesh[i].mVertexBuffer = mesh->mVertexBuffer;
1609               
1610                for (int j=0; j<mesh->mVertexBuffer->mVertexCount; j++)
1611                {               
1612                        int vi = vertex_list[j].v;
1613                        int ti = vertex_list[j].t;
1614                        int ni = vertex_list[j].n;
1615
1616                        Geometry::Vector3 auxpos(vertices[vi]);
1617                        if (auxpos.x < mesh->mMeshBounds.minX) mesh->mMeshBounds.minX = auxpos.x;
1618                        if (auxpos.y < mesh->mMeshBounds.minY) mesh->mMeshBounds.minY = auxpos.y;
1619                        if (auxpos.z < mesh->mMeshBounds.minZ) mesh->mMeshBounds.minZ = auxpos.z;
1620                        if (auxpos.x > mesh->mMeshBounds.maxX) mesh->mMeshBounds.maxX = auxpos.x;
1621                        if (auxpos.y > mesh->mMeshBounds.maxY) mesh->mMeshBounds.maxY = auxpos.y;
1622                        if (auxpos.z > mesh->mMeshBounds.maxZ) mesh->mMeshBounds.maxZ = auxpos.z;
1623
1624                        mesh->mVertexBuffer->mPosition[j] = auxpos;
1625                        mesh->mVertexBuffer->mNormal[j] = normals[ni];
1626                        if (texcoords.empty()==false)
1627                                mesh->mVertexBuffer->mTexCoords[j] = texcoords[ti];             
1628                }
1629
1630                delete[] vertex_list;
1631        }
1632
1633//private:
1634        std::map<vertex_arranger_node,int> vertex_map;
1635        Geometry::Mesh *mesh;
1636        int current_submesh;
1637        int *current_tris;
1638};
1639
1640
1641void    GeoMeshLoader::importOBJ(FILE *f, Mesh *mesh)
1642{
1643        mesh->hasSkeleton=false;
1644        mesh->mSubMeshCount=0;
1645
1646        std::vector<Geometry::Vector3> vertices;
1647        std::vector<Geometry::Vector3> normals;
1648        std::vector<Geometry::Vector2> texcoords;
1649        std::vector<std::vector<face_t> > faces;
1650        std::vector<face_t> current_faces;
1651
1652        mesh->mMeshBounds.maxX = -99999999.9f;
1653        mesh->mMeshBounds.maxY = -99999999.9f;
1654        mesh->mMeshBounds.maxZ = -99999999.9f;
1655        mesh->mMeshBounds.minX =  99999999.9f;
1656        mesh->mMeshBounds.minY =  99999999.9f;
1657        mesh->mMeshBounds.minZ =  99999999.9f;
1658        mesh->mMeshBounds.radius = 1.0f;
1659        mesh->mMeshBounds.scaleFactor = 1.0f;
1660
1661        char line[256]="";
1662        while(!feof(f))
1663        {
1664                fgets(line,256,f);
1665                if (line[0]=='v' && line[1]==' ')
1666                {
1667                        Geometry::Vector3 v3;
1668                        sscanf(line+2,"%f %f %f",&v3.x,&v3.y,&v3.z);
1669                        vertices.push_back(v3);
1670                }
1671                else if (line[0]=='v' && line[1]=='t')
1672                {
1673                        Geometry::Vector2 v2;
1674                        sscanf(line+2,"%f %f",&v2.x,&v2.y);
1675                        texcoords.push_back(v2);
1676                }
1677                else if (line[0]=='v' && line[1]=='n')
1678                {
1679                        Geometry::Vector3 v3;
1680                        sscanf(line+2,"%f %f %f",&v3.x,&v3.y,&v3.z);
1681                        normals.push_back(v3);
1682                }
1683                else if (line[0]=='f')
1684                {
1685                        face_t auxface;
1686                        auxface.n1=auxface.n2=auxface.n3=auxface.t1=auxface.t2=auxface.t3=auxface.v1=auxface.v2=auxface.v3=0;
1687                        int n = sscanf(line+2,"%d/%d/%d %d/%d/%d %d/%d/%d", &auxface.v1,&auxface.t1,&auxface.n1,
1688                                                                                                                            &auxface.v2,&auxface.t2,&auxface.n2,
1689                                                                                                                                &auxface.v3,&auxface.t3,&auxface.n3);
1690                        if (n<9)
1691                        {
1692                                auxface.n1=auxface.n2=auxface.n3=auxface.t1=auxface.t2=auxface.t3=auxface.v1=auxface.v2=auxface.v3=0;
1693                                n = sscanf(line+2,"%d//%d %d//%d %d//%d", &auxface.v1,&auxface.n1,
1694                                                                                                                  &auxface.v2,&auxface.n2,
1695                                                                                                                  &auxface.v3,&auxface.n3);
1696                                if (n<6)
1697                                {
1698                                        auxface.n1=auxface.n2=auxface.n3=auxface.t1=auxface.t2=auxface.t3=auxface.v1=auxface.v2=auxface.v3=0;
1699                                        n = sscanf(line+2,"%d/%d %d/%d %d/%d", &auxface.v1,&auxface.t1,
1700                                                                                                                   &auxface.v2,&auxface.t2,
1701                                                                                                                   &auxface.v3,&auxface.t3);
1702                                        if (n<6)
1703                                        {
1704                                                auxface.n1=auxface.n2=auxface.n3=auxface.t1=auxface.t2=auxface.t3=auxface.v1=auxface.v2=auxface.v3=0;
1705                                                n = sscanf(line+2,"%d %d %d", &auxface.v1,&auxface.v2,&auxface.v3);
1706                                        }
1707                                }
1708                        }
1709
1710                        auxface.v1=abs(auxface.v1); auxface.v2=abs(auxface.v2); auxface.v3=abs(auxface.v3);
1711                        auxface.t1=abs(auxface.t1); auxface.t2=abs(auxface.t2); auxface.t3=abs(auxface.t3);
1712                        auxface.n1=abs(auxface.n1); auxface.n2=abs(auxface.n2); auxface.n3=abs(auxface.n3);
1713                        auxface.v1--; auxface.v2--; auxface.v3--;
1714                        auxface.t1--; auxface.t2--; auxface.t3--;
1715                        auxface.n1--; auxface.n2--; auxface.n3--;
1716                        current_faces.push_back(auxface);
1717                }
1718                else if (line[0]=='g')
1719                {
1720                        if (current_faces.size()>0)
1721                                faces.push_back(current_faces);
1722                        current_faces.clear();
1723                }
1724        }
1725
1726        if (current_faces.size()>0)
1727                faces.push_back(current_faces);
1728        current_faces.clear();
1729
1730        mesh->mSubMeshCount = faces.size();
1731        bool found_texcoords=!texcoords.empty();
1732
1733        if (normals.empty())
1734        {
1735                // calculate face normals
1736                for (int i=0, inormal=0; i<mesh->mSubMeshCount; i++)
1737                {
1738                        Geometry::SubMesh *submesh = mesh->mSubMesh+i;
1739                         std::vector<face_t> & vecfaces = faces[i];
1740                        int j=0;
1741                        for (std::vector<face_t>::iterator it=vecfaces.begin(); it!=vecfaces.end(); it++,j++,inormal++)
1742                        {
1743                                face_t & auxface = *it;
1744                                auxface.n1 = inormal;
1745                                auxface.n2 = inormal;
1746                                auxface.n3 = inormal;
1747                                Geometry::Vector3 v1,v2,v3,v31,v21,nor;
1748                                v1 = vertices[auxface.v1];
1749                                v2 = vertices[auxface.v2];
1750                                v3 = vertices[auxface.v3];
1751                                v31 = v3 - v1;
1752                                v21 = v2 - v1;
1753                                nor = v21.crossProduct(v31);
1754                                nor.normalise();
1755                                normals.push_back(nor);
1756                        }                       
1757                }
1758        }
1759
1760        // fill up the mesh structure with the loaded information
1761
1762        VertexArranger vertex_arranger(mesh);
1763                 
1764        mesh->mSubMesh=new Geometry::SubMesh[mesh->mSubMeshCount];
1765        for (int i=0; i<mesh->mSubMeshCount; i++)
1766        {
1767                Geometry::SubMesh *submesh = mesh->mSubMesh+i;
1768                int j=0;
1769                const std::vector<face_t> & vecfaces = faces[i];
1770                std::vector<Geometry::Index> aux_indices;
1771                submesh->mSharedVertexBuffer = true;
1772                submesh->mIndexCount = vecfaces.size()*3;
1773                submesh->mIndex=new Geometry::Index[submesh->mIndexCount];
1774
1775                vertex_arranger.SetCurrentSubMesh(i);
1776               
1777                for (std::vector<face_t>::const_iterator it=vecfaces.begin(); it!=vecfaces.end(); it++,j++)
1778                {
1779                        const face_t & auxface = *it;
1780
1781                        vertex_arranger.AddFace(auxface.v1,auxface.v2,auxface.v3,
1782                                                                        auxface.t1,auxface.t2,auxface.t3,
1783                                                                        auxface.n1,auxface.n2,auxface.n3);
1784                }                       
1785        }
1786
1787        vertex_arranger.Arrange(vertices,normals,texcoords);
1788}
1789
Note: See TracBrowser for help on using the repository browser.