前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实验8 OpenGL太阳系动画

实验8 OpenGL太阳系动画

作者头像
步行者08
发布2020-10-27 14:55:42
2.1K0
发布2020-10-27 14:55:42
举报
文章被收录于专栏:图形学与OpenGL图形学与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.实验代码:

代码语言:javascript
复制
#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的机器人手臂不停旋转划圈。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-10-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.实验目的:
  • 2.实验内容:
  • 3.实验原理:
  • 4.实验代码:
  • 5.实验提高
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档