Swift Playgroundsで学ぶiOSプログラミング 第95回
ARKitで3Dオブジェクトを配置する
現実世界の床にボールや自動車のモデルを配置する
2018年07月23日 19時00分更新
このところARKitを利用するプログラムに取り組んでいます。最初はほとんどARKitが動作するかどうかだけを確かめるようなプログラムから始めました。
というのも、すでに述べたように、ARKitは、Swift Playgroundsが利用可能なすべてのiPadで動作するとは限らないからです。そして前回は、カメラで撮影中の現実世界の中の水平面を検出する機能をプログラムしてみました。現実世界の(映像の)中に、非現実世界の3Dオブジェクトなどを自然な感じで配置するには、現実世界の地面、あるいは床やテーブルの位置や形状に基づいて、非現実世界の座標系を設定する必要があるからです。
前回は、検出した水平面の位置と大きさに合わせて、ちょうどシートを敷くように、半透明の緑色の平面を配置していました。それによって、水平面がうまく検出できたことは確認できたものの、それだけではAR(拡張現実)の効果として寂しい絵であったことは否めません。そこで、今回は単なる水平面の検出と確認から脱却して、形のある立体的な3Dオブジェクトを配置してみることにします。
ARKitの初回には、文字列から生成した3Dオブジェクトをやみくもに空中に配置していましたが、2回目で水平面が検出できるようになりました。そこで3回目の今回は、それらを組み合わせて地面や床、あるいはテーブル上に置いたように見える3Dオブジェクトを配置してみようというわけです。
まずは、3Dオブジェクトとしては最もシンプルな球体を置いてみます。その後、3Dのモデリングアプリで作成した比較的複雑な形状のオブジェクトを配置してみましょう。これらは、オブジェクトの複雑さ(データ量)としてはかなり異なりますが、ARKitを利用したプログラム上の処理の手順としては、それほど大きく変わることはありません。
検出した水平面に沿った平面の代わりに球体を配置する
今回の最初のプログラムは、前回の最終的なものより、むしろシンプルな状態からスタートします。前回の平面検出では、いったん検出できた平面に対しても、その後のカメラの動きによってさらに広い領域が検出できた場合にアップデートを実行していました。具体的には、rendererのdidAddメソッドで最初に検出した平面を画面に表示し、さらにdidUpdateメソッドによって追加された情報を使って大きさを修正していました。今回は、didAddメソッドだけを実装して、最初に検出した平面の中央にオブジェクトを配置することにします。
プログラムの最初の部分は、前回のものと何も変わりません。
ざっと復習すると、ビューコントローラーのプロパティとして、ARKitが提供するシーンビューを用意し、viewDidLoadメソッドの中で、そのシーンビューをビューコントローラーのビューに置き換えます。つまり、プレイグラウンド画面にはシーンビューだけを表示するようにします。
viewWillAppearメソッドの中では、現実世界の水平面の検出機能をオンにして、シーンビューのセッションを起動します。また、水平面が検出された際には、このビューコントローラー内のデリゲートメソッド、rendererが呼び出されるように設定しています。
そのrendererのdidAddメソッドの中で、検出した水平面上にオブジェクトを配置していきます。とりあえず、前回に描いた半透明の緑の平面はそのまま残し、その上に赤いボールを配置してみることにしましょう。
ボールは、まず球体(Sphere)として、半径だけを指定してSCNSphereクラスのオブジェクトを作ります。そして、そこに赤い色を設定し、それからノード(SCNNode)を作成します。さらにそのノードの位置を設定してから、メソッドに渡されてきた全体のノードに、子ノードとしてセットします。
プログラムの他の部分は、前回のものと同じです。これで、平面を検出すると、緑のシートの上に赤いボールが表示されるはずです。しかし、実際に表示されたボールは、ちょうど南半球(下半分)が、緑のシートの下に潜り込んだようになってしまいました。
球体の位置は、検出した平面の中央に設定したのですが、それは球の中心の点となるので、当然と言えば当然の結果です。球が平面の上に乗っている、つまり球の表面が平面に接しているように配置するには、球の位置を、その半径分だけ上に持ち上げる必要があります。そのためには、球の位置の高さ方向を表すy軸の座標に、球の半径と同じ0.05を加えれば良いのです。
これで、赤いボールが緑のシートの上に、言い換えれば床の上に、ちょうど乗っているように見えるはずです。
この連載の記事
- 第100回 SceneKitの物理現象シミュレーションとアニメーションをARKitに持ち込む
- 第99回 「物理学体」と「物理学場」を設定して物理現象をシミュレーション
- 第98回 SceneKitのノードに動きを加えるプログラム
- 第97回 いろいろな形のノードをシーンの中に配置する
- 第96回 SceneKitの基礎シーンビュー、シーン、ノードを理解する
- 第94回 ARKitを使って非現実世界との融合に備える
- 第93回 ARKitが使えるiPadを識別するプログラム
- 第92回 Swift Playgrounds 2.1での問題点をまとめて解消する
- 第91回 iPadの内蔵カメラで撮影した写真を認識するプログラム
- この連載の一覧へ