[MeshOptimizer] Return the correct size from the position map when there are blendshapes (#2391)

The previous version returned the incorrect size from the position map when
blendshapes are present in the model. When there are blendshapes, the
vertex welding is disabled, and nothing is inserted into the position map.
However, the position map's size was being used to dictate how many
elements to create in the skinning info. The skinning info tries to
compensate for an incorrect max vertex index by resizing its underlying
vector when adding an influence, but that was using the index as the new
size of the vector, so it was off by one. This fixes both errors.

Signed-off-by: Chris Burel <burelc@amazon.com>
This commit is contained in:
Chris Burel
2021-07-23 10:13:53 -07:00
committed by GitHub
parent 3eed9af252
commit 1e10ee61ba
2 changed files with 26 additions and 8 deletions
@@ -35,7 +35,7 @@ namespace AZ::MeshBuilder
MeshBuilderSkinningInfo(size_t numOrgVertices);
void AddInfluence(size_t orgVtxNr, const Influence& influence) { mInfluences.resize(AZStd::max(mInfluences.size(), orgVtxNr)); mInfluences.at(orgVtxNr).emplace_back(influence); }
void AddInfluence(size_t orgVtxNr, const Influence& influence) { mInfluences.resize(AZStd::max(mInfluences.size(), orgVtxNr + 1)); mInfluences.at(orgVtxNr).emplace_back(influence); }
void RemoveInfluence(size_t orgVtxNr, size_t influenceNr) { mInfluences.at(orgVtxNr).erase(mInfluences.at(orgVtxNr).begin() + influenceNr); }
const Influence& GetInfluence(size_t orgVtxNr, size_t influenceNr) const { return mInfluences.at(orgVtxNr).at(influenceNr); }
size_t GetNumInfluences(size_t orgVtxNr) const { return mInfluences.at(orgVtxNr).size(); }
@@ -105,7 +105,6 @@ namespace AZ::SceneGenerationComponents
// Vector3 as a key into a unordered_map.
template <class MeshDataType>
class Vector3Map
: private AZStd::unordered_map<AZ::Vector3, AZ::u32>
{
public:
Vector3Map(const MeshDataType* meshData, bool hasBlendShapes, float positionTolerance)
@@ -116,9 +115,6 @@ namespace AZ::SceneGenerationComponents
{
}
using AZStd::unordered_map<AZ::Vector3, AZ::u32>::reserve;
using AZStd::unordered_map<AZ::Vector3, AZ::u32>::size;
AZ::u32 operator[](const AZ::u32 vertexIndex)
{
if (m_hasBlendShapes)
@@ -130,7 +126,7 @@ namespace AZ::SceneGenerationComponents
return m_meshData->GetUsedPointIndexForControlPoint(m_meshData->GetControlPointIndex(vertexIndex));
}
const auto& [iter, didInsert] = try_emplace(GetPositionForIndex(vertexIndex), m_currentOriginalVertexIndex);
const auto& [iter, didInsert] = m_map.try_emplace(GetPositionForIndex(vertexIndex), m_currentOriginalVertexIndex);
if (didInsert)
{
++m_currentOriginalVertexIndex;
@@ -149,11 +145,32 @@ namespace AZ::SceneGenerationComponents
return m_meshData->GetUsedPointIndexForControlPoint(m_meshData->GetControlPointIndex(vertexIndex));
}
auto iter = find(GetPositionForIndex(vertexIndex));
AZSTD_CONTAINER_ASSERT(iter != end(), "Element with key is not present");
auto iter = m_map.find(GetPositionForIndex(vertexIndex));
AZSTD_CONTAINER_ASSERT(iter != m_map.end(), "Element with key is not present");
return iter->second;
}
[[nodiscard]] size_t size() const
{
if (m_hasBlendShapes)
{
// Since blend shapes are present, the vertex welding is disabled, and the map will always be empty.
// Use the underlying mesh's vertex count instead.
return m_meshData->GetUsedControlPointCount();
}
return m_map.size();
}
void reserve(size_t count)
{
if (m_hasBlendShapes)
{
// Since blend shapes are present, the vertex welding is disabled, and the map will always be empty.
return;
}
m_map.reserve(count);
}
private:
AZ::Vector3 GetPositionForIndex(const AZ::u32 vertexIndex) const
@@ -167,6 +184,7 @@ namespace AZ::SceneGenerationComponents
) * m_positionTolerance;
}
AZStd::unordered_map<AZ::Vector3, AZ::u32> m_map;
const MeshDataType* m_meshData;
bool m_hasBlendShapes;
float m_positionTolerance;