一些示例:
运动应该像这样:http://360.art.pl/experimental/1/。但是当我使用四元数构建我的播放器时,它没有限制,我不知道如何解决http://360.art.pl/experimental/2/。
您可以尝试直接从偏航/俯仰构建四元数:
q = quat_from_axis_angle(up_vector, yaw) * quat_from_axis_angle(local_right, pitch)
(根据您将它们转换为旋转矩阵的方式,可能需要按相反顺序乘以这些值),或者每次更改它们时重新对齐:
rotated_right = apply_rotation(q, local_right);
projected_right = rotated_right - dot(rotated_right, up_vector) * up_vector;
realign = quat_align_vector(rotated_right, normalized(projected_right));
q = realign * q
projected_right
这里是将 rotated_right
投影到水平面上的投影。在不滚动的情况下,这两个向量必须相同,这意味着 dot(rotated_right, up_vector) = 0
。最后一个方程式是必须满足的实际约束条件。它对 q
是二次的。例如,对于 local_right=(1,0,0)
和 up_vector=(0,0,1)
,它变成了 dot(q*(1i+0j+0k)*conj(q), 0i+0j+1k)=2*x*z-2*w*y=0
,其中 q=w+xi+yi+zk
。
您可以在 http://en.wikipedia.org/wiki/Quaternion 和 http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 找到 quat_from_axis_angle
和 apply_rotation
的公式。至于 quat_align_vector
,一种方法是
quat_align_vector(src, dst) = sqrt([dot(src, dst), cross(src, dst)])
假设 [a, b]
是一个具有实部 a
和虚部 b
的四元数。可以通过计算 exp(ln(x)/2)
(这些函数也在维基上)来计算 Sqrt(x)
。您还可以尝试使用 exp(ln(x)/2*tick*realign_rate)
替换 sqrt,以实现上向量的平滑恢复 :)。或者反过来,简化公式:
quat_align_vector(src, dst) = [dot(halfway, dst), cross(halfway, dst)],
halfway = normalized(normalized(src) + normalized(dst))
另请参阅https://dev59.com/SnM_5IYBdhLWcg3w6HzT#1171995。
编辑:校正向量,添加约束条件。
首先让我描述一下你所说的约束类型。给定一个world_up
向量,您希望限制旋转,使其相对于相机垂直显示。如果相机视图坐标被标记为camera_up
、camera_right
和camera_forward
:
constrain rotation matrix R such that: dot(R*world_up, camera_right) == 0
这可以直接完成(例如,在类似于{{link1:LookAt()
}}的函数中),通过构建一组垂直于视角方向view_forward
的坐标向量来实现:
given vectors: view_forward, world_up
Rot_forward = normalize(view_forward)
Rot_right = normalize( cross(view_forward, world_up) )
Rot_up = cross(Rot_right, Rot_forward)
view_forward
向量而不是四元数会更自然。