【问题标题】:ARKit – Get current position of ARCamera in a sceneARKit – 获取场景中 ARCamera 的当前位置
【发布时间】:2017-12-18 10:42:42
【问题描述】:

我正在同时学习 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(这样用户会看到对象向他们移动)

感谢您的帮助。

【问题讨论】:

    标签: swift scenekit augmented-reality arkit


    【解决方案1】:

    将自己设置为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 方法。

    【讨论】:

    • 这可行,但您也可以通过获取会话的 currentFrame 属性来获取帧,而无需成为会话代表。
    • @rickster 你很紧张,我已经编辑了答案,但通常你想让其他节点对你改变你的位置做出反应,例如跟随你。无论如何,您都希望不断更新新的相机姿势。
    • 是的。关键是,根据您的应用程序的其他设置方式,您可以让 ARKit 以 60 fps 的速度为您提供帧并在获得它们时进行渲染,或者您可以以(最高)60 fps 运行您自己的渲染循环并询问每次您需要一个框架时,ARKit 都会提供一个框架。它支持这两种方式,所以使用任何你喜欢的方式。
    • 这对我来说并不一致。我经常将 (0,0,0) 作为 xyz 坐标。
    • 有谁知道变换矩阵中的所有值是什么?他们很难弄清楚。
    【解决方案2】:

    我知道它已经解决了,但我有一个巧妙的解决方案.. 我更喜欢添加一个渲染器委托方法。它是 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)
    }
    

    【讨论】:

    • 为什么只取旋转矩阵的对角线项?为什么“位置”等于“方向+位置”。位置是位置,即变换的最后一列。左上角的 3x3 矩阵包含方向(可能还有比例和剪切)。有不同的方法可以从中提取俯仰、偏航和滚动,但对角线不是其中之一。
    • @kjyv 你在哪里看到位置是变换的最后一列?感谢分享!
    • @kjyv 是 transform.m33 for orientation 应该是 -transform.m33
    • 对于方向,最好只使用sceneView.pointOfView.presentation.worldOrientation。如果您真的需要从转换中获取它,请查看例如这里gamedev.stackexchange.com/questions/50963/…你应该更喜欢四元数而不是模棱两可的欧拉角。
    • 这在很多层面上都是错误的 - 变换的方向包含在 3x3 矩阵中,而不仅仅是对角线条目。位置就是位置
    【解决方案3】:

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

    代码如下:

    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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-12-20
      • 1970-01-01
      • 1970-01-01
      • 2021-05-16
      • 2017-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-04
      相关资源
      最近更新 更多