CrossRoad

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

WebXR対応のBabylon.jsでVRコントローラの各種ボタン入力を制御する方法

以前、WebXRのimmersiveモードとBabylon.jsについて紹介したことがありました。

www.crossroad-tech.com

このときは、VRモード切り替え、テレポート、コントローラを別の3DCGモデルに変更する方法などを紹介しましたが、コントローラの個別のボタン入力の方法が未記載でした。

かなり時間が経ってしまったのですが、コントローラのボタン入力方法を確認できたので、サンプルコード付きでまとめました。

なお、動作確認はOculus Quest2で行っています。

1. WebXR準拠のコントローラ入力について

WebXR Device APIとして、このサイトの中でコントローラ入力について説明があります。

developer.mozilla.org

説明後半の「the WebXR Input Profiles Registry」のリンクからGitHubに飛んで、profilesというフォルダを選択すると、WebXRに準拠したデバイスの製造元のフォルダを確認できます。

github.com

必要なデバイスを選択するとボタン入力に関するjsonファイルがあります。たとえばoculus-touch-v3.json (おそらくOculus Quest2のコントローラ) をみると、このような記載があります。

gist.github.com

ここに書かれたcomponentsの中の要素が、コントローラに割り当てられたボタンです。

もう少し直感的に理解するには、コントローラの割り当て確認サイトを使うのが良いです。このリポジトリのソースコードで動いています。

WebXR Input Profile Viewer

A work example of webxr input profiles viewer

このように、どのボタンがどのIDなのかがわかります。コントローラを右手に変更することもできます。

2. Babylon.jsによるWebXRのVRコントローラー入力方針

公式ドキュメントはこちらです。

doc.babylonjs.com

しかし、なぜかPlayGroundによるサンプルコードが入っておらず、断片的なコードしかありませんでした。そのため、まだWebXRでのやり方をきちんと理解できていない私だとよくわかりませんでした。

大まかに言うと、motionControllerとしてのコンポーネントを複数の手段のどれかを使って取得し、コンポーネントに対して処理を書いていく流れです。

取得手段1:WebXR Device APIで規定された名称を直接取得する

const triggerComponent = motionController.getComponent("xr-standard-trigger");

取得手段1':WebXR Device APIで規定されたidを直接取得する

const xr_ids = motionController.getComponentIds();

xr_idsにはコントローラの入力がマッピングされたjsonファイルのcomponentsの名称が入ります。これを配列として、xr_ids[0], xr_ids[1], ..として使います。

取得手段2:WebXR Device APIで規定されたtypeを直接取得する

const squeezeComponent = motionController.getComponentOfType("squeeze");

ただ、これだと先ほどのWebXR Device APIでは、Oculus Quest2のA, B, X, Yボタンは全てtype:buttonだったので区別がつかないかもしれません。

いくつか調べていたところ、取得手段1'の方法でcomponentを作り、コントローラの入力を設定する方法を書かれているサイトを見つけました。

qiita.com

そこで、この内容を参考にしつつ、直感的にわかるようにキー入力で変化が起きるようにしました。また、簡単に試せるようにPlaygroundで動くようにしました。

3. Babylon.jsによるWebXRのVRコントローラ入力の書き方

まず、Oculus Quest2では、WebXR Device APIでのキー割り当てはこのようになっています。

key mapping of WebXR motion controller (Quest2)

Babylon.jsの中でサポートしているIDを調べたところこうなっていました。

調べた方法

gist.github.com

console.logの出力結果を整理したものです。

[left controller]
xr-standard-trigger
xr-standard-squeeze
xr-standard-thumbstick
x-button
y-button
thumbrest

[right controller]
xr-standard-trigger
xr-standard-squeeze
xr-standard-thumbstick
a-button
b-button
thumbrest

今回はこの中でthumbrest以外のボタンが押されると、sphereまたはcubeが拡大、縮小、移動 (thumbstick割り当てのみ) という単純なサンプルを書きました。

sphereとcubeの割り当てです。

WebXR controller key map for cube and sphere on Babylon.js

ボタン入力についてはこのように書きました。他のボタンも同様です。

gist.github.com

thumb stickについてはこうです。

gist.github.com

ただ、Babylon.jsのWebXRでVRモードにすると、左右のthumbstickのX変位がカメラ向き移動に使われます。そのため、今回の書き方だとthumb stickのY方向は問題ないですが、X方向の入力を入れると合わせてカメラも移動してしまいます。解決方法がわかったら追記します。

全てを書いたものは以下のPlayGroundにあります。

WebXR_motion controller input sample on PlayGround

Ocuus Quest2のブラウザでこのURLにアクセスすると確認できます。このようになります。

ちなみに、thumbrestについては動きが取れませんでした。thumbrest自体よくわかっていないのですが、Oculus公式のサイトをみるとおそらくthumb stickに触れているかどうかなのだと思われます。
わかったら追記します。

Oculus Touch (L) Thumbstick CapTouch - 左コントローラーのサムスティックの静電容量式タッチイベント。[Axis Value (軸値)]は、ユーザーがサムスティックに触れている場合は1を返し、触れていない場合は0を返します。

引用元:Oculus Controller Input Mapping | Oculus Developers

なお、今後使うことはないと思われますが、WebVRモードでのキー割り当てについては以前書いたとおりです。

www.crossroad-tech.com

4. おわりに

シンプルな例ですが、WebXRでのコントローラ入力が整理できたので、Babylon.js Editorで動くようにサンプルコードを準備したいと思います。