🎥

PhotoDomeでズームアウトするとパノラマが歪むのでカメラ操作を変更する【Babylon.js】

2022/09/01に公開

概要

babylonjs の PhotoDome と ArcRotateCamera でパノラマビューを作った際、ArcRotateCamera のデフォルト実装だとマウスホイールのスクロールでズームアウトした際に背景が歪む

https://playground.babylonjs.com/#WP9WDU#115

var createScene = function () {
    var scene = new BABYLON.Scene(engine);
    var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2,  Math.PI / 2, 5, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);

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

    dome.imageMode = BABYLON.PhotoDome.MODE_SIDEBYSIDE;

    return scene;
};

Google Street View や three.js の panolens の場合はこうならないので、マウスホイール操作の実装を変えて歪まないようにする。

デフォルトだとスクロール操作で radius が変更されるが、Inspector をいじいじしてみると fov を変更するようにすれば歪まずにズームアウトできそうだったのでやってみた。

対応

camera.inputs.attached.mousewheel.detachControl(); でマウスホイールの操作を無効にしてマウスホイールのイベントを書く

var createScene = function () {
   var scene = new BABYLON.Scene(engine);
   var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2,  Math.PI / 2, 0.1, BABYLON.Vector3.Zero(), scene);
   camera.attachControl(canvas, true);
   // avoid pinch and wheel changes
   camera.inputs.attached.mousewheel.detachControl();

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

   dome.imageMode = BABYLON.PhotoDome.MODE_SIDEBYSIDE;

   scene.onPointerObservable.add((pointerEvt) => {
       camera.fov -= pointerEvt.event.wheelDelta * 0.0001;
       camera.fov = Math.max(0.1, camera.fov);
       camera.fov = Math.min(2, camera.fov)
   }, BABYLON.PointerEventTypes.POINTERWHEEL)

   return scene;
};

実行
https://playground.babylonjs.com/#WP9WDU#122

ズームアウトしても画面の端が伸びるだけで歪まなくなった。
これで Google Street View などのパノラマサイトと同じような挙動

モバイル対応

PCサイトとしてはこれで良いですが、スマホ等のタッチスクリーンデバイスでピンチ操作をした際の挙動がデフォルトのままになっていますのでこちらも書き換えます。

公式ドキュメントの HammerJS Input を参考にタッチ操作のカメラ操作をカスタマイズ
https://doc.babylonjs.com/divingDeeper/cameras/customizingCameraInputs#hammerjs-input

https://github.com/ioridev/babylonjs-zoom-without-distortion/blob/main/src/ArcRotateCameraHammerJsInput.ts

input.multiTouchPanAndZoom = false; でピンチ操作を無効にして先程定義した操作を追加します。
inputs.add(new ArcRotateCameraHammerJsInput());

これでモバイルのピンチ操作でも fov が変更されるようになりました。

サンプル:
https://github.com/ioridev/babylonjs-zoom-without-distortion

Discussion