ARKit - 获取场景中ARCamera的当前位置

Rya*_*ter 28 augmented-reality scenekit swift arkit

我正在同时学习ARKit和Scenekit,这是一个挑战.

创建了ARWorldTrackingSessionConfiguration会话后,我想知道是否有人知道在场景会话中获取用户"相机"位置的方法.我的想法是想要将对象设置为用户当前位置的动画.

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)
Run Code Online (Sandbox Code Playgroud)

但是,即使我正在移动相机,似乎currentCameraPosition总是[0,0,0].知道我做错了什么吗?最终的想法是我会旋转对象围绕一个看不见的球体,直到它在镜头前,然后动画它,做一些与此类似:旋转SCNCamera节点看着周围的假想球体的对象(这种方式,用户看到对象动画的对象)

谢谢你的帮助.

jls*_*ert 23

把自己定位为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)
}
Run Code Online (Sandbox Code Playgroud)

正如里克斯特指出的那样,你总是可以ARFrame通过调用获得当前和相机的位置session.currentFrame.如果您只需要一次位置,这很有用,例如移动相机所在的节点,但delegate如果您想获得相机位置的更新,则应使用该方法.

  • 这可行,但您也可以通过获取会话的"currentFrame"属性来获取帧而不是会话委托. (4认同)
  • 真正.点是,取决于你的应用程序如何设置,你可以让ARKit为你提供60 fps的帧,你可以在你得到它们时进行渲染,或者你可以运行自己的渲染循环(最高)60 fps并询问每次需要一个框架的ARKit.它支持两种方式,因此请使用您喜欢的方式. (2认同)
  • 这对我来说并不一致。我经常将 (0,0,0) 作为 xyz 坐标。 (2认同)

Moh*_*gab 13

我知道它已经解决但我有一个小巧的解决方案..我会优先添加一个渲染器委托方法..它是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)
}
Run Code Online (Sandbox Code Playgroud)

当然你不能默认添加两个SCNVector3开箱即用..所以你需要粘贴出类以下

func +(lhv:SCNVector3, rhv:SCNVector3) -> SCNVector3 {
     return SCNVector3(lhv.x + rhv.x, lhv.y + rhv.y, lhv.z + rhv.z)
}
Run Code Online (Sandbox Code Playgroud)

  • 对于方向,最好只使用sceneView.pointOfView.presentation.worldOrientation.如果您真的需要从变换中获取它,请查看例如https://gamedev.stackexchange.com/questions/50963/how-to-extract-euler-angles-from-transformation-matrix您应该更喜欢四元数在模糊的欧拉角度. (2认同)

ARG*_*Geo 6

为方便起见,您可以ViewController使用session(_:didUpdate:)将发生更新的实例方法创建扩展。

这是代码:

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, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self                     // ARVIEW DELEGATE
    }   
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let configuration = ARWorldTrackingConfiguration()
        sceneView.session.run(configuration)
        sceneView.session.delegate = self             // ARSESSION DELEGATE
    }
}
Run Code Online (Sandbox Code Playgroud)