ARKitサンプルプログラムでワイングラスを表示する

iOS11から公開されたARKitでプリセットの3Dデータではなく任意の3Dデータを表示する方法を紹介します。
サンプルプログラムのビルド方法については[こちら](http://qiita.com/noby111/items/c992ad9cb9775f3ed364)で紹介しています。

### 3Dデータの準備
---
サンプルプログラムでの3DオブジェクトはSCNNodeを継承したVirtualObjectクラスのインスタンスとして扱われています。
そのため、任意の3DデータはSCNNodeで読み込める形式である必要があります。
scnやobjやdaeなどの色々な形式のファイルがありますが、shuさんの記事[SceneKitで扱える3Dモデルのフォーマット／アニメーションつき3DモデルをSceneKitで使う](http://qiita.com/shu223/items/0161f82d000d5cdf009c)によると、COLLADAファイル(拡張子は.dae)が一番良いようです。
Blenderなどを使っても作れるようですが、ここではその方法は割愛します。
私はワイングラスの3Dデータであるglass.daeというファイルを用意しましたのでこれをサンプルプログラムで表示したいと思います。

### 3Dデータのプロジェクトへの追加
---
サンプルプログラムのブロジェクト構造を見ると、Models.scnassetsというディレクトリ配下に3Dデータが配置されていることが分かります。従って、ここにglass.daeを配置することします。
　![sample_files_scheme.png](https://qiita-image-store.s3.amazonaws.com/0/200963/6376c3d8-04d9-0c70-958e-7bcdd7b837cb.png)

- glassという名前を付けたディレクトリを作成し、そこにglass.daeを配置する
- Models.scnassetsを選択した状態で Xcodeのメニュー ＞ File ＞ Add Files to "Models.scnassets"... を選択する
![xcode_file_add_menu.png](https://qiita-image-store.s3.amazonaws.com/0/200963/1e140134-f59d-2066-ebbb-46fa637b7a31.png)
- ファイル選択ダイアログが開くので先ほどのglassディレクトリを選択する
- candleやchairと並んでglassディレクトリが追加されていればOKです
- 最後にdaeファイルをscnファイルへ変換しておきます、VirtualObjectManagerは拡張子がscnのファイルをロードするので他のchairなどと合わせておきます
- glass.daeを選択した状態で Xcodeのメニュー ＞ Editor ＞ Convert to SceneKit scene file format (.scn)を選択します
　![scn_convert.png](https://qiita-image-store.s3.amazonaws.com/0/200963/0fac2673-143f-7005-0630-476b309bfee8.png)
- daeファイル内のオブジェクトの表示角度を調整する（daeファイルはscn形式と基本座標が異なるらしくX軸の角度を-90に設定しておく必要がある）
![edit_euler.png](https://qiita-image-store.s3.amazonaws.com/0/200963/9c7990d8-b9a7-4030-7912-eca1f665ddce.png)
※上記のスクリーンショットのように元データの3Dオブジェクトのサイズが大きい場合はScaleを1より小さくする調整が必要になります


### 3Dデータのロード
---
candleやchair等のどのような3DデータがあるかはVirtualObjects.jsonの中にあります。
![virtual_object_json.png](https://qiita-image-store.s3.amazonaws.com/0/200963/d3469492-545a-1466-323a-091bab1395c8.png)
他に倣ってchair要素の後に先ほど追加したglassの定義を追加します。

```diff
[
    {
        "modelName": "candle",
        "displayName": "Candle",
        "particleScaleInfo": {"flame": 0.018 }
    },
    {
        "modelName": "cup",
        "displayName": "Cup",
        "particleScaleInfo": { }
    },
    {
        "modelName": "vase",
        "displayName": "Vase",
        "particleScaleInfo": { }
    },
    {
        "modelName": "lamp",
        "displayName": "Lamp",
        "particleScaleInfo": { }
    },
    {
        "modelName": "chair",
        "displayName": "Chair",
        "particleScaleInfo": { }
    },
+   {
+       "modelName": "glass",
+       "displayName": "Glass",
+       "particleScaleInfo": { }
+   },
]
```

これでひとまずデータの追加は完了です。

### アイコンデータの準備
---
サンプルプログラムをビルドすると分かりますが、実際にオブジェクトを表示させようとした時にどのオブジェクトにするかをユーザが選ぶ必要があります。この時にオブジェクト名の横に小さなアイコンが表示されており、3Dデータの他にアイコンを用意する必要があります。
　![icon_list.png](https://qiita-image-store.s3.amazonaws.com/0/200963/a590e9fb-59d7-2960-1792-324dff93b153.png)
アイコンは60x60と90x90の二種類が必要になります。用意するのが面倒であればサンプルプロジェクト内のchair@2x.pngとchair@3x.pngをコピーしてglass@2x.pngとglass@3x.pngにリネームしてしまっても良いと思います。
私の場合は[このサイト](https://www.silhouette-ac.com)から手頃なものをダウンロードさせてもらいました。

### アイコンデータの追加
---

- Xcodeの左側にあるプロジェクト構成ペインでAssets.xcassetsを選択し、＋ボタンを押し New Image Setを選択する

　![add_imageset.png](https://qiita-image-store.s3.amazonaws.com/0/200963/732f6b78-ebeb-71e1-b11d-ead23d3f5faa.png)

- Imageをglassへリネームする

　![rename.png](https://qiita-image-store.s3.amazonaws.com/0/200963/15590e85-3457-c547-0a64-b348ecfdca6e.png)

- glassイメージセットの2xと3xにそれぞれglass@2x.pngとglass@3x.pngをドロップする

　![imageset.png](https://qiita-image-store.s3.amazonaws.com/0/200963/0a2a4041-be53-0d92-d5d3-cb233df24659.png)

- このような状態になっていればOK

　 ![imageset2.png](https://qiita-image-store.s3.amazonaws.com/0/200963/87fd3943-794d-085f-2c23-0f795d0f03e6.png)


### ビルド
---
最後はこの状態でビルドを実行すればOKです。
ここまで問題がなければこのように自分で追加した3Dデータをサンプルプログラムで表示することができます。
![IMG_0003.PNG](https://qiita-image-store.s3.amazonaws.com/0/200963/7717bcb6-735a-d721-baf3-995d4c138f48.png)
![IMG_0004.PNG](https://qiita-image-store.s3.amazonaws.com/0/200963/6e1a75c0-9f2b-be4e-0019-e4f680ffbad1.png)
光の当て方を調整していないので周りと全然マッチしていない・・・。