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 を選択する。

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

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

ソースコード

ViewController.swift を修正する。

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

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 メソッドを以下のように書き換える。
環境マッピングを有効にする。

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 テキストが実空間の映像に合成されて表示されている。
表側は赤色。側面は青色。

裏側は緑色。

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

参考資料