Answers:
内森·里德(Nathan Reed)和泰德隆(teodron)暴露后,将向量v旋转单位长度四元数q的公式为:
1)从v中创建一个纯四元数p。这仅意味着添加第四个坐标0:
2)将其与q预乘,并将其与共轭q *后乘:
3)这将导致另一个纯四元数,可以将其转换为向量:
该向量被旋转了。
这是可行的,但远非最佳。四元数乘法意味着无数次操作。我对诸如此类的各种实现感到很好奇,并决定查找这些实现来自何处。这是我的发现。
我们还可以将q描述为3维向量u和标量s的组合:
根据四元数乘法的规则,并且由于单位长度四元数的共轭只是反函数,所以我们得到:
标量部分(椭圆)为零,如此处所述。有趣的是矢量部分,也就是我们的旋转矢量v'。可以使用一些基本的向量身份进行简化:
现在这更加理想 ; 两个点积,一个叉积和一些附加项:大约一半的业务量。这将在源代码中给出类似的内容(假设一些通用的矢量数学库):
void rotate_vector_by_quaternion(const Vector3& v, const Quaternion& q, Vector3& vprime)
{
// Extract the vector part of the quaternion
Vector3 u(q.x, q.y, q.z);
// Extract the scalar part of the quaternion
float s = q.w;
// Do the math
vprime = 2.0f * dot(u, v) * u
+ (s*s - dot(u, u)) * v
+ 2.0f * s * cross(u, v);
}
vprime = v + ((cross(u, v) * s) + cross(u, cross(u, v)) * 2.0f
这是否是类似的优化?它看起来有些相似,但并不相同-它仅使用叉积,不使用点积。原始源代码可以在官方GLM存储库的type_quat.inl文件中找到,该文件中包含operator*
一个四元数和一个矢量(vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v)
)
首先,q ^(-1)不是-q / magnitude(q); 它是q * /(magnitude(q))^ 2(q *是共轭;除实数之外的所有分量)。当然,如果所有四元数都已经归一化(通常在旋转系统中),则可以按量级进行除法运算。
至于与向量的乘积,您只需通过将quat的实数分量设置为零并将其ijk分量设置为向量的xyz来将向量扩展为四元数。然后,执行四元数乘法以获得v',然后再次提取ijk分量。(v'的实部应始终为零,加上或减去一些浮点误差。)
第一个观察结果:的逆q
不是-q/magnitude(q)
,那是完全错误的。四元数的旋转意味着这些4D复数等价物具有统一范数,因此位于该4D空间中的S3单位球体上。quat是一元的事实意味着其范数是norm(q)^2=q*conjugate(q)=1
,这意味着quat的逆是其共轭。
如果单位四元数写为q=(w,x,y,z)
=(cos(t),sin(t)v),则其共轭数conjugate(q)=(w,-x,-y,-z)
==(cos(t),-sin(t)v),其中t是旋转角的一半,而v是旋转轴(当然是单位矢量)。
当那个汉密尔顿花花公子决定使用更高维度的复数等价物时,他还偶然发现了一些不错的性质。例如,如果您使用一个完全纯的四元数q=(0,x,y,z)
(没有标量部分w!),则可以认为该废话是矢量(实际上是人们可能将其称为S3球的赤道的quat)。 !-如果我们考虑当今19世纪人们在技术上受到的损害在我们看来似乎是弯曲的东西,那么请多加注意。因此,汉密尔顿以quat形式获取了该矢量:v=(0,x,y,z)
考虑了quat 的几何特性,进行了一系列实验。
INPUT: _v=(x,y,z)_ a random 3D vector to rotate about an __u__ unit axis by an angle of _theta_
OUTPUT: q*(0,_v_)*conjugate(q)
哪里
q = (cos(theta/2), sin(theta/2)*u)
conjugate(q) = inverse(q) = (cos(theta/2), -sin(theta/2)*u)
norm(q)=magnitude(q)=|q|=1
观察:q *(0,v)* conj(q)必须是(0,v')形式的另一个夸脱。我不会详细解释为什么会发生这种情况,但是如果您通过这种方法旋转一个纯虚构的四元数(在我们的例子中是一个矢量!),那么您必须得到一个类似的对象:纯虚构的四元数。 ...,您将其虚构的部分作为结果。有了它,带螺母壳的四元数旋转的奇妙世界。
注意:对于那些使用过分使用的短语的人:quats很好,因为它们避免了'em gimbal lock ..应该首先释放他们的想象力!!夸脱仅仅是“优雅的”数学工具,可以通过使用其他方法完全避免,我发现在几何上完全等效的是轴角方法。
代码:我喜欢的C ++库非常简单,但具有3D图形实验人员所需的所有矩阵,矢量和quat操作,而不必花费超过15分钟的时间来学习。如果您不是C ++新手,则在15分钟内完成。祝好运!
这是通过四元数转换向量的另一种方法。这是MS在xna框架中执行此操作的方式。 http://pastebin.com/fAFp6NnN
我尝试手工解决此问题,并提出了以下等式/方法:
// inside quaterion class
// quaternion defined as (r, i, j, k)
Vector3 rotateVector(const Vector3 & _V)const{
Vector3 vec(); // any constructor will do
vec.x = 2*(r*_V.z*j + i*_V.z*k - r*_V.y*k + i*_V.y*j) + _V.x*(r*r + i*i - j*j - k*k);
vec.y = 2*(r*_V.x*k + i*_V.x*j - r*_V.z*i + j*_V.z*k) + _V.y*(r*r - i*i + j*j - k*k);
vec.z = 2*(r*_V.y*i - r*_V.x*j + i*_V.x*k + j*_V.y*k) + _V.z*(r*r - i*i - j*j + k*k);
return vec;
}
如果有人愿意查看我使用的http://pastebin.com/8QHQqGbv的 mt派生,我将不胜感激,我建议将其复制到支持侧面滚动的文本编辑器中
用我的记法,我用q ^(-1)表示共轭(而不是逆)和不同的标识符,但我希望它是可以遵循的。我认为多数是正确的,尤其是在证明向量的实部会消失的地方。