From 28008debf72710bd82bc06cc0f3bd9675e6eb456 Mon Sep 17 00:00:00 2001 From: ulfjorensen Date: Fri, 21 Jan 2011 15:37:34 +0000 Subject: [PATCH] forgot the new files... git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@895 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/ColladaExporter.cpp | 364 +++++++++++++++++++++++++++++++++++++++ code/ColladaExporter.h | 112 ++++++++++++ 2 files changed, 476 insertions(+) create mode 100644 code/ColladaExporter.cpp create mode 100644 code/ColladaExporter.h diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp new file mode 100644 index 000000000..6fcac6928 --- /dev/null +++ b/code/ColladaExporter.cpp @@ -0,0 +1,364 @@ +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2010, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#include "AssimpPCH.h" +#include "ColladaExporter.h" + +using namespace Assimp; + +namespace Assimp +{ + + // ------------------------------------------------------------------------------------------------ +// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp +void ExportSceneCollada( aiExportDataBlob* pBlob, const aiScene* pScene) +{ + // invoke the exporter + ColladaExporter iDoTheExportThing( pScene); + + // we're still here - export successfully completed. Load result into given blob + pBlob->size = iDoTheExportThing.mOutput.tellp(); + pBlob->data = new char[pBlob->size]; + iDoTheExportThing.mOutput.seekg( 0); + iDoTheExportThing.mOutput.read( (char*) pBlob->data, pBlob->size); +} + +} // end of namespace Assimp + + +// ------------------------------------------------------------------------------------------------ +// Constructor for a specific scene to export +ColladaExporter::ColladaExporter( const aiScene* pScene) +{ + mScene = pScene; + + // set up strings + endstr = "\n"; // std::endl is too complicated for me to insert here. + + // start writing + WriteFile(); +} + +// ------------------------------------------------------------------------------------------------ +// Starts writing the contents +void ColladaExporter::WriteFile() +{ + // write the DTD + mOutput << "" << endstr; + // COLLADA element start + mOutput << "" << endstr; + PushTag(); + + WriteHeader(); + + WriteGeometryLibrary(); + + WriteSceneLibrary(); + + // useless Collada bullshit at the end, just in case we haven't had enough indirections, yet. + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << "" << endstr; +} + +// ------------------------------------------------------------------------------------------------ +// Writes the asset header +void ColladaExporter::WriteHeader() +{ + // Dummy stuff. Nobody actually cares for it anyways + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "Someone" << endstr; + mOutput << startstr << "Assimp Collada Exporter" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "Y_UP" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; +} + +// ------------------------------------------------------------------------------------------------ +// Writes the geometry library +void ColladaExporter::WriteGeometryLibrary() +{ + mOutput << startstr << "" << endstr; + PushTag(); + + for( size_t a = 0; a < mScene->mNumMeshes; ++a) + WriteGeometry( a); + + PopTag(); + mOutput << startstr << "" << endstr; +} + +// ------------------------------------------------------------------------------------------------ +// Writes the given mesh +void ColladaExporter::WriteGeometry( size_t pIndex) +{ + const aiMesh* mesh = mScene->mMeshes[pIndex]; + std::string idstr = GetMeshId( pIndex); + + // opening tag + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + PushTag(); + + // Positions + WriteFloatArray( idstr + "-positions", FloatType_Vector, (float*) mesh->mVertices, mesh->mNumVertices); + // Normals, if any + if( mesh->HasNormals() ) + WriteFloatArray( idstr + "-normals", FloatType_Vector, (float*) mesh->mNormals, mesh->mNumVertices); + + // texture coords + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) + { + if( mesh->HasTextureCoords( a) ) + { + WriteFloatArray( idstr + "-tex" + boost::lexical_cast (a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, + (float*) mesh->mTextureCoords[a], mesh->mNumVertices); + } + } + + // vertex colors + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) + { + if( mesh->HasVertexColors( a) ) + WriteFloatArray( idstr + "-color" + boost::lexical_cast (a), FloatType_Color, (float*) mesh->mColors[a], mesh->mNumVertices); + } + + // assemble vertex structure + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + if( mesh->HasNormals() ) + mOutput << startstr << "" << endstr; + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) + { + if( mesh->HasTextureCoords( a) ) + mOutput << startstr << "" << endstr; + } + for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) + { + if( mesh->HasVertexColors( a) ) + mOutput << startstr << "" << endstr; + } + + PopTag(); + mOutput << startstr << "" << endstr; + + // write face setup + mOutput << startstr << "mNumFaces << "\" material=\"tellme\">" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + + mOutput << startstr << ""; + for( size_t a = 0; a < mesh->mNumFaces; ++a ) + mOutput << mesh->mFaces[a].mNumIndices << " "; + mOutput << "" << endstr; + + mOutput << startstr << "

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

" << endstr; + PopTag(); + mOutput << startstr << "
" << endstr; + + // closing tags + PopTag(); + mOutput << startstr << "
" << endstr; + PopTag(); + mOutput << startstr << "
" << endstr; +} + +// ------------------------------------------------------------------------------------------------ +// Writes a float array of the given type +void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount) +{ + size_t floatsPerElement = 0; + switch( pType ) + { + case FloatType_Vector: floatsPerElement = 3; break; + case FloatType_TexCoord2: floatsPerElement = 2; break; + case FloatType_TexCoord3: floatsPerElement = 3; break; + case FloatType_Color: floatsPerElement = 3; break; + default: + return; + } + + std::string arrayId = pIdString + "-array"; + + mOutput << startstr << "" << endstr; + PushTag(); + + // source array + mOutput << startstr << " "; + PushTag(); + + if( pType == FloatType_TexCoord2 ) + { + for( size_t a = 0; a < pElementCount; ++a ) + { + mOutput << pData[a*3+0] << " "; + mOutput << pData[a*3+1] << " "; + } + } + else if( pType == FloatType_Color ) + { + for( size_t a = 0; a < pElementCount; ++a ) + { + mOutput << pData[a*4+0] << " "; + mOutput << pData[a*4+1] << " "; + mOutput << pData[a*4+2] << " "; + } + } + else + { + for( size_t a = 0; a < pElementCount * floatsPerElement; ++a ) + mOutput << pData[a] << " "; + } + mOutput << "" << endstr; + PopTag(); + + // the usual Collada bullshit. Let's bloat it even more! + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); + + switch( pType ) + { + case FloatType_Vector: + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + break; + + case FloatType_TexCoord2: + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + break; + + case FloatType_TexCoord3: + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + break; + + case FloatType_Color: + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + break; + } + + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; +} + +// ------------------------------------------------------------------------------------------------ +// Writes the scene library +void ColladaExporter::WriteSceneLibrary() +{ + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); + + // start recursive write at the root node + WriteNode( mScene->mRootNode); + + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; +} + +// ------------------------------------------------------------------------------------------------ +// Recursively writes the given node +void ColladaExporter::WriteNode( const aiNode* pNode) +{ + mOutput << startstr << "mName.data << "\" name=\"" << pNode->mName.data << "\">" << endstr; + PushTag(); + + // write transformation - we can directly put the matrix there + // TODO: (thom) decompose into scale - rot - quad to allow adressing it by animations afterwards + const aiMatrix4x4& mat = pNode->mTransformation; + mOutput << startstr << ""; + mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; + mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " "; + mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " "; + mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4; + mOutput << "" << endstr; + + // instance every geometry + for( size_t a = 0; a < pNode->mNumMeshes; ++a ) + { + const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]]; + mOutput << startstr << "" << endstr; + PushTag(); + + PopTag(); + mOutput << startstr << "" << endstr; + } + + // recurse into subnodes + for( size_t a = 0; a < pNode->mNumChildren; ++a ) + WriteNode( pNode->mChildren[a]); + + PopTag(); + mOutput << startstr << "" << endstr; +} diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h new file mode 100644 index 000000000..8c0f2c7fc --- /dev/null +++ b/code/ColladaExporter.h @@ -0,0 +1,112 @@ +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2010, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file ColladaExporter.h + * Declares the exporter class to write a scene to a Collada file + */ +#ifndef AI_COLLADAEXPORTER_H_INC +#define AI_COLLADAEXPORTER_H_INC + +#include "../include/aiAssert.h" +#include + +struct aiScene; +struct aiNode; + +namespace Assimp +{ + +/// Helper class to export a given scene to a Collada file. Just for my personal +/// comfort when implementing it. +class ASSIMP_API ColladaExporter +{ +public: + /// Constructor for a specific scene to export + ColladaExporter( const aiScene* pScene); + +protected: + /// Starts writing the contents + void WriteFile(); + + /// Writes the asset header + void WriteHeader(); + + /// Writes the geometry library + void WriteGeometryLibrary(); + + /// Writes the given mesh + void WriteGeometry( size_t pIndex); + + enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color }; + + /// Writes a float array of the given type + void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount); + + /// Writes the scene library + void WriteSceneLibrary(); + + /// Recursively writes the given node + void WriteNode( const aiNode* pNode); + + /// Enters a new xml element, which increases the indentation + void PushTag() { startstr.append( " "); } + /// Leaves an element, decreasing the indentation + void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); } + + /// Creates a mesh ID for the given mesh + std::string GetMeshId( size_t pIndex) const { return std::string( "meshId" ) + boost::lexical_cast (pIndex); } + +public: + /// Stringstream to write all output into + std::stringstream mOutput; + +protected: + /// The scene to be written + const aiScene* mScene; + + /// current line start string, contains the current indentation for simple stream insertion + std::string startstr; + /// current line end string for simple stream insertion + std::string endstr; +}; + +} + +#endif // !! AI_COLLADAEXPORTER_H_INC