glPushMatrix()和glPopmatirx()

原文地址:http://blog.csdn.net/tyxkzzf/article/details/40907273OpenGL有三个矩阵堆栈,分别是GL_MODELVIEW(模型视图矩阵堆栈)、GL_PROJECTION(投影矩阵堆栈)、GL_TEXTURE(纹理矩阵堆栈),用法和普通堆栈一样;这里我们只讲模型视图矩阵堆栈,OpenGL提供了相应的接口:glPushMatir

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

原文地址:http://blog.csdn.net/tyxkzzf/article/details/40907273

OpenGL有三个矩阵堆栈,分别是GL_MODELVIEW(模型视图矩阵堆栈)、GL_PROJECTION(投影矩阵堆栈)、GL_TEXTURE(纹理矩阵堆栈),用法和普通堆栈一样;

这里我们只讲模型视图矩阵堆栈,OpenGL提供了相应的接口:glPushMatirx()和glPopMatrix()。

这个模型视图矩阵堆栈是干嘛用的呢?我们在三维空间中绘制模型,大部分时候需要对模型进行移动、旋转、缩放操作,其实OpenGL移动的不是模型,而是坐标系(效果是一样的啦,就比如你坐在车上,跟你并排的还有一辆车,都是静止不动的,这时候你倒车的效果和旁边那辆车前进的效果是不是一样的)。但是,但空间中有多个模型的时候,这个时候,问题来了,我们怎么确定每个模型都绘制在预期的位置呢?

比如,我们想要绘制太阳系,中间是太阳,静止不动,地球围绕太阳旋转,月亮围绕地球旋转,如下图所示的情景:

glPushMatrix()和glPopmatirx()

我们首先将坐标系移动到太阳的位置,绘制太阳,再将坐标系移动到地球的位置,绘制地球,然后将坐标系移动到月亮的位置,绘制月亮;如果还有金星、木星、火星呢,他们也都是以太阳为中心旋转,这样子,我们可以绘制完月亮之后再将坐标系回退到绘制地球的时候的坐标系,移动相应的位置,绘制金星,然后再回退或者移动新位置绘制木星。。。。。。这样的操作不但麻烦,而且容易出错(麻烦的东西都比较容易出错,所以要简洁),那怎么办最好呢,其实就是绘制地球、金星、木星、火星等的时候以太阳为坐标原点,在绘制地球之前先把当前的模型视图矩阵压入堆栈中保存下来(glPushMatirx),这样你在进行变换就不会影响到堆栈中的矩阵,这个时候将坐标系移动到地球的位置绘制地球,绘制完成之后将模型视图矩阵堆栈中的栈顶矩阵(就是我们刚才保存的矩阵)弹出(glPopMatrix),恢复原来的坐标系,再压入堆栈,绘制金星,再弹出。。。。。。

可以使用嵌套,即:

绘制太阳

压栈

(栈顶矩阵为太阳对应的模型视图矩阵)

移动坐标系到地球位置

绘制地球

压栈(这里就嵌套了)

(栈顶矩阵为地球地球对应的模型视图矩阵)

移动坐标系到月亮的位置

绘制月亮

压栈(嵌套又见嵌套)

(栈顶局长为月亮对应的模型视图矩阵)

移动坐标系到月亮的月亮(虚构)的位置

绘制月亮的月亮

出栈

(栈顶矩阵恢复为地球地球对应的模型视图矩阵,这时可以绘制第二个月亮了)

出栈

(栈顶矩阵恢复为太阳对应的模型视图矩阵,这时可以绘制金星、木星、火星等等了)

出栈

(栈顶为最初的模型视图矩阵,这时可以绘制太阳2,太阳3.。。。。。。太阳9,后羿射日前)

具体代码为(代码只实现了绘制两个月亮,也是嵌套,没有那么多,原理是一样的)

[cpp] 
view plain
 copy

 
在CODE上查看代码片
派生到我的代码片

  1. // Called to draw scene  
  2. void RenderScene(void)  
  3.     {  
  4.     // Earth and Moon angle of revolution  
  5.     static float fMoonRot = 0.0f;  
  6.     static float fEarthRot = 0.0f;  
  7.   
  8.     // Clear the window with current clearing color  
  9.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  10.   
  11.     // Save the matrix state and do the rotations  
  12.     glMatrixMode(GL_MODELVIEW);  
  13.     glPushMatrix();  
  14.   
  15.     // Translate the whole scene out and into view    
  16.     glTranslatef(0.0f, 0.0f, -300.0f);    
  17.       
  18.     // Set material color, Red  
  19.     // Sun  
  20.         glDisable(GL_LIGHTING);  
  21.     glColor3ub(255, 255, 0);  
  22.     glutSolidSphere(15.0f, 30, 17);  
  23.         glEnable(GL_LIGHTING);  
  24.   
  25.     // Move the light after we draw the sun!  
  26.     glLightfv(GL_LIGHT0,GL_POSITION,lightPos);  
  27.   
  28.     // Rotate coordinate system  
  29.     glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f);  
  30.   
  31.     // Draw the Earth  
  32.     glColor3ub(0,0,255);  
  33.     glTranslatef(105.0f,0.0f,0.0f);  
  34.     glutSolidSphere(15.0f, 30, 17);  
  35.   
  36.     glPushMatrix();  
  37.     // Rotate from Earth based coordinates and draw Moon  
  38.     glColor3ub(200,200,200);  
  39.     glRotatef(fMoonRot,0.0f, 1.0f, 0.0f);  
  40.     glTranslatef(30.0f, 0.0f, 0.0f);  
  41.     fMoonRot+= 15.0f;  
  42.     if(fMoonRot > 360.0f)  
  43.         fMoonRot = 0.0f;  
  44.     glutSolidSphere(6.0f, 30, 17);  
  45.     glPopMatrix();  
  46.   
  47.     glColor3ub(100, 250, 0);  
  48.     glRotatef(fMoonRot, 1.0f, 0.0f, 0.0f);  
  49.     glTranslatef(0.0f, 20.0f, 0.0f);  
  50.     glutSolidSphere(6.0f, 30, 17);  
  51.   
  52.     // Restore the matrix state  
  53.     glPopMatrix();  // Modelview matrix  
  54.   
  55.     // Step earth orbit 5 degrees  
  56.     fEarthRot += 5.0f;  
  57.     if(fEarthRot > 360.0f)  
  58.         fEarthRot = 0.0f;  
  59.   
  60.     // Show the image  
  61.     glutSwapBuffers();  
  62. }  

实现效果图:

glPushMatrix()和glPopmatirx()

glPushMatrix()和glPopmatirx()

glPushMatrix()和glPopmatirx()

glPushMatrix()和glPopmatirx()

glPushMatrix()和glPopmatirx()

不过需要注意的是,模型视图矩阵堆栈最大为32个,Windows平台,有数量限制,超出的话将会报错。

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/125895.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java 用户态_深入理解内核态和用户态

    java 用户态_深入理解内核态和用户态1.内核态和用户态、内核线程和用户线程等解释操作系统调度CPU的最小单元是线程,也叫轻量级进程(LightWeightProcess),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。系统的用户空间和内核空间:虚拟内存被操作系统划分成两块:内核空间和用户空间,内核空间是内…

    2022年9月17日
  • oracle优化器统计信息相关

    优化器使用统计信息来生成每个sql语句最优的执行计划。准确的统计信息对于数据库的效率至关重要。dba和程序开发人员都应该了解一些统计信息相关知识,这可以使你更好的理解为什么会生成一个你看到的执行计划,知其然且知其所以然。

    2022年4月8日
  • html5之本地存储localStorage示例

    html5之本地存储localStorage示例

    2021年9月12日
  • ubuntu安装python pip_anaconda pipenv

    ubuntu安装python pip_anaconda pipenv简单介绍在Ubuntu上安装Python的virtualenv前提:本机安装了Linux系统(这里推荐用Ubuntu安装,或是CentOS)(Ubuntu的安装比较简单,推荐用VirtualBox,可以去Oracle官网下载VirtualBox(https://www.virtualbox.org/),然后去Ubuntu官网(https://www.ubuntu.com/download)…

    2022年8月26日
  • Linux命令:traceroute命令(路由跟踪)

    Linux命令:traceroute命令(路由跟踪)traceroute是用来检测发出数据包的主机到目标主机之间所经过的网关数量的工具。traceroute的原理是试图以最小的TTL(存活时间)发出探测包来跟踪数据包到达目标主机所经过的网关,然后监听一个来自网关ICMP的应答。发送数据包的大小默认为38个字节。原理:程序利用增加存活时间(TTL)来实现其功能。每当数据包(3个数据包包括源地址,目的地址和包发出的时间标签)经过一个路由器,其存活时间就会

    2022年6月17日
  • LocationManager的简单使用

    LocationManager在Android中可以根据LocationManager来获取设备所在的地理信息根据需求可以将定位的代码移动到所需的地方或者可以稍加改动获取城市的信息MainActivity中:packagecom.example.myapplicationpp;importandroid.Manifest;importandroid.app.Activity;…

    2022年4月5日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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