CrossRoad

XRを中心とした技術ブログ。 Check also "English" category.

Blender2.9を使ってPLATEAUの3DCGモデルの位置を原点付近に自動的に移動させるPythonスクリプトについて

以前、PLATEAUの3DCGモデルをインポートするとうまく表示されないことと、その対応方法を書きました。

www.crossroad-tech.com

そのとき、ポリゴン数削減やorigin to geometryなどは自動実行できるようにしましたが、位置の調整が未対応でした。

今回、位置の調整までできたので備忘録も兼ねて方法を解説します。

1. 今回の位置調整方針

PLATEAUの3DCGモデルをそのまま読み込むと、CGのWorld空間の原点から遠く離れています。Babylon.js Editorではこの距離が遠すぎてうまく読み込めないこともありました。

この遠い距離の辺りに座標を合わせてCameraを移動させれば見えるはずですが、やはり原点付近にある方がわかりやすいので3DCGモデルの位置関係を保ったまま原点付近に移動させようと思いました。

Blenderで"A"キーを押して全選択し、ドラッグを繰り返せば実現できます。しかし、そもそも面倒ですし、x=70000のような値もあって一回のドラッグでは1000程度しか移動しないので、ドラッグの繰り返しはかなり大変です。

そこで、このように考えました。

how to optimize distance for PLATEAU model

これにより、Blenderに表示されているPLATEAUの3DCGモデルを原点の付近に移動させることができます。もちろんimport直後の絶対的な距離を気にしなければならない場合は使えませんが、ちょっとPLATEAUを使ってウォークスルーを試したいとか、一部の区域の地形データだけを使って何かを作りたい場合はこれで十分だと思います。

2. Blenderで選択したオブジェクトのx, y座標や原点からの距離を算出するPythonスクリプトの記述方法

この処理は2段階に分かれています。最初の1つめがこちらです。

gist.github.com

BlenderでPythonを使うとき、読み込んだ全メッシュを対象とするには、

    for obj in bpy.context.view_layer.objects:
        if obj.type == 'MESH':

を使用します。配列に追加するにはappendです。

2つめの処理がこちらです。

gist.github.com

ここでは、最初の処理で作ったdistance_listsの配列の中を調べて、値が最も大きい要素のindex番号をmax_distance_indexに格納しています。

配列pos_listsとdistance_listsは同じ順番で作っています。そのため、pos_listsのmax_distance_index番目のxとyの値が原点から最も遠いオブジェクトのxとyの値ということになります。

あとは同じようにbpy.context.view_layer.objectsを使って全メッシュを対象にして、この処理を書いて各オブジェクトのxとyの座標を移動させています。

            obj.location.x = obj.location.x - pos_lists[max_distance_index][0]
            obj.location.y = obj.location.y - pos_lists[max_distance_index][1]

3. 動作確認

動画にまとめました。

youtu.be

この記事では説明用にスクリプトの一部しか紹介していないのでこのままでは実行できません。完全なスクリプトは以下のGitHubに置いてあります。

github.com

4. それぞれのフレームワークで読み込んだときの大きさについて

今のところ、フレームワークと3DCGモデルの拡張子によって、読み込み直後の大きさが変わります。
表にするとこのような感じです。表でのscaleはBlenderで設定した値です。「それぞれのフレームワークの初期画面からズームイン/アウトをしないでも表示される場合は「ちょうどよい」、ズームイン/アウトが必要な場合は「大きすぎる」、「小さすぎる」(ズームインしないと形状や詳細が識別困難) と書いています。

フレームワーク fbx (scale=1) glb (scale=1) glb (scale=10)
Babylon.js Editor ちょうどよい 小さすぎる ちょうどよい
Three.js Editor 大きすぎる ちょうどよい 大きすぎる
Godot Engine 未対応 小さすぎる ちょうどよい

いくつか画像を貼ります。

■Three.js Editorで fbx (scale=1)をインポート

Imported a PLATEAU model as fbx(scale=1) in Three.js Editor

■Three.js Editorで glb (scale=1)をインポート

Imported a PLATEAU model as glb(scale=1) in Three.js Editor

Three.js Editorの初期画面はGridが画面全体に表示されます。つまり、glb (scale=1) がちょうどよい大きさです。

■Godot Engineで glb (scale=1)をインポート Imported a PLATEAU model as glb(scale=1) in Godot Engine

■Godot Engineで glb (scale=10)をインポート Imported a PLATEAU model as glb(scale=10) in Godot Engine

WebXRのimmersive-vrモードにしたとき、画面に表示されているcubeがほぼコントローラと同じ大きさです。

5. おわりに

元々、Babylon.js EditorやGodot EngineのWebXRコンテンツを作る方法を解説するためにPLATEAUモデルを軽く使いたいだけだったのですが、思ったよりも補正が必要でした。今回のPythonスクリプトには位置調整以外にも、ポリゴン数削減、origin to geometry、メッシュ結合なども入っているので、Unityを使う場合であってもPLATEAUの3DCGモデルが使いやすくなると思います。