|
|
@@ -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;
|