2
Copyright (c) 2009 NetAllied Systems GmbH
4
This file is part of dae23ds.
6
Licensed under the MIT Open Source License,
7
for details please see LICENSE file or the website
8
http://www.opensource.org/licenses/mit-license.php
11
#include "DAE23dsStableHeaders.h"
12
#include "DAE23dsWriter.h"
13
#include "DAE23dsMeshWriter.h"
14
#include "DAE23dsMeshHandler.h"
15
#include "DAE23dsMeshLengthCalculator.h"
16
#include "DAE23dsSceneGraphWriter.h"
17
#include "DAE23dsSceneGraphHandler.h"
18
#include "DAE23dsMaterialsLengthCalculator.h"
19
#include "DAE23dsMaterialsWriter.h"
21
#include "COLLADASaxFWLLoader.h"
23
#include "COLLADAFWRoot.h"
24
#include "COLLADAFWGeometry.h"
25
#include "COLLADAFWNode.h"
26
#include "COLLADAFWVisualScene.h"
27
#include "COLLADAFWInstanceGeometry.h"
30
#include "CommonFWriteBufferFlusher.h"
31
#include "CommonCharacterBuffer.h"
36
static size_t FLUSHERBUFFERSIZE = 1024*1024*4;
37
static size_t BUFFERSIZE = 1024*1024*2;
39
static const size_t RESERVED_OBJECTIDS_COUNT = 0;
40
static const size_t RESERVED_MATERIALNUMBERS_COUNT = 1;
43
//--------------------------------------------------------------------
44
bool Writer::InstanceGeometryInfo::operator<( const InstanceGeometryInfo& rhs ) const
46
if (fwInstanceGeometry < rhs.fwInstanceGeometry)
48
if (fwInstanceGeometry > rhs.fwInstanceGeometry)
54
//--------------------------------------------------------------------
55
bool Writer::InstanceGeometryIdentifier::operator<( const InstanceGeometryIdentifier& rhs ) const
57
if (fwInstanceGeometry < rhs.fwInstanceGeometry)
59
if (fwInstanceGeometry > rhs.fwInstanceGeometry)
62
if (instanceNumber < rhs.instanceNumber)
64
if (instanceNumber > rhs.instanceNumber)
70
//--------------------------------------------------------------------
71
Writer::Writer( const COLLADABU::URI& inputFile, const COLLADABU::URI& outputFile, bool applyTransformationsToMeshes )
72
: mInputFile(inputFile)
73
, mOutputFile(outputFile)
74
, mApplyTransformationsToMeshes(applyTransformationsToMeshes)
76
, mCurrentRun(SCENEGRAPH_RUN)
78
, mGeometryMaterialBindingFileNameMap(compare)
79
, mObjectAndMaterialBlockLength(0)
80
, mNextObjectId( RESERVED_OBJECTIDS_COUNT )
81
, mNextMaterialNumber( RESERVED_MATERIALNUMBERS_COUNT )
85
//--------------------------------------------------------------------
91
//--------------------------------------------------------------------
92
void Writer::reportError( const String& method, const String& message, Severity severity )
96
case SEVERITY_INFORMATION:
97
std::cout << "Information";
99
case SEVERITY_WARNING:
100
std::cout << "Warning";
102
case _SEVERITY_ERROR:
103
std::cout << "Error";
106
if ( !method.empty() )
107
std::cout << " in " << method;
109
std::cout << message << std::endl;
112
//--------------------------------------------------------------------
115
COLLADASaxFWL::Loader loader;
116
COLLADAFW::Root root(&loader, this);
118
Common::FWriteBufferFlusher bufferFlusher( getOutputFile().toNativePath().c_str(), FLUSHERBUFFERSIZE );
119
Common::Buffer buffer( BUFFERSIZE, &bufferFlusher);
124
loader.setObjectFlags( COLLADASaxFWL::Loader::ASSET_FLAG
125
| COLLADASaxFWL::Loader::EFFECT_FLAG
126
| COLLADASaxFWL::Loader::MATERIAL_FLAG
127
| COLLADASaxFWL::Loader::LIBRARY_NODES_FLAG
128
| COLLADASaxFWL::Loader::VISUAL_SCENES_FLAG
129
| COLLADASaxFWL::Loader::SCENE_FLAG
130
| COLLADASaxFWL::Loader::GEOMETRY_FLAG);
131
if ( !root.loadDocument(mInputFile.toNativePath()) )
134
createUniqueIdNodeMap();
136
SceneGraphHandler sceneGraphHandler(this, mVisualScene, mLibraryNodesList);
137
sceneGraphHandler.handle();
139
calculateMaterialsBlockLength();
140
calculateMeshesLength();
142
writeHeader( sceneGraphHandler.getScenegraphLength() );
143
writeMaterialsBlocks();
145
// load and write geometries
146
mCurrentRun = GEOMETRY_RUN;
147
if ( !root.loadDocument(mInputFile.toNativePath()) )
150
SceneGraphWriter sceneGraphWriter(this, mVisualScene, mLibraryNodesList);
151
sceneGraphWriter.write( sceneGraphHandler.getScenegraphLength() );
156
//--------------------------------------------------------------------
157
void Writer::calculateMeshesLength()
159
MeshDataMap::const_iterator it = mMeshDataMap.begin();
160
for ( ; it != mMeshDataMap.end(); ++it)
162
const MeshData& meshData = it->second;
163
MeshLengthCalculator meshLengthCalculator( this, meshData );
164
meshLengthCalculator.handle();
168
//--------------------------------------------------------------------
169
void Writer::calculateMaterialsBlockLength()
171
MaterialsLengthCalculator materialsLengthCalculator(this);
172
materialsLengthCalculator.calculate();
175
//--------------------------------------------------------------------
176
void Writer::writeMaterialsBlocks()
178
MaterialsWriter materialsWriter(this);
179
materialsWriter.write();
182
//------------------------------
183
void Writer::createUniqueIdNodeMap( COLLADAFW::Node* node )
185
mUniqueIdNodeMap[node->getUniqueId()] = node;
186
createUniqueIdNodeMap( node->getChildNodes() );
189
//------------------------------
190
void Writer::createUniqueIdNodeMap( const COLLADAFW::NodePointerArray& nodes )
192
for ( size_t i = 0, cout = nodes.getCount(); i < cout; ++i)
194
COLLADAFW::Node* node = nodes[i];
195
createUniqueIdNodeMap( node );
199
//------------------------------
200
void Writer::createUniqueIdNodeMap()
202
createUniqueIdNodeMap( mVisualScene->getRootNodes() );
203
Writer::LibraryNodesList::const_iterator it = mLibraryNodesList.begin();
204
for ( ; it != mLibraryNodesList.end(); ++it )
206
const COLLADAFW::LibraryNodes& libraryNodes = *it;
207
createUniqueIdNodeMap( libraryNodes.getNodes() );
212
//--------------------------------------------------------------------
213
void Writer::cancel( const String& errorMessage )
217
//--------------------------------------------------------------------
222
//--------------------------------------------------------------------
223
void Writer::finish()
227
//--------------------------------------------------------------------
228
bool Writer::writeGlobalAsset( const COLLADAFW::FileInfo* asset )
230
if ( mCurrentRun != SCENEGRAPH_RUN )
235
//--------------------------------------------------------------------
236
bool Writer::writeVisualScene( const COLLADAFW::VisualScene* visualScene )
238
if ( mCurrentRun != SCENEGRAPH_RUN )
240
mVisualScene = new COLLADAFW::VisualScene(*visualScene);
244
//--------------------------------------------------------------------
245
bool Writer::writeLibraryNodes( const COLLADAFW::LibraryNodes* libraryNodes )
247
if ( mCurrentRun != SCENEGRAPH_RUN )
249
mLibraryNodesList.push_back(*libraryNodes);
253
//--------------------------------------------------------------------
254
bool Writer::writeGeometry( const COLLADAFW::Geometry* geometry )
256
if ( geometry->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH )
259
switch ( mCurrentRun )
263
MeshHandler meshHandler( this, (COLLADAFW::Mesh*)geometry );
264
return meshHandler.handle();
269
MeshWriter meshWriter( this, (COLLADAFW::Mesh*)geometry );
270
return meshWriter.handle();
278
//--------------------------------------------------------------------
279
bool Writer::writeMaterial( const COLLADAFW::Material* material )
281
if ( mCurrentRun != SCENEGRAPH_RUN )
283
mUniqueIdFWMaterialMap.insert(std::make_pair(material->getUniqueId(),*material ));
287
//--------------------------------------------------------------------
288
bool Writer::writeEffect( const COLLADAFW::Effect* effect )
290
if ( mCurrentRun != SCENEGRAPH_RUN )
292
mUniqueIdFWEffectMap.insert(std::make_pair(effect->getUniqueId(),*effect ));
296
//--------------------------------------------------------------------
297
bool Writer::writeCamera( const COLLADAFW::Camera* camera )
299
if ( mCurrentRun != SCENEGRAPH_RUN )
304
//--------------------------------------------------------------------
305
bool Writer::writeImage( const COLLADAFW::Image* image )
307
if ( mCurrentRun != SCENEGRAPH_RUN )
309
mUniqueIdFWImageMap.insert(std::make_pair(image->getUniqueId(),*image ));
313
//--------------------------------------------------------------------
314
bool Writer::writeLight( const COLLADAFW::Light* light )
316
if ( mCurrentRun != SCENEGRAPH_RUN )
321
//--------------------------------------------------------------------
322
bool Writer::writeAnimation( const COLLADAFW::Animation* animation )
327
//--------------------------------------------------------------------
328
bool Writer::writeAnimationList( const COLLADAFW::AnimationList* animationList )
333
//--------------------------------------------------------------------
334
void Writer::fillMaterialBindingMap(const GeometryMaterialBinding& materialBinding)
336
const COLLADAFW::MaterialBindingArray& fwBindings = materialBinding.fwInstanceGeometry->getMaterialBindings();
337
size_t fwBindingCount = fwBindings.getCount();
339
if ( fwBindingCount == materialBinding.bindingMap.size() )
341
//both container have already equal size. Nothing to do
345
for ( size_t i = 0; i< fwBindingCount; ++i)
347
const COLLADAFW::MaterialBinding& fwBinding = fwBindings[i];
348
materialBinding.bindingMap.insert(std::make_pair(fwBinding.getMaterialId(), fwBinding.getReferencedMaterial()));
352
//--------------------------------------------------------------------
353
bool Writer::compare( const GeometryMaterialBinding& lhs, const GeometryMaterialBinding& rhs )
355
const COLLADAFW::UniqueId& lhsGeometryUniqueId = lhs.fwInstanceGeometry->getInstanciatedObjectId();
356
const COLLADAFW::UniqueId& rhsGeometryUniqueId = rhs.fwInstanceGeometry->getInstanciatedObjectId();
358
if ( lhsGeometryUniqueId < rhsGeometryUniqueId )
361
if ( lhsGeometryUniqueId > rhsGeometryUniqueId )
364
const COLLADAFW::MaterialBindingArray& lhsFwBinding = lhs.fwInstanceGeometry->getMaterialBindings();
365
const COLLADAFW::MaterialBindingArray& rhsFwBinding = rhs.fwInstanceGeometry->getMaterialBindings();
367
if ( lhsFwBinding.getCount() < rhsFwBinding.getCount() )
370
if ( lhsFwBinding.getCount() > rhsFwBinding.getCount() )
373
fillMaterialBindingMap(lhs);
374
fillMaterialBindingMap(rhs);
376
const MaterialBindingMap& lhsBindingMap = lhs.bindingMap;
377
const MaterialBindingMap& rhsBindingMap = rhs.bindingMap;
379
assert(lhsBindingMap.size() == rhsBindingMap.size());
381
MaterialBindingMap::const_iterator lhsIt = lhsBindingMap.begin();
382
MaterialBindingMap::const_iterator rhsIt = rhsBindingMap.begin();
384
for ( ; lhsIt != lhsBindingMap.end(); ++lhsIt, ++rhsIt)
386
if ( lhsIt->first < rhsIt->first )
389
if ( lhsIt->first > rhsIt->first )
392
if ( lhsIt->second < rhsIt->second )
395
if ( lhsIt->second > rhsIt->second )
402
//--------------------------------------------------------------------
403
bool Writer::writeHeader( ChunkLength sceneGraphLength )
406
//plus material blocks
407
//plus plus empty chunk
408
ChunkLength edit3DSLength = mObjectAndMaterialBlockLength + EMPTY_CHUNK_LENGTH ;
410
// add mesh version size
411
edit3DSLength += MESH_VERSION_CHUNK_LENGTH;
413
// add EDIT_MASTERSCALE version length
414
edit3DSLength += EDIT_MASTERSCALE_CHUNK_LENGTH;
417
// edit 3ds plus empty chunk
418
ChunkLength mainLength = edit3DSLength + EMPTY_CHUNK_LENGTH;
420
// add M3D3DS_VERSION version length and scene graph length
421
mainLength += M3D_VERSION_CHUNK_LENGTH+ sceneGraphLength;
427
mBuffer->copyToBuffer(MAIN3DS);
428
mBuffer->copyToBuffer(mainLength);
431
// M3D_VERSION version
432
mBuffer->copyToBuffer(M3D3DS_VERSION);
433
mBuffer->copyToBuffer(M3D_VERSION_CHUNK_LENGTH);
434
mBuffer->copyToBuffer(M3D_VERSION);
437
mBuffer->copyToBuffer(EDIT3DS);
438
mBuffer->copyToBuffer(edit3DSLength);
441
mBuffer->copyToBuffer(MESH3DS_VERSION);
442
mBuffer->copyToBuffer(MESH_VERSION_CHUNK_LENGTH);
443
mBuffer->copyToBuffer(MESH_VERSION);
446
mBuffer->copyToBuffer(EDIT_MASTERSCALE);
447
mBuffer->copyToBuffer(EDIT_MASTERSCALE_CHUNK_LENGTH);
448
mBuffer->copyToBuffer((float)1);
453
//--------------------------------------------------------------------
454
ChunkLength Writer::getObjectNameLength()
456
return OBJECT_NAME_LENGTH;
459
//--------------------------------------------------------------------
460
ChunkLength Writer::getMaterialNameLength()
462
return OBJECT_NAME_LENGTH;
465
//--------------------------------------------------------------------
466
template<class NumberType, char prefix>
467
const char* Writer::calculateNameFromNumber( const NumberType& number)
469
// we do not support to big meshes here
470
assert(number < 100000);
471
static char buffer[OBJECT_NAME_LENGTH];
474
if ( number < 1000000) *(p++) = '0';
475
if ( number < 100000) *(p++) = '0';
476
if ( number < 10000) *(p++) = '0';
477
if ( number < 100) *(p++) = '0';
478
if ( number < 10) *(p++) = '0';
479
p += Common::itoa( number, p, 10);
485
//--------------------------------------------------------------------
486
const char* Writer::calculateMaterialNameFromMaterialNumer( const MaterialNumber& materialNumber)
488
return calculateNameFromNumber<MaterialNumber, 'M'>(materialNumber);
491
//--------------------------------------------------------------------
492
const char* Writer::calculateObjectNameFromObjectId( const ObjectId& objectId)
494
return calculateNameFromNumber<ObjectId, 'G'>(objectId);
497
} // namespace DAE23ds