我需要一个更快的四元数-向量乘法程序来完善我的数学库。目前我正在使用标准公式
到目前为止,我已经实现了三种替代方案以提高速度:
#1,我不知道这个方法是从哪里得到的:
所有三种方法都产生了错误的结果。然而,我注意到了一些有趣的模式。首先,1号和2号方法产生相同的结果。如果将矩阵转置,则3号方法产生与将向量乘以派生矩阵得到的结果相同(我是偶然发现这个规律的,之前我的四元数转矩阵代码假设矩阵是行主序,这是不正确的)。
我的四元数数据存储定义如下:
v' = qv(q^-1)
,这与用四元数制作矩阵后将其与向量相乘得到的结果相同,因此我对其正确性有信心。到目前为止,我已经实现了三种替代方案以提高速度:
#1,我不知道这个方法是从哪里得到的:
v' = (q.xyz * 2 * dot(q.xyz, v)) + (v * (q.w*q.w - dot(q.xyz, q.zyx))) + (cross(q.xyz, v) * q.w * w)
实现为:
vec3 rotateVector(const quat& q, const vec3& v)
{
vec3 u(q.x, q.y, q.z);
float s = q.w;
return vec3(u * 2.0f * vec3::dot(u, v))
+ (v * (s*s - vec3::dot(u, u)))
+ (vec3::cross(u, v) * s * 2.0f);
}
#2,感谢这篇精彩的博客提供思路。
t = 2 * cross(q.xyz, v);
v' = v + q.w * t + cross(q.xyz, t);
实现方式:
__m128 rotateVector(__m128 q, __m128 v)
{
__m128 temp = _mm_mul_ps(vec4::cross(q, v), _mm_set1_ps(2.0f));
return _mm_add_ps(
_mm_add_ps(v, _mm_mul_ps(_mm_shuffle_ps(q, q, _MM_SHUFFLE(3, 3, 3, 3)), temp)),
vec4::cross(q, temp));
}
第三点,来自多个来源,
v' = v + 2.0 * cross(cross(v, q.xyz) + q.w * v, q.xyz);
实现方式:
__m128 rotateVector(__m128 q, __m128 v)
{
//return v + 2.0 * cross(cross(v, q.xyz) + q.w * v, q.xyz);
return _mm_add_ps(v,
_mm_mul_ps(_mm_set1_ps(2.0f),
vec4::cross(
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(q, q, _MM_SHUFFLE(3, 3, 3, 3)), v),
vec4::cross(v, q)),
q)));
}
所有三种方法都产生了错误的结果。然而,我注意到了一些有趣的模式。首先,1号和2号方法产生相同的结果。如果将矩阵转置,则3号方法产生与将向量乘以派生矩阵得到的结果相同(我是偶然发现这个规律的,之前我的四元数转矩阵代码假设矩阵是行主序,这是不正确的)。
我的四元数数据存储定义如下:
union
{
__m128 data;
struct { float x, y, z, w; };
float f[4];
};
我的实现有问题吗,还是我漏掉了什么重要的东西?