如何计算三维空间中相机方向的两点之间的角度

问题描述 投票:0回答:1

我目前面临的问题是我想要计算从相机位置到目标位置的弧度角度。但是,此计算也需要考虑相机的前进方向。

例如,当相机背向物体时,该功能应返回π。到目前为止,我编写的函数大部分时间都在工作。然而,当用户接近X轴和Z轴时,箭头不再指向目标,而是略微指向左侧或右侧,这取决于您是否处于正X或Z空间。

目前,我不确定为什么我的功能不起作用。我对此行为的唯一解释是万向节锁定。但是我不太确定如何使用四元数实现相同的功能。

我还在这篇文章中附上了一些照片,这个问题有点清楚了。

这是我现在正在使用的功能:

 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轴对齐时会发生相同的行为。

enter image description here

swift math transformation arkit scncamera
1个回答
0
投票

我想出了我的问题的答案,解决方案是将对象转换为相机的预期,然后只需使用atan2获取相机和物体之间的角度,希望这篇文章能够帮助未来的读者!

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)

}
© www.soinside.com 2019 - 2024. All rights reserved.