From 8f34c24ae0fd9c49eb90d8f1c1cc2b3c85fd3e30 Mon Sep 17 00:00:00 2001 From: Marshall Hahn Date: Mon, 30 Sep 2013 14:07:53 -0400 Subject: [PATCH 1/4] remove duplicate vectors when export obj format --- code/ObjExporter.cpp | 54 +++++++++++++++++++++++++++----------- code/ObjExporter.h | 15 +++++++++++ include/assimp/vector3.h | 1 + include/assimp/vector3.inl | 10 +++++++ 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 9ac902ee3..6cc1063d2 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -59,16 +59,10 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene // we're still here - export successfully completed. Write both the main OBJ file and the material script { boost::scoped_ptr 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(exporter.mOutput.tellp()),1); } { boost::scoped_ptr outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt")); - if(outfile == NULL) { - throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName())); - } outfile->Write( exporter.mOutputMat.str().c_str(), static_cast(exporter.mOutputMat.tellp()),1); } } @@ -199,6 +193,7 @@ void ObjExporter :: WriteGeometryFile() AddNode(pScene->mRootNode,mBase); // write vertex positions + vpMap.getVectors(vp); mOutput << "# " << vp.size() << " vertex positions" << endl; BOOST_FOREACH(const aiVector3D& v, vp) { mOutput << "v " << v.x << " " << v.y << " " << v.z << endl; @@ -206,6 +201,7 @@ void ObjExporter :: WriteGeometryFile() mOutput << endl; // write uv coordinates + vtMap.getVectors(vt); mOutput << "# " << vt.size() << " UV coordinates" << endl; BOOST_FOREACH(const aiVector3D& v, vt) { mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl; @@ -213,6 +209,7 @@ void ObjExporter :: WriteGeometryFile() mOutput << endl; // write vertex normals + vnMap.getVectors(vn); mOutput << "# " << vn.size() << " vertex normals" << endl; BOOST_FOREACH(const aiVector3D& v, vn) { mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl; @@ -252,6 +249,31 @@ void ObjExporter :: WriteGeometryFile() } } + + + + +int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) +{ + std::map::iterator vertIt = vecMap.find(vec); + if(vertIt != vecMap.end()){// vertex already exists, so reference it + return vertIt->second; + } + vecMap[vec] = mNextIndex; + int ret = mNextIndex; + mNextIndex++; + return ret; +} + +void ObjExporter::vecIndexMap::getVectors( std::vector& vecs ) +{ + vecs.resize(vecMap.size()); + for(std::map::iterator it = vecMap.begin(); it != vecMap.end(); it++){ + vecs[it->second-1] = it->first; + } +} + + // ------------------------------------------------------------------------------------------------ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { @@ -262,6 +284,7 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri mesh.matname = GetMaterialName(m->mMaterialIndex); mesh.faces.resize(m->mNumFaces); + for(unsigned int i = 0; i < m->mNumFaces; ++i) { const aiFace& f = m->mFaces[i]; @@ -281,21 +304,22 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri for(unsigned int a = 0; a < f.mNumIndices; ++a) { const unsigned int idx = f.mIndices[a]; - // XXX need a way to check if this is an unique vertex or if we had it already, - // in which case we should instead reference the previous occurrence. - ai_assert(m->mVertices); - vp.push_back( mat * m->mVertices[idx] ); - face.indices[a].vp = vp.size(); + aiVector3D vert = mat * m->mVertices[idx]; + face.indices[a].vp = vpMap.getIndex(vert); if (m->mNormals) { - vn.push_back( m->mNormals[idx] ); + face.indices[a].vn = vnMap.getIndex(m->mNormals[idx]); + } + else{ + face.indices[a].vn = 0; } - face.indices[a].vn = vn.size(); if (m->mTextureCoords[0]) { - vt.push_back( m->mTextureCoords[0][idx] ); + face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]); + } + else{ + face.indices[a].vt = 0; } - face.indices[a].vt = vt.size(); } } } diff --git a/code/ObjExporter.h b/code/ObjExporter.h index f857f5879..4f2f83240 100644 --- a/code/ObjExporter.h +++ b/code/ObjExporter.h @@ -112,6 +112,21 @@ private: const aiScene* const pScene; std::vector vp, vn, vt; + + class vecIndexMap + { + int mNextIndex; + std::map vecMap; + public: + + vecIndexMap():mNextIndex(1) + {} + + int getIndex(const aiVector3D& vec); + void getVectors( std::vector& vecs ); + }; + + vecIndexMap vpMap, vnMap, vtMap; std::vector meshes; // this endl() doesn't flush() the stream diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index cbdee264d..5b3da297d 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -85,6 +85,7 @@ public: // comparison bool operator== (const aiVector3t& other) const; bool operator!= (const aiVector3t& other) const; + bool operator< (const aiVector3t& other) const; template operator aiVector3t () const; diff --git a/include/assimp/vector3.inl b/include/assimp/vector3.inl index c03437980..90370fa07 100644 --- a/include/assimp/vector3.inl +++ b/include/assimp/vector3.inl @@ -149,6 +149,16 @@ AI_FORCE_INLINE bool aiVector3t::operator!= (const aiVector3t& oth } // ------------------------------------------------------------------------------------------------ template +AI_FORCE_INLINE bool aiVector3t::operator< (const aiVector3t& other) const { + if(x < other.x) return true; + if(x > other.x) return false; + if(y < other.y) return true; + if(y > other.y) return false; + if(z < other.z) return true; + return false; +} +// ------------------------------------------------------------------------------------------------ +template AI_FORCE_INLINE const aiVector3t aiVector3t::SymMul(const aiVector3t& o) { return aiVector3t(x*o.x,y*o.y,z*o.z); } From 66fd9bb8a28ea170522d1d50fc3c3c51bdfbbefb Mon Sep 17 00:00:00 2001 From: Marshall Hahn Date: Mon, 30 Sep 2013 14:11:37 -0400 Subject: [PATCH 2/4] fixed bad merge --- code/ObjExporter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 6cc1063d2..bbf26ce56 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -59,10 +59,16 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene // we're still here - export successfully completed. Write both the main OBJ file and the material script { boost::scoped_ptr 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(exporter.mOutput.tellp()),1); } { boost::scoped_ptr outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt")); + if(outfile == NULL) { + throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName())); + } outfile->Write( exporter.mOutputMat.str().c_str(), static_cast(exporter.mOutputMat.tellp()),1); } } From b72b16c90b025486a756caad68838cbd7b77f887 Mon Sep 17 00:00:00 2001 From: Marshall Hahn Date: Mon, 30 Sep 2013 14:12:38 -0400 Subject: [PATCH 3/4] whitespace fix --- code/ObjExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index bbf26ce56..dce217d12 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -60,7 +60,7 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene { boost::scoped_ptr outfile (pIOSystem->Open(pFile,"wt")); if(outfile == NULL) { - throw DeadlyExportError("could not open output .obj file: " + std::string(pFile)); + throw DeadlyExportError("could not open output .obj file: " + std::string(pFile)); } outfile->Write( exporter.mOutput.str().c_str(), static_cast(exporter.mOutput.tellp()),1); } From c5921540064ee19cabd0707422274b9c3262f9b9 Mon Sep 17 00:00:00 2001 From: Marshall Hahn Date: Tue, 1 Oct 2013 11:21:36 -0400 Subject: [PATCH 4/4] using a custom compare function instead of a global aiVector3t less than operator --- code/ObjExporter.cpp | 4 ++-- code/ObjExporter.h | 17 ++++++++++++++++- include/assimp/vector3.h | 1 - include/assimp/vector3.inl | 10 ---------- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index dce217d12..b680abb74 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -261,7 +261,7 @@ void ObjExporter :: WriteGeometryFile() int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) { - std::map::iterator vertIt = vecMap.find(vec); + vecIndexMap::dataType::iterator vertIt = vecMap.find(vec); if(vertIt != vecMap.end()){// vertex already exists, so reference it return vertIt->second; } @@ -274,7 +274,7 @@ int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) void ObjExporter::vecIndexMap::getVectors( std::vector& vecs ) { vecs.resize(vecMap.size()); - for(std::map::iterator it = vecMap.begin(); it != vecMap.end(); it++){ + for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); it++){ vecs[it->second-1] = it->first; } } diff --git a/code/ObjExporter.h b/code/ObjExporter.h index 4f2f83240..4f6555aa5 100644 --- a/code/ObjExporter.h +++ b/code/ObjExporter.h @@ -113,10 +113,25 @@ private: std::vector vp, vn, vt; + + struct aiVectorCompare + { + bool operator() (const aiVector3D& a, const aiVector3D& b) const + { + if(a.x < b.x) return true; + if(a.x > b.x) return false; + if(a.y < b.y) return true; + if(a.y > b.y) return false; + if(a.z < b.z) return true; + return false; + } + }; + class vecIndexMap { int mNextIndex; - std::map vecMap; + typedef std::map dataType; + dataType vecMap; public: vecIndexMap():mNextIndex(1) diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index 5b3da297d..cbdee264d 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -85,7 +85,6 @@ public: // comparison bool operator== (const aiVector3t& other) const; bool operator!= (const aiVector3t& other) const; - bool operator< (const aiVector3t& other) const; template operator aiVector3t () const; diff --git a/include/assimp/vector3.inl b/include/assimp/vector3.inl index 90370fa07..c03437980 100644 --- a/include/assimp/vector3.inl +++ b/include/assimp/vector3.inl @@ -149,16 +149,6 @@ AI_FORCE_INLINE bool aiVector3t::operator!= (const aiVector3t& oth } // ------------------------------------------------------------------------------------------------ template -AI_FORCE_INLINE bool aiVector3t::operator< (const aiVector3t& other) const { - if(x < other.x) return true; - if(x > other.x) return false; - if(y < other.y) return true; - if(y > other.y) return false; - if(z < other.z) return true; - return false; -} -// ------------------------------------------------------------------------------------------------ -template AI_FORCE_INLINE const aiVector3t aiVector3t::SymMul(const aiVector3t& o) { return aiVector3t(x*o.x,y*o.y,z*o.z); }