OpenGL的glPushMatrix和glPopMatrix矩阵栈顶操作函数详解

OpenGL中图形绘制后,往往需要一系列的变换来达到用户的目的,而这种变换实现的原理是又通过矩阵进行操作的。opengl中的变换一般包括视图变换、模型变换、投影变换等,在每次变换后,opengl将会呈现一种新的状态(这也就是我们为什么会成其为状态机)。有时候在经过一些变换后我们想回到原来的状态,就像我们谈恋爱一样,换来换去还是感觉初恋好,怎么办?强大的openg…

大家好,又见面了,我是你们的朋友全栈君。

        OpenGL中图形绘制后,往往需要一系列的变换来达到用户的目的,而这种变换实现的原理是又通过矩阵进行操作的。opengl中的变换一般包括视图变换、模型变换、投影变换等,在每次变换后,opengl将会呈现一种新的状态(这也就是我们为什么会成其为状态机)。

        有时候在经过一些变换后我们想回到原来的状态,就像我们谈恋爱一样,换来换去还是感觉初恋好,怎么办?强大的opengl就帮我们提供了两个函数:giPushMatrix()和glPopMatrix();

        首先我们要知道,对于矩阵的操作都是对于矩阵栈的栈顶来操作的。当前矩阵即为矩阵栈的栈顶元素,而对当前矩阵进行平移、旋转等的变换操作也同样是对栈顶矩阵的修改。所以我们在变换之前调用giPushMatrix()的话,就会把当前状态压入第二层,不过此时栈顶的矩阵也与第二层的相同。

       当经过一系列的变换后,栈顶矩阵被修改,此时调用glPopMatrix()时,栈顶矩阵被弹出,且又会恢复为原来的状态。

       函数的作用过程可以用下图描述,更为直观。

    OpenGL的glPushMatrix和glPopMatrix矩阵栈顶操作函数详解

 

          在opengl场景中一般存在多种矩阵变换操作,而控制这些操作的命令主要用到

          glMatrixMode(GLenum mode); 
          作用:用于指定用哪个矩阵作为当前矩阵,mode用于指定哪一种矩阵栈是其后矩阵操作的目标。mode可取: 
           GL_MODELVIEW: 把其后的矩阵操作施加于造型视图矩阵栈。(默认) 
           GL_PROJECTION: 把其后的矩阵操作施加于投影矩阵栈。 
           GL_TEXTURE: 把其后的矩阵操作施加于纹理矩阵栈。

          注意上述三种模式分别对应了三种矩阵栈。

          所以在场景中存在多种矩阵变换时,glPushMatrix()和glPopMatrix()一般情况下也要结合glMatrixMode(GLenum mode)运用,系统才知道具体操作的是哪个矩阵栈。

 

          注意:

          摄像机矩阵和模型矩阵用的是同一个矩阵,就是GL_MODELVIEW (model是模型搜索矩阵,view是摄像机矩阵,GL_MODELVIEW里保存的是这两个矩阵的积)。所以选择GL_MODELVIEW之后直接用glTranslate,glRotate之类的就行。

          其实摄像机和模型矩阵本质上是一回事(这也是为什么OpenGL把这两个矩阵放在一起保存的原因),因为比如把整个世界向y+方向移动10跟把摄像机向y-方向移动10是等价的。旋转也是一样。

          虽然矩阵里可以保存任何变换,但按照OpenGL的概念,model和view矩阵里只能保存平移,旋转和缩放;project矩阵里只能保存投影矩阵,viewport矩阵里只能保存二维平移和缩放。这样来看把model和view放在一起是合理的。他们之间的区别纯粹是人为的。

 

    附上代码例子:

 1 #include <stdlib.h>  2 #include "include\glut.h"  3  4 static int year = 0, day = 0;  5  6 void init(void)  7 {  8 glClearColor (0.0, 0.0, 0.0, 0.0);  9  glShadeModel (GL_FLAT); 10 } 11 12 void display(void) 13 { 14  glClear (GL_COLOR_BUFFER_BIT); 15 glColor3f (1.0, 1.0, 1.0); 16 17  glPushMatrix(); 18  { 19 glutWireSphere(1.0, 20, 16); /* draw sun */ 20 glRotatef ((GLfloat) year, 0.0, 1.0, 0.0); 21 22 glTranslatef (2.0, 0.0, 0.0); //把坐标原点变换位置 23 24 glRotatef ((GLfloat) day, 0.0, 1.0, 0.0); 25 glutWireSphere(0.2, 10, 8); /* draw smaller planet */ 26  } 27  glPopMatrix(); 28 29  glutSwapBuffers(); 30 } 31 32 void reshape(int w, int h) 33 { 34 glViewport (0, 0, (GLsizei) w, (GLsizei) h); 35  glMatrixMode (GL_PROJECTION); 36  glLoadIdentity (); 37 gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0); 38 39  glMatrixMode(GL_MODELVIEW); 40  glLoadIdentity(); 41 gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 42 } 43 44 void keyboard(unsigned char key, int x, int y) 45 { 46 switch (key) { 47 case 'd': 48 day = (day + 10) % 360; 49  glutPostRedisplay(); 50 break; 51 case 'D': 52 day = (day - 10) % 360; 53  glutPostRedisplay(); 54 break; 55 case 'y': 56 year = (year + 5) % 360; 57  glutPostRedisplay(); 58 break; 59 case 'Y': 60 year = (year - 5) % 360; 61  glutPostRedisplay(); 62 break; 63 case 27: 64 exit(0); 65 break; 66 default: 67 break; 68  } 69 } 70 71 int main(int argc, char** argv) 72 { 73 glutInit(&argc, argv); 74 glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); 75 glutInitWindowSize (500, 500); 76 glutInitWindowPosition (100, 100); 77 glutCreateWindow (argv[0]); 78 79  init(); 80  glutDisplayFunc(display); 81  glutReshapeFunc(reshape); 82  glutKeyboardFunc(keyboard); 83  glutMainLoop(); 84 return 0; 85 }

    运行结果:

    OpenGL的glPushMatrix和glPopMatrix矩阵栈顶操作函数详解

 

转载于:https://www.cnblogs.com/1024Planet/p/5650162.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/127308.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • ODrive应用 #6 编码器

    编码器支持的编码器请首先阅读一下ODrive编码器选型指南。编码器校准ODrive支持的所有编码器类型都需要进行某种编码器校准。这需要以下条件:选择一种编码器并将其安装到电动机选择编码器通讯接口(e.g.,AB,ABIorSPI)将编码器通信接口连接到ODrive加载正确的odrive固件(默认的固件大多数情况下都是可以的)电机校准将设置保存在ODrive中,并正…

  • (实例篇)LNMP 1.4一键安装包,安装教程

    (实例篇)LNMP 1.4一键安装包,安装教程

  • c语言函数回调详解_c语言回调函数例子

    c语言函数回调详解_c语言回调函数例子关于静态库和动态库的使用和制作方法。http://blog.csdn.net/morixinguan/article/details/52451612今天我们要搞明白的一个概念叫回调函数。什么是回调函数?百度的权威解释如下:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实…

    2022年10月30日
  • Flink处理函数实战之一:深入了解ProcessFunction的状态(Flink-1.10)

    Flink处理函数实战之一:深入了解ProcessFunction的状态(Flink-1.10)

    2020年11月19日
  • python安装教程[通俗易懂]

    python安装教程[通俗易懂]python安装教程本章节我们将向大家介绍如何在本地搭建Python开发环境。Python可应用于多平台包括Linux和MacOSX。你可以通过终端窗口输入"python&

  • Android ListView禁止滑动

    Android ListView禁止滑动由于数据较少,如果listview滑动感觉不怎么美观,于是想要Listview禁止滑动,其实也很简单,只要拦截listview的Ontouch事件就可以了具体代码如下:`ListViewlv=(ListView)findViewById(R.id.listView);lv.setOnTouchListener(newOnTouchListener(){

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号