mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-07-05 04:35:53 +00:00
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 (mDuration == 0.f) return;
|
||||||
|
|
||||||
if (Time >= mDuration) Time = mDuration;
|
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 RotChannel = mBoneInfo[BoneID].RotationChannelIdx;
|
||||||
u8 TransChannel = mBoneInfo[BoneID].TranslationChannelIdx;
|
u8 TransChannel = mBoneInfo[BoneID].TranslationChannelIdx;
|
||||||
|
|
||||||
if (ScaleChannel != 0xFF)
|
if (ScaleChannel != 0xFF && pOutScale)
|
||||||
{
|
{
|
||||||
const CVector3f& rkLow = mScaleChannels[ScaleChannel][LowKey];
|
const CVector3f& rkLow = mScaleChannels[ScaleChannel][LowKey];
|
||||||
const CVector3f& rkHigh = mScaleChannels[ScaleChannel][LowKey + 1];
|
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& rkLow = mRotationChannels[RotChannel][LowKey];
|
||||||
const CQuaternion& rkHigh = mRotationChannels[RotChannel][LowKey + 1];
|
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& rkLow = mTranslationChannels[TransChannel][LowKey];
|
||||||
const CVector3f& rkHigh = mTranslationChannels[TransChannel][LowKey + 1];
|
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:
|
public:
|
||||||
CAnimation();
|
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;
|
bool HasTranslation(u32 BoneID) const;
|
||||||
|
|
||||||
inline float Duration() const { return mDuration; }
|
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];
|
// Get transform data
|
||||||
rTransform.SetIdentity();
|
SBoneTransformInfo TransformInfo;
|
||||||
|
TransformInfo.Position = mPosition;
|
||||||
|
|
||||||
if (pAnim)
|
if (pAnim)
|
||||||
pAnim->EvaluateTransform(Time, mID, rTransform);
|
pAnim->EvaluateTransform(Time, mID, &TransformInfo.Position, &TransformInfo.Rotation, &TransformInfo.Scale);
|
||||||
|
|
||||||
if (!pAnim || !pAnim->HasTranslation(mID))
|
|
||||||
rTransform.Translate(mPosition);
|
|
||||||
|
|
||||||
if (mpParent)
|
|
||||||
rTransform = rData[mpParent->ID()] * rTransform;
|
|
||||||
|
|
||||||
if (AnchorRoot && IsRoot())
|
if (AnchorRoot && IsRoot())
|
||||||
rTransform.ZeroTranslation();
|
TransformInfo.Position = CVector3f::skZero;
|
||||||
|
|
||||||
for (u32 iChild = 0; iChild < mChildren.size(); iChild++)
|
// Apply parent transform
|
||||||
mChildren[iChild]->UpdateTransform(rData, pAnim, Time, AnchorRoot);
|
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;
|
rTransform *= mInvBind;
|
||||||
|
|
||||||
|
// Calculate children
|
||||||
|
for (u32 iChild = 0; iChild < mChildren.size(); iChild++)
|
||||||
|
mChildren[iChild]->UpdateTransform(rData, TransformInfo, pAnim, Time, AnchorRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CBone::TransformedPosition(const CBoneTransformData& rkData) const
|
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)
|
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)
|
void CSkeleton::Draw(FRenderOptions /*Options*/, const CBoneTransformData& rkData)
|
||||||
|
@ -12,6 +12,16 @@
|
|||||||
class CBoneTransformData;
|
class CBoneTransformData;
|
||||||
class CBone;
|
class CBone;
|
||||||
|
|
||||||
|
struct SBoneTransformInfo
|
||||||
|
{
|
||||||
|
CVector3f Position;
|
||||||
|
CQuaternion Rotation;
|
||||||
|
CVector3f Scale;
|
||||||
|
|
||||||
|
SBoneTransformInfo()
|
||||||
|
: Position(CVector3f::skZero), Rotation(CQuaternion::skIdentity), Scale(CVector3f::skOne) {}
|
||||||
|
};
|
||||||
|
|
||||||
class CSkeleton : public CResource
|
class CSkeleton : public CResource
|
||||||
{
|
{
|
||||||
DECLARE_RESOURCE_TYPE(eSkeleton)
|
DECLARE_RESOURCE_TYPE(eSkeleton)
|
||||||
@ -33,6 +43,7 @@ public:
|
|||||||
std::pair<s32,float> RayIntersect(const CRay& rkRay, 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
|
class CBone
|
||||||
@ -49,7 +60,7 @@ class CBone
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CBone(CSkeleton *pSkel);
|
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;
|
CVector3f TransformedPosition(const CBoneTransformData& rkData) const;
|
||||||
bool IsRoot() const;
|
bool IsRoot() const;
|
||||||
|
|
||||||
|
@ -22,16 +22,15 @@ class CSkin : public CResource
|
|||||||
};
|
};
|
||||||
std::vector<SVertGroup> mVertGroups;
|
std::vector<SVertGroup> mVertGroups;
|
||||||
|
|
||||||
u32 mSkinnedVertexCount;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSkin() {}
|
CSkin() {}
|
||||||
|
|
||||||
const SVertexWeights& WeightsForVertex(u32 VertIdx)
|
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 = {
|
static const SVertexWeights skNullWeights = {
|
||||||
{ 0, 0, 0, 0 },
|
{ 3, 0, 0, 0 },
|
||||||
{ 0.f, 0.f, 0.f, 0.f }
|
{ 1.f, 0.f, 0.f, 0.f }
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 Index = 0;
|
u32 Index = 0;
|
||||||
|
@ -94,8 +94,17 @@ void CAnimationLoader::ReadUncompressedANIM()
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NumRotationChannels = NumBoneChannels;
|
// In MP1 every bone channel has a rotation, so just copy the valid channels from the bone channel list.
|
||||||
RotationIndices = BoneIndices;
|
RotationIndices.resize(NumBoneChannels);
|
||||||
|
|
||||||
|
for (u32 iBone = 0; iBone < BoneIndices.size(); iBone++)
|
||||||
|
{
|
||||||
|
if (BoneIndices[iBone] != 0xFF)
|
||||||
|
{
|
||||||
|
RotationIndices[NumRotationChannels] = BoneIndices[iBone];
|
||||||
|
NumRotationChannels++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translation channel indices
|
// Translation channel indices
|
||||||
|
Loading…
x
Reference in New Issue
Block a user