有一种方法可以在不使用矩阵或向量的情况下完成此操作,类似于this numpy implementation。我们可以将经度/纬度视为两个四元数旋转组合在一起。
让我们使用一个Z-up右手坐标系。我们称经度为φ,纬度为θ,并将由这两个值表示的点称为(φ, θ)。为了可视化,红轴对应X,绿色对应Y,蓝色对应Z。
我们想要找到表示从红色的(0, 0)旋转到绿色的(a, b)的四元数:
我们可以将这个旋转表示为先经度旋转,然后是纬度旋转的组合,如下所示: 首先,我们沿着Z轴旋转了a,这将转换X和Y轴。然后,我们沿着新的本地Y轴旋转了b。因此,我们知道了该旋转的两组轴/角度信息。(cos(α/2), ω.x*sin(α/2), ω.y*sin(α/2), ω.z*sin(α/2))
因此,第一次旋转由绕世界坐标系(0, 0, 1)轴旋转a度表示,结果如下:
q1 = (cos(a/2), 0, 0, sin(a/2))
q2 = (cos(b/2), 0, sin(b/2), 0)
q2*q1 = (cos(a/2)cos(b/2), -sin(a/2)sin(b/2), cos(a/2)sin(b/2), sin(a/2)cos(b/2))
虽然这没什么意义,但我们可以确认这个公式与之前提到的numpy实现是相同的。
JCooper提出了一个很好的观点,即在这种情况下,仍然有一个自由度留给X轴。如果θ保持在±90度范围内,我们可以想象Z轴始终指向上方。这会限制X轴旋转并希望这正是您想要的。
希望这能帮到您!
编辑:请注意,这与使用2个欧拉角进行操作基本相同。因此,要撤销此转换,可以使用任何四元数到欧拉角的转换,前提是旋转顺序相同。
仅有经度和纬度无法描述四元数。经度和纬度可以描述三维球面上的一个点。假设这是一个法向量直接指向屏幕的点。你还有一个自由度。球体可以围绕由lat-lon指定的点的法向量旋转。如果你想要一个表示球体方向的四元数,你需要完全指定旋转。
所以假设你想要保持球体的北极朝上。如果北极与物体的+z轴对齐,并且屏幕上的“上”与世界的+y轴对齐,然后你想要旋转球体,使得球面上的点R直接指向屏幕(其中R是使用经纬度转欧几里得坐标系找到的),那么你可以按照以下方式创建旋转矩阵。
您想让对象的R与世界的+z(假设是类似于OpenGL的视图坐标系)对齐,并且您希望对象的+z尽可能地与世界的+y对齐。我们需要第三个轴;因此,我们规范化R,然后找到:P = crossP([0 0 1]^T,R)。我们规范化P,然后将正交性强加到第二个轴上:Q = crossP(R,P)。最后,规范化Q。现在,我们有3个正交向量P,Q,R,我们希望它们分别与世界的x,y,z对齐。
我假设P,Q和R是列向量;因此,要创建一个变换矩阵,我们只需将它们粘在一起:M = [P Q R]。现在M是将世界坐标中的点转换为对象坐标的矩阵。要走相反的方向,我们找到M的逆。幸运的是,当矩阵的列正交时,逆矩阵与转置矩阵相同。所以我们得到:
[ P^T ]
M^-1 = M^T = [ Q^T ]
[ R^T ]
从那里开始,如果需要的话,您可以使用矩阵转四元数找到一个四元数。然后,您可以使用slerp或您选择的方法在四元数之间进行插值。
也许你可以研究一下boost C++库是如何实现它的。(或者甚至使用它) http://www.boost.org/doc/libs/1_46_0/libs/math/doc/quaternion/html/boost_quaternions/quaternions/create.html
经度和纬度在很大程度上类似于球面坐标系中的方位角(θ-[0,2*PI])和倾角(ρ?[0,PI])角度(当然表面半径r=1)。Boost在我发布的链接中有一个用于球面到四元数的函数。