🐡

Image-to-3Dで生成したモデルにボーンを追加する

に公開

今回は以下のモデルを使って生成した3次元モデルに対して、リグを組む(ボーンを追加する)ことにトライしてみました。
Blender初心者なので変なところはあるかもしれません。

https://github.com/Tencent-Hunyuan/Hunyuan3D-2

Hunyuan3D-2の環境構築

前提

  • Windows
  • RTX4080
  • Python 3.11.7

作業のメモをとってなかったのですが、おそらくほぼGitHub通りで良かったはずです。
git clone後に以下を実施。

set HF_HUB_DISABLE_SYMLINKS=1 //これだけ手順外で実施
pip install -r requirements.txt
pip install -e .
cd hy3dgen/texgen/custom_rasterizer
python3 setup.py install
cd ../../..
cd hy3dgen/texgen/differentiable_renderer
python3 setup.py install

写真を撮る

適当に子供のぬいぐるみをぱしゃり。

背景を除去。

Image-to-3Dの実施

Hunyuan3D-2のリポジトリ内にあるassetsのフォルダの中に先ほどの用意した写真を「photo.png」という名前でおきます。
用意したファイル名にあわせてexamples/textured_shape_gen_mini.pyを修正します。
私の環境ではメモリが足りないので、miniの方で実行します。

-image_path = 'assets/demo.png'
+image_path = 'assets/haggy.png'

-mesh.export(f'demo_mini.glb')
+mesh.export(f'haggy.glb')

-mesh.export('demo_textured_mini.glb')
+mesh.export('haggy_textured.glb')

Hunyuan3D-2のリポジトリのルートで以下を実行します。

python examples/textured_shape_gen_mini.py

結構長い時間待つと、glbファイルが出力されています。

Blenderで読み込む

前提

  • Blenderはインストール済み

今回はRigifyを使ってみるので、アドオンを有効にしておきます。
「編集」>「プリファレンス」>「アドオン」を開くと、Rigifyというのがあるのでチェックをいれます。

先ほどの生成された2個のglbのうち、texuredの方を「インポート」します。
結果、無事出力されました。

口の中も口っぽい雰囲気にはなってます。

右下の方に小さなゴミがあるので、こいつは消します。

また見た目にわからないゴミが他にもあるので綺麗にしていきます。
これをやらないと、自動的にウェイトを計算しても「エラーはでないけど関節を動かしても何も動かない」という結果になります。

「オブジェクトモード」から「編集モード」に変更して、Aを押して全メッシュを選択状態にしてから「クリーンアップ」から「非平面を分割」「孤立を削除」「距離でマージ」をそれぞれ選択します。
※全角モードになってる場合、Aを押しても反応しないです。半角モードで実行してください。Blenderのショートカットは全角モードだと反応しないようなので注意です。

さらに、選択モードを「辺」にしたうえで「選択」>「非多様体」を選択してみます。
すると一部のメッシュがオレンジ色に変わることがあります。
添付画像でも、もも辺りでちょこっとだけ色が変わってます。

非多様体がある場合は、この状態でもう1度「距離でマージ」を実行します。
オレンジが消えない場合、「距離でマージ」を実行すると画面左下に「距離でマージ」の実行パラメータを編集できる小さなウィンドウがでてるので、そのパラメータを修正してオレンジが消えるように調整します。

リグを組む

Shift+Aで表示されるメニューから「アーマチュア」>「Rigifyメタリグ」>「基本」>「Basic Human」を選択します。

するとメタリグというものが表示されるので、形をあわせます。

形があったら、Ctrl+Aで表示されるメニューの「全トランスフォーム」を選択します。

その後、画面右下の方にあるパネルから緑色の走ってる人みたいなアイコンを選び、「リグを生成」のボタンを押します。

すると、リグが生成されます。

Shiftを押しながら「モデル(geometry)」>「リグ」の順番に選択し(必ずこの順番にクリックする必要があります)、Ctrl+Pを押して表示されるメニューから「自動のウェイトで」を選択します。
これでボーンにあわせてモデルが変形するようになります。

「ポーズモード」や「ウェイトペイント」で正しくバインドできているかは確認できます。
下記画像はポーズモードでアニメーションを手作業で作った結果です。

ハマったところ

最後の「自動のウェイトで」が、ウェイトが計算できなくてもエラーにならないため、だいぶハマりました。
素人の推測ですが、生成AIで作ったモデルには手作業で作るモデルでは起きないようなメッシュが混ざっていて(穴が空いてるとか)、ウェイトの計算が正しくできないのだと思います。

あと、ChatGPTに聞いてもなかなか解決しない。
用語の意味がわからないし、UIの操作をテキストで指示されてもなかなかわからない。
Youtubeの教材を見ても手順的に違いが見つからず苦労しました。

ちなみに

使ったモデルではあまり細かい絵には対応できないです。
ぬいぐるみぐらいの感じならそこまで違和感はないかも…という感じ。

追記:Mixamoのリグを使う

MixamoはAdobeが提供しているサイトです。
ここでモーションがダウンロードできます、

https://www.mixamo.com/

サインイン後、適当なモーションを選び、DOWNLOADボタンを押します。

欲しいのはリグだけなのでWithout Skinを選択します。

ダウンロードしたfbxファイルをBlenderでインポートし、先ほどと同じような感じで形をあわせます。

ただし、前回実施した形があったら、Ctrl+Aで表示されるメニューの「全トランスフォーム」を選択します。については、回転と位置だけを適用し、トランスフォームは適用しません。スケールが違うデータなのでトランスフォームが1.0になると超デカくなって画面外に飛んできます。トランスフォームは0.001で良いです。

で、これの何が嬉しいかというとボーンがMixamoになるのでMixamoのアニメーションをあてるためのマッピングが不要になります。
Rigifyで作ったボーンにMixamoのアニメーションを当てようと思うと、↓のような感じでボーンのマッピング表を作ってclipActionを適用させていく必要があるのですが、ボーンの数が違うし、どのAIに聞いてもうまくいかないし、素人には無理だと挫折しました。

function getBoneMap () {
  const m = {
    mixamorigHips   : 'hips',
    mixamorigSpine  : 'DEF-spine001',
    mixamorigSpine1 : 'DEF-spine002',
    mixamorigSpine2 : 'DEF-spine004',
    mixamorigNeck   : 'neck',
    mixamorigHead   : 'head',
    // 以下略

しかし、TargetもSoruceもMixamoに統一しちゃえば変換が不要になるので、こんな感じでブラウザでも簡単に動かせるようになります。

Discussion