Chapter 04

1-03 : モデルを扱う

ちょまど (千代田まどか)
ちょまど (千代田まどか)
2022.05.20に更新

このページの原文: https://doc.babylonjs.com/start/chap1/first_import

💻 Importing a Scene or Model (シーンやモデルのインポート)

モデルをシーンに追加すると、ブラウザからモデルが読み込まれます。
ご存知の通り、web サイトから何かをロードするときは非同期関数を使用します。
したがって、モデルで何かをする前にそのモデルがちゃんとロード完了されていなければなりません。
そのためには SceneLoader.ImportMeshAsync メソッドを使用し、下記のように実行します。

BABYLON.SceneLoader.ImportMeshAsync(model name, folder path, file name, scene);

シーンのパラメータはオプショナルで、デフォルトだと現在のシーンとなります。
最初のパラメータは、すべてのモデルをロードするか、1つのモデルのみをロードするか、モデルのリストをロードするかに応じて、以下の 3 つのタイプのいずれかになります。

// 空文字列はすべてのメッシュをロード
BABYLON.SceneLoader.ImportMeshAsync("", "/相対パス/", "ファイル名"); 

// ひとつのモデルの名前を指定
BABYLON.SceneLoader.ImportMeshAsync("モデル名1", "/相対パス/", "ファイル名"); 

// 複数のモデルの名前の配列
BABYLON.SceneLoader.ImportMeshAsync(["モデル名1", "モデル名2"], "/相対パス/", "ファイル名"); 

上記の呼び出しはいずれもモデルをロードのみすることに注意してください。(ロードするのみで、それらを操作することはしていません。)
内部的には、Promise オブジェクトがセットアップされて返されていますが、上記のコードはその返ってきた Promise の結果について何もしていません。(表示して終了してるだけ)(その辺の操作をするのはこの後やります)

この例は、次の 2 つの Playground (リンク先参照) にあり、そしてそれらは指定された名前のモデルのみインポートしていることがわかります。

  1. Loading Your First Model (最初のモデルをロード)
    BABYLON.SceneLoader.ImportMeshAsync("semi_house", "https://assets.babylonjs.com/meshes/", "both_houses_scene.babylon");
  2. Loading Multiple Models at Once (複数のモデルをまとめてロード)
    BABYLON.SceneLoader.ImportMeshAsync(["ground", "semi_house"], "https://assets.babylonjs.com/meshes/", "both_houses_scene.babylon");

BABYLON.SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "both_houses_scene.babylon"); の場合。(第一引数が空文字列なので全てのモデルをロードしてる)

ロード完了時にオブジェクトを操作する

ということで、さっきは表示して終了でしたが、次は、ロード完了したオブジェクトを(位置を変えたり)操作してみましょう。
処理の結果にもとづいてオブジェクトを操作するために、Promise の結果 (result) を使った then メソッドを使用します。result オブジェクトにはロードされたすべてのモデルのメッシュなどが入っています。

BABYLON.SceneLoader.ImportMeshAsync("", "/relative path/", "myFile")
    .then((result) => {
        result.meshes[1].position.x = 20;
        const myMesh1 = scene.getMeshByName("myMesh_1");
        myMesh1.rotation.y = Math.PI / 2;
});

ロード完了時のオブジェクト操作サンプル

この Playground でのサンプルでは、すべてのモデルをインポートした後、そのモデルの位置を変更する処理をしています。

https://playground.babylonjs.com/#YNEAUL#13
const createScene = function () {
    const scene = new BABYLON.Scene(engine);
    const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 15, new BABYLON.Vector3(0, 0, 0));
    camera.attachControl(canvas, true);
    const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
    // モデル読み込み
    BABYLON.SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "both_houses_scene.babylon")
        .then((result) => { // 読み込みが完了したら
            const house1 = scene.getMeshByName("detached_house");
            house1.position.y = 2; // y 軸方向(↑)に +2
            const house2 = result.meshes[2];
            house2.position.y = 1;
    });
    return scene;
};


y 軸は上に伸びています

https://twitter.com/chomado/status/1480616107711303680

☞ Moving On (次は)

Playground のシーンで作業するのもひとつの手ですが、最終的には、ゲームまたはアプリケーションを自分の web サイトで実行する必要があります。 次のセクションでは、これを行うための HTML テンプレートを提供します。

❕ Warning (モデルインポート時の注意)

モデルを Babylon.js にインポートするときの注意点です。

例1

一部のソフトウェアでは、rotationQuaternion がセットされた状態ですべてのメッシュを保存するため、最初に次のコードを追加しない限り、rotation メソッドを使用できません。

任意のバージョンの Babylon.js

// Any version of Babylon.js
myMesh.rotationQuaternion = null; 

4.00 以上のバージョンの Babylon.js

// babylon.js versions > 4.00
myMesh.rotation = BABYLON.Vector3.Zero(); 

例2 (.babylon と .glb)

まったく同じシーンからエクスポートされ、Babylon.js にインポートされた .babylon.glb それぞれのファイルの中身を見てみましょう。

.babylon モデルは 1 つのメッシュとして保存されます。つまり、各家の本体と屋根が 1 つの家を形成します。

detached_house
ground
semi_house

一方、 .glb では、サブメッシュとして保存されるすべてのモデルとモデルパーツを保持するために、_root_ ノードが追加されます。

_root_
    detached_house
        detached_house primitive0
        detached_house primitive1
    ground
    semi_house
        semi_house primitive0
        semi_house primitive1