以前、Babylon.jsのWebVR機能について書いたとき、360度画像をみられる"photoDome"という機能を少しだけ紹介しました。
Babylon.jsのWebVRモードと通常モードを切り替える方法 - CrossRoad
今回、このような問い合わせがありました。
@WheetTweet はじめまして。Limesさんの書いた記事を参考にBabylonJSのPhotoDomeを触っています。もしよろしければ、PhotoDome自体を自動的に(scene.registerAfterRenderの中で値を変更するなどして)回転させる方法をご教示いただけないでしょうか。domeのrotationを変更しても効果は見られず…。
— XEGASY (@YSAIQS) 2019年6月11日
Twitter上で説明するのは簡単ではないので、photoDomeの回転方法について、サンプルコード付きでまとめました。
- 1. photoDomeはsphereにテクスチャを貼ったもの
- 2. photoDomeのメッシュ名称はdebugLayerからも確認できる
- 3. photoDomeのオブジェクトを取得するにはgetMeshByName()を使う
- 4. ActionManagerを使って、キーボード入力でphotoDomeを回転させる
- 5. registerAfterRenderを使って、自動的に回転させる
- 6. ソースコード
- 7. おわりに
以下の環境で動作を確認しています。
Chrome: 74.0.3729.169
Babylon.js:4.0.3
1. photoDomeはsphereにテクスチャを貼ったもの
Babylon.jsはソースコードがGitHubで公開されています。
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が有効になると、画面の上にかぶさるような形で表示されます。
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のソースコードをみていたので割と早く解決しました。 次回はソースコードのビルド方法などを書ければと思います。