计算机图形学课程设计报告--范文
《计算机图形学》课程设计报告
题目名称:
专 业
班 级
学 号
姓 名
指导教师
年 月 日
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; alpha 通道的24位图 unsigned char *data;
// 纹理宽度
// 纹理高度
// 每个象素对应的字节数,3:24位图,4:带// 纹理数据
}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 #include #include #include #include #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 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 #include #include
#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
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
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
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
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
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
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
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
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]
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]
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]
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]
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