openGL实现太阳系行星系统

Solarysystem项目总结

一、汇总所用函数与知识

1.头文件:

#include<GL/glut.h>或#include<gl/glut.h>

2.openGL相关函数

(1)主函数创建窗口

glutInit();

glutInitDisplayMode();

glutInitWindowPosition();

glutinitwindowSize();

glutCreateWindow();

glutDisplayFunc();

glutIdleFunc();

glutKeyboardFunc();

glutMainLoop();

(2)绘制星球star

glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND);

glPushMatrix();

glRotatef();

glTranslatef();

glBegin(GL_LINES);

glVertex2f();

glEnd();

glColor3f();

glutSolidSphere();

gpPopMatrix();

(3)绘制地球类行星

glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);

(4)显示onDisplay

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(.7f, .7f, .7f, .1f); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(75.0f, 1.0f, 1.0f, 40000000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(viewX, viewY, viewZ, centerX, centerY, centerZ, upX, upY, upZ); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST);

glutSwapBuffers();

3.其他编程相关知识

enum枚举

二、函数详解

1.主函数创建窗口

(1)glutinit();

(21条消息) 一. glutInit(argc, argv); glut初始化API_xianhua7877的博客-CSDN博客_glutinit

glutinit()用于初始化glut库,从main处获取两个参数

int main(int argc, char* argv[])
//对应: 
      glutInit(&argc,argv);
//这是目前所用的,其它参考链接

(2)glutInitDisplayMode();

glutinitDisplayMode()函数的作用主要时在创建窗口时指定模式的类型。

函数的原型为:glutinitDisplayMode(unsigned int mode)

mode 包括集中可能的布尔组合,可以指定颜色模式,数量和缓冲区类型

颜色模式:

GLUT_RGBA GLUT_RGB GLUT_INDEX 三种 其中 GLUT_RGBA为默认的颜色模式,一般使用它即可(修改没有看出一二的区别)

GLUT_INDEX 是指定颜色索引模式的窗口,具体含义,未知。

缓冲区类型:

GLUT_DOUBLE GLUT_SINGLE两种,分别代表双缓冲窗口和单缓冲窗口

单缓冲,将所有的绘图指令在窗口上完成,绘图效率慢,如果电脑比较慢,屏幕会发生闪烁,一般只用于显示单独的一副非动态的图像;

双缓冲,绘图指令在一个缓冲区完成,绘图很快,在绘图指令完成后再通过交换完成的图形立即显示在屏幕上,避免绘图不完整,效率高,一般用于生成动画效果。

一般使用 GLUT_DOUBLE 即可

其它类型:(暂且不做深入探究)

(3)glutInitWindowPosition();

原始函数:void glutinitWindowPosition(int x,int y)

x,y的单位为像素,是确定窗口左上角出现在屏幕上的位置,屏幕左上角为(0,0)。

(4)glutinitwindowSize();

函数原型 void glutinitwindowSize(int width,int height) 设置窗口的初始大小

width 宽 height 长 单位是像素

(5)glutCreateWindow();

函数原型: int glutCreatWindow(char *name)

功能是创建一个以name命名的窗口 比如说:glutCreateWindow("solarysystem")

当窗口创建之后,窗口的环境状态改变可以很快的完成,但是只有glutMainloop()执行之后窗口显示状态才会执行,即窗口才会出现,否则窗口会闪现一瞬然后迅速消失。

返回值是窗口唯一的短整型标识符,范围从1开始,当调用glutSetWindow时可以使用这个窗口的标识符。

标识符的一部分应用:

(21条消息) OpenGL入门6——GLUT窗口demystify的博客-CSDN博客glutcreatewindow

(6)glutDisplayFunc();

函数原型:void glutDisplayFunc(void(*func)(void))

使用方式:glutDisplayFunc(&display) void display(void)是绘制函数

如:glutDisplayFunc(onDisplay);

该函数在程序运行时是自动调用的,调用的时机有:窗口内容绘制、窗口大小改变,窗口重绘。

作用就是绘制窗口

(7)glutIdleFunc();

函数原型:void glutidelFunc(void(*func)(void))

使用方法:glutidelFunc(&func)

如:glutidelFunc(onUpdate)

glut的空闲回调函数,意思是当没有其他操作时,就一直调用func函数,在例子中就是,如果没有其他事件比如扩大缩小窗口等等,那么就一直执行onUpdate函数,不断对窗口画面进行更新,从而实现一个动画效果。

代表了窗口空闲时哪个函数将要被调用

回调函数参考 知识集锦回调函数

(8)glutKeyboardFunc();

普通键盘输入-glutKeyboard()

函数原型:void glutKeyboardFunc(void(*Func)(unsigned char key,int x,int y));

用于处理可以用Ascii表示的键盘按下事件。

使用方法: glutKeyboardFunc(&ProcessKeyboard)

如:glutKeyboardFunc(onKeyboard);

其中key是指按下的键的ascii,对于字母数字可以直接用'x' 、'9'表示,对于esc、回车、delete等有ascii的就用对应的ascii数值表示,如esc的对应的是27

而x,y代表的是按下键盘时鼠标相当于窗口左上角所在的位置,以像素为单位,目前作用未知

给一个例子:

//main
void onKeyboard(unsigned char key, int x, int y)//键盘控制
{
    solarsystem.onKeyboard(key, x, y);
}
int main()
{
    glutKeyboardFunc(onKeyboard);
}
//solarysystem
void onKeyboard(unsigned char key, int x, int y)
    {
        switch (key) {
        case 'w': viewY += OFFSET; break; // 摄像机Y 轴位置增加 OFFSET
        case 's': viewZ += OFFSET; break;
        case 'S': viewZ -= OFFSET; break;
        case 'a': viewX -= OFFSET; break;
        case 'd': viewX += OFFSET; break;
        case 'x': viewY -= OFFSET; break;
        case 'r':
            viewX = 0; viewY = REST_Y; viewZ = REST_Z;
            centerX = centerY = centerZ = 0;
            upX = upY = 0; upZ = 1;
            break;
        case 27: exit(0); break;
        default: break;
        }
    }

特殊键盘输入处理函数:glutSpecialFunc();

用于处理不存在于ascii中的键盘输入

函数原型:void glutspecialFunc(void(*func)(int key,int x,int y));

key参数:

GLUT_KEY_F1:F1功能键 GLUT_KEY_F2:F2功能键

GLUT_KEY_F3:F3功能键 GLUT_KEY_F4:F4功能键

GLUT_KEY_F5:F5功能键 GLUT_KEY_F6:F6功能键

GLUT_KEY_F7:F7功能键 GLUT_KEY_F8:F8功能键

GLUT_KEY_F9:F9功能键 GLUT_KEY_F10:F10功能键

GLUT_KEY_F11:F11功能键 GLUT_KEY_F12:F12功能键

GLUT_KEY_LEFT:左方向键 GLUT_KEY_UP:上方向键

GLUT_KEY_RIGHT:右方向键 GLUT_KEY_DOWN:下方向键

GLUT_KEY_HOME:Home键 GLUT_KEY_END:End键

GLUT_KEY_INSERT:Insert键 GLUT_KEY_PAGE_UP:PageUp键

GLUT_KEY_PAGE_DOWN:PageDown键

(9)glutMainLoop();

开启glut事件处理循环,让所有与事件有关的函数调用无限循环。

在一个glut程序中,这个例程被调用一次,就不再返回,它将调用必要的任何已注册的回调。

所谓的事件就是比如安乐不同的键,进行了鼠标互动,进行了数据更新,甚至于每一次进行的刷新,就是例如以下的函数

glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowPosition(WINDOW_X_POS, WINDOW_Y_POS);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("solarsystem by c++");
glutDisplayFunc(onDisplay);
glutIdleFunc(onUpdate);
glutKeyboardFunc(onKeyboard);

只有程序退出(如exit(0)出现)时才会跳出循环,否则就是无限循环,当没有其他操作时,进行的事件就是上面说过的空闲回调函数,在这里就是进行onUpdate更新。

(10)其他窗口函数--知识集锦glut窗口

(21条消息) OpenGL入门6——GLUT窗口demystify的博客-CSDN博客glutcreatewindow

(11)回调函数集锦

(21条消息) Glut 回调函数小结_xianhua7877的博客-CSDN博客

2.solarysystem.h—宏定义内容和全局变量

(1)定义多维数组的宏

功能:当很多不同的物品都有相同的数组,数组名相同而值不同那么就用它

#include<iostream>
using namespace std;
#define AVG_three(name,v1,v2,v3)((name[0])=(v1),(name[1])=(v2),(name[2])=(v3))
int main()
{
    int name[3]={0,0,0};
    AVG_three(name,2,3,4);
    cout<<name[1];
    AVG_three(name,2,5,3);
    cout<<name[1];
    return 0;
}

#define 名字(放数组名的地方(随意去一个例如name),值1,值2,值3。。。。)((数组名[0])=(值1),(数组名[1]=(值2).。。。。。。)

如果太长两部分之间可以用反斜杠连接,换到下一行,否则就要在一行内完成宏定义

#define AVG_three(name,v1,v2,v3)\
((name[0])=(v1),(name[1])=(v2),(name[2])=(v3))

(2)enum枚举数组

参见知识集锦-enum数组

3.绘制星球—drawStar

(1)glEnable()

glEnable(GL_LINE_SMOOTH)//执行后过滤线段的锯齿

glEnable(GL_BLEND)//启用颜色混合,例如实现半透明效果

其他glenable()相关参数和功能参照知识集锦--glenable

(2)glPushMatrix() glPopMatrix();

将平移变换等操作放在这两个函数之间可以保证操作时是以世界原点为基础的,可以使本次变换与上次变换独立

更多了解参考:

glPushMatrix_百度百科 (baidu.com)

(22条消息) glPushMatrix和glPopMatrix的作用passtome的博客-CSDN博客glpopmatrix

使用:

        glPushMatrix();//开始
        {//变换
            //处理卫星
            if (parentStar != 0 && parentStar->distance > 0)
            {
                glRotatef(parentStar->alpha, 0, 0, 1);
                glTranslatef(parentStar->distance, 0.0, 0.0);
            }
            glBegin(GL_LINES);
            for (int i = 0; i < n; ++i)
                glVertex2f(distance * cos(2 * PI * i / n), distance * sin(2 * PI * i / n));
                glEnd();
                glRotatef(alpha, 0, 0, 1);
                glTranslatef(distance, 0.0, 0.0);
                glRotatef(alphaself, 0, 0, 1);
                glColor3f(rgbaColor[0], rgbaColor[1], rgbaColor[2]);
                glutSolidSphere(radius, 40, 32);
        }
        glPopMatrix();//结束

(3)glRotatef(alpha,x,y,z)

void WINAPI glRotatef(
   GLfloat angle,//角度  xyz为正则是逆时针旋转
   GLfloat x,
   GLfloat y,
   GLfloat z
);

angle:为旋转的角度,单位为度。 x,y,z:为对应xyz轴的布尔值变量。 x,y,z表示要围绕哪个坐标轴旋转,x,y,z值相当于一个布尔值,0.0表示假,而非零参数则表示真。 例如:

如果想让当前的几何图形围绕着z轴转,那么让x=0,y=0,而z设为非零值即可。

如果这里的x=0,y=0,z=0那么将围绕着x轴旋转。

如果设置的旋转值(x,y,z的值)为正数,那么旋转的方向是逆时针的,如果旋转值是负数,那么旋转的方向是顺时针的。

(4)glTranslatef(x,y,z)

glTranslated()和glTranslatef()这两个函数是定义一个平移矩阵,该矩阵与当前矩阵相乘,使后续的图形进行平移变换。

void glTranslated(GLdouble x,
           GLdouble y,
           GLdouble z);
​
void glTranslatef(GLdouble x,
          GLdouble y,
          GLdouble z);
//x,y,z:分别指定沿x,y,z轴方向的平移分量。重点就是沿着x,y,z轴移动。
//注意在glTranslatef(x, y, z)中,移动的时候,并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。作用是将绘点坐标的原点在当前原点的基础上平移一个(x,y,z)向量。

(5)glBegin()

glBegin(GL_LINES)以两个顶点为一组绘制线段

glBegin操作参考:

glBegin 函数 (Gl.h) - Win32 apps | Microsoft Docs

(22条消息) OpenGL 解析glBegin()Hi乌龟的博客-CSDN博客_glbegin函数

(22条消息) openGL学习笔记三 : 绘制点、线以及多边形天心fox的博客-CSDN博客

(6)glVertex2f()

绘制点的函数有很多,数字和符号不同数字代表几个参数,符号代表类型,2f表示两个32位浮点数(GLfloat和GLclampf)的参数,代表点的x y坐标

其他的:

(22条消息) openGL学习笔记三 : 绘制点、线以及多边形天心fox的博客-CSDN博客

(7)glEnd()

glBegin()和glEnd()结合限定了一组或多组图元的定点定义

他们之间可以调用的函数:

(22条消息) glBegin()和glEnd()之间可调用的函数PersonFly小逗的博客-CSDN博客

(8)glColor3f()

void WINAPI glColor3f(
   GLfloat red,
   GLfloat green,
   GLfloat blue
);

三个参数值的范围是[0.0,1.0],可以将这三个参数值视为颜色的成分。

0.0------>不使用该颜色

1.0------->使用该颜色的最大值

glColor3f(0.0, 0.0, 0.0);  --> 黑色
glColor3f(1.0, 0.0, 0.0);  --> 红色
glColor3f(0.0, 1.0, 0.0);  --> 绿色
glColor3f(0.0, 0.0, 1.0);  --> 蓝色
glColor3f(1.0, 1.0, 0.0);  --> 黄色
glColor3f(1.0, 0.0, 1.0);  --> 品红色
glColor3f(0.0, 1.0, 1.0);  --> 青色
glColor3f(1.0, 1.0, 1.0);  --> 白色

如果在glBegin()与glEnd()函数之间多次连续调用颜色函数,那么,只会显示出最后一次的颜色

例如:

glBegin(GL_POINTS)
    glColor3f(0.0, 1.0,  0.0);  //绿色
    glColor3f(1.0, 1.0,  0.0);  //黄色
    glVertex(0.25, 0.75, 0.0);
glEnd();

最终线的颜色是黄色。

其他opengl颜色的应用:

OpenGL(四)之颜色篇 - 马列神教 - 博客园 (cnblogs.com)

(9)glutSolidSphere()

函数原型:void glutSolidSphere(GLdouble radius , GLint slices , GLint stacks);

该函数用于渲染一个球体,球体球心位于原点,一般来说,后两个参数赋值越大,渲染花费的事件越长,效果越逼真。

radius---->球体半径 slices------>经线数 stacks----->纬线数

(10)drawStar总结

首先处理卫星,让其跟着母星进行大的运动,并移动到响应的初始位置。

如果不是卫星,那么就绘制公转轨道,进行公转和绘制公转半径,进行自转,绘制星球颜色,最后根据这些操作渲染出一个球体。

4.绘制地球类行星

(1)glMaterialfv()

函数原型

void WINAPI glMaterialfv(
GLenum face,
GLenum pname,
const GLfloat *params
);

指定用于光照计算的当前材质属性

face:取值为 GL_FRONT GL_BACK GL_FRONT和GL_BACK 代表属性将应用于物体的那一面,前后还是前和后

pname:指出要设置那种材质属性,属性一共有五种分别是

GL_AMBIENT环境颜色
GL_GIFFUSE散射颜色
GL_SPECULAR镜面反射颜色
GL_EMISSION材质的发光颜色
GL_SHININESS镜面反射指数

params:要设置的属性值,是一个指向数组的指针(向量版本)或一个数值(非向量版本)。只有设置参数值是GL_SHININESS时,才能使用非向量版本。

下面为pname的可能取值和对应值的意义

参数值默认值意义
GL_AMBIENT(0.2,0.2,0.2,1.0)材质的环境颜色
GL_DIFFUSE(0.8,0.8,0.8,1.0)材质的散射颜色
GL_AMBIENT_AND_DIFFUSE材质的环境颜色和散射颜色
GL_SPECULAR(0.0,0.0,0.0,1.0)材质的镜面反射颜色
GL_SHININESS0.0镜面反射指数
GL_EMISSION(0.0,0.0,0.1,1.0)材质的发射光颜色
GL_COLOR_INDEXES(0, 1, 1)环境颜色索引、散射颜色索引和镜面反射颜色索引

目前属性如何取值找不到太多的参考,但GL_AMBIENT和GL_DIFFUSE尽量相同会更贴合实际并且

以下为材质表四组值分别指GL_AMBIENT   GL_DIFFUSE  GL_SPECULAR GL_SHININESS
​
//黄铜
​
    0.329412, 0.223529, 0.027451, 1.000000,
​
    0.780392, 0.568627, 0.113725, 1.000000,
​
    0.992157, 0.941176, 0.807843, 1.000000,
​
    27.897400,
​
    //青铜
​
    0.212500, 0.127500, 0.054000, 1.000000,
​
    0.714000, 0.428400, 0.181440, 1.000000,
​
    0.393548, 0.271906, 0.166721, 1.000000,
​
    25.600000,
​
    //亮青铜
​
    0.250000, 0.148000, 0.064750, 1.000000,
​
    0.400000, 0.236800, 0.103600, 1.000000,
​
    0.774597, 0.458561, 0.200621, 1.000000,
​
    76.800003,
​
    //铬
​
    0.250000, 0.250000, 0.250000, 1.000000,
​
    0.400000, 0.400000, 0.400000, 1.000000,
​
    0.774597, 0.774597, 0.774597, 1.000000,
​
    76.800003,
​
//铜
​
    0.191250, 0.073500, 0.022500, 1.000000,
​
    0.703800, 0.270480, 0.082800, 1.000000,
​
    0.256777, 0.137622, 0.086014, 1.000000,
​
    12.800000,
​
//亮铜
​
    0.229500, 0.088250, 0.027500, 1.000000,
​
    0.550800, 0.211800, 0.066000, 1.000000,
​
    0.580594, 0.223257, 0.069570, 1.000000,
​
    51.200001,
​
//金
​
    0.247250, 0.199500, 0.074500, 1.000000,
​
    0.751640, 0.606480, 0.226480, 1.000000,
​
    0.628281, 0.555802, 0.366065, 1.000000,
​
    51.200001,
​
//亮金
​
    0.247250, 0.224500, 0.064500, 1.000000,
​
    0.346150, 0.314300, 0.090300, 1.000000,
​
    0.797357, 0.723991, 0.208006, 1.000000,
​
    83.199997,
​
//白蜡
​
    0.105882, 0.058824, 0.113725, 1.000000,
​
    0.427451, 0.470588, 0.541176, 1.000000,
​
    0.333333, 0.333333, 0.521569, 1.000000,
​
    9.846150,
​
//银
​
    0.192250, 0.192250, 0.192250, 1.000000,
​
    0.507540, 0.507540, 0.507540, 1.000000,
​
    0.508273, 0.508273, 0.508273, 1.000000,
​
    51.200001,
​
//亮银色
​
    0.231250, 0.231250, 0.231250, 1.000000,
​
    0.277500, 0.277500, 0.277500, 1.000000,
​
    0.773911, 0.773911, 0.773911, 1.000000,
​
    89.599998,
​
//翡翠、祖母绿
​
    0.021500, 0.174500, 0.021500, 0.550000,
​
    0.075680, 0.614240, 0.075680, 0.550000,
​
    0.633000, 0.727811, 0.633000, 0.550000,
​
    76.800003,
​
//碧玉
​
    0.135000, 0.222500, 0.157500, 0.950000,
​
    0.540000, 0.890000, 0.630000, 0.950000,
​
    0.316228, 0.316228, 0.316228, 0.950000,
​
    12.800000,
​
//黑曜石
​
    0.053750, 0.050000, 0.066250, 0.820000,
​
    0.182750, 0.170000, 0.225250, 0.820000,
​
    0.332741, 0.328634, 0.346435, 0.820000,
​
    38.400002,
​
//珍珠
​
    0.250000, 0.207250, 0.207250, 0.922000,
​
    1.000000, 0.829000, 0.829000, 0.922000,
​
    0.296648, 0.296648, 0.296648, 0.922000,
​
    11.264000,
​
//红宝石
​
    0.174500, 0.011750, 0.011750, 0.550000,
​
    0.614240, 0.041360, 0.041360, 0.550000,
​
    0.727811, 0.626959, 0.626959, 0.550000,
​
    76.800003,
​
//绿宝石、绿松石
​
    0.100000, 0.187250, 0.174500, 0.800000,
​
    0.396000, 0.741510, 0.691020, 0.800000,
​
    0.297254, 0.308290, 0.306678, 0.800000,
​
    12.800000,
​
//黑塑料
​
    0.000000, 0.000000, 0.000000, 1.000000,
​
    0.010000, 0.010000, 0.010000, 1.000000,
​
    0.500000, 0.500000, 0.500000, 1.000000,
​
    32.000000,
​
//黑橡胶
​
    0.020000, 0.020000, 0.020000, 1.000000,
​
    0.010000, 0.010000, 0.010000, 1.000000,
​
    0.400000, 0.400000, 0.400000, 1.000000,
​
    10.000000,
​
//紫罗兰
​
    0.110000, 0.060000, 0.090000, 1.000000,
​
    0.430000, 0.470000, 0.540000, 1.000000,
​
    0.330000, 0.330000, 0.520000, 1.000000,
​
    22.000000
​

按照例子推测 GL_EMISSION的四个值应该是RGBA颜色设置的四个值

GLfloat mat_emission[] = { rgbaColor[0],rgbaColor[1],rgbaColor[2],rgbaColor[3] };

使用案例:

        GLfloat mat_ambient[] = { 0.0f,0.0f,0.5f,1.0f };
//环境颜色
        GLfloat mat_diffuse[] = { 0.0f,0.0f,0.5f,1.0f };
//散射颜色
        GLfloat mat_specular[] = { 0.0f,0.0f,1.0f,1.0f };
//镜面反射颜色
        GLfloat mat_emission[] = { rgbaColor[0],rgbaColor[1],rgbaColor[2],rgbaColor[3] };
//材质的发光颜色
        GLfloat mat_shininess = 90.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_EMISSION, mat_emission);
        glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);

上面四个带向量的用glMaterialfv()

GL_SHININESS用glMaterialf()

5.绘制发光星球

(1)glLightfv()

函数原型:

void WINAPI glLightfv(
         GLenum  light,
         GLenum  pname,
   const GLfloat *params
);

使用样例:

        GLfloat light_position[] = { 0.0f,0.0f,0.0f,1.0f };
        GLfloat light_ambient[] = { 0.0f,0.0f,0.0f,1.0f };
        GLfloat linght_diffuse[] = { 1.0f,1.0f,1.0f,1.0f };
        GLfloat light_specular[] = { 1.0f,1.0f,1.0f,1.0f };
        glLightfv(GL_LIGHT0, GL_POSITION, light_position);
        glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, linght_diffuse);
        glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);

light: 光线标识符/光源编号,可取GL_LIGHT0、GL_LIGHT1、……、GL_LIGHT7共8个值,分别代表八个不同的光源。

pname:光源属性

GL_AMBIENT(设置光源的环境光属性,默认值(0,0,0,1))

GL_DIFFUSE(设置光源的散射光属性,默认值(1,1,1,1))

GL_SPECULAR(设置光源的镜面反射光属性,默认值(1,1,1,1))

GL_POSITION(设置光源的位置,默认值(0,0,1,0))

注意:对于GL_POSITION,(x,y,z,w)定义了光源在空间中的位置。

当w≠0时,它表示光源处于空间中(x,y,z)处,这时的光源称为定点光源;

当w=0时,根据齐次坐标的性质,它表示光源位于无穷远处,此时光源称

为定向光源,其所有光线几乎是相互平等的,如太阳。其光线方向由点

(x,y,z)指向(0,0,0)。

params:光源属性的值,由数组指定

光照设置好后还要启动光照,就像手电筒组装好之后还要打开开关一样,后续会介绍。

6.绘制太阳系—solarsystem

(1)视角

我们定义九个成员变量:

​
GLdouble viewX, viewY, viewZ;
GLdouble centerX, centerY, centerZ;
GLdouble upX, upY, upZ;

接下来了解三维编程中摄像机视角的变化:

如果我们把摄像机想象成我们自己的头,那么:

  • viewX, viewY, viewZ 就相当于头(摄像机)在 世界坐标中的坐标位置;

  • centerX, centerY, centerZ 则相当于头所看(摄像机所拍)物体的坐标位置;

  • upX, upY, upZ 则相当于头顶(摄像机顶部)朝上的方向向量(因为我们可以歪着头观察一个物体)。

所观察物体(太阳)的位置在 (0,0,0),则在SolarSystem类中的构造函数将视角初始化为:

#define REST 700
#define REST_Y (-REST)
#define REST_Z (REST)
​
viewX = 0;
viewY = REST_Y;
viewZ = REST_Z;
centerX = centerY = centerZ = 0;
upX = upY = 0;
upZ = 1;

则可以通过 gluLookAt 函数来设置视角的九个参数:

gluLookAt(viewX, viewY, viewZ, centerX, centerY, centerZ, upX, upY, upZ);

(2)onDisplay

<1>glClear() glClearColor()

函数原型:

void WINAPI glClear(
   GLbitfield mask
);

GLbitfield:可以使用 | 运算符组合不同的缓冲标志位,表明需要清除的缓冲

  • GL_COLOR_BUFFER_BIT: 当前可写的颜色缓冲

  • GL_DEPTH_BUFFER_BIT: 深度缓冲

  • GL_ACCUM_BUFFER_BIT: 累积缓冲

  •  GL_STENCIL_BUFFER_BIT: 模板缓冲

同时用两个就用|间隔

glClear()函数的作用是用当前缓冲区清除值,也就是glClearColor、glClearDepth、glClearIndex、glClearStencil、glClearAccum等函数所指定的值来清除指定的缓冲区,也可以使用glDrawBuffer一次清除多个颜色缓存。比如:

  glClearColor(0.0,0.0,0.0,0.0);
  glClear(GL_COLOR_BUFFER_BIT);

  第一条语句表示清除颜色设为黑色,第二条语句表示实际完成了把整个窗口清除为黑色的任务,glClear()的唯一参数表示需要被清除的缓冲区。

<2>glMatrixMode()

函数原型:void glMatrixMode(GLenum mode)

mode指定接下来矩阵操作的目标

  • GL_MODELVIEW,对模型视图矩阵堆栈应用随后的矩阵操作。可以在执行此命令后,输出自己的物体图形了。

  • GL_PROJECTION,对投影矩阵堆栈应用随后的矩阵操作。可以在执行此命令后,为我们的场景增加透视。

  • GL_TEXTURE,对纹理矩阵堆栈应用随后的矩阵操作。可以在执行此命令后,为我们的图形增加纹理贴图。

glMatrixMode(GL_PROJECTION);

代表接下来要对投影进行相关操作。

<3>glLoadIdentity();

函数原型:void glLoadIdentity(void)

功能是对当前矩阵进行初始化,将当前矩阵变成单位矩阵

单位矩阵就是对角线上都是1,其余元素皆为0的矩阵。

调用glLoadIdentity()之后,实际上将当前点移到了屏幕中心:类似于一个复位操作 1.X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。 2.OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。 3.中心左面的坐标值是负值,右面是正值。 移向屏幕顶端是正值,移向屏幕底端是负值。 移入屏幕深处是负值,移出屏幕则是正值。

<4>gluPerspective()

函数原型:

void gluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)  //视角   横纵比  近距离  远距离

OpenGL有两种投影:正射投影(垂直投影)和透视投影。透视投影通过指定一个平截头体来定义视见体的范围

fovy:视角,代表眼睛睁开的角度,越大则视野范围越宽阔,物体距离越远(0~180)

aspect:表示剪裁面的宽高比,影响到截面的大小。

zNear:近剪裁面到眼睛的位置(非负)

zFar:远剪裁面到眼睛的位置(非负)

zNear的值可以设置的很小,zFar的值可以设置的很大,这样看的范围更深一些

如果一个模型的z坐标为ptz,ptz大于zFar或者ptz小于zNear你都将看不到改模型;

Fovy值在180-360的范围内,你会发现渲染的图像反转了过来(不是镜像),就相当于你和你看到的东西一起倒了过来(脑补一下你眼前的东西跟你一起头朝地,脚朝上);

<5>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 相机向上的方向在世界坐标中的方向 你把相机想象成为你自己的脑袋: 第一组数据就是脑袋的位置 第二组数据就是眼睛看的物体的位置 第三组就是头顶朝向的方向(因为你可以歪着头看同一个物体) 同视角

gluLookAt(viewX, viewY, viewZ, centerX, centerY, centerZ, upX, upY, upZ);

头--物---头顶

<6>开启光照

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

GL_LIGHT0比较特殊是白光,其他光都是没有颜色的即黑色

OpenGL可以同时为我们提供8个有效的光源。也就是说,我们最多同时启用8个光源。它们分别是GL_LIGHT0 , GL_ LIGHT1,GL_ LIGHT2......*
​
*其中,GL_LIGHT0是最特殊的一个光源,我们可以为GL_ LIGHT0指定环境光成分。在默认情况下,GL_LIGHT0 光源的颜色为白色,其他7个光源在默认情况下是没有颜色的,也即是黑色。*

<7>glEnable(GL_DEPTH_TEST);

glEnable(GL_DEPTH_TEST): 用来开启更新[深度](https://so.csdn.net/so/search?q=深度&spm=1001.2101.3001.7020)缓冲区的功能,也就是,如果通过比较后深度值发生变化了,会进行更新深度缓冲区的操作。启动它,OpenGL就可以跟踪再Z轴上的像素,这样,它只会再那个像素前方没有东西时,才会绘画这个像素。
在做绘画3D时,这个功能最好启动,视觉效果比较真实。

<8>双缓冲交换两个缓冲区指针

glutSwapBuffers();

   glutSwapBuffers函数是 OpenGL中 GLUT工具包中用于实现 双缓冲技术的一个重要函数。该函数的功能是交换两个缓冲区 指针。
   
   通常, 我们所看到的窗体、文字、图像,从根本上来说都是“画”出来的。比如,制作一个简单的五子棋, 我们可能先要绘制棋盘,然后绘制棋子,我们可能还要绘制一些提示信息。虽然这些绘制操作有一定的先后顺序,通常情况下,操作系统的这些绘制速度非常的快,使人眼误认为这些绘制操作是同时完成的。
   
   但当我们进行复杂的绘图操作时,画面便可能有明显的闪烁。解决这个问题的关键在于使绘制的东西同时出现在 屏幕上。所谓 双缓冲技术, 是指使用两个缓冲区: 前台缓冲和后台缓冲。前台缓冲即我们看到的屏幕,后台缓冲则在内存当中,对我们来说是不可见的。每次的所有绘图操作都在后台缓冲中进行, 当绘制完成时, 把绘制的最终结果复制到 屏幕上, 这样, 我们看到所有GDI元素同时出现在屏幕上,从而解决了频繁刷新导致的画面闪烁问题。
   
在OpenGL中实现 双缓冲技术的一种简单方法:
  1.在调用 glutInitDisplayMode函数时, 开启GLUT_DOUBLE,即 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);。这里将我们惯用的GLUT_SINGLE替换为GLUT_DOUBLE,意为要使用 双缓冲而非单缓冲。
  2.调用 glutDisplayFunc(display)注册 回调函数时, 在回调函数中所有绘制操作完成后调用glutSwapBuffers()交换两个缓冲区指针。
  3.调用 glutIdleFunc注册一个空闲时绘制操作函数, 注册的这个函数再调用display函数。

<9>onDisplay总结:

首先进行清缓存(颜色和深度,并定义清缓存的颜色)

然后设置投影视图,开启投影,清空矩阵,最后设置参数

第三步进行模型处理,设置模型视图,清空矩阵,定义摄像机视角

打开光照、开启更新深度

绘制图形

最后双缓冲区交换指针

项目学习参考链接为:

(22条消息) C++ 实现太阳系行星系统(OpenGL)_git1314的博客-CSDN博客_c++实现太阳系行星系统

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
视点变换,旋转,加速减速,星空背景 太阳,光晕 各行星纹理 #include #include #include #include #include #include #include #pragma comment(lib, "winmm.lib") #pragma comment(lib,"wininet") // 纹理图像结构 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; // 定义窗口的标题、宽度、高度、全屏布尔变量 #define WIN_TITLE "模拟太阳系星球的转动" 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; // 月亮公转速度 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); } // 初始化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); //摄像机x,摄像机y,摄像机z, 目标点x,目标点y,目标点z, 摄像机顶朝向x,摄像机顶朝向y,摄像机顶朝向z // 获得系统时间使太阳系有动态效果 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 ); //指定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.5f); // 设置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(); /**********************************绘制月亮************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 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角度,控制月亮自转 glBindTexture(GL_TEXTURE_2D, texture[11]); 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 'r': case 'R': // 视点上下左右移动 if(viewer[0]=-6.0) viewer[0]-=0.5; break; case 'u': case 'U': if(viewer[1]=-6.0) viewer[1]-=0.1; break; case'+': case '=': // 加速,减速,暂停 g_fSpeedmodifier+=1.0f; glutPostRedisplay(); break; case ' ': g_bOrbitOn = !g_bOrbitOn; glutPostRedisplay(); break; case'-': //按'-'减小运行速度 g_fSpeedmodifier-=1.0f; 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]=-3.0) viewer[3]-=0.1; break; case GLUT_KEY_UP: 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 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 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 main(int argc, char** argv) { //读图片 LoadBmp("Picture//Sky.bmp" , &skyImg;); LoadBmp("Picture//Sun.bmp" , &sunImg;); LoadBmp("Picture//Ray.bmp" , &rayImg;); LoadBmp("Picture//Mercu.bmp" , &mercuImg;); LoadBmp("Picture//Venus.bmp" , &venusImg;); //金星 LoadBmp("Picture//Earth.bmp" , &earthImg;); LoadBmp("Picture//Mars.bmp" , &marsImg;); //火星 LoadBmp("Picture//Jupiter.bmp" , &jupiterImg;); //木星 LoadBmp("Picture//Saturn.bmp" , &saturnImg;); //土星 LoadBmp("Picture//Uranus.bmp" , &uranusImg;); //天王星 LoadBmp("Picture//Neptune.bmp" , &neptuneImg;); //海王星 LoadBmp("Picture//Moon.bmp" , &moonImg;); glutInit(&argc;, argv); // 初始化GLUT库 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); // 初始化显示模式 glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT); // 初始化窗口大小 glutInitWindowPosition(20,20); // 初始化窗口位置 GLuint window = glutCreateWindow(WIN_TITLE); // 建立窗口 InitGL(); // 初始化OpenGL glutDisplayFunc(Display); glutReshapeFunc(Reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(special_keys); glutMouseFunc(mouse); glutIdleFunc(Display); // 设置窗口空闲时的处理函数 glutMainLoop(); // 进入事件处理循环 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值