Как вращать вокруг центра экрана с помощью кватернионов в opengl?

Я пытаюсь реализовать вращение арбола / трекбола, но у меня проблема с центром вращения. Я хочу, чтобы центр был центром моего экрана, несмотря ни на что.

Позвольте мне объяснить, что я сделал до сих пор.

Я создал кватерион (ось вращения: vector_start x vector_end, угол: vector_start * vector_end)

Из этого кватерниона я создал матрицу вращения, чтобы использовать ее с glMultMatrixf (matrix) и получить желаемое вращение.

Проблема в том, что, хотя моя модель, кажется, вращается как шаровой шар, как и должно, она всегда вращается вокруг своей локальной исходной точки. Как я могу заставить его вращаться вокруг центра моего экрана независимо от того, где находится его локальное начало?

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


person Community    schedule 09.12.2009    source источник


Ответы (2)


Вы должны решить эту проблему, применив матрицы вращения и перемещения в правильном порядке. В вашем коде вы можете перевести обратно в исходную точку T (-pos_x, -pos_y, -pos_z), применить ваше вращение и снова перевести в центр объекта T (pos_x, pos_y, pos_z). Это должно работать в целом, независимо от того, как построена ваша матрица вращения.

person catchmeifyoutry    schedule 09.12.2009
comment
Да, но когда я применяю glMultMatrixf (), opengl не поворачивает модель вокруг своего локального источника? Поэтому, если я переведу на начало координат поворота (не используя glRotatef (), а glMultMatrix ()), а затем переведу обратно, моя модель будет снова повернута вокруг своей исходной точки, а не так, как если бы ее исходная точка была, например, центром экрана. - person ; 09.12.2009
comment
Переведите с помощью glTranslatef (), затем умножьте на свою матрицу вращения glMultMatrix () и снова переведите обратно с помощью glTranslatef (). Это в отличие от простого вызова glMultMatrix (). Это не работает? - person catchmeifyoutry; 09.12.2009
comment
Нет, не работает. Что он делает, так это то, что он вращает модель, как указано в матрице вращения, применяемой glMultMatrixf, но вокруг ее локального источника. Я попытался преобразовать кватернион вращения в углы Эйлера, а затем применить glRotatef (Yaw, 0., 0., 1.); glRotatef (Pich, 0., 1., 0.); glRotatef (Roll, 1., 0., 0.); вместо прямого применения glMultMatrixf (), но тогда, когда вращение происходило вокруг центра экрана, оно не имело ничего общего с вращением арбузного шара! - person ; 10.12.2009
comment
Я тоже пробовал работать только с матрицами трансформации, но с теми же результатами! Я создал матрицу перевода в центр, скажем, A, затем матрицу поворота с помощью QuatMatrix * LastRotation, а затем матрицу перевода, которая соответствует тому месту, где я был раньше, скажем B. Итак, моя окончательная матрица преобразования: Final = B * QuatMatrix * LastRotation * A. Наконец, примените glMultMatrix (Final), но результат был таким же вращением вокруг локального источника моей модели. - person ; 10.12.2009

Вот код, который я написал некоторое время назад для программы просмотра запуска трехступенчатой ​​ракеты. Я получил большую часть информации из http://www.euclideanspace.com/maths/geometry/rotations

Примечание: рыскание, тангаж и крен могут измениться для вас в зависимости от того, как вы настроили систему координат.

      // Assuming the angles are in radians.
            double p = curPitch * Math.PI/180.0 / 2.0;
            double y = curYaw * Math.PI/180.0 / 2.0;
            double r = curRoll * Math.PI/180.0 / 2.0;

            double sinp = Math.sin(p);
            double siny = Math.sin(y);
            double sinr = Math.sin(r);
            double cosp = Math.cos(p);
            double cosy = Math.cos(y);
            double cosr = Math.cos(r);

            Vector3 axis = new Vector3();

            //here's the important part: how you get your quaternion vector!
            axis.x = sinr * cosp * cosy - cosr * sinp * siny;
            axis.y = cosr * sinp * cosy + sinr * cosp * siny;
            axis.z = cosr * cosp * siny - sinr * sinp * cosy;

            //now normalize the vector in case we want to use it again later
            axis = Vector3.normalizeVector(axis);

            orientation[1] = axis.x;
            orientation[2] = axis.y;
            orientation[3] = axis.z;

            //w is omega: the angle to rotate about the quaternion
            double w = cosr * cosp * cosy + sinr * sinp * siny;

            w = Math.acos(w) * 2.0;

            orientation[0] = w;

            gl.glPushMatrix();

              //translate object first, then rotate it.
              gl.glTranslated(curDisplacement[0] + saveDisplacement[0], -curDisplacement[1] + saveDisplacement[2], curDisplacement[2] + saveDisplacement[1]);

              //this order might be messed up because I screwed up my coordinate system, but the idea is still there
              gl.glRotated(orientation[0]*180/Math.PI, orientation[2]*180/Math.PI, orientation[3]*180/Math.PI, orientation[1]*180/Math.PI);

             //place your objects
             gl.glPopMatrix();

Надеюсь это поможет!

person bkritzer    schedule 18.12.2009