2013-08-27 2 views
0

Изучение книги OpenGL SuperBible fram Addison-Wesley, я прочитал:
каждый вызов glTranslate кумулятивный на видовую матрицу
Что это значит?
Означает ли это, что, например, этот код:(каждый вызов glTranslate является кумулятивным по матрице просмотра модели), что это значит и как отключить эту функцию?

glTranslatef(2.0,3.0,0); 
glTranslatef(4.0,5.0,0); 

первые шаги объекта, который находится на нуле до точки (2,3,0), а затем переводит его из (2,3,0) в (2+4,3+5,0+0) = (6,8,0) не от происхождения снова?

Это правда о glScalef и glRotatef тоже?
, например, этот код:

glScalef(2.0,3.0,4.0); 
glScalef(3.0,4.0,5.0); 

первым превратить 1x1x1 кубоид в 2x3x4 кубического прямоугольника, а затем превращает этот кубический прямоугольник к 6x12x20 один?
И наконец, означает ли этот код, что общий поворот на 75 градусов вокруг оси х?

glRotatef(30.0,1,0,0); 
glRotatef(45.0,1,0,0); 

наиболее importantant: ли вызова glLoadIdentity() перед каждым вызовом этих функций отменяет эти функции?
Я имею в виду Как вы думаете, этот код гарантирует, что каждый раз, когда translates will be done from the origin?, scale changes will be done from the initial state?

void COpenGLControl::ZoomToFullExtent() 
{ 
float zoom1 = (float)oglWindowWidth/(float)ImageWidth; 
float zoom2 = (float)oglWindowHeight/(float)ImageHeight; 
m_fZoom = min(zoom1,zoom2); 
m_fZoomInverse = 1/m_fZoom; 
m_fPosX = 0; 
m_fPosY = 0; 
OnDraw(NULL); 
} 

void COpenGLControl::FixedZoomIn() 
{ 
m_fZoom = 2*m_fZoom; 
m_fZoomInverse = 1/m_fZoom; 
OnDraw(NULL); 
} 

void COpenGLControl::FixedZoomOut() 
{ 
m_fZoom = 0.5*m_fZoom; 
m_fZoomInverse = 1/m_fZoom; 
OnDraw(NULL); 
} 

void COpenGLControl::OnMouseMove(UINT nFlags, CPoint point) 
{ 
// TODO: Add your message handler code here and/or call default 
if (WantToPan) 
{ 
    if (m_fLastX < 0.0f && m_fLastY < 0.0f) 
    { 
     m_fLastX = (float)point.x; 
     m_fLastY = (float)point.y; 
    } 
    diffX = (int)(point.x - m_fLastX); 
    diffY = (int)(point.y - m_fLastY); 
    m_fLastX = (float)point.x; 
    m_fLastY = (float)point.y; 
    if (nFlags & MK_MBUTTON) 
    { 
     m_fPosX += (float)0.2f*m_fZoomInverse*diffX; 
     m_fPosY += (float)0.2f*m_fZoomInverse*diffY; 
    } 
    OnDraw(NULL); 
} 
CWnd::OnMouseMove(nFlags, point); 
} 

void COpenGLControl::OnDraw(CDC *pDC) 
{ 
// TODO: Camera controls 
wglMakeCurrent(hdc,hrc); 
glLoadIdentity(); 
gluLookAt(0,0,1,0,0,0,0,1,0); 
glScalef(m_fZoom,m_fZoom,1.0); 
glTranslatef(m_fPosX, m_fPosY, 0.0f); 
wglMakeCurrent(NULL, NULL); 
} 

ответ

0

OpenGl сохраняет видовую матрицу, которая умножать координаты ваших вершин. Каждый вызов для перевода, поворота, масштабирования и т. Д. Будет умножать эту матрицу справа. Так что если у вас есть:

glLoadIdentity(); 
glTranslatef(2.0,3.0,0); 
glTranslatef(4.0,5.0,0); 

Результат будет первым переводом ваших вершин на 4,5,0, а затем на 2,3,0. Внутри это будет работать следующим образом: 1. Матрица modelView будет тождественной. 2. текущая матрица modelView (идентификатор) будет правильно умножаться на матрицу перевода со значениями (4, 5, 0) для более подробной информации (http://en.wikipedia.org/wiki/Translation_%28geometry%29) 3. Текущая модельViewматрица (одна из шагов 2) будет справа умножается на вторую матрицу сдвига.

В вашем примере масштабирования:

glScalef(2.0,3.0,4.0); 
glScalef(3.0,4.0,5.0); 

Это будет эквивалентно первому превратить 1x1x1 кубоид в 3x4x5 параллелепипеда, а затем в 6x12x20. В корпусе поворота сначала поверните на 45 градусов, а затем 30.

На ваш вопрос об использовании glLoadIdentity() матрица modelView будет идентична независимо от предыдущего значения матрицы.

Вы также можете быть заинтересованы в проверке системы стека трансформации opengl.

1

glTranslate, glScale, glRotate не действуют на «объекты» (независимо от объекта. OpenGL не знает, что такое «объект», он знает только точки, линии и треугольники).

В старой фиксированной функции OpenGL у вас есть несколько матричных стеков. Стек представляет собой структуру данных, похожую на список, с двумя операциями push и pop. Фактически вы можете получить его из списка:

stack : list; 

void stack::push() { 
    this->append(copy(this->last_element)); 
} 

void stack::pop() { 
    this->drop(this->last_element); 
} 

Проекция и моделирование являются наиболее часто используемыми. Для манипуляции всегда есть один конкретный матричный стек. glMatrixMode выбирает, какой из них; подумайте об этом как о ссылке.

stack<mat4x4> modelview; 
stack<mat4x4> projection; 
stack<mat4x4> *M; 

void glMatrixMode(mode) { 
    switch(mode) { 
    case GL_MODELVIEW: 
     M = &modelview; break; 

    case GL_PROJECTION: 
     M = &projection; break; 
    } 
} 

void glPushMatrix() { 
    M->push(); 
} 

void glPopMatrix() { 
    M->pop(); 
} 

Функции манипуляции с фиксированной функцией OpenGL действуют на верхнем элементе стека активной матрицы (M).

void glLoadIdentity() { 
    M->last_element = identity_matrix; 
} 

void glTranslate(x,y,z) { 
    /* make a translation matrix and R-multiply in place */ 
    mat4x4 T = translate_matrix(x,y,z); 
    M->last_element = M->last_element * T; 
} 

void glScale(x,y,z) { 
    /* make a scaling matrix and R-multiply in place */ 
    mat4x4 S = scaling_matrix(x,y,z); 
    M->last_element = M->last_element * S; 
} 

void glRotate(a,x,y,z) { 
    /* make a rotation matrix and R-multiply in place */ 
    mat4x4 R = rotation_matrix(a,x,y,z); 
    M->last_element = M->last_element * R; 
} 

И все это происходит за занавеской при вызове этих функций.

0

Обратите особое внимание на функции API OpenGL, которые включают в себя описание: «делает ... до текущий ...».

OpenGL - это прославленный конечный автомат, а вещи, подобные связанным объектам и матрицам (в устаревшем OpenGL), сохраняют свое состояние. Когда вы звоните в glTranslatef (...), он умножает текущую матрицу (определенную матричным режимом и вершиной вашего стека матриц). Если вы не выпустите glLoadMatrixf (...), glLoadIdentity (...) или измените стек матрицы, glTranslatef (...) будет просто накапливаться каждый раз, когда вы его вызываете.


glLoadIdentity (...) заменит текущей матрицы с идентичностью:

1, 0, 0, 0 
    0, 1, 0, 0 
    0, 0, 1, 0 
    0, 0, 0, 1 

Если вы настраиваете ваши преобразования матрицы каждый кадр, как правило, требуется, чтобы вы это делаете. В противном случае все ваши преобразования будут относиться к предыдущему состоянию (хотя это иногда желательно).