Более быстрое умножение кватернионных векторов не работает
Мне нужна более быстрая процедура умножения кватернионных векторов для моей математической библиотеки. Щас использую каноническийv' = qv(q^-1)
, который дает тот же результат, что и умножение вектора на матрицу из кватерниона, так что я уверен в его правильности.
До сих пор я реализовал 3 альтернативных «более быстрых» метода:
# 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));
}
И № 3, из многочисленных источников,
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)));
}
Все 3 из них дают неверные результаты. Однако я заметил некоторые интересные закономерности. Прежде всего, # 1 и # 2 дают одинаковый результат. # 3 дает тот же результат, который я получаю при умножении вектора на производную матрицу, если указанная матрица транспонирована (я обнаружил это случайно, ранее мой код из матрицы «четверть в матрицу» предполагал матрицы основных строк, что было неверно).
Хранение данных моих кватернионов определяется как:
union
{
__m128 data;
struct { float x, y, z, w; };
float f[4];
};
Мои реализации несовершенны, или я что-то здесь упускаю?