Cache the model-animation bounds more efficiently.

To render models, we need to know the maximum bounds it takes over the
course of an animation. This depends only on the ModelDef and the
AnimationDef (and thus the SkeletonDef).
Currently, we recompute this data for each model, which is inefficient.
Caching it in ModelDef is faster, particularly avoiding lag spikes at
game start on some maps.
The animations are referred by a unique ID to avoid pointer-related
issues. I would have preferred weak_ptr, but that cannot be stably
hashed for now.

While at it, switch to unique_ptr/vectors.

Differential Revision: https://code.wildfiregames.com/D2967
This was SVN commit r25306.
This commit is contained in:
wraitii
2021-04-23 14:26:59 +00:00
parent 52258ce48b
commit f73fa05542
7 changed files with 90 additions and 88 deletions
+31
View File
@@ -31,6 +31,37 @@
# include <xmmintrin.h>
#endif
void CModelDef::GetMaxBounds(CSkeletonAnimDef* anim, bool loop, CBoundingBoxAligned& result)
{
std::unordered_map<u32, CBoundingBoxAligned>::const_iterator it = m_MaxBoundsPerAnimDef.find(anim ? anim->m_UID : 0);
if (it != m_MaxBoundsPerAnimDef.end())
{
result = it->second;
return;
}
size_t numverts = GetNumVertices();
SModelVertex* verts = GetVertices();
if (!anim)
{
for (size_t i = 0; i < numverts; ++i)
result += verts[i].m_Coords;
m_MaxBoundsPerAnimDef[0] = result;
return;
}
ENSURE(anim->m_UID != 0);
std::vector<CMatrix3D> boneMatrix(anim->GetNumKeys());
// NB: by using frames, the bounds are technically pessimistic (since interpolation could end up outside of them).
for (size_t j = 0; j < anim->GetNumFrames(); ++j)
{
anim->BuildBoneMatrices(j*anim->GetFrameTime(), boneMatrix.data(), loop);
for (size_t i = 0; i < numverts; ++i)
result += SkinPoint(verts[i], boneMatrix.data());
}
m_MaxBoundsPerAnimDef[anim->m_UID] = result;
}
CVector3D CModelDef::SkinPoint(const SModelVertex& vtx,
const CMatrix3D newPoseMatrices[])
{