画像から 3D の模型を起こす Pixal3D で、検証用に用意した人物を作り、12,000 三角形に減らして骨を付け、動きを付けられるかを技術検証しました。動きを付けるところまではできましたが、見た目は粗いままで、成功とは言いがたい出来でした。

この記事は、その途中の骨を付ける段で詰まった話です。Blender で Mixamo と同じ名前の骨を置いて自動ウェイトをかけると、警告が出て、腰のほかはどの骨にも重みが付きませんでした。

結論

  • Blender で書き出した GLB を読み直すと、UV の継ぎ目で頂点が割れていました。境界の辺が 10,308 本、5,980 個の切れた島になっていて、bone heat がどの骨でも解けませんでした。
  • 骨を付ける前に bmesh.ops.remove_doubles で頂点を繋ぐと、警告が消え、腕・脚の骨にも重みが付きました。UV は面の角ごとに持っているので崩れません。
  • 減らした後に小さなかけらや潰れた三角形が残っていても、全部の骨で失敗しました。一番大きい塊だけを残すと通りました。
  • 重みが付いた後、腕を下ろすと襟にしわが寄り、上げると上着の裾が開きました。脇の下より下と胸の内側で腕の重みを切ると、どちらも直りました。

試した環境

  • Blender 4.5 LTS:スクリプトを blender -b(画面なし)で動かした
  • 模型:Pixal3D の人物を 12,000 三角形に減らし、GLB で書き出した物
  • 骨:Mixamo の名前(mixamorig: で始まる)の骨 25 本を置き、ARMATURE_AUTO(自動ウェイト)で親子付け

腰にしか重みが付かない

骨を付けるスクリプトでは、整えた後に書き出した GLB を読み込み、骨を置いて自動ウェイトをかけていました。1回目は次の警告が出ました。

Warning: Bone Heat Weighting: failed to find solution for one or more bones

骨ごとに重みの付いた頂点を数えると、腰(mixamorig:Hips)が 6,111 頂点で、背骨・腕・脚の骨はどれも 0 でした。重みの無い頂点を腰と頭に振る後処理を入れていたので、腰の分はその後処理で付いただけです。警告の文は「1本以上の骨で」ですが、実際にはどの骨でも解けていませんでした。

読み直した模型が、継ぎ目でばらばらだった

Blender で書き出した GLB を、読み直しただけの模型を数えました。

項目値
頂点12,150
面12,000
境界の辺10,308
多様体でない辺10,308
位置の重なった頂点6,170
つながった塊5,980

glTF では UV の継ぎ目で頂点が分けて持たれ、読み込むとそのまま継ぎ目で割れています。継ぎ目ごとに切れた島になり、bone heat がどの骨でも解けませんでした。自分で書き出した物を読み直しただけなので、ここが割れているとは疑いにくい所です。

骨を付ける前に、頂点を繋ぎました。UV は面の角ごとに持つので、頂点を繋いでも崩れません。

import bmesh

bm = bmesh.new(); bm.from_mesh(mesh.data)
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=1e-6)
bm.to_mesh(mesh.data); bm.free()

これで警告が消え、腕・脚の骨にも重みが付きました。

減らした後のかけらでも、全部の骨で失敗した

その後、減らす前に中空の殻の中を塗りつぶすための升(3次元の格子)を細かく(7mm に)して減らすと、3 頂点だけのかけらが 15 個と、潰れた三角形が残りました。この模型では、bone heat が全部の骨で失敗しました。一番大きい塊だけを残すと通りました。頂点を繋いでも失敗するときは、小さなかけらが残っていないかも数えてみる値打ちがあります。

人形の肩と胸の境を指で区切る手

重みが付いた後の、襟と裾

重みが付いて腕が動くようになると、別の所が崩れました。腕を下ろすと、襟にしわが寄りました。

腕を下ろした人物。襟にしわが寄っている

腕を上げると、上着の裾が開きました。

腕を上げた人物。上着の裾が開いている

脇の下より下と、胸の内側で腕の骨の重みを切ると、どちらも直りました。

腕の重みを切った後に腕を下ろした人物。襟のしわが無い

腕の重みを切った後に腕を上げた人物。上着の裾が閉じている

おわりに

自動ウェイトがどの骨でも解けないときは、骨より先に模型のつながりを数えると、原因が分かりました。試した Blender 4.5 LTS では、glTF を読み直した模型が UV の継ぎ目で割れていました。頂点を繋いで重みが付き、襟と裾の崩れも直せましたが、解けたのは骨の重みの問題までで、人物の見た目は粗いままでした。

※ Blender の glTF の読み込みと自動ウェイトの振る舞いは執筆時点で試した物で、いまは変わっている可能性があります。