假设您有一个摄像机投影矩阵,即摄像机平移矢量+旋转四元数,就像每个典型的摄像机一样,它可以向任何方向移动和旋转。并且无论它向前,向上还是向下,我都需要显示一个类似指南针的指示器,指向相机所针对的位置。
问题在于,当摄像机指向下方时,摄像机围绕其旋转的光学中心定义了罗盘的值,但是当摄像机指向前方时,摄像机围绕它旋转的中心不再影响罗盘的价值,在这种情况下,摄像机的方向定义罗盘的值。
当相机向下倾斜45度时,它会变得更加难看,在这种情况下,相机中心周围的旋转是否会影响罗盘的旋转,这一点甚至不清楚。
那么有一种优雅的方法可以根据任意相机投影矩阵/四元数得到罗盘值吗?
提前谢谢!
答案 0 :(得分:2)
如果你只想指向目标的箭头:
Transform camera = Camera.main.transform;
Transform target = Target.transform;
Vector3 relativePosition = target.position - camera.position;
Vector3 targetRelative = Vector3.ProjectOnPlane(relativePosition, camera.forward);
float angle = Angle360(camera.up, targetRelative, camera.forward);
Compass.transform.rotation = Quaternion.Euler(0, 0, angle);
角度函数是:
float Angle360(Vector3 from, Vector3 to, Vector3 normal)
{
float dot = Vector3.Dot(from, to);
float det = Vector3.Dot(normal, Vector3.Cross(from, to));
return Mathf.Atan2(det, dot)*Mathf.Rad2Deg;
}
以下是如何在世界空间中获取指南针的方向:
在XZ平面上投影摄像机方向和目标位置
Transform camera = Camera.main.transform;
Transform target = Target.transform;
Vector3 cameraWorldDirXZ = Vector3.ProjectOnPlane(camera.forward, Vector3.up).normalized;
Vector3 targetWorldDirXZ = Vector3.ProjectOnPlane(target.position, Vector3.up).normalized;
cameraWorldDirXZ
和targetWorldDirXZ
之间的角度是指南针的角度。
但我不认为这会像你认为的那样。这为您提供了围绕camera.forward
轴旋转y
向量以面向目标所需的角度。如果围绕camera.forward
进行旋转,则不要更改camera.forward
向量或y
轴,以免指南针发生变化。
您可能想在本地空间尝试指南针。为此你投影到相机XZ平面:
Vector3 cameraLocalDirXZ = camera.forward;
Vector3 targetLocalDirXZ = Vector3.ProjectOnPlane(target.position, camera.up).normalized;
cameraLocalDirXZ
和targetLocalDirXZ
之间的角度再次是罗盘针的角度。这为您提供了在camera.forward
周围camera.up
旋转以面向目标所需的角度。请注意,当您围绕camera.forward
进行旋转时,它会更改camera.up
,因此它会更改指南针方向。
答案 1 :(得分:1)
如果有人偶然发现这个问题,解决方法(感谢@Pluto)非常简单,将相机四元数乘以三个轴向量(0,0,1),(0,1,0),(1,0) ,0),你将得到三个矢量来定义你的相机的坐标系,将这三个矢量投影到你的平面上,找到你的三个投影点的质心,并且你有罗盘方向。
以下是这段代码:
def f(row):
phone_numbers_59 = phone_data['Number'].tolist()
callid = phone_data['CALL ID'].tolist()
get_callid = []
for i in range(0, len(phone_numbers_59)):
if any([x in phone_numbers_59[i] for x in row['Numbers']]):
get_callid.append(callid[i])
if len(get_callid) > 0:
return get_callid
else:
return "NA"
s = data.apply(f, axis=1)