Index: ps/trunk/source/graphics/ModelDef.cpp =================================================================== --- ps/trunk/source/graphics/ModelDef.cpp +++ ps/trunk/source/graphics/ModelDef.cpp @@ -33,7 +33,9 @@ void CModelDef::GetMaxBounds(CSkeletonAnimDef* anim, bool loop, CBoundingBoxAligned& result) { - std::unordered_map::const_iterator it = m_MaxBoundsPerAnimDef.find(anim ? anim->m_UID : 0); + const u32 animIndex = anim ? anim->m_UID : 0; + + std::unordered_map::const_iterator it = m_MaxBoundsPerAnimDef.find(animIndex); if (it != m_MaxBoundsPerAnimDef.end()) { result = it->second; @@ -47,19 +49,28 @@ { for (size_t i = 0; i < numverts; ++i) result += verts[i].m_Coords; - m_MaxBoundsPerAnimDef[0] = result; + m_MaxBoundsPerAnimDef[animIndex] = result; return; } - ENSURE(anim->m_UID != 0); + ENSURE(animIndex != 0); + CMatrix3D* inverseBindBoneMatrix = GetInverseBindBoneMatrices(); std::vector 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); + + const size_t numFrames = anim->GetNumFrames(); + const float frameTime = anim->GetFrameTime(); + const size_t numBones = GetNumBones(); + + // NB: by using frames, the bounds are technically pessimistic, + // since interpolation between frames can put vertices farther. + for (size_t j = 0; j < numFrames; ++j) + { + anim->BuildBoneMatrices(j * frameTime, boneMatrix.data(), loop); + for (size_t i = 0; i < numBones; ++i) + boneMatrix[i] *= inverseBindBoneMatrix[i]; for (size_t i = 0; i < numverts; ++i) result += SkinPoint(verts[i], boneMatrix.data()); } - m_MaxBoundsPerAnimDef[anim->m_UID] = result; + m_MaxBoundsPerAnimDef[animIndex] = result; } CVector3D CModelDef::SkinPoint(const SModelVertex& vtx, Index: ps/trunk/source/graphics/SkeletonAnimDef.h =================================================================== --- ps/trunk/source/graphics/SkeletonAnimDef.h +++ ps/trunk/source/graphics/SkeletonAnimDef.h @@ -96,7 +96,6 @@ // Unique identifier - used by CModelDef to cache bounds per-animDef. // (hopefully we won't run into the u32 limit too soon). u32 m_UID; - static u32 nextUID; }; #endif Index: ps/trunk/source/graphics/SkeletonAnimDef.cpp =================================================================== --- ps/trunk/source/graphics/SkeletonAnimDef.cpp +++ ps/trunk/source/graphics/SkeletonAnimDef.cpp @@ -28,19 +28,22 @@ #include "ps/CLogger.h" #include "ps/FileIo.h" +namespace +{ // Start IDs at 1 to leave 0 as a special value. -u32 CSkeletonAnimDef::nextUID = 1; +u32 g_NextSkeletonDefUID = 1; +} /////////////////////////////////////////////////////////////////////////////////////////// // CSkeletonAnimDef constructor CSkeletonAnimDef::CSkeletonAnimDef() : m_FrameTime(0), m_NumKeys(0), m_NumFrames(0) { - m_UID = nextUID++; + m_UID = g_NextSkeletonDefUID++; // Log a warning if we ever overflow. Should that not result from a bug, bumping to u64 ought to suffice. - if (nextUID == 0) + if (g_NextSkeletonDefUID == 0) { // Reset to 1. - nextUID++; + g_NextSkeletonDefUID++; LOGWARNING("CSkeletonAnimDef unique ID overflowed to 0 - model-animation bounds may be incorrect."); } }