source: GTP/trunk/Lib/Geom/shared/GeoTool/src/GeoMeshSaver.cpp @ 891

Revision 891, 17.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   GeoMeshSaver.cpp
10/*===========================================================================*/
11#include        <GeoMeshSaver.h>
12
13using   namespace       Geometry;
14using   namespace       std;
15
16//------------------------------------------
17//              Public:
18//------------------------------------------
19
20////////////////////
21//      Constructors.   //
22////////////////////
23GeoMeshSaver::GeoMeshSaver()
24{
25        mMaterialName                           =       "";
26        mSkeletallyAnimated     =       false;
27
28        //      Initializa the mesh bounds.
29        mMeshBounds.minx                        =       0.0;
30        mMeshBounds.miny                        =       0.0;
31        mMeshBounds.minz                        =       0.0;
32        mMeshBounds.maxx                        =       0.0;
33        mMeshBounds.maxy                        =       0.0;
34        mMeshBounds.maxz                        =       0.0;
35        mMeshBounds.radius              =       0.0;
36}
37
38GeoMeshSaver::GeoMeshSaver(GeometryBounds bounds)
39{
40        mMaterialName                           =       "";
41        mSkeletallyAnimated     =       false;
42
43        //      Initializa the mesh bounds.
44        mMeshBounds.minx                        =       bounds.minx;
45        mMeshBounds.miny                        =       bounds.miny;
46        mMeshBounds.minz                        =       bounds.minz;
47        mMeshBounds.maxx                        =       bounds.maxx;
48        mMeshBounds.maxy                        =       bounds.maxy;
49        mMeshBounds.maxz                        =       bounds.maxz;
50        mMeshBounds.radius              =       bounds.radius;
51}
52
53//////////////////
54//      Destroyer.      //
55//////////////////
56GeoMeshSaver::~GeoMeshSaver()
57{
58}
59
60//      Saves a Mesh into a file.
61int     GeoMeshSaver::save(Mesh *geoMesh,       const   char    *fileNameMesh)
62{
63        int                     size;
64        String  name(fileNameMesh);
65       
66        //      Open the file.
67        mSerializer     =       new     Serializer(     name,
68                                                                                                                                Serializer::WRITE);
69
70        //      Set the mesh.
71        mGeoMesh        =       geoMesh;
72
73        //      Write the file header.
74        writeFileHeader();
75
76        //      Write the mesh data.
77        writeMesh(geoMesh);
78
79        //      Debug.
80        cout    <<      "Write mesh finish"
81                                <<      endl;
82       
83        size    =       mSerializer->GetSize();
84       
85        //      Close the file.
86        delete  mSerializer;
87       
88        //      Return the number of bytes written.
89        return  size;
90}
91
92//------------------------------------------
93//              Private:
94//------------------------------------------
95
96//      Write the main mesh.
97void    GeoMeshSaver::writeMesh(Mesh    *geoMesh)
98{
99        //      Debug.
100        cout    <<      "Write the chunk header"
101                                <<      endl;
102       
103        // Header
104        writeChunkHeader(M_MESH, calcMeshSize(geoMesh));
105
106        //      Write the skeletally animated flag.
107        writeBools(mSkeletallyAnimated,1);
108       
109        cout    <<      "1 - VertexCount: "
110                                <<      geoMesh->mVertexBuffer->mVertexCount
111                                <<      endl;
112
113        //      Write shared geometry.
114        if (geoMesh->mVertexBuffer->mVertexCount > 0)
115        {
116                //      Debug.
117                cout    <<      "Write the shared vertex buffer"
118                                        <<      endl;
119               
120                writeGeometry(geoMesh->mVertexBuffer);
121        }
122
123        //      Write submeshes.
124        for (int i = 0; i < geoMesh->mSubMeshCount;     i++)
125        {
126                //      Debug.
127                cout    <<      "Write the submesh "
128                                        <<      i
129                                        <<      endl;
130               
131                writeSubMesh(&geoMesh->mSubMesh[i]);
132        }
133
134        //      Write the mesh bounds.
135        writeMeshBounds(mMeshBounds);
136       
137        /*
138        // Write skeleton info if required
139        if (pMesh->hasSkeleton())
140        {
141        LogManager::getSingleton().logMessage("Exporting skeleton link...");
142        // Write skeleton link
143        writeSkeletonLink(pMesh->getSkeletonName());
144        LogManager::getSingleton().logMessage("Skeleton link exported.");
145
146        // Write bone assignments
147        if (!pMesh->mBoneAssignments.empty())
148        {
149        LogManager::getSingleton().logMessage("Exporting shared geometry bone assignments...");
150
151        Mesh::VertexBoneAssignmentList::const_iterator vi;
152        for (vi = pMesh->mBoneAssignments.begin();
153        vi != pMesh->mBoneAssignments.end(); ++vi)
154        {
155        writeMeshBoneAssignment(vi->second);
156        }
157
158        LogManager::getSingleton().logMessage("Shared geometry bone assignments exported.");
159        }
160        }
161
162        // Write LOD data if any
163        if (pMesh->getNumLodLevels() > 1)
164        {
165        LogManager::getSingleton().logMessage("Exporting LOD information....");
166        writeLodInfo(pMesh);
167        LogManager::getSingleton().logMessage("LOD information exported.");
168
169        }
170        // Write bounds information
171        LogManager::getSingleton().logMessage("Exporting bounds information....");
172        writeBoundsInfo(pMesh);
173        LogManager::getSingleton().logMessage("Bounds information exported.");
174
175        // Write submesh name table
176        LogManager::getSingleton().logMessage("Exporting submesh name table...");
177        writeSubMeshNameTable(pMesh);
178        LogManager::getSingleton().logMessage("Submesh name table exported.");
179
180        // Write edge lists
181        if (pMesh->isEdgeListBuilt())
182        {
183        LogManager::getSingleton().logMessage("Exporting edge lists...");
184        writeEdgeList(pMesh);
185        LogManager::getSingleton().logMessage("Edge lists exported");
186        }
187        */
188}
189
190//      Write a submesh.
191void    GeoMeshSaver::writeSubMesh(SubMesh      *geoSubMesh)
192{
193        bool                                            idx32bit;
194        unsigned        long    indexCount;
195        String                                  materialName;
196        Index                                           *index;
197        Index                                           *indexBegin;
198        Index                                           *indexEnd;
199       
200        //      Debug.
201        cout    <<      "Write the submesh chunk header"
202                                <<      endl;
203       
204        // Header.
205        writeChunkHeader(M_SUBMESH, calcSubMeshSize(geoSubMesh));
206
207        //      Debug.
208        cout    <<      "Write the material name"
209                                <<      endl;
210
211        // Material Name.
212        materialName    =       getMaterialName();
213        writeString(materialName);
214
215        //      Debug.
216        cout    <<      "Write the shared vertex buffer flag: "
217                                <<      endl;
218
219        // bool useSharedVertices
220        writeBools(geoSubMesh->mSharedVertexBuffer, 1);
221
222        indexCount      =       geoSubMesh->mIndexCount;
223
224        //      If the submesh is in triangle strips.
225        if (geoSubMesh->mType == GEO_TRIANGLE_STRIPS)
226        {
227                indexCount      +=      2 * geoSubMesh->mStripCount - 2;
228        }
229       
230        writeInts(indexCount, 1);
231
232        // bool indexes32Bit
233        idx32bit        =       true;
234        writeBools(idx32bit, 1);
235
236        //      Debug.
237        cout    <<      "Write the mIndex array"
238                                <<      endl;
239
240        //      If the submesh is in triangle strips.
241        if (geoSubMesh->mType == GEO_TRIANGLE_STRIPS)
242        {
243                //      Debug.
244                cout    <<      "Write triangle strips"
245                                        <<      endl;
246               
247                //      For each one of the strips.
248                for (int strip = 0; strip < geoSubMesh->mStripCount; strip++)
249                {
250                        //      First index of the strip.
251                        indexBegin      =       geoSubMesh->mStrip[strip];
252
253                        //      If is the final strip
254                        if (strip       == (geoSubMesh->mStripCount - 1))
255                        {
256                                //      The end of the index array.
257                                indexEnd        = &geoSubMesh->mIndex[geoSubMesh->mIndexCount];
258                        }
259                        else
260                        {
261                                //      The beginning of the next strip.
262                                indexEnd        = geoSubMesh->mStrip[strip + 1];
263                        }
264
265                        int i;
266                        i       = 0;
267
268                        if (strip != 0)
269                        {
270                                writeInts(indexBegin[i], 1);
271                        }
272                       
273                        //      For each index of the strip.
274                        for (index = indexBegin; index < indexEnd; index++)
275                        {
276                                writeInts(indexBegin[i], 1);
277                               
278                                //      Increments i.
279                                i++;
280                        }
281
282                        if (strip       != (geoSubMesh->mStripCount - 1))
283                        {
284                                writeInts(indexBegin[i - 1], 1);
285                        }
286
287                }
288        }
289        //      If the submesh is in triangle list.
290        else
291        {
292                //      Write the index array.
293                for (int i = 0; i < geoSubMesh->mIndexCount; i++)
294                {
295                        writeInts(geoSubMesh->mIndex[i], 1);
296                }
297        }
298
299        // M_GEOMETRY stream (Optional: present only if useSharedVertices = false)
300        if (!geoSubMesh->mSharedVertexBuffer)
301        {
302                //      Debug.
303                cout    <<      "Write the geometry of the submesh"
304                                        <<      endl;
305
306                writeGeometry(geoSubMesh->mVertexBuffer);
307        }
308
309        //      Debug.
310        cout    <<      "mIndex array written"
311                                <<      endl;
312
313        // Operation type
314        writeSubMeshOperation(geoSubMesh);
315
316        //TODO:Bones.
317        /*
318        // Bone assignments
319        if (!s->mBoneAssignments.empty())
320        {
321                LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments...");
322
323                SubMesh::VertexBoneAssignmentList::const_iterator vi;
324
325                for (vi = s->mBoneAssignments.begin();
326                                vi != s->mBoneAssignments.end(); ++vi)
327                {
328                        writeSubMeshBoneAssignment(vi->second);
329                }
330
331                LogManager::getSingleton().logMessage("Dedicated geometry bone assignments exported.");
332        }
333        */
334}
335
336//      Write the submesh operation chunk and data.
337void GeoMeshSaver::writeSubMeshOperation(const  SubMesh *geoSubMesh)
338{
339        unsigned        short opType;
340        unsigned        long    size;
341
342        //      Debug.
343        cout    <<      "Write submesh operation"
344                                <<      endl;
345       
346        size    =       CHUNK_OVERHEAD_SIZE     +       sizeof(unsigned short);
347       
348        // Header
349        writeChunkHeader(M_SUBMESH_OPERATION, size);
350
351        //      If the mesh is in triangle strips.
352        if (geoSubMesh->mType   ==      GEO_TRIANGLE_STRIPS)
353        {
354                opType  =       5;
355        }
356        //      If the mesh is in triangle list.
357        else
358        {
359                opType  =       4;
360        }
361       
362        writeShorts(opType, 1);
363
364        //      Debug.
365        cout    <<      "Submesh operation Written"
366                                <<      endl;
367}
368
369//      Write geometry.
370void    GeoMeshSaver::writeGeometry(VertexBuffer        *vertexBuffer)
371{
372        unsigned        short   element;
373        unsigned        long    size;
374        unsigned        short   buffer_count;
375
376        buffer_count    =       3;
377
378       
379        //      Calc the size in bytes of the geometry chunk.
380        size    =       calcGeometrySize(vertexBuffer);
381               
382        //      Header.
383        //
384        //      Write the M_GEOMETRY header.
385        writeChunkHeader(M_GEOMETRY, size);
386
387        writeInts(vertexBuffer->mVertexCount,1);
388
389        //      Vertex declaration.
390        //      Calculate the size of vertex declaration.
391        size    =       CHUNK_OVERHEAD_SIZE
392                                        +
393                                        buffer_count
394                                        *
395                                        (CHUNK_OVERHEAD_SIZE    +       (sizeof(unsigned short) *       5));
396
397        //      Write the vertex declaration header.
398        writeChunkHeader(       M_GEOMETRY_VERTEX_DECLARATION,size);
399
400        //      Obtain the size of the vertex element chunk.
401        size    =       CHUNK_OVERHEAD_SIZE     +       (sizeof(unsigned short) *       5);
402
403        //      Positions.
404        //      Write the vertex element header for position.
405        writeChunkHeader(       M_GEOMETRY_VERTEX_ELEMENT,size);
406
407        element =       0;
408        writeShorts(element,1);
409
410        element =       VET_FLOAT3;
411        writeShorts(element,1);
412       
413        element =       VES_POSITION;
414        writeShorts(element,1);
415       
416        element =       0;
417        writeShorts(element,1);
418       
419        element =       0;
420        writeShorts(element,1);
421
422        //      Normals.
423        //      Write the vertex element header for position.
424        writeChunkHeader(       M_GEOMETRY_VERTEX_ELEMENT,size);
425       
426        element =       1;
427        writeShorts(element,1);
428       
429        element =       VET_FLOAT3;
430        writeShorts(element,1);
431       
432        element =       VES_NORMAL;
433        writeShorts(element,1);
434       
435        element =       0;
436        writeShorts(element,1);
437       
438        element =       0;
439        writeShorts(element,1);
440
441        //      Textures.
442        //      Write the vertex element header for position.
443        writeChunkHeader(M_GEOMETRY_VERTEX_ELEMENT,size);
444       
445        element =       2;
446        writeShorts(element,1);
447       
448        element =       VET_FLOAT2;
449        writeShorts(element,1);
450       
451        element =       VES_TEXTURE_COORDINATES;
452        writeShorts(element,1);
453       
454        element =       0;
455        writeShorts(element,1);
456       
457        element =       0;
458        writeShorts(element,1);
459
460        //      Obtain the size for vertex buffer header for positons.
461        size    =       (2      *       CHUNK_OVERHEAD_SIZE)    +       (2      *       sizeof(unsigned short));
462
463        //      Write the vertex buffer header for positions.
464        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER,      size);
465
466        element =       0;
467        writeShorts(element,1);
468       
469        element =       12;
470        writeShorts(element,1);
471
472        //      Obtain the size for the vertex buffer data header for positions.
473        size    =       CHUNK_OVERHEAD_SIZE
474                                        +
475                                        ((sizeof(float) *       3)      *       vertexBuffer->mVertexCount);
476
477        //      Write the vertex buffer data header for positions.
478        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER_DATA, size);
479
480        //      Write all the positions coords.
481        mSerializer->WriteArray(vertexBuffer->mPosition,
482                                                                                                        vertexBuffer->mVertexCount);
483
484        //      Obtain the size for vertex buffer header for normals.
485        size    =       (2      *       CHUNK_OVERHEAD_SIZE)    +       (2      *       sizeof(unsigned short));
486
487        //      Write the vertex buffer header.
488        writeChunkHeader(       M_GEOMETRY_VERTEX_BUFFER,       size);
489
490        element =       1;
491        writeShorts(element,1);
492       
493        element =       12;
494        writeShorts(element,1);
495
496        //      Obtain the size for the vertex buffer data header for normals.
497        size    =       CHUNK_OVERHEAD_SIZE
498                                        +
499                                        ((sizeof(float) *       3)      *       vertexBuffer->mVertexCount);
500
501        //      Write the vertex buffer data header for normals.
502        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER_DATA, size);
503
504        //      Write all the normals coords.
505        mSerializer->WriteArray(vertexBuffer->mNormal,
506                                                                                                        vertexBuffer->mVertexCount);
507
508        //      Obtain the size for vertex buffer header for textures.
509        size    =       (2      *       CHUNK_OVERHEAD_SIZE)    +       (2      *       sizeof(unsigned short));
510
511        //      Write the vertex buffer header for textures.
512        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER,      size);
513
514        element =       2;
515        writeShorts(element,1);
516       
517        element =       8;
518        writeShorts(element,1);
519
520        //      Obtain the size for the vertex buffer data header for textures.
521        size    =       CHUNK_OVERHEAD_SIZE
522                                        +
523                                        ((sizeof(float) *       2)      *       vertexBuffer->mVertexCount);
524
525        //      Write the vertex buffer data header for textures.
526        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER_DATA, size);
527
528        //      Debug.
529        cout    <<      "-7-"   <<      endl;
530
531        //      Write all the texture coords.
532        mSerializer->WriteArray(vertexBuffer->mTexCoords,
533                                                                                                        vertexBuffer->mVertexCount);
534
535        //      Debug.
536        cout    <<      "-8-"   <<      endl;
537
538}
539
540//      TODO: Write Mesh Bounds.
541void    GeoMeshSaver::writeMeshBounds(GeometryBounds bounds)
542{
543        size_t  size;
544
545        size    =       CHUNK_OVERHEAD_SIZE
546                                        +
547                                        (sizeof(float)  *       7);
548
549        writeChunkHeader(M_MESH_BOUNDS, size);
550
551        writeFloats(bounds.minx,1);
552        writeFloats(bounds.miny,1);
553        writeFloats(bounds.minz,1);
554        writeFloats(bounds.maxx,1);
555        writeFloats(bounds.maxy,1);
556        writeFloats(bounds.maxz,1);
557        writeFloats(bounds.radius,1);
558}
559
560//      Calc the mesh size in bytes.
561size_t GeoMeshSaver::calcMeshSize(const Mesh    *geoMesh)
562{
563        size_t size = CHUNK_OVERHEAD_SIZE;
564
565        //      Debug.
566        cout    <<      "Calc the size of the mesh"
567                                <<      endl;
568       
569        // Num shared vertices
570        size += sizeof(uint32);
571
572        //      Debug.
573        cout    <<      "VertexCount: "
574                                <<      geoMesh->mVertexBuffer->mVertexCount
575                                <<      endl;
576
577        // Geometry
578        if (geoMesh->mVertexBuffer->mVertexCount > 0)
579        {
580                //      Debug.
581                cout    <<      "Calc the size of the shared vertex buffer"
582                                        <<      endl;
583               
584                size += calcGeometrySize(geoMesh->mVertexBuffer);
585        }
586
587        // Submeshes
588        for (unsigned short i = 0; i < geoMesh->mSubMeshCount; ++i)
589        {
590                //      Debug.
591                cout    <<      "Calc the size of the submesh "
592                                        <<      i
593                                        <<      endl;
594
595                size += calcSubMeshSize(&geoMesh->mSubMesh[i]);
596        }
597
598        //      Mesh Bounds size added.
599        size    +=      CHUNK_OVERHEAD_SIZE
600                                                +
601                                                (sizeof(float)  *       7);
602
603        /*
604        // Skeleton link
605        if (geoMesh->hasSkeleton())
606        {
607                size += calcSkeletonLinkSize(geoMesh->getSkeletonName());
608        }
609        */
610
611        /*
612        // Submesh name table
613        size += calcSubMeshNameTableSize(geoMesh);
614
615        // Edge list
616        if (geoMesh->isEdgeListBuilt())
617        {
618                size += calcEdgeListSize(geoMesh);
619        }
620        */
621       
622        return size;
623}
624
625//      Calc the size in bytes for the submesh.
626size_t GeoMeshSaver::calcSubMeshSize(const SubMesh      *geoSubMesh)
627{
628        size_t size = CHUNK_OVERHEAD_SIZE;
629
630        // Material name
631        size += getMaterialName().length() + 1;
632
633        // bool useSharedVertices
634        size += sizeof(bool);
635        // unsigned int indexCount
636        size += sizeof(unsigned int);
637        // bool indexes32bit
638        size += sizeof(bool);
639
640        // unsigned int* faceVertexIndices
641        size += sizeof(unsigned int) * geoSubMesh->mIndexCount;
642
643        // Geometry
644        if (!geoSubMesh->mSharedVertexBuffer)
645        {
646                size += calcGeometrySize(geoSubMesh->mVertexBuffer);
647        }
648
649        return size;
650}
651
652//      Calc the geometry size in bytes.
653size_t GeoMeshSaver::calcGeometrySize(const VertexBuffer* vertexBuffer)
654{
655        unsigned        long            size;
656        unsigned        long            buffer_count;
657
658        //      and another for normals.
659        buffer_count    =       3;
660
661        //      Calculate the size of the Geometry chunk.
662        size    =       CHUNK_OVERHEAD_SIZE     +       sizeof(unsigned int);
663        size    =       size
664                                        +
665                                        CHUNK_OVERHEAD_SIZE
666                                        +
667                                        buffer_count
668                                        *
669                                        (CHUNK_OVERHEAD_SIZE    +       (sizeof(unsigned short) *       5));
670        size    =       size
671                                        +
672                                        buffer_count
673                                        *
674                                        (       (CHUNK_OVERHEAD_SIZE            *       2)
675                                                +
676                                                (sizeof(unsigned short) *       2)
677                                                +
678                                                vertexBuffer->mVertexCount
679                                        );
680
681        return size;
682}
683
684//      Write the file header.
685void GeoMeshSaver::writeFileHeader(void)
686{
687        String  mesh_version("[MeshSerializer_v1.30]");
688       
689        writeShorts(M_HEADER, 1);
690
691        writeString(mesh_version);
692
693}
694
695//      Write a header chunk given.
696void GeoMeshSaver::writeChunkHeader(unsigned short      id,
697                                                                                                                                                unsigned long           size)
698{
699        mSerializer->WriteData(&id,sizeof(unsigned short),1);
700        mSerializer->WriteData(&size,sizeof(unsigned long),1);
701}
702
703//      Write integers into the file.
704void    GeoMeshSaver::writeInts(unsigned long   id,
705                                                                                                                        unsigned long   count)
706{
707        mSerializer->WriteData(&id,sizeof(id),count);
708}
709
710//      Write shorts into the file
711void    GeoMeshSaver::writeShorts(unsigned short        id,
712                                                                                                                                unsigned long           count)
713{
714        mSerializer->WriteData(&id,sizeof(id),count);
715}
716
717//      Write float into the file.
718void    GeoMeshSaver::writeFloats(float                                         id,
719                                                                                                                                unsigned long           count)
720{
721        mSerializer->WriteData(&id,sizeof(id),count);
722}
723
724//      Write a string into the file.
725void GeoMeshSaver::writeString(const    String  &string)
726{
727        mSerializer->WriteData(string);
728}
729
730//      Write booleans into the file.
731void    GeoMeshSaver::writeBools(       const bool id,
732                                                                                                                                unsigned        long            count)
733{
734        mSerializer->WriteData(&id,sizeof(bool),count);
735}
736
737//      Sets the material of the mesh.
738void    GeoMeshSaver::setMaterialName(String    materialName)
739{
740        mMaterialName   =       materialName;
741}
742
743//      Gets the material of the mesh.
744String  GeoMeshSaver::getMaterialName()
745{
746        return  mMaterialName;
747}
748
749//      Set Mesh Bounds.
750void    GeoMeshSaver::setMeshBounds(GeometryBounds      bounds)
751{
752        mMeshBounds.minx                =       bounds.minx;
753        mMeshBounds.miny                =       bounds.miny;
754        mMeshBounds.minz                =       bounds.minz;
755        mMeshBounds.maxx                =       bounds.maxx;
756        mMeshBounds.maxy                =       bounds.maxy;
757        mMeshBounds.maxz                =       bounds.maxz;
758        mMeshBounds.radius      =       bounds.radius;
759}
760
Note: See TracBrowser for help on using the repository browser.