学习本书OpenGL SuperBible fram Addison-Wesley
,我读到:
每次调用glTranslate都是在modelview矩阵上累积的
这是什么意思?
这是否意味着例如这段代码:
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
立方矩形,然后将此立方矩形转换为glRotatef(30.0,1,0,0);
glRotatef(45.0,1,0,0);
一个?
最后,这段代码是否意味着围绕x轴旋转总共75度?
translates will be done from the origin?
最重要的一点:在每次调用这些函数之前调用glLoadIdentity()会取消这些功能吗?
我的意思是你认为这段代码确保每次都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);
}
{{1}}
答案 0 :(得分: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;
}
这就是在调用这些功能时幕后发生的一切。
答案 1 :(得分:0)
OpenGl保留了一个modelView矩阵,它乘以顶点的坐标。每次调用翻译,旋转,缩放等都会将此矩阵乘以右侧。所以如果你有:
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.当前的modelViewmatrix(步骤2中的一个)将正确乘以第二个转换矩阵。
在缩放示例中:
glScalef(2.0,3.0,4.0);
glScalef(3.0,4.0,5.0);
相当于首先将1x1x1长方体转换为3x4x5长方体,然后转换为6x12x20。 在旋转情况下,首先旋转45度然后旋转30度。
关于使用glLoadIdentity()的问题,modelView矩阵将独立于矩阵的先前值。
您可能也有兴趣检查opengl的转换堆栈系统。
答案 2 :(得分:0)
特别注意包含描述的OpenGL API函数:“对... 当前 ......”。
OpenGL是一个美化的状态机,绑定对象和矩阵(在传统OpenGL中)之类的东西保持其状态。当您调用glTranslatef (...)
时,它会将当前矩阵(由矩阵模式和矩阵堆栈的 top 定义)相乘。除非您发出glLoadMatrixf (...)
,glLoadIdentity (...)
或修改矩阵堆栈,否则glTranslatef (...)
只会在您每次调用时累积。
glLoadIdentity (...)
会将当前矩阵替换为其标识:
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1
如果每帧设置变换矩阵,通常需要执行此操作。否则,所有转换都将相对于先前的状态(尽管有时需要这样做)。