ボーン情報ファイル(*.bnf)
一行目の数字がボーンの数、次の行からは(ボーンのインデックス)(親ボーンのインデックス)
(ボーン回転中心の座標x,y,z)の順番に並んでいます。
ただし回転中心は、親ボーンのローカル座標ではなく、モデルのローカル座標で表されております。
即ちこれらを順にID,ParentID,Rx,Ry,Rzとおくと、ボーンインデックスIDのボーンが、クォータニオンq[ID]を
与えられた場合の変換行列は以下のようになります:
(注:一般的な線形代数の教科書が変換を行う順に次々と左から掛けているのに対して、
DirectXでは行列の掛け算の順番がそれとは逆になっているようです。これは行列Mに対して
ベクトルvを変換する場合の表現が、DirectXではv*Mとなっているからです。一般的な線形代数の
本では、ほとんどがM*vの表記になっていると思います)
- ID = 0の場合
Matrix[ID] = T( -Rx , -Ry , -Rz ) * QuaternionToMatrix(q[ID]) * T( Rx , Ry , Rz )
- ID > 0の場合
Matrix[ID] = T( -Rx , -Ry , -Rz ) * QuaternionToMatrix(q[ID]) * T( Rx , Ry , Rz ) * Matrix[ParentID]
ここで、T( x , y , z)は( x , y , z )だけ平行移動させる変換行列、QuaternionToMatrix(q)はクォータニオン(q)
を対応する行列に変換したものです。式の中身については、やはり他のサイトや書籍に譲ることにします。
ただ、DirectXにはD3DXQuaternionRotationMatrixという関数が用意されていて、これを用いれば
クォータニオンを行列に変換することができます。
ちなみに、アニメーションを再生させる場合であれば、キーフレームごとのクォータニオンの親子関係を
あらかじめ全て計算しておいてもいいでしょう。この場合、変換行列は次のようになります:
- ID = 0の場合
Matrix[ID] = T( -Rx , -Ry , -Rz ) * QuaternionToMatrix(q’[ID]) * T( Rx , Ry , Rz )
- ID > 0の場合
Matrix[ID] = T( -Rx’, -Ry’, -Rz’) * QuaternionToMatrix(q’[ID]) * T( Rx’, Ry’, Rz’)
但し、
q’[0] = q[0]
q’[ID] = q[ID] * q’[ParentID] (ID > 0)
であり、Rx’,Ry’,Rz’は、
クォータニオンp( w , x , y , z ) = ( 0 , Rx , Ry , Rz )、
クォータニオンp’( w , x , y , z ) = ( 0 , Rx’, Ry’, Rz’)
とおいたときに、
p’ = q’[ParentID] * p * q’-1[ParentID]
となります。
なお、常にParentID < IDとなっているので、IDを0から順に(ボーンの数−1)までforループを用いて
1ずつ増加させながら計算すれば、全てのq’[ID]を取得することができます。
(近日中にこの部分のプログラムソースコードをアップロードする予定です)