Meta Quest ブラウザのWebXRの対応状況(2022年11月) 

以前、Oculus QuestのWebXR Device APIを試しましたが、当時はまだ古いWebVR APIが主流でした。

https://qiita.com/binzume/items/e9f3dcb90d2f006c066e

３年以上経過しましたが、ChromiumやMeta Questブラウザ(Oculus Broeser)のWebXRサポートは徐々に進んでいます。
また、最近Meta Quest Proの発表に合わせて、いくつかの機能が利用可能になりました。

# 最近利用可能になったAPI

WebXR Device APIはまだ発展途上で、いろいろな機能が追加され続けていますが、最近Meta Questブラウザで利用可能になったAugmented Reality Module、Anchors Module、Plane Detection Moduleの動作を確認してみました。

- WebXR Augmented Reality Module (`immersive-ar`)
- WebXR Anchors Module (`anchors`)
- WebXR Plane Detection Module (`plane-detection`)

plane-detectionやanchorsを使って、部屋の壁に写真を貼り付けるみたいなことが簡単にできるようになりました。


![xrplanes2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58515/d1aec6de-8acb-8698-392b-f5c02eb8a5f3.jpeg)

## 環境

- Meta Quest Pro
- Meta Questブラウザ: 24.2.0.12.55.415101478(Chromium 106.05249.126)

Quest Proで確認していますが、Quest2のブラウザでも最新版にアップデートされていればほとんどの機能は動作します。

(Meta Questブラウザのリリースノート長らく更新されてないようなので、アップデート内容を知るには、フォーラムやSNSを監視したりChromiumの更新内容を見るのが確実？)

## WebXR Augmented Reality Module

https://immersive-web.github.io/webxr-ar-module/

パススルー機能を使ったARがブラウザ上で使えます。

セッション作成時、XRSystem.requestSession()に`immersive-vr`に加えて、`immersive-ar`を渡せるようになりました。すでに多くのARライブラリが`immersive-ar`をサポートしているのでそのまま動きます。

映像はトラッキング用のセンサとして使ってるカメラと共用のようで、画質は荒いのと、奥行き情報も無いのでオクルージョンなどもできませんが、レイテンシもほとんどないので違和感なく動きます。画像が荒いのはフレームレートを維持したり、奥行きに合わせて画像を補正したりする処理の都合に思えます。
もちろんQuest 2では白黒です。

## WebXR Anchors Module

https://immersive-web.github.io/anchors/

`requiredFeatures` もしくは `optionalFeatures` オプションに `anchors` を追加することで利用可能です。

Anchors Moduleは以前から使えましたが、いつのまにか `XRAnchor.requestPersistentHandle()` が動くようになっていました。

ブラウザやデバイスを再起動しても維持できるので、現実世界の特定の場所にオブジェクトを固定できます。

気をつけないといけないのは、サイトのoriginごとに作れるPersistentHandleの個数に制限があるのと、作成済みのHandleの一覧なども取得できないので、UUIDを自分で管理して不要になったら`deletePersistentAnchor`を呼び出して削除する必要があります。

上限に達すると `Failed to execute 'requestPersistentHandle' on 'XRAnchor': Maximum number of anchors reached!` のようなエラーが発生します。
UUIDを覚えてない場合、JavaScriptからは何もできなくなるのでブラウザのサイトのデータを削除しないといけません。Quest Browserの設定からはPersistent Anchorだけ消すような操作はできないのでcookieやlocalStorageなどの情報も一緒に消えます。

おそらくこれはバグだと思いますが、現状`deletePersistentAnchor()`に失敗することがあって、無視して使ってるとわりとすぐ上限に達します。createAnchor()で作ったXRAnchorに対してrequestPersistentHandle()して、同じセッション上でdeletePersistentAnchor()すると失敗するようなので、次回XRセッションを作るときまで保存しておいて、リトライするしか無さそうでした。

あとrequestPersistentHandleに成功するのにdeleteもrestoreもできなくなることがありました。この場合はQuestのガーディアン設定をクリアして設定し直したら解決。ガーディアンごとに何か状態を保存しているようです。
原因が分からず、デバイスを再起動したり、adb shell pm clearでブラウザのストレージをクリアしたりしてもだめで、ファクトリーリセットするか迷いましたが、ガーディアン設定に思い当たって良かったです。

とりあえず、現状は頻繁にAnchorを作ったり更新したりすることは避けて、原点にAnchorを一つ作っておいて相対位置を管理するなどしたほうが無難そうです。

AFRAME用のコンポーネントの実装例：
https://github.com/binzume/vr-workspace/tree/master/apps/xranchortest

## WebXR Plane Detection Module

https://immersive-web.github.io/real-world-geometry/plane-detection.html

`requiredFeatures` もしくは `optionalFeatures` オプションに `plane-detection` を追加することで利用可能です。

現実世界の平面を検出できる機能ですが、Questでは事前に設定した机や部屋のポリゴンにアクセスできるようです。ガーディアンで設定した床の形状なども使えません。

天井や床は設定した形状に外接する矩形が設定されているみたいなので、ちゃんとした床の形状を表すポリゴンがほしいときは壁の平面を使って切り抜くなどする必要があります。


AFRAMEで平面を表示する例(上のスクリーンショットの緑のライン)：
https://github.com/binzume/vr-workspace/blob/master/js/xrplane.js


# まだ使えない機能

```
Feature 'hit-test' is not permitted by permissions policy
Feature 'light-estimation' is not supported for mode: immersive-ar
Feature 'depth-sensing' is not supported for mode: immersive-ar
Unrecognized feature requested: camera-access
Unrecognized feature requested: marker-tracking
```

Hit Test ModuleはChromiumには実装されていますが、Quest上ではパーミッションが無いと言われてしまいます。カメラの映像を使う機能も利用不可。

# 雑感

欲しい機能は徐々に揃ってきている感じがします。

まだカメラ映像の上にレンダリング結果をオーバーレイするだけですが、Depth Sensing Moduleなどが使えるようになると、現実世界の物体を考慮した処理ができるようになるのと、カメラ映像にアクセスするAPIが使えれば、見える風景を書き換えられるようになるので将来に期待。

ただ今のところ、Chromiumが積極的にWebXRをサポートしてくれていますが、他のブラウザはいまいちなので、どうなるかが少し心配。