8thWall で HoloLensのコンテンツを作る


# ~~特に明記されているようには見えないのですが~~HoloLens 2でも動きます。

結論から言うと~~一部の機能とは言え動きます。~~ World Effectsでコンテンツを作ることができます。 

8thWallはNiantic社のWebXRプラットフォームです。
このプラットフォームでは開発に必要な環境が全て提供されており、通信環境とブラウザだけあればXRコンテンツを作り、アプリとして公開することができます。利用者側はURL（QRコード）でアクセスするとブラウザからARコンテンツを体験することができます。

* コードエディタ
* コードの構成管理,資産管理
* コードのデプロイ
* アプリの公開（本番環境,検証環境）

WebXR系なので、Javacsriptベースでの開発になります。言語はA-frame, Three.js, Babylon.jsなどいくつか選ぶことができるので自身の好みのSDKで開発ができます。
加えてNianticのサービスに関連する独自の機能を利用することができます。

* Sky Effects
実空間の空の部分のみにARコンテンツを描画する機能(遠方空間のため3DOF基準)
* World Effects
SLAMによるARコンテンツ描画(近接空間のため6DOF基準)
* Lightship VPS
VPSによるWaySpotをつかったコンテンツ作成に必要

Lightship VPSについては過去整理した資料もあるので参考にしてみてください。

https://qiita.com/miyaura/items/e7f1ac6bf318a5461f11

そんな8thWallなのですが、当初モバイルAR向けのプラットフォームでいわゆるXRデバイスであるヘッドセットでは利用できない状況があったのですが、Meta Quest 3等一部のデバイスでは動作するようになっています。

(2024/03/22 追記)
[8thwallのForumで確認](https://forum.8thwall.com/t/since-when-can-8thwall-execute-on-hololens-2)してみたのですが、以下のブログでHoloLensについてはWorld Effectsはサポートしているとアナウンスされている話を聞きました。

https://www.8thwall.com/blog/post/59297774102/introducing-reality-engine-8th-wall-webar-moves-beyond-the-smartphone

## とりあえず動くのをみる

簡単なデモを公開しています。このアプリは床面に草を生やすだけのアプリなのですがa-frameで作成しています。

https://www.8thwall.com/reseul/multidevicesggw

元のコードは以下のプロジェクトなのでこちらもマルチデバイスにはなっているのですがいくつか設定に問題がありうまく動かなかったので調整したものが上記になります。


他にも公開されているサンプルなかにもいくつか動かくものがあります。例えば、以下のプロジェクトもHoloLens 2で動きます。

https://www.8thwall.com/8thwall/manipulate-aframe

8thWall自体がマルチデバイス対応したプラットフォームとなったことで簡単にマルチデバイスかつデプロイ不要のWebXRということで使い方次第では面白いコンテンツも作ることができるかもしれません。今回はHoloLens 2でう動かすために注意すべきポイントなどを紹介します。

## 作り方

基本的な考え方（カメラ原点等）はUnityやUnreal Engineのネイティブ開発をそれほど差はありません。8thWallの場合はブラウザ１つで開発できるのでその気になったら、思いついたその場でアプリを作ることができます。
今回はa-frameでの作り方を紹介します。

【流れ】
1. 空のA-frameテンプレートを使った新しくプロジェクトを作る
1. デバイス関連の設定
1. オブジェクトを操作できるようにする設定
1. デバッグと実行

### 1.空のA-frameテンプレートを使った新しくプロジェクトを作る

まずはA-frameの空プロジェクトを作成します。

https://www.8thwall.com/8thwall/unitcube-aframe

リンク先の[Clone Project]を押すと自分の環境にクローンが作られます。プロジェクト名やタイトルなどを設定して生成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/2ed660c1-6c61-db0a-5731-c9abb8a51f48.png)

生成するとコードエディタが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/44cfc332-7ebc-4195-eb78-7cd91038db52.png)

このサンプルにはCubeが１つ設置された状態なのですがこのCubeを操作できる形で修正しHoloLens 2 で実際に動かしてみたいと思います。

### 2. デバイス関連の設定

修正するのはBody.htmlのみですが関連する設定も見ていきます。
8thwallではA-frameの<a-scene>タグに属性を付与することでXR関連の設定を行うことができます。利用できる属性は次の通りです。

* xrconfig
カメラ関連の設定
* xrweb
World Effects関連の設定
* xrlayers
Sky Effects関連の設定
* xrface 
顔認識関連の設定
* xrhand
ハンドトラッキングの設定

設定できる項目の詳細は公式のドキュメントに記載があります。

https://www.8thwall.com/docs/ja/api/aframe/

今回はシンプルに空間に物体を表示してそれを操作することを実現します。この場合に必要な要素してはxrconfigとxrwebの2つになります。xrwebとxrconfigは一部共通する設定もあるのですが、8thwall全体で利用する設定項目がxrconfig、World Effects関連の設定がxrconfigにあります。World Effectsは自身の周辺の空間を使用した6DOFのARコンテンツを作る際に利用する機能で、8thwallでは基本的な機能といえます。
この他にもxrWebにはImage Target,Lightship VPSなどの設定もあります。

有効にするためにはbody.htmlに記述がある<a-scene>タグに属性を付与するだけで有効化できます。ちなみに、World Effectsのテンプレートを使うとこの他にも関連する機能が追加されます。実はこのテンプレート自体オブジェクトの操作を行うための設定も入っています。それについては次の手順で紹介します。

```html
<a-scene 
landing-page
xrextras-loading
xrextras-runtime-error
xrextras-gesture-detector
xrweb="allowedDevices: any">
....
```

ここでポイントになるのはxrwebの設定項目になります。allowDevicesの設定を変えることで対応するデバイスを変更することができます。設定項目は以下の通りで、HoloLens 2でアプリを起動させるためには[mobile-and-headsets]を設定するようなのですが、anyを設定しても動作はしています。anyを設定するとPC上でもVRをブラウザで体験することも可能です。

* mobile
* mobile-and-headsets
* any

### 3.オブジェクトを操作できるようにする設定

次にオブジェクトの操作を行うための設定です。オブジェクトの操作を行うためにはジェスチャー機能を有効にしたうえで、操作対象になるオブジェクトに対して属性を付与します。ジェスチャー機能については[xrextras-gesture-detector]属性を<a-scene>タグに追加します。

オブジェクトに設定できる操作は以下の通りです。


| 項目 | 概要 |パラメータ
|:-:|:-|:-|
|  xrextras-gesture-detector | a-sceneタグに追加しジェスチャー機能を有効化する属性 | - |
|  xrextras-tap-recenter| タップ操作でセンター位置を補正する（VRデバイスのリセンター） | - |
|  xrextras-one-finger-rotate | 指１本（片手）操作でオブジェクトを回転する操作を有効化する属性 |<UL><LI>Factor(デフォルト値:6)<BR>ドラッグ操作時の感度。大きくするほど少しの操作で多くの回転</LI></UL>|
|  xrextras-two-finger-rotate | 指２本（両手）操作でオブジェクトを回転する操作を有効化する属性  |<UL><LI>Factor(デフォルト値:6)<BR>ドラッグ操作時の感度。大きくするほど少しの操作で多くの回転</LI></UL>||
|  xrextras-pinch-scale | ピンチ操作（指２本間を広げたり縮めたりする）によるサイズ変更を有効化する操作  |<UL><LI>min(デフォルト値:0.33)<BR>ピンチ操作による最小サイズ</LI><LI>max(デフォルト値:3)<BR>ピンチ操作による最大サイズ</LI><LI>scale(デフォルト値:0)<BR>初期サイズ。0に設定するとオブジェクトの設定を初期スケールにする</LI></UL>|
|  xrextras-hold-drag | ホールド＆ドラッグ操作でオブジェクトの移動を有効化する属性。この移動操作は指定された床などの基準面に”乗っている”オブジェクトを移動するというUXに基づいて作られています。ホールド状態を維持すると基準面から少し浮くようなアニメーションが入り、その後移動させることができます。ホールドを解除すると浮いていたオブジェクトが着地します。  |<UL><LI>cameraId(デフォルト値:camera)<BR><a-camera>タグのID</LI><LI>groundId(デフォルト値:ground)<BR>地面として利用する<a-entity>タグのID</LI><LI>dragDelay(デフォルト値:300)<BR>対象物の移動が開始されるまでのタップホールド時間</LI><LI>riseHeight(デフォルト値:1)<BR>ホールド中のオブジェクトの高さ</LI></UL>|
|  xrextras-play-video | タップによりビデオ再生する操作を有効化する属性 |<UL><LI>video(デフォルト値:"")<BR>&lt;video>属性のID</LI><LI>thumb(デフォルト値:"")<BR>&lt;img>属性のID</LI><LI>canstop(デフォルト値:null)<BR>タップ操作で一時停止するか</LI></UL>|

テンプレートにはすでにxrextras-one-finger-rotateが入っています。

```html
<a-box 
  xrextras-one-finger-rotate
  position="0 0.5 0" 
  material="
    color: #AD50FF; shader: flat; 
    src: https://cdn.8thwall.com/web/assets/cube-texture.png"
  shadow>
</a-box>
```

HoloLesを含めたXRデバイスでよく使うオブジェクト操作に合わせて「両手で回転」、「ピンチ操作でサイズ変更」、「タップ＆ホールドで移動」という機能を入れる場合は以下のようにオブジェクトを変更します。
最初にa-cameraとa-planeの設定を見直します。xrextras-hold-dragを使いたいのですがこの属性にカメラと基準面になる床の情報を与える必要があるためです。変更点としてはIDをそれぞれcameraとgroundで定義します。これでデフォルト値としてxrextras-hold-dragに認識されます。

```html
<a-camera 
  id="camera"
  position="0 2 0"
></a-camera>

<a-plane 
  id="ground"
  height="2000" 
  width="2000" 
  rotation="-90 0 0" 
  material="shader: shadow; opacity: 0.67" 
shadow>
</a-plane>
```

a-cameraタグについてはさらに追加の修正を行います。HoloLensなどのXRデバイスのカメラ位置の調整です。Unityなどで開発する場合もデバイスのカメラの位置は原点(0,0,0)にしていましたが8thwallも同じように対応しないとコンテンツ（特にハンドレイ）がずれて描画されます。このため原点位置を調整します。注意点は地面のy座標を0にすること、オブジェクトをタップで操作するためにはタップ可能なオブジェクトをraycasterで設定する必要があります。今回はタグのクラス属性にcantapが指定されている場合は操作可能となるように定義します。
デバッグ中にPCを利用する場合、「cursor="fuse: false; rayOrigin: mouse;"」の設定を追加しておくとマウス操作でRayを処理できるようになるのでデバッグには便利です。

```html
<a-camera 
  id="camera"
  position="0 2 0"
  raycaster="objects: .cantap"
  cursor="fuse: false; rayOrigin: mouse;"
></a-camera>
```
次にオブジェクトの設定を行います。オブジェクトには先ほどの操作ができる属性を付与します。合わせて位置の調整も行いました。8thwallは右手系なので注意してください（Unityは左手系）。また、Rayによる操作を受け付けるためにクラス属性にcantapを設定します。

```html
<!-- -->
<a-box
  class="cantap"
  xrextras-two-finger-rotate
  xrextras-pinch-scale
  xrextras-hold-drag
  position="0 0 -7" 
  material="
    color: #AD50FF; shader: flat; 
    src: https://cdn.8thwall.com/web/assets/cube-texture.png"
  shadow>
</a-box>
```

これで、オブジェクト操作が可能なアプリの完成です。

### 4. デバッグと実行

デバッグについてはいくつか手段があるのですが、今回は実機でのデバッグ方法について紹介します。8thwallでは実機で動作させながらデバッグするリモートデバッグの機能がありますのでこれを使います。
使い方は簡単で、8thwallの上部メニューから[preview]を選択するとデバッグ用のURLが記されたQRコードが表示されます。スマホなどのモバイル端末についてこれを読み込むことでデバッグが可能です。ヘッドセットでのデバッグは、左下のヘッドセットのアイコンをクリックし、link Sharingを有効にします。この状態でにHoloLensを**開発端末と同一ネットワークに接続し**ブラウザからアクセスすると[8th.io/link]対象の8thwallのアプリが選択できるのでクリックして起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/440a662e-c074-d9c7-cd45-ea3f9737ee0e.png)

問題がなくアプリを公開したい場合は、変更した内容を全てpushした後、公開の手続きを行います。

## 注意点や所感

使ってみた所感なども記載しておきます。

### ちょっとしたコンテンツを作るのには便利

プロトタイピングとしてさっと作って確認するという使い方ができるのはかなり便利なのではと思いました。最近はjavascriptでもライブラリが提供されている場合も多いため様々なコンテンツも開発できそうです。ただ、ネイティブ実装ができるUnityなどに比べるとできることには制約があるので、使い分けは必要になると思います。ですが、ある程度のコンテンツをデプロイなしに体験してもらうことができる環境としてはとても有用な気がします（もちろんそれがHoloLensのようなデバイスで必要になるのかというのはありますが。。。）。

### そもそも、正式ではないかもしれない
おそらくですが、偶然動いているような気がします。そう思う理由として、以下になります（もし情報を見かけたことがあるかたは是非コメントなどで教えてほしいです）。

* 公式に対応しているという話を見つけられなかった
* ハンドレイや、タップ操作などは行えているのですが、VRのコントローラが表示されている
 
上記を鑑みても、デバイスに合わせた細やかな操作というのは現時点ではできていない可能性があります。ただ、先日Meta社が8thwallと提携したニュースもあったりと、ヘッドセットでも8thwallが使える環境は整いつつあると思うのでこれからどうなるかは楽しみです。

### 座標系やスケールの話

これについてはWebXRという切り口でも様々なところで言及されていると思いますが、Unityのように1単位=1mというわけではないというところ。Unityの感覚でコンテンツのスケールを構成すると思っているよりも大きな数値を使わないとイメージ通りにはならないかもしれないです。