C++实现太阳系行星系统
实验楼项目:C++实现太阳系行星系统
关于详细知识跟着实验做比较好
基础知识
做这个项目需要知道一些基础知识:
- OpenGL
- GLUT
类设计
main.cpp
#include<GL/glut.h>
#include "solarsystem.hpp"
#define WINDOW_X_POS 50
#define WINDOW_Y_POS 50
#define WIDHT 700
#define HEIGHT 700
SolarSystem solarsystem;
void onDisplay(void)
{
solarsystem.onDisplay();
}
void onUpdate(void)
{
solarsystem.onUpdate();
}
void onKeyboard(unsigned char 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("SolarSystem at Wuhan");
glutDisplayFunc(onDisplay);
glutIdleFunc(onUpdate);
glutKeyboardFunc(onKeyboard);
glutMainLoop();
return 0;
}
solarsystem.cpp
#include "solarsystem.hpp"
#define REST 700
#define REST_Z (REST)
#define REST_Y (-REST)
void SolarSystem::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 TIMEPAST 1
void SolarSystem::onUpdate()
{
for (int i = 0; i < STARS_NUM; ++i)
stars[i]->update(TIMEPAST);
this->onDisplay();
}
#define OFFSET 20
void SolarSystem::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;
default: break;
}
}
#define SUN_RADIUS 48.74
#define MER_RADIUS 7.32
#define VEN_RADIUS 18.15
#define EAR_RADIUS 19.13
#define MOO_RADIUS 6.15
#define MAR_RADIUS 10.19
#define JUP_RADIUS 42.90
#define SAT_RADIUS 36.16
#define URA_RADIUS 25.56
#define NEP_RADIUS 24.78
#define MER_DIS 62.06
#define VEN_DIS 115.56
#define EAR_DIS 168.00
#define MOO_DIS 26.01
#define MAR_DIS 228.00
#define JUP_DIS 333.40
#define SAT_DIS 428.10
#define URA_DIS 848.00
#define NEP_DIS 949.10
#define MER_SPEED 87.0
#define VEN_SPEED 225.0
#define EAR_SPEED 365.0
#define MOO_SPEED 30.0
#define MAR_SPEED 687.0
#define JUP_SPEED 1298.4
#define SAT_SPEED 3225.6
#define URA_SPEED 3066.4
#define NEP_SPEED 6014.8
#define SELFROTATE 3
enum STARS
{
Sun, // 太阳
Mercury, // 水星
Venus, // 金星
Earth, // 地球
Moon, // 月球
Mars, // 火星
Jupiter, // 木星
Saturn, // 土星
Uranus, // 天王星
Neptune, // 海王星
};
#define SET_VALUE_3(name, value0, value1, value2) \
((name)[0])=(value0), ((name)[1])=(value1), ((name)[2])=(value2)
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] = new LightPlanet(SUN_RADIUS, 0, 0, SELFROTATE, 0, rgbColor);
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()
{
for (int i = 0; i < STARS_NUM; ++i)
delete stars[i];
}
solarsystem.hpp
#include <GL/glut.h>
#include "stars.hpp"
#define STARS_NUM 10
class SolarSystem
{
public:
SolarSystem();
~SolarSystem(); // 析构函数
void onDisplay();
void onUpdate();
void onKeyboard(unsigned char key, int x, int y);
private:
Star *stars[STARS_NUM];
// 定义观察视角的参数
GLdouble viewX, viewY, viewZ;
GLdouble centerX, centerY, centerZ;
GLdouble upX, upY, upZ;
};
stars.cpp
#include "stars.hpp"
#include<cmath>
#define PI 3.1415926
Star::Star(GLfloat radius, GLfloat distance, GLfloat speed, GLfloat selfSpeed, Star *parentStar)
{
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 = parentStar;
if (speed > 0)
this->speed = 360.0f / speed;
else
this->speed = 0.0f;
}
void Star::drawStar()
{
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
int n = 1440;
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(alphaSelf, 0, 0, 1);
glColor3f(rgbaColor[0], rgbaColor[1],rgbaColor[2]);
glutSolidSphere(radius, 40, 32);
}
glPopMatrix();
}
void Star::update(long timeSpan)
{
alpha += timeSpan * speed; // 更新角度
alphaSelf += selfSpeed; // 更新自转角度
}
Planet::Planet(GLfloat radius, GLfloat distance, GLfloat speed, GLfloat selfSpeed, Star *parentStar, GLfloat rgbColor[3]):
Star(radius, distance, speed, selfSpeed, parentStar)
{
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(GLfloat radius, GLfloat distance, GLfloat speed, GLfloat selfSpeed, Star *parentStar, GLfloat rgbColor[3]):
Planet(radius, distance, speed, selfSpeed, parentStar, rgbColor)
{
;
}
void LightPlanet::drawLight()
{
GLfloat light_position[] = {0.0f, 0.0f, 0.0f, 1.0f};
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);
}
stars.hpp
#ifndef stars_hpp
#define stars_hpp
#include<GL/glut.h>
class Star
{
public:
GLfloat radius; // 星球的半径
GLfloat speed, selfSpeed; // 星球的公转、自转速度
GLfloat distance; // 星球的中心与父节点星球中心的距离
GLfloat rgbaColor[4]; // 星球的颜色
Star *parentStar; // 父节点星球
Star(GLfloat radius, GLfloat distance, GLfloat speed, GLfloat selfSpeed, Star *parentStar); // 构造函数
void drawStar(); // 对一般的星球移动、旋转等活动进行绘制
virtual void draw() { drawStar(); } // 提供默认实现
virtual void update(long timeSpan); // 参数为每次刷新画面时的时间跨度
protected:
GLfloat alphaSelf, alpha;
};
class Planet : public Star
{
public:
Planet(GLfloat radius, GLfloat distance, GLfloat speed, GLfloat selfSpeed, Star *parentStar, GLfloat rgbColor[3]);
void drawPlanet(); // 增加对具备自身材质的行星绘制材质
virtual void draw() { drawPlanet(); drawStar(); }
};
class LightPlanet : public Planet
{
public:
LightPlanet(GLfloat radius, GLfloat distance, GLfloat speed, GLfloat selfSpeed, Star *parentStar, GLfloat rgbColor[]);
void drawLight(); // 增加对提供光源的恒星绘制光照
virtual void draw() { drawLight(); drawPlanet(); drawStar(); }
};
#endif