CrossRoad

AR、MR、VR、Babylon.jsを中心とした技術ブログ。 If you're non-Japanese native guys, check "English" category.

Babylon.jsで360度画像を回転させる方法

以前、Babylon.jsのWebVR機能について書いたとき、360度画像をみられる"photoDome"という機能を少しだけ紹介しました。

Babylon.jsのWebVRモードと通常モードを切り替える方法 - CrossRoad

今回、このような問い合わせがありました。

Twitter上で説明するのは簡単ではないので、photoDomeの回転方法について、サンプルコード付きでまとめました。

以下の環境で動作を確認しています。

Chrome: 74.0.3729.169

Babylon.js:4.0.3

1. photoDomeはsphereにテクスチャを貼ったもの

Babylon.jsはソースコードがGitHubで公開されています。

GitHub - BabylonJS/Babylon.js: Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.

src/Helpers/photoDome.ts の中にはこのような記述があります。

//L140付近
     // create
        let material = this._material = new BackgroundMaterial(name + "_material", scene);
        this._mesh = Mesh.CreateSphere(name + "_mesh", options.resolution, options.size, scene, false, Mesh.BACKSIDE);
//L149付近
        this.photoTexture = new Texture(urlOfPhoto, scene, true, !this._useDirectMapping, undefined, undefined, (message, exception) => {
            this.onLoadErrorObservable.notifyObservers(message || "Unknown error occured");

            if (onError) {
                onError(message, exception);
            }
        });

        this.photoTexture.onLoadObservable.addOnce(() => {
            this._setReady(true);
        });

詳しい処理はソースコードをご確認ください。

2. photoDomeのメッシュ名称はdebugLayerからも確認できる

先ほどのphotoDome.ts L140付近の記述より、名前に"_mesh"をつけたものがメッシュとなります。つまり、以下のような書き方をしたときは、"testdome_mesh"がメッシュの名前になります。

    var dome = new BABYLON.PhotoDome(
        "testdome",
        "./textures/360photo.jpg",
        {
            resolution: 32,
            size: 1000
        },
        scene
    );

これは、Inspectorでも確認することができます。Inspectorとは、Babylon.jsで作った空間のオブジェクトを確認から.babylon形式でのシーンの保存まで、色々な機能が入った補助画面です。

こちらに詳しく書かれています。

Display and Use the Inspector - Babylon.js Documentation

使い方は簡単で、sceneを定義した後で以下の1行を追加するだけです。

scene.debugLayer.show();

debugLayerが有効になると、画面の上にかぶさるような形で表示されます。

debugLayer of Babylon.js

Nodesに記載の通り、"testdome_mesh"と書かれているのがわかります。

3. photoDomeのオブジェクトを取得するにはgetMeshByName()を使う

以前、下記の記事でも書きましたが、Babylon.jsでは、オブジェクトを取得する方法の一つにgetMeshByNameがあります。

UnityからエクスポートしたBabylon.jsデータの制御方法 - CrossRoad

これを使うことで、photoDomeのメッシュ情報を取得することができます。たとえば、下記のように書きます。

var mesh= scene.getMeshByName("testdome_mesh");

4. ActionManagerを使って、キーボード入力でphotoDomeを回転させる

ActionManagerはキー入力を受け付ける機能です。以下で紹介したことがあります。

Babylon.jsのWebVRモードと通常モードを切り替える方法 - CrossRoad

BJS_SwitchToNormal_WebVR/index.html at master · flushpot1125/BJS_SwitchToNormal_WebVR · GitHub

たとえば、ボタン入力のたびにphotoDomeを一定数回転させるには、このように書きます。

scene.actionManager = new BABYLON.ActionManager(scene);
scene.actionManager.registerAction(
new BABYLON.ExecuteCodeAction({
        trigger: BABYLON.ActionManager.OnKeyDownTrigger,
        parameter: 'e' //press "e" key
    },
    function () { 
        mesh.rotation.y += Math.PI/9;//180/9=20deg
    }
));

これでキーボードのEを押すたびにy軸周りに20度回転します。ここでのy軸は、アプリが実行された瞬間の視野と垂直方向です。つまり、y軸周りの回転は実際に人が左右を見回すときと似た方向です。

5. registerAfterRenderを使って、自動的に回転させる

自動的に回転させるには、registerAfterRenderを使います。registerAfterRenderについては、下記を参照ください。

Transform Coordinates - Babylon.js Documentation

先ほど取得したphotodomeの変数meshをy軸周りに回転させるには、このように書きます。

scene.registerAfterRender(function () {
    mesh.rotate(BABYLON.Axis.Y, Math.PI / 360, BABYLON.Space.LOCAL);
});

これでy軸周りに自動的に回転します。

6. ソースコード

下記におきました。

GitHub - flushpot1125/babylonjs_photodome_rotate

7. おわりに

ちょうどBabylon.jsのソースコードをみていたので割と早く解決しました。 次回はソースコードのビルド方法などを書ければと思います。