ARKit估算垂直平面命中测试获取平面旋转。

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的命中测试类型进行了很好的解释,但对于estimatedVerticalPlane则为nil。(ARKit 1.5如何获取垂直平面的旋转)。
此外,当我在调试器上执行:po 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)
    }
}
}

最后的向量不应该是滚动、俯仰、偏航吗? - BlackMirrorz
可能我们应该模仿eulerAngles中的顺序进行设置,我现在没有时间检查,你能确认一下吗?这样我就可以更新返回值了。 - michael-martinez
好的,我认为它看起来还不错 :) - michael-martinez
谢谢,目前还是相当实验性的,我们需要确认不同用例下是否正确表示了检测到的墙壁,即偏航角值是否代表实际的偏航角度(大多数情况下,这将是放置平面的唯一有用信息)。 - michael-martinez
@michael-martinez 你好,能否说明一下这个是如何使用的?在调用computeYrotationOnHitLocation之后,你只需要执行hittest.transform.eulerAngles吗? 然后将返回的角度应用于你想要放置的几何体上? - mushcraft
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接