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

Revision 1024, 30.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
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        materialName[strlen(materialName) - 1]  =       '\0';
430
431        fread(&useSharedVertices,sizeof(bool),1,f);
432       
433        if (option      ==      GEOMESH_BUILD)
434        {
435                //      Obtain the material name.
436                strcpy(geoSubMesh->mMaterialName,materialName);
437               
438                //      Obtain the flag of vertex shared.
439                geoSubMesh->mSharedVertexBuffer =       useSharedVertices;
440               
441                if (useSharedVertices)
442                {
443                        //      The VB of the submesh points to the VB of the mesh.
444                        geoSubMesh->mVertexBuffer       =       geoMesh->mVertexBuffer;
445                }
446        }
447
448        fread(&numIndices,sizeof(unsigned int),1,f);
449        fread(&idx32bit,sizeof(bool),1,f);
450       
451        if (option == GEOMESH_BUILD)
452        {
453                        //      Sets the index count of the submesh.
454                        geoSubMesh->mIndexCount =       numIndices;
455       
456                        //      Create the index arrar for this submesh.
457                        geoSubMesh->mIndex      =       new Index[numIndices];
458        }
459       
460
461        if (idx32bit)
462        {
463                unsigned int aux;
464
465                for (int i = 0; i < numIndices; i++)
466                {
467                        fread(&aux,sizeof(unsigned int),1,f);
468
469                        if (option == GEOMESH_BUILD)
470                        {
471                                        geoSubMesh->mIndex[i]   =       aux;
472                        }
473                }
474        }
475        else
476        {
477                unsigned short aux;
478
479                for (int i = 0; i < numIndices; i++)
480                {
481                        fread(&aux,sizeof(unsigned short),1,f);
482                       
483                        if (option == GEOMESH_BUILD)
484                        {
485                                geoSubMesh->mIndex[i]   =       aux;
486                        }
487                }
488        }
489
490  // M_GEOMETRY chunk
491        // (Optional: present only if useSharedVertices = false)
492  if (!useSharedVertices)
493        {
494                chunkID = readChunk(f);
495               
496                if (chunkID != M_GEOMETRY)
497                {
498                        //      Debug.
499                        cout    <<      "Error: Missing mesh geometry."
500                                                <<      endl;
501
502                        //      Error.
503                        mError  =       true;
504                }
505               
506                readGeometry(f, geoMesh, option);
507        }
508
509        // Find all bone assignments (if present)
510        if (!feof(f))
511        {
512                chunkID = readChunk(f);
513                while(!feof(f) &&
514                                        (chunkID == M_SUBMESH_BONE_ASSIGNMENT ||
515                                        chunkID == M_SUBMESH_OPERATION))
516                {
517                        switch(chunkID)
518                        {
519                                case M_SUBMESH_OPERATION:
520                                                               
521                                        //      Debug.
522                                        cout    <<      "               M_SUBMESH_OPERATION"
523                                                                <<      endl;
524
525                                        readSubMeshOperation(f, geoMesh, option);
526                                       
527                                        break;
528                                       
529                                case M_SUBMESH_BONE_ASSIGNMENT:
530                                       
531                                        //      Debug.
532                                        //cout  <<      "               M_SUBMESH_BONE_ASSIGNMENT"
533                                        //                      <<      endl;
534                                       
535                                        if (option      ==      GEOMESH_BUILD)
536                                        {
537                                                readSubMeshBoneAssignment(f, geoSubMesh, option);
538                                        }
539                                        else
540                                        {
541                                                jumpChunk(f);
542                                        }
543                                       
544                                        break;
545                        }
546
547                        if (!feof(f))
548                        {
549                                chunkID =       readChunk(f);
550                        }
551
552                }
553                if (!feof(f))
554                {
555                        // Backpedal back to start of chunk.
556                        fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
557                }
558        }
559
560}
561
562//---------------------------------------------------------------------------
563//      Read a mesh lod information.
564//---------------------------------------------------------------------------
565void GeoMeshLoader::readMeshLodInfo(FILE        *f, Mesh        *geoMesh)
566{
567        unsigned        short   chunkID;
568        unsigned        short   i;
569        unsigned        short   aux;
570        bool                                            aux2;
571
572  // unsigned short numLevels;
573        fread(&aux,sizeof(unsigned short),1,f);
574        // bool manual;
575        // (true for manual alternate meshes, false for generated)
576        fread(&aux2,sizeof(bool),1,f);
577
578        // Loop from 1 rather than 0 (full detail index is not in file)
579        for (i = 1; i < aux; ++i)
580        {
581                chunkID = readChunk(f);
582                if (chunkID != M_MESH_LOD_USAGE)
583                {
584                        //      Debug.
585                        cout    <<      "Error: Missing M_MESH_LOD_USAGE chunk"
586                                                <<      endl;
587                }
588                else
589                {
590                        cout    <<      "               M_MESH_LOD_USAGE"
591                                                <<      endl;
592                }
593               
594                jumpChunk(f);
595
596        }
597}
598
599//---------------------------------------------------------------------------
600//      Read a submesh name table.
601//---------------------------------------------------------------------------
602void GeoMeshLoader::readSubMeshNameTable(FILE   *f, Mesh        *geoMesh)
603{
604                unsigned        short   chunkID;
605                unsigned        short   subMeshIndex;
606                char                                            string[255];
607
608                if (!feof(f))
609                {
610                        chunkID =       readChunk(f);
611                       
612                        while   (!feof(f) && (chunkID == M_SUBMESH_NAME_TABLE_ELEMENT ))
613                        {
614                                //      Debug.
615                                cout    <<      "               M_SUBMESH_NAME_TABLE_ELEMENT"
616                                                        <<      endl;
617                               
618                                // Read in the index of the submesh.
619                                fread(&subMeshIndex,sizeof(unsigned short),1,f);
620                               
621                                // Read in the String and map it to its index.
622                                fgets(string,255,f);
623
624                                // If we're not end of file get the next chunk ID.
625                                if (!feof(f))
626                                {
627                                        chunkID = readChunk(f);
628                                }
629                        }
630                        if (!feof(f))
631                        {
632                                // Backpedal back to start of chunk.
633                                fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
634                        }
635                }
636}
637
638//---------------------------------------------------------------------------
639//      Read a mesh file.
640//---------------------------------------------------------------------------
641void GeoMeshLoader::readMesh(FILE       *f, Mesh        *geoMesh, int option)
642{
643        unsigned        short   chunkID;
644        bool                                            nada;
645
646        //      Create the VertexBuffer of the mesh.
647        geoMesh->mVertexBuffer  =       new     VertexBuffer();
648        geoMesh->mVertexBuffer->mVertexCount    =       0;
649
650        //La vacio antes de leer el mesh
651        list.clear();
652
653        // bool skeletallyAnimated
654        fread(&nada,sizeof(bool),1,f);
655
656  // Find all subchunks
657        if (!feof(f))
658        {
659                chunkID =       readChunk(f);
660
661                while(!feof(f) &&
662                                (chunkID == M_GEOMETRY ||
663                                 chunkID == M_SUBMESH ||
664                                 chunkID == M_MESH_SKELETON_LINK ||
665                                 chunkID == M_MESH_BONE_ASSIGNMENT ||
666                                 chunkID == M_MESH_LOD ||
667                                 chunkID == M_MESH_BOUNDS ||
668                                 chunkID == M_SUBMESH_NAME_TABLE ||
669                                 chunkID == M_EDGE_LISTS))
670                {
671                        switch(chunkID)
672                        {
673                                case M_GEOMETRY:
674
675                                        //      Debug.
676                                        cout    <<      "               M_GEOMETRY"
677                                                                <<      endl;
678
679                                        readGeometry(f, geoMesh, option);
680                                        break;
681
682                                case M_SUBMESH:
683
684                                        //      Debug.
685                                        cout    <<      "               M_SUBMESH"
686                                                                <<      endl;
687
688                                        if (option == GEOMESH_BUILD)
689                                        {
690                                                //      Increments the current submesh.
691                                                currentSubMesh++;
692                                        }
693
694                                        readSubMesh(f, geoMesh, option);
695
696                                        break;
697
698                                case M_MESH_SKELETON_LINK:
699
700                                        //      Debug.
701                                        cout    <<      "               M_MESH_SKELETON_LINK  "
702                                                                <<      endl;
703                                                               
704
705                                        readSkeletonLink(f, geoMesh, option);
706
707                                        break;
708
709                                case M_MESH_BONE_ASSIGNMENT:
710
711                                        //      Debug.
712                                        //cout  <<      "               M_MESH_BONE_ASSIGNMENT  "
713                                        //                      <<      endl;
714
715                                        readMeshBoneAssignment(f, geoMesh, option);
716
717                                        break;
718
719                                case M_MESH_LOD:
720
721                                        //      Debug.
722                                        cout    <<      "               M_MESH_LOD"
723                                                                <<      endl;
724                                       
725                                        readMeshLodInfo(f, geoMesh);
726                                        break;
727
728                                case M_MESH_BOUNDS:
729
730                                        //      Debug.
731                                        cout    <<      "               M_MESH_BOUNDS "
732                                                                <<      endl;
733
734                                        //jumpChunk(f);
735                                        readMeshBounds(f, geoMesh, option);
736                                        break;
737
738                                case M_SUBMESH_NAME_TABLE:
739
740                                        //      Debug.
741                                        cout    <<      "               M_SUBMESH_NAME_TABLE "
742                                                                <<      endl;
743
744                                        readSubMeshNameTable(f, geoMesh);
745                                        break;
746
747                                case M_EDGE_LISTS:
748
749                                        //      Debug.
750                                        cout    <<      "               M_EDGE_LISTS "
751                                                                <<      endl;
752
753                                        jumpChunk(f);
754                                        break;
755                        }
756
757                        if (!feof(f))
758                        {
759                                chunkID =       readChunk(f);
760                        }
761
762                }
763
764                if (!feof(f))
765                {
766                        // Backpedal back to start of chunk
767                        fseek(f,-(long)CHUNK_OVERHEAD_SIZE,1);
768
769                        //      Debug.
770                        cout    <<      "Error: Reading failure."
771                                                <<      endl;
772
773                        //      Error.
774                        mError  =       true;
775                }
776        }
777
778}
779
780
781//---------------------------------------------------------------------------
782//      Allocate memory to the array of strips
783//---------------------------------------------------------------------------
784SubMesh* GeoMeshLoader::BuildStripsGeoSubMesh(SubMesh* geoSubMesh)
785{
786        bool            head_found;
787        bool            tail_found;
788        int                     strip_count;
789        int                     tailIndex;
790        size_t  tail;
791
792
793        head_found                                                      =       false;
794        tail_found                                                      =       false;
795        geoSubMesh->mStripCount =       1;
796
797        //      Foreachone of the indices.
798        //      Obtains the number of triangle strips.
799        for (int i = 0; i < (geoSubMesh->mIndexCount - 1); i++)
800        {
801                if (geoSubMesh->mIndex[i] == geoSubMesh->mIndex[i+1])
802                {
803                        if (head_found)
804                        {
805                                tail_found      =       true;
806                        }
807                        else
808                        {
809                                head_found      =       true;
810                        }
811
812                        //      Jump one index.
813                        i++;
814                }
815                else
816                {
817                        //      Increments the number of triangle strips.
818                        if (tail_found)
819                        {
820                                geoSubMesh->mStripCount++;
821                        }
822
823                        head_found      =       false;
824                        tail_found      =       false;
825                }
826        }
827
828        geoSubMesh->mStrip              =       (Index**) malloc(       sizeof(Index*)
829                        *
830                        geoSubMesh->mStripCount);
831
832        //      Number of strips. Initially there is one triangle strip.
833        strip_count     =       1;
834
835        head_found                                              =       false;
836        tail_found                                              =       false;
837
838        //      Initialize the fist triangle strip.
839        geoSubMesh->mStrip[0]   =       &geoSubMesh->mIndex[0];
840
841        //      Foreachone of the indices.
842        //      Assigns the beginning of the triangle strips.
843        for(int i = 0;i < (geoSubMesh->mIndexCount - 1); i++)
844        {
845                if(geoSubMesh->mIndex[i] == geoSubMesh->mIndex[i+1])
846                {
847                        if(head_found)
848                        {
849                                if (!tail_found)
850                                {
851                                        tailIndex               =       i;
852                                }
853
854                                tail_found      =       true;
855                        }
856                        else
857                        {
858                                head_found      =       true;
859                        }
860
861                        //      Jump one index.
862                        i++;
863                }
864                else
865                {
866                        //      Increments the number of triangle strips.
867                        if(tail_found)
868                        {
869                                geoSubMesh->mStrip[strip_count++]       =       &geoSubMesh->mIndex[tailIndex];
870                        }
871
872                        head_found      =       false;
873                        tail_found      =       false;
874                }
875        }
876
877        //      Remove degenerate triangles of a submesh given.
878        geoSubMesh      =       removeDegenerateTriangles(geoSubMesh);
879
880        return  geoSubMesh;
881}
882
883//---------------------------------------------------------------------------
884//      Remove degenerate triangles of a submesh given.
885//---------------------------------------------------------------------------
886SubMesh *       GeoMeshLoader::removeDegenerateTriangles(SubMesh        *geoSubMesh)
887{
888        Index           *indices;
889        Index           *index;
890        Index           *indexBegin;
891        Index           *indexEnd;
892        Index           *new_strip_starts;
893        size_t  new_index_count;
894        size_t  current_index;
895
896        //      Stores the new starts of strips.
897        new_strip_starts        =       new     Index[geoSubMesh->mStripCount];
898       
899        //      Calculate the new index count.
900        new_index_count =       geoSubMesh->mIndexCount
901                -
902                (2 * geoSubMesh->mStripCount)
903                +
904                2;
905
906        //      Auxiliar index array.
907        indices =       new     Index[new_index_count];
908
909        //      Initialize the current index;
910        current_index   =       0;
911       
912        //      For each one of the strips.
913        for (int strip = 0; strip < geoSubMesh->mStripCount; strip++)
914        {
915                //      Stars of strip without degenerate triangles.
916                new_strip_starts[strip] =       current_index;
917               
918                //      First index of the strip.
919                indexBegin      =       geoSubMesh->mStrip[strip];
920
921                //      If is the final strip
922                if (strip       == (geoSubMesh->mStripCount - 1))
923                {
924                        //      The end of the index array.
925                        indexEnd        = &geoSubMesh->mIndex[geoSubMesh->mIndexCount];
926                }
927                else
928                {
929                        //      The beginning of the next strip.
930                        indexEnd        = geoSubMesh->mStrip[strip + 1];
931                }
932
933                int i;
934                i       = 0;
935
936                //      If is not the first strip.
937                if (strip != 0)
938                {
939                        indexBegin++;
940                }
941
942                //      If is not the last strip.
943                if (strip       != (geoSubMesh->mStripCount - 1))
944                {
945                        indexEnd--;
946                }
947
948                //      For each index of the strip.
949                for (index = indexBegin; index < indexEnd; index++)
950                {
951                        indices[current_index++]        =       indexBegin[i];
952
953                        //      Increments i.
954                        i++;
955                }
956
957        }
958
959        //      Free Index memory.
960        delete  []geoSubMesh->mIndex;
961
962        //      Update index count.
963        geoSubMesh->mIndexCount =       new_index_count;
964
965        geoSubMesh->mIndex      =       new     Index[new_index_count];
966
967        //      Store new index array without degenerate triangles.
968        for (size_t     i       =       0;      i       <       geoSubMesh->mIndexCount; i++)
969        {
970                geoSubMesh->mIndex[i]   =       indices[i];
971        }
972
973        //      Free auxiliar index array;
974        delete  []indices;
975
976        //      Update start of the strip.
977        for (int        strip   =       0; strip < geoSubMesh->mStripCount; strip++)
978        {
979                geoSubMesh->mStrip[strip]       =       &geoSubMesh->mIndex[new_strip_starts[strip]];
980        }
981
982        //      Free auxiliar strip starts.
983        delete  []new_strip_starts;
984       
985        return  geoSubMesh;
986}
987
988//---------------------------------------------------------------------------
989//      Loads a mesh.
990//---------------------------------------------------------------------------
991Mesh* GeoMeshLoader::load(char  *nameFileMesh)
992{
993        unsigned        short   uno;
994  unsigned      short   chunkID;
995        char                                            version[255];
996        char                                            kk;
997        FILE                                            *pFile;
998        SubMesh                                 *geosubmesh;
999
1000        //      Debug.
1001        cout    <<      "---------------------------------"
1002                                <<      endl
1003                                <<      "\t LOAD MESH"
1004                                <<      endl
1005                                <<      "---------------------------------"
1006                                <<      endl;
1007
1008        geoMesh =       NULL;
1009
1010        //      Open the mesh file.
1011        pFile   =       fopen(nameFileMesh, "rb");
1012
1013  if (pFile)
1014        {
1015                //      Initialize the current submesh;
1016                currentSubMesh  =       -1;
1017
1018                //      Initialize the return value.
1019                geoMesh =       new     Mesh();
1020
1021                //      Count the submeshes
1022                //      and next build the geomesh.
1023                for (int option = 0; option < 2;option++)
1024                {
1025                        //      Initialize Error.
1026                        mError  =       false;
1027       
1028                        fread(&uno,sizeof(unsigned short),1,pFile);
1029
1030                        if (uno != M_HEADER)
1031                        {
1032                                //      Debug.
1033                                cout    <<      "Error: Header not found."
1034                                        <<      endl;
1035
1036                                //      Error.
1037                                mError  =       true;
1038                        }
1039
1040                        // Read version.
1041                        fgets(version,255,pFile);
1042
1043                        cout    <<      version <<      endl;
1044
1045                        if (strcmp(version,"[MeshSerializer_v1.30]\n"))
1046                        {
1047                                //      Debug.
1048                                cout    <<      "Error: Wrong mesh version."
1049                                        <<      endl
1050                                        <<      "Only version 1.3 or older allowed."
1051                                        <<      endl;
1052
1053                                //      Error.
1054                                mError  =       true;
1055                        }
1056
1057                        while(!feof(pFile))
1058                        {
1059                                chunkID = readChunk(pFile);
1060
1061                                switch (chunkID)
1062                                {
1063                                        case M_MESH:
1064                                                readMesh(pFile, geoMesh, option);
1065                                                break;
1066                                }
1067                        }
1068
1069                        //      Create the submesh array.
1070                        if (option == SUBMESH_COUNT)
1071                        {
1072                                geoMesh->mSubMesh       = new SubMesh[geoMesh->mSubMeshCount];
1073                        }
1074
1075                        //      Move the curso to the begining of the file.
1076                        fseek(pFile,0,SEEK_SET);
1077                }
1078
1079                //      Goes to the end of the file.
1080                fseek(pFile,0,SEEK_END);
1081
1082                //      Gets the size of the file.
1083                mFileSize       =       ftell(pFile);
1084
1085                // Close the mesh file.
1086                fclose(pFile);
1087
1088                //      If no error.
1089                if (!mError)
1090                {
1091                        for (int submesh = 0;   submesh < geoMesh->mSubMeshCount; submesh++)
1092                        {
1093                                //      Gets the actual submesh.
1094                                geosubmesh      =       &geoMesh->mSubMesh[submesh];
1095
1096                                if (geosubmesh->mType == Geometry::GEO_TRIANGLE_STRIPS)
1097                                {
1098                                        //      Fill the strips list.
1099                                        geosubmesh      =       BuildStripsGeoSubMesh(geosubmesh);
1100                                }
1101                        }
1102
1103                        //      Sets coods between -1 and 1.
1104                        normalizeModel(geoMesh);
1105                }
1106        }
1107        else
1108        {
1109                //      Debug.
1110                cout    <<      "Error: File not found."
1111                                        <<      endl;
1112
1113                //      File not found.
1114                mError  =       true;
1115        }
1116
1117        //      If an error happens.
1118        if (mError)
1119        {
1120                delete  geoMesh;
1121               
1122                geoMesh =       NULL;
1123        }
1124       
1125        return  geoMesh;
1126}
1127
1128//---------------------------------------------------------------------------
1129//      Sets coords between -1 and 1.
1130//---------------------------------------------------------------------------
1131void    GeoMeshLoader::normalizeModel(Mesh      *geoMesh)
1132{
1133        unsigned        int     i;
1134        float                                   maxx, minx, maxy, miny, maxz, minz;
1135        float                                   cx, cy, cz, w, h, d, max;
1136        float                                   scale;
1137        VertexBuffer    *vertex_buffer;
1138
1139        //      Gets vertex buffer.
1140        vertex_buffer   =       geoMesh->mSubMesh[0].mVertexBuffer;
1141       
1142        //      Get the max/mins.
1143        maxx = minx = vertex_buffer->mPosition[0].x;
1144        maxy = miny = vertex_buffer->mPosition[0].y;
1145        maxz = minz = vertex_buffer->mPosition[0].z;
1146       
1147        //      For each submesh.
1148        for (int submesh = 0; submesh < geoMesh->mSubMeshCount; submesh++)
1149        {
1150                //      Gets the actual submesh.
1151                vertex_buffer   =       geoMesh->mSubMesh[submesh].mVertexBuffer;
1152
1153                //      For each index of the strip.
1154                for (int i = 0; i < vertex_buffer->mVertexCount; i++)
1155                {
1156                        if (maxx < vertex_buffer->mPosition[i].x)
1157                        {
1158                                maxx = vertex_buffer->mPosition[i].x;
1159                        }
1160
1161                        if (minx > vertex_buffer->mPosition[i].x)
1162                        {
1163                                minx = vertex_buffer->mPosition[i].x;
1164                        }
1165
1166                        if (maxy < vertex_buffer->mPosition[i].y)
1167                        {
1168                                maxy = vertex_buffer->mPosition[i].y;
1169                        }
1170
1171                        if (miny > vertex_buffer->mPosition[i].y)
1172                        {
1173                                miny = vertex_buffer->mPosition[i].y;
1174                        }
1175
1176                        if (maxz < vertex_buffer->mPosition[i].z)
1177                        {
1178                                maxz = vertex_buffer->mPosition[i].z;
1179                        }
1180
1181                        if (minz > vertex_buffer->mPosition[i].z)
1182                        {
1183                                minz = vertex_buffer->mPosition[i].z;
1184                        }
1185                }
1186
1187                //      If is a shared vertex Buffer.
1188                if (geoMesh->mSubMesh[submesh].mSharedVertexBuffer)
1189                {
1190                        break;
1191                }
1192        }
1193       
1194        //      Calculate model width, height, and depth.
1195        w = fabs(maxx) + fabs(minx);
1196        h = fabs(maxy) + fabs(miny);
1197        d = fabs(maxz) + fabs(minz);
1198
1199        //      Calculate center of the model.
1200        cx = (maxx + minx) / 2.0;
1201        cy = (maxy + miny) / 2.0;
1202        cz = (maxz + minz) / 2.0;
1203
1204
1205        //      Calculate max dimension.
1206        if (w > h)
1207        {
1208                max     =       w;
1209        }
1210        else
1211        {
1212                max     =       h;
1213        }
1214
1215        if (d > max)
1216        {
1217                max     =       d;
1218        }
1219       
1220        //      Calculate unitizing scale factor.
1221        scale = 1.0 / max;
1222
1223        geoMesh->mMeshBounds.scaleFactor                =       scale;
1224
1225        //      Translate around center then scale.
1226        //      For each submesh.
1227        for (int submesh = 0; submesh < geoMesh->mSubMeshCount; submesh++)
1228        {
1229                //      Gets the actual submesh.
1230                vertex_buffer   =       geoMesh->mSubMesh[submesh].mVertexBuffer;
1231
1232                //      For each index of the strip.
1233                for (int i = 0; i < vertex_buffer->mVertexCount; i++)
1234                {
1235                        vertex_buffer->mPosition[i].x -= cx;
1236                        vertex_buffer->mPosition[i].y -= cy;
1237                        vertex_buffer->mPosition[i].z -= cz;
1238                        vertex_buffer->mPosition[i].x *= scale;
1239                        vertex_buffer->mPosition[i].y *= scale;
1240                        vertex_buffer->mPosition[i].z *= scale;
1241                }
1242
1243                //      If is a shared vertex Buffer.
1244                if (geoMesh->mSubMesh[submesh].mSharedVertexBuffer)
1245                {
1246                        break;
1247                }
1248        }
1249
1250}
1251
1252//---------------------------------------------------------------------------
1253//      Get the size in bytes of the file.
1254//---------------------------------------------------------------------------
1255size_t  GeoMeshLoader::getFileSize()
1256{
1257        return  mFileSize;
1258}
1259
1260//---------------------------------------------------------------------------
1261//      Constructor
1262//---------------------------------------------------------------------------
1263GeoMeshLoader::GeoMeshLoader()
1264{
1265        geoMesh                 =       NULL;
1266        mFileSize               =       0;
1267}
1268
1269//---------------------------------------------------------------------------
1270//      Destroyer.
1271//---------------------------------------------------------------------------
1272GeoMeshLoader::~GeoMeshLoader()
1273{
1274        delete  geoMesh;
1275}
1276
1277//---------------------------------------------------------------------------
1278//      Read bones of the submesh.
1279//---------------------------------------------------------------------------
1280void GeoMeshLoader::readSubMeshBoneAssignment(FILE* f, SubMesh* geoSubMesh,int option)
1281{
1282        if (option == GEOMESH_BUILD)
1283        {
1284                VertexBoneAssignment assign;
1285
1286                // unsigned int vertexIndex;
1287                fread(&(assign.vertexIndex),sizeof(unsigned int),1,f);
1288                // unsigned short boneIndex;
1289                fread(&(assign.boneIndex),sizeof(unsigned short),1,f);
1290                // float weight
1291                fread(&(assign.weight),sizeof(float),1,f);
1292
1293                geoSubMesh->mBones.push_back(assign);
1294        }
1295}
1296
1297//---------------------------------------------------------------------------
1298//      Read bones of the main mesh.
1299//---------------------------------------------------------------------------
1300void GeoMeshLoader::readMeshBoneAssignment(FILE* f, Mesh* geoMesh,int option)
1301{
1302        if (option == GEOMESH_BUILD)
1303        {
1304                VertexBoneAssignment assign;
1305
1306                // unsigned int vertexIndex;
1307                fread(&(assign.vertexIndex),sizeof(unsigned int),1,f);
1308                // unsigned short boneIndex;
1309                fread(&(assign.boneIndex),sizeof(unsigned short),1,f);
1310                // float weight
1311                fread(&(assign.weight),sizeof(float),1,f);
1312
1313
1314                geoMesh->mBones.push_back(assign);
1315        }
1316}
1317
1318//---------------------------------------------------------------------------
1319//      Read skeleton link.
1320//---------------------------------------------------------------------------
1321void GeoMeshLoader::readSkeletonLink(FILE* f, Mesh* geoMesh,int option)
1322{
1323        if (option == GEOMESH_BUILD)
1324        {
1325                fgets(geoMesh->mSkeletonName,255,f);
1326               
1327                geoMesh->hasSkeleton    =       true;
1328
1329                //      Debug.
1330                cout    <<      "Skeleton Name: "
1331                                        <<      geoMesh->mSkeletonName
1332                                        <<      endl;
1333        }
1334}
1335
1336//---------------------------------------------------------------------------
1337//      Read bounding box settings.
1338//---------------------------------------------------------------------------
1339void    GeoMeshLoader::readMeshBounds(FILE      *f, Mesh        *geoMesh,       int     option)
1340{
1341        if (option == GEOMESH_BUILD)
1342        {
1343                fread(&(geoMesh->mMeshBounds.minX),sizeof(float),1,f);
1344                fread(&(geoMesh->mMeshBounds.minY),sizeof(float),1,f);
1345                fread(&(geoMesh->mMeshBounds.minZ),sizeof(float),1,f);
1346                fread(&(geoMesh->mMeshBounds.maxX),sizeof(float),1,f);
1347                fread(&(geoMesh->mMeshBounds.maxY),sizeof(float),1,f);
1348                fread(&(geoMesh->mMeshBounds.maxZ),sizeof(float),1,f);
1349                fread(&(geoMesh->mMeshBounds.radius),sizeof(float),1,f);
1350        }
1351}
1352
Note: See TracBrowser for help on using the repository browser.