個別のGLBを独自JSONから再配置して一部だけ大きさが変わる場合は、位置・回転に加えてスケールも保存しているか確認します。この記事では、1.50mの部材をZ方向へ0.9倍にした配置を例に、1.35mの高さを再現する方法を試します。

対象はBlenderのPythonで配置を自動化している人です。GLBを1つ読み込むだけの操作や、すべてのモデルが100倍になる問題を一律に解決する手順ではありません。Godotへ初めてGLBを読み込む手順は別記事で説明しています。

検証環境:Blender 4.3.2、2026年10月12日。付属スクリプトをバックグラウンド実行し、GLBの書き出し・再読み込みと16項目のチェックを行いました。最新版という意味ではありません。

ここでは、Blender座標の配置情報を独自のJSONに保存し、Blenderへ読み込んだGLBに適用するケースを扱います。GLB内部のglTFノードを直接編集する手順ではありません。

Zスケール0.9を失うと、1.35mの高さが1.50mへ戻る

元の部材の高さを1.50m、原点を底面、回転をゼロとします。配置した部材のZスケールが0.9なら、高さは1.50 × 0.9 = 1.35mです。再構築時にスケールを1へ戻すと、位置が同じでも上端が15cm高くなります。

底面原点と位置が同じ部材の比較。Zスケール1では高さ1.50m、0.9では高さ1.35mとなり、上端に15cmの差が出る。
説明用の自作図。元の3Dモデルのスクリーンショットではありません。

位置・回転・スケールをセットで記録する

この小例では、単位をメートル、座標をBlenderのXYZ順、回転をZ軸まわりのラジアンに固定します。別の部材配置と区別できる名前も付けます。

{
  "instance_name": "support_01",
  "location_blender": [0, 0, 0],
  "rotation_z_radians": 0,
  "scale_blender": [1, 1, 0.9]
}

Blenderでは、配置用の親オブジェクトに次の値を設定します。個別GLBを読み込んだ際の内部変換は残し、そのルートを配置用の親の下に置く構成です。配置用の親は新規作成した、制約やアニメーションのないものを想定します。次のコードは変換を設定する部分の抜粋です。

root.location = row["location_blender"]
root.rotation_mode = 'XYZ'
root.rotation_euler = (0, 0, row["rotation_z_radians"])
root.scale = row["scale_blender"]

必須キーとして読むと、欠落時にエラーが出ます。「なければ[1,1,1]」という処理は、意図した0.9が保存されなかった不具合を隠すことがあるため、新しい配置データでは明示する方が点検しやすくなります。Blenderの各プロパティは公式Object APIで確認できます。

再現スクリプトで実際の高さを測る

再現スクリプトと配置JSONをダウンロードし、展開してください。reproduce.pyとplacement.jsonは同じフォルダに置きます。JSONファイルを実際に読み込み、生成した部材を一時GLBへ書き出して、2回読み戻します。一方は比較用にscaleを[1,1,1]、もう一方はJSONの値を使います。比較用の1は意図的な設定で、必須キーが欠けた時の代替値ではありません。

Blender 4.3.2での確認は、展開フォルダをカレントディレクトリにして、次のコマンドで行いました。blenderコマンドが見つからない場合は、インストール済みBlender実行ファイルのパスに置き換えます。

blender --background --factory-startup --python-exit-code 1 --python reproduce.py -- --report result.json

付属のZスケール0.9では、比較用が1.50m、JSONから配置したものが約1.35mになります。placement.jsonの最後の値を0.5へ変更すると約0.75mになります。結果はresult.jsonにも出力されます。同名のレポートがあれば上書きされるので、作業用フォルダで試してください。

  • scaleが[1,1,1]の比較用:実測1.50m
  • JSONのscaleが[1,1,0.9]:実測約1.350000m
  • JSONのscaleが[1.2,0.8,0.5]、位置[10,20,30]、Z回転0.7rad:実測0.75m

高さは画面上の見た目ではなく、読み込んだメッシュ頂点をワールド座標へ変換し、最大Zと最小Zの差から求めます。Z軸だけを回転させるこの例なら、期待値は1.50 × |Zスケール|です。X・Y軸で傾けるとワールドZ方向の高さが変わるので、同じ式は使えません。

Blender 4.3.2で再構築した2本の部材。右側を選択したDimensionsのZは1.35m。
付属コードで再構築した比較シーンをBlender 4.3.2で開いた実画面。右側のDimensions Zは1.35mです。選択中の子メッシュ自体のScaleは1で、0.9の倍率は配置用の親に設定しています。左側は別途選択して1.50mを確認しました。

同じテストをまとめて実行する

展開したフォルダで次のコマンドを実行し、付属の検証をまとめて確認します。

blender --background --factory-startup --python-exit-code 1 --python verify_reproduce.py

最後に「REPRODUCE_TESTS_PASS」と「checks: 16」が表示され、終了コード0なら付属の検証が通っています。scale欠落、要素数不足、真偽値、非有限数、壊れたJSON、Unit Scaleが1以外のケースを含みます。単純な静的メッシュのテストであり、リグやアニメーションの保証ではありません。

scale_blenderを削除したJSONは、オブジェクトを追加する前にエラーで止まります。各XYZ配列が3つの有限数かも検査します。–python-exit-code 1はPython例外を終了コード1として返す指定です。検証スクリプトverify_reproduce.pyでは、0.9と0.5の実測、結果ファイルの読み戻し、不正なJSONの拒否、既存オブジェクトの位置・表示状態を確認します。

この小例はObject Mode、SceneのUnit Scaleが1.0の状態を前提にします。テスト用オブジェクトを追加して選択状態を変えますが、既存オブジェクトの削除や.blendファイルの保存はしません。一時GLBは測定後に削除します。動作確認用の単純な静的メッシュに限るため、親子階層やアニメーションを含む一般的な配置データの検証器としては使えません。

glTFのscaleと独自JSONを混同しない

glTFのノード変換はmatrix、またはtranslation・rotation・scaleで表します。後者の合成はT × R × Sで、頂点にはスケール、回転、移動の順に作用します。scaleを省略した場合の既定値は[1,1,1]です。これはglTFの仕様であり、独自JSONの不足を自動修復する仕組みではありません。Khronos glTF 2.0仕様

また、BlenderはZ-up、glTFはY-upです。この記事のコードはBlenderのインポーターで読み込んだ後にBlender座標の値を使うため、さらに軸変換を加えません。glTFノードを直接読む処理を作る場合は、座標系や四元数の並びを別途確認してください。Khronos glTFの座標系・単位

倍率の二重適用に注意

「スケールを適用して1にすれば解決」と決めつけるのも早計です。Blenderのスケール適用は変換をオブジェクトデータへ反映します。形状へ倍率を焼き込んだ上で配置JSONにも同じ倍率を残すと、二重に縮小する可能性があります。部材側へ焼き込むか、配置側に持つかを揃えましょう。Blender公式Apply説明(4.0日本語版)

うまくいかないときの確認順

  1. 一部だけ高さが違う:配置JSONのscale_blenderがXYZの3要素で保存されているか確認します。
  2. 全体が一定倍率で違う:シーンのUnit Scale、元モデルの寸法、配置側の親スケールを順に調べます。このサンプルはUnit Scale 1.0以外では停止します。
  3. 倍率を直したらさらに小さくなる:モデルへスケールを焼き込んだ後、同じ倍率を配置側でも掛けていないか確認します。
  4. 高さは合うが位置がずれる:原点の位置と親オブジェクトの変換を確認します。原点を移動する基本も参考になります。
  5. Missing required keyで止まる:JSONの必須キーを戻します。[1,1,1]を自動補完して問題を隠すより、保存漏れの原因を直します。

最後は再構築した形状で確認する

JSONの値が揃っただけで終了せず、個別GLBとJSONから組み直して参照シーンと比較します。最低限、配置数、各オブジェクトのワールド変換、外接範囲を確認し、同じカメラと照明で見比べます。

親子階層、制約、アニメーション、XYZ全軸の回転があるシーンには、この記事のZ回転だけの形式では足りません。まずはスケールを含む小さな配置で往復テストを作り、その後に必要な変換情報を増やすと原因を絞りやすくなります。

次に読む記事