ARKit Hello World (宙に浮く Hello World テキスト in 拡張現実)

## 概要
- iOS の ARKit を使って拡張現実で Hello World テキストが宙に浮くアプリを作る
- Storyboard の状態を修正せず、ソースコードだけで実現する
 
## 今回の環境

- Xcode 10.3
- ARKit 2
- iPhone X + iOS 12.4.1

## プロジェクトの作成

Xcode にてテンプレートから iOS + Argumented Reality App を選択する。

<img width="727" alt="hello-world-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/67dd90a2-a955-2b46-12c3-80896bc879f6.png">

Language に Swift を、Content Technology に SceneKit を指定する。

<img width="728" alt="hello-world-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/b85cba66-9f2c-718b-0145-93b256e3cfe6.png">

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

<img width="960" alt="hello-world-3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/767716f8-d9b5-c50f-e2df-055367d25aac.png">

## ソースコード

ViewController.swift を修正する。

viewDidLoad メソッドを以下のように書き換える。
SCNText によるテキストをAR空間に表示する。

```swift
override func viewDidLoad() {
    super.viewDidLoad()

    // Set the view's delegate
    sceneView.delegate = self

    // Show statistics such as fps and timing information
    sceneView.showsStatistics = true

    // シーンを生成
    let scene = SCNScene()

    // Set the scene to the view
    sceneView.scene = scene

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

    // テキストの色と質感を用意
    // SCNText には最大5つの要素があり、それぞれに SCNMaterial を指定できる
    // front, back, extruded sides, front chamfer, back chamfer
    // front material
    let m1 = SCNMaterial()
    m1.diffuse.contents = UIColor.red // 前面に赤色
    // 鏡面反射感を出す
    m1.lightingModel = .physicallyBased
    m1.metalness.contents = 1.0
    m1.metalness.intensity = 1.0
    m1.roughness.intensity = 0.0
    // back material
    let m2 = SCNMaterial()
    m2.diffuse.contents = UIColor.green // 背面に緑色
    m2.lightingModel = .physicallyBased
    m2.metalness.contents = 1.0
    m2.metalness.intensity = 1.0
    m2.roughness.intensity = 0.0
    // extruded sides material
    let m3 = SCNMaterial()
    m3.diffuse.contents = UIColor.blue // 側面に青色
    m3.lightingModel = .physicallyBased
    m3.metalness.contents = 1.0
    m3.metalness.intensity = 1.0
    m3.roughness.intensity = 0.0
    // front chamfer material
    let m4 = SCNMaterial()
    m4.diffuse.contents = UIColor.yellow
    // back chamfer material
    let m5 = SCNMaterial()
    m5.diffuse.contents = UIColor.yellow

    // テキストの色と質感をセット
    text.materials = [m1, m2, m3, m4, m5]

    // AR空間の要素としてテキストをセット
    let textNode = SCNNode(geometry: text)

    // テキストを配置する場所を決める
    let (min, max) = (textNode.boundingBox)
    let textBoundsWidth = (max.x - min.x)
    let textBoundsheight = (max.y - min.y)
    let z = CGFloat(-1.0) // 目の前1メートルの距離
    textNode.pivot = SCNMatrix4MakeTranslation(textBoundsWidth/2 + min.x, textBoundsheight/2 + min.y, 0)
    textNode.position = SCNVector3(0, 0, z)

    // AR空間にテキスト要素を配置
    sceneView.scene.rootNode.addChildNode(textNode)

    // 必要に応じて自動的に光源が追加されるように設定
    sceneView.autoenablesDefaultLighting = true

    // デバッグ用設定
    // バウンディングボックス、ワイヤーフレームを表示する
    sceneView.debugOptions = [.showBoundingBoxes, .showWireframe]
}
```

viewWillAppear メソッドを以下のように書き換える。
環境マッピングを有効にする。

```swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Create a session configuration
    let configuration = ARWorldTrackingConfiguration()

    // 環境マッピングを有効にする
    configuration.environmentTexturing = .automatic

    // Run the view's session
    sceneView.session.run(configuration)
}
```

## 実機での実行結果

実機 (iPhone X + iOS 12.4.1) にインストールして実行してみる。
Hello World テキストが実空間の映像に合成されて表示されている。
表側は赤色。側面は青色。

![hello-world-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/19944a99-1c93-1837-9699-9d37ba351081.jpeg)

裏側は緑色。

![hello-world-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/d6eccf89-85d1-0222-fca8-b42fa07bba47.jpeg)

環境マッピング機能で、周囲の景色が多少映り込んでいる。

![hello-world-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/4cf25555-3aad-66a5-a5c5-df4aebf93f88.jpeg)

## 参考資料
- [ARKit \| Apple Developer Documentation](https://developer.apple.com/documentation/arkit)
- [SceneKit \| Apple Developer Documentation](https://developer.apple.com/documentation/scenekit)
- [\[iOS 11\]\[ARKit\] 空間に3Dテキストを表示してみる \#WWDC2017 ｜ DevelopersIO](https://dev.classmethod.jp/smartphone/ios-11-arkit-scntext-2/)
- [\[iOS11\]\[ARKit\] SCNBoxとSCNTextでラベルみたいなノードを作成してみました ｜ DevelopersIO](https://dev.classmethod.jp/smartphone/iphone/ios11-arkit-scntext-scnbox-label/)
- [SCNTextのPivotPointを中心に持って来る \- Qiita](https://qiita.com/noby111/items/3b59ac12aad09548beca)