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

Revision 1136, 43.2 KB checked in by gumbau, 18 years ago (diff)
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        size_t                                          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        size_t                                  i;
165        //float                                         aux;
166        size_t                                  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(size_t 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 (size_t     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 (size_t     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        size_t  strip_count;
869        size_t  tailIndex;
870        //size_t        tail;
871
872        head_found                                                      =       false;
873        tail_found                                                      =       false;
874        geoSubMesh->mStripCount =       1;
875
876        //      Foreachone of the indices.
877        //      Obtains the number of triangle strips.
878        for (size_t     i = 0; i < (geoSubMesh->mIndexCount - 1); i++)
879        {
880                if (geoSubMesh->mIndex[i] == geoSubMesh->mIndex[i+1])
881                {
882                        if (head_found)
883                        {
884                                tail_found      =       true;
885                        }
886                        else
887                        {
888                                head_found      =       true;
889                        }
890
891                        //      Jump one index.
892                        i++;
893                }
894                else
895                {
896                        //      Increments the number of triangle strips.
897                        if (tail_found)
898                        {
899                                geoSubMesh->mStripCount++;
900                        }
901
902                        head_found      =       false;
903                        tail_found      =       false;
904                }
905        }
906
907        geoSubMesh->mStrip      =       (Index**) malloc(       sizeof(Index*)
908                                                                                                *
909                                                                                                geoSubMesh->mStripCount);
910
911        //      Number of strips. Initially there is one triangle strip.
912        strip_count     =       1;
913        head_found      =       false;
914        tail_found      =       false;
915
916        //      Initialize the fist triangle strip.
917        geoSubMesh->mStrip[0]   =       &geoSubMesh->mIndex[0];
918
919        //      Foreachone of the indices.
920        //      Assigns the beginning of the triangle strips.
921        for(size_t      i = 0;i < (geoSubMesh->mIndexCount - 1); i++)
922        {
923                if(geoSubMesh->mIndex[i] == geoSubMesh->mIndex[i+1])
924                {
925                        if(head_found)
926                        {
927                                if (!tail_found)
928                                {
929                                        tailIndex               =       i;
930                                }
931
932                                tail_found      =       true;
933                        }
934                        else
935                        {
936                                head_found      =       true;
937                        }
938
939                        //      Jump one index.
940                        i++;
941                }
942                else
943                {
944                        //      Increments the number of triangle strips.
945                        if(tail_found)
946                        {
947                                geoSubMesh->mStrip[strip_count++]       =       &geoSubMesh->mIndex[tailIndex];
948                        }
949
950                        head_found      =       false;
951                        tail_found      =       false;
952                }
953        }
954
955        //      Remove degenerate triangles of a submesh given.
956        //geoSubMesh    =       removeDegenerateTriangles(geoSubMesh);
957
958        return  geoSubMesh;
959}
960
961//---------------------------------------------------------------------------
962//      Remove degenerate triangles of a submesh given.
963//---------------------------------------------------------------------------
964SubMesh *       GeoMeshLoader::removeDegenerateTriangles(SubMesh        *geoSubMesh)
965{
966        Index           *indices;
967        Index           *index;
968        Index           *indexBegin;
969        Index           *indexEnd;
970        Index           *new_strip_starts;
971        size_t  new_index_count;
972        size_t  current_index;
973
974        //      Stores the new starts of strips.
975        new_strip_starts        =       new     Index[geoSubMesh->mStripCount];
976       
977        //      Calculate the new index count.
978        new_index_count =       geoSubMesh->mIndexCount
979                -
980                (2 * geoSubMesh->mStripCount)
981                +
982                2;
983
984        //      Auxiliar index array.
985        indices =       new     Index[new_index_count];
986
987        //      Initialize the current index.
988        current_index   =       0;
989       
990        //      For each one of the strips.
991        for (size_t     strip = 0; strip < geoSubMesh->mStripCount; strip++)
992        {
993                //      Stars of strip without degenerate triangles.
994                new_strip_starts[strip] =       (Index)current_index;
995               
996                //      First index of the strip.
997                indexBegin      =       geoSubMesh->mStrip[strip];
998
999                //      If is the final strip
1000                if (strip       == (geoSubMesh->mStripCount - 1))
1001                {
1002                        //      The end of the index array.
1003                        indexEnd        = &geoSubMesh->mIndex[geoSubMesh->mIndexCount];
1004                }
1005                else
1006                {
1007                        //      The beginning of the next strip.
1008                        indexEnd        = geoSubMesh->mStrip[strip + 1];
1009                }
1010
1011                int i;
1012                i       = 0;
1013
1014                //      If is not the first strip.
1015                if (strip != 0)
1016                {
1017                        indexBegin++;
1018                }
1019
1020                //      If is not the last strip.
1021                if (strip       != (geoSubMesh->mStripCount - 1))
1022                {
1023                        indexEnd--;
1024                }
1025
1026                //      For each index of the strip.
1027                for (index = indexBegin; index < indexEnd; index++)
1028                {
1029                        indices[current_index++]        =       indexBegin[i];
1030
1031                        //      Increments i.
1032                        i++;
1033                }
1034
1035        }
1036
1037        //      Free Index memory.
1038        delete  []geoSubMesh->mIndex;
1039
1040        //      Update index count.
1041        geoSubMesh->mIndexCount =       new_index_count;
1042
1043        geoSubMesh->mIndex      =       new     Index[new_index_count];
1044
1045        //      Store new index array without degenerate triangles.
1046        for (size_t     i       =       0;      i       <       geoSubMesh->mIndexCount; i++)
1047        {
1048                geoSubMesh->mIndex[i]   =       indices[i];
1049        }
1050
1051        //      Free auxiliar index array;
1052        delete  []indices;
1053
1054        //      Update start of the strip.
1055        for (size_t     strip   =       0; strip < geoSubMesh->mStripCount; strip++)
1056        {
1057                geoSubMesh->mStrip[strip]       =       &geoSubMesh->mIndex[new_strip_starts[strip]];
1058        }
1059
1060        //      Free auxiliar strip starts.
1061        delete  []new_strip_starts;
1062       
1063        return  geoSubMesh;
1064}
1065
1066//---------------------------------------------------------------------------
1067//      Loads a mesh.
1068//---------------------------------------------------------------------------
1069Mesh* GeoMeshLoader::load(char  *nameFileMesh)
1070{
1071        unsigned        short   uno;
1072        unsigned        short   chunkID;
1073        char            version[255];
1074        FILE            *pFile;
1075        SubMesh         *geosubmesh;
1076
1077        //      Debug.
1078        cout    <<      "---------------------------------"
1079                                <<      endl
1080                                <<      "\t LOAD MESH"
1081                                <<      endl
1082                                <<      "---------------------------------"
1083                                <<      endl;
1084
1085        // retrieve the extension of the file
1086        std::string fileExt;
1087        std::string completeFileName(nameFileMesh);
1088        for (std::string::reverse_iterator it = completeFileName.rbegin(); it!=completeFileName.rend(); it++)
1089                if (*it=='.')
1090                        break;
1091                else
1092                        fileExt += *it;
1093
1094        std::transform(fileExt.begin(), fileExt.end(), fileExt.begin(), std::toupper);
1095        reverse(fileExt.begin(),fileExt.end());
1096       
1097        geoMesh =       NULL;
1098        if (lodstripsdata)
1099                delete lodstripsdata;
1100        lodstripsdata=NULL;
1101
1102        if (treesimpseq)
1103                delete treesimpseq;
1104        treesimpseq=NULL;
1105
1106        //      Open the mesh file.
1107        pFile   =       fopen(nameFileMesh, "rb");
1108
1109        if (pFile)
1110        {
1111                //      Initialize the current submesh;
1112                currentSubMesh  =       -1;
1113
1114                //      Initialize the return value.
1115                geoMesh =       new     Mesh();
1116
1117                if (fileExt==std::string("OBJ"))
1118                {
1119                        mError  =       false;
1120                        importOBJ(pFile,geoMesh);
1121                }
1122                else
1123                {
1124                        //      Count the submeshes
1125                        //      and next build the geomesh.
1126                        for (int option = 0; option < 2;option++)
1127                        {
1128                                //      Initialize Error.
1129                                mError  =       false;
1130               
1131                                fread(&uno,sizeof(unsigned short),1,pFile);
1132
1133                                if (uno != M_HEADER)
1134                                {
1135                                        //      Debug.
1136                                        cout    <<      "Error: Header not found."
1137                                                <<      endl;
1138
1139                                        //      Error.
1140                                        mError  =       true;
1141                                }
1142
1143                                // Read version.
1144                                fgets(version,255,pFile);
1145
1146                                cout    <<      version <<      endl;
1147
1148                                if (strcmp(version,"[MeshSerializer_v1.30]\n"))
1149                                {
1150                                        //      Debug.
1151                                        cout    <<      "Error: Wrong mesh version."
1152                                                <<      endl
1153                                                <<      "Only version 1.3 or older allowed."
1154                                                <<      endl;
1155
1156                                        //      Error.
1157                                        mError  =       true;
1158                                }
1159
1160                                while(!feof(pFile))
1161                                {
1162                                        chunkID = readChunk(pFile);
1163
1164                                        switch (chunkID)
1165                                        {
1166                                                case M_MESH:
1167                                                        readMesh(pFile, geoMesh, option);
1168                                                        break;
1169                                        }
1170                                }
1171
1172                                //      Create the submesh array.
1173                                if (option == SUBMESH_COUNT)
1174                                {
1175                                        geoMesh->mSubMesh       = new SubMesh[geoMesh->mSubMeshCount];
1176                                }
1177
1178                                //      Move the curso to the begining of the file.
1179                                fseek(pFile,0,SEEK_SET);
1180                        }
1181
1182                        //      Goes to the end of the file.
1183                        fseek(pFile,0,SEEK_END);
1184
1185                        //      Gets the size of the file.
1186                        mFileSize       =       ftell(pFile);
1187                }
1188
1189                // Close the mesh file.
1190                fclose(pFile);
1191
1192                //      If no error.
1193                if (!mError)
1194                {
1195                        for (size_t     submesh = 0;    submesh < geoMesh->mSubMeshCount; submesh++)
1196                        {
1197                                //      Gets the actual submesh.
1198                                geosubmesh      =       &geoMesh->mSubMesh[submesh];
1199
1200                                if (geosubmesh->mType == Geometry::GEO_TRIANGLE_STRIPS)
1201                                {
1202                                        //      Fill the strips list.
1203                                        geosubmesh      =       BuildStripsGeoSubMesh(geosubmesh);
1204                                }
1205                        }
1206
1207                        //      Sets coods between -1 and 1.
1208                        normalizeModel(geoMesh);
1209                }
1210        }
1211        else
1212        {
1213                //      Debug.
1214                cout    <<      "Error: File not found."
1215                                        <<      endl;
1216
1217                //      File not found.
1218                mError  =       true;
1219        }
1220
1221        //      If an error happens.
1222        if (mError)
1223        {
1224                delete  geoMesh;
1225               
1226                geoMesh =       NULL;
1227        }
1228       
1229        return  geoMesh;
1230}
1231
1232//---------------------------------------------------------------------------
1233//      Sets coords between -1 and 1.
1234//---------------------------------------------------------------------------
1235void    GeoMeshLoader::normalizeModel(Mesh      *geoMesh)
1236{
1237        float                                   maxx, minx, maxy, miny, maxz, minz;
1238        float                                   cx, cy, cz, w, h, d, max;
1239        float                                   scale;
1240        VertexBuffer    *vertex_buffer;
1241
1242        //      Gets vertex buffer.
1243        vertex_buffer   =       geoMesh->mSubMesh[0].mVertexBuffer;
1244       
1245        //      Get the max/mins.
1246        maxx = minx = vertex_buffer->mPosition[0].x;
1247        maxy = miny = vertex_buffer->mPosition[0].y;
1248        maxz = minz = vertex_buffer->mPosition[0].z;
1249       
1250        //      For each submesh.
1251        for (size_t     submesh = 0; submesh < geoMesh->mSubMeshCount; submesh++)
1252        {
1253                //      Gets the actual submesh.
1254                vertex_buffer   =       geoMesh->mSubMesh[submesh].mVertexBuffer;
1255
1256                //      For each index of the strip.
1257                for (size_t     i = 0; i < vertex_buffer->mVertexCount; i++)
1258                {
1259                        if (maxx < vertex_buffer->mPosition[i].x)
1260                        {
1261                                maxx = vertex_buffer->mPosition[i].x;
1262                        }
1263
1264                        if (minx > vertex_buffer->mPosition[i].x)
1265                        {
1266                                minx = vertex_buffer->mPosition[i].x;
1267                        }
1268
1269                        if (maxy < vertex_buffer->mPosition[i].y)
1270                        {
1271                                maxy = vertex_buffer->mPosition[i].y;
1272                        }
1273
1274                        if (miny > vertex_buffer->mPosition[i].y)
1275                        {
1276                                miny = vertex_buffer->mPosition[i].y;
1277                        }
1278
1279                        if (maxz < vertex_buffer->mPosition[i].z)
1280                        {
1281                                maxz = vertex_buffer->mPosition[i].z;
1282                        }
1283
1284                        if (minz > vertex_buffer->mPosition[i].z)
1285                        {
1286                                minz = vertex_buffer->mPosition[i].z;
1287                        }
1288                }
1289
1290                //      If is a shared vertex Buffer.
1291                if (geoMesh->mSubMesh[submesh].mSharedVertexBuffer)
1292                {
1293                        break;
1294                }
1295        }
1296       
1297        //      Calculate model width, height, and depth.
1298        w = fabs(maxx) + fabs(minx);
1299        h = fabs(maxy) + fabs(miny);
1300        d = fabs(maxz) + fabs(minz);
1301
1302        //      Calculate center of the model.
1303        cx = (maxx + minx) / 2.0f;
1304        cy = (maxy + miny) / 2.0f;
1305        cz = (maxz + minz) / 2.0f;
1306
1307
1308        //      Calculate max dimension.
1309        if (w > h)
1310        {
1311                max     =       w;
1312        }
1313        else
1314        {
1315                max     =       h;
1316        }
1317
1318        if (d > max)
1319        {
1320                max     =       d;
1321        }
1322       
1323        //      Calculate unitizing scale factor.
1324        scale = 1.0f / max;
1325
1326        geoMesh->mMeshBounds.scaleFactor                =       scale;
1327
1328
1329        bool    *sharedmesh;
1330
1331        sharedmesh      =       new bool[geoMesh->mSubMeshCount];
1332
1333        bool    firstsharedmesh =       true;
1334
1335        for (size_t     submesh = 0; submesh < geoMesh->mSubMeshCount; submesh++)
1336        {
1337                if (geoMesh->mSubMesh[submesh].mSharedVertexBuffer)
1338                {
1339                        sharedmesh[submesh]     =       true;
1340                }
1341                else
1342                {
1343                        sharedmesh[submesh]     =       false;
1344                }
1345        }
1346
1347        //      Translate around center then scale.
1348        //      For each submesh.
1349        for (size_t     submesh = 0; submesh < geoMesh->mSubMeshCount; submesh++)
1350        {
1351                //      If is a shared vertex Buffer.
1352                if (geoMesh->mSubMesh[submesh].mSharedVertexBuffer)
1353                {
1354                        if (!firstsharedmesh)
1355                        {
1356                                continue;
1357                        }
1358                        else
1359                        {
1360                                firstsharedmesh =       false;
1361                        }
1362                }
1363
1364                //      Gets the actual submesh.
1365                vertex_buffer   =       geoMesh->mSubMesh[submesh].mVertexBuffer;
1366
1367                //      For each index of the strip.
1368                for (size_t     i       =       0;      i < vertex_buffer->mVertexCount;        i++)
1369                {
1370                        vertex_buffer->mPosition[i].x -= cx;
1371                        vertex_buffer->mPosition[i].y -= cy;
1372                        vertex_buffer->mPosition[i].z -= cz;
1373                        vertex_buffer->mPosition[i].x *= scale;
1374                        vertex_buffer->mPosition[i].y *= scale;
1375                        vertex_buffer->mPosition[i].z *= scale;
1376                }
1377        }
1378
1379        delete[] sharedmesh;
1380}
1381
1382//---------------------------------------------------------------------------
1383//      Get the size in bytes of the file.
1384//---------------------------------------------------------------------------
1385size_t  GeoMeshLoader::getFileSize()
1386{
1387        return  mFileSize;
1388}
1389
1390//---------------------------------------------------------------------------
1391//      Constructor
1392//---------------------------------------------------------------------------
1393GeoMeshLoader::GeoMeshLoader()
1394{
1395        geoMesh                         =       NULL;
1396        mFileSize                       =       0;
1397        lodstripsdata   =       NULL;
1398        treesimpseq             =       NULL;
1399}
1400
1401//---------------------------------------------------------------------------
1402//      Destroyer.
1403//---------------------------------------------------------------------------
1404GeoMeshLoader::~GeoMeshLoader()
1405{
1406        if (geoMesh)
1407        {
1408                delete  geoMesh;
1409        }
1410
1411        if (lodstripsdata)
1412        {
1413                delete lodstripsdata;
1414        }
1415
1416        if (treesimpseq)
1417        {
1418                delete treesimpseq;
1419        }
1420}
1421
1422//---------------------------------------------------------------------------
1423//      Read bones of the submesh.
1424//---------------------------------------------------------------------------
1425void GeoMeshLoader::readSubMeshBoneAssignment(FILE* f,
1426                                                                                                                                                                                        SubMesh* geoSubMesh,
1427                                                                                                                                                                                        int option)
1428{
1429        if (option == GEOMESH_BUILD)
1430        {
1431                VertexBoneAssignment assign;
1432
1433                // unsigned int vertexIndex;
1434                fread(&(assign.vertexIndex),sizeof(unsigned int),1,f);
1435                // unsigned short boneIndex;
1436                fread(&(assign.boneIndex),sizeof(unsigned short),1,f);
1437                // float weight
1438                fread(&(assign.weight),sizeof(float),1,f);
1439
1440                geoSubMesh->mBones.push_back(assign);
1441        }
1442}
1443
1444//---------------------------------------------------------------------------
1445//      Read bones of the main mesh.
1446//---------------------------------------------------------------------------
1447void GeoMeshLoader::readMeshBoneAssignment(FILE* f, Mesh* geoMesh,int option)
1448{
1449        if (option == GEOMESH_BUILD)
1450        {
1451                VertexBoneAssignment assign;
1452
1453                // unsigned int vertexIndex;
1454                fread(&(assign.vertexIndex),sizeof(unsigned int),1,f);
1455                // unsigned short boneIndex;
1456                fread(&(assign.boneIndex),sizeof(unsigned short),1,f);
1457                // float weight
1458                fread(&(assign.weight),sizeof(float),1,f);
1459
1460                geoMesh->mBones.push_back(assign);
1461        }
1462}
1463
1464//---------------------------------------------------------------------------
1465//      Read skeleton link.
1466//---------------------------------------------------------------------------
1467void GeoMeshLoader::readSkeletonLink(FILE* f, Mesh* geoMesh,int option)
1468{
1469        if (option == GEOMESH_BUILD)
1470        {
1471                fgets(geoMesh->mSkeletonName,255,f);
1472               
1473                geoMesh->hasSkeleton    =       true;
1474
1475                //      Debug.
1476                cout    <<      "Skeleton Name: "
1477                                        <<      geoMesh->mSkeletonName
1478                                        <<      endl;
1479        }
1480}
1481
1482//---------------------------------------------------------------------------
1483//      Read bounding box settings.
1484//---------------------------------------------------------------------------
1485void    GeoMeshLoader::readMeshBounds(FILE      *f, Mesh        *geoMesh,       int     option)
1486{
1487        if (option == GEOMESH_BUILD)
1488        {
1489                fread(&(geoMesh->mMeshBounds.minX),sizeof(float),1,f);
1490                fread(&(geoMesh->mMeshBounds.minY),sizeof(float),1,f);
1491                fread(&(geoMesh->mMeshBounds.minZ),sizeof(float),1,f);
1492                fread(&(geoMesh->mMeshBounds.maxX),sizeof(float),1,f);
1493                fread(&(geoMesh->mMeshBounds.maxY),sizeof(float),1,f);
1494                fread(&(geoMesh->mMeshBounds.maxZ),sizeof(float),1,f);
1495                fread(&(geoMesh->mMeshBounds.radius),sizeof(float),1,f);
1496        }
1497}
1498
1499struct face_t
1500{
1501        int v1,v2,v3;
1502        int t1,t2,t3;
1503        int n1,n2,n3;
1504};
1505
1506class VertexArranger
1507{
1508public:
1509
1510        VertexArranger(Geometry::Mesh *m)
1511        {
1512                mesh                                            =       m;
1513                current_submesh =       0;
1514                current_tris            =       new int[m->mSubMeshCount];
1515
1516                for (size_t     i       =       0;      i < m->mSubMeshCount;   i++)
1517                {
1518                        current_tris[i] =       0;
1519                }
1520        }
1521
1522        ~VertexArranger(void)
1523        {
1524                delete[] current_tris;
1525        }
1526
1527        void AddFace(int v1, int v2, int v3, int t1, int t2, int t3, int n1, int n2, int n3){
1528                Geometry::SubMesh *submesh = mesh->mSubMesh + current_submesh;
1529
1530                vertex_arranger_node vertex1(v1,n1,t1);
1531                vertex_arranger_node vertex2(v2,n2,t2);
1532                vertex_arranger_node vertex3(v3,n3,t3);
1533               
1534                int j = current_tris[current_submesh];
1535
1536                std::map<vertex_arranger_node,int>::iterator res;
1537                res=vertex_map.find(vertex1);
1538                if (res==vertex_map.end())
1539                {
1540                        int val = (int)vertex_map.size();
1541                        vertex_map[vertex1] = val;
1542                        submesh->mIndex[j*3+0] = val;
1543                }
1544                else
1545                        submesh->mIndex[j*3+0] = res->second;
1546
1547                res=vertex_map.find(vertex2);
1548                if (res==vertex_map.end())
1549                {
1550                        int val = (int)vertex_map.size();
1551                        vertex_map[vertex2] = val;
1552                        submesh->mIndex[j*3+1] = val;
1553                }
1554                else
1555                        submesh->mIndex[j*3+1] = res->second;
1556
1557                res=vertex_map.find(vertex3);
1558                if (res==vertex_map.end())
1559                {
1560                        int val = (int)vertex_map.size();
1561                        vertex_map[vertex3] = val;
1562                        submesh->mIndex[j*3+2] = val;
1563                }
1564                else
1565                {
1566                        submesh->mIndex[j*3+2] = res->second;
1567                }
1568
1569                current_tris[current_submesh] ++;
1570        }
1571
1572        int GetVertexCount(void) const
1573        {
1574                return (int)vertex_map.size();
1575        }
1576
1577        void SetCurrentSubMesh(int i)
1578        {
1579                current_submesh = i;
1580        }
1581       
1582        class vertex_arranger_node
1583        {
1584        public:
1585                int v, n, t;
1586
1587                vertex_arranger_node(void){
1588                        v=n=t=-1;
1589                }
1590                vertex_arranger_node(int iv, int in=-1, int it=-1){
1591                        v=iv;
1592                        n=in;
1593                        t=it;
1594                }
1595
1596                bool operator<(const vertex_arranger_node &vu) const {
1597                        if (v<vu.v) return true;
1598                        if (v>vu.v) return false;
1599                        if (n<vu.n) return true;
1600                        if (n>vu.n) return false;
1601                        if (t<vu.t) return true;
1602                        if (t>vu.t) return false;
1603                        return false;
1604                }
1605                bool operator==(const vertex_arranger_node &vu) const {
1606                        return (v==vu.v && v==vu.v && n==vu.n && n==vu.n && t==vu.t && t==vu.t);
1607                }       
1608        };
1609
1610/*      VertexArranger::vertex_arranger_node *GetVertexInfo(void) const {
1611                vertex_arranger_node * vertex_list = new vertex_arranger_node[GetVertexCount()];
1612                for (std::map<vertex_arranger_node,int>::const_iterator it=vertex_map.begin(); it!=vertex_map.end(); it++)
1613                        vertex_list[it->second] = it->first;
1614                return vertex_list;
1615        }
1616
1617        const std::vector<int> GetIndexInfo(void) const { return indices; }*/
1618
1619        void Arrange( const std::vector<Geometry::Vector3> & vertices,
1620                                  const std::vector<Geometry::Vector3> & normals,
1621                                  const std::vector<Geometry::Vector2> & texcoords){
1622
1623                mesh->mVertexBuffer=new Geometry::VertexBuffer;
1624                mesh->mVertexBuffer->mVertexCount = GetVertexCount();
1625                mesh->mVertexBuffer->mPosition = new Geometry::Vector3[mesh->mVertexBuffer->mVertexCount];
1626                mesh->mVertexBuffer->mTexCoords = texcoords.empty()?NULL:new Geometry::Vector2[mesh->mVertexBuffer->mVertexCount];
1627                mesh->mVertexBuffer->mNormal = normals.empty()?NULL:new Geometry::Vector3[mesh->mVertexBuffer->mVertexCount];
1628                mesh->mVertexBuffer->mVertexInfo = Geometry::VERTEX_POSITION | (texcoords.empty()?0:Geometry::VERTEX_TEXCOORDS) | (normals.empty()?0:Geometry::VERTEX_NORMAL);
1629
1630                // sort the calculated vertices
1631               
1632                vertex_arranger_node * vertex_list = new vertex_arranger_node[mesh->mVertexBuffer->mVertexCount];
1633                for (std::map<vertex_arranger_node,int>::iterator it=vertex_map.begin(); it!=vertex_map.end(); it++)
1634                        vertex_list[it->second] = it->first;
1635
1636                for (   size_t  i       =       0;      i < mesh->mSubMeshCount;        i++)
1637                {
1638                        mesh->mSubMesh[i].mVertexBuffer = mesh->mVertexBuffer;
1639                }
1640               
1641                for (size_t     j       =       0;      j < mesh->mVertexBuffer->mVertexCount;  j++)
1642                {               
1643                        int vi = vertex_list[j].v;
1644                        int ti = vertex_list[j].t;
1645                        int ni = vertex_list[j].n;
1646
1647                        Geometry::Vector3 auxpos(vertices[vi]);
1648
1649                        if (auxpos.x < mesh->mMeshBounds.minX)
1650                        {
1651                                mesh->mMeshBounds.minX = auxpos.x;
1652                        }
1653
1654                        if (auxpos.y < mesh->mMeshBounds.minY)
1655                        {
1656                                mesh->mMeshBounds.minY = auxpos.y;
1657                        }
1658
1659                        if (auxpos.z < mesh->mMeshBounds.minZ)
1660                        {
1661                                mesh->mMeshBounds.minZ = auxpos.z;
1662                        }
1663
1664                        if (auxpos.x > mesh->mMeshBounds.maxX)
1665                        {
1666                                mesh->mMeshBounds.maxX = auxpos.x;
1667                        }
1668
1669                        if (auxpos.y > mesh->mMeshBounds.maxY)
1670                        {
1671                                mesh->mMeshBounds.maxY = auxpos.y;
1672                        }
1673
1674                        if (auxpos.z > mesh->mMeshBounds.maxZ)
1675                        {
1676                                mesh->mMeshBounds.maxZ = auxpos.z;
1677                        }
1678
1679                        mesh->mVertexBuffer->mPosition[j]       =       auxpos;
1680                        mesh->mVertexBuffer->mNormal[j]         =       normals[ni];
1681
1682                        if (texcoords.empty() == false)
1683                        {
1684                                mesh->mVertexBuffer->mTexCoords[j] = texcoords[ti];
1685                        }
1686                }
1687
1688                delete[] vertex_list;
1689        }
1690
1691//private:
1692        std::map<vertex_arranger_node,int>      vertex_map;
1693        Geometry::Mesh                                                                                  *mesh;
1694        int                                                                                                                                     current_submesh;
1695        int                                                                                                                                     *current_tris;
1696};
1697
1698
1699void    GeoMeshLoader::importOBJ(FILE *f, Mesh *mesh)
1700{
1701        mesh->hasSkeleton=false;
1702        mesh->mSubMeshCount=0;
1703
1704        std::vector<Geometry::Vector3> vertices;
1705        std::vector<Geometry::Vector3> normals;
1706        std::vector<Geometry::Vector2> texcoords;
1707        std::vector<std::vector<face_t> > faces;
1708        std::vector<face_t> current_faces;
1709
1710        mesh->mMeshBounds.maxX = -99999999.9f;
1711        mesh->mMeshBounds.maxY = -99999999.9f;
1712        mesh->mMeshBounds.maxZ = -99999999.9f;
1713        mesh->mMeshBounds.minX =  99999999.9f;
1714        mesh->mMeshBounds.minY =  99999999.9f;
1715        mesh->mMeshBounds.minZ =  99999999.9f;
1716        mesh->mMeshBounds.radius = 1.0f;
1717        mesh->mMeshBounds.scaleFactor = 1.0f;
1718
1719        char line[256]="";
1720        while(!feof(f))
1721        {
1722                fgets(line,256,f);
1723                if (line[0]=='v' && line[1]==' ')
1724                {
1725                        Geometry::Vector3 v3;
1726                        sscanf(line+2,"%f %f %f",&v3.x,&v3.y,&v3.z);
1727                        vertices.push_back(v3);
1728                }
1729                else if (line[0]=='v' && line[1]=='t')
1730                {
1731                        Geometry::Vector2 v2;
1732                        sscanf(line+2,"%f %f",&v2.x,&v2.y);
1733                        texcoords.push_back(v2);
1734                }
1735                else if (line[0]=='v' && line[1]=='n')
1736                {
1737                        Geometry::Vector3 v3;
1738                        sscanf(line+2,"%f %f %f",&v3.x,&v3.y,&v3.z);
1739                        normals.push_back(v3);
1740                }
1741                else if (line[0]=='f')
1742                {
1743                        face_t auxface;
1744                        auxface.n1=auxface.n2=auxface.n3=auxface.t1=auxface.t2=auxface.t3=auxface.v1=auxface.v2=auxface.v3=0;
1745                        int n = sscanf(line+2,"%d/%d/%d %d/%d/%d %d/%d/%d", &auxface.v1,&auxface.t1,&auxface.n1,
1746                                                                                                                            &auxface.v2,&auxface.t2,&auxface.n2,
1747                                                                                                                                &auxface.v3,&auxface.t3,&auxface.n3);
1748                        if (n<9)
1749                        {
1750                                auxface.n1=auxface.n2=auxface.n3=auxface.t1=auxface.t2=auxface.t3=auxface.v1=auxface.v2=auxface.v3=0;
1751                                n = sscanf(line+2,"%d//%d %d//%d %d//%d", &auxface.v1,&auxface.n1,
1752                                                                                                                  &auxface.v2,&auxface.n2,
1753                                                                                                                  &auxface.v3,&auxface.n3);
1754                                if (n<6)
1755                                {
1756                                        auxface.n1=auxface.n2=auxface.n3=auxface.t1=auxface.t2=auxface.t3=auxface.v1=auxface.v2=auxface.v3=0;
1757                                        n = sscanf(line+2,"%d/%d %d/%d %d/%d", &auxface.v1,&auxface.t1,
1758                                                                                                                   &auxface.v2,&auxface.t2,
1759                                                                                                                   &auxface.v3,&auxface.t3);
1760                                        if (n<6)
1761                                        {
1762                                                auxface.n1=auxface.n2=auxface.n3=auxface.t1=auxface.t2=auxface.t3=auxface.v1=auxface.v2=auxface.v3=0;
1763                                                n = sscanf(line+2,"%d %d %d", &auxface.v1,&auxface.v2,&auxface.v3);
1764                                        }
1765                                }
1766                        }
1767
1768                        auxface.v1=abs(auxface.v1); auxface.v2=abs(auxface.v2); auxface.v3=abs(auxface.v3);
1769                        auxface.t1=abs(auxface.t1); auxface.t2=abs(auxface.t2); auxface.t3=abs(auxface.t3);
1770                        auxface.n1=abs(auxface.n1); auxface.n2=abs(auxface.n2); auxface.n3=abs(auxface.n3);
1771                        auxface.v1--; auxface.v2--; auxface.v3--;
1772                        auxface.t1--; auxface.t2--; auxface.t3--;
1773                        auxface.n1--; auxface.n2--; auxface.n3--;
1774                        current_faces.push_back(auxface);
1775                }
1776                else if (line[0]=='g')
1777                {
1778                        if (current_faces.size()>0)
1779                                faces.push_back(current_faces);
1780                        current_faces.clear();
1781                }
1782        }
1783
1784        if (current_faces.size()>0)
1785                faces.push_back(current_faces);
1786        current_faces.clear();
1787
1788        mesh->mSubMeshCount = faces.size();
1789        bool found_texcoords=!texcoords.empty();
1790
1791        if (normals.empty())
1792        {
1793                // calculate face normals
1794                for (size_t i=0, inormal=0; i<mesh->mSubMeshCount; i++)
1795                {
1796                        Geometry::SubMesh *submesh = mesh->mSubMesh+i;
1797                         std::vector<face_t> & vecfaces = faces[i];
1798                        int j=0;
1799                        for (std::vector<face_t>::iterator it=vecfaces.begin(); it!=vecfaces.end(); it++,j++,inormal++)
1800                        {
1801                                face_t & auxface = *it;
1802
1803                                auxface.n1 = (int)inormal;
1804                                auxface.n2 = (int)inormal;
1805                                auxface.n3 = (int)inormal;
1806
1807                                Geometry::Vector3 v1,v2,v3,v31,v21,nor;
1808                                v1 = vertices[auxface.v1];
1809                                v2 = vertices[auxface.v2];
1810                                v3 = vertices[auxface.v3];
1811                                v31 = v3 - v1;
1812                                v21 = v2 - v1;
1813                                nor = v21.crossProduct(v31);
1814                                nor.normalise();
1815                                normals.push_back(nor);
1816                        }                       
1817                }
1818        }
1819
1820        // fill up the mesh structure with the loaded information
1821
1822        VertexArranger vertex_arranger(mesh);
1823                 
1824        mesh->mSubMesh=new Geometry::SubMesh[mesh->mSubMeshCount];
1825        for (size_t     i       =       0;      i < mesh->mSubMeshCount;        i++)
1826        {
1827                Geometry::SubMesh *submesh = mesh->mSubMesh+i;
1828                int j=0;
1829                const std::vector<face_t> & vecfaces = faces[i];
1830                std::vector<Geometry::Index> aux_indices;
1831                submesh->mSharedVertexBuffer = true;
1832                submesh->mIndexCount = vecfaces.size()*3;
1833                submesh->mIndex=new Geometry::Index[submesh->mIndexCount];
1834
1835                vertex_arranger.SetCurrentSubMesh((int)i);
1836               
1837                for (std::vector<face_t>::const_iterator it=vecfaces.begin(); it!=vecfaces.end(); it++,j++)
1838                {
1839                        const face_t & auxface = *it;
1840
1841                        vertex_arranger.AddFace(auxface.v1,auxface.v2,auxface.v3,
1842                                                                        auxface.t1,auxface.t2,auxface.t3,
1843                                                                        auxface.n1,auxface.n2,auxface.n3);
1844                }                       
1845        }
1846
1847        vertex_arranger.Arrange(vertices,normals,texcoords);
1848}
1849
Note: See TracBrowser for help on using the repository browser.