Babylon.js を使用して手で操作できる WebXR ピアノを構築してみよう！

この投稿は、[WebXR ( WebVR/WebAR ) Advent Calendar 2021](https://adventar.org/calendars/6556) の 20 日目の記事です。

本記事では、[Babylon.js](https://www.babylonjs.com/) を使って WebXR の VR 空間上に 3D ピアノを構築し、ハンド トラッキングを有効にして手で簡単な操作をできるようにする方法を紹介します。

# Babylon.js とは
Babylon.js は、3D コンテンツとイマーシブ アプリケーションを簡単に開発できるようにする JavaScript 3D エンジンのフレームワークです。Visual Studio Code などの開発環境で実装することはもちろん、[Playground](https://playground.babylonjs.com/) と呼ばれるオンラインのエディターや、[Babylon.js Editor](http://editor.babylonjs.com/) という専用のリッチな開発環境を利用してすぐに開発を始めることができます。Babylon.js Editor については、[Limes](https://twitter.com/limes2018) さんが [紹介記事](https://www.crossroad-tech.com/entry/babylonjs-editor-4.0-release) を書かれているので、興味がある方はぜひご参考ください。

ちなみに、Babylon.js は VR だけでなく AR にも対応しています。[WebXR Plane Detection API](https://immersive-web.github.io/real-world-geometry/plane-detection.html) など新しい機能を使う実装も簡単に行えます。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Babylon.js の AR サポートでキズナアイちゃんを投影 😊<br><br>&lt;model-viewer&gt; ほどお手軽感はないものの、割と簡単なコーディングでカスタマイズ性は高そう。いまのところ iPhone には対応していないが今後に期待デス。<a href="https://t.co/gZZVqZM5bK">https://t.co/gZZVqZM5bK</a><br><br>©︎ <a href="https://twitter.com/hashtag/KizunaAI?src=hash&amp;ref_src=twsrc%5Etfw">#KizunaAI</a> <a href="https://t.co/AIyz3BmFtv">pic.twitter.com/AIyz3BmFtv</a></p>&mdash; ユスキィ (Yusuke Hara) (@ms_yuhara) <a href="https://twitter.com/ms_yuhara/status/1279029640800071680?ref_src=twsrc%5Etfw">July 3, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Babylon.js is encroaching the real world...!! 🎉<br><br>Thanks for really nice features and samples. Here is my demo using WebXR Hit Test and Plain Detection in Babylon.js. <a href="https://t.co/zfmDCREoVl">pic.twitter.com/zfmDCREoVl</a></p>&mdash; ユスキィ (Yusuke Hara) (@ms_yuhara) <a href="https://twitter.com/ms_yuhara/status/1279792752582987777?ref_src=twsrc%5Etfw">July 5, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 3D ピアノ モデルを構築する
さて、VR 空間でピアノを弾けるようにするためには、ピアノの 3D モデルを構築し、それぞれの鍵盤に対応したピアノの音を出力できるようにする仕組みが必要です。一見複雑に思えますが、マイクロソフトが提供している Babylon.js のチュートリアルにしたがって、スクラッチから簡単にピアノの 3D モデルを準備することができます。

&nbsp;&nbsp;[チュートリアル: Babylon.js を使用して WebXR でピアノを構築する](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/javascript/tutorials/babylonjs-webxr-piano/introduction-01)

このチュートリアルでは、以下のような 3D ピアノを構築し、WebXR の VR 空間で実際に演奏できるところまでの実装を紹介しています。そのため、本記事で実現したいことの 9 割はこのチュートリアルで完了です 😂

![3D ピアノ モデル](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672566/cbf3e677-3ee8-090d-5fe0-839d4fcec830.png)

Babylon.js で作成した 3D シーンを WebXR に対応させるにあたり、重要なポイントだけ紹介しておきます。
はじめに、単に WebXR に対応させるだけであれば、以下の 1 行を追加するだけです！非常に簡単です。

``` JavaScript:scene.js
    const xrHelper = await scene.createDefaultXRExperienceAsync();
```

VR 空間でコントローラーを扱えるようにするためには、以下のコードを追加します。あとはコントローラーの操作に応じて発生するポインターのイベントを実装して、ピアノの鍵盤を押下するといったアクションを実現します。

``` JavaScript:scene.js
    const featuresManager = xrHelper.baseExperience.featuresManager;
    const pointerSelection = featuresManager.enableFeature(BABYLON.WebXRFeatureName.POINTER_SELECTION, "stable", {
        xrInput: xrHelper.input,
        enablePointerSelectionOnAllControllers: true
    });
```

VR 空間内を移動できるテレポートを実現したい場合は、床を表現するメッシュを作成し、以下のコードを追加します。これだけでテレポートできるようになります。

``` JavaScript:scene.js
    const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 400, height: 400 });
    const teleportation = featuresManager.enableFeature(BABYLON.WebXRFeatureName.TELEPORTATION, "stable", {
        xrInput: xrHelper.input,
        floorMeshes: [ground],
        snapPositions: [new BABYLON.Vector3(2.4 * 3.5 * scale, 0, -10 * scale)],
    });
```

続いてハンド トラッキングを有効にしていきますが、ハンド トラッキングのような新しい機能を試す場合は、チュートリアルでインクルードしている安定板ではなく、最新のプレビュー版を使用する方が正しく動作することが多いです。以下のようにプレビュー版の JS ファイルに置き換えておきます。

``` HTML:index.html
    <script src="https://preview.babylonjs.com/babylon.js"></script>
```

# ハンド トラッキングを有効にする
WebXR におけるハンド トラッキングとは、正確には [WebXR Hand Input Module - Level 1](https://www.w3.org/TR/webxr-hand-input-1/) という仕様で、2021 年 8 月 24 日に W3C Working Draft として公開されています。具体的には、ベースとなる [WebXR Device API](https://www.w3.org/TR/webxr/) を拡張し、多関節ハンド ポーズをトラッキングする機能を定義しています。

この仕様では、以下の図のような Skeleton Joints を定義しており、Joint のインデックスやボーンの部分にメッシュを作成することで、WebXR の空間上に手を模したオブジェクトを表示できるようにしています。

![WebXR Hand の Skeleton Joints](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672566/bc153f8f-95b0-c86a-542a-cfc6651aa49f.png)

WebXR Hand Input 対応ブラウザーには、Oculus Quest/Quest2 の Oculus Browser や Firefox Reality for HoloLens 2 があります。Oculus Browser では、以前は ``` chrome://flags ``` から以下のように ``` #webxr-hands ``` を有効に変更する必要がありましたが、最新の Oculus Browser では明示的に有効にしなくても、既定でハンド トラッキングできるようになっているようです。

![chrome://flags の #webxr-hands](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672566/ef0ad2b4-707e-8bd2-81e2-11e3f0a6f461.png)

では、Babylon.js で作成した 3D ピアノを手で操作できるようにしてみましょう。これも非常に簡単で、以下のコードを追加します。これだけでハンド トラッキングが動作し、既定の手のメッシュが表示されるようになります。

``` JavaScript:scene.js
    const handTracking = featuresManager.enableFeature(BABYLON.WebXRFeatureName.HAND_TRACKING, "latest", {
        xrInput: xrHelper.input
    });
```

なお、Babylon.js の既定の実装では、人差し指と親指でつまむようなピンチ操作を行うことで、``` POINTERDOWN ``` や ``` POINTERUP ``` のイベントが発生します。そのため、鍵盤をつまむように操作することで、3D ピアノの音を出すことができます。残念ながらこれは現実のピアノの操作性とは大きく異なるものですが、手のメッシュに物理演算のエンジンを組み込むことも可能なため、鍵盤との衝突判定を実装するなどして、よりリアルなピアノを作り込むことも可能と思います。手のメッシュのカスタマイズも可能なため、興味がある方は、Babylon.js のドキュメントを参考にしてみてください。

&nbsp;&nbsp;[Babylon.js - WebXR Selected Features](https://doc.babylonjs.com/divingDeeper/webXR/WebXRSelectedFeatures#hand-tracking)

![WebXR でピアノを弾く](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672566/32706660-cc4e-fe22-abdc-3930f74a75b2.png)

# ライブ デモ
本記事で紹介したコードを実装したデモを [https://tinyurl.com/webxrpiano](https://tinyurl.com/webxrpiano) (リダイレクト先は [https://edgewatcher.azurewebsites.net/babylonjs-piano-tutorial/index.html](https://edgewatcher.azurewebsites.net/babylonjs-piano-tutorial/index.html)) に用意しました。WebXR でなくても通常のブラウザーで開いてピアノに触れることができますが、Oculus Quest 2 など対応デバイスをお持ちの方は、ぜひハンド トラッキングによる操作を試してみてください 😊

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ブラウザーで <a href="https://twitter.com/hashtag/WebXR?src=hash&amp;ref_src=twsrc%5Etfw">#WebXR</a> の VR 空間上に 3D ピアノを構築し、ハンド トラッキングにより手で弾いてみる 👍<br><br>つたない演奏だけどね 🥺 <a href="https://t.co/NzFE4O85h7">pic.twitter.com/NzFE4O85h7</a></p>&mdash; ユスキィ (Yusuke Hara) (@ms_yuhara) <a href="https://twitter.com/ms_yuhara/status/1472152730148155395?ref_src=twsrc%5Etfw">December 18, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

次回は [ft-lab (Yutaka Yoshisaka)](https://qiita.com/ft-lab) さんの "Web からのお手軽 AR の手段 (model-viewer)、glTF/usd による表現力の違いについて" です。