Thats my last Updated Code:
Animation Componenets:
class CKeyframe { public: float time; float value;};enum CAnimationTrackType { TRANSLATEX = 0, TRANSLATEY, TRANSLATEZ, ROTATEX, ROTATEY, ROTATEZ};class CAnimationTrack { public: unsigned int trackID; unsigned int nodeID; CAnimationTrackType trackType; std::vector<CKeyframe *> keys;};
Animation Class:
class CAnimation { protected: std::vector<CAnimationTrack *> m_Tracks; float startTime, endTime; char name[32]; public: CAnimation(); ~CAnimation(); CAnimationTrack * FindTrackByID(unsigned int trackID); CKeyframe * FindKeyframeByTime(unsigned int trackID, float keyframe_time); void AddTrack(unsigned int trackID, unsigned int nodeID, CAnimationTrackType trackType); void AddKeyframe(unsigned int trackID, float value, float time); void SetTime(float start_time, float end_time); CAnimationTrack * operator[](unsigned int index); CAnimationTrack *AnimationTrack(unsigned int index); unsigned int NumAnimationTracks(); };
CBlend.cpp
void CBlend::Blend(CVector3 &vPos, CQuat &qRotate, CKeyframe *curKf, CKeyframe *prevKf, float blend_factor, CAnimationTrackType trackType) { CVector3 vTmpPrev, vTmpCur; CQuat qTmpPrev, qTmpCur; if(trackType == TRANSLATEX) { vTmpPrev.x = prevKf->value; vTmpCur.x = curKf->value; } if(trackType == TRANSLATEY) { vTmpPrev.y = prevKf->value; vTmpCur.y = curKf->value; } if(trackType == TRANSLATEZ) { vTmpPrev.z = prevKf->value; vTmpCur.z = curKf->value; } if(trackType == ROTATEZ) { qTmpPrev.SetAxis(prevKf->value, 1, 0, 0); qTmpCur.SetAxis(curKf->value, 1, 0, 0); } if(trackType == ROTATEZ) { qTmpPrev.SetAxis(prevKf->value, 0, 1, 0); qTmpCur.SetAxis(curKf->value, 0, 1, 0); } if(trackType == ROTATEZ) { qTmpPrev.SetAxis(prevKf->value, 0, 0, 1); qTmpCur.SetAxis(curKf->value, 0, 0, 1); } vPos = vTmpCur * (1.0f - blend_factor) + vTmpPrev * blend_factor; qRotate.Slerp(qTmpCur, qTmpPrev, blend_factor);}void CBlend::Blend(CAnimation *pFinalAnim, CAnimation *pCurAnimation, CAnimation *pNextAnimation, float blend_factor) { CVector3 vTmp; CQuat qTmp; for(unsigned int i = 0; i < pCurAnimation->NumAnimationTracks(); i++) { for(unsigned int n = 0; n < pNextAnimation->NumAnimationTracks(); n++) { if(pCurAnimation->AnimationTrack(i)->nodeID == pNextAnimation->AnimationTrack(n)->nodeID && pCurAnimation->AnimationTrack(i)->trackType == pNextAnimation->AnimationTrack(n)->trackType) { for(unsigned int j = 0; j < pCurAnimation->AnimationTrack(i)->keys.size(); j++) { for(unsigned int k = 0; k < pNextAnimation->AnimationTrack(n)->keys.size(); k++) { Blend(vTmp, qTmp, pCurAnimation->AnimationTrack(i)->keys[j], pNextAnimation->AnimationTrack(n)->keys[j], blend_factor, pNextAnimation->AnimationTrack(n)->trackType); for(unsigned int v = 0; v < pFinalAnim->NumAnimationTracks(); v++) { if(pFinalAnim->AnimationTrack(v)->nodeID == pCurAnimation->AnimationTrack(i)->nodeID && pFinalAnim->AnimationTrack(i)->trackType == pCurAnimation->AnimationTrack(n)->trackType) { //What to write here?? } } } } } } }}
Animate Skeleton:
void CSkeletalAnimation::Animate(CSkeleton *pFinalSkel) { float time = g_Timer.GetSeconds(); //Haven't written loop yet. :) for(unsigned int i = 0; i < m_Tracks.size(); i++) { unsigned int uiFrame = 0; CBone * bone = pFinalSkel->FindBone(m_Tracks->nodeID); CAnimationTrackType trackType = m_Tracks->trackType; CVector3 vTmp; CQuat qTmp; while(uiFrame < m_Tracks->keys.size() && m_Tracks->keys[uiFrame]->time < time) uiFrame++; if(uiFrame == 0) { if(trackType == TRANSLATEX) { vTmp.x = m_Tracks->keys[0]->value; } if(trackType == TRANSLATEY) { vTmp.y = m_Tracks->keys[0]->value; } if(trackType == TRANSLATEZ) { vTmp.z = m_Tracks->keys[0]->value; } if(trackType == ROTATEX) { qTmp.SetAxis(m_Tracks->keys[0]->value, 1, 0, 0); } if(trackType == ROTATEY) { qTmp.SetAxis(m_Tracks->keys[0]->value, 0, 1, 0); } if(trackType == ROTATEZ) { qTmp.SetAxis(m_Tracks->keys[0]->value, 0, 0, 1); } } if(uiFrame == m_Tracks->keys.size()) { if(trackType == TRANSLATEX) { vTmp.x = m_Tracks->keys[uiFrame-1]->value; } if(trackType == TRANSLATEY) { vTmp.y = m_Tracks->keys[uiFrame-1]->value; } if(trackType == TRANSLATEZ) { vTmp.z = m_Tracks->keys[uiFrame-1]->value; } if(trackType == ROTATEX) { qTmp.SetAxis(m_Tracks->keys[uiFrame-1]->value, 1, 0, 0); } if(trackType == ROTATEY) { qTmp.SetAxis(m_Tracks->keys[uiFrame-1]->value, 0, 1, 0); } if(trackType == ROTATEZ) { qTmp.SetAxis(m_Tracks->keys[uiFrame-1]->value, 0, 0, 1); } } else { CKeyframe *prevKf = m_Tracks->keys[uiFrame-1]; CKeyframe *curKf = m_Tracks->keys[uiFrame]; float delta = curKf->time - prevKf->time; float blend = (time - prevKf->time) / delta; CBlend::Blend(vTmp, qTmp, curKf, prevKf, blend, trackType); } bone->qRotate = bone->qRotate * qTmp; bone->vPos = bone->vPos * vTmp; }}
Is that code right?? And please answer my question inside Blend::Blend function.
Thanks,
Kasya
P.S. Timer is temporary i'll change it anyway. :)