mikotoのキーフレーム復元に成功

クォータニオンに不慣れなのもあって大きく手間取ったが
なんとか前進。


まだ、浮動ボーンの扱いなどにおかしなところがあるようだが、mikotoフォーマットについて忘れないうちにメモしておく。


mkmファイルのQuaternionに記録されているキーフレーム値

# 例
0 (0.002538 0.000000 0.000000 0.999997)

は、回転クォータニオン(x, y, z, t)を記録している。
((t, x, y, z)ではない)

この回転クォータニオンには、
「現フレームのボーンのZ軸からの回転状態」から
「一つ前のフレームのボーンのZ軸からの回転状態」への
回転同士の差分が格納されている。
式で書くと
Q_{n}^{-1} \cdot Q_{n-1}
となる。


Q_{n} \cdot Q_{n-1}^{-1}

何故このような形式になっているのかはここではまだ気にしない。


Q_{n}
は、ベクトル[0, 0, 1](Z軸。mikoto形式の基準軸)からベクトル[bone_end - bone_start]への回転クォータニオンとなる。
(さらに[0, 1, 0]から[h点 - bone_start]への回転の2軸をあわせる必要がある。)
外積で回転軸、内積で角度を求めて回転クォータニオンとする。
(ここで回転軸の正規化を怠って数日はまったw)


次にキーフレームからのボーン復元について。
(ここは不正確かもしれない)

これには、親ボーンについて

  • 始点
  • 回転状態
  • 初期回転状態

現ボーンについて

  • 親ボーンの始点からの相対位置
  • 回転状態
  • 初期回転状態

が必要だった。
それぞれの項目について少し説明しておく

親ボーンの始点

ルートから順番に処理していくことで確定してきた
ボーンのワールド座標における始点位置。ルートから再帰的に処理する必要がある。

初期回転状態(mkiのsrot)

ボーンをmqoから読み込んだ状態でのボーンの向き。
つまり[0, 0, 1](Z軸。mikoto形式の基準)から[bone_end-bone_start]への回転クォータニオン
これは、mqoを読み込んだときに求めておく。
もしくはmkiから読み込む。

回転状態

mkmのQuaternionに記録されている値から初期回転状態の影響を除いたもの。
式で書くと
I_{n}^{-1} \cdot Q_{n} \( I_{n-1}^{-1} \cdot Q_{n-1} \)^{-1}
となる(回転初期状態のクォータニオンをInitからIと表記)。
展開すると
I_{n}^{-1} \cdot Q_{n} \cdot Q_{n-1}^{-1} \cdot I_{n-1}
I_{n}^{-1} \cdot MKM \cdot I_{n-1}
となりmkmと親子の回転初期状態から求められる。
mqoを読み込んでいる状態から一切動かしていない場合は、アイデンティティクォータニオン(1, 0, 0, 0)となるはず。
MKMは、キーフレームの動きと初期回転状態を内包しているので
それから初期回転を取り除いている。

親ボーンの始点からの相対位置(mkiのspos)

自身の始点から親の始点をひいたもの。回転初期状態と一緒に求めておく。


以上の情報から

始点 = 親の始点 + (親ボーンの始点からの相対位置 * 親の回転状態)
終点 = 始点 + (Z軸 * 初期回転状態 * 回転状態) * (ボーンの長さ)

という感じでキーフレームのボーンを復元できた。
もっとよいやり方はありそうだが、スケルトンの木構造をルートからたどりながら処理せざるを得ないと思われる。

これでようやく骨がポーズをとれるようになった。
(まだ、モデルと骨が結びついていないので骨だけ)
次のテーマは、キーフレームの補完かスキニングかな。

追加

ボーンの第3の点(H点というらしい)がY軸方向をあらわすっぽい。
おそらく始点->終点がZ軸なのに加えて
(始点->終点)X(始点->H点)がX軸。
求めた(Z軸)X(X軸)がY軸だと思う。
(Xは外積)
これで捻りを表現するということか。
現状だとZ軸しか一致させていないのでX軸かY軸についても一致させないと
不十分な様子。

ここが参考になりそう。
http://marupeke296.com/DXG_No21_BoneControlUsingQuaternion.html

追加2

明らかに間違っているところを直し