ARKit-从摄像机到锚点的距离

时间:2018-06-19 21:29:24

标签: ios swift arkit

我正在创建一个锚点,并将其添加到摄像机前面一定距离的ARSKView中,如下所示:

func displayToken(distance: Float) {
        print("token dropped at: \(distance)")
        guard let sceneView = self.view as? ARSKView else {
            return
        }

        // Create anchor using the camera's current position
        if let currentFrame = sceneView.session.currentFrame {
            // Create a transform with a translation of x meters in front of the camera
            var translation = matrix_identity_float4x4
            translation.columns.3.z = -distance
            let transform = simd_mul(currentFrame.camera.transform, translation)

            // Add a new anchor to the session
            let anchor = ARAnchor(transform: transform)
            sceneView.session.add(anchor: anchor)
        }
    }

然后为锚创建节点,如下所示:

func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
        // Create and configure a node for the anchor added to the view's session.
        if let image = tokenImage {
            let texture = SKTexture(image: image)
            let tokenImageNode = SKSpriteNode(texture: texture)
            tokenImageNode.name = "token"
            return tokenImageNode
        } else {
            return nil
        }
    }

这很好,我看到图像以适当的距离添加。但是,我要尝试的是计算移动时锚点/节点在相机前面的距离。问题是使用fabs(cameraZ-anchor.transform.columns.3.z)的计算似乎立即停止了。请查看下面我的代码,该代码位于update()方法中,用于计算相机和物体之间的距离:

override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendered
        guard let sceneView = self.view as? ARSKView else {
            return
        }

        if let currentFrame = sceneView.session.currentFrame {
            let cameraZ =  currentFrame.camera.transform.columns.3.z
            for anchor in currentFrame.anchors {
                if let spriteNode = sceneView.node(for: anchor), spriteNode.name == "token", intersects(spriteNode) {
                    // token is within the camera view
                    //print("token is within camera view from update method")
                    print("DISTANCE BETWEEN CAMERA AND TOKEN: \(fabs(cameraZ - anchor.transform.columns.3.z))")
                    print(cameraZ)
                    print(anchor.transform.columns.3.z)
                }
            }
        }
    }

感谢您提供任何帮助,以准确获取相机和锚点之间的距离。

5 个答案:

答案 0 :(得分:4)

4x4变换矩阵的最后一列是平移向量(或相对于父坐标空间的位置),因此您可以通过简单地减去这些向量来获得两个变换之间在三个维度上的距离。

let anchorPosition = anchor.transforms.columns.3
let cameraPosition = camera.transform.columns.3

// here’s a line connecting the two points, which might be useful for other things
let cameraToAnchor = cameraPosition - anchorPosition
// and here’s just the scalar distance
let distance = length(cameraToAnchor)

您正在执行的操作不正确,因为您要减去每个矢量的Z坐标。如果两个点在x,y和z上不同,则仅减去z不会获得距离。

答案 1 :(得分:2)

这个是用于场景工具包的,我还是留在这里。

let end = node.presentation.worldPosition
let start = sceneView.pointOfView?.worldPosition

let dx = (end?.x)! - (start?.x)!
let dy = (end?.y)! - (start?.y)!
let dz = (end?.z)! - (start?.z)!

let distance = sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2))

答案 2 :(得分:2)

使用RealityKit可以实现这种方式。如果您使用的是世界跟踪配置,则您的AnchorEntity对象符合HasAnchoring,这将为您提供target。目标是AnchoringComponent.Target的枚举。它的情况为.world(let transform)。您可以像这样将世界变换与相机的世界变换进行比较:

if case let AnchoringComponent.Target.world(transform) = yourAnchorEntity.anchoring.target {
    let theDistance = distance(transform.columns.3, frame.camera.transform.columns.3)
 }

这花了我一些时间,但我发现其他可能正在使用RealityKit的人可能会从中受益。

答案 3 :(得分:0)

如@codeman上文所述,这是正确的解决方案:

let distance = simd_distance(YOUR_NODE.simdTransform.columns.3, (sceneView.session.currentFrame?.camera.transform.columns.3)!);

答案 4 :(得分:0)

3D距离-您可以检查这些实用程序

class ARSceneUtils {
        /// return the distance between anchor and camera.
        class func distanceBetween(anchor : ARAnchor,AndCamera camera: ARCamera) -> CGFloat {
        let anchorPostion = SCNVector3Make(
            anchor.transform.columns.3.x,
            anchor.transform.columns.3.y,
            anchor.transform.columns.3.z
        )
        let cametaPosition = SCNVector3Make(
            camera.transform.columns.3.x,
            camera.transform.columns.3.y,
            camera.transform.columns.3.z
        )
        return CGFloat(self.calculateDistance(from: cametaPosition , to: anchorPostion))
    }

    /// return the distance between 2 vectors.
    class func calculateDistance(from: SCNVector3, to: SCNVector3) -> Float {
        let x = from.x - to.x
        let y = from.y - to.y
        let z = from.z - to.z
        return sqrtf( (x * x) + (y * y) + (z * z))
    }

}

现在您可以致电:

guard let camera = session.currentFrame?.camera else { return }
let anchor = // you anchor
let distanceAchorAndCamera = ARSceneUtils.distanceBetween(anchor: anchor, AndCamera: camera)