RealityKit + ARKit 3 + SwiftUI で宙に浮く Hello World テキスト in 拡張現実

## 概要
- iOS の RealityKit を使って拡張現実で Hello World テキストが宙に浮くアプリを作る
- ARKit 3 は裏側で動作しているが今回は直接操作はしない
- UI 部分の構築に SwiftUI を使用する
- Storyboard の状態を修正せず、ソースコードだけで実現する

## 環境
- Xcode 11.0
- RealityKit
- ARKit 3
- Swift 5.1
- SwiftUI
- iPhone X + iOS 13.0

## プロジェクトの作成

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

<img width="727" alt="realitykit-hello-world-01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/4a755163-653d-b62e-f7ef-dc37ccd09777.png">

以下のオプションを選択する。

- Language: Swift
- Content Technology: RealityKit
- User Interface: SwiftUI

<img width="722" alt="realitykit-hello-world-02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/98840c65-5f8d-c83e-05b0-d361f69d338b.png">

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

<img width="881" alt="realitykit-hello-world-03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/fdc9331c-0c86-f279-11f4-21c4f0a344c4.png">

## ソースコード

ContentView.swift を以下の内容に修正する。

```swift
import SwiftUI
import RealityKit

struct ContentView : View {
    var body: some View {
        return ARViewContainer().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer: UIViewRepresentable {

    func makeUIView(context: Context) -> ARView {

        // RealityKit のメインとなるビュー
        let arView = ARView(frame: .zero)

        // デバッグ用設定
        // 処理の統計情報と、検出した3D空間の特徴点を表示する。
        arView.debugOptions = [.showStatistics, .showFeaturePoints]

        // シーンにアンカーを追加する
        let anchor = AnchorEntity(plane: .horizontal, minimumBounds: [0.15, 0.15])
        arView.scene.anchors.append(anchor)

        // テキストを作成
        let textMesh = MeshResource.generateText(
            "Hello, world!", 
            extrusionDepth: 0.1,
            font: .systemFont(ofSize: 1.0), // 小さいとフォントがつぶれてしまうのでこれぐらいに設定
            containerFrame: CGRect.zero,
            alignment: .left,
            lineBreakMode: .byTruncatingTail)
        // 環境マッピングするマテリアルを設定
        let textMaterial = SimpleMaterial(color: UIColor.yellow, roughness: 0.0, isMetallic: true)
        let textModel = ModelEntity(mesh: textMesh, materials: [textMaterial])
        textModel.scale = SIMD3<Float>(0.1, 0.1, 0.1) // 10分の1に縮小
        textModel.position = SIMD3<Float>(0.0, 0.0, -0.2) // 奥0.2m
        anchor.addChild(textModel)

        // 立方体を作成
        let boxMesh = MeshResource.generateBox(size: 0.1)
        // 光源を無視する単色を設定
        let boxMaterial = UnlitMaterial(color: UIColor.red)
        let boxModel = ModelEntity(mesh: boxMesh, materials: [boxMaterial])
        boxModel.position = SIMD3<Float>(-0.2, 0.0, 0.0) // 左0.2m
        anchor.addChild(boxModel)

        // 球体を作成
        let sphereMesh = MeshResource.generateSphere(radius: 0.1)
        // 環境マッピングするマテリアルを設定
        let sphereMaterial = SimpleMaterial(color: UIColor.white, roughness: 0.0, isMetallic: true)
        let sphereModel = ModelEntity(mesh: sphereMesh, materials: [sphereMaterial])
        sphereModel.position = SIMD3<Float>(0.0, 0.0, 0.0)
        anchor.addChild(sphereModel)
        
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {}
}
```

## 実機での実行結果

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

実空間を背景にして Hello World テキスト、赤い立方体、金属的な球体が合成されて表示されている。

![realitykit-hello-world-07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/3bc51ab5-aac9-df79-421b-75aebea2ccff.jpeg)

![realitykit-hello-world-04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/f7e58847-fc2f-06cc-9771-6d2eec90fab8.jpeg)

裏側からは反転した Hello World テキストになっている。

![realitykit-hello-world-05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/5f18fca5-4604-f554-40b8-b63bbcedd7de.jpeg)

球体には環境マッピングで周囲の景色が写り込んでいる。

![realitykit-hello-world-06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/f5396366-85a5-64ec-659f-44d1a77516ee.jpeg)

# 参考資料

- [Introducing RealityKit and Reality Composer \- WWDC 2019 \- Videos \- Apple Developer](https://developer.apple.com/videos/play/wwdc2019/603)
- [Building Apps with RealityKit \- WWDC 2019 \- Videos \- Apple Developer](https://developer.apple.com/videos/play/wwdc2019/605/)
- [RealityKit \| Apple Developer Documentation](https://developer.apple.com/documentation/realitykit)
- [MeshResource \- RealityKit \| Apple Developer Documentation](https://developer.apple.com/documentation/realitykit/meshresource)
- [ModelEntity \- RealityKit \| Apple Developer Documentation](https://developer.apple.com/documentation/realitykit/modelentity)
- [RealityKit の説明と SceneKit との違いについて考える \(Xcode 11\.0 Beta 1\) \- Apple Engine](http://appleengine.hatenablog.com/entry/2019/06/07/052651)