下面是上周的作业的要求:

基本功能:完成一个初步的太阳系程序。场景中有三个球体,一个表示太阳,一个表示地球,一个表示月亮;地球不停地绕太阳旋转,月亮绕地球旋转。 进一步扩展功能(选作下面的1项或几项功能):如果地球有两个月亮呢?画上轨道线;让轨道倾斜; 提示:画球体的函数: glutWireSphere(1.0, 20, 16);如何让物体不停运动呢?void glutTimerFunc( );glutPostRedisplay()或glutIdleFunc()


中我总结了上周学到所有的变换的原理以及对应的函数。下面我们就要通过这个作业来剖析OpenGL中这些变换函数的具体细节。
因为是刚开始学,第三周就直接上手很难受,感觉无从下手,所以我找了度娘的一个实现程序,通过老师课上讲的与这个程序中每处用到变换的细节对比就可以理解真谛所在。
在看这段程序之前,我总结了三点理解OpenGL中具体程序运行的个人观点:
(1)OpenGL中并无绝对单位,只有相对大小!!!
(2)OpenGL中所有的变化都是局部变化,也就是说OpenGL中所有物体的变换都以当前物体的中心为原点,只不过有时候他自己的中心恰好在默认的原点。
(3)OpenGL是先对物体进行操作(先罗列一堆变换等函数),再画这个物体
以上三点对于OpenGL程序的理解至关重要,一定要带着这三点去理解下面的程序和函数,其中一些观念与我们主观会不同,要慢慢接受。

#include <windows.h>
#include <GL/freeglut.h>
static int day=200;
void display()
{glEnable(GL_DEPTH_TEST);//用户初始化glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除屏幕和深度缓冲  glMatrixMode(GL_PROJECTION);//设置矩阵模型(投影变换)  glLoadIdentity();//载入单位化矩阵//透视变换角度75度,长宽比1:1,最近可视距离1,最远400000两倍地球公转半径gluPerspective(75,1,1,400000);glMatrixMode(GL_MODELVIEW);//设置矩阵模型(模型、视点变换)glLoadIdentity();//载入单位化矩阵//整体布局,视角位(这里是45度倾角),物体位置,z轴正向gluLookAt(0,-200000,-200000,0,0,0,0,0,1);//太阳glColor3f(1.0f, 0.0f, 0.0f);glutWireSphere(69600,20,20);//地球glColor3f(0.0f, 0.0f, 1.0f);glRotatef(day,0,0,-1);glTranslatef(150000,0,0);glutWireSphere(15945,20,20);//月亮glColor3f(1.0f, 1.0f, 0.0f);glRotatef(day/30*360-day,0,0,-1);glTranslatef(38000,0,0);glutWireSphere(4345,20,20);//交换前后缓冲区glutSwapBuffers();
}
void timer(int p)
{day++;if(day>360) day=0;//注册按一定时间间隔触发的定时器回调函数glutTimerFunc(50,timer,0);//在图像绘制的所有操作之后,要加入 glutPostRedisplay() 来重绘图像,否则图像只有响应鼠标或键盘消息时才会更新图像。//有点像窗口重绘函数一样。它要求当前的回调函数返回时执行显示回调函数glutMainLoop():使程序进入事件处理循环。glutPostRedisplay();
}void processNormalKeys(unsigned char key,int x,int y)
{if(key==27){ //"esc"exit(0);}
}
int main(int argc, char* argv[])
{glutInit(&argc, argv);//初始化freeglutglutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);//初始化OPENGL显示方式//设定OPENGL窗口位置和大小glutInitWindowSize (400, 400); glutInitWindowPosition (100, 100);     //打开窗口glutCreateWindow ("太阳地球月亮");//按esc退出glutKeyboardFunc(processNormalKeys);//开始OPENGL的循环glutDisplayFunc(display); //glutIdleFunc(myIdle);可以用来代替下面的glutTimerFunc让物体一直动//设置全局的回调函数,当没有窗口事件到达时,FREEGLUT程序功能可以执行后台处理任务或连续动画。//如果启用,这个idle function会被不断调用,直到有窗口事件发生。回调函数没有参数。//当前的窗口和菜单在执行idlefunc之前不会改变。当程序依赖多窗口或菜单时最好不要依赖于当前设定。glutTimerFunc(50,timer,0);//按一定时间间隔触发的定时器回调函数glutMainLoop();return 0;
}
/*void myIdle(void)
{++day;if(day>=360)day=0;    display();
}*/

上面这个程序的效果是月亮围着地球转,二者又同时围着太阳转,月亮、地球、太阳都没有自转。对于程序中OpenGL一定会用到的框架类型的函数,就不解释了,可以看https://blog.csdn.net/derbi123123/article/details/104619415这个文章。下面我们就来剖析这个程序中所有用到OpenGL变换相关的函数的细节,也就是display函数中的内容。

如果看不同上面一些变换函数的参数或者不知道它在干嘛,可以看OpenGL中各种变换的原理以及对应的OpenGL函数里面总结了所有变换相关的函数。

涉及到投影、模型、视点变换的函数:

 glMatrixMode(GL_PROJECTION);//设置成模型矩阵模式(投影变换)   glLoadIdentity();//载入单位化矩阵//透视变换角度75度,长宽比1:1,最近可视距离1,最远400000两倍地球公转半径gluPerspective(75,1,1,400000);glMatrixMode(GL_MODELVIEW);//设置成模型矩阵模式(模型、视点变换)glLoadIdentity();//载入单位化矩阵//整体布局,视角位(这里是45度倾角),物体位置,z轴正向gluLookAt(0,-200000,-200000,0,0,0,0,0,1);

对象的变换都是通过矩阵来实现的,在进行矩阵操作前,需用glMatrixMode()指定当前操作的矩阵对象,GL_PROJECTION告诉电脑是要进行投影变换了,GL_MODELVIEW告诉电脑是要进行模型、视点变换了。
glLoadIdentity()用来载入单位化矩阵(重载矩阵),是为了想让之后进行的变换不受之前变换的影响。
gluPerspective()就是投影变换,gluLookAt()是视点变换,这里可能有些懵逼,这些乱七八糟的参数是怎么得到的?说白了还是要清楚一点OpenGL中并无绝对单位,只有相对大小!!! 比如投影变换的第四个参数是400000,也就是远平面到视点的距离是400000个单位,而视点变换的前三个参数是视点位置,程序中是(0,-200000,-200000),就是是我们的视点,而后三个参数是头朝上的方向,程序中是(0,0,1),也就是说我们头朝z轴,我们来看看效果:

一定要仔细看太阳(红色的),上面的顶点在我们看不见的那侧,你会发现我们在仰视这个太阳,也就是原点在屏幕中心,我们在(0,-200000,-200000)看它,是这样的效果,为了体现出参数设置细节,我们不妨把gluLookAt(0,-200000,-200000,0,0,0,0,0,1);改成
gluLookAt(0,200000,200000,0,0,0,0,0,1);,我们再来看效果:

我们可以看到上面的顶点在我们视野的下方了,下面的顶点反而看不见了,我们是在俯视这个太阳,这样我们就可以体会到视点变换函数前三个参数它具体的作用。

涉及到几何变换的函数:

一定要带着下面的思想取体会这段代码。
OpenGL中并无绝对单位,只有相对大小!!!
OpenGL中所有的变化都是局部变化,也就是说OpenGL中所有物体的变换都以当前物体的中心为原点,只不过有时候他自己的中心恰好在默认的原点。
OpenGL是先对物体进行操作(先罗列一堆变换等函数),再画这个物体

 //太阳glColor3f(1.0f, 0.0f, 0.0f);glutWireSphere(69600,20,20);//地球glColor3f(0.0f, 0.0f, 1.0f);glRotatef(day,0,0,-1);glTranslatef(150000,0,0);glutWireSphere(15945,20,20);//月亮glColor3f(1.0f, 1.0f, 0.0f);glRotatef(day/30*360-day,0,0,-1);glTranslatef(38000,0,0);glutWireSphere(4345,20,20);

就是这段代码产生了地球围着太阳转,月亮既围着地球转又围着太阳转的静态效果,让物体不停运动的函数glutTimerFunc()不是这里的重点,可以百度了解。注意上述代码得到的就是一个静态图(也许和下面不一样,反正是静态的):

关键在于这段代码这样写的缘由:
(1)首先是理解OpenGL中所有的变化都是局部变化,也就是说OpenGL中所有物体的变换都以当前物体的中心为原点,我们可以看到画了太阳之后,对地球的变换都是相对于太阳做的,画了地球之后对月亮的变换都是相对于地球做的。由此我们要体会画图的顺序是怎样的。
(2)其次要理解OpenGL是先对物体进行操作(先罗列一堆变换等函数),再画这个物体,这个很容易,我们看程序也能看出来。
(3)最后理解OpenGL中并无绝对单位,只有相对大小!!!
先看一下这个画球体的函数:

glutWireSphere(半径,球体纬线的条数,球体经线的条数)

其作用是画一个可透视的球体。
我们可以看到太阳的半径是69600,地球是15945,月亮是4345,他就是一个相对大小,只要你愿意把它设成1,2,3都行(但要确保前后其他函数的比例也与1,2,3一致),这就是相对的含义,还有地球glTranslatef(150000,0,0);是相对于太阳沿x轴z方向平移150000个单位,前面也看到了,投影函数设置的远平面是400000个单位,所以说这都是相对的,一定要理解这个。
至于旋转变换函数的参数取值我只能说地球绕太阳一圈要一年我们为了方便计算用的360天,月亮绕地球一圈要27天我们为了方便计算用的30天。

最后,再加上可以让物体一直运动的函数后实现的效果是月亮围着地球转,二者又同时围着太阳转,但月亮、地球、太阳都没有自转,所以大家去思考尝试实现月亮、地球、太阳的自转可以发现更多的奥秘!!!

用上周的作业:画一个太阳、地球、月亮的运动模型来剖析OpenGL中变换乃至整个绘制的秘密相关推荐

  1. openGl编程实现一个太阳地球月亮的一个简单运动系统

    一. 项目目的 使用openGl编程实现一个太阳地球月亮的一个简单运动系统,要求实现三维转动.点光源变化.纹理映射及阴影等效果 二. 任务实现 \1. 满足三者实际大小/距离的比例关系: \2. 满足 ...

  2. Python模拟太阳-地球-月亮运动模型

    作者 | Charles,cv方向在读研究生.[Charles 的皮卡丘]专注于分享有趣好玩的Python小项目(AI.爬虫等等). 来源 | Charles 的皮卡丘 编辑 | Jane [导语]春 ...

  3. [css] 用css画一个太阳

    [css] 用css画一个太阳 // css.sun {margin: 200px;width: 200px;height: 200px;border-radius: 50%;background: ...

  4. Python模拟登录,matplotlib模块,Python模拟太阳-地球-月亮运动模型

    前言 利用python模拟太阳-地球-月亮运动模型. 让我们愉快地开始吧~ 开发工具 **Python版本:**3.6.4 相关模块: pygame模块: matplotlib模块: numpy模块: ...

  5. 暑假来了,画一个日月地球的轨道模型给孩子们,秒懂四季更迭、日蚀月蚀

    无言相守45亿年,太阳.地球和月球这三个好基友究竟是怎样的关系呢?从孩提时代我就一直在想,要是能有一个可以直观演示太阳.地球和月球运行轨迹的模型就好了.今天,我终于实现了小时候的梦想:用WxGL画出了 ...

  6. Unity学生作业:太阳地球月亮自转和公转

    1.第一步 打开Unity. 2.第二步 在场景中创建3个Sphere球体并分别命名为Moon, Sun和Earth. 在命名完之后调整3个球的大小和位置,并贴上贴图.将Moon作为Earth的子物体 ...

  7. webgl 绘制太阳 地球 月亮

    目录 1.开发环境 2.内容说明 1.计算球体的坐标和纹理 2.求顶点索引 3.数据加载到缓存中 4.绘制球体 5.其他 3.运行结果及代码下载 1.开发环境 浏览器 : 火狐 firefox(配置参 ...

  8. CSS太阳地球月亮转圈圈loading

    一个css例子 css太阳 月亮 地球转转转 知识点总结: justify-content: center; justify-content 用于设置或检索弹性盒子元 素在主轴(横轴)方向上的对齐方式 ...

  9. OpenGl太阳地球月亮运动系统

    在讲解这个运动系统,首先我们的来讲解OpenGl里有关几个图形变换的知识,这里就以球为例,我们需要知道将球平移,旋转的2个知识.因为系统必须用到平移和旋转. 1 平移变换: glTranslatef( ...

  10. three.js旋转,材质,灯光使用 —— 太阳地球月亮运动

    import * as THREE from 'three' //引入控制器 import { OrbitControls } from 'three/examples/jsm/controls/Or ...

最新文章

  1. 高校人工智能热的“冷”思考
  2. JAVA集合迭代遍历和特性介绍
  3. 吴恩达深度学习笔记13-Course4-Week4【人脸识别和神经风格转换】
  4. 微服务之数据同步Porter 1
  5. PWA(Progressive Web App)入门系列:Notification
  6. js手机号中间四位_11位手机号码隐藏中间四位数,学会Substitute函数一键搞定!...
  7. 大数据量下高并发同步的讲解(不看,保证你后悔!)
  8. jvisualvm工具
  9. React环境配置(第一个React项目)
  10. python查单词音标_有没有通过读音或音标就能查出英语单词的办法,比如发音查词软件?...
  11. 淘宝客佣金设置多少合适?淘宝客的佣金是怎么算的?
  12. 公开下载 |《2021技术人的百宝黑皮书》来了!
  13. ArcGIS学习网站
  14. VBA之for循环使用
  15. 小米汽车设计图纸泄露,官方称非最终文件;微软裁员遣散费高达8亿美元,人均获赔54万元;苹果暂停自研Wi-Fi芯片|极客头条...
  16. TXT文件转Pascal voc数据集XML格式标注文件
  17. Typora 标题无法对齐
  18. 安卓系统6.0设置默认打开允许安装来自未知来源的应用的开关
  19. LYNC 2010 RTM版正式公布
  20. python导入随机函数库_python之random库

热门文章

  1. Proof_Of_Work机制
  2. wpsppt页面卷曲在哪里_用PPT制作页面卷角效果,你会吗?
  3. Windows常见基本进程三:dumprep or dumprep进程(Dump Reporting Tool启动项)
  4. 论文解读:Cycle ISP Real Image Restoration via Improved Data Synthesis
  5. 抽奖概率 php_php实现抽奖概率算法代码
  6. java sql date类_java.util.Date和java.sql.Date 一点区别
  7. 基于SDCC的工程化实践
  8. cpu_relax()函数的意义
  9. fastlane实现Android自动化打包
  10. 串行通信又称为点对点通信(PtP),其中点对点如何理解