8th Wall で顔出しパネルを作成する 

# この記事を読んでできること
Niantic社の提供する 8th Wallを使って、バーチャル顔出しパネルを作成します。

# 前提
## 必要なスキル
+ 8th Wallの基本操作を理解している(コード編集、素材アップロード、ビルド、公開)
+ 画像加工の基礎スキルがある(透過PNGファイルを用意できる)

## 事前準備
+ 8th Wallのアカウントを作成済であること
+ 顔だしパネル用の画像を用意する

## 動作要件
スマホのカメラで撮影する前提です。8th Wallのシステム要件は次の通りです。
+ iOS：
    + Safari (iOS 11+)
+ Android：
    + Chrome
    + Firefox
    + Samsung Internet
    + Microsoft Edge

詳細は下記ページを参照してください。（私は普段使いのブラウザがBraveで、うまく動作しなかったためしばらくハマっていました…）

https://www.8thwall.com/docs/ja/getting-started/requirements/

# 顔出し用の画像作成
なにはなくとも、まずは顔出し用の画像を用意します。画像の形式は顔はめ部分を透過しますので、pngに変換してください。
こちらのサンプルはWindowsのペイントで作成したのですが、Qiitaに投稿すると穴がわかりにくかったのでグレーで塗りつぶしてます(透過になってないです)。

<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/d4463bc7-2385-b807-fd6c-1b3500c6a03d.png">


# プログラムの作成
## プロジェクトのクローン
今回作成するプログラムの元となる下記サンプルプロジェクトから、クローンします。

クローン元プロジェクト：

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

こちらはお城の3Dモデルをカメラの前に表示させ、ドラッグ、ピンチアウトなどでモデルを操作できるデモです。モデルの操作処理を流用します。
こちらのサンプルにカメラ撮影機能を追加するのですが、出来合いのモジュールが用意されているので数行の追加で完成します。カメラ機能は下記サンプルが参考になります。

カメラ機能の参考プロジェクト：

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


## 編集作業
クローンが完成し、プロジェクトが立ち上がった後、必要な作業は下記２点です。
1. 画像のアップロード
2. body.htmlの編集


### 画像のアップロード
画面左のファイル一覧のAssets に顔出しパネルの画像をアップロードしてください。今回は`panel.png`というファイル名で作成しています。


![menu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/8aacd9c7-662c-46e1-0bff-4a9a5921192e.png)

### body.htmlの編集
とりあえず、下記を貼れば動くかと思います。

~~~body.html
<a-scene
  xrextras-gesture-detector
  landing-page
  xrextras-loading
  xrextras-runtime-error
  renderer="colorManagement: true"
  xrweb="allowedDevices: any">
  
  <!-- 起動時に読込むアセットの定義 -->
  <a-assets>
    <img id="panel" src="assets/panel.png" />
  </a-assets>

  <!-- カメラ設定 -->
  <a-camera
    id="camera"
    position="0 3 5"
    raycaster="objects: .cantap"
    cursor="fuse: false; rayOrigin: mouse;">
  </a-camera>

  <!-- イメージの読み込み -->
  <a-image
    id="model"
    src="#panel"
    class="cantap"
    xrextras-hold-drag
    xrextras-two-finger-rotate
    xrextras-pinch-scale="max: 30"
    scale="2 2 1"
    position="0 3 1"
    shadow="receive: false">
  </a-image>

  <!-- 床面 -->
  <a-plane
    id="ground"
    rotation="-90 0 0"
    width="1000"
    height="1000"
    material="shader: shadow"
    shadow>
  </a-plane>

  <!-- ▼▼▼ 以下、カメラ機能の追加 ▼▼▼ -->
  <!-- キャプチャーボタン -->
  <xrextras-capture-button capture-mode="photo"></xrextras-capture-button>

  <!-- キャプチャー画像の設定 -->
  <xrextras-capture-config
    file-name-prefix="kaohame-image-"
    request-mic="manual"></xrextras-capture-config>

  <!-- キャプチャーのプレビュー -->
  <xrextras-capture-preview></xrextras-capture-preview>
</a-scene>
~~~

### ソースの解説
まず、8th wall自体についての説明です。
8th wallでは通常のA-Frameに加え、主にカメラ周りの操作が拡張されています。ヘッダファイル 2行目に定義されているのが、拡張パッケージの`xrextras`です。
~~~head.html
<meta name="8thwall:renderer" content="aframe:1.3.0">
<meta name="8thwall:package" content="@8thwall.xrextras">
<meta name="8thwall:package" content="@8thwall.landing-page">
~~~
こいつが曲者で、8th wallの公式ドキュメントを探しても、まともな説明がなされていません。サンプルなどを見て回るうちに、githubのREADMEにパラメタ解説がありました。
ソースの各所に`xrextras-`のついた要素、属性が出てきますが、詳しくは下記を参照してください。

https://github.com/8thwall/web/blob/master/xrextras/src/aframe/README.md

続いてbodyソースの各部を見ていきます。まずは最初の`<a-scene>`からです。
~~~html
<a-scene
  xrextras-gesture-detector
  landing-page
  xrextras-loading
  xrextras-runtime-error
  renderer="colorManagement: true"
  xrweb="allowedDevices: any">
~~~
`<a-scene>`要素はA-frameのソース全体を囲うタグです。
だいたい8th wallのサンプルの書き出しは上記のような感じですが、今回のサンプルでは`xrextras-gesture-detector`属性がつけられています。これは画面タッチでの操作を行うための拡張のようです。

次に`<a-assets>`要素です。
~~~html
  <!-- 起動時に読込むアセットの定義 -->
  <a-assets>
    <img id="panel" src="assets/panel.png" />
  </a-assets>
~~~
A-Frameでは画像、動画、3Dモデルなどを事前に定義して先読みしておくのがベターのようです。

続いて、カメラ、パネル、床面の設定です。
~~~html
  <!-- カメラ設定 -->
  <a-camera
    id="camera"
    position="0 3 5"
    raycaster="objects: .cantap"
    cursor="fuse: false; rayOrigin: mouse;">
  </a-camera>

  <!-- イメージの読み込み -->
  <a-image
    id="model"
    src="#panel"
    class="cantap"
    xrextras-hold-drag
    xrextras-two-finger-rotate
    xrextras-pinch-scale="max: 30"
    scale="2 2 1"
    position="0 3 1"
    shadow="receive: false">
  </a-image>

  <!-- 床面 -->
  <a-plane
    id="ground"
    rotation="-90 0 0"
    width="1000"
    height="1000"
    material="shader: shadow"
    shadow>
  </a-plane>
~~~
以下、主要な設定について記載します。
#### `<a-camera>` 要素
+ `position`属性
カメラの視点を設定します。"0 3 5"はX,Y,Z軸です。サンプルでは上下位置のY軸に3、前後の調整Z軸に5を設定しています。

#### `<a-image>`要素
本プログラムでメインとなるのが`<a-image>`要素です。
+ src 属性
`<a-assets>`で指定した`id=panel`はこちらの`src="#panel"`と紐づきます。
+ xrextras-hold-drag 属性
ドラッグでパネルを移動できるようにします。
+ xrextras-two-finger-rotate 属性
二本指で回転できるようにします。
+ xrextras-pinch-scale 属性
ピンチアウトで拡大、縮小できるようにします。`max: 30`はどこまで大きくできるかの上限値です。
+ scale
画像の横、縦、奥行きのサイズ(比率)です。今回のサンプルはだいたい正方形だったので、横2、縦2 としています。
+ position
画像の表示位置です。

#### `<a-plane>`要素
床面がどちらを向いているかを定義します。画面上は描画されませんが、`a-image`の xrextras-hold-drag 属性はcamera、ground に連携する仕様となっています。物体をドラッグして移動したあとに、床面に設置してとどまるようになっています。

最後に撮影機能についてです。
~~~html
  <!-- ▼▼▼ 以下、カメラ機能の追加 ▼▼▼ -->
  <!-- キャプチャーボタン -->
  <xrextras-capture-button capture-mode="photo"></xrextras-capture-button>

  <!-- キャプチャー画像の設定 -->
  <xrextras-capture-config
    file-name-prefix="kaohame-image-"
    request-mic="manual"></xrextras-capture-config>

  <!-- キャプチャーのプレビュー -->
  <xrextras-capture-preview></xrextras-capture-preview>
~~~
こちらは画面に、撮影ボタン、撮影した画像に対しての設定、撮影画像のプレビューを指定しています。
画面にカメラのボタンが表示されて、タップするとブラウザ内のキャプチャが作成されます。プレビュー枠の下にダウンロードボタンが表示されるので、そちらをクリックすると`kaohame-image-`から始まるファイル名で端末内に写真が保存されるようになります。

## 動作確認
そんな感じで作成したアプリがこちらになります。

https://twitter.com/MinakuchiyaEnl/status/1721376261526950109?t=t69U1visQS9NDk7tX4aYnA&s=19

## 終わりに
今回のサンプルではA-FRAMEのタグ(拡張含みますが)だけで、コーディング完了です。カメラ周りは出来合いの機能が作りこまれてるので、あっさり実装できます。

ただ、某顔出しパネルマニアに見てもらったところ「自撮りしたい！」との要望があったため、最終的にフロントカメラへの切り替えも追加することにしました。そのあたりはJavaScriptやCSSをもう少しいじる必要がありますので、別で説明しようと思います。