Более быстрое умножение кватернионных векторов не работает

Мне нужна более быстрая процедура умножения кватернионных векторов для моей математической библиотеки. Щас использую канонический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];
};

Мои реализации несовершенны, или я что-то здесь упускаю?

Ответы на вопрос(1)

Ваш ответ на вопрос