Răsfoiți Sursa

Respect merge identical vertices in ObjExporter (#5521)

Co-authored-by: Kim Kulling <[email protected]>
Julian Knodt 1 an în urmă
părinte
comite
39ce0c0456
2 a modificat fișierele cu 27 adăugiri și 20 ștergeri
  1. 19 15
      code/AssetLib/Obj/ObjExporter.cpp
  2. 8 5
      code/AssetLib/Obj/ObjExporter.h

+ 19 - 15
code/AssetLib/Obj/ObjExporter.cpp

@@ -59,9 +59,9 @@ 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* props) {
     // invoke the exporter
-    ObjExporter exporter(pFile, pScene);
+    ObjExporter exporter(pFile, pScene, false, props);
 
     if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
         throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
@@ -86,9 +86,9 @@ 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* ) {
+void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* props) {
     // invoke the exporter
-    ObjExporter exporter(pFile, pScene, true);
+    ObjExporter exporter(pFile, pScene, true, props);
 
     if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
         throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
@@ -111,7 +111,7 @@ void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* p
 static const std::string MaterialExt = ".mtl";
 
 // ------------------------------------------------------------------------------------------------
-ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl)
+ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl, const ExportProperties* props)
 : filename(_filename)
 , pScene(pScene)
 , vn()
@@ -130,7 +130,10 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt
     mOutputMat.imbue(l);
     mOutputMat.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
 
-    WriteGeometryFile(noMtl);
+    WriteGeometryFile(
+        noMtl,
+        props == nullptr ? true : props->GetPropertyBool("bJoinIdenticalVertices", true)
+    );
     if ( !noMtl ) {
         WriteMaterialFile();
     }
@@ -255,14 +258,14 @@ void ObjExporter::WriteMaterialFile() {
     }
 }
 
-void ObjExporter::WriteGeometryFile(bool noMtl) {
+void ObjExporter::WriteGeometryFile(bool noMtl, bool merge_identical_vertices) {
     WriteHeader(mOutput);
     if (!noMtl)
         mOutput << "mtllib "  << GetMaterialLibName() << endl << endl;
 
     // collect mesh geometry
     aiMatrix4x4 mBase;
-    AddNode(pScene->mRootNode, mBase);
+    AddNode(pScene->mRootNode, mBase, merge_identical_vertices);
 
     // write vertex positions with colors, if any
     mVpMap.getKeys( vp );
@@ -330,7 +333,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
 }
 
 // ------------------------------------------------------------------------------------------------
-void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
+void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices) {
     mMeshes.emplace_back();
     MeshInstance& mesh = mMeshes.back();
 
@@ -362,13 +365,14 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
         for(unsigned int a = 0; a < f.mNumIndices; ++a) {
             const unsigned int idx = f.mIndices[a];
 
+            const unsigned int fi = merge_identical_vertices ? 0 : idx;
             aiVector3D vert = mat * m->mVertices[idx];
 
             if ( nullptr != m->mColors[ 0 ] ) {
                 aiColor4D col4 = m->mColors[ 0 ][ idx ];
-                face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)});
+                face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b), fi});
             } else {
-                face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)});
+                face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0), fi});
             }
 
             if (m->mNormals) {
@@ -388,21 +392,21 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
 }
 
 // ------------------------------------------------------------------------------------------------
-void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) {
+void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices) {
     const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
 
     aiMesh *cm( nullptr );
     for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
         cm = pScene->mMeshes[nd->mMeshes[i]];
         if (nullptr != cm) {
-            AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
+            AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices);
         } else {
-            AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
+            AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices);
         }
     }
 
     for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
-        AddNode(nd->mChildren[i], mAbs);
+        AddNode(nd->mChildren[i], mAbs, merge_identical_vertices);
     }
 }
 

+ 8 - 5
code/AssetLib/Obj/ObjExporter.h

@@ -51,6 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <vector>
 #include <map>
 
+#include <assimp/Exporter.hpp>
+
 struct aiScene;
 struct aiNode;
 struct aiMesh;
@@ -63,7 +65,7 @@ namespace Assimp {
 class ObjExporter {
 public:
     /// Constructor for a specific scene to export
-    ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false);
+    ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false, const ExportProperties* props = nullptr);
     ~ObjExporter();
     std::string GetMaterialLibName();
     std::string GetMaterialLibFileName();
@@ -97,10 +99,10 @@ private:
 
     void WriteHeader(std::ostringstream& out);
     void WriteMaterialFile();
-    void WriteGeometryFile(bool noMtl=false);
+    void WriteGeometryFile(bool noMtl=false, bool merge_identical_vertices = false);
     std::string GetMaterialName(unsigned int index);
-    void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat);
-    void AddNode(const aiNode* nd, const aiMatrix4x4& mParent);
+    void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices);
+    void AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices);
 
 private:
     std::string filename;
@@ -109,6 +111,7 @@ private:
     struct vertexData {
         aiVector3D vp;
         aiColor3D vc; // OBJ does not support 4D color
+        uint32_t index = 0;
     };
 
     std::vector<aiVector3D> vn, vt;
@@ -133,7 +136,7 @@ private:
             if (a.vc.g > b.vc.g) return false;
             if (a.vc.b < b.vc.b) return true;
             if (a.vc.b > b.vc.b) return false;
-            return false;
+            return a.index < b.index;
         }
     };