在opengl场景中一般存在多种矩阵变换操作,而控制这些操作的命令主要用到glMatrixMode函数。
模型视图矩阵是在对物体进行缩放或者从不同的视角观察物体的时候所调用的。主要涉及到三个函数:
glTranslate、glRotate、glScale。
一、平移glTranslatef
1.glTranslatef介绍
void WINAPI glTranslatef(
GLfloat x,
GLfloat y,
GLfloat z
);
沿X轴正方向平移x个单位(x是有符号数)
沿Y轴正方向平移y个单位(y是有符号数)
沿Z轴正方向平移z个单位(z是有符号数)
2.glTranslatef应用
众所周知:当我们利用OpenGL绘制图形时,glVertex3f第三个参数>=0的话屏幕就绘制不出效果。如下方代码:
void Draw()
{
glClearColor(1, 1, 1, 1.0f); //白色背景
glClear(GL_COLOR_BUFFER_BIT);
//绘制独立的三角形
glBegin(GL_TRIANGLES); //注意是逆时针绘制
glColor4ub(0, 0, 255, 255); //蓝
glVertex3f(-0.2f, -0.2f, 0.0f);
glColor4ub(255, 0, 0, 255); //红
glVertex3f(0.2f, -0.2f, 0.0f);
glColor4ub(0, 255, 0, 255); //绿
glVertex3f(0.0f, 0.2f, 0.0f);
glEnd();
}
所以要想获得正确的绘制效果,除了改glVertex3f的第三个参数为负数,我们还可以用矩阵转换的方式实现。
void Init()
{
glMatrixMode(GL_PROJECTION);//将当前矩阵指定为投影矩阵,对投影矩阵操作
gluPerspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);//创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵
glMatrixMode(GL_MODELVIEW); //将当前矩阵指定为模型视图矩阵,对模型视图矩阵操作
glLoadIdentity(); //把矩阵设为单位矩阵
glTranslatef(0, 0, - 1.5f);//此时ModedlViewMatrix就可以让之后的所有数据都带上一个-1.5的Z方向的偏移
}
二、旋转glRotatef
1.glRotatef介绍
void WINAPI glRotatef(
GLfloat angle,
GLfloat x,
GLfloat y,
GLfloat z
);
glRotatef函数针对上一个矩阵,使该矩阵以点(0,0,0)到点(x,y,z)为轴,逆时针旋转angle度。
2.glRotatef应用
void Init()
{
glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵,对投影矩阵操作
gluPerspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);//创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵
glMatrixMode(GL_MODELVIEW); //将当前矩阵指定为模型视图矩阵,对模型视图矩阵操作
glLoadIdentity(); //把矩阵设为单位矩阵
glRotatef(30, 0, 0, 1); //此时ModedlViewMatrix就可以让之后的所有数据都绕(0,0,1)旋转30度
}
三、缩放glScalef
1.glScalef介绍
void WINAPI glScalef(
GLfloat x,
GLfloat y,
GLfloat z
);
glScalef 函数沿 x、y 和 z 轴生成常规缩放。
2.glScalef应用
以第三个参数来分析:
(1)当glVertex3f的第三个参数为0,通过glTranslatef来进行矩阵平移时,在使用glScalef后绘制画面上会有图形缩放的效果。
void Init()
{
glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵,对投影矩阵操作
gluPerspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);//创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵
glMatrixMode(GL_MODELVIEW); //将当前矩阵指定为模型视图矩阵,对模型视图矩阵操作
glLoadIdentity(); //把矩阵设为单位矩阵
glTranslatef(0, 0, - 1.5f); //平移
glScalef(0.1f, 0.1f, 0.1f);
}
void Draw()
{
glClearColor(1, 1, 1, 1.0f); //白色背景
glClear(GL_COLOR_BUFFER_BIT);
//绘制独立的三角形
glBegin(GL_TRIANGLES); //注意是逆时针绘制
glColor4ub(0, 0, 255, 255); //蓝
glVertex3f(-0.2f, -0.2f, 0.0f);
glColor4ub(255, 0, 0, 255); //红
glVertex3f(0.2f, -0.2f, 0.0f);
glColor4ub(0, 255, 0, 255); //绿
glVertex3f(0.0f, 0.2f, 0.0f);
glEnd();
}
如上方代码:
注释glScalef(0.1f, 0.1f, 0.1f);时 |
|
添加glScalef(0.1f, 0.1f, 0.1f);时 |
|
(2)当glVertex3f的第三个参数不为0,且没有通过glTranslatef来进行矩阵平移时,由于glScalef影响了glVertex3f的第三个参数,点的绘制离摄像头近了,所以绘制后,在视觉效果上没有图形缩放的效果。如下方的代码:加上或者注释glScalef(0.1f, 0.1f, 0.1f);后画面效果不变。
void Init()
{
glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵,对投影矩阵操作
gluPerspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);//创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵
glMatrixMode(GL_MODELVIEW); //将当前矩阵指定为模型视图矩阵,对模型视图矩阵操作
glLoadIdentity(); //把矩阵设为单位矩阵
glScalef(0.1f, 0.1f, 0.1f);
}
void Draw()
{
glClearColor(1, 1, 1, 1.0f); //白色背景
glClear(GL_COLOR_BUFFER_BIT);
//绘制独立的三角形
glBegin(GL_TRIANGLES); //注意是逆时针绘制
glColor4ub(0, 0, 255, 255); //蓝
glVertex3f(-0.2f, -0.2f, -1.5f);
glColor4ub(255, 0, 0, 255); //红
glVertex3f(0.2f, -0.2f, -1.5f);
glColor4ub(0, 255, 0, 255); //绿
glVertex3f(0.0f, 0.2f, -1.5f);
glEnd();
}
四、压栈出栈
由于openGL只有一个坐标系,所以平常画物体,应该注意保存当前坐标系坐标,以便画完后返回。如下方代码:这样画A就不会影响其他部分了。
glPushMatrix()
//坐标变换。。。
//画好物体A
glPopMatrix();
//继续新的代码
1.glPushMatrix & glPopMatrix
对于矩阵的操作都是对于矩阵栈的栈顶来操作的。当前矩阵即为矩阵栈的栈顶元素,而对当前矩阵进行平移、旋转等的变换操作也同样是对栈顶矩阵的修改。所以我们在变换之前调用glPushMatrix()的话,就会把当前状态压入第二层,并且此时栈顶的矩阵也与第二层的相同。
当经过一系列的变换后,栈顶矩阵被修改,此时调用glPopMatrix()时,栈顶矩阵被弹出,且又会恢复为原来的状态。文章来源:https://www.toymoban.com/news/detail-769472.html
2.举个栗子
(1)代码
void Init()
{
glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵,对投影矩阵操作
gluPerspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f);//创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵
glMatrixMode(GL_MODELVIEW); //将当前矩阵指定为模型视图矩阵,对模型视图矩阵操作
glLoadIdentity(); //把矩阵设为单位矩阵
}
void Draw()
{
glClearColor(1, 1, 1, 1.0f); //白色背景
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity(); //重置矩阵设为单位矩阵
//glTranslatef使两个同位置的三角形分开
glPushMatrix();
glTranslatef(-0.4f, 0.0f, 0.0f); //向左平移0.4个单位
glBegin(GL_TRIANGLES); //注意是逆时针绘制
glColor4ub(0, 0, 255, 255); //蓝
glVertex3f(-0.2f, -0.2f, -1.0f);
glColor4ub(255, 0, 0, 255); //红
glVertex3f(0.2f, -0.2f, -1.0f);
glColor4ub(0, 255, 0, 255); //绿
glVertex3f(0.0f, 0.2f, -1.0f);
glEnd();
glPopMatrix();
glPushMatrix();
glTranslatef(0.4f, 0.0f, 0.0f); //向右平移0.4个单位
glBegin(GL_TRIANGLES); //注意是逆时针绘制
glColor4ub(0, 0, 255, 255); //蓝
glVertex3f(-0.2f, -0.2f, -1.0f);
glColor4ub(255, 0, 0, 255); //红
glVertex3f(0.2f, -0.2f, -1.0f);
glColor4ub(0, 255, 0, 255); //绿
glVertex3f(0.0f, 0.2f, -1.0f);
glEnd();
glPopMatrix();
(2)效果
五、注意
由于矩阵乘法不具有交换律的性质,所以对一个矩阵先旋转后平移和先平移后旋转这两种不同的操作产生的效果不同。(想想unity场景中对一个模型的操作)。文章来源地址https://www.toymoban.com/news/detail-769472.html
到了这里,关于OpenGL | OpenGL矩阵操作(视图模型矩阵下)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!