From e4e1946018b55492d040ba023356ee2e1410f952 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Thu, 24 Jun 2021 10:32:04 -0700 Subject: [PATCH] Determine the original vertex index based on the position The Assimp library does not expose the FBX control point indices. This change causes vertices that are close enough in their position to be considered as coming from the same control point. This allows the mesh optimizer to consider vertices with the same control point index (or "original vertex index" as it is called in the code) for deduplication. Signed-off-by: Chris Burel --- .../MeshOptimizer/MeshOptimizerComponent.cpp | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp index 58be460a44..4321cb0108 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp @@ -107,7 +107,7 @@ namespace AZ::SceneGenerationComponents auto* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(2); + serializeContext->Class()->Version(3); } } @@ -434,6 +434,12 @@ namespace AZ::SceneGenerationComponents const float weightThreshold = skinRule ? skinRule->GetWeightThreshold() : 0.001f; meshBuilder.SetSkinningInfo(ExtractSkinningInfo(meshData, skinWeights, maxWeightsPerVertex, weightThreshold)); + constexpr float positionTolerance = 0.0001f; + constexpr float positionToleranceReciprocal = 1.0f / positionTolerance; + AZStd::unordered_map positionMap{}; + + AZ::u32 currentOriginalVertexIndex = 0; + // Add the vertex data to all the layers const AZ::u32 faceCount = meshData->GetFaceCount(); for (AZ::u32 faceIndex = 0; faceIndex < faceCount; ++faceIndex) @@ -441,8 +447,20 @@ namespace AZ::SceneGenerationComponents meshBuilder.BeginPolygon(baseMesh->GetFaceMaterialId(faceIndex)); for (const AZ::u32 vertexIndex : meshData->GetFaceInfo(faceIndex).vertexIndex) { - const int orgVertexNumber = meshData->GetUsedPointIndexForControlPoint(meshData->GetControlPointIndex(vertexIndex)); - AZ_Assert(orgVertexNumber >= 0, "Invalid vertex number"); + // Round the vertex position so that a float comparison can be made with entires in the positionMap + AZ::Vector3 position = meshData->GetPosition(vertexIndex); + position *= positionToleranceReciprocal; + position += AZ::Vector3(0.5f); + position = AZ::Vector3(AZ::Simd::Vec3::Floor(position.GetSimdValue())); + position *= positionTolerance; + + const auto& [iter, didInsert] = positionMap.try_emplace(position, currentOriginalVertexIndex); + if (didInsert) + { + ++currentOriginalVertexIndex; + } + const AZ::u32 orgVertexNumber = iter->second; + orgVtxLayer->SetCurrentVertexValue(orgVertexNumber); posLayer->SetCurrentVertexValue(meshData->GetPosition(vertexIndex));