SwiftのARKitの基本機能を見てみよう

# 初めに
今回はSwiftで最近よく使われている[ARKit](https://developer.apple.com/documentation/arkit)の基本機能を実装していきたいと思います。
ARKitまだよくわからない人にとっての入門記事としてはぴったりかなと。
では初めていきます。よろしくお願いします。

## 導入
まずXcodeを開き、手順は以下です。
Create a new Xcode project
![スクリーンショット 2021-09-03 11.07.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/2524c0d6-f867-6fb3-d9fb-5b68b263fe6d.png)
ここでいつものAppではなく、Augmented Reality Appを選択する。
![スクリーンショット 2021-09-03 11.08.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/3eae3106-631c-ea97-6509-31fd453419e6.png)
次に、Content Technologyでもうすでに選択されているSceneKitを選択して、自分の指定して位置にアプリを作成する。
そしたら、すでにこのようなサンプルプロジェクトが作られています。
![スクリーンショット 2021-09-03 11.13.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/af84da76-b835-7746-5f84-a13ba25e8c4d.png)
![スクリーンショット 2021-09-03 11.16.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/f568fda4-33e4-f398-15b9-8bcbc6bd860e.png)


```swift:ViewController
import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        
        // Create a new scene
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        
        // Set the scene to the view
        sceneView.scene = scene
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()

        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }

    // MARK: - ARSCNViewDelegate
    
/*
    // Override to create and configure nodes for anchors added to the view's session.
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        let node = SCNNode()
     
        return node
    }
*/
    
    func session(_ session: ARSession, didFailWithError error: Error) {
        // Present an error message to the user
        
    }
    
    func sessionWasInterrupted(_ session: ARSession) {
        // Inform the user that the session has been interrupted, for example, by presenting an overlay
        
    }
    
    func sessionInterruptionEnded(_ session: ARSession) {
        // Reset tracking and/or remove existing anchors if consistent tracking is required
        
    }
}
```
ここでまず初めに不要なものを削除して実機で実行してみることにしましょう。
実機での実行の仕方は、[こちら](https://i-app-tec.com/ios/device-test.html)を見てもらえるとわかります。

```swift:ViewController
import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
           
        // Create a new scene
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        
        // Set the scene to the view
        sceneView.scene = scene
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()

        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }
}
```
![Videotogif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/2fc79e64-f9ca-da4a-1d8d-307b7d55fa7c.gif)
ship.scnが浮かび上がっています。

また```configuration```のところをいじることで色々な見え方をデザインすることが出来ます。
一例として、

```swift
// Create a session configuration
        //let configuration = ARWorldTrackingConfiguration()
        let configuration = AROrientationTrackingConfiguration()
```
と置き換えてみてください。

![Videotogif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/dd1bb9d8-4da8-383a-2749-cbe5cb2d088f.gif)

この違いは、[ARWorldTrackingConfiguration](https://developer.apple.com/documentation/arkit/arworldtrackingconfiguration)と[AROrientationTrackingConfiguration](https://developer.apple.com/documentation/arkit/arorientationtrackingconfiguration)
のドキュメントを見て貰えばわかりやすいのですが、
AROrientationTrackingConfigurationはDeviceの3DのPositionを検知できない構造になっているので、このような違いが出てしまっています。
主に、ARWorldTrackingConfigurationを使うことが多いですが、他にも、色々なconfiguration objectsがあるので[ドキュメント](https://developer.apple.com/documentation/arkit/configuration_objects)を見ながら、実機で試してもらうと面白いですよ。

ここからARKitで使われる基本的な機能の紹介をしていきたいと思います。

## Create a 3D Object
次は画面上にcubeを作成していきたいと思います。

```swift:ViewController
import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        let cube = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.01)
        
        let material = SCNMaterial()
        
        material.diffuse.contents = UIColor.red
        
        cube.materials = [material]
        
        let node = SCNNode()
        
        node.position = SCNVector3(x: 0, y: 0.1, z: -0.5)
        
        node.geometry = cube
        
        sceneView.scene.rootNode.addChildNode(node)
        
        //いらない部分はコメントアウト
//        // Create a new scene
//        let scene = SCNScene(named: "art.scnassets/ship.scn")!
//
//        // Set the scene to the view
//        sceneView.scene = scene
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = AROrientationTrackingConfiguration()

        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }
}

```