[iOS 11][ARKit] Core Locationと組み合わせてコンパスを作ってみた

2017.11.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

今回は、ARKitCore Locationを組み合わせて、コンパスを作って見ました。コンパスアプリは普通に沢山ありますが、景色の一部として表示されてるコンパスも少し面白いのではないでしょうか。

最初に、作成したサンプルが動作しているようすをご覧下さい。

2 コンパス 3Dオブジェクトについて

コンパスは、ScreneKit Scene FileからXcodeで作成しました。

001

使用したのは、基本的なシェードであるCylinderPyramid及び、3D Textで、それぞれを変形しています。

003

具体的には、コンパスの針の部分は、Pyramidを2つ組み合わせ、その外円は、Cylinderです。

002

色々な方向から確認しながら作業を進めます。

作成したシーンファイルから、コンパスオブジェクトを抜き出して、シーンに追加するコードは、次のようになります。

if let compassScene = SCNScene(named: "art.scnassets/Compass.scn") {
    if let node = compassScene.rootNode.childNode(withName: "compass", recursively: true) {
        sceneView.scene.rootNode.addChildNode(node)
    }
}

3 北に向ける

コンパスオブジェクトは、シーンが初期化された時点で、デバイスが向いている方向を正面として配置されます。

コンパスを北(磁北)に向けるためには、このオブジェクトをY軸を中心に回転させる必要があります。 そこで、Core Locationで取得した角度だけ、逆に回転させています。

004

コードは、次のようになりました。

func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
    if angle == -1 { // コンパスの回転を初期化するのは、最初の1回のみ
        angle = newHeading.magneticHeading
        compassNode?.rotation = SCNVector4(0, 1, 0, (angle / 180) * Double.pi)
    }
}

4 真下に配置する

シーンの中に配置したノードは、位置(position)を持っており、その位置は変化しません。 しかし、今回のコンパスは、常に自分の真下にあって欲しいので、カメラの位置を基準に逐次位置を変更してます。

カメラ(ノード)は、sceneView.pointOfViewで取得できます。そして、convertPositionを使用して、カメラを基準にコンパスの位置を計算しています。

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    guard let camera = sceneView.pointOfView else { return }
    let position = SCNVector3(x: 0, y: -1.5, z: 0) // 偏差(自分を中心に、1.5m下方)
    compassNode?.position = camera.convertPosition(position, to: nil) // カメラ位置からの偏差に変換する
}

5 最後に

カメラ位置とCode Locationの位置情報(経緯度)を組み合わせれば、シーンの中のオブジェクトを現実の位置に基づいて配置できます。

マーカーが無いARKitですが、Core Locationと組み合わせれば、複数のデバイスで共通の位置にオブジェクトが表示できるかも知れません。

次は、その辺を試して見たいと思います。

コードは、下記に置きました。参考になれば幸いです。
github [GitHub] https://github.com/furuya02/ARKitCompass

6 参考リンク


[iOS] 位置情報の取得 (Swift3編)
[iOS 11] はじめてのARKit #WWDC2017
[iOS 11][ARKit] 距離の計測について #WWDC2017
[iOS 11][ARKit] 平面の検出について #WWDC2017
[iOS 11][ARKit] 物理衝突を実装して、キューブを落として見る #WWDC2017
[iOS 11][ARKit] 空間に3Dテキストを表示してみる #WWDC2017
[iOS 11] ARKitでソファー設置からあの子の身長測定まで色々やってみた
[iOS 11][ARKit] 近所の駐車場で、大型ディスプレイでビデオを見る!
[iOS11][ARKit] オブジェクトの位置と回転「常にこっちを向いている怪獣」
[iOS11][ARKit] SCNBoxとSCNTextでラベルみたいなノードを作成してみました
[iOS 11][ARKit] UIViewをテクスチャーにしてTwitterクライアントを作ってみる
[iOS 11][ARKit] 新登場! Googleの3Dオブジェクトライブラリ Poly が便利すぎる