实验8 OpenGL太阳系动画
1.实验目的:
- 熟悉颜色缓存、深度缓存、模板缓存、累计缓存的内容,掌握缓存清除的方法;
- 建立太阳、地球、月亮的运动模型;
- 利用双缓存技术,用动画方式显示模型,加深读者对几何变换、投影变换以及观察变换的理解,并提高利用图形软件包绘制图形的能力。
2.实验内容:
模拟简单的太阳系,如图A.8所示。太阳在中心,地球每365天绕太阳转一周,月球每年绕地球转12周。另外,地球每天24个小时绕它自己的轴旋转。
图A.8 太阳系动画
3.实验原理:
(1)主要用三维平移变换、旋转变换实现太阳、地球、月亮的相对运动。
本节实验绘制了一个简单的太阳系。为了编写这个程序,需要使用glRtate函数让这颗行星绕太阳旋转,并且绕自身的轴旋转。还需要使用glTranslate函数让这颗行星远离太阳系原点,移动到自己的轨道上。可以在glutWireSphere函数中使用适当的参数,在绘制两个球体时指定球体的大小。 为了绘制这个太阳系,首先需要设置一个投影变换和一个视图变换。在这个例子中,可以使用glutPerspective函数和gluLookAt函数。 绘制太阳比较简单,因为它位于全局固定坐标系统的原点,也就是球体函数进行绘图的位置。因此,绘制太阳时并不需要移动,可以使用glRotate*函数绕一个任意的轴旋转。绘制一颗绕太阳旋转的行星要求进行几次模型变换。这颗行星需要每天绕自己的轴旋转一周,每年沿着自己的轨道绕太阳旋转一周。 为了确定模型变换的顺序,可以从局部坐标系统的角度考虑。首先,调用初始的glRotate函数对局部坐标系统进行旋转,这个局部坐标系统最初与全局固定坐标系统是一致的。接着,可以调用glTranslate函数把局部坐标系统移动到行星轨道上的一个位置。移动的距离应该等于轨道的半径。因此,第一个glRotate函数实际上确定了这颗行星从什么地方开始绕太阳旋转(或者说,从一年的什么时候开始)。 第二次调用glRotate函数使局部坐标轴进行旋转,因此确定了这颗行星在一天中的时间。当调用了这些函数变换之后,就可以绘制这颗行星了。
(2)利用双缓存技术实现动画效果。
双缓存技术能在一个屏幕之外的缓冲区内进行渲染,再用交换命令把图形放到屏幕上。双缓存技术的主要用途是: ①有些复杂图形绘制时间较长,但不需要显示绘制图形的所有步骤,只有整幅图像绘制完之后,才将其置于屏幕上; ②用于制作动画,动画中每一帧都再画面外缓冲区绘制,绘制完之后再交换到屏幕上。实际编程过程中,每个OpenGL支持的窗口系统都可以通过调用glutSwapBuffers()来实现前后缓冲区之间的交换。
4.实验代码:
#include <gl/glut.h>
float fEarth = 2.0f; //地球绕太阳的旋转角度
float fMoon = 24.0f; //月球绕地球的旋转角度
void myInit()
{
glEnable(GL_DEPTH_TEST); //启用深度测试
glClearColor(0.0f, 0.0f, 0.0f, 0.8f); //背景为黑色
}
void myReshape(int w, int h)
{
if (0 == h)
h = 1;
glViewport(0, 0, w, h); //设置视区尺寸
glMatrixMode(GL_PROJECTION); //指定当前操作投影矩阵堆栈
glLoadIdentity(); //重置投影矩阵
//指定透视投影的观察空间
gluPerspective(45.0f, (float)w / (float)h, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void myDisplay(void)
{
//清除颜色和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //指定当前操作模型视图矩阵堆栈
glLoadIdentity(); //重置模型视图矩阵
glTranslatef(0.0f, 0.0f, -500.0f); //将图形沿z轴负向移动
glColor3f(1.0f, 0.0f, 0.0f); //画太阳
glutSolidSphere(50.0f, 20, 20);
glColor3f(0.0f, 0.0f, 1.0f);
glRotatef(23.27,0.0,0.0,1.0); //地球与太阳的黄赤交角
glRotatef(fEarth, 0.0f, 1.0f, 0.0f);
glTranslatef(200.0f, 0.0f, 0.0f);
glutSolidSphere(20.0f, 20, 20); //画地球
glPopMatrix();
glPopMatrix();
glRotatef(6.0f, 1.0f, 1.0f, 1.0f);
glRotatef(fMoon, 0.0f, 1.0f, 0.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glTranslatef(30.0f, 0.0f, 0.0f);
glutSolidSphere(5.0f, 20, 20); //画月球
glLoadIdentity();
glFlush();
glutSwapBuffers();
}
void myIdle(void) //在空闲时调用,达到动画效果
{
fEarth += 0.03f; //增加旋转步长,产生动画效果
if (fEarth > 360.0f)
fEarth = 2.0f;
fMoon += 0.24f;
if (fMoon > 360.0f)
fMoon = 24.0f;
myDisplay();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
//窗口使用RGB颜色,双缓存和深度缓存
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(600, 400);
glutCreateWindow("太阳系动画");
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutIdleFunc(&myIdle);
myInit();
glutMainLoop();
return 0;
}
5.实验提高
(1)让实验6的茶壶旋转; (2)让实验7的机器人手臂不停旋转划圈。
- 那些公司网页隐藏的彩蛋
- 你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(下)
- 你真的会玩SQL吗?透视转换的艺术
- 你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(上)
- 你真的会玩SQL吗?实用函数方法汇总
- 你真的会玩SQL吗?冷落的Top和Apply
- 你真的会玩SQL吗?你所不知道的 数据聚合
- 你真的会玩SQL吗?简单的数据修改
- 将Error异常日志从普通日志中剥离
- 一步一步在Windows中使用MyCat负载均衡 下篇
- Android实现TCP断点上传,后台C#服务实现接收
- Android如何制作漂亮的自适布局的键盘
- 实用收藏Linux命令备忘
- 0基础搭建Hadoop大数据处理-环境
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 开源日志管理系统Graylog之Sidecar功能实践
- CentOS-AltArch-7(ARM版)下源码编译MySQL5.7.31
- 用BurpSuit的Burpy插件搞定WEB端中的JS加密算法
- CentOS7下安装文档协作工具Confluence7.2.1
- caret包进行机器学习
- 容器化Go应用--基础镜像的未知时区问题
- 写给自己的Object和Function的3个灵魂拷问
- 48. Vue路由-使用命名视图实现经典布局
- 47. Vue使用children属性实现路由嵌套
- RecyclerView的缓存机制和内存优化
- 使用Anchore Enine来完善DevSecOps工具链
- PyTorch版CenterNet训练自己的数据集
- SpringBoot2 整合FreeMarker模板,完成页面静态化处理
- PHP多文件上传格式化
- NDK开发案例 | C/C++调用java层代码