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

Revision 826, 15.7 KB checked in by gumbau, 19 years ago (diff)

Modification Stripify for mesh discrimination.
Adds submesh operation type.

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       
197        //      Debug.
198        cout    <<      "Write the submesh chunk header"
199                                <<      endl;
200       
201        // Header.
202        writeChunkHeader(M_SUBMESH, calcSubMeshSize(geoSubMesh));
203
204        //      Debug.
205        cout    <<      "Write the material name"
206                                <<      endl;
207
208        // Material Name.
209        materialName    =       getMaterialName();
210        writeString(materialName);
211
212        //      Debug.
213        cout    <<      "Write the shared vertex buffer flag: "
214                                <<      endl;
215
216        // bool useSharedVertices
217        writeBools(geoSubMesh->mSharedVertexBuffer, 1);
218
219        indexCount      =       geoSubMesh->mIndexCount;
220
221        writeInts(indexCount, 1);
222
223        // bool indexes32Bit
224        idx32bit        =       true;
225        writeBools(idx32bit, 1);
226
227        //      Debug.
228        cout    <<      "Write the mIndex array"
229                                <<      endl;
230
231        //      Write the index array.
232        for (int i = 0; i < geoSubMesh->mIndexCount; i++)
233        {
234                writeInts(geoSubMesh->mIndex[i], 1);
235        }
236
237        // M_GEOMETRY stream (Optional: present only if useSharedVertices = false)
238        if (!geoSubMesh->mSharedVertexBuffer)
239        {
240                //      Debug.
241                cout    <<      "Write the geometry of the submesh"
242                                        <<      endl;
243
244                writeGeometry(geoSubMesh->mVertexBuffer);
245        }
246
247        //      Debug.
248        cout    <<      "mIndex array written"
249                                <<      endl;
250
251        // Operation type
252        writeSubMeshOperation(geoSubMesh);
253
254        //TODO:Bones.
255        /*
256        // Bone assignments
257        if (!s->mBoneAssignments.empty())
258        {
259                LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments...");
260
261                SubMesh::VertexBoneAssignmentList::const_iterator vi;
262
263                for (vi = s->mBoneAssignments.begin();
264                                vi != s->mBoneAssignments.end(); ++vi)
265                {
266                        writeSubMeshBoneAssignment(vi->second);
267                }
268
269                LogManager::getSingleton().logMessage("Dedicated geometry bone assignments exported.");
270        }
271        */
272}
273
274//      Write the submesh operation chunk and data.
275void GeoMeshSaver::writeSubMeshOperation(const  SubMesh *geoSubMesh)
276{
277        unsigned        short opType;
278        unsigned        long    size;
279
280        //      Debug.
281        cout    <<      "Write submesh operation"
282                                <<      endl;
283       
284        size    =       CHUNK_OVERHEAD_SIZE     +       sizeof(unsigned short);
285       
286        // Header
287        writeChunkHeader(M_SUBMESH_OPERATION, size);
288
289        //      If the mesh is in triangle strips.
290        if (geoSubMesh->mType   ==      GEO_TRIANGLE_STRIPS)
291        {
292                opType  =       5;
293        }
294        //      If the mesh is in triangle list.
295        else
296        {
297                opType  =       4;
298        }
299       
300        writeShorts(opType, 1);
301
302        //      Debug.
303        cout    <<      "Submesh operation Written"
304                                <<      endl;
305}
306
307//      Write geometry.
308void    GeoMeshSaver::writeGeometry(VertexBuffer        *vertexBuffer)
309{
310        unsigned        short   element;
311        unsigned        long    size;
312        unsigned        short   buffer_count;
313
314        buffer_count    =       3;
315
316       
317        //      Calc the size in bytes of the geometry chunk.
318        size    =       calcGeometrySize(vertexBuffer);
319               
320        //      Header.
321        //
322        //      Write the M_GEOMETRY header.
323        writeChunkHeader(M_GEOMETRY, size);
324
325        writeInts(vertexBuffer->mVertexCount,1);
326
327        //      Vertex declaration.
328        //      Calculate the size of vertex declaration.
329        size    =       CHUNK_OVERHEAD_SIZE
330                                        +
331                                        buffer_count
332                                        *
333                                        (CHUNK_OVERHEAD_SIZE    +       (sizeof(unsigned short) *       5));
334
335        //      Write the vertex declaration header.
336        writeChunkHeader(       M_GEOMETRY_VERTEX_DECLARATION,size);
337
338        //      Obtain the size of the vertex element chunk.
339        size    =       CHUNK_OVERHEAD_SIZE     +       (sizeof(unsigned short) *       5);
340
341        //      Positions.
342        //      Write the vertex element header for position.
343        writeChunkHeader(       M_GEOMETRY_VERTEX_ELEMENT,size);
344
345        element =       0;
346        writeShorts(element,1);
347
348        element =       VET_FLOAT3;
349        writeShorts(element,1);
350       
351        element =       VES_POSITION;
352        writeShorts(element,1);
353       
354        element =       0;
355        writeShorts(element,1);
356       
357        element =       0;
358        writeShorts(element,1);
359
360        //      Normals.
361        //      Write the vertex element header for position.
362        writeChunkHeader(       M_GEOMETRY_VERTEX_ELEMENT,size);
363       
364        element =       1;
365        writeShorts(element,1);
366       
367        element =       VET_FLOAT3;
368        writeShorts(element,1);
369       
370        element =       VES_NORMAL;
371        writeShorts(element,1);
372       
373        element =       0;
374        writeShorts(element,1);
375       
376        element =       0;
377        writeShorts(element,1);
378
379        //      Textures.
380        //      Write the vertex element header for position.
381        writeChunkHeader(M_GEOMETRY_VERTEX_ELEMENT,size);
382       
383        element =       2;
384        writeShorts(element,1);
385       
386        element =       VET_FLOAT2;
387        writeShorts(element,1);
388       
389        element =       VES_TEXTURE_COORDINATES;
390        writeShorts(element,1);
391       
392        element =       0;
393        writeShorts(element,1);
394       
395        element =       0;
396        writeShorts(element,1);
397
398        //      Obtain the size for vertex buffer header for positons.
399        size    =       (2      *       CHUNK_OVERHEAD_SIZE)    +       (2      *       sizeof(unsigned short));
400
401        //      Write the vertex buffer header for positions.
402        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER,      size);
403
404        element =       0;
405        writeShorts(element,1);
406       
407        element =       12;
408        writeShorts(element,1);
409
410        //      Obtain the size for the vertex buffer data header for positions.
411        size    =       CHUNK_OVERHEAD_SIZE
412                                        +
413                                        ((sizeof(float) *       3)      *       vertexBuffer->mVertexCount);
414
415        //      Write the vertex buffer data header for positions.
416        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER_DATA, size);
417
418        //      Write all the positions coords.
419        mSerializer->WriteArray(vertexBuffer->mPosition,
420                                                                                                        vertexBuffer->mVertexCount);
421
422        //      Obtain the size for vertex buffer header for normals.
423        size    =       (2      *       CHUNK_OVERHEAD_SIZE)    +       (2      *       sizeof(unsigned short));
424
425        //      Write the vertex buffer header.
426        writeChunkHeader(       M_GEOMETRY_VERTEX_BUFFER,       size);
427
428        element =       1;
429        writeShorts(element,1);
430       
431        element =       12;
432        writeShorts(element,1);
433
434        //      Obtain the size for the vertex buffer data header for normals.
435        size    =       CHUNK_OVERHEAD_SIZE
436                                        +
437                                        ((sizeof(float) *       3)      *       vertexBuffer->mVertexCount);
438
439        //      Write the vertex buffer data header for normals.
440        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER_DATA, size);
441
442        //      Write all the normals coords.
443        mSerializer->WriteArray(vertexBuffer->mNormal,
444                                                                                                        vertexBuffer->mVertexCount);
445
446        //      Obtain the size for vertex buffer header for textures.
447        size    =       (2      *       CHUNK_OVERHEAD_SIZE)    +       (2      *       sizeof(unsigned short));
448
449        //      Write the vertex buffer header for textures.
450        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER,      size);
451
452        element =       2;
453        writeShorts(element,1);
454       
455        element =       8;
456        writeShorts(element,1);
457
458        //      Obtain the size for the vertex buffer data header for textures.
459        size    =       CHUNK_OVERHEAD_SIZE
460                                        +
461                                        ((sizeof(float) *       2)      *       vertexBuffer->mVertexCount);
462
463        //      Write the vertex buffer data header for textures.
464        writeChunkHeader(M_GEOMETRY_VERTEX_BUFFER_DATA, size);
465
466        //      Debug.
467        cout    <<      "-7-"   <<      endl;
468
469        //      Write all the texture coords.
470        mSerializer->WriteArray(vertexBuffer->mTexCoords,
471                                                                                                        vertexBuffer->mVertexCount);
472
473        //      Debug.
474        cout    <<      "-8-"   <<      endl;
475
476}
477
478//      TODO: Write Mesh Bounds.
479void    GeoMeshSaver::writeMeshBounds(GeometryBounds bounds)
480{
481        size_t  size;
482
483        size    =       CHUNK_OVERHEAD_SIZE
484                                        +
485                                        (sizeof(float)  *       7);
486
487        writeChunkHeader(M_MESH_BOUNDS, size);
488
489        writeFloats(bounds.minx,1);
490        writeFloats(bounds.miny,1);
491        writeFloats(bounds.minz,1);
492        writeFloats(bounds.maxx,1);
493        writeFloats(bounds.maxy,1);
494        writeFloats(bounds.maxz,1);
495        writeFloats(bounds.radius,1);
496}
497
498//      Calc the mesh size in bytes.
499size_t GeoMeshSaver::calcMeshSize(const Mesh    *geoMesh)
500{
501        size_t size = CHUNK_OVERHEAD_SIZE;
502
503        //      Debug.
504        cout    <<      "Calc the size of the mesh"
505                                <<      endl;
506       
507        // Num shared vertices
508        size += sizeof(uint32);
509
510        //      Debug.
511        cout    <<      "VertexCount: "
512                                <<      geoMesh->mVertexBuffer->mVertexCount
513                                <<      endl;
514
515        // Geometry
516        if (geoMesh->mVertexBuffer->mVertexCount > 0)
517        {
518                //      Debug.
519                cout    <<      "Calc the size of the shared vertex buffer"
520                                        <<      endl;
521               
522                size += calcGeometrySize(geoMesh->mVertexBuffer);
523        }
524
525        // Submeshes
526        for (unsigned short i = 0; i < geoMesh->mSubMeshCount; ++i)
527        {
528                //      Debug.
529                cout    <<      "Calc the size of the submesh "
530                                        <<      i
531                                        <<      endl;
532
533                size += calcSubMeshSize(&geoMesh->mSubMesh[i]);
534        }
535
536        //      Mesh Bounds size added.
537        size    +=      CHUNK_OVERHEAD_SIZE
538                                                +
539                                                (sizeof(float)  *       7);
540
541        /*
542        // Skeleton link
543        if (geoMesh->hasSkeleton())
544        {
545                size += calcSkeletonLinkSize(geoMesh->getSkeletonName());
546        }
547        */
548
549        /*
550        // Submesh name table
551        size += calcSubMeshNameTableSize(geoMesh);
552
553        // Edge list
554        if (geoMesh->isEdgeListBuilt())
555        {
556                size += calcEdgeListSize(geoMesh);
557        }
558        */
559       
560        return size;
561}
562
563//      Calc the size in bytes for the submesh.
564size_t GeoMeshSaver::calcSubMeshSize(const SubMesh      *geoSubMesh)
565{
566        size_t size = CHUNK_OVERHEAD_SIZE;
567
568        // Material name
569        size += getMaterialName().length() + 1;
570
571        // bool useSharedVertices
572        size += sizeof(bool);
573        // unsigned int indexCount
574        size += sizeof(unsigned int);
575        // bool indexes32bit
576        size += sizeof(bool);
577
578        // unsigned int* faceVertexIndices
579        size += sizeof(unsigned int) * geoSubMesh->mIndexCount;
580
581        // Geometry
582        if (!geoSubMesh->mSharedVertexBuffer)
583        {
584                size += calcGeometrySize(geoSubMesh->mVertexBuffer);
585        }
586
587        return size;
588}
589
590//      Calc the geometry size in bytes.
591size_t GeoMeshSaver::calcGeometrySize(const VertexBuffer* vertexBuffer)
592{
593        unsigned        long            size;
594        unsigned        long            buffer_count;
595
596        //      and another for normals.
597        buffer_count    =       3;
598
599        //      Calculate the size of the Geometry chunk.
600        size    =       CHUNK_OVERHEAD_SIZE     +       sizeof(unsigned int);
601        size    =       size
602                                        +
603                                        CHUNK_OVERHEAD_SIZE
604                                        +
605                                        buffer_count
606                                        *
607                                        (CHUNK_OVERHEAD_SIZE    +       (sizeof(unsigned short) *       5));
608        size    =       size
609                                        +
610                                        buffer_count
611                                        *
612                                        (       (CHUNK_OVERHEAD_SIZE            *       2)
613                                                +
614                                                (sizeof(unsigned short) *       2)
615                                                +
616                                                vertexBuffer->mVertexCount
617                                        );
618
619        return size;
620}
621
622//      Write the file header.
623void GeoMeshSaver::writeFileHeader(void)
624{
625        String  mesh_version("[MeshSerializer_v1.30]");
626       
627        writeShorts(M_HEADER, 1);
628
629        writeString(mesh_version);
630
631}
632
633//      Write a header chunk given.
634void GeoMeshSaver::writeChunkHeader(unsigned short      id,
635                                                                                                                                                unsigned long           size)
636{
637        mSerializer->WriteData(&id,sizeof(unsigned short),1);
638        mSerializer->WriteData(&size,sizeof(unsigned long),1);
639}
640
641//      Write integers into the file.
642void    GeoMeshSaver::writeInts(unsigned long   id,
643                                                                                                                        unsigned long   count)
644{
645        mSerializer->WriteData(&id,sizeof(id),count);
646}
647
648//      Write shorts into the file
649void    GeoMeshSaver::writeShorts(unsigned short        id,
650                                                                                                                                unsigned long           count)
651{
652        mSerializer->WriteData(&id,sizeof(id),count);
653}
654
655//      Write float into the file.
656void    GeoMeshSaver::writeFloats(float                                         id,
657                                                                                                                                unsigned long           count)
658{
659        mSerializer->WriteData(&id,sizeof(id),count);
660}
661
662//      Write a string into the file.
663void GeoMeshSaver::writeString(const    String  &string)
664{
665        mSerializer->WriteData(string);
666}
667
668//      Write booleans into the file.
669void    GeoMeshSaver::writeBools(       const bool id,
670                                                                                                                                unsigned        long            count)
671{
672        mSerializer->WriteData(&id,sizeof(bool),count);
673}
674
675//      Sets the material of the mesh.
676void    GeoMeshSaver::setMaterialName(String    materialName)
677{
678        mMaterialName   =       materialName;
679}
680
681//      Gets the material of the mesh.
682String  GeoMeshSaver::getMaterialName()
683{
684        return  mMaterialName;
685}
686
687//      Set Mesh Bounds.
688void    GeoMeshSaver::setMeshBounds(GeometryBounds      bounds)
689{
690        mMeshBounds.minx                =       bounds.minx;
691        mMeshBounds.miny                =       bounds.miny;
692        mMeshBounds.minz                =       bounds.minz;
693        mMeshBounds.maxx                =       bounds.maxx;
694        mMeshBounds.maxy                =       bounds.maxy;
695        mMeshBounds.maxz                =       bounds.maxz;
696        mMeshBounds.radius      =       bounds.radius;
697}
698
Note: See TracBrowser for help on using the repository browser.