Blog スタッフブログ

iOS Swift システム開発

[Swift][ARKit]ARSCNViewに対するタップ地点特定処理

Swift

こんにちは、株式会社MIXシステム開発担当のBloomです。

早速本題のARKitにおいてARSCNView中で取得したAR空間においてタップ地点の座標を特定する手順について、

お仕事の中で得た知見を共有させていただきたいと思います。

AR空間の取得

今回はARKitを利用します。まずは対応端末で下記コードを実行しAR空間を取得しましょう。

import ARKit
class ViewController: UIViewController {
    @IBOutlet var sceneView: ARSCNView!
    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self
        sceneView.scene = SCNScene()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = [.horizontal, .vertical]
        sceneView.session.run(configuration)
    }
}

さて、これで平面検出を駆動させられました。このままタップ地点を特定しましょう。

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else {return}
        let pos = touch.location(in: sceneView)
        guard let raycast = sceneView.raycastQuery(from: pos,
                                                   allowing: .existingPlaneGeometry,
                                                   alignment: .horizontal),
              let result = sceneView.session.raycast(raycast).first else {
            return
        }
        let hitPos = result.worldTransform.position()
    }

ここではraycastQueryメソッドを利用しています。raycastQueryは指定したスクリーン座標からZ軸方向に垂直に伸びる光線を伸ばし(本当にセンサーを発射しているわけではなく擬似的に)、allowingで指定した対象と衝突した地点の座標を返却します。

allowingにはestimatedPlane, existingPlaneGeometry, existingPlaneInfiniteが指定可能であり、それぞれ推定状態の平面、検出が完了した平面、検出平面を無限に広げた平面をそれぞれ対象に取れます。うまく使い分けましょう。

これで簡単にタップ地点の検出ができました。良かったですね。

参考文献

[Swift, ARKit]非推奨になったhitTestからraycastQueryに移行する – Qiita.com