DirectX 9 で骨格アニメーション用のプログラムを作成しようとしています。LoadMeshFromHierarchy 関数を使用してアニメーション メッシュをロードしました。アニメーション メッシュからキーフレームを読み取ってアニメーションを指示できるように、animController をバイパスしたいと考えています。ファイル (ex. tiny.x) を読み込んで、これらのキーを自由にループします。
これが私がこれまでに持っているものです...この時点で、.xファイルを正常に解析し、各アニメーションと、クラス(Anim)内の唯一のアニメーションセットのanimationkeyを保存しました。この更新機能を実行すると、アニメーション化されたメッシュが変形します。理由がわかりません...各フレームの変換マトリックスを更新するプロセスだと思います...ここに私のコードがあります:
void cAnimationCollection::Update(DWORD AnimSetIndex, DWORD time)
{
D3DXFRAME_EXTENDED *currentFrame = (D3DXFRAME_EXTENDED*)m_entity->m_frameRoot;
cAnimationSet *AnimSet = m_AnimationSets;
assert(AnimSetIndex <= index);
while(AnimSet != NULL)
{
if(AnimSet->m_index == AnimSetIndex)
{
cAnimation *Anim = AnimSet->m_Animations;
while(Anim != NULL)
{
D3DXMatrixIdentity(&Anim->m_Frame->TransformationMatrix);
if(Anim->m_NumScaleKeys && Anim->m_ScaleKeys)
{
DWORD ScaleKey=0, ScaleKey2=0;
for(DWORD i = 0; i < Anim->m_NumScaleKeys; i++)
{
if(time >= Anim->m_ScaleKeys[i].m_Time)
ScaleKey = i;
}
ScaleKey2 = (ScaleKey>=(Anim->m_NumScaleKeys-1))?ScaleKey:ScaleKey+1;
float TimeDiff = Anim->m_ScaleKeys[ScaleKey2].m_Time - Anim->m_ScaleKeys[ScaleKey].m_Time;
if(!TimeDiff)
TimeDiff = 1;
float Scalar = ((float)time - Anim->m_ScaleKeys[ScaleKey].m_Time) / (float)TimeDiff;
D3DXVECTOR3 vecScale = Anim->m_ScaleKeys[ScaleKey2].m_VecKey - Anim->m_ScaleKeys[ScaleKey].m_VecKey;
vecScale *= Scalar;
vecScale += Anim->m_ScaleKeys[ScaleKey].m_VecKey;
D3DXMATRIX matScale;
D3DXMatrixScaling(&matScale, vecScale.x, vecScale.y, vecScale.z);
Anim->m_Frame->TransformationMatrix *= matScale;
}
if(Anim->m_NumRotationKeys && Anim->m_RotationKeys)
{
DWORD RotKey=0, RotKey2=0;
for(DWORD i = 0; i < Anim->m_NumRotationKeys; i++)
{
if(time >= Anim->m_RotationKeys[i].m_Time)
RotKey = i;
}
RotKey2 = (RotKey>=(Anim->m_NumRotationKeys-1))?RotKey:RotKey+1;
float TimeDiff = Anim->m_RotationKeys[RotKey2].m_Time - Anim->m_RotationKeys[RotKey].m_Time;
if(!TimeDiff)
TimeDiff = 1;
float Scalar = ((float)time - Anim->m_RotationKeys[RotKey].m_Time) / (float)TimeDiff;
D3DXQUATERNION quatRotation;
D3DXQuaternionSlerp(&quatRotation,
&Anim->m_RotationKeys[RotKey].m_QuatKey,
&Anim->m_RotationKeys[RotKey2].m_QuatKey,
Scalar);
D3DXMATRIX matRotation;
D3DXMatrixRotationQuaternion(&matRotation, &quatRotation);
Anim->m_Frame->TransformationMatrix *= matRotation;
}
if(Anim->m_NumTranslationKeys && Anim->m_TranslationKeys)
{
DWORD PosKey=0, PosKey2=0;
for(DWORD i = 0; i < Anim->m_NumTranslationKeys; i++)
{
if(time >= Anim->m_TranslationKeys[i].m_Time)
PosKey = i;
}
PosKey2 = (PosKey>=(Anim->m_NumTranslationKeys-1))?PosKey:PosKey+1;
float TimeDiff = Anim->m_TranslationKeys[PosKey2].m_Time - Anim->m_TranslationKeys[PosKey].m_Time;
if(!TimeDiff)
TimeDiff = 1;
float Scalar = ((float)time - Anim->m_TranslationKeys[PosKey].m_Time) / (float)TimeDiff;
D3DXVECTOR3 vecPos = Anim->m_TranslationKeys[PosKey2].m_VecKey - Anim->m_TranslationKeys[PosKey].m_VecKey;
vecPos *= Scalar;
vecPos += Anim->m_TranslationKeys[PosKey].m_VecKey;;
D3DXMATRIX matTranslation;
D3DXMatrixTranslation(&matTranslation, vecPos.x, vecPos.y, vecPos.z);
Anim->m_Frame->TransformationMatrix *= matTranslation;
}
if(Anim->m_NumMatrixKeys && Anim->m_MatrixKeys)
{
DWORD Key1 = 0, Key2 = 0;
for(DWORD i=0;i<Anim->m_NumMatrixKeys;i++)
{
if(time >= Anim->m_MatrixKeys[i].m_Time)
Key1 = i;
}
Key2 = (Key1>=(Anim->m_NumMatrixKeys-1))?Key1:Key1+1;
float TimeDiff = Anim->m_MatrixKeys[Key2].m_Time - Anim->m_MatrixKeys[Key1].m_Time;
if(!TimeDiff)
TimeDiff = 1;
float Scalar = ((float)time - Anim->m_MatrixKeys[Key1].m_Time) / (float)TimeDiff;
D3DXMATRIX matDiff = Anim->m_MatrixKeys[Key2].m_MatKey - Anim->m_MatrixKeys[Key1].m_MatKey;
matDiff *= Scalar;
matDiff += Anim->m_MatrixKeys[Key1].m_MatKey;
Anim->m_Frame->TransformationMatrix *= matDiff;
}
Anim = Anim->m_Next;
}
}
AnimSet = AnimSet->m_Next;
}
m_entity->UpdateFrameMatrices(m_entity->m_frameRoot, 0);
m_entity->UpdateSkinnedMesh(m_entity->m_frameRoot);
if(AnimSet == NULL)
return;
}
私の方法は正しいですか?各フレームに対して最初に行うことは、変換マトリックスを恒等にリセットすることです。次に、各キー (移動、スケール、回転、およびマトリックス) の補間値を計算し、それを変換マトリックスに適用します。次に、フレームを更新します。マトリックス、そしてスキニングされたメッシュ。
何か案は?