ARKitは、ちょっと試すだけなら超簡単です。APIはシンプルだし、Xcodeのテンプレートからサクッと動くものがつくれます。
しかしまた、ものすごく奥深くもあります。レンダリングはSceneKitやMetalと組み合わせられるので、これだけで3Dプログラミングのほぼあらゆるテクニックが使えるということになりますし、カメラからの生の入力データCVPixelBuffer
にもアクセスできるので、Core Image, Core ML, Vision, Metal,
etc…と組み合わせて、画像/動画処理のあらゆるテクニックを駆使できるということにもなります。ARKitが検出している特徴点データや、デプスデータにもアクセスできます。
そんな手軽さも奥深さも兼ね備えるARKit、新機能が追加されるたびにインターネット上では多くのデモやプロトタイプが公開され、iOSアプリ開発者の枠を超えて広く話題になっています。App StoreではARKitのリリースから約半年で対応アプリケーションが約1300万回ダウンロードされたそうです。
本書では、ARKitの「超簡単な導入」から始めて、最終的にはネットやストアで話題になっていたようなアイデアを実装できるようになるところまでをカバーするように構成しました。
「入門編」では、はじめの一歩として、最小実装でARKitを体験します。実にシンプルな実装で強力なAR機能が利用できることを実感していただけることでしょう。
その後は平面を検出する方法、その平面に仮想オブジェクトを設置する方法、そしてその仮想オブジェクトとインタラクションできるようにする方法…と、読み進めるにつれて「作りながら」引き出しが増えていき、最終的にはARKitを用いた巻尺(メジャー)や、空間に絵や文字を描くといった、ARKitならではのアプリケーションの実装ができるよう構成しています。
ARKitのAPIはシンプルとはいえ、リファレンスだけから実装方法を汲み取るのは難しい部分もあります。またAppleのサンプルは動かして試してみたり、ちょっと改変してみたりして用いる分にはいいですが、実装内容は結構複雑で初心者には意図がわかりにくいものになっている面があります。
といった方は、ぜひ本書を手にとってみてください。本書がARKit開発のスタートを切るきっかけになれば幸いです。
ARKitは現実の空間を利用するフレームワークなので、自分の手元(実機)で実際に動かし体感しながら学んでいくのがベストです。本書のサンプルプロジェクトはhttps://github.com/shu223/ARKitBook
にありますので、ぜひXcodeを開いてサンプルを動かし、デバイスを持って歩き回ったりするなど、楽しみながら学んでください。
はじめに
第1章 入門編その1 - 最小実装で体験してみる
第2章 入門編その2 - 水平面を検出する
第3章 入門編その3 - 検出した水平面に仮想オブジェクトを置く
第4章 ARKit開発に必須の機能
第5章 平面検出の基礎
第6章 画像検出と画像トラッキング
第7章 3D物体検出と3D物体スキャン
第8章 AR空間におけるインタラクションを実現する
第9章 AR体験の永続化と共有
第10章 フェイストラッキング
第11章 特徴点を利用する
第12章 デプスを利用する
第13章 オクルージョン
第14章 モーションキャプチャ
第15章 ビデオフォーマット
第16章 アプリケーション実装例1: 現実空間の長さを測る
第17章 アプリケーション実装例2: 空中に絵や文字を描く
第18章 アプリケーション実装例3: Core ML + Vision + ARKit
第19章 Metal + ARKit
参考文献
非常に高機能・高性能なARKitですが、シンプルなAPIで簡単に扱えるようになっています。各クラスの役割や詳細な使い方は後述するとして、まずは(約)3行でできるARKitの最小実装を示しますので、「こんなに簡単にできるのか」と実感してもらいつつ、そこからARKitのAPIデザインの大枠を掴んでください。
実はXcodeの「Augmented Reality App」テンプレートからプロジェクトを生成すれば、一行もコードを書かずにそのままビルドしてAR機能が動作するアプリが新規作成できてしまいます。ですが、「非常に簡単に実装できる」という点を体感してもらうためにも、本章では既存プロジェクトに数行のコードを追加してAR機能を構築する、というところから始めます。
サンプルコード: FirstAR
プロジェクトの設定やアセットの追加を行います。
まず、ARKitではカメラを利用するので、Info.plistにNSCameraUsageDescription
キー*1を追加しておきます。
次に、ARKitを用いて「現実世界にオーバーレイするシーン」のデータをプロジェクトに追加します。ここではship.scn(図1.1)というシーンファイル*2と、そこから参照しているtexture.pngを追加*3することにします。
ARKitをインポートします。
import ARKit
Interface Builder(以降IB)からARSCNView
オブジェクトを追加*4し、ARSCNView
を保持するプロパティと接続しておきます。
@IBOutlet var sceneView: ARSCNView!
viewDidLoad()
に次の3行を追加します。
// シーンを生成してARSCNViewにセット
sceneView.scene = SCNScene(named: "art.scnassets/ship.scn")!
// セッションのコンフィギュレーションを生成
let configuration = ARWorldTrackingConfiguration()
// セッション開始
sceneView.session.run(configuration)
これでもうビルドして実機で動かせるようになりました。アプリを起動してすぐにカメラ入力がスタートするので、周りをグルッと見てください。カメラから見える現実の世界に仮想の飛行機が設置されているはずです。デバイスを持って移動してみても、飛行機は最初の位置にしっかり固定され、色々な角度から見ることができます。
つまり、わずか3行程度の実装によって、現実世界に仮想シーンをオーバーレイし、デバイスの位置や角度の変化に追従するARの機能が構築できたことになります。
最小実装での挙動を確認できたところで、上で書いたコードが何をしていたのかを把握するため、出てきたクラスについて簡単に見ていきましょう。
ARKitでは、そのAR機能全体をARSession
クラスを用いてセッション単位で管理します。
ARSession
のrun(_:)
メソッドを呼ぶと、セッションが動作開始します。セッションが開始すると、ARKit内部でカメラからの入力の画像解析や、デバイスのモーション情報の取得・解析が開始され、現実空間の認識とデバイスのトラッキング(現実空間におけるデバイス=自分の位置や向きを追跡)が始まります。
session.run(configuration)
ARKitのない時代にARを実現しようとした場合、AVFoundationでカメラ入力画像データの取得、Core Motionでモーション情報の取得、かつそれらを「リアルタイムに」解析・統合するという、非常に複雑で難易度の高い実装が必要でした。それが、run(_:)
メソッドを呼ぶだけで実現できるようになったのです。
run
メソッドの定義は次のようになっており、第1引数には次項で解説するARConfiguration
を指定します。
func run(_ configuration: ARConfiguration,
options: ARSession.RunOptions = [])
第2引数のoptions
はデフォルト値(オプションなし)が与えられているため省略可能です。本章でもできるだけコードをシンプルにするために省略しています。*5
ARKitのセッションを中断したい場合は、pause()
メソッドを呼びます。
session.pause()
なお、セッションにはもう1つ「リセット」という概念が存在します。これについては、後の「ARKit開発に必須の機能」で解説します。
ARConfiguration
クラスは、ARKitのセッションの様々なコンフィギュレーションを管理するためのクラスです。ARSession
をrunするときの引数に渡します。
このクラスを用いて、たとえば「オーディオデータも取得するか(providesAudioData
プロパティ)」「カメラ入力からシーンのライティングを推定するか(isLightEstimationEnabled
プロパティ)」といったことが設定できます。
上の実装で出てきたARWorldTrackingConfiguration
はARConfiguration
のサブクラスで、デバイスの向きや位置をトラッキングし、かつデバイスのカメラから見える現実世界の「面」*6を検出する、というコンフィギュレーションを表します*7。
ARKitはコアな処理のみを行い、実際の描画はSceneKitやSpriteKit、Metalが担当します。
特に、3D空間の描画は基本的にSceneKitが担当します。SceneKitには、描画する3次元のシーン(SCNScene
)を、UIKitベースのUI階層内で共存して描画するためのSCNView
というUIView
を継承したクラスがあり、
class SCNView : UIView, SCNSceneRenderer, SCNTechniqueSupport
これを継承してARKit関連の機能を持たせたものが、ARSCNView
クラスです。
class ARSCNView : SCNView
ARSCNView
は、上述したARSession
オブジェクトをプロパティで保持しており、また「AR空間におけるインタラクションを実現する」で後述するヒットテストの機能も持っています。すなわちARSCNView
は、「ARKit関連の機能を取り扱いつつ、UIKitベースのUI階層内で3次元シーンを描画するためのクラス」といえます。
前述のコードにはARSession
オブジェクトを生成する処理はありませんでした。ARSCNView
オブジェクトを生成した時点で、そのsession
プロパティにはすでにARSession
オブジェクトが生成されて入っているためです。そのおかげで、ARSCNView
オブジェクトを用意すればあとはセッションをrunするだけ(sceneView.session.run(configuration)
)という手軽さでARが実現できるようになっています。
[*1] XcodeのInfo.plistエディタでは「Privacy - Camera Usage Description」と表示されます。
[*2] .scn
はSceneKit用のシーンのデータを扱うファイルの拡張子です。なお、ここで用いているship.scnはXcodeの「Augmented Reality App」テンプレートに含まれています。
[*3] サンプルではこれらのファイルを、.scnassets
という拡張子のついたSceneKitのアセット管理用フォルダに入れています。
[*4] ViewController
直下のUIView
オブジェクトのクラスをARSCNView
に変更するだけでもOKです。
[*5] 第2引数のoptions
に指定できるARSession.RunOptions
は、「ARKit開発に必須の機能」で解説しています。
[*6] 公式リファレンスでは「Surface」と表現されています。平面(Plane)だけではなく曲面も含めるという意味での「Surface」なので、本書では「面」と訳しました。
[*7] ARWorldTrackingConfiguration
を使用して水平面を検出する方法については、後の「水平面を検出するためのコンフィギュレーション」で解説します。