Swift Playgroundsで学ぶiOSプログラミング 第100回
SceneKitをARKitのプログラムに導入する
SceneKitの物理現象シミュレーションとアニメーションをARKitに持ち込む
2018年08月03日 17時00分更新
このところ数回は、SceneKitを使って仮想の3D世界に物体を配置し、それらをアニメーションで強制的に動かしたり、物理シミュレーションによって自発的に動かしてみたりしてきました。
もう少し遡って思い出してみると、SceneKitに手をつける前には、ARKitを利用したプログラミングに取り組んでいました。その中で、ARKitで扱う仮想世界の部分は、ほぼ完全にSceneKitに頼っていることがわかりました。そこで、いったんARKitの探求を中断して、SceneKitに移行したのでした。
もちろん前回までで、SceneKitの使い方を完璧にマスターしたというわけではありませんが、上で述べたように仮想世界を扱う仕組みは、ひととおりざっと理解できたのではないかと思います。そこで今回は、再びARKitに戻って、SceneKitでの経験を生かしたプログラミングを試してみることにします。
以前にARKitを扱った際には、まず、ARKit自体が動作することを確認した後、現実世界の水平面(床や地面)を検出し、その上に静止した仮想物体を配置するところまでを試しました。その「静止した仮想物体」は、SceneKitによって実現したものでした。そして前回までで、SceneKitによって「動く仮想物体」を実現する方法もわかりました。そこで、今回は現実世界の映像の中に動く仮想物体を投影してみます。
今回の最初には、シンプルな物理現象のシミュレーションによって、仮想物体が自然に動くようにします。次に、そこにジェスチャー認識機能を加え、現実世界の映像の中にある仮想物体に直接触れられるかのような感覚を味わえるようにします。そして最後に、アニメーション機能によって、仮想物体を現実世界の中で動き回れるようにしてみます。
「赤いガムテープ」を空中浮遊させる
以前にも確認したように、3D仮想空間を投影するためのシーンビューは、ARKitでも使います。しかし、そのシーンビューはSceneKitのシーンビューと同じものではありませんでした。ARKitの中で使うために機能を強化したARKit専用のシーンビューとして、ARSCNViewクラスのオブジェクトを使います。
とはいえ、その後の操作は、通常の、つまりSceneKitのシーンビューと大差ありません。例えば今回のプログラムでは、シーン全体に作用する重力をキャンセルするための設定を、viewDidLoadの中で実行しています。そのためのコードは、前回までに示したSceneKitのプログラムと何ら変わりません。
一方、ARKitで扱うシーンビューには、SceneKitでは必要がなかった操作も加える必要があります。それは、iPadのジャイロや重力センサー、カメラの映像などの変化によって現実世界をトラッキングする機能を起動したり、停止したりするものです。これは、以前と同様に、起動はviewWillAppear、停止はviewWillDisappearの中で実行しています。
前者の中では、やはり以前同様、水平面を検出する機能を有効にし、デフォルトの照明もオンにしています。
実際にシーンの中に物体(ノード)を配置するのは、水平面が検出されたときに呼ばれるrendererのdidAddメソッドの中です。今回は、検出された水平面に、平面のジオメトリ(SCNPlane)から作った透明のノードを配置することにしました。それは、そのノードに物理学場(SCNPhysicsField)を設定するためです。物理学場はノードに設定することで有効になるので、透明の平面でも立派にその役割を果たします。
ここでは、まず検出された水平面よりも0.5だけ高い位置に透明の平面を配置しています。この面自体は動かないように、静止タイプの物理学体(PhysicsBody)も設定します。そして、これがいちばん重要ですが、周囲の物体を比較的強い力で引き付けるスプリングを、その水平面の中央に設定しました。
rendererメソッドの残りの部分では、SCNTubeのジオメトリから作った円筒形のノードを、透明の平面よりも、さらに0.2だけ高い位置に置いています。色は目立つように赤にしました。
これが物理学場の影響を受けるように、ダイナミックタイプの物理学体を設定しています。スプリングによる力の中心からちょっとずらすことで、最初からある程度の動きが付くことに期待しています。
このプログラムを起動して、室内なら床やテーブル、屋外なら地面などの水平面を検出させると、その少し上に、赤い円筒系の物体が表示されるはずです。
ちょうど赤いガムテームのロールのように見えるかもしれません。複数の水平面を検出すると、そのたびに赤い円筒形も追加されます。平面の中央に設置したスプリングの力は、同じシーン内のノードに影響するので、複数の水平面を検出させることで、赤いガムテープは、よりダイナミックに動きます。
この連載の記事
- 第99回 「物理学体」と「物理学場」を設定して物理現象をシミュレーション
- 第98回 SceneKitのノードに動きを加えるプログラム
- 第97回 いろいろな形のノードをシーンの中に配置する
- 第96回 SceneKitの基礎シーンビュー、シーン、ノードを理解する
- 第95回 現実世界の床にボールや自動車のモデルを配置する
- 第94回 ARKitを使って非現実世界との融合に備える
- 第93回 ARKitが使えるiPadを識別するプログラム
- 第92回 Swift Playgrounds 2.1での問題点をまとめて解消する
- 第91回 iPadの内蔵カメラで撮影した写真を認識するプログラム
- この連載の一覧へ