Вращение камеры в OpenGL без использования glRotate glLookAt

Я пытаюсь написать собственную функцию поворота камеры в OpenGL, но не могу ее запустить. Моя камера в основном взята из flipcode с небольшими изменениями:

Код камеры:

Camera::Camera(float x, float y, float z) {
    memset(Transform, 0, 16*sizeof(float));
    Transform[0] = 1.0f;
    Transform[5] = 1.0f;
    Transform[10] = 1.0f;
    Transform[15] = 1.0f;
    Transform[12] = x; Transform[13] = y; Transform[14] = z;

    Left=&Transform[0];
    Up=&Transform[4];
    Forward=&Transform[8];
    Position=&Transform[12];

    old_x = 0;
    old_y = 0;
}

Вид устанавливается перед каждым визуализируемым кадром:

void Camera::setView() {

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    float viewmatrix[16]={//Remove the three - for non-inverted z-axis
                          Transform[0], Transform[4], -Transform[8], 0,
                          Transform[1], Transform[5], -Transform[9], 0,
                          Transform[2], Transform[6], -Transform[10], 0,

                          -(Transform[0]*Transform[12] +
                          Transform[1]*Transform[13] +
                          Transform[2]*Transform[14]),

                          -(Transform[4]*Transform[12] +
                          Transform[5]*Transform[13] +
                          Transform[6]*Transform[14]),

                          //add a - like above for non-inverted z-axis
                          (Transform[8]*Transform[12] +
                          Transform[9]*Transform[13] +
                          Transform[10]*Transform[14]), 1};
    glLoadMatrixf(viewmatrix);
}

Теперь к моей проблеме, вращению. Рассмотрим, например, вращение вокруг оси Y. Это стек матрицы вращения:

// deg is the angle it is not working in degree or radiant
void Camera::rotateLocal_y(float deg){
    glMatrixMode(GL_MODELVIEW);

    glPushMatrix();
    glLoadMatrixf(Transform);

    rotateMatrixf_y(Transform, deg);



    glGetFloatv(GL_MODELVIEW_MATRIX, Transform);
    glPopMatrix();
}

Итак, далее я собираюсь показать функцию вращения:

//rotate a matrix around y axis
void rotateMatrixf_y(float *aMatrix, float angle){
    //                                  x                   y               z                       t
    float rotMatrix[] = {cos(angle),0,-1*sin(angle),0, 0, 1, 0, 0, sin(angle), 0, cos(angle), 0, 0, 0, 0, 1};

     multMatrixMatrix(rotMatrix,aMatrix);

}

И, наконец, функция умножения матриц:

void multMatrixMatrix(float* m_a, float* m_b){
    float m_c[16] = {m_a[0]*m_b[0]+m_a[4]*m_b[1]+m_a[8]*m_b[2]+m_a[12]*m_b[3],
                    m_a[0]*m_b[4]+m_a[4]*m_b[5]+m_a[8]*m_b[6]+m_a[12]*m_b[7],
                    m_a[0]*m_b[8]+m_a[4]*m_b[9]+m_a[8]*m_b[10]+m_a[12]*m_b[11],
                    m_a[0]*m_b[12]+m_a[4]*m_b[13]+m_a[8]*m_b[14]+m_a[12]*m_b[15],

                    m_a[1]*m_b[0]+m_a[5]*m_b[1]+m_a[9]*m_b[2]+m_a[13]*m_b[3],
                    m_a[1]*m_b[4]+m_a[5]*m_b[5]+m_a[9]*m_b[6]+m_a[13]*m_b[7],
                    m_a[1]*m_b[8]+m_a[5]*m_b[9]+m_a[9]*m_b[10]+m_a[13]*m_b[11],
                    m_a[1]*m_b[12]+m_a[5]*m_b[13]+m_a[9]*m_b[14]+m_a[13]*m_b[15],

                    m_a[2]*m_b[0]+m_a[6]*m_b[1]+m_a[10]*m_b[2]+m_a[14]*m_b[3],
                    m_a[2]*m_b[4]+m_a[6]*m_b[5]+m_a[10]*m_b[6]+m_a[14]*m_b[7],
                    m_a[2]*m_b[8]+m_a[6]*m_b[9]+m_a[10]*m_b[10]+m_a[14]*m_b[11],
                    m_a[2]*m_b[12]+m_a[6]*m_b[13]+m_a[10]*m_b[14]+m_a[14]*m_b[15],

                    m_a[3]*m_b[0]+m_a[7]*m_b[1]+m_a[11]*m_b[2]+m_a[15]*m_b[3],
                    m_a[3]*m_b[4]+m_a[7]*m_b[5]+m_a[11]*m_b[6]+m_a[15]*m_b[7],
                    m_a[3]*m_b[8]+m_a[7]*m_b[9]+m_a[11]*m_b[10]+m_a[15]*m_b[11],
                    m_a[3]*m_b[12]+m_a[7]*m_b[13]+m_a[11]*m_b[14]+m_a[15]*m_b[15]
    };

    m_b =  m_c;

}

Я, хотя это должно быть так, но кажется, что что-то в корне неправильно. Он вообще не движется. камера настроена правильно. Порядок методов: cam.rotate, затем cam.setView.

Оригинальная функция поворота флипкодов:

void Camera::rotateLoc(float deg, float x, float y, float z) {

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadMatrixf(Transform);

    glRotatef(deg, x,y,z);

    glGetFloatv(GL_MODELVIEW_MATRIX, Transform);
    glPopMatrix();
}

person Knut    schedule 10.01.2012    source источник
comment
Поскольку вы используете C++, не рассматривали ли вы возможность использования GLM для ваших нужд в векторной и матричной математике?   -  person R. Martinho Fernandes    schedule 11.01.2012
comment
@ Али: Я хочу попробовать так. Когда я использовал только glRotatef для x и y, также происходило вращение вокруг оси z. @Мартиньо: Нет   -  person Knut    schedule 11.01.2012


Ответы (1)


Ваш код довольно грязный и неполный.

Я думаю, что ваша проблема здесь:

glPushMatrix();
glLoadMatrixf(Transform);                    // give the Transform matrix to GL (why?)

rotateMatrixf_y(Transform, deg);             // modify the Transform matrix

glGetFloatv(GL_MODELVIEW_MATRIX, Transform); // (3) retrieve the original Tranform matrix
glPopMatrix();

(3) просто отменяет любые изменения, которые вы делали в «Преобразовании», вызывая «rotateMatrixf_y».

Код флипкода, который вы добавили, использует OpenGL для обновления матрицы преобразования, вызывая glRotatef' и считывая результат, что нормально. В коде вашего метода вы должны просто удалить все ссылки на OpenGL и просто оставить вызов rotateMatrixf_y, который выполняет всю работу самостоятельно.

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

person rotoglup    schedule 10.01.2012
comment
И даже если (3) не отменит все, glPopMatrix в конце сделает это. - person R. Martinho Fernandes; 11.01.2012
comment
@Р. Martinho, в зависимости от семантики rotateLocal_y да, я не очень понимаю, что этот метод должен делать, у меня сложилось впечатление, что он должен просто обновить матрицу Transform, но я могу ошибаться - person rotoglup; 11.01.2012
comment
@ R и M: я убрал метод GlGet, но изменений нет. Относительно push/pop: перед glPushMatrix в стеке находится идентификационная матрица. Затем я выполняю толчок, помещаю на него матрицу преобразования, сохраняю ее. Затем следует всплывающее окно для рисования объектов с помощью матрицы идентичности. Когда я устанавливаю View, я напрямую беру матрицу Transform. Я отредактировал Вопрос, там есть оригинальная функция от флипкода, которая работает и имеет те же вызовы функций, но функцию поворота. - person Knut; 11.01.2012
comment
@rotoglup - да, rotate_local_y просто обновляет матрицу преобразования - person Knut; 11.01.2012