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

Revision 1526, 43.2 KB checked in by gumbau, 18 years ago (diff)

Updated modules to the new interface and the new simplification algorithm improvements.

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