四元 - 旋转为

Quaternion - Rotate To

本文关键字:旋转 四元      更新时间:2023-10-16

我在世界空间中有一些对象,假设(0,0,0),想将其旋转以面对(10,10,10)。

我该如何使用四元素?

这个问题没有任何意义。您说您希望一个对象"面对"一个特定的观点,但这并不能提供足够的信息。

首先, face 该方向意味着什么?在OpenGL中,这意味着本地参考框架中的 -Z 轴与某些外部参考框架中的指定方向对齐。为了使这种对齐实现,我们需要知道对象的相关轴目前"面向"的方向。

但是,这仍然无法定义唯一的转换。即使您知道要使 -Z 轴点的方向,该对象仍然可以自由旋转 。这就是为什么函数gluLookAt()要求您提供" AT"方向 an'up'方向的原因。

我们需要知道的下一件事是最终重点需要采用哪种格式?对象的方向通常以四个季度格式存储。但是,如果要以图形方式旋转对象,则可能需要旋转矩阵。

所以让我们做一些假设。我假设您的对象以世界上的 c 为中心,并且具有默认对齐。即,对象的 x y z axes与世界的 x y对齐 z axes。这意味着对象相对于世界的方向可以表示为身份矩阵或身份Quaternion: [1 0 0 0](使用 w 的quaternion juntive,首先是)。

)。 )。

如果您想要最短的旋转,以使对象的 -z 轴与点 p := [p.x p.y p.z],那么您将绕轴旋转 a 。现在,我们将找到这些值。首先,我们通过标准化向量 p-c ,然后使用单位长度 -Z> -Z 向量,然后再次归一化来找到Axis a a :

a = ranstorize(crossproduct( -Z ,normalize( p-c-c )));

>

通过取圆点的逆余弦发现的这两个单位向量之间的最短角度:

φ= acos(dotproduct( -Z ,归一化)

不幸的是,这是两个向量形成的角度的绝对值的度量。我们需要弄清楚围绕 a 旋转时是正还是负。必须有一种更优雅的方法,但是想到的第一种方法是找到一个垂直于 a -Z> -Z 的第三个轴它的点产物与我们的目标轴。VIS:

B = CrossProduct( A -Z> -Z );

if(dotproduct( b ,归一化( p -c -c ))< 0)φ=-φ;

一旦我们拥有轴和角度,就很容易将其变成四元素:

q = [cos(φ/2)sin(φ/2) a ];

这个新的四个四基因代表对象的新方向。它可以用于渲染目的的矩阵转换为矩阵,也可以使用Quaternion乘法规则直接使用它来直接旋转对象的顶点。

可以在OGRE :: vector3类的OGRE源代码中找到代表两个向量之间旋转的四个旋转的示例。

为了响应您的澄清,为了回答这个问题,我无耻地复制了一种非常有趣且整洁的算法,用于在两个向量之间找到Quat,这些向量看起来像我从未从这里从这里见过。从数学上讲,这似乎是有效的,并且由于您的问题是关于其背后的数学,所以我敢肯定您可以将此伪代码转换为C 。

quaternion q;
vector3 c = cross(v1,v2);
q.v = c;
if ( vectors are known to be unit length ) {
    q.w = 1 + dot(v1,v2);
} else {
    q.w = sqrt(v1.length_squared() * v2.length_squared()) + dot(v1,v2);
}
q.normalize();
return q;

让我知道您是否需要帮助澄清该伪代码的任何位。

应该很简单。
dot(a,b) = a1*b1 + a2*b2 + ... + an*bn

cross(a,b) = well, the cross product. it's annoying to type out and
can be found anywhere.

您可能需要使用SLERP(球形线性插值)。请参阅本文以获取有关如何在C

中进行的参考。