画像から 3D の模型を起こす Pixal3D で、検証用に用意した人物を A ポーズの絵から作り、その姿勢のまま骨を置いて、Mixamo の動きを写せるかを技術検証しました。12,000 三角形・骨付きの人物に動きを付けるところまではできましたが、見た目は粗いままで、成功とは言いがたい出来でした。

この記事は、その途中で、A ポーズの骨に動きを写す所で詰まった話です。写してみると、どの動きでも両腕が前を向いてしまいました。

結論

  • 骨は A ポーズのまま置き、Mixamo(T ポーズ)の動きを写すときに、腕の骨の休みの向きを水平に上げた向きに直してから差を取りました。
  • 骨の向きは bone.tail_local - bone.head_local(人物全体から見た向き)で取ります。Bone.vector(親の骨から見た向き)で直すと、どの動きでも腕が前を向きました。
  • 上腕の上げ角の上限(25°)は、水平からの仰ぎ角 asin(z) で測ります。atan2 で測ると、真上を越えた所で 90° から 170° に飛び、腕を 145° 逆へ回しました。
  • 上げ過ぎた腕を下げる向きは、上げ過ぎるほど体の外向きに寄せました。

試した環境

  • 人物:4方向の絵を A ポーズで描かせ、Pixal3D で起こした約 2.6 頭身の人物(高さを 2.3 に合わせた)
  • Blender 4.5 LTS:骨を置くのと動きを写すのはスクリプトで。骨は Mixamo と同じ名前の 25 本
  • 動き:Mixamo の動き。休みの姿勢は T ポーズ

A ポーズの骨に、T ポーズの動きを写す

4方向の絵は、腕の細い人物でも腕の長さが絵どおりに起きるように、A ポーズで描かせました。そのため骨も A ポーズのまま置きました。Mixamo の動きは T ポーズを休みの姿勢にしているので、写すときは腕の骨の休みの向きを水平に上げた向きに直してから、動きとの回転の差を取りました。

A ポーズの骨に T ポーズの動きを写す流れ

Bone.vector で直すと、腕が前を向いた

休みの向きを直すのに、最初は Bone.vector で骨の向きを取っていました。Bone.vector は親の骨から見た向きです。これで直すと、どの動きでも腕が前を向きました。待機の上腕の向きは (-0.16, -0.86, -0.48) でした。

A ポーズの骨に応援の動きを写した人物。両腕が前に出ている

どちらも「骨の向き」として取れるので、取り違えやすい所です。人物全体から見た向きで取るように直しました。

# 人物全体(アーマチュア)から見た骨の向き
d = bone.tail_local - bone.head_local
# bone.vector は親の骨から見た向きなので、休みの向きの直しには使わない

直した後の待機の上腕は (0.18, -0.02, -0.98) で、体の横に下りる向きになりました。

向きの取り方を直した後の動き。腕が体の横に下りている

人形の腕を体の横へ下ろして直す手

上げ角の上限は、水平からの仰ぎ角で測る

頭の大きい人物では、上げた腕が頭の後ろに隠れないように、上腕の上げ角に上限(25°)を付けました。この角を atan2(d.z, sign * d.x) で測っていたところ、腕が真上を越えた所で角度が 90° から 170° に飛びました。応援の 119〜122 コマ目で、腕を 145° 逆へ回していました。

水平からの仰ぎ角 asin(d.z) に替え、越えた分だけ水平の向きのまま下げると、1コマの最大の回転は 35.2° に収まりました。

# d: 上腕の向き(人物全体から見た、長さ 1 の向き)
elev = math.degrees(math.asin(d.z))   # 水平からの仰ぎ角
# atan2(d.z, sign * d.x) は、腕が真上を越えると 90° → 170° に飛ぶ

atan2 で測ると 1コマに最大 145.0°、asin で測ると最大 35.2°

下げる向きにも気を付ける所がありました。上げた腕の水平の向きはぶれるので、そのまま下げると後ろを向いて 63° 跳ねました。上げ過ぎた分が大きいほど、下げる向きを体の外向きに寄せるようにしました。

確かめていないこと

  • 頭の大きい人物に読める応援の動き(跳ねる・手をたたく・胸の前でガッツポーズ)は確かめていません。

おわりに

A ポーズの骨に T ポーズの動きを写すときは、骨の向きをどこから見た向きで取るかと、角度の測り方が真上で飛ばないか、の2つを押さえると、腕が前を向く崩れと、腕が逆へ回る跳ねは無くなりました。ただ、髪の大きい別の人物では、応援で上げた腕が大きな髪に隠れ、手が髪に刺さったように見える所が残り、人物の見た目も粗いままでした。

※ Blender の Bone.vector などの振る舞いは執筆時点で試した物で、いまは変わっている可能性があります。