ARKit – Get current position of ARCamera in a scene
I know it had been solved but i have a little neat solution for it .. I would prefere adding a renderer delegate method.. it's a method in ARSCNViewDelegate
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
guard let pointOfView = sceneView.pointOfView else { return }
let transform = pointOfView.transform
let orientation = SCNVector3(-transform.m31, -transform.m32, transform.m33)
let location = SCNVector3(transform.m41, transform.m42, transform.m43)
let currentPositionOfCamera = orientation + location
print(currentPositionOfCamera)
}
of course you can't by default add the two SCNVector3 out of the box.. so you need to paste out of the class the following
func +(lhv:SCNVector3, rhv:SCNVector3) -> SCNVector3 {
return SCNVector3(lhv.x + rhv.x, lhv.y + rhv.y, lhv.z + rhv.z)
}
Set yourself as the ARSession.delegate
. Than you can implement session(_:didUpdate:)
which will give you an ARFrame
for every frame processed in your session. The frame has an camera
property that holds information on the cameras transform, rotation and position.
func session(_ session: ARSession, didUpdate frame: ARFrame) {
// Do something with the new transform
let currentTransform = frame.camera.transform
doSomething(with: currentTransform)
}
As rickster pointed out you always can get the current ARFrame
and the camera position through it by calling session.currentFrame
.
This is useful if you need the position just once, eg to move a node where the camera has been but you should use the delegate
method if you want to get updates on the camera's position.
ARKit + SceneKit
For your convenience you can create a ViewController
extension with an instance method session(_:didUpdate:)
where an update will be occured.
import ARKit
import SceneKit
extension ViewController: ARSessionDelegate {
func session(_ session: ARSession, didUpdate frame: ARFrame) {
let transform = frame.camera.transform
let position = transform.columns.3
print(position.x, position.y, position.z) // UPDATING
}
}
class ViewController: UIViewController {
@IBOutlet var sceneView: ARSCNView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
sceneView.session.delegate = self // ARSESSION DELEGATE
let config = ARWorldTrackingConfiguration()
sceneView.session.run(config)
}
}
RealityKit
In RealityKit, ARView's object contains a camera's transform as well:
import RealityKit
import UIKit
import Combine
class ViewController: UIViewController {
@IBOutlet var arView: ARView!
var subs: [AnyCancellable] = []
override func viewDidLoad() {
super.viewDidLoad()
arView.scene.subscribe(to: SceneEvents.Update.self) { _ in
let camTransform = self.arView.cameraTransform.matrix
print(camTransform) // UPDATING
}.store(in: &subs)
}
}