首页 文章

ARKit 估计 VerticalPlane 命中测试获得平面旋转

提问于
浏览
3

我正在使用 ARKit 在运行时检测墙壁,当触摸屏幕的某个点时,我会使用类型为.estimatedVerticalPlane 的点击测试。我正在尝试将 Y 旋转应用于与检测到的平面方向相对应的节点。

我想计算旋转:

private func computeYRotationForHitLocation(hitTestResult: ARHitTestResult) -> Float {
    guard hitTestResult.type == .estimatedVerticalPlane else { return 0.0 }
//        guard let planeAnchor = hitTestResult.anchor as? ARPlaneAnchor else { return 0.0 }
//        guard let anchoredNode = sceneView.node(for: planeAnchor) else { return 0.0 }

    let worldTransform = hitTestResult.worldTransform
    let anchorNodeOrientation = ???

    return .pi * anchorNodeOrientation.y
}

如何推断给定墙的方向来应用 anchorNodeOrientation,本文对提供 ARAnchor 的命中测试类型很好地说明了这一点,但对于估计的 VerticalPlane 则为零。 (ARKit 1.5 如何获得垂直平面的旋转)。

另外,当我这样做时:在调试器上安装 hitTestResult.worldTransform 会打印 worldTransform 91 度等的旋转值,但是我无法从转换中获取它。

1 回答

  • 3

    我终于设法通过以下转换从转换中获得了欧拉角,仍然必须检查结果的正确性:

    import SceneKit
    import ARKit
    
    public extension matrix_float4x4 {
    
    /// Retrieve translation from a quaternion matrix
    public var translation: SCNVector3 {
        get {
            return SCNVector3Make(columns.3.x, columns.3.y, columns.3.z)
        }
    }
    
    /// Retrieve euler angles from a quaternion matrix
    public var eulerAngles: SCNVector3 {
        get {
            //first we get the quaternion from m00...m22
            //see http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
            let qw = sqrt(1 + self.columns.0.x + self.columns.1.y + self.columns.2.z) / 2.0
            let qx = (self.columns.2.y - self.columns.1.z) / (qw * 4.0)
            let qy = (self.columns.0.z - self.columns.2.x) / (qw * 4.0)
            let qz = (self.columns.1.x - self.columns.0.y) / (qw * 4.0)
    
            //then we deduce euler angles with some cosines
            //see https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
            // roll (x-axis rotation)
            let sinr = +2.0 * (qw * qx + qy * qz)
            let cosr = +1.0 - 2.0 * (qx * qx + qy * qy)
            let roll = atan2(sinr, cosr)
    
            // pitch (y-axis rotation)
            let sinp = +2.0 * (qw * qy - qz * qx)
            var pitch: Float
            if fabs(sinp) >= 1 {
                pitch = copysign(Float.pi / 2, sinp)
            } else {
                pitch = asin(sinp)
            }
    
            // yaw (z-axis rotation)
            let siny = +2.0 * (qw * qz + qx * qy)
            let cosy = +1.0 - 2.0 * (qy * qy + qz * qz)
            let yaw = atan2(siny, cosy)
    
            return SCNVector3(roll, pitch, yaw)
        }
    }
    }
    

相关问题