Bladeren bron

Restore merging of near-identical vertices for JoinIdenticalVertices (#6278)

* Restore merging of near-identical vertices for JoinIdenticalVertices

---------

Co-authored-by: Kim Kulling <[email protected]>
Matt Penny 4 maanden geleden
bovenliggende
commit
489c8d565b
2 gewijzigde bestanden met toevoegingen van 60 en 24 verwijderingen
  1. 60 1
      code/PostProcessing/JoinVerticesProcess.cpp
  2. 0 23
      include/assimp/Vertex.h

+ 60 - 1
code/PostProcessing/JoinVerticesProcess.cpp

@@ -100,6 +100,65 @@ void JoinVerticesProcess::Execute( aiScene* pScene) {
 
 namespace {
 
+struct CompareVerticesAlmostEqual {
+    bool operator () (const Vertex & a, const Vertex & b) const {
+        static const float epsilon = 1e-5f;
+        static const float squareEpsilon = epsilon * epsilon;
+
+        if ((a.position - b.position).SquareLength() > squareEpsilon) {
+            return false;
+        }
+
+        // We just test the other attributes even if they're not present in the mesh.
+        // In this case they're initialized to 0 so the comparison succeeds.
+        // By this method the non-present attributes are effectively ignored in the comparison.
+
+        if ((a.normal - b.normal).SquareLength() > squareEpsilon) {
+            return false;
+        }
+
+        if ((a.tangent - b.tangent).SquareLength() > squareEpsilon) {
+            return false;
+        }
+
+        if ((a.bitangent - b.bitangent).SquareLength() > squareEpsilon) {
+            return false;
+        }
+
+        for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i ++) {
+            if ((a.texcoords[i] - b.texcoords[i]).SquareLength() > squareEpsilon) {
+                return false;
+            }
+        }
+
+        for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; i ++) {
+            if (GetColorDifference(a.colors[i], b.colors[i]) > squareEpsilon) {
+                return false;
+            }
+        }
+
+        // If reached this point, they are ~equal
+        return true;
+    }
+};
+
+struct HashVertex {
+    inline void hash_combine(std::size_t& seed, const ai_real& v) const {
+        std::hash<ai_real> hasher;
+        seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+    }
+
+    size_t operator () (const Vertex & v) const {
+        size_t hash = 0;
+
+        hash_combine(hash, v.position.x);
+        hash_combine(hash, v.position.y);
+        hash_combine(hash, v.position.z);
+
+        return hash;
+    }
+};
+
 template<class XMesh>
 void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) {
     // replace vertex data with the unique data sets
@@ -208,7 +267,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) {
         }
     }
     // a map that maps a vertex to its new index
-    std::map<Vertex, int> vertex2Index = {};
+    std::unordered_map<Vertex, int, HashVertex, CompareVerticesAlmostEqual> vertex2Index = {};
     // we can not end up with more vertices than we started with
     // Now check each vertex if it brings something new to the table
     int newIndex = 0;

+ 0 - 23
include/assimp/Vertex.h

@@ -183,29 +183,6 @@ struct Vertex {
         return *this;
     }
 
-    bool operator < (const Vertex & o) const {
-        if (position < o.position) return true;
-        if (position != o.position) return false;
-
-        if (normal < o.normal) return true;
-        if (normal != o.normal) return false;
-
-        for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i ++) {
-          if (texcoords[i] < o.texcoords[i]) return true;
-          if (texcoords[i] != o.texcoords[i]) return false;
-        }
-
-        // note that tangent/bitangent are not checked since they are optional
-
-        for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; i ++) {
-          if (colors[i] < o.colors[i]) return true;
-          if (colors[i] != o.colors[i]) return false;
-        }
-
-        // if reached this point, they are equal
-        return false;
-    }
-
     // ----------------------------------------------------------------------------
     /// Convert back to non-interleaved storage
     void SortBack(aiMesh* out, unsigned int idx) const {