[Hunyuan3D #02 実践] オリジナルモデルを作る(minimal_demo.py / Blender / GLB軽量化Tips)

1. はじめに

前回の #01 では、Hunyuan3D(ShapeGen / TexGen)を Windows + CUDA 環境で動かすためのセットアップ までを整理しました。

今回はその続きとして、実際に手を動かして 1枚の画像からオリジナルの3Dモデル(GLB)を作る実践編 を進めます。

題材は、昨日生成した 焚火(takibi)モデル です。 minimal_demo.py を使って画像からGLBを生成し、その後に Blenderで確認・軽微編集 を行い、Babylon.js で使いやすい形に整えるところまでを扱います。

今回のポイントは、単に「生成できた」で終わらないことです。実際に運用してみると、以下のような“実務でハマるポイント”が出てきます。

  • Blenderで再エクスポートしたら GLBのサイズが急に肥大化 した
  • GitHubにpushしようとしたら、100MB制限で弾かれた
  • ファイルを消したのに、なぜかpushできない(=Git履歴に残っていた)

こうしたトラブルは、手順書だけでは出てこない部分ですが、実際に3Dアセットを扱うとかなり高確率で遭遇します。 そのため本記事では、生成手順に加えて、GLBの軽量化やGit運用の注意点 までまとめて共有します。


テーマ

今回のテーマは、単発の生成テストではなく、「作って、直して、使える形にする」までの実践フロー です。 具体的には次の5点を軸に進めます。

2. 入力画像の準備(焚火画像)

今回の入力には、焚火の画像 assets/takibi.png を使います。 Hunyuan3D は 1枚画像から形状とテクスチャを推定 するので、入力画像の作り方で結果がかなり変わります。

同じコードを使っていても、画像の状態が違うだけで

  • 形がきれいに出る
  • 形が崩れる
  • テクスチャがにじむ
  • 不要な突起や面が出る

といった差が出やすいです。 そのため、生成前に「画像をどう準備するか」はかなり重要です。


今回使う画像

今回のサンプルでは、プロジェクト内の assets フォルダに配置した焚火画像を入力に使います。

image_path = 'assets/takibi.png'

このように、minimal_demo.py 側でパスを差し替えるだけで、生成対象を切り替えられます。 まずは1枚に固定して、結果を見ながら少しずつ調整していくのが効率的です。


背景は透過PNGが扱いやすい

Hunyuan3Dの入力はRGB画像でも動きますが、背景が透過されたPNG の方が扱いやすいです。

理由は単純で、背景情報が強いとモデルがそれを「形状の一部」と誤認しやすいからです。 例えば、背景の影・床・壁・模様が強い画像を入れると、

  • 背景の面が一緒に立体化される
  • 物体の輪郭が崩れる
  • 下側に謎の土台ができる

といった形でノイズになりやすくなります。

透過PNGが用意できるなら、それを使うのが基本です。 もしRGB画像しかない場合でも、今回のコードでは BackgroundRemover を使って背景除去できる構成にしているので、最低限の保険になります。


単体オブジェクトが中央にある画像が安定しやすい

入力画像は、できるだけ 「主役が1つ」「中央にある」 状態にしておくと安定しやすいです。

Hunyuan3Dは1枚画像から立体を推定するため、画面内に複数の情報があると、どれを主対象として扱うかが曖昧になります。 その結果、形状が混ざったり、輪郭が不安定になったりしやすくなります。

今回の焚火のようなケースでは、次の条件を満たすとかなり扱いやすいです。

  • 被写体が中央寄り
  • 背景がシンプル
  • 被写体が見切れていない
  • 余白が極端に広すぎない(小さすぎて埋もれない)

「被写体が小さくて背景が大半を占める画像」より、 被写体が適度なサイズで画面の中心にいる画像 の方が、形状の推定が安定しやすい印象があります。


影や背景が強いと形状が崩れやすい

特に注意したいのが、強い影・床への落ち影・背景のコントラスト です。

見た目としては自然な画像でも、モデル側から見るとそれが「別の形」に見えてしまうことがあります。 今回のような焚火は、火・薪・発光・影が混ざりやすい題材なので、入力画像の質で差が出やすい部類です。

以下のような画像は崩れやすくなります。

  • 影が濃く、輪郭と一体化している
  • 背景が複雑(草、床模様、壁のテクスチャなど)
  • 被写体の一部が白飛び/黒つぶれしている
  • 発光が強すぎて輪郭が消えている

このあたりは、コード側の工夫よりも先に、画像を少し整えるだけで改善 することが多いです。


ここで一言Tips

最初の1体を作るときは、題材選びで成功率がかなり変わります。


まずは小物(焚火・壺・箱・岩)から始めると成功率が高い

Hunyuan3Dの挙動を掴む段階では、まず 形が単純な小物 から試すのがおすすめです。

例えば:

  • 焚火(今回)
  • 置物

このあたりは、全体のシルエットが分かりやすく、1枚画像からでも形状がまとまりやすいです。 また、多少ディテールが崩れても「小物の味」で許容しやすいので、最初の成功体験を作りやすいです。


人物・細いパーツ・複雑な形は難易度が上がる

逆に、最初から人物や複雑なモチーフを狙うと、一気に難易度が上がります。

特に難しいのは以下のようなケースです。

  • 人物(手指、髪、服のひらひら)
  • 細いパーツが多いもの(鎖、枝、脚の細い家具)
  • 空間的に抜けが多い形(柵、骨組み)
  • 前後関係が複雑なもの

1枚画像ベースだと、見えていない裏側や細部の推定が難しいので、破綻が出やすくなります。 このあたりは、まず小物で生成フローを安定させてから挑戦する方がスムーズです。


今回の進め方

今回は、まず assets/takibi.png を使って 1回生成を通し切ること を優先します。 その上で、結果を見ながら

  • 画像の余白調整
  • 背景除去の改善
  • 明るさ・コントラスト調整

などを必要に応じて足していく流れにします。

次の章では、minimal_demo.py を使って実際に ShapeGen → TexGen → GLB出力 を行うコードを見ていきます。

3. minimal_demo.py で GLB を生成する(本編)

ここからは、実際に minimal_demo.py を使って 焚火画像からGLBを生成 していきます。 今回の本編はこのパートです。

Hunyuan3D の基本フローはシンプルで、ざっくり言うと次の2段階です。

  1. ShapeGen で形状(メッシュ)を作る
  2. TexGen でテクスチャを焼く(色を付ける)

この2つを順番に実行して、最後に .glb として出力します。

実行コード(今回使った最小構成)

まずは、今回使ったコードをそのまま載せます。 #01 の環境構築が終わっていれば、この形でそのまま試せます。

from PIL import Image

from hy3dgen.rembg import BackgroundRemover
from hy3dgen.shapegen import Hunyuan3DDiTFlowMatchingPipeline
from hy3dgen.texgen import Hunyuan3DPaintPipeline

model_path = 'tencent/Hunyuan3D-2'
pipeline_shapegen = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained(model_path)
pipeline_texgen = Hunyuan3DPaintPipeline.from_pretrained(model_path)

image_path = 'assets/takibi.png'
image = Image.open(image_path).convert("RGBA")
if image.mode == 'RGB':
    rembg = BackgroundRemover()
    image = rembg(image)

mesh = pipeline_shapegen(image=image)[0]
mesh = pipeline_texgen(mesh, image=image)
mesh.export('takibi.glb')

このコードで、assets/takibi.png を入力として、最終的に takibi.glb が出力されます。


処理の流れ(上から順に)

コード自体は短いですが、役割がはっきり分かれているので、順番に見ていくと理解しやすいです。


1) 画像読み込み(PIL)

最初に、入力画像を PIL.Image で読み込みます。

image_path = 'assets/takibi.png'
image = Image.open(image_path).convert("RGBA")

ここでは RGBA に変換しています。 透過PNGを扱う前提なので、アルファ込みで持っておく形です。

実務メモ 透過PNGを使うなら RGBA で扱うのが素直です。 背景付きのJPEG/PNGを使う場合は、後段の背景除去とセットで考えます。


2) 背景除去(必要な場合)

次に BackgroundRemover を使う処理があります。

if image.mode == 'RGB':
    rembg = BackgroundRemover()
    image = rembg(image)

この処理の役割は、背景付き画像(RGB)を入力したときの保険 です。 背景を切り抜いて、被写体だけに近い状態にしてからShapeGenに渡します。

ただし今回のコードは、直前で convert("RGBA") しているため、image.mode は基本的に RGBA になります。 そのため、このままだと if image.mode == 'RGB' は通らず、背景除去は実行されません。

つまり、今回のように最初から透過PNGを使う想定なら、それで問題ありません。 逆に RGB画像から背景除去したい場合 は、以下のように書く方が分かりやすいです。

image = Image.open(image_path)
if image.mode == "RGB":
    rembg = BackgroundRemover()
    image = rembg(image)
else:
    image = image.convert("RGBA")

この形にしておくと、透過PNGでもRGB画像でも動きが明確になります。


3) ShapeGen(形状生成)

ここが、3D形状を作る本体です。

mesh = pipeline_shapegen(image=image)[0]

Hunyuan3DDiTFlowMatchingPipeline は、Hunyuan3Dの ShapeGen(形状生成) を担当するパイプラインです。 入力画像から3Dメッシュを推定して返します。

記事内では、ここを次のように説明すると分かりやすいです。

  • ShapeGen = 立体の形を作る工程
  • まずここで「形がそれっぽく出るか」を確認する
  • 見た目(色)はまだ最終形ではない

実務的にも、まずShapeGenの結果が良いかどうかを見るのが重要です。 形が崩れている場合、TexGenを回しても根本的な改善にはなりにくいので、先に入力画像側を見直す方が効率的です。


4) TexGen(テクスチャ生成)

次に、生成したメッシュへテクスチャを付けます。

mesh = pipeline_texgen(mesh, image=image)

Hunyuan3DPaintPipeline は、Hunyuan3Dの TexGen(テクスチャ生成) のパイプラインです。 ShapeGenで作ったメッシュに対して、元画像を参考に色や見た目を付けてくれます。

記事では、ここを「ペイント工程」として説明すると直感的です。

  • TexGen = 形に色を塗る工程
  • ShapeGenで作った形状に、元画像の雰囲気を反映したテクスチャを付ける
  • 見た目の完成度を上げる工程

今回の焚火のように、火や薪の色味が重要な題材では、TexGenの有無で見た目の印象がかなり変わります。


5) GLB出力

最後に、生成結果をGLBとして保存します。

mesh.export('takibi.glb')

これで takibi.glb が出力されます。 このファイルは、そのまま

  • Blender で読み込んで確認・編集
  • Babylon.js に読み込んで配置
  • 他のglTF対応ツールで確認

といった形で使えます。

今回の記事では、このあとBlenderで開いて、向きやサイズ感、書き出し設定を調整していきます。

解説ポイント(記事本文向けまとめ)

Hunyuan3DDiTFlowMatchingPipeline

形状生成(ShapeGen) を担当するパイプラインです。 入力画像から3D形状(メッシュ)を推定して作ります。


Hunyuan3DPaintPipeline

テクスチャ生成(TexGen) を担当するパイプラインです。 ShapeGenで作ったメッシュに対して、元画像を元に色や質感を付けます。


BackgroundRemover

RGB画像の背景除去に使います。 透過PNGを使う場合は不要なこともありますが、背景付き画像を使う場合の安定化に有効です。


mesh.export(’takibi.glb')

生成した結果を .glb として保存します。 Blender や Babylon.js にそのまま持っていける形式なので、実制作に接続しやすいのが便利です。

4. 実行時間を短くするコツ(重要)

Hunyuan3D を使っていると、最初に気になるのが「1回の実行にどれくらい時間がかかるか」だと思います。 実際、生成系ワークフローは 試行回数がそのまま作業時間に直結 するので、ここをうまく回せるかどうかで体感がかなり変わります。

今回の焚火モデル作成でも、コード自体は短いのに、初回実行や再試行で思ったより時間がかかる場面がありました。 逆に言うと、いくつかコツを押さえるだけでかなり楽になります。

この章では、実際に使ってみて効いた時短ポイントを整理します。

4-1. 初回は遅い(キャッシュのダウンロード)

最初にいちばん重要なのがこれです。 初回実行は遅くて普通 です。

from_pretrained() を使っているので、初回は内部で

  • モデル本体のダウンロード
  • 関連ファイルの取得
  • キャッシュ作成

が発生します。 このタイミングでは GPU を使った生成処理だけでなく、ネットワークとファイルI/Oの時間も入るので、かなり待つことがあります。

一方、2回目以降はダウンロード済みのファイルが使われるため、キャッシュが効いて体感速度がかなり改善 します。


キャッシュ場所(Windows の例)

Windows環境では、Hugging Face 系のキャッシュは通常このあたりに入ります。

  • C:\Users\<ユーザー名>\.cache\huggingface\...

環境によって多少構成は違いますが、.cache\huggingface 以下にモデル関連データが溜まっていきます。 「初回だけやたら遅い」「2回目から速い」という挙動は、ここにキャッシュができているためです。


実務メモ

  • 初回は“動いていない”と誤解しやすい 実際はダウンロードやロード中のことが多いです。
  • 記事やメモには「初回は時間がかかる」と明記しておくと親切です。
  • 複数モデルを試す場合(例: Hunyuan3D-2 / Hunyuan3D-2mini)、モデルごとに初回コストがあります。

4-2. 画像サイズを下げる

入力画像が大きすぎると、生成の前処理・メモリ使用・全体の処理時間が無駄に重くなりやすいです。 特に「とりあえず結果を見たい」段階では、最初から超高解像度を入れるメリットはあまりありません。

まずは 512〜1024px程度 を目安に試すのがおすすめです。

  • 512px:試行回数を増やしやすい
  • 1024px:見た目の情報を少し残しやすい
  • それ以上:最終調整用なら検討、ただし重くなりやすい

小物は高解像度入力でも差が出にくいことがある

今回の焚火のような小物モデルでは、入力を極端に高解像度にしても、見た目の差が思ったほど出ないことがあります。 一方で、処理時間や扱いづらさだけ増えることがあるので、最初の段階では “ほどほどの解像度” が効率的です。

特に、焚火・壺・箱・岩のような題材はシルエットと大きな色面が重要なので、まずは中くらいの解像度で十分です。


実務メモ

  • 元画像をリサイズして takibi_1024.png などに分けておくと比較しやすいです。
  • バリエーションを試すときは、画像解像度も一緒に記録すると後で再現しやすくなります。

4-3. まず ShapeGen だけ確認する(段階実行)

Hunyuan3D の処理は、ShapeGen(形状生成)→ TexGen(テクスチャ生成)の2段階です。 毎回TexGenまで一気に回すと時間がかかるので、試行時は まずShapeGenだけで形を確認 すると効率がかなり良くなります。


Shapeのみで確認する例

mesh = pipeline_shapegen(image=image)[0]
mesh.export('takibi_shape_only.glb')

この段階で確認したいのは、主に以下です。

  • シルエットが大きく崩れていないか
  • 余計な面や土台が出ていないか
  • 焚火として成立する形になっているか

形が良さそうなら、そのあとで TexGen を回してテクスチャ付きの完成版を作る流れにすると、無駄な待ち時間を減らせます。


段階実行のメリット

  • 失敗パターンの切り分けがしやすい 形が悪いのか、色が悪いのかを分けて見られる
  • 試行回数を増やせる TexGenを毎回回さないだけでだいぶ軽くなる
  • 画像調整の効果を確認しやすい 背景除去や余白調整の影響が見えやすい

生成AIのワークフローは、最初から完成形を狙うより、段階ごとに確認 した方が全体として速いです。


4-4. バリエーション試行は「画像側」を先に調整

生成結果を改善したいとき、ついモデル側の設定やコードをいじりたくなりますが、実際には 入力画像の整形 の方が効くことが多いです。

今回のような minimal_demo.py ベースの実行では、まず画像側を調整した方が再現性も高く、比較もしやすいです。

優先して見直したいのはこのあたりです。


明るさ

暗すぎる画像は輪郭が潰れやすく、明るすぎる画像は輪郭が飛びやすいです。 焚火のように発光が強い題材は特に、火の部分だけ白飛びしていると形状推定が不安定になりやすいです。

  • 少し暗部を持ち上げる
  • 白飛びを抑える
  • コントラストを強くしすぎない

このあたりを軽く整えるだけで、形の安定感が変わることがあります。


背景除去の質

背景が残っていると、モデルがそれを形状の一部として解釈しやすくなります。 特に、焚火の周りの地面・影・煙っぽい成分はノイズになりやすいです。

  • 透過PNGを使う
  • RGB画像なら背景除去してから渡す
  • 輪郭がギザギザでも、背景がない方がマシなことが多い

「背景付きで綺麗な画像」より、背景なしで被写体だけの画像 の方が安定するケースは多いです。


被写体の余白

被写体が小さすぎると、モデルが対象をうまく捉えにくくなります。 逆に、画面いっぱいすぎても一部が切れたり、情報が詰まりすぎたりします。

  • 被写体が中央
  • 余白は適度(狭すぎず広すぎず)
  • 被写体全体がきちんと収まっている

このバランスを取るだけでも、ShapeGenの結果がかなり安定しやすくなります。


正面向き(見せたい面)

1枚画像ベースでは、入力画像で見えている面が主に使われる ので、「どの角度を見せるか」がそのまま完成形に影響します。

例えば焚火なら、

  • いちばん“焚火らしく”見える向き
  • 薪の配置が分かりやすい向き
  • 火のシルエットが綺麗な向き

を選んだ方が、完成時の見た目も自然になりやすいです。


まとめ(時短の考え方)

Hunyuan3D の時短でいちばん効くのは、GPU設定を細かくいじることよりも、まず 試行の回し方を最適化すること です。

今回の実務的な時短ポイントをまとめると:

  • 初回が遅いのは正常(キャッシュ作成)
  • 画像は512〜1024px程度から試す
  • まずShapeGenだけで形を確認
  • 改善はモデル設定より先に画像側を調整

この4つを押さえるだけで、待ち時間のストレスがかなり減ります。

次の章では、生成した takibi.glb を Blender で開いて、向き・スケール・原点などを確認しながら、Babylon.jsで扱いやすい状態に整えていきます。

5. Blenderでの確認と軽微編集(今回の焚火)

minimal_demo.pytakibi.glb を出力できたら、次は Blender で一度開いて確認します。 この工程は省略もできますが、Babylon.js 側で配置してから違和感に気づくことが多いので、先にBlenderで整えておく方が実務的には安全 です。

今回の焚火モデルでも、生成直後のGLBをそのまま使うのではなく、Blenderで

  • サイズ感
  • 向き
  • 高さ
  • 原点位置

を確認して、Babylon.js で扱いやすい状態に寄せました。

5-1. Blenderで takibi.glb を読み込む

まずは Blender で takibi.glb を読み込みます。

  • [ファイル] → [インポート] → [glTF 2.0]
  • takibi.glb を選択して読み込み

読み込んだら、最初に見るポイントは「見た目の良さ」よりも、まず 配置・向き・原点 です。 見た目はあとで調整できますが、原点や向きのズレはBabylon.js側で毎回補正が必要になって面倒になります。


5-2. サイズ感・向き・原点位置を調整

生成モデルは、題材や画像によってスケール感がかなりバラつきます。 焚火のような小物でも、読み込んでみると

  • 想像より大きい / 小さい
  • 微妙に傾いている
  • 原点が中心ではなく変な位置にある

といったことは普通にあります。

今回のように Babylon.js に持っていく前提なら、Blender上で最低限この3点を揃えておくと後が楽です。


サイズ感

Babylon.js 側で scaling を使って調整もできますが、元データのスケールが極端だと扱いづらいです。 Blender上で「小物として自然なサイズ感」にざっくり合わせておくと、配置時の微調整が減ります。


向き

GLBの見た目は正しくても、正面の向き が自分のプロジェクト基準とズレていることがあります。 焚火のような対称に近い小物でも、薪の見え方や火の見栄えに向きの“正面”があります。

Babylon.js 側で回転を足す前提でも、Blenderで「この向きが正面」と決めておくと、後の配置が安定します。


原点位置

ここが実務上いちばん重要です。 原点が変な位置にあると、Babylon.js側で

  • 地面に置きにくい
  • 回転の中心がズレる
  • スケール変更時の挙動が気持ち悪い

といった問題が出やすくなります。

焚火のような小物は、基本的に 足元(接地面) か 中心 に原点を置くのが扱いやすいです。


5-3. 必要なら回転 / スケール / 位置を修正

見た目を確認して問題があれば、Blender上で軽微編集を行います。 今回の段階では、大きなモデリング作業ではなく、配置のための調整 が中心です。

よくやる修正はこのあたりです。

  • 回転:正面向きを揃える
  • スケール:大きすぎる/小さすぎるの補正
  • 位置:接地位置を合わせる(地面に埋まらないように)

焚火のような小物は、Babylon.js上で地面メッシュの上に置くことが多いので、 Blender上で「底面が0付近」に来るようにしておくと、実装がかなり楽になります。


5-4. Babylon.js用に扱いやすい向きにそろえる

今回の最終用途は Babylon.js なので、Blenderでの確認も「Blenderで綺麗に見えるか」だけでなく、Babylon.jsで使いやすいか を基準にします。

例えば、Babylon.js側でよくやる処理は以下のようなものです。

  • mesh.position.y = ... で地面に置く
  • mesh.rotation.y = ... で向きを変える
  • mesh.scaling.setAll(...) でサイズ調整する

このとき、元のGLBが素直な状態になっていると、コードがシンプルになります。 逆に、原点ズレ・傾き・高さズレがあると、毎回個別補正が増えて、後から見ても分かりにくくなります。

そのため、今回の段階では「見た目を完璧にする」より、配置しやすいデータに整える ことを優先しています。


実務Tips(今回の焚火で効いたこと)

小物は原点を足元 or 中心に揃えると使いやすい

小物モデルは、原点位置で使い勝手が大きく変わります。

  • 足元原点:地面に置く用途に強い(焚火・箱・樽など)
  • 中心原点:回転・演出用途に強い(浮遊物、回転演出など)

焚火は「地面に置く」前提が強いので、今回は 足元寄せ の考え方が相性が良いです。


Y-up(glTF)で扱う前提を意識

glTF / GLB は基本的に Y-up 前提です。 Babylon.js も通常は Y が上方向として扱うので、この前提で向きや高さを確認しておくとズレにくくなります。

Blender上で見た目が合っていても、エクスポート後に「なんか回転が変」「高さが想定と違う」と感じるときは、Y軸基準で再確認すると原因が見つかりやすいです。


Blender上で見た目が良くても、Babylon.jsで地面に埋まる場合がある

これは今回みたいなワークフローでよくあります。 Blenderの画面上では自然に見えていても、Babylon.jsで position.y = 0 付近に置くと、地面に半分埋まって見えることがあります。

原因はほぼ以下のどちらかです。

  • 原点がモデル中心にある
  • メッシュの最低点が原点より下にある

対策としては、Blenderで次を確認しておくと安全です。

  • 原点位置がどこにあるか
  • モデルの底面がどこにあるか
  • 地面基準で置いたときに埋まらないか

「あとでコードで y += 0.3 すればいい」ともできますが、 小物が増えるほど調整値がバラバラになって管理しにくくなるので、最初に揃えておくのが楽です。

6. トラブル:Blender再出力でGLBが肥大化した(35MB→128MB)

今回いちばん実務的にハマったのがここです。 Hunyuan3Dで生成した元の takibi.glb は 約35MB だったのに、Blenderで軽微編集して再エクスポートした bonfire2.glb が 約128MB まで増えてしまいました。

焚火のような小物でこのサイズはかなり重く、Web用途(Babylon.js / Git管理 / 配布)では扱いづらいです。 しかも、見た目の編集自体は軽微だったので、「なぜここまで増えたのか」が最初は分かりにくいのが厄介でした。

ここは同じ流れで作業する人がかなりハマりやすいので、原因と対処をまとめておきます。


6-1. 原因(要約)

BlenderからglTF再出力時、設定次第でデータが膨らむ

GLBは「メッシュ + マテリアル + テクスチャ + その他データ」が1つにまとまった形式です。 Blenderから再エクスポートするとき、書き出し設定によっては、元のGLBよりもデータが大きくなることがあります。

今回のケースでは、単純に「Blenderで編集したから重くなった」というより、再出力時の設定 が主因でした。


特に画像(テクスチャ)の再エンコードで肥大化しやすい

サイズが大きく増える原因として、いちばん効きやすいのが 画像(テクスチャ) です。

GLBの容量は、見た目以上にテクスチャが支配しやすいです。 小物モデルでも、テクスチャが重いと一気にサイズが増えます。

今回も、増加量(35MB → 128MB)から見て、メッシュの差分というより テクスチャ再出力の影響 が大きいと判断できました。 実際、Blenderの書き出し設定を見直しただけでサイズが大きく改善したので、ここが主犯だったと見てよいです。


不要なアニメーション出力も増量要因

今回の書き出し設定では、Blenderの glTF export で アニメーション関連がON になっていました。 焚火のような静的モデル(小物)には不要ですが、ONのままだと不要なデータが含まれる可能性があります。

特に「生成モデル → Blender確認 → 再書き出し」の流れだと、アニメーションを使っていないのにデフォルトでONのまま出力してしまいがちです。 こういう小さな設定の積み重ねで、サイズが地味に増えていきます。


6-2. 対処(今回効いた設定)

今回実際に効いたのは、以下の4点です。 これだけで bonfire2.glb のサイズが大きく改善しました。


1) 圧縮(Draco)ON

Blenderの glTF エクスポート設定で、圧縮(Draco) を有効化します。

  • [ファイル] → [エクスポート] → [glTF 2.0]
  • 右側のエクスポート設定で 「圧縮」 をON

Dracoは主にメッシュ側の圧縮ですが、小物でも一定の効果があります。 特に、最適化を何もしていないGLBよりは確実に扱いやすくなります。

注意 Dracoはテクスチャそのものの圧縮ではないので、サイズ増の主因が画像の場合はこれだけで劇的には減らないこともあります。 ただ、ONにしておく価値は高いです。


2) アニメーションOFF(小物なら不要)

今回の焚火モデルではアニメーションを使っていないので、glTFエクスポート時の アニメーション関連をOFF にしました。

小物モデルで不要な項目は、基本的に切っておく方が安全です。

  • アニメーション
  • シェイプキーアニメーション
  • アクション関連(使っていなければ)

これで無駄なデータ混入を避けられます。 「使ってないけどONのまま」は、GLB肥大化の地味な原因になりやすいです。


3) Purge All(未使用データ削除)

Blenderで読み込み・編集を繰り返すと、内部に未使用データが残ることがあります。 見た目には分かりにくいですが、不要な画像・マテリアル・データブロックが残っていると、書き出し時に影響することがあります。

書き出し前に一度、以下を実行しておくと安全です。

  • [ファイル] → [クリーンアップ] → [すべてパージ(Purge All)]

今回も、サイズ問題を疑ってからこの手順を入れるようにして、再エクスポートの安定性が上がりました。


4) 必要ならテクスチャ解像度を落とす

今回のケースは設定見直しでかなり改善しましたが、まだ重い場合は テクスチャ解像度の見直し が効きます。

焚火のような小物は、4K級のテクスチャを使っても、Web上では差が分かりにくいことがあります。 その場合は、2Kや1Kに落とすだけでサイズをかなり減らせます。

目安としては:

  • 試作・確認用:1K前後
  • 近距離で見せる用途:2K検討
  • 4K:本当に必要な場合のみ

「小物なのにGLBが重い」ときは、まずテクスチャを疑うのが早いです。


6-3. 結果(ビフォー / アフター)

今回の実測結果はかなり分かりやすくて、記事ネタとしても強いです。

  • Hunyuan3D出力(元):takibi.glb ≒ 35MB
  • Blender再出力(設定見直し前):bonfire2.glb ≒ 128MB
  • Blender再出力(設定見直し後):bonfire2.glb ≒ 15MB

最終的に 15MB まで下がったので、Web用途(Babylon.js)としてかなり扱いやすくなりました。 読み込み体感やGit運用の面でも、ここまで軽くなるとかなり楽です。


6-4. 記事に載せると効くポイント(スクショ推奨)

この章は、スクショ付きで載せると説得力がかなり上がります。 特に以下の3点を並べると、読者に伝わりやすいです。

  1. BlenderのglTF書き出し設定画面(圧縮ON / アニメOFF)
  2. ファイルサイズ比較(35MB / 128MB / 15MB)
  3. Windowsエクスプローラー or Git pushログのサイズ表示

「設定を変えたら軽くなった」だけでなく、 どの設定を見直したか + どれくらい減ったか が数字で見えると、再現しやすい記事になります。


6-5. 実務的な学び(今回のポイント)

今回のトラブルで一番大きかった学びは、次の2つです。

  • GLBのサイズは、見た目の編集量ではなく“書き出し設定”で大きく変わる
  • 小物でもテクスチャ次第で一気に重くなる

Hunyuan3Dで生成したあと、Blenderで少し直して使う流れは今後も多いと思うので、 この「再エクスポート時の設定チェック」はテンプレ化しておくとかなり安定します。

7. トラブル:GitHub pushで100MB制限に引っかかった

今回もうひとつハマったのが、GitHubへの git push で 100MB制限 に引っかかった件です。 しかも厄介なのが、エラー時点では「もう重いファイルは消したはず」だったことです。

結論から言うと、原因は Git履歴に 100MB超えの bonfire2.glb が残っていた ことでした。 これは初心者ほどハマりやすいポイントなので、手順ごと残しておきます。


7-1. 何が起きたか(症状)

Blender再出力で一度 bonfire2.glb が 125MB超え になっており、その状態でGitに入っていました。 その後、ファイルを削除したり軽量版に差し替えたりしたのに、git push すると GitHub に拒否されました。

エラーメッセージは要点としてこういう内容です。

  • File public/models/bonfire2.glb is 125.63 MB
  • this exceeds GitHub's file size limit of 100.00 MB
  • GH001: Large files detected

ここで重要なのは、GitHubは「今の作業フォルダ」だけを見ているわけではない という点です。


7-2. ポイント(ここが落とし穴)

「今ファイルが無い」だけではダメ

ローカルのフォルダから bonfire2.glb を消していても、過去のコミットに入っていれば、push時にその履歴ごと送ろうとして失敗します。

つまり、今回のようなケースでは「ファイル削除」だけでは不十分で、履歴から消す必要がある ということです。


Git履歴に100MB超えファイルが残っているとpush失敗

GitHubの制限は、現在の状態だけでなく、push対象のコミット履歴全体 に対してかかります。 そのため、過去コミットに一瞬でも大きいファイルが入っていた場合、履歴を修正しないと通りません。


今回は bonfire2.glb が履歴に残っていたのが原因

実際に確認すると、bonfire2.glb は直近2コミットに含まれていました。 この確認には、以下のコマンドが便利です。

git log --oneline -- public/models/bonfire2.glb

これで「どのコミットにそのファイルが入っているか」が分かります。 今回のケースでは、直近2コミットに入っていたので、そこを修正すれば解決できる状態でした。


7-3. 対処(今回やった手順)

今回はまだ push が成功していない状態だったので、直近のコミット履歴を rebase で修正 する方法で対応しました。 この方法は、履歴を丸ごと捨てずに済むので、実務でも使いやすいです。


1) 対象ファイルが入っているコミットを確認

まず、どのコミットに bonfire2.glb が入っているかを確認します。

git log --oneline -- public/models/bonfire2.glb

ここで対象コミットが2つ出たので、直近2コミットを対象に rebase する方針にしました。


2) インタラクティブrebaseを開始

直近2コミットを編集対象にします。

git rebase -i HEAD~2

エディタが開くので、対象コミットの pickedit に変更して保存します。 (今回のケースでは2つとも対象)


3) 1つ目のコミットからファイルを履歴上外す

rebaseが止まったら、対象ファイルを Gitの管理対象から外し ます。

git rm --cached --ignore-unmatch public/models/bonfire2.glb

ここで --cached を付けるのがポイントです。 これは「作業フォルダのファイルを消す」のではなく、コミット内容から外す 動きになります。

続けて、コミットを修正します。

git commit --amend --no-edit

4) rebaseを続行

1つ目の修正が終わったら、rebaseを進めます。

git rebase --continue

次の対象コミットで再び停止するので、同じ作業を繰り返します。


5) 2つ目のコミットでも同じ作業

同様に bonfire2.glb を履歴から除去して、コミットを修正します。

git rm --cached --ignore-unmatch public/models/bonfire2.glb
git commit --amend --no-edit
git rebase --continue

これで、対象の2コミットから bonfire2.glb を外した状態で履歴が再構成されます。


6) 履歴から消えたか確認

rebase完了後、もう一度ログを確認します。

git log --oneline -- public/models/bonfire2.glb

何も出なければOK です。 これで bonfire2.glb は履歴から消えています。


7) push再実行で成功

最後に push をやり直します。

git push -u origin main

今回はこれで正常に通りました。 ログ上も、送信サイズが軽量化後のサイズ帯に収まっており、重い履歴が除去できていることが確認できました。


7-4. 学び(今回の本質)

GitHubの制限は「現在のファイル」だけでなく「pushする履歴」も見る

これが今回の一番重要なポイントです。

  • ローカルでファイルを削除した
  • .gitignore に追加した
  • 軽量版に差し替えた

これらをやっていても、重いファイルが一度でもコミットに入っていると push は失敗 します。 その場合は、今回のように rebase で履歴を修正 するか、必要に応じて filter-repo / filter-branch などで履歴から消す必要があります。


7-5. 再発防止のメモ(実務向け)

今回みたいな事故を減らすには、最初から「作業用GLB」と「公開用GLB」を分けておくのが有効です。

例えば:

  • public/models/bonfire.glb … 公開用(軽量化済み)
  • public/models/bonfire_wip.glb … 作業用(Git管理しない)

さらに .gitignore で作業用を除外しておくと安全です。

public/models/*_wip.glb
public/models/*_temp.glb
public/models/*_test.glb

3Dアセットは画像や動画と同じで、気づくとサイズが膨らみやすいので、 Git運用のルールを少し決めておくと後でかなり楽になります。


この章までで、Hunyuan3Dで作った焚火モデルを

  • 生成(ShapeGen / TexGen)
  • Blender確認・軽微編集
  • GLB軽量化
  • GitHub運用

まで一通り回せるようになります。

次は補足として、minimal_vae_demo.py の位置づけ(今回の本線ではない理由)を軽く整理しておくと、記事全体がさらにまとまりやすくなります。

8. minimal_vae_demo.py は何に使う?(補足)

Hunyuan3D のサンプルには minimal_demo.py とは別に、minimal_vae_demo.py も含まれています。 名前が似ているので最初は「これも同じ用途?」と思いやすいですが、役割は少し違います。

今回の #02 では本線を minimal_demo.py に絞っていますが、ここで minimal_vae_demo.py の位置づけだけ軽く整理しておきます。


8-1. 位置づけ

これは 画像→3D生成の本線ではない

今回やりたいことは、1枚画像からオリジナル3D(GLB)を作る ことです。 その本線は、ShapeGen + TexGen を使う minimal_demo.py です。

一方で minimal_vae_demo.py は、画像から直接3Dを作る流れではなく、既存のメッシュをVAEで扱う タイプのコードです。 つまり、生成の入口がそもそも違います。


既存メッシュを VAE で latent 化して再構成する検証コード

minimal_vae_demo.py でやっていることをざっくり言うと、次の流れです。

  1. 既存のGLBを読み込む
  2. Surface(点群/表面表現)に変換する
  3. VAEでエンコード(latent化)
  4. VAEでデコード(再構成)
  5. メッシュとして書き出す

つまり、「画像から3Dを新規生成する」というより、すでにある3DをVAE経由で再構成してみる ためのサンプルです。 用途としては、生成パイプライン本体のデモというより、内部表現を触るための検証寄りです。


内部構造理解・再構成品質チェック・研究用途寄り

このコードが活きるのは、例えばこういう場面です。

  • Hunyuan3DのVAEがどういう再構成をするか試したい
  • Hunyuan3D-2Hunyuan3D-2mini で再構成品質を比較したい
  • latent表現ベースの処理や軽量化の可能性を見たい
  • 生成結果の後処理・再構成の研究をしたい

つまり、実制作の最短導線 というより、 「中身をもう少し掘る」「品質や構造を比較する」方向のコードです。


8-2. 今回は使わない理由

目的が「画像からオリジナル3Dを作る」だから

今回の記事の目的は、あくまで

  • 画像を用意する
  • minimal_demo.py でGLBを生成する
  • Blenderで確認・軽微編集する
  • GLBを軽量化してGit管理する

という、実際の制作フローを1本通すことです。 この流れに対しては、minimal_vae_demo.py は役割が少し違うので、ここで深入りすると記事の軸がぼやけます。


読者の導線としては minimal_demo.py が最短

環境構築の次に読者が欲しいのは、まず「1個ちゃんと作れる」ことです。 その意味で、minimal_demo.py は導線が非常に分かりやすいです。

  • 入力画像を差し替える
  • ShapeGen → TexGen を回す
  • GLBが出る

この流れは、Hunyuan3Dを初めて触る人にとっても理解しやすく、再現しやすいです。 一方で minimal_vae_demo.py は、VAE・surface loader・latent・再構成パラメータなど、前提知識が増えるぶん、最初の1本としては少し重いです。

そのため、#02 では 「存在は紹介するけど、使うのは次以降」 という扱いがちょうど良いと思います。


8-3. 将来ネタ(#03候補)

minimal_vae_demo.py は今回の本線ではないですが、逆に言うと 次の検証記事のネタとしてかなり良い です。 特にあなたの実験ログ系の流れと相性が良いです。


VAE再構成でメッシュ品質がどう変わるか

同じGLBをVAEに通したときに、

  • シルエットがどう変わるか
  • 細部がどれくらい落ちるか
  • 面の滑らかさや破綻が出るか

を比較すると、かなり面白い検証になります。 「見た目」と「データ量」のバランスを見る記事にもできます。


Hunyuan3D-2 と Hunyuan3D-2mini の比較

minimal_vae_demo.py のサンプルでも Hunyuan3D-2mini を使う例が出ているので、 ここを入口にして

  • Hunyuan3D-2
  • Hunyuan3D-2mini

の違いを比較する記事は作りやすいです。

比較観点としては、

  • 速度
  • VRAM使用量
  • 再構成品質
  • 小物での実用性

あたりが分かりやすいです。


再構成結果の軽量化 / ディテール差

今回の #02 で「GLBサイズ問題」を扱った流れともつながります。 VAE再構成を挟むことで、場合によっては

  • ディテールが落ちる代わりに扱いやすくなる
  • メッシュ構造が整理される
  • 後段の最適化しやすさが変わる

といった違いが出る可能性があります。

このあたりは、単なる導入記事ではなく、実験記事としてかなり価値が出るテーマ です。

関連記事