nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: #include "AssimpPCH.h" nuclear@0: nuclear@0: #ifndef ASSIMP_BUILD_NO_EXPORT nuclear@0: #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER nuclear@0: #include "ColladaExporter.h" nuclear@0: nuclear@0: using namespace Assimp; nuclear@0: nuclear@0: namespace Assimp nuclear@0: { nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp nuclear@0: void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene) nuclear@0: { nuclear@0: // invoke the exporter nuclear@0: ColladaExporter iDoTheExportThing( pScene); nuclear@0: nuclear@0: // we're still here - export successfully completed. Write result to the given IOSYstem nuclear@0: boost::scoped_ptr outfile (pIOSystem->Open(pFile,"wt")); nuclear@0: if(outfile == NULL) { nuclear@0: throw DeadlyExportError("could not open output .dae file: " + std::string(pFile)); nuclear@0: } nuclear@0: nuclear@0: // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy. nuclear@0: outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast(iDoTheExportThing.mOutput.tellp()),1); nuclear@0: } nuclear@0: nuclear@0: } // end of namespace Assimp nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Constructor for a specific scene to export nuclear@0: ColladaExporter::ColladaExporter( const aiScene* pScene) nuclear@0: { nuclear@0: // make sure that all formatting happens using the standard, C locale and not the user's current locale nuclear@0: mOutput.imbue( std::locale("C") ); nuclear@0: nuclear@0: mScene = pScene; nuclear@0: nuclear@0: // set up strings nuclear@0: endstr = "\n"; nuclear@0: nuclear@0: // start writing nuclear@0: WriteFile(); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Starts writing the contents nuclear@0: void ColladaExporter::WriteFile() nuclear@0: { nuclear@0: // write the DTD nuclear@0: mOutput << "" << endstr; nuclear@0: // COLLADA element start nuclear@0: mOutput << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: WriteHeader(); nuclear@0: nuclear@0: WriteMaterials(); nuclear@0: WriteGeometryLibrary(); nuclear@0: nuclear@0: WriteSceneLibrary(); nuclear@0: nuclear@0: // useless Collada fu at the end, just in case we haven't had enough indirections, yet. nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes the asset header nuclear@0: void ColladaExporter::WriteHeader() nuclear@0: { nuclear@0: // Dummy stuff. Nobody actually cares for it anyways nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "Someone" << endstr; nuclear@0: mOutput << startstr << "Assimp Collada Exporter" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "2000-01-01T23:59:59" << endstr; nuclear@0: mOutput << startstr << "2000-01-01T23:59:59" << endstr; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "Y_UP" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Reads a single surface entry from the given material keys nuclear@0: void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) nuclear@0: { nuclear@0: if( pSrcMat->GetTextureCount( pTexture) > 0 ) nuclear@0: { nuclear@0: aiString texfile; nuclear@0: unsigned int uvChannel = 0; nuclear@0: pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); nuclear@0: poSurface.texture = texfile.C_Str(); nuclear@0: poSurface.channel = uvChannel; nuclear@0: } else nuclear@0: { nuclear@0: if( pKey ) nuclear@0: pSrcMat->Get( pKey, pType, pIndex, poSurface.color); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes an image entry for the given surface nuclear@0: void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) nuclear@0: { nuclear@0: if( !pSurface.texture.empty() ) nuclear@0: { nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << ""; nuclear@0: for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) nuclear@0: { nuclear@0: if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) nuclear@0: mOutput << *it; nuclear@0: else nuclear@0: mOutput << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; nuclear@0: } nuclear@0: mOutput << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes a color-or-texture entry into an effect definition nuclear@0: void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName) nuclear@0: { nuclear@0: mOutput << startstr << "<" << pTypeName << ">" << endstr; nuclear@0: PushTag(); nuclear@0: if( pSurface.texture.empty() ) nuclear@0: { nuclear@0: mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; nuclear@0: } else nuclear@0: { nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes the two parameters necessary for referencing a texture in an effect entry nuclear@0: void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName) nuclear@0: { nuclear@0: // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture nuclear@0: if( !pSurface.texture.empty() ) nuclear@0: { nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << pMatName << "-" << pTypeName << "-image" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << pMatName << "-" << pTypeName << "-surface" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes the material setup nuclear@0: void ColladaExporter::WriteMaterials() nuclear@0: { nuclear@0: materials.resize( mScene->mNumMaterials); nuclear@0: nuclear@0: /// collect all materials from the scene nuclear@0: size_t numTextures = 0; nuclear@0: for( size_t a = 0; a < mScene->mNumMaterials; ++a ) nuclear@0: { nuclear@0: const aiMaterial* mat = mScene->mMaterials[a]; nuclear@0: nuclear@0: aiString name; nuclear@0: if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) nuclear@0: name = "mat"; nuclear@0: materials[a].name = std::string( "m") + boost::lexical_cast (a) + name.C_Str(); nuclear@0: for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) nuclear@0: if( !isalnum( *it) ) nuclear@0: *it = '_'; nuclear@0: nuclear@0: ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); nuclear@0: if( !materials[a].ambient.texture.empty() ) numTextures++; nuclear@0: ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); nuclear@0: if( !materials[a].diffuse.texture.empty() ) numTextures++; nuclear@0: ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); nuclear@0: if( !materials[a].specular.texture.empty() ) numTextures++; nuclear@0: ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); nuclear@0: if( !materials[a].emissive.texture.empty() ) numTextures++; nuclear@0: ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); nuclear@0: if( !materials[a].reflective.texture.empty() ) numTextures++; nuclear@0: ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); nuclear@0: if( !materials[a].normal.texture.empty() ) numTextures++; nuclear@0: nuclear@0: mat->Get( AI_MATKEY_SHININESS, materials[a].shininess); nuclear@0: } nuclear@0: nuclear@0: // output textures if present nuclear@0: if( numTextures > 0 ) nuclear@0: { nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) nuclear@0: { nuclear@0: const Material& mat = *it; nuclear@0: WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); nuclear@0: WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); nuclear@0: WriteImageEntry( mat.specular, mat.name + "-specular-image"); nuclear@0: WriteImageEntry( mat.emissive, mat.name + "-emissive-image"); nuclear@0: WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); nuclear@0: WriteImageEntry( mat.normal, mat.name + "-normal-image"); nuclear@0: } nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: // output effects - those are the actual carriers of information nuclear@0: if( !materials.empty() ) nuclear@0: { nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) nuclear@0: { nuclear@0: const Material& mat = *it; nuclear@0: // this is so ridiculous it must be right nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: // write sampler- and surface params for the texture entries nuclear@0: WriteTextureParamEntry( mat.emissive, "emissive", mat.name); nuclear@0: WriteTextureParamEntry( mat.ambient, "ambient", mat.name); nuclear@0: WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); nuclear@0: WriteTextureParamEntry( mat.specular, "specular", mat.name); nuclear@0: WriteTextureParamEntry( mat.reflective, "reflective", mat.name); nuclear@0: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emissive-sampler"); nuclear@0: WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); nuclear@0: WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); nuclear@0: WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); nuclear@0: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << mat.shininess << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: nuclear@0: WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); nuclear@0: nuclear@0: // deactivated because the Collada spec PHONG model does not allow other textures. nuclear@0: // if( !mat.normal.texture.empty() ) nuclear@0: // WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); nuclear@0: nuclear@0: nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: nuclear@0: // write materials - they're just effect references nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) nuclear@0: { nuclear@0: const Material& mat = *it; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes the geometry library nuclear@0: void ColladaExporter::WriteGeometryLibrary() nuclear@0: { nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: for( size_t a = 0; a < mScene->mNumMeshes; ++a) nuclear@0: WriteGeometry( a); nuclear@0: nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes the given mesh nuclear@0: void ColladaExporter::WriteGeometry( size_t pIndex) nuclear@0: { nuclear@0: const aiMesh* mesh = mScene->mMeshes[pIndex]; nuclear@0: std::string idstr = GetMeshId( pIndex); nuclear@0: nuclear@0: if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) nuclear@0: return; nuclear@0: nuclear@0: // opening tag nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: // Positions nuclear@0: WriteFloatArray( idstr + "-positions", FloatType_Vector, (float*) mesh->mVertices, mesh->mNumVertices); nuclear@0: // Normals, if any nuclear@0: if( mesh->HasNormals() ) nuclear@0: WriteFloatArray( idstr + "-normals", FloatType_Vector, (float*) mesh->mNormals, mesh->mNumVertices); nuclear@0: nuclear@0: // texture coords nuclear@0: for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) nuclear@0: { nuclear@0: if( mesh->HasTextureCoords( a) ) nuclear@0: { nuclear@0: WriteFloatArray( idstr + "-tex" + boost::lexical_cast (a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, nuclear@0: (float*) mesh->mTextureCoords[a], mesh->mNumVertices); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // vertex colors nuclear@0: for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) nuclear@0: { nuclear@0: if( mesh->HasVertexColors( a) ) nuclear@0: WriteFloatArray( idstr + "-color" + boost::lexical_cast (a), FloatType_Color, (float*) mesh->mColors[a], mesh->mNumVertices); nuclear@0: } nuclear@0: nuclear@0: // assemble vertex structure nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: if( mesh->HasNormals() ) nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) nuclear@0: { nuclear@0: if( mesh->HasTextureCoords( a) ) nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) nuclear@0: { nuclear@0: if( mesh->HasVertexColors( a) ) nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: nuclear@0: // write face setup nuclear@0: mOutput << startstr << "mNumFaces << "\" material=\"theresonlyone\">" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: nuclear@0: mOutput << startstr << ""; nuclear@0: for( size_t a = 0; a < mesh->mNumFaces; ++a ) nuclear@0: mOutput << mesh->mFaces[a].mNumIndices << " "; nuclear@0: mOutput << "" << endstr; nuclear@0: nuclear@0: mOutput << startstr << "

"; nuclear@0: for( size_t a = 0; a < mesh->mNumFaces; ++a ) nuclear@0: { nuclear@0: const aiFace& face = mesh->mFaces[a]; nuclear@0: for( size_t b = 0; b < face.mNumIndices; ++b ) nuclear@0: mOutput << face.mIndices[b] << " "; nuclear@0: } nuclear@0: mOutput << "

" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "
" << endstr; nuclear@0: nuclear@0: // closing tags nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "
" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "
" << endstr; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes a float array of the given type nuclear@0: void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount) nuclear@0: { nuclear@0: size_t floatsPerElement = 0; nuclear@0: switch( pType ) nuclear@0: { nuclear@0: case FloatType_Vector: floatsPerElement = 3; break; nuclear@0: case FloatType_TexCoord2: floatsPerElement = 2; break; nuclear@0: case FloatType_TexCoord3: floatsPerElement = 3; break; nuclear@0: case FloatType_Color: floatsPerElement = 3; break; nuclear@0: default: nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: std::string arrayId = pIdString + "-array"; nuclear@0: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: // source array nuclear@0: mOutput << startstr << " "; nuclear@0: PushTag(); nuclear@0: nuclear@0: if( pType == FloatType_TexCoord2 ) nuclear@0: { nuclear@0: for( size_t a = 0; a < pElementCount; ++a ) nuclear@0: { nuclear@0: mOutput << pData[a*3+0] << " "; nuclear@0: mOutput << pData[a*3+1] << " "; nuclear@0: } nuclear@0: } nuclear@0: else if( pType == FloatType_Color ) nuclear@0: { nuclear@0: for( size_t a = 0; a < pElementCount; ++a ) nuclear@0: { nuclear@0: mOutput << pData[a*4+0] << " "; nuclear@0: mOutput << pData[a*4+1] << " "; nuclear@0: mOutput << pData[a*4+2] << " "; nuclear@0: } nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: for( size_t a = 0; a < pElementCount * floatsPerElement; ++a ) nuclear@0: mOutput << pData[a] << " "; nuclear@0: } nuclear@0: mOutput << "" << endstr; nuclear@0: PopTag(); nuclear@0: nuclear@0: // the usual Collada fun. Let's bloat it even more! nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: switch( pType ) nuclear@0: { nuclear@0: case FloatType_Vector: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: break; nuclear@0: nuclear@0: case FloatType_TexCoord2: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: break; nuclear@0: nuclear@0: case FloatType_TexCoord3: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: break; nuclear@0: nuclear@0: case FloatType_Color: nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: break; nuclear@0: } nuclear@0: nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Writes the scene library nuclear@0: void ColladaExporter::WriteSceneLibrary() nuclear@0: { nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: // start recursive write at the root node nuclear@0: WriteNode( mScene->mRootNode); nuclear@0: nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Recursively writes the given node nuclear@0: void ColladaExporter::WriteNode( const aiNode* pNode) nuclear@0: { nuclear@0: mOutput << startstr << "mName.data << "\" name=\"" << pNode->mName.data << "\">" << endstr; nuclear@0: PushTag(); nuclear@0: nuclear@0: // write transformation - we can directly put the matrix there nuclear@0: // TODO: (thom) decompose into scale - rot - quad to allow adressing it by animations afterwards nuclear@0: const aiMatrix4x4& mat = pNode->mTransformation; nuclear@0: mOutput << startstr << ""; nuclear@0: mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; nuclear@0: mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " "; nuclear@0: mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " "; nuclear@0: mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4; nuclear@0: mOutput << "" << endstr; nuclear@0: nuclear@0: // instance every geometry nuclear@0: for( size_t a = 0; a < pNode->mNumMeshes; ++a ) nuclear@0: { nuclear@0: const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]]; nuclear@0: // do not instanciate mesh if empty. I wonder how this could happen nuclear@0: if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) nuclear@0: continue; nuclear@0: nuclear@0: mOutput << startstr << "mMeshes[a]) << "\">" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PushTag(); nuclear@0: mOutput << startstr << "mMaterialIndex].name << "\" />" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: // recurse into subnodes nuclear@0: for( size_t a = 0; a < pNode->mNumChildren; ++a ) nuclear@0: WriteNode( pNode->mChildren[a]); nuclear@0: nuclear@0: PopTag(); nuclear@0: mOutput << startstr << "" << endstr; nuclear@0: } nuclear@0: nuclear@0: #endif nuclear@0: #endif nuclear@0: