hibitの技術系メモ

数学とか3Dとか翻訳とか

なぜ Blender で不用意にアーマチュアを削除するとアバターが仰向けに倒れるのか、そしてなぜそうなっているのか

 ここら辺の話を理由を含めて整理している記事が、検索して見つからなさそうだったので、書いてみます。

 Blender でモデルをいじっているとします。

f:id:hibit_at:20220413102723p:plain

 アーマチュアを削除します。

f:id:hibit_at:20220413102746p:plain

 崩壊します。

f:id:hibit_at:20220413102807p:plain

(画像ではわかりづらいですが、巨大化して仰向けに倒れています)

これを直すためには

f:id:hibit_at:20220413103301p:plain

 全オブジェクトを選択して、「Object -> Apply -> All Transforms」をします(Ctrl + A でもいけます)。実際は、適用する対象はアーマチュア(ボーンの集合体)だけで、適用する項目は Scale と Rotation だけでいいのですが、いちいち選ぶのも面倒だと思うので、全オブジェクトを対象に全項目において適用するのが、手順が少なくて間違いがないです。

 ここまでは良く知られた話だと思いますが、ここからはもう少し踏み込んで話をしていきます。

なぜこうなるのか

 人型のモデル(Unity にならってヒューマノイドと呼ぶことにします)は、ボーンの集合体(アーマチュア)にポリゴンの集合体(メッシュ)が紐づいています。ここで、アーマチュアとメッシュは親子関係になっています。子は親のトランスフォーム(Position(位置)、Rotation(回転)、Scale(拡大)を総称した概念)を引き継ぎます。Unity に慣れている方は、アーマチュアがメッシュの親オブジェクトといえばわかりやすいと思います。

 先程のモデルでは、実はアーマチュアが回転&縮小していて、子であるメッシュはその影響を受けているのです。

f:id:hibit_at:20220413104800p:plain

 アーマチュアの情報を見ると、Rotation と Scale が 1 ではないことがわかります。

 つまり本当は、

f:id:hibit_at:20220413104413p:plain

 これが本来の姿であり、

f:id:hibit_at:20220413104501p:plain

 アーマチュアの子になることによってこのような変形を受けています。

 なので、アーマチュアを削除すると、その束縛から解き放たれて本来の姿に戻ります。これが冒頭に述べた事故が起こる直接的な要因です。

なぜそうなっているのか

 ここで、なんでそんな二重に回転させて差し引きゼロみたいなことをしてるの? と疑問に思う人が多いと思います。販売されている多くのモデルはこのような仕様になっており、それには意味があります。

 それを説明するには座標系の話をする必要があります。

 空間を記述するには 3 次元の軸が必要ですが、実は Blender と Unity ではこの軸の指定の仕方が違います(Blender と Unity に限った話ではないのですが……)。

 Blender右手系 Z-up

f:id:hibit_at:20220413105218p:plain

 Unity は左手系 Y-up です。

f:id:hibit_at:20220413105324p:plain

 そのため、両者の座標を全くの変換なしでやりとりすることはできません。BlenderからUnityを意識したFBXを出力するという記事に詳しいですが、Blender においてデフォルトで出力したメッシュは、Unity においては X 軸の回転が -90 度加えられた状態になっています。

f:id:hibit_at:20220413110027p:plain

Blender で素の monkey を fbx に出力して Unity にインポートした図。X 軸に回転が加えられている)

f:id:hibit_at:20220413110223p:plain

 例えばこのような状態で Apply Rotation をします。

f:id:hibit_at:20220413110425p:plain

 再び回転させて正面を向かせます。(Blender 上の X 軸が 90 度傾いていることに注意してください)

f:id:hibit_at:20220413110746p:plain

 こうしてエクスポートされた fbx は、Unity 上では全く回転のしていない綺麗なデータとなります。

 実は、アバターのデータに対しても全く同じことがいえます。

 Blender 上で整列されたヒューマノイドをそのままエクスポートすると、Unity 上では「アーマチュアが -90度、その子のメッシュがすべて 90度」という、ややこしい差し引きゼロ状態になってしまいます。そうならないように、モデルの作者さんが、Blender 上で調整してくれていたということですね。

この調整をしないとエラーが起こる?

 私が体験した限りではありません。

 私自身、改変をする時はめんどうくさくて Blender 上で Apply All Transform したままの状態で fbx を吐き出し作業をしていますが、この座標系の違い由来のエラーに遭遇したことはありません。なので、この処理は「データが綺麗になる」という意味合いが大きいと考えます。まあ、Unity で動かしていく中で、プラグインの組み合わせによってはエラーを吐くということもありますので、なるべく Unity に合わせておくに越したことはないと思います。

 回転だけでなく拡大にも調整を加えているのは、メートル単位とセンチ単位の互換かと思われます。Unity においては、回転においては上記の問題が起きますが、スケールについては自動調整されるようなので、この点は気にしなくてよいですが、他のソフトとの互換のためにやっているものと思われます。