От кватернионов до вращений OpenGL - PullRequest
11 голосов
/ 29 октября 2011

У меня есть объект, который я хочу вращать с помощью клавиш.Объект должен рыскать, качаться и катиться.После долгих попыток я понял, что glRotate имеет свои ограничения, и реализовать такую ​​функцию с помощью этой функции будет невозможно.

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

Я читал о кватернионах и довольно хорошо их понимал, но как реализовать их в моей программе OpenGLдо сих пор загадкаКто-нибудь знает маленький пример?Не о том, как реализовать класс кватернионов, а о том, как его использовать.Я не понимаю, как собрать все воедино.

Ответы [ 2 ]

9 голосов
/ 29 октября 2011

Вы можете легко строить матрицы вращения из единичных кватернионов .

При заданном кватернионе единицы a + bi + cj + dk вы можете построить следующие 3x3матрица:

The matrix

Добавьте последнюю строку и столбец, взятые из единичной матрицы 4x4, glMultMatrix и все готово:)

4 голосов
/ 29 октября 2011

Наиболее важным является реализация метода, который будет строить матрицы вращения из кватернионов.Затем, как и в случае с обычной матрицей вращения, просто умножьте ее на матрицу вида модели.

Это простой пример, который использовался для вращения куба движением мыши.Как видите, мне нужно было реализовать три метода: toMatrix, quaternionFromAxis, multiplyWith.Предполагая, что вы понимаете кватернионы, должно быть ясно, что они делают.

void display() {

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushMatrix();

    // Multiply quaternion with current modelview matrix    
    glMultMatrixf(cameraQuaternion.toMatrix());

    // Some other transformations
    glTranslatef(-0.5f, -0.5f, -0.5f);

    // Draw something, i.e. cube
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glDrawArrays(GL_TRIANGLES, 0, 36);

    glPopMatrix();
}

void mouseMoved(float dx, float dy) {
    float axisY[] = { 0, 1, 0 },
          axisX[] = { 1, 0, 0 };

    float sensitivity = 0.005f;
    Quaternion *q1 = Quaternion.quaternionFromAxis(axisY, dx * sensitivity];
    Quaternion *q2 = Quaternion.quaternionFromAxis(axisX, dy * sensitivity];

    // Multiply two quaternions with camera
    cameraQuaternion = (q1.multiplyWith(q2)).multiplyWith(cameraQuaternion);
}
...