diff options
Diffstat (limited to 'src/3rdparty/assimp/code/ObjExporter.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/ObjExporter.cpp | 185 |
1 files changed, 137 insertions, 48 deletions
diff --git a/src/3rdparty/assimp/code/ObjExporter.cpp b/src/3rdparty/assimp/code/ObjExporter.cpp index ca07730bc..a8bf9935a 100644 --- a/src/3rdparty/assimp/code/ObjExporter.cpp +++ b/src/3rdparty/assimp/code/ObjExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -38,8 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - - #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER @@ -53,17 +52,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/scene.h> #include <memory> - using namespace Assimp; -namespace Assimp { + +namespace Assimp { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp -void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) -{ +void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { // invoke the exporter ObjExporter exporter(pFile, pScene); + if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } + // we're still here - export successfully completed. Write both the main OBJ file and the material script { std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); @@ -81,16 +83,46 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene } } +// ------------------------------------------------------------------------------------------------ +// Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp +void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) { + // invoke the exporter + ObjExporter exporter(pFile, pScene, true); + + if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } + + // we're still here - export successfully completed. Write both the main OBJ file and the material script + { + std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); + if(outfile == NULL) { + throw DeadlyExportError("could not open output .obj file: " + std::string(pFile)); + } + outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1); + } + + +} + } // end of namespace Assimp static const std::string MaterialExt = ".mtl"; // ------------------------------------------------------------------------------------------------ -ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene) +ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl) : filename(_filename) , pScene(pScene) -, endl("\n") -{ +, vp() +, vn() +, vt() +, vc() +, mVpMap() +, mVnMap() +, mVtMap() +, mVcMap() +, mMeshes() +, endl("\n") { // make sure that all formatting happens using the standard, C locale and not the user's current locale const std::locale& l = std::locale("C"); mOutput.imbue(l); @@ -98,8 +130,14 @@ ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene) mOutputMat.imbue(l); mOutputMat.precision(16); - WriteGeometryFile(); - WriteMaterialFile(); + WriteGeometryFile(noMtl); + if (!noMtl) + WriteMaterialFile(); +} + +// ------------------------------------------------------------------------------------------------ +ObjExporter::~ObjExporter() { + } // ------------------------------------------------------------------------------------------------ @@ -116,22 +154,31 @@ std::string ObjExporter :: GetMaterialLibName() } // ------------------------------------------------------------------------------------------------ -std::string ObjExporter :: GetMaterialLibFileName() -{ +std::string ObjExporter::GetMaterialLibFileName() { + // Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl + size_t lastdot = filename.find_last_of('.'); + if (lastdot != std::string::npos) + return filename.substr(0, lastdot) + MaterialExt; + return filename + MaterialExt; } // ------------------------------------------------------------------------------------------------ -void ObjExporter :: WriteHeader(std::ostringstream& out) -{ +void ObjExporter::WriteHeader(std::ostringstream& out) { out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl; - out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl << endl; + out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' + << aiGetVersionRevision() << ")" << endl << endl; } // ------------------------------------------------------------------------------------------------ -std::string ObjExporter :: GetMaterialName(unsigned int index) +std::string ObjExporter::GetMaterialName(unsigned int index) { const aiMaterial* const mat = pScene->mMaterials[index]; + if ( nullptr == mat ) { + static const std::string EmptyStr; + return EmptyStr; + } + aiString s; if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) { return std::string(s.data,s.length); @@ -166,11 +213,17 @@ void ObjExporter::WriteMaterialFile() if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) { mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl; } + if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_TRANSPARENT,c)) { + mOutputMat << "Tf " << c.r << " " << c.g << " " << c.b << endl; + } - float o; + ai_real o; if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) { mOutputMat << "d " << o << endl; } + if(AI_SUCCESS == mat->Get(AI_MATKEY_REFRACTI,o)) { + mOutputMat << "Ni " << o << endl; + } if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) { mOutputMat << "Ns " << o << endl; @@ -205,26 +258,37 @@ void ObjExporter::WriteMaterialFile() } } -// ------------------------------------------------------------------------------------------------ -void ObjExporter :: WriteGeometryFile() -{ +void ObjExporter::WriteGeometryFile(bool noMtl) { WriteHeader(mOutput); - mOutput << "mtllib " << GetMaterialLibName() << endl << endl; + if (!noMtl) + mOutput << "mtllib " << GetMaterialLibName() << endl << endl; // collect mesh geometry aiMatrix4x4 mBase; AddNode(pScene->mRootNode, mBase); - // write vertex positions - vpMap.getVectors(vp); - mOutput << "# " << vp.size() << " vertex positions" << endl; - for(const aiVector3D& v : vp) { - mOutput << "v " << v.x << " " << v.y << " " << v.z << endl; + // write vertex positions with colors, if any + mVpMap.getVectors( vp ); + mVcMap.getColors( vc ); + if ( vc.empty() ) { + mOutput << "# " << vp.size() << " vertex positions" << endl; + for ( const aiVector3D& v : vp ) { + mOutput << "v " << v.x << " " << v.y << " " << v.z << endl; + } + } else { + mOutput << "# " << vp.size() << " vertex positions and colors" << endl; + size_t colIdx = 0; + for ( const aiVector3D& v : vp ) { + if ( colIdx < vc.size() ) { + mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl; + } + ++colIdx; + } } mOutput << endl; // write uv coordinates - vtMap.getVectors(vt); + mVtMap.getVectors(vt); mOutput << "# " << vt.size() << " UV coordinates" << endl; for(const aiVector3D& v : vt) { mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl; @@ -232,7 +296,7 @@ void ObjExporter :: WriteGeometryFile() mOutput << endl; // write vertex normals - vnMap.getVectors(vn); + mVnMap.getVectors(vn); mOutput << "# " << vn.size() << " vertex normals" << endl; for(const aiVector3D& v : vn) { mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl; @@ -240,12 +304,13 @@ void ObjExporter :: WriteGeometryFile() mOutput << endl; // now write all mesh instances - for(const MeshInstance& m : meshes) { + for(const MeshInstance& m : mMeshes) { mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl; if (!m.name.empty()) { mOutput << "g " << m.name << endl; } - mOutput << "usemtl " << m.matname << endl; + if (!noMtl) + mOutput << "usemtl " << m.matname << endl; for(const Face& f : m.faces) { mOutput << f.kind << ' '; @@ -272,8 +337,7 @@ void ObjExporter :: WriteGeometryFile() } // ------------------------------------------------------------------------------------------------ -int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) -{ +int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) { vecIndexMap::dataType::iterator vertIt = vecMap.find(vec); // vertex already exists, so reference it if(vertIt != vecMap.end()){ @@ -286,8 +350,7 @@ int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) } // ------------------------------------------------------------------------------------------------ -void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs ) -{ +void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs ) { vecs.resize(vecMap.size()); for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){ vecs[it->second-1] = it->first; @@ -295,12 +358,33 @@ void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs ) } // ------------------------------------------------------------------------------------------------ -void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) -{ - meshes.push_back(MeshInstance()); - MeshInstance& mesh = meshes.back(); +int ObjExporter::colIndexMap::getIndex( const aiColor4D& col ) { + colIndexMap::dataType::iterator vertIt = colMap.find( col ); + // vertex already exists, so reference it + if ( vertIt != colMap.end() ) { + return vertIt->second; + } + colMap[ col ] = mNextIndex; + int ret = mNextIndex; + mNextIndex++; - mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : ""); + return ret; +} + +// ------------------------------------------------------------------------------------------------ +void ObjExporter::colIndexMap::getColors( std::vector<aiColor4D> &colors ) { + colors.resize( colMap.size() ); + for ( colIndexMap::dataType::iterator it = colMap.begin(); it != colMap.end(); ++it ) { + colors[ it->second - 1 ] = it->first; + } +} + +// ------------------------------------------------------------------------------------------------ +void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { + mMeshes.push_back(MeshInstance()); + MeshInstance& mesh = mMeshes.back(); + + mesh.name = std::string( name.data, name.length ); mesh.matname = GetMaterialName(m->mMaterialIndex); mesh.faces.resize(m->mNumFaces); @@ -325,20 +409,25 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 const unsigned int idx = f.mIndices[a]; aiVector3D vert = mat * m->mVertices[idx]; - face.indices[a].vp = vpMap.getIndex(vert); + face.indices[a].vp = mVpMap.getIndex(vert); if (m->mNormals) { aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx]; - face.indices[a].vn = vnMap.getIndex(norm); - } - else{ + face.indices[a].vn = mVnMap.getIndex(norm); + } else { face.indices[a].vn = 0; } - if (m->mTextureCoords[0]) { - face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]); + if ( nullptr != m->mColors[ 0 ] ) { + aiColor4D col4 = m->mColors[ 0 ][ idx ]; + face.indices[ a ].vc = mVcMap.getIndex( col4 ); + } else { + face.indices[ a ].vc = 0; } - else{ + + if ( m->mTextureCoords[ 0 ] ) { + face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]); + } else { face.indices[a].vt = 0; } } |