ARKit estimatedVerticalPlane 命中测试获取平面旋转
ARKit estimatedVerticalPlane hit test get plane rotation
我正在使用 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 应用给定的墙方向,这个 post 很好地解释了提供 ARAnchor 的命中测试类型,但对于 estimatedVerticalPlane 它是零。 ().
此外,当我执行 : po hitTestResult.worldTransform 在调试器上时,它会打印 worldTransform 的旋转 91 度等,但我无法从变换中检索它。
我终于通过以下变换从变换中得到了欧拉角,仍然要检查结果的正确性:
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)
}
}
}
我正在使用 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 应用给定的墙方向,这个 post 很好地解释了提供 ARAnchor 的命中测试类型,但对于 estimatedVerticalPlane 它是零。 (
此外,当我执行 : po hitTestResult.worldTransform 在调试器上时,它会打印 worldTransform 的旋转 91 度等,但我无法从变换中检索它。
我终于通过以下变换从变换中得到了欧拉角,仍然要检查结果的正确性:
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)
}
}
}