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

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