您可以尝试直接从偏航/俯仰构造四元数:
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。 Sqrt(x) 可以计算为 exp(ln(x)/2)(这些函数也在 wiki 上)。您也可以尝试将 sqrt 替换为 exp(ln(x)/2*tick*realign_rate) 以平滑恢复向上向量 :) 。或者反其道而行之,稍微简化一下公式:
quat_align_vector(src, dst) = [dot(halfway, dst), cross(halfway, dst)],
halfway = normalized(normalized(src) + normalized(dst))
另见https://stackoverflow.com/a/1171995。
编辑:更正向量,添加约束。