source: GTP/trunk/Lib/Geom/shared/GeoTool/src/GeoMeshLoader.cpp @ 1071

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