Fixed child bones inheriting scale from their parent, fixed null weights on CSkin being incorrect, fixed uncompressed animations being read incorrectly
This commit is contained in:
parent
82f037c69e
commit
e781908205
|
@ -15,8 +15,10 @@ CAnimation::CAnimation()
|
|||
}
|
||||
}
|
||||
|
||||
void CAnimation::EvaluateTransform(float Time, u32 BoneID, CTransform4f& rOut) const
|
||||
void CAnimation::EvaluateTransform(float Time, u32 BoneID, CVector3f *pOutTranslation, CQuaternion *pOutRotation, CVector3f *pOutScale) const
|
||||
{
|
||||
const bool kInterpolate = true;
|
||||
if (!pOutTranslation && !pOutRotation && !pOutScale) return;
|
||||
if (mDuration == 0.f) return;
|
||||
|
||||
if (Time >= mDuration) Time = mDuration;
|
||||
|
@ -29,25 +31,25 @@ void CAnimation::EvaluateTransform(float Time, u32 BoneID, CTransform4f& rOut) c
|
|||
u8 RotChannel = mBoneInfo[BoneID].RotationChannelIdx;
|
||||
u8 TransChannel = mBoneInfo[BoneID].TranslationChannelIdx;
|
||||
|
||||
if (ScaleChannel != 0xFF)
|
||||
if (ScaleChannel != 0xFF && pOutScale)
|
||||
{
|
||||
const CVector3f& rkLow = mScaleChannels[ScaleChannel][LowKey];
|
||||
const CVector3f& rkHigh = mScaleChannels[ScaleChannel][LowKey + 1];
|
||||
rOut.Scale( Math::Lerp<CVector3f>(rkLow, rkHigh, t) );
|
||||
*pOutScale = (kInterpolate ? Math::Lerp<CVector3f>(rkLow, rkHigh, t) : rkLow);
|
||||
}
|
||||
|
||||
if (RotChannel != 0xFF)
|
||||
if (RotChannel != 0xFF && pOutRotation)
|
||||
{
|
||||
const CQuaternion& rkLow = mRotationChannels[RotChannel][LowKey];
|
||||
const CQuaternion& rkHigh = mRotationChannels[RotChannel][LowKey + 1];
|
||||
rOut.Rotate( rkLow.Slerp(rkHigh, t) );
|
||||
*pOutRotation = (kInterpolate ? rkLow.Slerp(rkHigh, t) : rkLow);
|
||||
}
|
||||
|
||||
if (TransChannel != 0xFF)
|
||||
if (TransChannel != 0xFF && pOutTranslation)
|
||||
{
|
||||
const CVector3f& rkLow = mTranslationChannels[TransChannel][LowKey];
|
||||
const CVector3f& rkHigh = mTranslationChannels[TransChannel][LowKey + 1];
|
||||
rOut.Translate( Math::Lerp<CVector3f>(rkLow, rkHigh, t) );
|
||||
*pOutTranslation = (kInterpolate ? Math::Lerp<CVector3f>(rkLow, rkHigh, t) : rkLow);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class CAnimation : public CResource
|
|||
|
||||
public:
|
||||
CAnimation();
|
||||
void EvaluateTransform(float Time, u32 BoneID, CTransform4f& rOut) const;
|
||||
void EvaluateTransform(float Time, u32 BoneID, CVector3f *pOutTranslation, CQuaternion *pOutRotation, CVector3f *pOutScale) const;
|
||||
bool HasTranslation(u32 BoneID) const;
|
||||
|
||||
inline float Duration() const { return mDuration; }
|
||||
|
|
|
@ -10,27 +10,33 @@ CBone::CBone(CSkeleton *pSkel)
|
|||
{
|
||||
}
|
||||
|
||||
void CBone::UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot)
|
||||
void CBone::UpdateTransform(CBoneTransformData& rData, const SBoneTransformInfo& rkParentTransform, CAnimation *pAnim, float Time, bool AnchorRoot)
|
||||
{
|
||||
CTransform4f& rTransform = rData[mID];
|
||||
rTransform.SetIdentity();
|
||||
// Get transform data
|
||||
SBoneTransformInfo TransformInfo;
|
||||
TransformInfo.Position = mPosition;
|
||||
|
||||
if (pAnim)
|
||||
pAnim->EvaluateTransform(Time, mID, rTransform);
|
||||
|
||||
if (!pAnim || !pAnim->HasTranslation(mID))
|
||||
rTransform.Translate(mPosition);
|
||||
|
||||
if (mpParent)
|
||||
rTransform = rData[mpParent->ID()] * rTransform;
|
||||
pAnim->EvaluateTransform(Time, mID, &TransformInfo.Position, &TransformInfo.Rotation, &TransformInfo.Scale);
|
||||
|
||||
if (AnchorRoot && IsRoot())
|
||||
rTransform.ZeroTranslation();
|
||||
TransformInfo.Position = CVector3f::skZero;
|
||||
|
||||
// Apply parent transform
|
||||
TransformInfo.Position = rkParentTransform.Position + (rkParentTransform.Rotation * TransformInfo.Position);
|
||||
TransformInfo.Rotation = rkParentTransform.Rotation * TransformInfo.Rotation;
|
||||
|
||||
// Calculate transform
|
||||
CTransform4f& rTransform = rData[mID];
|
||||
rTransform.SetIdentity();
|
||||
rTransform.Scale(TransformInfo.Scale);
|
||||
rTransform.Rotate(TransformInfo.Rotation);
|
||||
rTransform.Translate(TransformInfo.Position);
|
||||
rTransform *= mInvBind;
|
||||
|
||||
// Calculate children
|
||||
for (u32 iChild = 0; iChild < mChildren.size(); iChild++)
|
||||
mChildren[iChild]->UpdateTransform(rData, pAnim, Time, AnchorRoot);
|
||||
|
||||
rTransform *= mInvBind;
|
||||
mChildren[iChild]->UpdateTransform(rData, TransformInfo, pAnim, Time, AnchorRoot);
|
||||
}
|
||||
|
||||
CVector3f CBone::TransformedPosition(const CBoneTransformData& rkData) const
|
||||
|
@ -86,7 +92,7 @@ u32 CSkeleton::MaxBoneID() const
|
|||
|
||||
void CSkeleton::UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot)
|
||||
{
|
||||
mpRootBone->UpdateTransform(rData, pAnim, Time, AnchorRoot);
|
||||
mpRootBone->UpdateTransform(rData, SBoneTransformInfo(), pAnim, Time, AnchorRoot);
|
||||
}
|
||||
|
||||
void CSkeleton::Draw(FRenderOptions /*Options*/, const CBoneTransformData& rkData)
|
||||
|
|
|
@ -12,6 +12,16 @@
|
|||
class CBoneTransformData;
|
||||
class CBone;
|
||||
|
||||
struct SBoneTransformInfo
|
||||
{
|
||||
CVector3f Position;
|
||||
CQuaternion Rotation;
|
||||
CVector3f Scale;
|
||||
|
||||
SBoneTransformInfo()
|
||||
: Position(CVector3f::skZero), Rotation(CQuaternion::skIdentity), Scale(CVector3f::skOne) {}
|
||||
};
|
||||
|
||||
class CSkeleton : public CResource
|
||||
{
|
||||
DECLARE_RESOURCE_TYPE(eSkeleton)
|
||||
|
@ -32,7 +42,8 @@ public:
|
|||
void Draw(FRenderOptions Options, const CBoneTransformData& rkData);
|
||||
std::pair<s32,float> RayIntersect(const CRay& rkRay, const CBoneTransformData& rkData);
|
||||
|
||||
inline u32 NumBones() const { return mBones.size(); }
|
||||
inline u32 NumBones() const { return mBones.size(); }
|
||||
inline CBone* RootBone() const { return mpRootBone; }
|
||||
};
|
||||
|
||||
class CBone
|
||||
|
@ -49,7 +60,7 @@ class CBone
|
|||
|
||||
public:
|
||||
CBone(CSkeleton *pSkel);
|
||||
void UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot);
|
||||
void UpdateTransform(CBoneTransformData& rData, const SBoneTransformInfo& rkParentTransform, CAnimation *pAnim, float Time, bool AnchorRoot);
|
||||
CVector3f TransformedPosition(const CBoneTransformData& rkData) const;
|
||||
bool IsRoot() const;
|
||||
|
||||
|
|
|
@ -22,16 +22,15 @@ class CSkin : public CResource
|
|||
};
|
||||
std::vector<SVertGroup> mVertGroups;
|
||||
|
||||
u32 mSkinnedVertexCount;
|
||||
|
||||
public:
|
||||
CSkin() {}
|
||||
|
||||
const SVertexWeights& WeightsForVertex(u32 VertIdx)
|
||||
{
|
||||
// Null weights bind everything to the root bone in case there is no matching vertex group
|
||||
static const SVertexWeights skNullWeights = {
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0.f, 0.f, 0.f, 0.f }
|
||||
{ 3, 0, 0, 0 },
|
||||
{ 1.f, 0.f, 0.f, 0.f }
|
||||
};
|
||||
|
||||
u32 Index = 0;
|
||||
|
|
|
@ -94,8 +94,17 @@ void CAnimationLoader::ReadUncompressedANIM()
|
|||
|
||||
else
|
||||
{
|
||||
NumRotationChannels = NumBoneChannels;
|
||||
RotationIndices = BoneIndices;
|
||||
// In MP1 every bone channel has a rotation, so just copy the valid channels from the bone channel list.
|
||||
RotationIndices.resize(NumBoneChannels);
|
||||
|
||||
for (u32 iBone = 0; iBone < BoneIndices.size(); iBone++)
|
||||
{
|
||||
if (BoneIndices[iBone] != 0xFF)
|
||||
{
|
||||
RotationIndices[NumRotationChannels] = BoneIndices[iBone];
|
||||
NumRotationChannels++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Translation channel indices
|
||||
|
|
Loading…
Reference in New Issue