计算机图形学课程设计报告

课 程 设 计 报告

题 目 旋转四面体

摘要

本文主要描述了计算机图形学中,运用C++和OpenGL来实现的绘制一个实体四面体。其中简单的用glutTimerFunc,glutSpecialFunc等函数实现了用光标键控制其旋转和用键盘上的F1、F2键实现自动旋转功能,并加设两个光源,一个为点光源,一个为聚光源。

关键字:旋转球体 OpenGL glutTimerFunc glutMouseFunc glutMotionFunc

(1)设计内容

运用 C/C++、OpenGL实现。

绘制四面体,并用光标键、鼠标控制其旋转或自动旋转。

实现添加光源、纹理等真实感图形绘制的功能。

界面友好,源程序代码清晰有层次。

(2)将OPENGL中的glut中的文件进行配置

(3)打开C++开发软件

首先打开C++,选择新建工程当中的计算机图形学课程设计报告

路径进行备份,之后选择计算机图形学课程设计报告

二:需求分析

绘制四面体,明确绘制四面体的函数体是glutWireTetrahedron();(绘制线框四面体)glutSolidTetrahedron();(绘制实体四面体),

键盘控制自动旋转的开始和停止,添加一个BOOR变量。

其他功能实现需编程实现

,然后选择存储,最后进入编写程序界面。

三:详细设计

初始化:

首先定义定态变量

计算机图形学课程设计报告

设置菜单项的默认参数是1,即线框四面体(下文介绍),另外设置默认绕X轴,Y轴的旋转参数,然后进行光源初始化,设置背景颜色等

代码如下:

void Initial(void)

{

glClearColor(0.0f,1.0f,1.0f,1.0f);

glColor3f(0.0f,0.0f,0.0f);

GLfloat mat_ambient[]={0.2f,0.2f,0.2f,1.0f};

GLfloat mat_diffuse[]={0.8f,0.8f,0.8f,1.0f};

GLfloat mat_specular[]={1.0f,1.0f,1.0f,1.0f};

GLfloat mat_shininess[]={50.0f};

GLfloat light0_diffuse[]={0.0f,0.0f,1.0f,1.0f};

GLfloat light0_position[]={1.0f,1.0f,1.0f,0.0f};

GLfloat light1_ambient[]={0.2f,0.2f,0.2f,1.0f}; 设置菜单项的默认参数是1,即线框四面体(下文介绍),另外设置默认绕X轴,Y轴的旋转

GLfloat light1_diffuse[]={1.0f,0.0f,0.0f,1.0f};

GLfloat light1_specular[]={1.0f,0.6f,0.6f,1.0f};

GLfloat light1_position[]={-3.0f,-3.0f,3.0f,1.0f};

GLfloat spot_direction[]={1.0f,1.0f,-1.0f};

//定义材质属性

glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient); //指定材质的环境反射光反射系数

glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse); //指定材质的漫反射光反射系数

glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular); //指定材质的镜面反射光反射系数

glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess); //指定材质的镜面反射指数值 //light0 为漫反射的蓝色点光源

glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse); //指定漫反射光成分

glLightfv(GL_LIGHT0,GL_POSITION,light0_position); //指定光源的位置 //light1 为红色聚光光源

glLightfv(GL_LIGHT1,GL_AMBIENT,light1_ambient); //指定环境光成分

glLightfv(GL_LIGHT1,GL_DIFFUSE,light1_diffuse); //指定漫反射光成分

glLightfv(GL_LIGHT1,GL_SPECULAR,light1_specular); //指定镜面光成分

glLightfv(GL_LIGHT1,GL_POSITION,light1_position); //指定光源位置

glLightf(GL_LIGHT1,GL_SPOT_CUTOFF,30.0); //指定聚光截止角

glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION,spot_direction); //指定聚光灯的方向

glEnable(GL_LIGHTING); //启用光源

glEnable(GL_LIGHT0); //启用光源

glEnable(GL_LIGHT1); //启用光源

}

设置坐标系参数:

运用ChangeSize()函数进行设置

代码如下:

void ChangeSize(int w,int h)

{

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(-1.5f,1.5f,-1.5f,1.5f);

}

绘制正四面体:

实体四面体代码是

添加菜单项:

菜单函数编写

绘制实体四面体glutSolidTetrahedron();

编写Display函数,运行时执行该函数

void Display(void)

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW); //指定设置模型视图变换参数

glLoadIdentity(); //消除以前的变换

glRotatef(xRot,1.0f,0.0f,0.0f); //绕x轴旋转图形

glRotatef(yRot,0.0f,1.0f,0.0f); //绕y轴旋转图形

glutSolidTetrahedron(); //绘制实体正四面体

glPushMatrix(); //保存当前的模型视图矩阵

glFlush();

}

键盘F1,F2实现自动旋转的开始和停止:

光标键控制旋转:

当程序运行时,四面体为静止的,当按下F1键后,四面体开始自动旋转,当按下F2键后四面体停止自动旋转,变为静止状态。

在程序开始时先定义一个布尔变量控制自动旋转的开始和停止:

函数的作用下进行有时间间隔的自动旋转

另外当按下键盘的上下左右键时,图形就会旋转,否则不旋转,

函数代码如下:

bool tm=false; //定义一个布尔函数,实现自动旋转的开始和停止

再顶义一个Timer函数,实现四面体按每100毫秒转动一次

void TimerFunc(int value)

{

glutPostRedisplay();

xRot-=5.0f;yRot+=5.0f;

glutPostRedisplay(); //窗口执行重绘操作

if(tm)

glutTimerFunc(100,TimerFunc,1);

}

以下的代码就是键盘光标和自动旋转的代码:

void SpecialKeys(int key,int x,int y)

{

//光标键控制图形的选转

if(key==GLUT_KEY_UP) xRot-=5.0f;

}

Main函数的调用编写:

当对图形的绘制,功能的代码编写完之后,然后进行最后的main函数的编写,调用所有编写的函数即可完成编写工作,代码如下:

int main(int argc, char* argv[])

{

glutInitWindowSize(400,400);

glutInitWindowPosition(100,100);

glutCreateWindow("OpenGL四面体绘制函数示例,多光源四面体");

glutDisplayFunc(Display); glutInit(&argc,argv);

glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); //窗口使用RGB颜色和单缓存

if(key==GLUT_KEY_DOWN)

xRot+=5.0f;

if(key==GLUT_KEY_LEFT)

yRot-=5.0f;

if(key==GLUT_KEY_RIGHT)

yRot+=5.0f;

if(xRot>355.0f)

xRot=0.0f;

if(xRot<-1.0f)

xRot=355.0f;

if(yRot>356.0f)

yRot=0.0f;

if(yRot<-1.0f)

yRot=355.0f;

switch(key) {

case GLUT_KEY_F1: //按F1键实现自动旋转

tm=true;

glutTimerFunc(100,TimerFunc,1); //指定定时器回调函数

break;

case GLUT_KEY_F2: //按F2键停止自动旋转

tm=false;

}

glutPostRedisplay(); //窗口执行重绘操作

glutReshapeFunc(ChangeSize);

glutSpecialFunc(SpecialKeys);

Initial();

glutMainLoop();

return 0;

}

编写到现在已经完成,接下来进行程序的调试,运行阶段

系统测试:

最后根据题目要求对系统进行调试运行 实体四面体运行结果如下:

计算机图形学课程设计报告

总结:

经过不断的对系统进行修补,测试,图形所需要的基本功能已经基本实现,已经达到预期所需要的结果,能够假设光源,用关标键控制图形的旋转,按下F1、F2键实现自动旋转的开始和停止等功能,但是纹理功能没有实现,以后注意参考资料,达到此项功能。

参考资料

《计算机图形学基础》(第二版) 陆枫 电子工业出版社 《数据结构》 严蔚敏 高等教育出版社

 

第二篇:《计算机图形学》课程设计报告

《计算机图形学》课程设计报告

课题名称:         Solar System(大阳系)            

课题负责人名(学号): 曾睿(0643111150)

同组成员名单(角色): 曾睿(0643111150) 

                                         

                                         

指导教师:    李征                       

评阅成绩:                               

评阅意见:                               

                                         

                                         

提交报告时间:2008 年 12 月 17 日


Solar System(太阳系)

软件工程 专业

学生 曾睿      指导老师   李征

[摘要]太阳系(Solar System)是以太阳为中心,和所有受到太阳重力约束的天体的集合体,主要包括太阳,八大行星,以及卫星.此课题模拟太阳系围绕太阳运转的模型,以太阳,八大行星和月球形成大致的体系结构,以VC6.0为平台用OpenGL基础知识实现从不同角度观测太阳系.

关键词:OpenGL VC6.0 太阳系 运转 角度

一、实验名称: Solar System(太阳系)

二、  实验的目的和要求:

1.熟悉OpenGL基础函数

2.通过程序模拟太阳系运行

3.实现改变视角观测太阳系

三、实验的环境:

1硬件环境:CPU Intel Pentium D ,1G内存

2.软件环境:

操作系统:Windows xp SP2

编译软件及版本:vc6.0  OpenGL环境

四、系统描述

1.太阳

太阳是恒星,能够自转,体积是太阳系中最大的,能够发光,处于太阳系中心位置.

2.八大行星

八大行星按与太阳距离从近到远分别为: 水星, 金星,地球,火星,木星,土星,天王星,海王星,各有各的大小,其中以木星最大,以各自不同的公转速度绕太阳运行,并自转.

3.月球

月球是围绕地球旋转的卫星.体积是系统中最小的,旋转周期比较快。

. 理论基础:

用windows api创建窗口,使用OpenGL绘制函数绘制球体,实现位图文件读取,并转换为纹理,使用系统时间控制球体转动,设置视点视角,通过改变视角从不同角度观测.

所使用的计算机图形学理论基础:

1. 3D管道中的几何变换

旋转矩阵行向量为该矩阵坐标系在原坐标系上的坐标,列向量为原坐标系的向量在本旋转矩阵坐标系上的坐标。

旋转是欧氏变换;旋转、放缩是线性变换;旋转、放缩、平移是仿射变换;旋转、放缩、平移、透视投影是射影变换。

线性变换在四维空间,仿射变换在三维空间,射影必须采用摄像坐标系,仿射变换是到自身的一类变换.

齐次坐标系就是将一个原本是n维的向量用一个n+1维向量来表示。 实数。显然一个向量的齐次表示是不唯一的,齐次坐标的h取不同的值都表示的是同一个点,比如齐次坐标[8,4,2]、[4,2,1]表示的都是二维点[2,1]。

它提供了用矩阵运算把二维、三维甚至高维空间中的一个点集从一个坐标系变换到另一个坐标系的有效方法。

4维坐标的旋转到了3维坐标就是平移.

世界坐标系描述了物体在空间的位置,角度在世界坐标系中可以设定物体的位置,决定物体以什么方式进行放置

局部坐标系描述了物体的形状,大小,样式等,可以在这一坐标系中设定物体的形状

当我们在虚拟场景中放置物体时,必须将其从局部坐标系转换到世界坐标系

局部到世界的坐标系转换可以看做向量的转化

局部坐标系到世界坐标系:旋转,放缩,平移

世界坐标系到观测坐标系:平移,旋转。

透视投影,就是以中心投影为依据所作的透视图象。

正交投影将物体垂直的投影在屏幕上,在正交投影当中,物体的大小不会随着视口屏幕等参数的改变而变化。在正交投影中,三维物体的坐标沿平行线投影到观察平面上,它保持物体的有关比例不变。

虚拟摄像机的内部参数是指摄像机的几何和光学参数,包括焦距、缩放系数、摄像机光轴和像平面的交点,外部参数主要是指摄像机坐标系与世界坐标系的转换矩阵.

OPENGL中有Glulookat, Glperspective, Glmodelviewmatrix等函数可以完成对摄像机内、外参数的指定.

void gluLookAt(

GLdouble eyex,

GLdouble eyey,

GLdouble eyez,

GLdouble centerx,

GLdouble centery,

GLdouble centerz,

GLdouble upx,

GLdouble upy,

GLdouble upz

);

eye=(eyex, eyey, eyez)是视点(原点)的位置

center = (centerx, centery, centerz)是视口中心点的位置

center - eye是z轴负方向

z = (eye - center) / |eye - center|

up = (upx, upy, upz) - eye表示上方

x轴正方向x = up × z / |up × z|

y轴正方向(就是正上方)y = z × x

gluLookAt()相当于设定平移,旋转,倾斜三个基本的矩阵.

void gluPerspective(

  GLdouble fovy, //角度

  GLdouble aspect,//视景体的宽高比

  GLdouble zNear,//沿z轴方向的两裁面之间的距离的近处

GLdouble zFar //沿z轴方向的两裁面之间的距离的远处

)

2. 2D管道中的像素操作

几何图形像素化就是将几何物体按照一些设定好的方法投影到屏幕上的过程和方法.

像素化就是在图像上每隔一段距离取一个点,作为该区域的颜色代表。将其数字化。这种存储转化叫做像素化。因为计算机不能处理无限的,只能处理有限的,这样做能更好的抽象出对象,并处理。用几何线段和几何连接构成的图形叫做几何图形,一般是有点和线构成面,像素图形是像素化后得到的图形,只有这样才能处理这些图形.

斜率-截距方程主要使用Bresenham画线算法逐像素的进行绘制如y=kx+m的方程

参数方程中的圆因为各方位一致,所以只需考虑8分之1的段即可,而椭圆参数方程

则要考虑4分支1的段。直线段在像素化过程中要先利用bresnham算法,d误差率被用来计算坐标,公式di+1=di+k(xi+1-xi),根据d是否大于0.5决定y坐标是否递增。

图像出现不准确的锯齿状的边缘等现象叫走样,产生原因是由于低频采样不充分而造成的信息失真或由离散量表示连续量引起的失真.

超采样方法来进行直线反走样.原理是将每个像素分成n×n个子像素,然后在子像素级对直线进行光栅化,这样就可以得到每个像素中被激活的子像素的个数.在n×n伪光栅上,可以光栅化的子像素最多为n个.每个物理像素的光强与其被激活的子像素数与n的比值成正比.假设一个物理像素中被激活的子像素有m个,其可能的最大光强为Imax,为该像素的光强.

3. 光照模型

环境光是模拟2次、3次以及多次光反射形成的,是来自于周围环境没有固定方向的光,在物体和周围环境之间多次反射后,最终达到平衡时的一种光,又称为背景光.环境光没有空间和方向上的特征,它在任何方向上的分布都相同,在所有方向上和所有物体表面上投射的环境光的量都是恒定不变的.

环境光主要是通过背景光影与主体形成某种映衬和对比,达到突出主体的目的,还有表现特定环境、时间或造成某种特殊气氛和影调等作用.

平行光源光线平行发散,点光源光线球体发散,二者在特定条件可以转化。

聚光光源使用聚光镜头或反射镜等聚成的光,点光型比较简单.

点光源达到无穷远就成为平行光源,点光源入射光源不同,聚光(点光源加衰减)入射方向不一样。

平行光源发出光线各线条平行,点光源从某一点发散出光线,聚光光源从某一点按一定的张角发射光线,面光源是一个平面发出光线.

漫反射是由物体表面的粗糙不平引起的,它均匀地向各个方向传播,与视点无关。漫反射由于是球面型的,所以向四面八方都反射,镜面反射处理为平行光的反射,具体处理的时候,不记录具体值,而采用路径算法,大大简化了计算量。一般来说,从物体表面反射或折射出来的光的强度取决于光源的位置与光的强度、物体表面的位置和朝向、表面材质的性质和视点的位置。对于理想镜面,反射光都将集中在镜面的反射方向上,视线只有在与反射光线重合时才能观察到镜面反射光。但是,对于那些非理想的镜面,由于表面实际上是由许多不同朝向的微小平面组成,镜面反射光将分布于表面的镜面反射方向的周围.

全局光照模型中射线跟踪算法的基本原理:

由光源发出的光到达景物表面后,产生反射和折射,简单光照明模型和简单光透射模型模拟了这两种现象。

在简单光照明模型中,反射被分为理想漫反射和镜面反射光,在简单光透射模型中,把透射光分为理想漫透射光和规则透射光。

由光源发出的光称为直接光,景物对直接光的反射或折射称为直接反射和直接折射,相对地,把景物表面间对光的反射和折射称为间接光,间接反射、间接折射,这些是光线在景物之间的传播方式,是光线跟踪算法的基础。

最基本的光线跟踪算法是跟踪镜面反射和折射。

从光源发出的光遇到景物的表面,发生反射和折射,光就改变方向,沿着反射方向和折射方向继续前进,直到遇到新的景物。但是光源发出光线,经反射与折射,只有很少的部分可以进入人的眼睛。因此实际光线跟踪算法的跟踪方向与光传播的方向是相反的,而是视线跟踪,由视点向象素发出一根射线,与第一个景物相交后,在其反射与折射方向上进行跟踪。

.详细设计:

设置视觉坐标系:

利用实用库函数gluLookAt()设置视觉坐标系。

void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);

该函数定义一个视图矩阵,并与当前矩阵相乘。eyex,eyey,eyez指定视点的位置;centerx,centery,centerz 指定参考点的位置;upx,upy,upz 指定视点向上的方向(如图)

视点E、参考点C、视点向上的方向U实际上就是设定了一个视觉坐标系。

模型变换:

是在世界坐标系中进行的。在这个坐标系中,可以对物体实施平移glTranslatef()、旋转glRotatef()。

glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度

glTranslatef(1.7f, 0.0f, 0.0f);     // 将坐标系右移1.7f

绘制球体:

每个三维物体包括两种形式:网状体(wire)和实心体(solid)。网状体没有平面法向,而实心体有,能进行光影计算,有光照时采用实心体模型。

 GLUquadricObj *quadric;      // 建立二次曲面对象

quadric = gluNewQuadric();// 建立一个曲面对象指针

gluSphere(quadric, 0.3f, 32, 32);   // 绘制太阳球体

矩阵入栈和矩阵出栈:

void glPushMatrix(); 
void glPopMatrix(); 

所有几何投影变换都是矩阵相乘的结果。这两个重要函数保存一个初始坐标点.

释放缓存:

不考虑信息缓存区是否放满,强制主机把命令传输出去。在高档体系结构中,每种操作是由图形硬件的不同部分分别执行的,CPU负责控制,这样才可以保证计算机资源的充分利用,提高作图质量和作图速度。OpenGL中提供了解决这个问题的操作。

glFlush();

建立窗口:

glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT); // 初始化窗口大小glutInitWindowPosition(30,30);       // 初始化窗口位置glutCreateWindow(WIN_TITLE);           // 建立窗口

、源代码:

loadTexture.h

#ifndef LOADTEXTURE

#define LOADTEXTURE

// 纹理图像结构

typedef struct

{

       int imgWidth;                      // 纹理宽度

       int imgHeight;                     // 纹理高度

       unsigned char byteCount;      // 每个象素对应的字节数,3:24位图,4:带alpha通道的24位图

       unsigned char *data;             // 纹理数据

}TEXTUREIMAGE;

// BMP文件头

#pragma pack(2)

typedef struct {

       unsigned short bfType;                 // 文件类型

       unsigned long   bfSize;                     // 文件大小

       unsigned short bfReserved1;   // 保留位

       unsigned short bfReserved2;   // 保留位

       unsigned long bfOffBits;              // 数据偏移位置

}BMPFILEHEADER;

#pragma pack()

// BMP信息头

typedef struct {

       unsigned long biSize;                  // 此结构大小

       long               biWidth;         // 图像宽度

       long               biHeight;        // 图像高度

       unsigned short biPlanes;        // 调色板数量

       unsigned short biBitCount;            // 每个象素对应的位数,24:24位图,32:带alpha通道的24位图

       unsigned long biCompression;      // 压缩

       unsigned long biSizeImage;   // 图像大小

       long               biXPelsPerMeter;// 横向分辨率

       long               biYPelsPerMeter;// 纵向分辨率

       unsigned long biClrUsed;             // 颜色使用数

       unsigned long biClrImportant;      // 重要颜色数

}BMPINFOHEADER;

//载入BMP位图文件

void LoadBmp(char *filename,  TEXTUREIMAGE *textureImg);

//生成纹理

void MakeTexture(TEXTUREIMAGE textureImg, GLuint * texName);

#endif

loadTexture.cpp

#include <stdio.h>

#include <stdlib.h>

#include <memory.h>

#include <string.h>

#include <GL/glut.h>

#include "loadTexture.h"

void LoadBmp(char *filename, TEXTUREIMAGE *textureImg)    // 载入图片

{

    int i, j;

       FILE *file;

       BMPFILEHEADER bmpFile;

       BMPINFOHEADER bmpInfo;

       int pixel_size;

       // 初始化纹理数据

       textureImg->imgWidth = 0;

       textureImg->imgHeight = 0;

       if (textureImg->data != NULL)

       {

              delete []textureImg->data;

       }

       // 打开文件

       file = fopen(filename, "rb");

       if (file == NULL)

       {

              return;

       }

       // 获取文件头

       rewind(file);

       fread(&bmpFile, sizeof(BMPFILEHEADER), 1, file);

       fread(&bmpInfo, sizeof(BMPINFOHEADER), 1, file);

       // 验证文件类型

       if (bmpFile.bfType != 0x4D42)

       {

              return;

       }

       // 获取图像色彩数

       pixel_size = bmpInfo.biBitCount >> 3;

      

       // 读取文件数据

       textureImg->data = new unsigned char[bmpInfo.biWidth * bmpInfo.biHeight * pixel_size];

      

      

       for(i = 0 ; i < bmpInfo.biHeight; i++)

       {

              fseek(file, bmpFile.bfOffBits + (bmpInfo.biHeight - i - 1) * bmpInfo.biWidth * pixel_size, SEEK_SET);   

              for (j = 0; j < bmpInfo.biWidth; j++)

              {

                     // 红色分量

                     fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 2, sizeof(unsigned char), 1, file);

                     // 绿色分量

                     fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 1, sizeof(unsigned char), 1, file);

                     // 蓝色分量

                     fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 0, sizeof(unsigned char), 1, file);

                     // Alpha分量

                     if (pixel_size == 4)

                     {

                            fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 3, sizeof(unsigned char), 1, file);

                     }

              }

       }

       // 记录图像相关参数

       textureImg->imgWidth = bmpInfo.biWidth;

       textureImg->imgHeight = bmpInfo.biHeight;

       textureImg->byteCount = pixel_size;

       fclose(file);

}

void MakeTexture(TEXTUREIMAGE textureImg, GLuint * texName)        //转换为纹理

{

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

       glGenTextures(1,texName);

       glBindTexture(GL_TEXTURE_2D , *texName);

       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureImg.imgWidth,textureImg.imgHeight, 0,

                       GL_RGB, GL_UNSIGNED_BYTE, textureImg.data);

}

Solar.cpp

#include <windows.h>

#include <GL/glut.h>

#include <math.h>

#include "loadTexture.h"

// 定义窗口的标题、宽度、高度、全屏布尔变量

#define WIN_TITLE "模拟太阳系--0643111150--曾睿"

const int WIN_WIDTH = 800;

const int WIN_HEIGHT = 600;

BOOL isFullScreen = FALSE;                     // 初始不为全屏

#define  DEG_TO_RAD 0.017453

float angle=0.0;

static GLdouble viewer[]= {0,0,0,0,0};              // 初始化视角

GLUquadricObj *quadric;                        // 建立二次曲面对象

GLfloat angle_Z;                               // 星空旋转角度

bool   g_bOrbitOn = true;                       // 控制转动暂停

float  g_fSpeedmodifier = 1.0f;

// 时间控制

float  g_fElpasedTime;

double g_dCurrentTime;

double g_dLastTime;

GLfloat LightAmbient[] = { 1.0f, 1.0f, 1.0f, 0.0f };        // 环境光参数

GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 0.0f };         // 漫射光参数

GLfloat LightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f };         // 光源的位置

// 纹理图象

TEXTUREIMAGE  skyImg;

TEXTUREIMAGE  sunImg;

TEXTUREIMAGE  rayImg;

TEXTUREIMAGE  mercuImg;

TEXTUREIMAGE  venusImg;

TEXTUREIMAGE  earthImg;

TEXTUREIMAGE  marsImg;

TEXTUREIMAGE  jupiterImg;

TEXTUREIMAGE  saturnImg;

TEXTUREIMAGE  uranusImg;

TEXTUREIMAGE  neptuneImg;

TEXTUREIMAGE  moonImg;

GLuint  texture[12];                                // 纹理数组

// 星球速度定义

static float fSunSpin    = 0.0f;                      // 太阳自转速度

static float fMercuSpin  = 0.0f;                      // 水星自转速度

static float fMercuOrbit = 0.0f;                       // 水星公转速度

static float fVenusSpin  = 0.0f;                      // 金星自转速度

static float fVenusOrbit = 0.0f;                       // 金星公转速度

static float fEarthSpin  = 0.0f;                       // 地球自转速度

static float fEarthOrbit = 0.0f;                        // 地球公转速度

static float fMarsSpin   = 0.0f;                       // 火星自转速度

static float fMarsOrbit  = 0.0f;                       // 火星公转速度

static float fJupiterSpin   = 0.0f;                      // 木星自转速度

static float fJupiterOrbit  = 0.0f;                      // 木星公转速度

static float fSaturnSpin   = 0.0f;                      // 土星自转速度

static float fSaturnOrbit  = 0.0f;                      // 土星公转速度

static float fUranusSpin   = 0.0f;                      // 天王星自转速度

static float fUranusOrbit  = 0.0f;                      // 天王星公转速度

static float fNeptuneSpin   = 0.0f;                     // 海王星自转速度

static float fNeptuneOrbit  = 0.0f;                      // 海王星公转速度

static float fMoonSpin   = 0.0f;                       // 月亮自转速度

static float fMoonOrbit  = 0.0f;                        // 月亮公转速度

// 初始化OpenGL

void InitGL(void)

{

       glClearColor(0.0f, 0.0f, 0.0f, 0.5f);

    glClearDepth(2.0f);

    glEnable(GL_DEPTH_TEST);

    glDepthFunc(GL_LEQUAL);

    glShadeModel(GL_SMOOTH);

    glEnable(GL_CULL_FACE);

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

      

       glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);    // 设置环境光

    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);     // 设置漫反射光

       glEnable(GL_LIGHTING);                           // 打开光照

    glEnable(GL_LIGHT1);                             // 打开光源1

    // 载入纹理

       glEnable(GL_TEXTURE_2D);                       // 开启2D纹理映射

       MakeTexture(skyImg, &texture[0]);

       MakeTexture(sunImg, &texture[1]);

       MakeTexture(rayImg, &texture[2]);

       MakeTexture(mercuImg, &texture[3]);

       MakeTexture(venusImg, &texture[4]);

       MakeTexture(earthImg, &texture[5]);

       MakeTexture(marsImg, &texture[6]);

       MakeTexture(jupiterImg, &texture[7]);

       MakeTexture(saturnImg, &texture[8]);

       MakeTexture(uranusImg, &texture[9]);

       MakeTexture(neptuneImg, &texture[10]);

       MakeTexture(moonImg, &texture[11]);

      

    quadric = gluNewQuadric();                  // 建立一个曲面对象指针

    gluQuadricTexture(quadric, GLU_TRUE);      // 建立纹理坐标

    gluQuadricDrawStyle(quadric, GLU_FILL);     // 面填充

}

void Display(void)

{

       glLoadIdentity();

       // 设置观察点的位置和观察的方向

       gluLookAt(viewer[0],viewer[1],viewer[2],viewer[3],viewer[4],-5,0,1,0);

       // 获得系统时间使太阳系有动态效果

       g_dCurrentTime = timeGetTime();

    g_fElpasedTime = (float)((g_dCurrentTime - g_dLastTime) * 0.0005);

    g_dLastTime    = g_dCurrentTime;

      

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

       glMatrixMode( GL_MODELVIEW );

      

    glTranslatef(0.0f, 0.0f, -5.0f);              // 将坐标系移入屏幕5.0f

    glRotatef(10, 1.0f ,0.0f, 0.0f);              // 将坐标系绕x轴旋转10度

    glEnable(GL_LIGHT0);                   // 打开光源0

    /**********************************绘制背景星空********************************************/

    glPushMatrix ();                         // 当前模型矩阵入栈

    glTranslatef(-10.0f, 3.0f, 0.0f);

    glRotatef (angle_Z, 0.0f, 0.0f, 1.0f);

    glEnable(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, texture[0]);     // 星空纹理

       // 绘制立方体,此处有问题,失败--!

    glBegin(GL_QUADS);

    glNormal3f( 0.0f, 0.0f, 1.0f);

    glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f);

    glTexCoord2f(6.0f, 0.0f); glVertex3f( 50.0f, -50.0f, -50.0f);

    glTexCoord2f(6.0f, 6.0f); glVertex3f( 50.0f,  50.0f, -50.0f);

    glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f,  50.0f, -50.0f);

    glEnd();

      

    glBegin(GL_QUADS);

    glNormal3f( 0.0f, 0.0f, -1.0f);

    glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f);

    glTexCoord2f(0.0f, 6.0f); glVertex3f( 50.0f, -50.0f, 50.0f);

    glTexCoord2f(0.0f, 0.0f); glVertex3f( 50.0f,  50.0f, 50.0f);

    glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f,  50.0f, 50.0f);

    glEnd();

    glBegin(GL_QUADS);

    glNormal3f( 0.0f, 1.0f, 0.0f);

    glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f);

    glTexCoord2f(6.0f, 6.0f); glVertex3f( 50.0f, -50.0f,  50.0f);

    glTexCoord2f(6.0f, 0.0f); glVertex3f( 50.0f, -50.0f, -50.0f);

    glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, -50.0f,  50.0f);

    glEnd();

    glBegin(GL_QUADS);

    glNormal3f( 0.0f, -1.0f, 0.0f);

    glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, 50.0f, -50.0f);

    glTexCoord2f(0.0f, 0.0f); glVertex3f( 50.0f, 50.0f,  50.0f);

    glTexCoord2f(0.0f, 6.0f); glVertex3f( 50.0f, 50.0f, -50.0f);

    glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f,  50.0f);

    glEnd();

      

    glBegin(GL_QUADS);

    glNormal3f( 1.0f, 0.0f, 0.0f);

    glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f);

    glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f,  50.0f,  50.0f);

    glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, -50.0f,  50.0f);

    glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f,  50.0f, -50.0f);

    glEnd();

    glBegin(GL_QUADS);

    glNormal3f( -1.0f, 0.0f, 0.0f);

    glTexCoord2f(6.0f, 6.0f); glVertex3f(50.0f, -50.0f, -50.0f);

    glTexCoord2f(0.0f, 0.0f); glVertex3f(50.0f,  50.0f,  50.0f);

    glTexCoord2f(6.0f, 0.0f); glVertex3f(50.0f, -50.0f,  50.0f);

    glTexCoord2f(0.0f, 6.0f); glVertex3f(50.0f,  50.0f, -50.0f);

    glEnd();

    glPopMatrix ();                             // 当前模型矩阵出栈

    /**********************************绘制太阳************************************************/  

    glBindTexture(GL_TEXTURE_2D, texture[2]);        // 光晕纹理

    glEnable(GL_BLEND);                           // 开启混合

    glDisable(GL_DEPTH_TEST);                     // 关闭深度测试

    // 绘制太阳光晕

    glDisable(GL_LIGHTING);                        // 关闭光照

    glBlendFunc(GL_SRC_ALPHA,GL_ONE);           // 半透明混合函数

    glColor4f(1.0f, 0.5f, 0.0f, 0.4f);                     // 设置RGBA值

    glBegin(GL_QUADS);

    glNormal3f( 0.0f, 0.0f, 1.0f);

    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);

    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);

    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);

    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);

    glEnd();

    glDisable(GL_BLEND);                           // 关闭混合

    glEnable(GL_DEPTH_TEST);

    glEnable(GL_LIGHTING);                        // 开启光照

    glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // 设置光源1位置

    glBindTexture(GL_TEXTURE_2D, texture[1]);        // 太阳纹理

       // 将坐标系绕Y轴旋转fSunSpin角度,控制太阳自转

       glRotatef(fSunSpin,0.0,1.0,0.0);

    gluSphere(quadric, 0.3f, 32, 32);                    // 绘制太阳球体

    /**********************************绘制水星************************************************/

    glDisable(GL_LIGHT0);

    glEnable(GL_TEXTURE_2D );                     // 开启纹理

    glPushMatrix ();                            // 当前模型视图矩阵入栈

       // 将坐标系绕Y轴旋转fMercuOrbit角度,控制水星公转

       glRotatef(fMercuOrbit, 0.0f, 1.0f, 0.0f);

    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);          // 将坐标系绕X轴旋转-90度

    glTranslatef(0.5f, 0.0f, 0.0f);                     // 将坐标系右移0.5f

    glBindTexture(GL_TEXTURE_2D, texture[3]);         // 水星纹理

       // 将坐标系绕Z轴旋转fMercuSpin角度  控制水星自转

       glRotatef(fMercuSpin , 0.0f, 0.0f, 1.0f);

    gluSphere(quadric, 0.04f, 32, 32);                    // 水星球体

    glPopMatrix ();                            // 当前模型视图矩阵出栈

       // 绘制轨道

    glBegin(GL_LINE_LOOP);

       for(angle=0;angle<=360;angle++)

              glVertex3f(0.5f*sin(DEG_TO_RAD*angle),0,0.5f*cos(DEG_TO_RAD*angle));

       glEnd();

       /**********************************绘制金星************************************************/  

    glDisable(GL_LIGHT0);

    glEnable(GL_TEXTURE_2D );                    // 开启纹理

       glPushMatrix ();                            // 当前模型视图矩阵入栈

       // 将坐标系绕Y轴旋转fVenusOrbit角度,控制金星公转

       glRotatef(fVenusOrbit , 0.0f, 1.0f, 0.0f);

       glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);          // 将坐标系绕X轴旋转-90度

    glTranslatef(0.8f, 0.0f, 0.0f);                 // 将坐标系右移0.8f

    glBindTexture(GL_TEXTURE_2D, texture[4]);        // 金星纹理

       // 将坐标系绕Z轴旋转fVenusSpin角度,控制金星自转

       glRotatef(fVenusSpin , 0.0f, 0.0f, 1.0f);

    gluSphere(quadric, 0.06f, 32, 32);                   // 金星球体

    glPopMatrix ();

       glBegin(GL_LINE_LOOP);

       for(angle=0;angle<=360;angle++)

              glVertex3f(0.8f*sin(DEG_TO_RAD*angle),0,0.8f*cos(DEG_TO_RAD*angle));    

       glEnd();

       /**********************************绘制地球************************************************/

    glDisable(GL_LIGHT0);

    glEnable(GL_TEXTURE_2D );                     // 开启纹理

       glPushMatrix ();                            // 当前模型视图矩阵入栈

       // 将坐标系绕Y轴旋转fEarthOrbit角度,控制地球公转

       glRotatef(fEarthOrbit , 0.0f, 1.0f, 0.0f);

       glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);// 将坐标系绕X轴旋转-90度

    glTranslatef(1.1f, 0.0f, 0.0f);                      // 将坐标系右移1.1f

    glBindTexture(GL_TEXTURE_2D, texture[5]);        // 地球纹理

       // 将坐标系绕Z轴旋转fEarthSpin角度,控制地球自转

       glRotatef(fEarthSpin , 0.0f, 0.0f, 1.0f);

    gluSphere(quadric, 0.08f, 32, 32);                   // 地球球体

    glPopMatrix ();

       glBegin(GL_LINE_LOOP);

       for(angle=0;angle<=360;angle++)

              glVertex3f(1.1f*sin(DEG_TO_RAD*angle),0,1.1f*cos(DEG_TO_RAD*angle));

       glEnd();

       /**********************************绘制火星************************************************/

    glDisable(GL_LIGHT0);

    glEnable(GL_TEXTURE_2D );                     // 开启纹理

    glPushMatrix ();                           // 当前模型视图矩阵入栈

       // 将坐标系绕Y轴旋转fMarsOrbit角度,控制火星公转

       glRotatef(fMarsOrbit  , 0.0f, 1.0f, 0.0f);

    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);           // 将坐标系绕X轴旋转-90度

    glTranslatef(1.4f, 0.0f, 0.0f);                      // 将坐标系右移1.4f

    glBindTexture(GL_TEXTURE_2D, texture[6]);         // 火星纹理

       // 将坐标系绕Z轴旋转fMarsSpin角度,控制火星自转

       glRotatef(fMarsSpin , 0.0f, 0.0f, 1.0f);

       gluSphere(quadric, 0.04f, 32, 32);                    // 火星球体

    glPopMatrix ();

       glBegin(GL_LINE_LOOP);

       for(angle=0;angle<=360;angle++)

              glVertex3f(1.4f*sin(DEG_TO_RAD*angle),0,1.4f*cos(DEG_TO_RAD*angle));

       glEnd();

    /**********************************绘制木星************************************************/

    glDisable(GL_LIGHT0);

    glEnable(GL_TEXTURE_2D );                     // 开启纹理

       glPushMatrix ();                           // 当前模型视图矩阵入栈

       // 将坐标系绕Y轴旋转fJupiterOrbit角度,控制木星公转

    glRotatef(fJupiterOrbit  , 0.0f, 1.0f, 0.0f);

    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);          // 将坐标系绕X轴旋转-90度

       glTranslatef(1.7f, 0.0f, 0.0f);                    // 将坐标系右移1.7f

    glBindTexture(GL_TEXTURE_2D, texture[7]);        // 木星纹理

       // 将坐标系绕Z轴旋转fJupiterSpin角度,控制木星自转

    glRotatef(fJupiterSpin , 0.0f, 0.0f, 1.0f);

    gluSphere(quadric, 0.13f, 32, 32);                   // 木星球体

    glPopMatrix ();

    glBegin(GL_LINE_LOOP);

       for(angle=0;angle<=360;angle++)

              glVertex3f(1.7f*sin(DEG_TO_RAD*angle),0,1.7f*cos(DEG_TO_RAD*angle));

       glEnd();

    /**********************************绘制土星************************************************/

    glDisable(GL_LIGHT0);

    glEnable(GL_TEXTURE_2D );                     // 开启纹理

       glPushMatrix ();                          // 当前模型视图矩阵入栈

       // 将坐标系绕Y轴旋转fSaturnOrbit角度,控制土星公转

    glRotatef(fSaturnOrbit , 0.0f, 1.0f, 0.0f);

    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);           // 将坐标系绕X轴旋转-90度

       glTranslatef(1.9f, 0.0f, 0.0f);                   // 将坐标系右移1.9f

    glBindTexture(GL_TEXTURE_2D, texture[8]);         // 土星纹理

       // 将坐标系绕Z轴旋转fSaturnSpin角度,控制土星自转

    glRotatef(fSaturnSpin , 0.0f, 0.0f, 1.0f);

    gluSphere(quadric, 0.1f, 32, 32);                     // 土星球体

    glPopMatrix ();

       glBegin(GL_LINE_LOOP);

       for(angle=0;angle<=360;angle++)

              glVertex3f(1.9f*sin(DEG_TO_RAD*angle),0,1.9f*cos(DEG_TO_RAD*angle));

       glEnd();

       /**********************************绘制天王星**********************************************/

       glDisable(GL_LIGHT0);

    glEnable(GL_TEXTURE_2D );                     // 开启纹理

       glPushMatrix ();                           // 当前模型视图矩阵入栈

       // 将坐标系绕Y轴旋转fUranusOrbit角度,控制天王星公转

    glRotatef(fUranusOrbit , 0.0f, 1.0f, 0.0f);

    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);           // 将坐标系绕X轴旋转-90度

       glTranslatef(2.1f, 0.0f, 0.0f);                      // 将坐标系右移2.1f

    glBindTexture(GL_TEXTURE_2D, texture[9]);        // 天王星纹理

       // 将坐标系绕Z轴旋转fUranusSpin角度,控制天王星自转

    glRotatef(fUranusSpin , 0.0f, 0.0f, 1.0f);

    gluSphere(quadric, 0.1f, 32, 32);                    // 天王星球体

    glPopMatrix ();

       glBegin(GL_LINE_LOOP);

       for(angle=0;angle<=360;angle++)

              glVertex3f(2.1f*sin(DEG_TO_RAD*angle),0,2.1f*cos(DEG_TO_RAD*angle));

       glEnd();

       /**********************************绘制海王星**********************************************/

       glDisable(GL_LIGHT0);

    glEnable(GL_TEXTURE_2D );                     // 开启纹理

       glPushMatrix ();                            // 当前模型视图矩阵入栈

       // 将坐标系绕Y轴旋转fNeptuneOrbit角度,控制海王星公转

    glRotatef(fNeptuneOrbit , 0.0f, 1.0f, 0.0f);

       glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);           // 将坐标系绕X轴旋转-90度

       glTranslatef(2.3f, 0.0f, 0.0f);                      // 将坐标系右移2.3f

    glBindTexture(GL_TEXTURE_2D, texture[10]);      // 海王星纹理

       // 将坐标系绕Z轴旋转fNeptuneSpin角度,控制海王星自转

    glRotatef(fNeptuneSpin , 0.0f, 0.0f, 1.0f);

    gluSphere(quadric, 0.08f, 32, 32);                  // 海王星球体

    glPopMatrix ();

       glBegin(GL_LINE_LOOP);

       for(angle=0;angle<=360;angle++)

              glVertex3f(2.3f*sin(DEG_TO_RAD*angle),0,2.3f*cos(DEG_TO_RAD*angle));

       glEnd();

      

       /**********************************绘制月亮************************************************/

    glBindTexture(GL_TEXTURE_2D, texture[11]);        // 月亮纹理

       glPushMatrix ();

       // 将坐标系绕Y轴旋转fEarthOrbit角度,控制月亮跟随地球

       glRotatef(fEarthOrbit , 0.0f, 1.0f, 0.0f);

    glTranslatef(1.1f, 0.0f, 0.0f);                       // 将坐标系右移1.1f

       // 将坐标系绕Y轴旋转fMoonOrbit角度,控制月亮公转

    glRotatef(fMoonOrbit , 0.0f, 1.0f, 0.0f);

    glTranslatef(0.15f, 0.0f, 0.0f);

       // 将坐标系绕Y轴旋转fMoonSpin角度,控制月亮自转

       glRotatef(fMoonSpin , 0.0f, 1.0f, 0.0f);

       gluSphere(quadric, 0.02, 32, 32);                     // 月亮球体

    glPopMatrix ();

    // 控制速度

       if( g_bOrbitOn == true )

       {

              fSunSpin -= g_fSpeedmodifier * (g_fElpasedTime * 10.0f);

              fMercuSpin -= g_fSpeedmodifier * (g_fElpasedTime * 15.0f);

              fMercuOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 40.0f);

              fVenusSpin -= g_fSpeedmodifier * (g_fElpasedTime * 10.0f);

              fVenusOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 30.0f);

              fEarthSpin  -= g_fSpeedmodifier * (g_fElpasedTime * 100.0f);

              fEarthOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 20.0f);

              fMarsSpin -= g_fSpeedmodifier * (g_fElpasedTime * 30.0f);

              fMarsOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 50.0f);

              fJupiterSpin -= g_fSpeedmodifier * (g_fElpasedTime * 90.0f);

              fJupiterOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 35.0f);

              fSaturnSpin -= g_fSpeedmodifier * (g_fElpasedTime * 90.0f);

              fSaturnOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 25.0f);

              fUranusSpin -= g_fSpeedmodifier * (g_fElpasedTime * 70.0f);

              fUranusOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 15.0f);

              fNeptuneSpin -= g_fSpeedmodifier * (g_fElpasedTime * 40.0f);

              fNeptuneOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 5.0f);

              fMoonSpin  -= g_fSpeedmodifier * (g_fElpasedTime * 50.0f);

              fMoonOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 200.0f);

       }

    angle_Z += 0.01f;                                   // 星空旋转

    glutSwapBuffers();                                  // 交换双缓存

       glFlush();

}

void Reshape(int width, int height)

{

       if (height==0)

              height=1;                                      // 改变窗口

    glViewport(0,0,width,height);                         // 设置视口

    // 设置投影矩阵

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

       gluLookAt(viewer[0],viewer[1],viewer[2],viewer[3],viewer[4],-5,0,1,0);

}

void keyboard(unsigned char key, int x, int y)

{

       switch(key) {

           case 'd': case 'D':                            // 视点上下左右移动

                     if(viewer[0]<=4.5)

                            viewer[0]+=0.1;

              break;

              case 'a': case 'A':

                     if(viewer[0]>=-6.0)

                            viewer[0]-=0.1;

              break;

              case 'w': case 'W':

                     if(viewer[1]<=4.5)

                            viewer[1]+=0.1;

              break;

              case 's': case 'S':

                     if(viewer[1]>=-6.0)

                            viewer[1]-=0.1;

              break;

             

              case'+':                                 // 加速,减速,暂停

              ++g_fSpeedmodifier;

              glutPostRedisplay();

              break;

              case ' ':

              g_bOrbitOn = !g_bOrbitOn;

              glutPostRedisplay();

              break;

              case'-':

              --g_fSpeedmodifier;

              glutPostRedisplay();

              break;

              case VK_ESCAPE:                         // 按ESC键时退出

                     exit(0);

              break;

        default:

                     break;

       }

}

void special_keys(int s_keys, int x, int y)

{

       switch(s_keys) {

        case GLUT_KEY_F1:             // 按F1键时切换窗口/全屏模式

            if(isFullScreen)

            {

                            glutReshapeWindow(WIN_WIDTH, WIN_HEIGHT);

                glutPositionWindow(30, 30);

                isFullScreen = FALSE;

                     }

            else

            {

                glutFullScreen();

                isFullScreen = TRUE;

            }

              break;

              case GLUT_KEY_RIGHT:                   // 视角上下左右旋转

                     if(viewer[3]<=4.5)

                            viewer[3]+=0.1;

              break;

              case GLUT_KEY_LEFT:

                     if(viewer[3]>=-3.0)

                            viewer[3]-=0.1;

              break;

              case GLUT_KEY_UP:

                     if(viewer[4]<=4.5)

                            viewer[4]+=0.1;

              break;

              case GLUT_KEY_DOWN:

                     if(viewer[4]>=-4.5)

                            viewer[4]-=0.1;

              break;

        default:

            break;

       }

}

void mouse(int btn, int state, int x, int y)                 // 远近视角

{

       if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN)

              viewer[2]+=0.3;

       if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN&&viewer[2]>=-3.9)

              viewer[2]-=0.3;

}

// 程序主函数

void main(int argc, char** argv)

{

       //读图片

       LoadBmp("Data//Sky.bmp"         , &skyImg);

       LoadBmp("Data//Sun.bmp"         , &sunImg);

       LoadBmp("Data//Ray.bmp"         , &rayImg);

    LoadBmp("Data//Mercu.bmp"     , &mercuImg);

       LoadBmp("Data//Venus.bmp"     , &venusImg);

       LoadBmp("Data//Earth.bmp"     , &earthImg);

       LoadBmp("Data//Mars.bmp"       , &marsImg);

       LoadBmp("Data//Jupiter.bmp" , &jupiterImg);

       LoadBmp("Data//Saturn.bmp"   , &saturnImg);

       LoadBmp("Data//Uranus.bmp"   , &uranusImg);

       LoadBmp("Data//Neptune.bmp" , &neptuneImg);

       LoadBmp("Data//Moon.bmp"       , &moonImg);

    glutInit(&argc, argv);                           // 初始化GLUT库

    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);          // 初始化显示模式

    glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT);    // 初始化窗口大小

    glutInitWindowPosition(30,30);                     // 初始化窗口位置

    glutCreateWindow(WIN_TITLE);                   // 建立窗口

    InitGL();                                       // 初始化OpenGL

    glutDisplayFunc(Display);

    glutReshapeFunc(Reshape);

    glutKeyboardFunc(keyboard);

       glutSpecialFunc(special_keys);

    glutMouseFunc(mouse);

    glutIdleFunc(Display);                   // 设置窗口空闲时的处理函数

    glutMainLoop();                        // 进入事件处理循环

}

八.运行效果:

1.运行按钮设置说明:

w或W键: 视点上移           s或S键: 视点下移

a或A键: 视点左移           d或D键: 视点右移

鼠标左键: 视点前移          鼠标右键: 视点后移

↑键:    视角上移           ↓键:     视角下移

←键:    视角左移           →键:     视角右移

小键盘 + :星球转动加速      小键盘 - :星球转动减速

空格键 : 停止转动  再次按下继续转动

F1键  : 切换窗口模式/全屏模式

ESC键 :  退出程序

2.运行截图:

改变视点:

改变视角:

、参考资料:

《计算机图形学》第三版     作者:Donald Hearn&M.Pauline Baker

《C++大学教程》第二版     作者:Harvey M.Deitel&Paul James Deitel

《OpenGL教程》             作者:nehe

相关推荐