[8th wall]オリジナルの3DモデルをARで表示してみる

# この記事を読んでできること
+ AIを利用してオリジナルの3Dモデルを作成します
+ 8th wallを利用して3Dモデルを表示させるアプリを作成します
+ Blender等、3Dモデルのデザインツールは使わずにとりあえず仕上げます
# 〇前提
## 必要なスキル
+ 多少の英語力(翻訳ツールが使えれば十分)
+ 8th Wallの基本操作を理解している(コード編集、素材アップロード、ビルド、公開)
## 事前準備
+ 8th Wallのアカウントを作成済であること
# 〇作成手順
## AI画像生成サイトで3Dモデルの元になる絵を作成する
お好みの画像生成AIがある、もしくは自分で描いちゃう方はこのステップはお任せします。
よくわかんない方は、Stable DiffusionがWeb上で試せるサイトを適当に探して元画像を作成します。
下記は適当に探したサイトです。

https://stablediffusionweb.com/

作成されたイメージは 全身、白背景が望ましいので、プロンプトに`full body`、`white background` あたりを入れるのが望ましいと思います。ということで `full body ,cute puppy photo , white background` と入力して生成すると、こんなワンちゃんができました。こちらの画像をダウンロードしておきます。
![aiimage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/a0aae125-1fb0-e865-9071-1c44d3a0a8a9.png)

## 2Dから3Dモデルを作成する
下記サイトはアップロードされた画像からAIで3Dモデルを生成するサイトです。表面の画像で裏面まで出来上がるってどういうこと？と思ったのですが、人間でも犬の顔を見れば体つきがどうなってるかイメージできますよね。まあ、そういうことでしょう（適当）。

https://www.csm.ai/

1. 上記サイトの右上「Get Start」ボタンを押下します。
2. アカウント未作成の場合「Resister」で登録、作成済の場合「Login」します。
3. Home画面で「Generate 3D Model」 を押下し、先ほど作成したワンちゃんの画像をアップロードします。
4. プレビュー画面に立体としての展開イメージが表示されます。3Dモデル生成に進む場合は右上の「Generate」ボタンを押下します。
![uploadimage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/c642b386-113d-10a3-a10a-0d3064e4305c.png)
5. 15～20分程度待つと、1次生成されたモデルが表示できるようになります。
出来上がったものが下記です。非常に残念な感じが漂ってますが、とりあえず先に進みます。
![3d1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/1b90b79a-989f-fb96-1c5f-f4836a7561b5.png)
![3d2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/bedcaed9-ca2e-9b9a-6590-a79039521fa6.png)
![3d3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/ab7322e7-0f76-1d60-a4a0-289c0e2a019b.png)
6. 先ほどは1次生成でしたので、「Refine mesh」を押下して精度のあがったモデルを生成します。数時間かかると思うので、とりあえずお茶でも飲んで待ちましょう。

でもって、出来上がったモデルがこちらです。
![inu1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/2fa9fbde-d297-56ee-88bf-6463f075c261.png)
![inu2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/b71b1582-3e16-29d9-8b06-95fe96354044.png)
犬だ。後ろもそれっぽいぞ。
ただ…
![inu3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/30d51581-f55a-ee24-b0db-89bce760fc5d.png)
うすっぺらいな（笑）
ということで、出来上がったモデルは右上のShareボタンから「GLB」を選択すると`mesh.glb`というファイルでダウンロード可能です。
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/371e2baf-50c4-929d-b717-98f0b975ead0.png)

## 8th Wallのプロジェクトを作成する
### プロジェクトの立ち上げ
8th Wallでの実装に進みます。クローン元のプロジェクトは「A-Frame: Manipulate 3D Model」を選択します。

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

プロジェクトが立ち上がると`sand-castle.glb`というファイル名で3Dモデルが登録済となっています。
![城.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/f203f3a5-f3c9-935e-fba7-8f17a9bf0db1.png)
### 3Dモデルのアップロード
こちらを先ほど作成した、オリジナルのモデルと差し替えます。アップロードしてプレビューで確認してみます（うむ、犬だ）。
![inu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/46321eb4-52d6-4f7b-6d25-12931ca0428c.png)
### ソースの修正
続いて`body.html`の3Dモデル読み込み箇所を修正します。モデルの読み込み箇所は次のようになっています。
~~~html
  <a-assets>
    <!-- Credit to Poly by Google for the model: https://poly.google.com/view/5ZMAz7_ucTn -->
    <a-asset-item id="sandCastleModel" src="assets/sand-castle.glb"></a-asset-item>
  </a-assets>
~~~
idは`puppy`、srcは`assets/sesh.glb`に修正します。

続いてモデルの表示部です。初期では次のようになってます。
~~~html
  <a-entity 
    id="model" 
    gltf-model="#sandCastleModel" 
    class="cantap" 
    xrextras-hold-drag 
    xrextras-two-finger-rotate 
    xrextras-pinch-scale 
    scale="3 3 3" 
    shadow="receive: false">
  </a-entity>
~~~
読み込んだモデルとの紐づけは`gltf-model="#sandCastleModel" `となっていますが、先ほどの変更に合わせて`gltf-model="#puppy" `とします。
ついでに、サイズをぐりぐりして遊びたいので`xrextras-pinch-scale`にパラメタを設定してみます。まずは`xrextras-pinch-scale="max:3"`としてみましょう。

あとは必要に応じて、ライトの加減を調整します。今回はあまりにも薄汚れた感じになっちゃったので、照明を明るくします。下記がモデルのライトアップ設定です。
~~~html
  <a-entity
    light="
      type: directional;
      intensity: 0.8;
      castShadow: true;
      shadowMapHeight:2048;
      shadowMapWidth:2048;
      shadowCameraTop: 10;
      target: #model;
      shadowRadius: 12"
    xrextras-attach="target: model; offset: 1 15 3;"
    shadow>
  </a-entity>
~~~
`intensity: 0.8;`を 2.8くらいに変更してみます。

というわけで、全体はこちら。
~~~body.html
<!-- Copyright (c) 2022 8th Wall, Inc. -->
<!-- body.html is optional; elements will be added to your html body after app.js is loaded. -->

<a-scene
  xrextras-gesture-detector
  landing-page
  xrextras-loading
  xrextras-runtime-error
  renderer="colorManagement: true"
  xrweb="allowedDevices: any">
  <!-- We can define assets here to be loaded when A-Frame initializes -->
  <a-assets>
    <!-- Credit to Poly by Google for the model: https://poly.google.com/view/5ZMAz7_ucTn -->
    <a-asset-item id="puppy" src="assets/mesh.glb"></a-asset-item>
  </a-assets>

  <!-- The raycaster will emit mouse events on scene objects specified with the cantap class -->
  <a-camera
    id="camera"
    position="0 8 8"
    raycaster="objects: .cantap"
    cursor="fuse: false; rayOrigin: mouse;">
  </a-camera>

  <a-entity
    light="
      type: directional;
      intensity: 2.8;
      castShadow: true;
      shadowMapHeight:2048;
      shadowMapWidth:2048;
      shadowCameraTop: 10;
      target: #model;
      shadowRadius: 12"
    xrextras-attach="target: model; offset: 1 15 3;"
    shadow>
  </a-entity>

  <a-light type="ambient" intensity="0.7"></a-light>

  <a-entity
    id="model"
    gltf-model="#puppy"
    class="cantap"
    xrextras-hold-drag
    xrextras-two-finger-rotate
    xrextras-pinch-scale="max:3"
    scale="3 3 3"
    shadow="receive: false">
  </a-entity>

  <a-plane
    id="ground"
    rotation="-90 0 0"
    width="1000"
    height="1000"
    material="shader: shadow"
    shadow>
  </a-plane>
</a-scene>
~~~
実行した結果がこちらです。

https://x.com/MinakuchiyaEnl/status/1721889654654529562?s=20

公開もしましたので、お試しは下記のリンクからどうぞ。

https://8th.io/cd6yz

今回はモデルのファイルサイズが3MBくらいでした。ファイルサイズが大きくなると、起動時の読み込みが遅くなると思います。モデリングツールで圧縮するとよいのかもしれませんが、ソフトのインストールが億劫で試してません。
また、圧縮のモジュールプロジェクトに読み込む手もあるようです。こちらはサンプルも公開されてたので暇があればやってみようと思います。