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

* Restore merging of near-identical vertices for JoinIdenticalVertices

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
This commit is contained in:
Matt Penny
2025-09-21 04:57:17 -04:00
committed by GitHub
parent 0581ed5f11
commit 489c8d565b
2 changed files with 60 additions and 24 deletions

View File

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