Slide 1

Slide 1 text

軽率にWebARアプリでImmersal によるVPSを実装する にー兄さん(@ninisan_drumath) VPS開発座談会

Slide 2

Slide 2 text

発表資料は公開します 内容はすべてSNS共有OK!

Slide 3

Slide 3 text

にー兄さん(@ninisan_drumath) - 筑波大学 情報科学類 - HoloLab inc.アルバイト - Microsoft学生アンバサダー - Iwaken Lab. Unity・WebAR・VPSが興味領域 Project TSUin-MI: 「つくば市をARネイティブな街にする」が目標 愛猫→

Slide 4

Slide 4 text

アジェンダ 1. 開発したもの 2. 実現プロセス 3. おわりに

Slide 5

Slide 5 text

開発したもの

Slide 6

Slide 6 text

WebAR×Immersalの試行 WebブラウザからWebARアプリを起動して Immersalによる位置合わせを実行 サーバーサイド位置合わせによって実現 WebARはBabylon.jsというライブラリで実装 GitHubで公開してます https://github.com/drumath2237/immersal-babylon-webxr

Slide 7

Slide 7 text

経緯やモチベーション (2021年HoloLens Edge上での動作を確認) 2021年10月頃に調査を開始 色々進展があったが最後まで実装しきれず中断 2022/7/1にImmersalのdiscordでひっそりアナウンス The WebAR mode has now been fixed on the Dev Portal. Works on Android Chrome, and you should have the chrome://flags/#webxr-incubations set to 'enabled'. Sample code: view page source for view.html 再チャレンジするか......→できた

Slide 8

Slide 8 text

開発環境 - Immersal REST API(v1.16.1) - Babylon.js 5.x - Vite - TypeScript - Chrome for Android (Google Pixel 4a 5G)

Slide 9

Slide 9 text

位置合わせをする手順 1. カメラ画像などの情報を取得 2. REST APIの仕様に沿ってデータ変換 3. REST APIへのリクエスト 4. レスポンスに沿って座標変換

Slide 10

Slide 10 text

情報を取得する

Slide 11

Slide 11 text

位置合わせに必要な情報 Immersal REST API(後述) のLocalize Imageで必要な情報 ● カメラ画像 ● カメラ内部パラメータ ● Immersal開発者トークン ● マップID配列 https://immersal.gitbook.io/sdk/api-documentation/rest-api#localize-image-1

Slide 12

Slide 12 text

位置合わせに必要な情報 Immersal REST API(後述) のLocalize Imageで必要な情報 ● カメラ画像 ● カメラ内部パラメータ ● Immersal開発者トークン ● マップID配列 ブラウザ上で取得するのが難しかった (セキュリティ上の問題)

Slide 13

Slide 13 text

Raw Camera Access WebXR Device APIに含まれる機能の一つ カメラ画像の取得が可能 現在実験的機能なので、 ARCoreが対応したデバイスの Chrome for Androidでしか動作しない 加えてWebXR Incubationが有効である必要が ある 詳しくはZennにまとめました https://zenn.dev/drumath2237/articles/52d62638c7d06f

Slide 14

Slide 14 text

画像データと内部パラメータの取得 カメラ画像の取得は そのままAPIが利用できる WebGLTextureとして取得できる 内部パラメータは右のような計算式で 取得 let viewerPose = xrFrame.getViewerPose(xrRefSpace); for (const view of viewerPose.views) { if (view.camera) { const cameraTexture = binding.getCameraImage(view.camera); } } function getCameraIntrinsics(projectionMatrix, viewport) { const p = projectionMatrix; let u0 = (1 - p[8]) * viewport.width / 2 + viewport.x; let v0 = (1 - p[9]) * viewport.height / 2 + viewport.y; let ax = viewport.width / 2 * p[0]; let ay = viewport.height / 2 * p[5]; let gamma = viewport.width / 2 * p[4]; }

Slide 15

Slide 15 text

画像データの変換

Slide 16

Slide 16 text

現状整理 Raw Camera Accessで 取得できる画像はWebGLTexture REST APIへのリクエストには Base64エンコードされたPNG画像が欲しい

Slide 17

Slide 17 text

逆算して考える Base64エンコードされたPNG画像にはPNG画像が必要 PNG画像を生成するにはピクセル情報が必要 ピクセル情報を取得るするにはWebGLでなんとかしなきゃ(雑

Slide 18

Slide 18 text

Immersal本家の実装 1. three.jsのエンジンからWebGLコンテキストを取得 2. WebGLコンテキストにWebGLTextureとFrameBufferをバインド 3. FrameBufferにテクスチャを紐づける 4. この状態でreadPixels 5. RGBA値が格納されたUint8Arrayを取得 6. WebWorker上でpngエンコード(UPNGというライブラリを使用)

Slide 19

Slide 19 text

自分の実装 WebGL APIにぎょっとしたので別の方法で試す 1. Babylon.jsのRawTextureを生成 2. RawTextureのフィールドに(強引に)WebGLTextureを代入 3. RawTexture.readPixelでUint8ClampedArrayを生成 4. ImageDataへ変換 5. canvasへ描画してPNG・Base64エンコード 本家のほうがスマートかも

Slide 20

Slide 20 text

REST APIへのリクエスト

Slide 21

Slide 21 text

API仕様に基づいてリクエストするだけ ドキュメントを見ながら必要情報を揃える エンドポイントへPOST https://api.immersal.com/localizeb64

Slide 22

Slide 22 text

レスポンス - マップID - 位置 - 回転行列 が返ってくる リクエストが不適切な場合はerrorだけ 適切なリクエストだけど位置合わせに失敗したら successがfalse ゼロベクトルと単位行列が返ってくる

Slide 23

Slide 23 text

無事リクエストが通った

Slide 24

Slide 24 text

座標変換

Slide 25

Slide 25 text

2種類の座標変換 - Immersal座標系 to Babylon.jsの座標系 - マップ座標系 to ワールド座標系

Slide 26

Slide 26 text

ImmersalとBabylon.js Immersal Babylon.js https://immersal.gitbook.io/sdk/tutorials/how-to-map/custom-im ages#rotation v1.14→v1.15の間で破壊的変更

Slide 27

Slide 27 text

マップ座標 to ワールド座標 Immersal マップ座標系の カメラの姿勢 カメラ座標系の マップの姿勢 ワールド座標系の マップの姿勢 レスポンスから変換行列を作成 逆変換を計算 リクエスト時のカメラの姿勢を適用 Map Physical World

Slide 28

Slide 28 text

座標系変換の手動テストツール

Slide 29

Slide 29 text

座標系変換の手動テストツール スマホを使わずにテストできるツール レスポンスデータをとっておく 姿勢行列の変換処理を実装して その挙動をビジュアルで確認 Babylon.jsのDebugLayerで 実際の数値も確認 トライアンドエラーの敷居を 下げる工夫

Slide 30

Slide 30 text

位置合わせができた

Slide 31

Slide 31 text

おわりに

Slide 32

Slide 32 text

展望・まとめ - WebARでImmersal位置合わせができた - もっといろいろ実験したい - WebARでPlaybackできる機能 - 他のVPSでの検証(PretiaとかGeospatial APIとか) - 一般的な環境でも動作してほしい - WebXR Device API以外のWebAR VPSに劣る点

Slide 33

Slide 33 text

参考文献 Raw Camera Accessのexplaner https://github.com/immersive-web/raw-camera-access/blob/main/explainer.md Raw Camera Accessについての記事 https://zenn.dev/drumath2237/articles/52d62638c7d06f Immersal座標系に関するドキュメント https://immersal.gitbook.io/sdk/tutorials/how-to-map/custom-images デモプロジェクト https://github.com/drumath2237/immersal-babylon-webxr