利用OpenGL模拟太阳系

一、实验目的与要求

1、了解OpenGL编程,并熟悉OpenGL的主要功能、绘制流程和基本语法,学会配置OpenGL坏境,并在该环境中编程绘图;
2、利用所学知识(如圆等基本图形的绘制,平移、旋转等三维几何变换,透视投影,三维观察,消隐等),模拟一个动画实体或场景;
3、学会调用OpenGL库中的函数,形成用OpenGL实现预期功能、解决问题的思路,对平时所学知识进行实践,达到融会贯通。

二、实验内容

程序分在5个函数中实现:
1、Initial()
在该函数中,主要通过调用glClearColor(),实现对背景的设置。为了模拟宇宙,达到更好的视觉效果,将背景设置为黑色。
2、ChangeSize()
在该函数中主要实现对视区的设置。通过调用glViewport()函数,对视区尺寸进行设置。通过调用gluPerspective()函数,对透视投影的观察空间进行设置,后期运行时,可根据实际情况随时调整,以达到更好的效果。
3、Display()
该函数是最为重要的函数,大部分功能均在此函数中实现。
首先,通过调用glTranslatef()函数,使初始位置沿z轴负向移动一段距离。
然后,调用glColor3f()函数,选择太阳的颜色。调用glutSolidSphere()函数,绘制太阳。绘制完成后,调用glPushMatrix()函数,保存当前的模型视图矩阵。
之后,由里向外绘制八大行星的公转轨道。调用glColor3f()函数,选定轨道的颜色。调用glSolidTorus()函数,依次改变半径,绘出轨道。
再后,依次从里向外依次绘制水星、金星、地球、火星、木星、土星、天王星、海王星。调用glPopMatrix()函数,恢复模型视图矩阵。调用glPushMatrix()函数,保存当前的模型视图矩阵。调用glColor3f()函数,选择行星的颜色。调用glRotatef()函数,使行星绕z轴旋转一定的角度,即达到公转效果。(公转速度满足离太阳越远,速度越慢的定性规律。)调用glTranslatef()函数,平移一段距离,到达该行星的预定轨道。调用glRotatef()函数,使行星自转。(金星的自转方向与其他行星不同,加以区分。)调用glutSolidSphere()函数,绘制行星。(使得各行星大小,符合定性规律。)同时,对函数glRotatef()中的参数fElect进行循环处理, 增加旋转步长,产生动画效果。
其中,在绘制地球之后,绘制火星之前,进行月球的绘制。月球的绘制与上述行星的绘制过程基本相同。不过,因为月球是以地球为中心公转,故无需调用glPushMatrix()函数。
最后,调用glutSwapBuffers()函数,交换缓冲区,将已渲染好的效果拿出来实现。
4、TimerFunc()
在该函数中,主要通过调用glutTimerFunc()函数,实现对画面的不断刷新,以达到动画的效果。
5、main()
在主函数中,对上述函数进行调用,使程序按期望的效果运行。同时,通过调用glutInitDisplayMode()函数,设置窗口使用RGB颜色、双缓存和深度缓存。通过调用glutCreateWindow()函数,设置运行窗口上显示的标题。

三、实验结果

利用OpenGL模拟太阳系_第1张图片利用OpenGL模拟太阳系_第2张图片

四、源程序

#include
void Initial()
{
	glEnable(GL_DEPTH_TEST);       // 启用深度测试
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	//背景为黑色
}
void ChangeSize(int w, int h)
{
	if (h == 0)	h = 1;
	glViewport(0, 0, w, h);               // 设置视区尺寸
	glMatrixMode(GL_PROJECTION);    // 指定当前操作投影矩阵堆栈
	glLoadIdentity();                   // 重置投影矩阵
	GLfloat fAspect;
	fAspect = (float)w / (float)h;            // 计算视区的宽高比
	gluPerspective(88.0, fAspect, 1.0, 500.0); // 指定透视投影的观察空间
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
void Display(void)
{
	static float fElect1 = 0.0f;  // 水星绕太阳旋转的角度
	static float fElect2 = 0.0f;  // 金星绕太阳旋转的角度
	static float fElect3 = 0.0f;  // 地球绕太阳旋转的角度
	static float fElect4 = 0.0f;  // 火星绕太阳旋转的角度
	static float fElect5 = 0.0f;  // 木星绕太阳旋转的角度
	static float fElect6 = 0.0f;  // 土星绕太阳旋转的角度
	static float fElect7 = 0.0f;  // 天王星绕太阳旋转的角度
	static float fElect8 = 0.0f;  // 海王星绕太阳旋转的角度
	static float fElect9 = 0.0f;  // 月球绕地球旋转的角度
	static float fElect10 = 0.0f;  // 除金星外其他星体自转的角度
	static float fElect11 = 0.0f;  // 金星自转的角度
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色和深度缓冲区
	glMatrixMode(GL_MODELVIEW);  // 指定当前操作模型视图矩阵堆栈
	glLoadIdentity();                  // 重置模型视图矩阵
	glTranslatef(0.0f, 0.0f, -300.0f);	   //将图形沿z轴负向移动
	glColor3f(1.0f, 0.1f, 0.1f);		//太阳的颜色
	glutSolidSphere(20.0f, 15, 15);      // 绘制太阳
	glPushMatrix();                  // 保存当前的模型视图矩阵

	glColor3f(0.4f, 0.4f, 0.4f);		//行星公转轨道的颜色
	glutSolidTorus(0.5f, 50.0f, 100, 50);	//绘制水星公转轨道
	glutSolidTorus(0.5f, 80.0f, 100, 50);	//绘制金星公转轨道
	glutSolidTorus(0.5f, 110.0f, 100, 50);	//绘制地球公转轨道
	glutSolidTorus(0.5f, 140.0f, 100, 50);	//绘制火星公转轨道
	glutSolidTorus(0.5f, 170.0f, 100, 50);	//绘制木星公转轨道
	glutSolidTorus(0.5f, 200.0f, 100, 50);	//绘制土星公转轨道
	glutSolidTorus(0.5f, 230.0f, 100, 50);	//绘制天王星公转轨道
	glutSolidTorus(0.5f, 260.0f, 100, 50);	//绘制海王星公转轨道

	glPopMatrix();	//恢复模型视图矩阵
	glPushMatrix(); 	// 保存当前的模型视图矩阵
	glColor3f(0.8f, 0.8f, 0.8f);  //水星的颜色
	glRotatef(fElect1, 0.0f, 0.0f, 1.0f);   // 公转
	glTranslatef(50.0f, 0.0f, 0.0f);       // 平移一段距离
	glRotatef(fElect10, 0.0f, 0.0f, 1.0f);  //自转
	glutSolidSphere(7.0f, 15, 15);       // 画出水星
	fElect1 += 12.0f;     // 增加旋转步长,产生动画效果
	if (fElect1 > 360.0f)	fElect1 = 12.0f;

	glPopMatrix();       // 恢复模型视图矩阵
	glPushMatrix();      // 保存当前的模型视图矩阵*/
	glColor3f(1.0f, 0.55f, 0.0f);	//金星的颜色
	glRotatef(fElect2, 0.0f, 0.0f, 1.0f);		//公转
	glTranslatef(80.0f, 0.0f, 0.0f);      // 平移一段距离
	glRotatef(fElect11, 0.0f, 0.0f, 1.0f); 	//自转
	glutSolidSphere(5.0f, 15, 15);       // 画出金星
	fElect2 += 10.0f;     // 增加旋转步长,产生动画效果
	if (fElect2 > 360.0f)	fElect2= 10.0f;

	glPopMatrix();       // 恢复模型视图矩阵
	glPushMatrix();      // 保存当前的模型视图矩阵*/
	glColor3f(0.0f, 0.0f, 0.55f);		//地球的颜色
	glRotatef(fElect3, 0.0f, 0.0f, 1.0f);		//公转
	glTranslatef(110.0f, 0.0f, 0.0f);      // 平移一段距离
	glRotatef(fElect10, 0.0f, 0.0f, 1.0f);	//自转
	glutSolidSphere(7.0f, 15, 15);       // 画出地球
	fElect3 += 9.0f;     // 增加旋转步长,产生动画效果
	if (fElect3 > 360.0f)	fElect3 = 9.0f;

	glColor3f(1.0f, 1.0f, 0.0f);	//月球的颜色
	glRotatef(fElect9, 0.0f, 0.0f, 1.0f);		//公转
	glTranslatef(10.0f, 0.0f, 0.0f);      // 平移一段距离
	glRotatef(fElect10, 0.0f, 0.0f, 1.0f);	//自转
	glutSolidSphere(2.0f, 15, 15);       // 画出月球
	fElect9 += 100.0f;     // 增加旋转步长,产生动画效果
	if (fElect9 > 360.0f)	fElect9 = 100.0f;

	glPopMatrix();       // 恢复模型视图矩阵
	glPushMatrix();      // 保存当前的模型视图矩阵*/
	glColor3f(0.82f, 0.41f, 0.12f);	//火星的颜色
	glRotatef(fElect4, 0.0f, 0.0f, 1.0f);		//公转
	glTranslatef(140.0f, 0.0f, 0.0f);      // 平移一段距离
	glRotatef(fElect10, 0.0f, 0.0f, 1.0f);	//自转
	glutSolidSphere(6.0f, 15, 15);       // 画出火星
	fElect4 += 8.0f;     // 增加旋转步长,产生动画效果
	if (fElect4 > 360.0f)	fElect4 = 8.0f;

	glPopMatrix();       // 恢复模型视图矩阵
	glPushMatrix();      // 保存当前的模型视图矩阵*/
	glColor3f(1.0f, 0.84f, 0.0f);		//木星的颜色
	glRotatef(fElect5, 0.0f, 0.0f, 1.0f);		//公转
	glTranslatef(170.0f, 0.0f, 0.0f);      // 平移一段距离
	glRotatef(fElect10, 0.0f, 0.0f, 1.0f);	//自转
	glutSolidSphere(10.0f, 15, 15);       // 画出木星
	fElect5 += 6.0f;     // 增加旋转步长,产生动画效果
	if (fElect5 > 360.0f)	fElect5 = 6.0f;
	
	glPopMatrix();       // 恢复模型视图矩阵
	glPushMatrix();      // 保存当前的模型视图矩阵*/
	glColor3f(0.94f, 0.90f, 0.55f);	//土星的颜色
	glRotatef(fElect6, 0.0f, 0.0f, 1.0f);		//公转
	glTranslatef(200.0f, 0.0f, 0.0f);      // 平移一段距离
	glRotatef(fElect10, 0.0f, 0.0f, 1.0f);	//自转
	glutSolidSphere(9.0f, 15, 15);       // 画出土星
	fElect6 += 4.0f;     // 增加旋转步长,产生动画效果
	if (fElect6 > 360.0f)	fElect6 = 4.0f;

	glPopMatrix();       // 恢复模型视图矩阵
	glPushMatrix();      // 保存当前的模型视图矩阵*/
	glColor3f(0.0f, 0.81f, 0.82f);		//天王星的颜色
	glRotatef(fElect7, 0.0f, 0.0f, 1.0f);		//公转
	glTranslatef(230.0f, 0.0f, 0.0f);      // 平移一段距离
	glRotatef(fElect10, 0.0f, 0.0f, 1.0f);	//自转
	glutSolidSphere(8.0f, 15, 15);       // 画出天王星
	fElect7 += 3.0f;     // 增加旋转步长,产生动画效果
	if (fElect7 > 360.0f)	fElect7 = 3.0f;

	glPopMatrix();       // 恢复模型视图矩阵
	glPushMatrix();      // 保存当前的模型视图矩阵*/
	glColor3f(0.39f, 0.58f, 0.93f);	//海王星的颜色
	glRotatef(fElect8, 0.0f, 0.0f, 1.0f); 	//公转
	glTranslatef(260.0f, 0.0f, 0.0f);      // 平移一段距离
	glRotatef(fElect10, 0.0f, 0.0f, 1.0f);	//自转
	glutSolidSphere(8.0f, 15, 15);       // 画出海王星
	fElect8 += 2.0f;     // 增加旋转步长,产生动画效果
	if (fElect8 > 360.0f)	fElect8 = 2.0f;

	fElect10 += 1.0f;
	if (fElect10 > 360.0f)	fElect10 = 1.0f;
	fElect11 += -1.0f;
	if (fElect10 < -360.0f)	fElect11 = -1.0f;

	glPopMatrix();       // 恢复模型视图矩阵
	glutSwapBuffers();
}
void TimerFunc(int value)
{
	glutPostRedisplay();
	glutTimerFunc(100, TimerFunc, 1);
}
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutCreateWindow("太阳系动画示例");
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(Display);
	glutTimerFunc(500, TimerFunc, 1);     //指定定时器回调函数
	Initial();
	glutMainLoop();
	return 0;
}

你可能感兴趣的:(opengl)