ARKit 获取 ARPlaneAnchor 顶点世界坐标

问题描述

我正在尝试获取 4 个 ARPlaneAnchor 顶点/边世界坐标中的每一个。使用世界坐标的原因是我已经有了用于放置来自命中测试的节点的函数/代码,并且我想使用相同的逻辑放置节点。

基本上,ARPlaneAnchor 只有 2D 相对位置(相对于它的 SCNNode),我试图将每个平面顶点的位置转换为世界坐标,然后使用这些坐标 (x,y,z)在那里放置一个新的 SCNNode/球体。

我不想将子节点添加到锚点的节点并使用锚点的中心来放置它,因为该节点会随着时间而改变。

解决方法

经过一些工作弄清楚了。人们会期望所有这些数学运算都由 ARKit 完成……如果有人找到更好的实现方式,请告诉我!

// helper to create a translation matrix
func translateTransform(_ x: Float,_ y: Float,_ z: Float) -> float4x4 {
    var tf = float4x4(diagonal: SIMD4<Float>(repeating: 1))
    tf.columns.3 = SIMD4<Float>(x: x,y: y,z: z,w: 1)
    return tf
}

@available(iOS 13.0,*)
extension ARPlaneAnchor {
    
    // returns all 4 world coordinates of the given plane
    // (topLeft,topRight,bottomLeft,bottomRight)
    func worldPoints() -> (SCNVector3,SCNVector3,SCNVector3) {
        
        // Get world's updated center
        let worldTransform = transform * translateTransform(center.x,center.z)
        
        let width = extent.x
        let height = extent.z

        let topLeft = worldTransform * translateTransform(-width / 2.0,-height / 2.0)
        let topRight = worldTransform * translateTransform(width / 2.0,-height / 2.0)
        let bottomLeft = worldTransform * translateTransform(-width / 2.0,height / 2.0)
        let bottomRight = worldTransform * translateTransform(width / 2.0,height / 2.0)

       
        let pointTopLeft = SCNVector3(
            x: topLeft.columns.3.x,y: topLeft.columns.3.y,z: topLeft.columns.3.z
        )

        let pointTopRight = SCNVector3(
            x: topRight.columns.3.x,y: topRight.columns.3.y,z: topRight.columns.3.z
        )

        let pointBottomLeft = SCNVector3(
            x: bottomLeft.columns.3.x,y: bottomLeft.columns.3.y,z: bottomLeft.columns.3.z
        )

        let pointBottomRight = SCNVector3(
            x: bottomRight.columns.3.x,y: bottomRight.columns.3.y,z: bottomRight.columns.3.z
        )
        
        return (
            pointTopLeft,pointTopRight,pointBottomLeft,pointBottomRight
        )
    }
}