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

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