ARKit を使って 3D モデルを AR で表示してみた

Document created by yuki_ozawaesrij-esridist Employee on Oct 26, 2017Last modified by masanobu_hiranoesrij-esridist on Oct 29, 2017
Version 8Show Document
  • View in full screen mode

iOS 11 が 2017 年 10 月にリリースされ、アップデートしてお使いの方も多いのではないでしょうか。

iOS 11 では色々な新機能が追加されており、 その目玉の一つに AR(拡張現実)対応が挙げられます。

そこで、Apple の AR フレームワークを利用するための SDK である ARKit を使用して、街並みの 3D モデルを AR で表示するアプリを作成してみました。

作成したアプリのイメージは動画をご覧ください。 

 

 

3D モデルも含めて、GitHub にサンプル コードを公開していますので、ぜひお試しください。

 

 

3D モデルの作成

3D コンテンツ作成ソフトウェアである Esri CityEngine(以下、CityEngine)を使用しました。

CityEngine を使用すると、都市および建物などの 3D モデルを既存の GIS データから効率的に作成できます。

今回はこちらのブログ記事を参考に OpenStreetMap から建物データを取得し、街並みの 3D モデルを作成しました。

作成した 3D モデルは、ARKit で扱える .dae ファイル(COLLADA 形式)として出力しました。

CityEngine では COLLADA や Wavefront OBJ 形式など、標準的な 3D 形式への出力をサポートしています。

CityEngine にご興味がある方は、無償のトライアル版もありますので、お試しください!

 

 

AR で表示

まず最初にアプリの画面に AR 用のビュー(ARSCNView)を追加します。

 


ARSCNView にはひとつのシーン(SCNScene)が割り当てられます。

SCNScene はビューに表示するシーンやシーンのコンテンツを管理します。

通常、SCNScene は 3D 形式のファイルから作成します。

let myScene = SCNScene(named: "<ファイル名>")

 

作成したシーンを ARSCNView にセットすることで AR 上に 3D モデルが表示されます。

self.sceneView.scene = myScene

 

 

また、ARSCNView がデフォルトで持つシーンにノード(SCNNode)を追加して表示することもできます。
ノードはシーンを構成するジオメトリ、ライト、カメラなどの要素です。

プログラミングでノードを作成して 3D モデルを表示することもできますし、3D 形式のファイルからノードを読み込むこともできます。
Xcode の SceneKit Editor の画面で、CityEngine で作成した .dae ファイルを見てみると、複数のマテリアル(3D オブジェクト)から構成されているのが分かります。

 

 

このマテリアル名を指定してノードを作成することができます。

.dae ファイルの特定のマテリアルをノードとして取得してするには以下のようにします。

let townScene = SCNScene(named: "<.dae のファイル名>")
townNode = townScene.rootNode.childNode(withName: "<マテリアル名>", recursively: true)

 

今回は .dae ファイルを構成する全てのマテリアルを1ノードとして扱うため、SceneKit Editor 上で新たに親ノードを作成([Scene graph] の下部にある [+] ボタンをクリック)し、親ノードの子ノードとしてマテリアルを追加しています。

 

 

取得したノードをシーンに追加するには、addChildNode を使用します。

self.sceneView.scene.rootNode.addChildNode(townNode)

 

サンプル コードでは、上記の方法で CityEngine で作成した複数の 3D モデルをシーンに追加しています。

このような流れで AR 上に 3D モデルを表示することができます。


位置や角度を調整してみる

次に、表示する 3D モデルの表示位置やサイズを変更してみます。

これらの操作はシーンを構成するノードに対して、3次元のベクトルを表現する SCNVector3 を使用して行います。

 

表示位置:

 

 

SCNNode の position を変更します。

以下の例では、向かってカメラの中心位置から右に 5 m、上に 10 m、奥行きを 1 mずらして表示します。

myNode.position = SCNVector3(5, 10, -1)

 

 

表示角度:

 

 

SCNNode の eulerAngles を変更します。

以下の例では、ピッチを 10 度、ヨーを -5 度、ロールを 0 度回転します。

myNode.eulerAngles = SCNVector3(10 * (Float.pi / 180), -5 * (Float.pi / 180), 0)


スケール:

 

 

SCNNode の scale を変更します。

以下の例では、3D モデルの実サイズに対して 1/2 倍のスケールで表示します。

myNode.scale = SCNVector3(0.5, 0.5, 0.5)

 


サンプル コードでは、ボタンをタップしたら画面の中心にノードを移動させています。

画面の特定の場所を指定して AR 上の座標を取得するには、ARSCNView の hitTest を利用できます。

hitTest のパラメータの ResultType には取得するオブジェクトの種類を指定します。

例えば、サンプル コードでは featurePoint を指定していますが、featurePoint は平面検出を考慮せずに、特定の場所の座標を取得します。

estimatedHorizontalPlane を指定すると検出された平面のサーフェスを取得します。

オブジェクトの取得が成功すると hitTest の返り値として、カメラから近い順に取得できた実世界のオブジェクトが返されます。

返り値から現実世界の座標を取得する場合は、以下のようにします。

SCNVector3(hitResult.worldTransform.columns.3.x, hitResult.worldTransform.columns.3.y, hitResult.worldTransform.columns.3.z)

 

ここで取得した座標を SCNNode の position に再設定し、ノードを移動させます。

以上、3D モデルを AR で表示するための方法をご紹介してきましたが、不明な箇所はサンプル コードをご覧ください。

 


おわりに

3D モデルを現実世界の風景に重ね合わせて見ることで、都市計画の完成イメージの再現などにも役立ちそうです。

今回の記事では、表示する方法や表示位置/角度の変更などの基本的な内容についてご紹介しました。

平面や光源検出など ARKit の特徴的な機能については、またの機会にご紹介したいと思います。

1 person found this helpful

Attachments

    Outcomes