如何计算两点之间关于 3-D 相机方向的角度 space
How to calculate the angle in between two points with regards to camera orientation in 3-D space
我目前面临的问题是我想计算从相机位置到目标位置的弧度角。但是,这个计算还需要考虑相机的航向。
例如,当相机背对物体时,函数应该 return π。到目前为止,我编写的函数大部分时间都有效。但是,当用户靠近 X 和 Z 轴时,箭头不再指向目标,而是稍微指向左侧或右侧,具体取决于您处于正 X 轴还是负 X 轴和 z space。
目前,我不确定为什么我的功能不起作用。我对这种行为的唯一解释是万向节锁定。但是我不太确定如何使用四元数实现相同的功能。
我还附上了一些照片post,问题更清楚了。
这是我现在正在使用的功能:
func getAngle() -> Float {
guard let pointOfView = self.sceneView.session.currentFrame else { return 0.0 }
let cameraPosition = pointOfView.camera.transform.columns.3
let heading = getUserVector()
let distance = SCNVector3Make(TargetPosition.x - cameraPosition.x ,TargetPosition.y - cameraPosition.y - TargetPosition.y,TargetPosition.z - cameraPosition.z)
let heading_scalar = sqrtf(heading.x * heading.x + heading.z * heading.z)
let distance_scalar = sqrtf(distance.z * distance.z + distance.z * distance.z)
let x = ((heading.x * distance.x) + (heading.z * distance.z) / (heading_scalar * distance_scalar))
let theta = acos(max(min(x, 1), -1))
if theta < 0.35 {
return 0
}
if (heading.x * (distance.z / distance_scalar) - heading.z * (distance.x/distance_scalar)) > 0{
return theta
}
else{
return -theta
}
}
func getUserVector() -> (SCNVector3) { // (direction)
if let frame = self.sceneView.session.currentFrame {
let mat = SCNMatrix4(frame.camera.transform) // 4x4 transform matrix describing camera in world space
let dir = SCNVector3(-1 * mat.m31, -1 * mat.m32, -1 * mat.m33) // orientation of camera in world space
print(mat)
return dir
}
return SCNVector3(0, 0, -1)
}
以下图为例。右上角的箭头应笔直向上指向中心对象,但它略微指向左侧。当我与 z 轴对齐时,与 x 轴对齐时会发生相同的行为。
我找到了我的问题的答案解决方案是将对象转换为相机的前景,然后简单地使用 atan2 来获得相机和对象之间的角度希望这个 post 会有所帮助未来的读者!
func getAngle() -> Float {
guard let pointOfView = self.sceneView.session.currentFrame else { return 0.0 }
let cameraPosition = pointOfView.camera.transform
let targetPosition = simd_float4x4(targetNode.transform)
let newTransform = simd_mul(cameraPosition.inverse, targetPosition).columns.3
let theta = atan2(newTransform.z, newTransform.y)
return theta + (Float.pi / 2)
}
我目前面临的问题是我想计算从相机位置到目标位置的弧度角。但是,这个计算还需要考虑相机的航向。
例如,当相机背对物体时,函数应该 return π。到目前为止,我编写的函数大部分时间都有效。但是,当用户靠近 X 和 Z 轴时,箭头不再指向目标,而是稍微指向左侧或右侧,具体取决于您处于正 X 轴还是负 X 轴和 z space。
目前,我不确定为什么我的功能不起作用。我对这种行为的唯一解释是万向节锁定。但是我不太确定如何使用四元数实现相同的功能。
我还附上了一些照片post,问题更清楚了。
这是我现在正在使用的功能:
func getAngle() -> Float {
guard let pointOfView = self.sceneView.session.currentFrame else { return 0.0 }
let cameraPosition = pointOfView.camera.transform.columns.3
let heading = getUserVector()
let distance = SCNVector3Make(TargetPosition.x - cameraPosition.x ,TargetPosition.y - cameraPosition.y - TargetPosition.y,TargetPosition.z - cameraPosition.z)
let heading_scalar = sqrtf(heading.x * heading.x + heading.z * heading.z)
let distance_scalar = sqrtf(distance.z * distance.z + distance.z * distance.z)
let x = ((heading.x * distance.x) + (heading.z * distance.z) / (heading_scalar * distance_scalar))
let theta = acos(max(min(x, 1), -1))
if theta < 0.35 {
return 0
}
if (heading.x * (distance.z / distance_scalar) - heading.z * (distance.x/distance_scalar)) > 0{
return theta
}
else{
return -theta
}
}
func getUserVector() -> (SCNVector3) { // (direction)
if let frame = self.sceneView.session.currentFrame {
let mat = SCNMatrix4(frame.camera.transform) // 4x4 transform matrix describing camera in world space
let dir = SCNVector3(-1 * mat.m31, -1 * mat.m32, -1 * mat.m33) // orientation of camera in world space
print(mat)
return dir
}
return SCNVector3(0, 0, -1)
}
以下图为例。右上角的箭头应笔直向上指向中心对象,但它略微指向左侧。当我与 z 轴对齐时,与 x 轴对齐时会发生相同的行为。
我找到了我的问题的答案解决方案是将对象转换为相机的前景,然后简单地使用 atan2 来获得相机和对象之间的角度希望这个 post 会有所帮助未来的读者!
func getAngle() -> Float {
guard let pointOfView = self.sceneView.session.currentFrame else { return 0.0 }
let cameraPosition = pointOfView.camera.transform
let targetPosition = simd_float4x4(targetNode.transform)
let newTransform = simd_mul(cameraPosition.inverse, targetPosition).columns.3
let theta = atan2(newTransform.z, newTransform.y)
return theta + (Float.pi / 2)
}