Xファイルの行列アニメーションだけがうまくいきません
Posted: 2016年3月31日(木) 17:37
Xファイルで回転・スケール・移動のアニメーションが設定されたファイルはうまく再生できるんですが
行列が格納されたファイルだけがうまく再生できません。
XファイルはたぶんSDKにある「tiny.x」というものなのですが、メッシュは正しく読み込めて表示もできますが
行列でアニメーションさせて見ても、変なガタガタした動きを少しするだけで、元々の動きとは似ても似つかない感じです。
一応、メッシュ自体は壊れないので、まったく見当違いな読み方はしてないとは思います。
ソースコードは全部を書くとすごく長くなるので、一部、問題がありそうな箇所だけ掲載してみます。
DirectX7ベースのコードです。
行列が格納されたファイルだけがうまく再生できません。
XファイルはたぶんSDKにある「tiny.x」というものなのですが、メッシュは正しく読み込めて表示もできますが
行列でアニメーションさせて見ても、変なガタガタした動きを少しするだけで、元々の動きとは似ても似つかない感じです。
一応、メッシュ自体は壊れないので、まったく見当違いな読み方はしてないとは思います。
ソースコードは全部を書くとすごく長くなるので、一部、問題がありそうな箇所だけ掲載してみます。
DirectX7ベースのコードです。
//使ってるクラスや構造体 -------
class RotateKey{
public:
FLOAT time;
D3DXQUATERNION rotate;
};
class ScaleKey{
public:
FLOAT time;
D3DXVECTOR3 scale;
};
class PositionKey{
public:
FLOAT time;
D3DXVECTOR3 position;
};
class MatrixKey{
public:
FLOAT time;
D3DMATRIX matrix;
};
class Animation{
public:
std::string name;
std::vector<RotateKey *> RotateKeyList;
std::vector<ScaleKey *> ScaleKeyList;
std::vector<PositionKey *> PositionKeyList;
std::vector<MatrixKey *> MatrixKeyList;
D3DMATRIX *m_mat;
~Animation();
};
class CAnimationSet{
public:
std::string name;
std::vector<Animation *> AnimationList;
HRESULT Load(char *fileName);
~CAnimationSet();
};
//-------------
//アニメーションキー読み込み部分
HRESULT ParseAnimationKey( LPDIRECTXFILEDATA pFileData, Animation* pAnimation)
{
// Read data from the file
LONG pData;
DWORD dwSize;
if( FAILED( pFileData->GetData( NULL, &dwSize, (void**)&pData ) ) )
return NULL;
// Read
DWORD dwKeyType = *((DWORD*)pData); pData += 4;
DWORD dwNumKeys = *((DWORD*)pData); pData += 4;
RotateKey* rotateKey;
ScaleKey* scaleKey;
PositionKey* positionKey;
MatrixKey* matrixKey;
//CString dststr = "";
for(DWORD i=0; i<dwNumKeys; i++)
{
DWORD dwTime = *((DWORD*)pData); pData += 4;
DWORD dwFloatKeys = *((DWORD*)pData); pData += 4; // dwKeyTypeで分かるので無視
switch(dwKeyType)
{
case 0: //回転キー
{
D3DXQUATERNION quat;
quat.w = -*((float*)pData); pData += 4; // 逆にしてます
quat.x = -*((float*)pData); pData += 4;
quat.y = -*((float*)pData); pData += 4;
quat.z = -*((float*)pData); pData += 4;
rotateKey = new RotateKey();
rotateKey->time = (FLOAT)dwTime;
rotateKey->rotate = quat;
pAnimation->RotateKeyList.push_back( rotateKey );
}
break;
case 1: //スケールキー
{
D3DXVECTOR3 v;
v.x = *((float*)pData); pData += 4;
v.y = *((float*)pData); pData += 4;
v.z = *((float*)pData); pData += 4;
scaleKey = new ScaleKey();
scaleKey->time = (FLOAT)dwTime;
scaleKey->scale = v;
pAnimation->ScaleKeyList.push_back( scaleKey );
}
break;
case 2: //移動キー
{
D3DXVECTOR3 v;
v.x = *((float*)pData); pData += 4;
v.y = *((float*)pData); pData += 4;
v.z = *((float*)pData); pData += 4;
positionKey = new PositionKey();
positionKey->time = (FLOAT)dwTime;
positionKey->position = v;
pAnimation->PositionKeyList.push_back( positionKey );
}
break;
default: //行列キーはこれでよい?
{
D3DMATRIX mat;
mat._11 = *((float*)pData); pData += 4;
mat._12 = *((float*)pData); pData += 4;
mat._13 = *((float*)pData); pData += 4;
mat._14 = *((float*)pData); pData += 4;
mat._21 = *((float*)pData); pData += 4;
mat._22 = *((float*)pData); pData += 4;
mat._23 = *((float*)pData); pData += 4;
mat._24 = *((float*)pData); pData += 4;
mat._31 = *((float*)pData); pData += 4;
mat._32 = *((float*)pData); pData += 4;
mat._33 = *((float*)pData); pData += 4;
mat._34 = *((float*)pData); pData += 4;
mat._41 = *((float*)pData); pData += 4;
mat._42 = *((float*)pData); pData += 4;
mat._43 = *((float*)pData); pData += 4;
mat._44 = *((float*)pData); pData += 4;
matrixKey = new MatrixKey();
matrixKey->time = (FLOAT)dwTime;
matrixKey->matrix = mat;
pAnimation->MatrixKeyList.push_back( matrixKey );
}
break;
}
}
return S_OK;
}
//アニメーション再生部分(行列アニメ以外の回転・スケール・移動アニメは完璧に動作してる)
HRESULT CAnimObject::SetTime(FLOAT fTime)
{
D3DXQUATERNION rotate;
D3DXVECTOR3 scale, position;
D3DMATRIX matRotate, matScale, matTrans, *mat = NULL, matMatrix;
Animation* pTmpAnim;
std::vector<Animation *>::iterator iter;
for(iter = m_pAnimSet->AnimationList.begin(); iter != m_pAnimSet->AnimationList.end(); iter++){
matRotate = InterpolateRotateKey(*iter, fTime);
matScale = InterpolateScaleKey(*iter, fTime);
matTrans = InterpolatePositionKey(*iter, fTime);
matMatrix = InterpolateMatrixKey(*iter, fTime);
pTmpAnim = *iter;
mat = pTmpAnim->m_mat;
D3DUtil_SetIdentityMatrix( *mat );
D3DMath_MatrixMultiply( *mat, matTrans, *mat );
D3DMath_MatrixMultiply( *mat, matRotate, *mat );
D3DMath_MatrixMultiply( *mat, matScale, *mat );
D3DMath_MatrixMultiply( *mat, matMatrix, *mat);
}
return S_OK;
}
//↑から呼び出されているキー検索部分
D3DMATRIX InterpolateMatrixKey(Animation *anim, FLOAT fTime)
{
D3DMATRIX m;
D3DMATRIX mat;
D3DUtil_SetIdentityMatrix( mat );
// 行列キーは存在しない
if(anim->MatrixKeyList.size() == 0)
return mat;
std::vector<MatrixKey *>::iterator first = anim->MatrixKeyList.begin();
MatrixKey *pKey;
// キーが一つしか存在しない場合
pKey = *first;
if(anim->MatrixKeyList.size() == 1){
m = pKey->matrix;
// キーが複数存在する場合
}else{
UINT iKey;
UINT dwp2;
UINT dwp3;
// 時間にあったキーフレームを検索する
float Time = (float)fmod(fTime, anim->MatrixKeyList[anim->MatrixKeyList.size()-1]->time);
for (iKey = 0 ;iKey < anim->MatrixKeyList.size() ; iKey++) {
if ((float)anim->MatrixKeyList[iKey]->time > Time) {
dwp3 = iKey;
dwp2= (0<iKey)?(iKey - 1):iKey;
break;
}
}
float fTime1 = (float)anim->MatrixKeyList[dwp2]->time;
float fTime2 = (float)anim->MatrixKeyList[dwp3]->time;
// 時間の前後のキーフレームで近い方を選択する
float fLerpValue = ((fTime2 - fTime1) !=0)?( (fTime - fTime1) / (fTime2 - fTime1)):0;
iKey = (0.5<fLerpValue)?dwp3:dwp2;
m = anim->MatrixKeyList[iKey]->matrix;
}
D3DMath_MatrixMultiply(mat, m, mat);
return mat;
}