ARKit – 获取场景中 ARCamera 的当前位置
ARKit – Get current position of ARCamera in a scene
我正在同时学习 ARKit 和 Scenekit,这是一个挑战。
创建 ARWorldTrackingSessionConfiguration 会话后,我想知道是否有人知道在场景会话中获取用户 'camera' 位置的方法。这个想法是我想为用户的当前位置设置动画。
let reaperScene = SCNScene(named: "reaper.dae")!
let reaperNode = reaperScene.rootNode.childNode(withName: "reaper", recursively: true)!
reaperNode.position = SCNVector3Make(0, 0, -1)
let scene = SCNScene()
scene.rootNode.addChildNode(reaperNode)
// some unknown amount of time later
let currentCameraPosition = sceneView.pointOfView?.position
let moveAction = SCNAction.move(to: currentCameraPosition!, duration: 1.0)
reaperNode.runAction(moveAction)
但是,currentCameraPosition 似乎总是 [0,0,0],即使我正在移动相机。知道我做错了什么吗?最终的想法是,我会围绕一个不可见的球体旋转对象,直到它在相机前面,然后对其进行动画处理,做类似的事情:Rotate SCNCamera node looking at an object around an imaginary sphere(这样用户会看到对象朝着他们动画)
感谢您的帮助。
将自己设置为ARSession.delegate
。比你可以实现 session(_:didUpdate:)
,这将为你在会话中处理的每个帧提供 ARFrame
。该框架有一个 camera
属性 ,用于保存有关相机变换、旋转和位置的信息。
func session(_ session: ARSession, didUpdate frame: ARFrame) {
// Do something with the new transform
let currentTransform = frame.camera.transform
doSomething(with: currentTransform)
}
正如 rickster 指出的那样,您始终可以通过调用 session.currentFrame
获得当前 ARFrame
和相机位置。
如果你只需要一次位置,这很有用,例如移动相机所在的节点,但如果你想获得相机位置的更新,你应该使用 delegate
方法。
我知道它已经解决了,但我有一些巧妙的解决方案..
我更喜欢添加渲染器委托方法。这是 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)
}
当然你不能默认添加开箱即用的两个 SCNVector3.. 所以你需要从 class 中粘贴以下
func +(lhv:SCNVector3, rhv:SCNVector3) -> SCNVector3 {
return SCNVector3(lhv.x + rhv.x, lhv.y + rhv.y, lhv.z + rhv.z)
}
ARKit + SceneKit
为方便起见,您可以使用实例方法 session(_:didUpdate:)
创建一个 ViewController
扩展,其中将发生更新。
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
在 RealityKit 中,ARView 的对象也包含相机的变换:
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)
}
}
我正在同时学习 ARKit 和 Scenekit,这是一个挑战。
创建 ARWorldTrackingSessionConfiguration 会话后,我想知道是否有人知道在场景会话中获取用户 'camera' 位置的方法。这个想法是我想为用户的当前位置设置动画。
let reaperScene = SCNScene(named: "reaper.dae")!
let reaperNode = reaperScene.rootNode.childNode(withName: "reaper", recursively: true)!
reaperNode.position = SCNVector3Make(0, 0, -1)
let scene = SCNScene()
scene.rootNode.addChildNode(reaperNode)
// some unknown amount of time later
let currentCameraPosition = sceneView.pointOfView?.position
let moveAction = SCNAction.move(to: currentCameraPosition!, duration: 1.0)
reaperNode.runAction(moveAction)
但是,currentCameraPosition 似乎总是 [0,0,0],即使我正在移动相机。知道我做错了什么吗?最终的想法是,我会围绕一个不可见的球体旋转对象,直到它在相机前面,然后对其进行动画处理,做类似的事情:Rotate SCNCamera node looking at an object around an imaginary sphere(这样用户会看到对象朝着他们动画)
感谢您的帮助。
将自己设置为ARSession.delegate
。比你可以实现 session(_:didUpdate:)
,这将为你在会话中处理的每个帧提供 ARFrame
。该框架有一个 camera
属性 ,用于保存有关相机变换、旋转和位置的信息。
func session(_ session: ARSession, didUpdate frame: ARFrame) {
// Do something with the new transform
let currentTransform = frame.camera.transform
doSomething(with: currentTransform)
}
正如 rickster 指出的那样,您始终可以通过调用 session.currentFrame
获得当前 ARFrame
和相机位置。
如果你只需要一次位置,这很有用,例如移动相机所在的节点,但如果你想获得相机位置的更新,你应该使用 delegate
方法。
我知道它已经解决了,但我有一些巧妙的解决方案.. 我更喜欢添加渲染器委托方法。这是 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)
}
当然你不能默认添加开箱即用的两个 SCNVector3.. 所以你需要从 class 中粘贴以下
func +(lhv:SCNVector3, rhv:SCNVector3) -> SCNVector3 {
return SCNVector3(lhv.x + rhv.x, lhv.y + rhv.y, lhv.z + rhv.z)
}
ARKit + SceneKit
为方便起见,您可以使用实例方法 session(_:didUpdate:)
创建一个 ViewController
扩展,其中将发生更新。
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
在 RealityKit 中,ARView 的对象也包含相机的变换:
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)
}
}