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()函数,设置运行窗口上显示的标题。
#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;
}