【ARKit】拡張現実テンプレートを再現する


この投稿は何?

Xcodeでアプリケーションを開発するとき、テンプレートを選択します。
特に、AR(拡張現実)アプリを開発する場合は Augmented Reality App テンプレートを選択します。
この投稿では、最も基本的なアプリ向けテンプレートの Single View App をカスタムして、Augmented Reality App テンプレートと同等にする手順を解説します。

何を作るの?

以下のような極めてシンプルなARアプリケーションを作成します。

この投稿記事では...

  • iPhone で現実空間を認識すること
  • 現実空間に、仮想オブジェクトを配置すること

を実践できます。

実行環境

ARKit は iOS11 とともにリリースされた拡張現実アプリケーションを開発するためのフレームワークです。実行するには、iPhoneSE 以降の iOS デバイスの実機が必須です。

なお、この投稿記事は以下の環境で実践しています。
- Xcode10
- macOS Mojave 10.14.2
- iPhoneX 実機 (iOS 12.1)

前提の知識とスキル

Xcode の基本的な使い方を理解している。
Swift の基本的な構文を理解している。
拡張現実 (AR) のことを知っている。

ARKit については以下のリンクで詳しく紹介されています。
iOSのための拡張現実

手順

作業完了後には、実機の iPhone を使用してビルドおよび実行します。
Mac と iPhone が正しく接続できることを確認しておいてください。

プロジェクトのオプションを選択する

Single View App テンプレートを選択します。

Product Name を入力します。
ここでは Typical Augmented Reality App としておきます。

プロジェクトは任意の場所に保存してください。
新しいプロジェクトが作成できました。

プロパティリストをカスタムする

プロジェクトを作成した直後は、プロジェクトナビゲーターが表示されています。
info タブを選択して、アプリケーションの概要を設定します。
このアプリケーションでは、ARとカメラを使用することを明示します。

ARKit を使用する

  1. Required device capabilities キーを展開します。
  2. item0+ をクリックして、サブキーを追記します。
  3. valuearkit と入力します。

カメラを使用する

  1. トップレベルにある任意の key+ をクリックします。
  2. 追加された key で、Privacy - Camera Usage Description を選択します。
  3. value はカラにしておきます。

シーンを作成する

Xcode にデフォルトで用意されている Augmented Reality App テンプレートには、飛行機の3Dモデルが作成されていますが、この投稿では飛行機ではなく「単純な立方体の3Dモデル」を使用します。

Assets フォルダを新規作成する (art.scnassets)

  1. Xcode メニューから「File > New > File...」を選択します。

  2. SceneKit Catalog を選択して、art.scnassets という名前で保存します。

  3. ナビゲータエリアに作成された art.scnassets フォルダを移動しておきます。

Assets フォルダにシーンファイルを作成

シーン は、仮想的な3D空間です。3D空間の座標系は、(x, y, z) の3軸で認識されます。
ここでは、何もないカラのシーンを作成します。
また、シーンに存在する物体のことを ノード と言います。

  1. art.scnassets フォルダを副クリックして、New File を選択します。

  2. ファイル名は cube.scn にしておきます。また、Scene graph にある camera ノードは削除しておきます。

シーンの操作方法は以下の通りです。

  • ドラッグ&ドロップ操作をすると、視点を回転
  • スクロース操作をすると、視点を移動
  • ピンチイン・アウトすると、視点をズームイン・アウト

立方体のノードを配置する

飛行機の3Dモデルを作るのは大変なので、代わりに立方体の3Dモデルをシーンに配置します。
この立方体ノードは、少しだけ平べったい感じの形状にします。

  1. Xcode メニューから「Editor > Create > Geometry > Box」を選択するか、オブジェクトライブラリから box をドラッグ&ドロップして、立方体ノードを cube.scn シーンに配置します。

  2. 立方体ノードの位置を設定する
    立方体ノードのノードインスペクタを表示します。
    Position プロパティを x:0, y:1, z:1 に変更します。
    単位はメートルなので、原点から 1m 高いところに立方体ノードが配置されます。

  3. 立方体ノードのサイズを設定する
    立方体ノードのアトリビュートインスペクタを表示します。
    Size プロパティを width:1, height:0.5, length:1 に変更します。
    縦横が 1m で高さが 50cm の立方体です。

  4. 立方体ノードを可視化する
    この時点で立方体ノードには形状と位置が設定されていますが、どのように見えるか設定していないので、見えない状態です。
    マテリアルインスペクタから、Diffuse プロパティから任意のカラーを設定します。

  5. シーンを確認する
    エディタエリア下部にある ボタンをクリックすると、シーンが描画されます。
    視点を回転・移動して、どのように見えるか確認しましょう。

確認できたら、□ ボタンを押して描画を停止します。

Storyboard をカスタムする

ARKit は iPhone のカメラが捉えた現実空間にシーンを投影します。こうすることで、「実際には存在しない仮想オブジェクト」が現実に存在するかのようにユーザは感じます。
この機能を実現するためには、iPhone の画面に ARSCNView オブジェクトを配置します。

arscnview を配置する

  1. ナビゲータエリアで、Main.storyboard を選択します。
  2. オブジェクトライブラリから ARKit SceneKit View を選択して、ビューコントローラに配置します。

Autolayout の制約を設定する

ユーザがAR世界に没入できるように、画面いっぱいに ARSCNView が表示されるようにします。
上下左右の safe area までの間隔を 0 にして、Add 4 Constraints をクリックします。

あらゆるデバイスで、画面いっぱいに拡張現実ビューが表示されるようになりました。

ビューをコードと接続する

  1. ビューコントローラを選択した状態で、アシスタントエディタモードに切り替えます。

    エディタエリアの左側にストーリーボード、右側にそのコードが表示されていることを確認します。

  2. ストーリーボード上の ARSCNView を副クリックします。
    コンテキストメニューにある New Referencing Outlet をドラッグして、コード側の ViewController クラス定義にドロップします。

  3. パネルが表示されるので、Name に sceneView と入力します。

アラートが表示されていますが、後で対処します。

コードを記述する

テンプレートを再現するにあたり、可能な限り忠実に記述しますが、理解度の向上を期待して一部の変数名などを変更しています。また、一部コードを追記しています。

アシスタントエディタモードからスタンダードエディタに切り替えて、ViewController.swift を表示します。

フレームワークをインポートする

コード上で、SceneKitARKit の機能を使用するために、フレームワークをインポートします。

ViewController.swift
import UIKit    // これは最初からある
import SceneKit
import ARKit

警告表示が消えました。
コードから、UI部品である ARSCNViewsceneView として操作できるようになりました。

デリゲートを設定する

ARSCNView で発生したイベントを ViewController クラス内で処理できるようにします。
1. プロトコルに準拠させて、ViewController クラスをデリゲート先に指定します。

ViewController.swift
class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet weak var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()

        sceneView.delegate = self    //デリゲート先になる
    }

}

シーンのインスタンスを生成する

  1. 作成した cube.scn ファイルをインスタンス化して、ビューの scene プロパティに設定ます。
ViewController.swift
class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet weak var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()

        sceneView.delegate = self

        let cubeScene = SCNScene(named: "art.scnassets/cube.scn")!  //インスタンスを生成
        sceneView.scene = cubeScene    //ビューに表示する
    }

}

ARセッションを実行する

アプリが起動してシーンが描画されたら、ARセッションを実行するようにします。

ViewController.viewWillApper()メソッド
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        let configration = ARWorldTrackingConfiguration()
        sceneView.session.run(configration )
    }

ARセッションを停止する

アプリが停止して、デバイス画面からシーンが非表示になったら、ARセッションを停止します。

ViewController.vierWillDisappear()メソッド
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        sceneView.session.pause()
    }

典型的なAR機能が動作するアプリケーションのコードが完成しました。

解析情報を表示する

ARKit が現実空間を認識・追跡していることをわかりやすくします。
また、デバイスに対してどれくらい負荷を掛けているかを解析する情報を表示するようにします。
以下のコードを追記してください。

ViewController.viewDidLoad()メソッド
    override func viewDidLoad() {
        super.viewDidLoad()

        sceneView.delegate = self

        sceneView.debugOptions = .showWorldOrigin
        sceneView.showsStatistics = true

        let cubeScene = SCNScene(named: "art.scnassets/cube.scn")!
        sceneView.scene = cubeScene
    }

実行

Mac と iPhone を接続して、実行先スキームを実機に変更します。

なお、ビルド・実行すると iPhone に「"Typical Augmented Reality App"がカメラへのアクセスを求めています」と表示されるので、OKをタップしてください。

ARアプリケーションを実行するには

ARKit による拡張現実は iPhone のカメラとモーションセンサーを連携することで実現しています。
アプリを実行するには、以下のような環境が要求されます。

  • 明るい場所
    カメラが撮影した映像が鮮明でない場合、ARKit は現実空間を認識・追跡できません。

  • 移動していない空間
    モーションセンサーはデバイスが移動した加速度を検出します。電車などの移動空間内ではセンサーが正しく動作しないことがあります。

  • 空間を認識させる
    アプリケーション起動後、デバイスを回転させたり移動させることで、現実空間を正しく認識できます。

こうなった

実際に起動した画面は、このようになります。

画面奥に見える「赤、青、緑の3軸」は、アプリケーションを起動した座標です。
つまり、このスクリーンショットは「地面すれすれでアプリ起動した後、左に回り込んだ」状態です。

まとめ

AR の基本機能である 空間認識仮想オブジェクトの投影 を使用できました。
ARKit には 平面を検出 する機能があります。また、投影した仮想オブジェクトを インタラクティブ に扱うこともできます。
さらに、認識しているAR空間を 共有 したり、特定の 2D画像や3Dモデルを検出 することもできるようになりました。
発表されて以来、着実に強化されていることからも Apple が ARKit にどれほど期待しているかが見て取れます。