源代码下载: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();//弹入矩阵,默认弹入的是单位矩阵,接下来的glRotatef,glTranslatef都会在堆栈顶部的矩阵的基础上进行,最后的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_Z和REST_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