tl;dr: モデルをアニメートするとき、各ジョイントは正しく動きますが、親ジョイントに対しては動きません。
Lua でカスタム構築された IQE ローダーとレンダラーを使用して、スケルトン アニメーション システムに取り組んでいます。この時点では、アニメーション時にスケルトンがバラバラに見えることを除いて、ほぼすべてが機能しています。各関節は正しく移動、回転、スケーリングしますが、親の位置を考慮していないため、ひどい問題が発生します。
IQM の仕様とデモを参照しても、何がうまくいかないのか一生わかりません。私の Lua コードは (私が知る限り) リファレンス C++ と同じです。
ベース ジョイント マトリックスの計算:
local base = self.active_animation.base
local inverse_base = self.active_animation.inverse_base
for i, joint in ipairs(self.data.joint) do
local pose = joint.pq
local pos = { pose[1], pose[2], pose[3] }
local rot = matrix.quaternion(pose[4], pose[5], pose[6], pose[7])
local scale = { pose[8], pose[9], pose[10] }
local m = matrix.matrix4x4()
m = m:translate(pos)
m = m:rotate(rot)
m = m:scale(scale)
local inv = m:invert()
if joint.parent > 0 then
base[i] = base[joint.parent] * m
inverse_base[i] = inv * inverse_base[joint.parent]
else
base[i] = m
inverse_base[i] = inv
end
end
アニメーション フレーム マトリックスの計算
local buffer = {}
local base = self.active_animation.base
local inverse_base = self.active_animation.inverse_base
for k, pq in ipairs(self.active_animation.frame[self.active_animation.current_frame].pq) do
local joint = self.data.joint[k]
local pose = pq
local pos = { pose[1], pose[2], pose[3] }
local rot = matrix.quaternion(pose[4], pose[5], pose[6], pose[7])
local scale = { pose[8], pose[9], pose[10] }
local m = matrix.matrix4x4()
m = m:translate(pos)
m = m:rotate(rot)
m = m:scale(scale)
local f = matrix.matrix4x4()
if joint.parent > 0 then
f = base[joint.parent] * m * inverse_base[k]
else
f = m * inverse_base[k]
end
table.insert(buffer, f:to_vec4s())
end
完全なコードは、詳細な調査のためにここにあります。関連するコードは /libs/iqe.lua にあり、関数 IQE:buffer() および IQE:send_frame() の下部近くにあります。このコードは LOVE ゲーム フレームワークのカスタム バージョンで実行され、Windows バイナリ (およびバッチ ファイル) が含まれています。
最後の注意: 私たちのマトリックス コードは、他の実装といくつかのテストに対して検証されています。