iOS の SceneKit で 3D 空間に Hello World

## 概要
- iOS の SceneKit を使って3D空間に Hello World テキストを表示するアプリを作る
- Storyboard の状態を修正せず、ソースコードだけで実現する

## 今回の環境
- Xcode 10.3
- iPhone X + iOS 12.4.1

## プロジェクトの作成

テンプレートから iOS + Single View App を選択する。

<img width="723" alt="scenekit-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/26a6d982-5d28-9f47-147c-7cba220e5bf9.png">

Language に Swift を指定する。

<img width="729" alt="scenekit-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/f67572ca-5b22-25f9-744a-db21586a34f6.png">

AppDelegate.swift と ViewController.swift という Swift のソースコードが用意される。

<img width="938" alt="scenekit-3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/c1fc7b47-f4b2-4368-f2b6-87b0c873d570.png">

## ソースコード

ViewController.swift を以下のものに置き換える。

```swift
import UIKit
import SceneKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // SCNView を構築して UIViewController のビューに設定する
        let scnView = SCNView(frame: self.view.frame)
        scnView.backgroundColor = UIColor.black // 背景を黒色に
        scnView.allowsCameraControl = true // ユーザーによる視点操作を可能に
        scnView.showsStatistics = true // 描画パフォーマンス情報を表示
        self.view = scnView

        // SCNScene を SCNView に設定する
        let scene = SCNScene()
        scnView.scene = scene

        // カメラをシーンに追加する
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
        scene.rootNode.addChildNode(cameraNode)

        // 無指向性の光源をシーンに追加する
        let omniLight = SCNLight()
        omniLight.type = .omni
        let omniLightNode = SCNNode()
        omniLightNode.light = omniLight
        omniLightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(omniLightNode)

        // あらゆる方向から照らす光源をシーンに追加する
        let ambientLight = SCNLight()
        ambientLight.type = .ambient
        ambientLight.color = UIColor.darkGray
        let ambientLightNode = SCNNode()
        ambientLightNode.light = ambientLight
        scene.rootNode.addChildNode(ambientLightNode)

        // 表示するテキストを用意する
        let str = "Hello, world!\nこんにちは、世界。"
        let text = SCNText(string: str, extrusionDepth: 1.0)
        text.font = UIFont.systemFont(ofSize: 1.0)

        // テキストの色を設定する
        // SCNText には最大5つの要素があり、それぞれに SCNMaterial を指定できる
        let m1 = SCNMaterial()
        m1.diffuse.contents = UIColor.red // 前面に赤色
        // back material
        let m2 = SCNMaterial()
        m2.diffuse.contents = UIColor.green // 背面に緑色
        // extruded sides material
        let m3 = SCNMaterial()
        m3.diffuse.contents = UIColor.blue // 側面に青色
        text.materials = [m1, m2, m3]

        // テキストノードを用意する
        let textNode = SCNNode(geometry: text)

        // テキストノードの中心を座標の基準にする
        let (min, max) = (textNode.boundingBox)
        let textBoundsWidth = (max.x - min.x)
        let textBoundsheight = (max.y - min.y)
        textNode.pivot = SCNMatrix4MakeTranslation(textBoundsWidth/2 + min.x, textBoundsheight/2 + min.y, 0)

        // テキストを配置する場所を決める
        textNode.position = SCNVector3(x: 0, y: 0, z: -1)

        // テキストノードをシーンに追加する
        scene.rootNode.addChildNode(textNode)

        // 球体をシーンに追加する
        let sphere:SCNGeometry = SCNSphere(radius: 1.5)
        let sphereNode = SCNNode(geometry: sphere)
        sphereNode.position = SCNVector3(x: 0, y: -3, z: 0)
        scene.rootNode.addChildNode(sphereNode)
    }
}
```

## 実機での実行結果

実機 (iPhone X + iOS 12.4.1) にインストールして実行してみる。

Hello World テキストと球体が画面の中の3D空間に表示されている。

<img width="375" alt="scenekit-4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/f9d40a7f-38ac-41b8-5c10-91d49900dc51.png">

画面をドラッグ操作等することで視点を移動することができる。

<img width="375" alt="scenekit-5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/8fc361b6-f886-d7b8-89f7-986f7b6935a3.png">

## 参考資料
- [SceneKit \| Apple Developer Documentation](https://developer.apple.com/documentation/scenekit)
- [UIViewController \- UIKit \| Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller)
- [iOS で SceneKit を試す\(Swift 3\) その4 \- SceneKit の構造 \- Apple Engine](http://appleengine.hatenablog.com/entry/2017/05/30/192435)