SceneKitでプリミティブなジオメトリから3Dモデルを作ろう

先日作成したARKitのサンプルコード集[ARKit-Emperor](https://github.com/kboy-silvergym/ARKit-Emperor)の中に、額縁の中に画像を入れて平面に置くというサンプルコードがあります。

![picture.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/6c4920b1-008c-2395-d51d-46a2f7de402f.gif)

この額縁はXcode上で、SceneKitで作成しました。

この額縁の作り方を紹介していきたいと思います。

# 完成品

<img width="746" alt="スクリーンショット 2018-12-01 20.59.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/a1d3be7d-c481-186a-9e35-d3ac954cfc49.png">
https://github.com/kboy-silvergym/ARKit-Emperor/blob/master/ARKit-Emperor/art.scnassets/pictureTable.scn

## 構造

<img width="733" alt="スクリーンショット 2018-12-01 21.01.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/1f6ff97e-7ab7-88c4-37f2-ca4f2a23f6e9.png">

- sideBoxという名前の四角柱が4本
- legという名前の脚が1本
- (おまけにspotという名前のスポットライト)

順をおって作り方を解説していきます。

# 作り方

## sideBoxを作ろう

art.scnassetsフォルダのところで新規ファイルを作ると`SceneKit Scene.scn`という名前でscnファイルが作られます。

<img width="412" alt="スクリーンショット 2018-12-01 21.07.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/4a0044c2-8c81-f85c-977d-46821a3dc939.png">

<img width="312" alt="スクリーンショット 2018-12-01 21.08.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/04a1d60b-b383-4eed-ab6a-6d8c8cfc7dda.png">

今回はこれを`pictureTable2`という名前にして進めていきます。

### まずはBoxをおく

Xcode10では、右上の□ボタンみたいなところを押すと、以下のようにnodeやlight、プリミティブ（基本的）なジオメトリが選択できます。

<img width="1280" alt="スクリーンショット 2018-12-01 21.10.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/11d59109-0f8b-ae5e-a55f-be88a3b28cda.png">

今回は、`Box`を選択します。これをドラッグアンドドロップで、sceneに持って行ってください。

<img width="1280" alt="スクリーンショット 2018-12-01 21.13.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/31d52f98-648e-2083-ccb9-9c2da4dbea0a.png">

ドラッグアンドドロップすると以下のように表示されます。マウスでドラッグすることで角度を変えることができて、右クリック（macのトラックパッド２本指）で平行移動できます。

<img width="1280" alt="スクリーンショット 2018-12-01 21.14.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/bf1d9cf2-6275-b41d-2101-a836c3acf6ce.png">

## Boxの大きさを調整していく

このBoxを選択した状態で、右側のattribute inspectorを選択すると、Sizeという項目が現れます。ここを変更して、細長い円柱を作っていきましょう。

<img width="1019" alt="スクリーンショット 2018-12-01 21.16.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/b7507839-0907-3b06-6be0-b0e7dd908ad1.png">

僕のサンプルでは、

- width 0.03
- height 0.53
- length 0.03

にしているので、同じように調整してみましょう。ちなみに単位はm(メートル)なので、0.03は3cm、0.53は53cmです。

<img width="1008" alt="スクリーンショット 2018-12-01 21.22.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/ffa567dc-544c-957c-e67f-6fb54bb61e3a.png">

### 色をつけよう

boxを選択したまま、今度はmaterialのタブを選択します。

shadingは質感を示していて、diffuseの部分で色を選択できます。また、diffuseには画像もしているすることができます。

([AppEngine](http://appleengine.hatenablog.com/entry/2017/07/12/153350)というブログがとても詳しいので気になる方は読んでみてください。)

<img width="1011" alt="スクリーンショット 2018-12-01 21.24.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/0f6d5420-b79e-c22d-f654-225db896a6c1.png">

### 4本に増やそう

Scene graghでコピーアンドペーストすると、増やすことができます。

<img width="323" alt="スクリーンショット 2018-12-01 21.28.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/8868849e-8c5a-67f4-1d1a-5bd51f0c4382.png">

### 移動、回転させてみよう

ただ、この状態はまだ全て同じポジションにあって重なっていますので、一本ずつずらしてみましょう。

<img width="720" alt="スクリーンショット 2018-12-01 21.29.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/83133e59-f6b4-9418-6542-a1cdbe7f3d09.png">

x、y, z軸を選択しながらドラッグすると平行移動できます。

![Dec-01-2018 21-31-06.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/b372f1b1-0304-64c3-9615-141ab788fafc.gif)

ちなみに角度の部分を選択しながらドラッグすると回転もできます。

![Dec-01-2018 21-34-11.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/412c618f-fe73-f0c1-6968-3ac94b2d1d37.gif)

### 4本のboxをグループ化

まず、emptyNodeをscene graphに追加します。

<img width="694" alt="スクリーンショット 2018-12-01 21.43.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/ec619b25-ca6e-ee2c-d82d-22dd1027595e.png">

適当な名前をつけます。

<img width="391" alt="スクリーンショット 2018-12-01 21.44.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/5fdc55c6-f1c2-9cfc-c131-e811d166fa47.png">

4本のboxをドラックアンドドロップでframeの配下に入れます。

<img width="322" alt="スクリーンショット 2018-12-01 21.44.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/83735881-de31-4a79-e084-f35a6e6c9f71.png">

### 4本のboxの座標や角度を調整する

これでboxたちはframeというnodeの配下に入ったので、frameのローカル座標系で座標を変更していくことになります。

今度は立方体マークのタブクリックして、transformのposition（座標）やeuler(角度)をいい感じに調整していきましょう。

<img width="969" alt="スクリーンショット 2018-12-01 21.47.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/1092ad73-2103-609a-e230-da5696dab3f3.png">

そしたらこんな感じ。

<img width="1010" alt="スクリーンショット 2018-12-01 21.51.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/fa7947f4-97e8-25e9-c939-42f6385ab085.png">

脚は今回説明を省きます。これで**完成！！**

# 作ったモデルをコードで呼び出す

```swift
    lazy var pictureTableNode: SCNNode = {
        let scene = SCNScene(named: "art.scnassets/pictureTable.scn")!
        let node = scene.rootNode.childNode(withName: "tableNode", recursively: false)!
        node.name = "tablePictureNode"
        
        // 写真のnode
        let picture = SCNBox(width: 0.5, height: 0.5, length: 0.01, chamferRadius: 0)
        picture.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "kboy_profile")
        let pictureNode = SCNNode(geometry: picture)
        
        // frameに貼る
        let frameNode = node.childNode(withName: "frame", recursively: true)
        frameNode?.addChildNode(pictureNode)
        
        node.scale = SCNVector3(x: 0.3, y: 0.3, z: 0.3)
        return node
    }()
```

こんな感じで呼び出して、positionに気をつけて画像を貼ると、

![picture.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/6c4920b1-008c-2395-d51d-46a2f7de402f.gif)

このようなアウトプットになります。

[ARKit-Empelor](https://github.com/kboy-silvergym/ARKit-Emperor)のPictureViewControllerで再現しているので、コードはそちらを確認してみてください！

https://github.com/kboy-silvergym/ARKit-Emperor/blob/master/ARKit-Emperor/View/Picture/PictureViewController.swift