Кватернионы искажаются или мерцают

Я пытаюсь создать свой собственный класс кватернионов и получаю странные результаты. Либо куб, который я пытаюсь вращать, мерцает как сумасшедший, либо он деформируется.

Это мой код:

void Quaternion::AddRotation(vec4 v)
{
    Quaternion temp(v.x, v.y, v.z, v.w);
    *this = temp * (*this);
}

mat4   Quaternion::GenerateMatrix(Quaternion &q)
{
    q.Normalize();

    //Row order
    mat4 m( 1 - 2*q.y*q.y - 2*q.z*q.z, 2*q.x*q.y - 2*q.w*q.z, 2*q.x*q.z + 2*q.w*q.y, 0,
            2*q.x*q.y + 2*q.w*q.z, 1 - 2*q.x*q.x - 2*q.z*q.z, 2*q.y*q.z + 2*q.w*q.x, 0,
            2*q.x*q.z - 2*q.w*q.y, 2*q.y*q.z - 2*q.w*q.x, 1 - 2*q.x*q.x - 2*q.y*q.y, 0,
            0, 0, 0, 1);

    //Col order
    //  mat4 m( 1 - 2*q.y*q.y - 2*q.z*q.z,2*q.x*q.y + 2*q.w*q.z,2*q.x*q.z - 2*q.w*q.y,0,
    //          2*q.x*q.y - 2*q.w*q.z,1 - 2*q.x*q.x - 2*q.z*q.z,2*q.y*q.z - 2*q.w*q.x,0,
    //          2*q.x*q.z + 2*q.w*q.y,2*q.y*q.z + 2*q.w*q.x,1 - 2*q.x*q.x - 2*q.y*q.y,0,
    //          0,0,0,1);

    return m;
}

Когда я создаю сущность, я даю ей кватернион:

entity->Quat.AddRotation(vec4(1.0f, 1.0f, 0.0f, 45.f));

И каждый кадр я пытаюсь дополнительно повернуть на небольшую величину:

for (int i = 0; i < Entities.size(); i++)
{
    if (Entities[i] != NULL)
    {
        Entities[i]->Quat.AddRotation(vec4(0.5f, 0.2f, 1.0f, 0.000005f));
        Entities[i]->DrawModel();
    }
    else
        break;
}

И, наконец, вот как я рисую каждый куб:

void Entity::DrawModel()
{
    glPushMatrix();

    //Rotation
    mat4 RotationMatrix;
    RotationMatrix = this->Quat.GenerateMatrix(this->Quat);

    //Position
    mat4 TranslationMatrix = glm::translate(mat4(1.0f), this->Pos);

    this->Trans = TranslationMatrix * RotationMatrix;

    glMultMatrixf(value_ptr(this->Trans));

    if (this->shape != NULL)
        this->shape->DrawShape();

    glPopMatrix();
}

EDIT: Это руководство, которое я использовал для изучения кватернионов: http://www.cprogramming.com/tutorial/3d/quaternions.html


person Edvin    schedule 16.09.2013    source источник
comment
Тогда ваш код где-то неверен. Можете ли вы упростить свой тестовый пример и провести модульное тестирование каждого из методов кватерниона? Попробуйте передать простые случаи вручную и проверьте правильность крайних случаев. К сожалению, здесь нет серебряной пули, кроме методичного и разумного кодирования, скорее всего, с помощью вышеупомянутого TDD.   -  person Bartek Banachewicz    schedule 16.09.2013
comment
Да, мой код неверен. Я не на 100% уверен, что понял ваш ответ, мой английский не самый лучший... Я пытался сделать его как можно более простым, отрисовывая только простой куб. Я не знаю, как настроить более простой тестовый пример, извините. Это весь код, который я использую в отношении кватернионов. Спасибо за ответ!   -  person Edvin    schedule 16.09.2013
comment
Более простой код не будет ничего отображать, просто вычислит и выведет числа на очень простых данных, которые вы можете проверить сами; вы также можете попытаться построить эквивалентные преобразования с матрицами и кватернионами (или, что еще лучше, с другой библиотекой кватернионов, которой вы доверяете), а затем проверить, совпадают ли результаты. Надеюсь, это немного прояснит ситуацию.   -  person Bartek Banachewicz    schedule 16.09.2013


Ответы (2)


Не изучая вашу матрицу вращения до конца, я могу придумать две возможные ошибки. Во-первых, ваша матрица вращения R не является ортогональной, т.е. обратная R не равна транспонированной. Это может привести к деформации объекта. Второе место, где можно спрятать ошибку, — это умножение ваших кватернионов.

person Georg Bremer    schedule 16.09.2013
comment
Я проверил. Инверсия != транспонирование. Спасибо, что напомнили, буду разбираться и, надеюсь, найду решение! - person Edvin; 17.09.2013

В матрице вращения ошибка. Попробуйте поменять местами элемент (2,3) на элемент (3,2).

person Derek Ledbetter    schedule 16.09.2013
comment
Это решило мою проблему мерцания! Спасибо! Но теперь я столкнулся с другой проблемой... Объект вращается только вокруг своей оси Y. Я буду разбираться в этом вопросе подробнее. По крайней мере, это легче отлаживать, чем мерцание... - person Edvin; 17.09.2013