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

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