Index: source/graphics/Model.cpp =================================================================== --- source/graphics/Model.cpp +++ source/graphics/Model.cpp @@ -176,11 +176,10 @@ m_PositionValid = false; ValidatePosition(); - // extend bounds by vertex positions at the frame - for (size_t i=0;iGetFrameTime(); } @@ -426,10 +425,12 @@ if (m_BoneMatrices) { - for (size_t i = 0; i < m_pModelDef->GetNumBones(); i++) - { - m_BoneMatrices[i] = m_BoneMatrices[i] * m_pModelDef->GetInverseBindBoneMatrices()[i]; - } + CMatrix3D* inverseBoneMatrices = m_pModelDef->GetInverseBindBoneMatrices(); + size_t numBones = m_pModelDef->GetNumBones(); + + // *= doesn't work here because A *= B isn't the same as A = A * B. + for (size_t i = 0; i < numBones; ++i) + m_BoneMatrices[i] = m_BoneMatrices[i] * inverseBoneMatrices[i]; // Note: there is a special case of joint influence, in which the vertex // is influenced by the bind-shape transform instead of a particular bone, @@ -437,7 +438,7 @@ // of bones. But since we're skinning in world space, we use the model's // world space transform and store that matrix in this special index. // (see http://trac.wildfiregames.com/ticket/1012) - m_BoneMatrices[m_pModelDef->GetNumBones()] = m_Transform; + m_BoneMatrices[numBones] = m_Transform; if (computeBlendMatrices) m_pModelDef->BlendBoneMatrices(m_BoneMatrices); Index: source/graphics/ModelDef.h =================================================================== --- source/graphics/ModelDef.h +++ source/graphics/ModelDef.h @@ -31,6 +31,7 @@ #include #include +class CBoundingBoxAligned; class CBoneState; /** @@ -189,19 +190,20 @@ /** * Transform the given vertex's position from the bind pose into the new pose. - * - * @return new world-space vertex coordinates */ - static CVector3D SkinPoint(const SModelVertex& vtx, - const CMatrix3D newPoseMatrices[]); + static void SkinPoint(const SModelVertex& vtx, const CMatrix3D newPoseMatrices[], CVector3D& result); + + /** + * Transform the given vertex's position from the bind pose into the new pose. Extend the bounds accordingly. + */ + static void SkinPoint(const SModelVertex& vtx, const CMatrix3D newPoseMatrices[], CBoundingBoxAligned& result); /** * Transform the given vertex's normal from the bind pose into the new pose. * * @return new world-space vertex normal */ - static CVector3D SkinNormal(const SModelVertex& vtx, - const CMatrix3D newPoseMatrices[]); + static void SkinNormal(const SModelVertex& vtx, const CMatrix3D newPoseMatrices[], CVector3D &result); /** * Transform vertices' positions and normals. Index: source/graphics/ModelDef.cpp =================================================================== --- source/graphics/ModelDef.cpp +++ source/graphics/ModelDef.cpp @@ -21,30 +21,29 @@ #include "precompiled.h" -#include "ModelDef.h" #include "graphics/SkeletonAnimDef.h" -#include "ps/FileIo.h" +#include "maths/BoundingBoxAligned.h" #include "maths/Vector4D.h" +#include "ModelDef.h" +#include "ps/FileIo.h" #if HAVE_SSE # include #endif -CVector3D CModelDef::SkinPoint(const SModelVertex& vtx, - const CMatrix3D newPoseMatrices[]) +void CModelDef::SkinPoint(const SModelVertex& vtx, const CMatrix3D newPoseMatrices[], CVector3D& result) { - CVector3D result (0, 0, 0); - for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i) - { result += newPoseMatrices[vtx.m_Blend.m_Bone[i]].Transform(vtx.m_Coords) * vtx.m_Blend.m_Weight[i]; - } +} - return result; +void CModelDef::SkinPoint(const SModelVertex& vtx, const CMatrix3D newPoseMatrices[], CBoundingBoxAligned& result) +{ + for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i) + result += newPoseMatrices[vtx.m_Blend.m_Bone[i]].Transform(vtx.m_Coords) * vtx.m_Blend.m_Weight[i]; } -CVector3D CModelDef::SkinNormal(const SModelVertex& vtx, - const CMatrix3D newPoseMatrices[]) +void CModelDef::SkinNormal(const SModelVertex& vtx, const CMatrix3D newPoseMatrices[], CVector3D& result) { // To be correct, the normal vectors apparently need to be multiplied by the // inverse of the transpose. Unfortunately inverses are slow. @@ -69,12 +68,9 @@ // (This isn't very good as a proof, but it's better than assuming M is // orthogonal when it's clearly not.) - CVector3D result (0, 0, 0); for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i) - { result += newPoseMatrices[vtx.m_Blend.m_Bone[i]].Rotate(vtx.m_Norm) * vtx.m_Blend.m_Weight[i]; - } // If there was more than one influence, the result is probably not going // to be of unit length (since it's a weighted sum of several independent @@ -84,7 +80,6 @@ if (vtx.m_Blend.m_Bone[1] != 0xff) // if more than one influence result.Normalize(); - return result; } void CModelDef::SkinPointsAndNormals( @@ -400,8 +395,8 @@ for (size_t i = 0; i < mdef->m_NumVertices; ++i) { - mdef->m_pVertices[i].m_Coords = SkinPoint(mdef->m_pVertices[i], &bindPose[0]); - mdef->m_pVertices[i].m_Norm = SkinNormal(mdef->m_pVertices[i], &bindPose[0]); + SkinPoint(mdef->m_pVertices[i], &bindPose[0], mdef->m_pVertices[i].m_Coords); + SkinNormal(mdef->m_pVertices[i], &bindPose[0], mdef->m_pVertices[i].m_Norm); } } }