项目实战学习笔记| OpenGl C++语言开发小行星系统 | 实验楼项目

源代码下载:https://download.csdn.net/download/u012737193/10307716


点击上下左右调整观看视角

源代码下载:https://download.csdn.net/download/u012737193/10307716

Main.cpp文件:

#include <GL/glut.h>//只要包含了这个头文件,

可以通过以下三个文件,设置点击键盘事件,屏幕刷新事件和静止的时候执行的函数

glutDisplayFunc(onDisplay);

glutIdleFunc(onUpdate);

glutKeyboardFunc(onKeyboard);

 

#include <GL/glut.h>

#include "solarsystem.hpp"

 

#define WINDOW_X_POS 50

#define WINDOW_Y_POS 50

#define WIDTH 700

#define HEIGHT 700

 

SolarSystem solarsystem;

 

void onDisplay(void) {

    solarsystem.onDisplay();

}

void onUpdate(void) {

    solarsystem.onUpdate();

}

void onKeyboard(unsignedchar key,int x, int y) {

    solarsystem.onKeyboard(key, x, y);

}

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

glutInit(&argc,argv);

glutInitDisplayMode(GLUT_RGBA| GLUT_DOUBLE);

glutInitWindowPosition(WINDOW_X_POS,WINDOW_Y_POS);

glutCreateWindow("SolarSytem at Shityanlou");

glutDisplayFunc(onDisplay);

glutIdleFunc(onUpdate);

glutKeyboardFunc(onKeyboard);

glutMainLoop();

return 0;

}

来源: 实验楼

链接: https://www.shiyanlou.com/courses/558

 

 

Stars.hpp文件:

#ifndef star_hpp//这个头文件的功能就是当star_hpp存在的时候不执行#ifndef#endif之间的内容

#define star_hpp

#include <GL/glut.h>

class Star {

public :

GLfloat radius;

GLfloat speed,selfSpeed;

GLfloat distance;

GLfloat rgbaColor[4];

Star * parentStar;

Star(GLfloat radius,GLfloatdistance,GLfloatspeed,GLfloatselfSpeed,Star*parent);

void drawStar();

virtual void draw() {drawStar();}

virtual void update(longtimeSpan);

protected:

GLfloat alphaSelf,alpha;

};

class Planet :publicStar {

public:

   Planet(GLfloat radius, GLfloat distance,

          GLfloat speed,  GLfloat selfSpeed,

          Star* parent,GLfloatrgbColor[3]);

    void drawPlanet();

    virtual void draw() {drawPlanet(); drawStar(); }

};

class LightPlanet :publicPlanet {

public:

   LightPlanet(GLfloat Radius, GLfloat Distance,

                GLfloat Speed,  GLfloat SelfSpeed,

                Star*Parent, GLfloatrgbColor[]);

    voiddrawLight();

    virtual void draw() {drawLight(); drawPlanet(); drawStar(); }

};

#endif /* star_hpp */

 

来源: 实验楼

链接: https://www.shiyanlou.com/courses/558

 

 

 

solarSystem.hpp:

#include <GL/glut.h>

#include "stars.hpp"

#define STARS_NUM 10

class SolarSystem {

public :

 SolarSystem();

 ~SolarSystem();

 

 void onDisplay();

 void onUpdate();

 void onKeyboard(unsignedchar key,int x,int y);

 

private:

 Star * stars[STARS_NUM];

 GLdouble viewX,viewY,viewZ;

 GLdouble centerX,centerY,centerZ;

 GLdouble upX,upY,upZ;

};

 

star.cpp:

 

//  star.cpp

//  solarsystem

//

 

#include"stars.hpp"

#include<cmath>

 

#define PI3.1415926535

 

Star::Star(GLfloatradius, GLfloat distance,

           GLfloat speed,  GLfloat selfSpeed,

           Star* parent) {

    this->radius = radius;

    this->selfSpeed = selfSpeed;

    this->alphaSelf = this->alpha = 0;

    this->distance = distance;

 

    for (int i = 0; i < 4; i++)

        this->rgbaColor[i] = 1.0f;

 

    this->parentStar = parent;

    if (speed > 0)

        this->speed = 360.0f / speed;

    else

        this->speed = 0.0f;

}

 

voidStar::drawStar() {

 

    glEnable(GL_LINE_SMOOTH);//设置绘制直线的时候平滑处理

    glEnable(GL_BLEND);//设置颜色叠加模式,假如没有这个设置alpha不透明度是没有效果的,也就不会出现半透明颜色叠加效果

 

    int n = 1440;

 

    glPushMatrix();//弹入矩阵,默认弹入的是单位矩阵,接下来的glRotatefglTranslatef都会在堆栈顶部的矩阵的基础上进行,最后的glPopMatrix();是可选的,弹出矩阵后弹出的矩阵就消失了,接下来是在堆栈顶部的一个新的矩阵的基础上进行调整,也就是弹出矩阵下面的矩阵

 

    {

        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();

}

 

voidStar::update(long timeSpan) {

    alpha += timeSpan * speed;

    alphaSelf += selfSpeed;

}

 

 

Planet::Planet(GLfloatradius, GLfloat distance,

               GLfloat speed,  GLfloat selfSpeed,

               Star* parent, GLfloatrgbColor[3]) :

Star(radius,distance, speed, selfSpeed, parent) {

    rgbaColor[0] = rgbColor[0];

    rgbaColor[1] = rgbColor[1];

    rgbaColor[2] = rgbColor[2];

    rgbaColor[3] = 1.0f;

}

 

void Planet::drawPlanet(){

    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);

}

 

LightPlanet::LightPlanet(GLfloatradius,    GLfloat distance, GLfloatspeed,

                         GLfloat selfSpeed,Star* parent,   GLfloat rgbColor[3]) :

Planet(radius,distance, speed, selfSpeed, parent, rgbColor) {

    ;

}

 

voidLightPlanet::drawLight() {

 

   GLfloat light_position[] = {0.0f, 0.0f, 0.0f, 1.0f};//这里是设定光源属性,一旦设定了光源属性,那么之后绘制的集合图形都会沿用这个设定,除非重新调用onDisplay(),onDisplay()调用了glClear(GL_COLOR_BUFFER_BIT  | GL_DEPTH_BUFFER_BIT);

glClearColor(.7f, .7f,.7f, .1f);清除了缓冲区,也就是把屏幕上的东西清除干净了,貌似把所有的设定也都清除干净了

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

    GLfloat light_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,  light_diffuse);

    glLightfv(GL_LIGHT0, GL_SPECULAR,light_specular);//

}

 

来源: 实验楼

链接: https://www.shiyanlou.com/courses/558

本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播

//solarsystem.cpp

// solarsystem

//

 

solarsystem.cpp:

#include"solarsystem.hpp"

 

#define REST 700

#define REST_Z(REST)

#define REST_Y(-REST)

//这里猜想是将REST赋值给REST_ZREST_Y

 

voidSolarSystem::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);

 

    for (int i=0; i<STARS_NUM; i++)

        stars[i]->draw();

 

    glutSwapBuffers();

}

 

#define TIMEPAST1

voidSolarSystem::onUpdate() {

 

    for (int i=0; i<STARS_NUM; i++)

        stars[i]->update(TIMEPAST);

 

    this->onDisplay();

}

 

#define OFFSET20

voidSolarSystem::onKeyboard(unsigned char key, int x, int y) {

 

    switch (key)    {

        case 'w': viewY += OFFSET; break;

        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;//退出程序,27不知道对应的是哪个键

        default: break;

    }

 

}

//设置宏,对应着默认的小行星的一些属性,包括半径,自传速度,公转速度

#defineSUN_RADIUS 48.74

#defineMER_RADIUS  7.32

#defineVEN_RADIUS 18.15

#defineEAR_RADIUS 19.13

#defineMOO_RADIUS  6.15

#defineMAR_RADIUS 10.19

#defineJUP_RADIUS 42.90

#defineSAT_RADIUS 36.16

#defineURA_RADIUS 25.56

#defineNEP_RADIUS 24.78

 

#defineMER_DIS   62.06

#defineVEN_DIS  115.56

#defineEAR_DIS  168.00

#defineMOO_DIS   26.01

#defineMAR_DIS  228.00

#define JUP_DIS  333.40

#defineSAT_DIS  428.10

#define URA_DIS848.00

#define NEP_DIS949.10

 

#defineMER_SPEED   87.0

#defineVEN_SPEED  225.0

#defineEAR_SPEED  365.0

#defineMOO_SPEED   30.0

#defineMAR_SPEED  687.0

#defineJUP_SPEED 1298.4

#defineSAT_SPEED 3225.6

#defineURA_SPEED 3066.4

#defineNEP_SPEED 6014.8

 

#defineSELFROTATE 3

 

enum STARS {Sun,Mercury, Venus, Earth, Moon,

    Mars, Jupiter, Saturn, Uranus, Neptune};

 

#defineSET_VALUE_3(name, value0, value1, value2) \

                   ((name)[0])=(value0),((name)[1])=(value1), ((name)[2])=(value2)

*//这是一种语法,是一种静态模板的写法,将value0,value1,value2赋值给数组name的第一个值,第二个值,第三个值

SolarSystem::SolarSystem(){

 

    viewX = 0;

    viewY = REST_Y;

    viewZ = REST_Z;

    centerX = centerY = centerZ = 0;

    upX = upY = 0;

    upZ = 1;

 

    GLfloat rgbColor[3] = {1, 0, 0};

stars[Sun]     = newLightPlanet(SUN_RADIUS, 0, 0, SELFROTATE, 0, rgbColor);

//Sun是一个枚举,定义在enum STARS {Sun, Mercury, Venus, Earth, Moon,

    Mars, Jupiter,Saturn, Uranus, Neptune};,其值为0

 

 

    SET_VALUE_3(rgbColor, .2, .2, .5);

    stars[Mercury] = new Planet(MER_RADIUS,MER_DIS, MER_SPEED, SELFROTATE, stars[Sun], rgbColor);

 

    SET_VALUE_3(rgbColor, 1, .7, 0);

    stars[Venus]   = new Planet(VEN_RADIUS, VEN_DIS, VEN_SPEED,SELFROTATE, stars[Sun], rgbColor);

 

    SET_VALUE_3(rgbColor, 0, 1, 0);

    stars[Earth]   = new Planet(EAR_RADIUS, EAR_DIS, EAR_SPEED,SELFROTATE, stars[Sun], rgbColor);

 

    SET_VALUE_3(rgbColor, 1, 1, 0);

    stars[Moon]    = new Planet(MOO_RADIUS, MOO_DIS,MOO_SPEED, SELFROTATE, stars[Earth], rgbColor);

 

    SET_VALUE_3(rgbColor, 1, .5, .5);

    stars[Mars]    = new Planet(MAR_RADIUS, MAR_DIS,MAR_SPEED, SELFROTATE, stars[Sun], rgbColor);

 

    SET_VALUE_3(rgbColor, 1, 1, .5);

    stars[Jupiter] = new Planet(JUP_RADIUS,JUP_DIS, JUP_SPEED, SELFROTATE, stars[Sun], rgbColor);

 

    SET_VALUE_3(rgbColor, .5, 1, .5);

    stars[Saturn]  = new Planet(SAT_RADIUS, SAT_DIS, SAT_SPEED,SELFROTATE, stars[Sun], rgbColor);

 

    SET_VALUE_3(rgbColor, .4, .4, .4);

    stars[Uranus]  = new Planet(URA_RADIUS, URA_DIS, URA_SPEED,SELFROTATE, stars[Sun], rgbColor);

 

    SET_VALUE_3(rgbColor, .5, .5, 1);

    stars[Neptune] = new Planet(NEP_RADIUS,NEP_DIS, NEP_SPEED, SELFROTATE, stars[Sun], rgbColor);

 

}

SolarSystem::~SolarSystem()//SolarSystem的析构函数,由于solorsystem只使用到了stars[]这个数组,因此将这个数组释放貌似就行了,不过在C++里面数组的释放貌似不需要我们操心,会自己释放,不过这么写的话显得技术比较高

{

    for(int i = 0; i<STARS_NUM; i++)

        delete stars[i];

}

 

来源: 实验楼

链接: https://www.shiyanlou.com/courses/558

 

MakeFile文件:

CXX = g++

EXEC = solarsystem

SOURCES = main.cpp stars.cppsolarsystem.cpp

OBJECTS = main.o stars.o solarsystem.o

LDFLAGS = -lglut -lGL -lGLU

//以上这部分是设置变量

all :

      $(CXX)$(SOURCES) $(LDFLAGS) -o $(EXEC)

//这一句实际上是g++ main.cpp stars.cpp solarsystem.cpp -lglut -lGL–lGLU –o solarsystem

 

clean:

      rm-f $(EXEC) *.gdb *.o


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值