mikotoのキーフレーム復元に成功
クォータニオンに不慣れなのもあって大きく手間取ったが
なんとか前進。
まだ、浮動ボーンの扱いなどにおかしなところがあるようだが、mikotoフォーマットについて忘れないうちにメモしておく。
mkmファイルのQuaternionに記録されているキーフレーム値
# 例 0 (0.002538 0.000000 0.000000 0.999997)
は、回転クォータニオン(x, y, z, t)を記録している。
((t, x, y, z)ではない)
この回転クォータニオンには、
「現フレームのボーンのZ軸からの回転状態」から
「一つ前のフレームのボーンのZ軸からの回転状態」への
回転同士の差分が格納されている。
式で書くと
となる。
逆
何故このような形式になっているのかはここではまだ気にしない。
は、ベクトル[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に記録されている値から初期回転状態の影響を除いたもの。
式で書くと
となる(回転初期状態のクォータニオンをInitからIと表記)。
展開すると
となり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
明らかに間違っているところを直し