四元数 - 旋转到

Pee*_*eeS 4 c++ math quaternions

我在世界空间中有一些物体,让我们说(0,0,0)并想要将它旋转到面(10,10,10).

我如何使用四元数?

JCo*_*per 8

这个问题没有多大意义.你说你希望一个对象"面对"一个特定的点,但这并不能提供足够的信息.

首先,面对这个方向意味着什么?在OpenGL中,这意味着本地参考帧中的-z轴与某些外部参考帧中的指定方向对齐.为了实现这种对齐,我们需要知道对象的相关轴当前"面向"的方向.

但是,这仍然没有定义一个独特的转变.即使您知道使-z轴指向哪个方向,对象仍然可以围绕该轴旋转.这就是为什么函数gluLookAt()要求你提供'at'方向 'up'方向.

我们需要知道的下一件事是最终结果需要采用什么格式?对象的方向通常以四元数格式存储.但是,如果要以图形方式旋转对象,则可能需要旋转矩阵.

所以让我们做一些假设.我假设您的对象位于世界的点c并且具有默认对齐方式.即,对象的x,yz轴与世界的x,yz轴对齐.这意味着对象相对于世界的方向可以表示为单位矩阵或标识四元数:( [1 0 0 0]使用四元数约定,其中w首先出现).

如果你想要最短的旋转将对象的-z轴与点p:= [px py pz] 对齐,那么你将围绕轴a旋转φ .现在我们将找到这些价值观.首先,我们通过归一化矢量pc找到轴a,然后将单位长度为-z矢量的交叉积,然后再次归一化:

a = normalize(crossProduct(-z,normalize(pc)));

通过取其点积的反余弦得到的这两个单位向量之间的最短角度:

φ= acos(dotProduct(-z,normalize(pc)));

不幸的是,这是由两个矢量形成的角度的绝对值的量度.我们需要弄清楚它是否围绕旋转时的积极或消极的一个.必须有一种更优雅的方式,但首先想到的方法是找到第三个轴,垂直于a-z,然后从它的点积中取出符号和目标轴.可见:

b = crossProduct(a,-z);

if(dotProduct(b,normalize(pc))<0)φ=-φ;

一旦我们获得了轴和角度,将其转换为四元数很容易:

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

这个新的四元数代表了对象的新方向.它可以转换为矩阵以进行渲染,或者如果需要,可以使用它直接旋转对象的顶点,使用四元数乘法规则.