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

时间:2017-07-13 14:50:24

标签: swift scenekit augmented-reality 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)

然而,即使我在移动相机,似乎currentCameraPosition总是[0,0,0]。知道我做错了什么吗?最终我的想法是,我会围绕一个不可见的球体旋转对象,直到它在摄像机前面,然后为其设置动画,执行与此类似的操作:Rotate SCNCamera node looking at an object around an imaginary sphere(这样用户可以看到对象向它们生成动画)

感谢您的帮助。

3 个答案:

答案 0 :(得分:22)

将自己设为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所指出的那样,通过调用ARFrame,您始终可以通过它获取当前session.currentFrame和相机位置。 如果您只需要一次位置,这很有用,例如移动相机所在的节点,但如果您想获得相机位置的更新,则应使用delegate方法。

答案 1 :(得分:12)

我知道它已经解决但我有一个小巧的解决方案.. 我会优先添加一个渲染器委托方法..它是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开箱即用..所以你需要粘贴出类以下

func +(lhv:SCNVector3, rhv:SCNVector3) -> SCNVector3 {
     return SCNVector3(lhv.x + rhv.x, lhv.y + rhv.y, lhv.z + rhv.z)
}

答案 2 :(得分:2)

为方便起见,您可以使用实例方法ViewController创建一个session(_:didUpdate:)扩展名。这是代码:

extension ViewController: ARSessionDelegate {

    func session(_ session: ARSession, didUpdate frame: ARFrame) {
        let transform = currentFrame.camera.transform 
        print("Updates")                               // 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
    }
}