太阳系Demo(openGL)

这个是8年前写的demo,提交的一份作业,按照提出的需求点,以最快和最简单的方式完成功能,因此代码比较简单。

1)截图

2) 功能点描述:

1、公转,自传

2、基础的摄像机运动

3、正视和顶视

4、天空盒

5、太阳黑子爆炸

6、彗星带尾巴

7、录制重播

3) 实现代码:

1、简单的摄像机代码(目前仅支持移动,不支持旋转)

 1 struct glCamera
 2 {
 3   vec3  pos;//摄像机的世界空间坐标
 4   float viewMatrix[16];
 5   vec3  forward;
 6   vec3  right;
 7   vec3  up;
 8
 9 public :
10
11   glCamera( vec3 at)
12   {
13     pos=at;
14   }
15
16   void getViewMatrix()
17   {
18     glMatrixMode(GL_MODELVIEW);
19     glGetFloatv(GL_MODELVIEW_MATRIX,viewMatrix);
20   }
21
22   void update()
23   {
24    glMatrixMode(GL_MODELVIEW);
25    glLoadIdentity();
26
27    glTranslatef(-pos.x,-pos.y,-pos.z);
28
29    getViewMatrix();
30    right=vec3(viewMatrix[0],viewMatrix[4],viewMatrix[8]);
31    up=vec3(viewMatrix[1],viewMatrix[5],viewMatrix[9]);
32    forward=vec3(viewMatrix[2],viewMatrix[6],viewMatrix[10]);
33   }
34
35 };

2、天空盒

  1  glDrawSkyBox(glTexture *tex,float x,float y,float z,float width,float height,float len)
  2 {
  3   tex->MakeCurrent();
  4
  5   //获取中心点
  6   x=x-width/2;
  7   y=y-height/2;
  8   z=z-len/2;
  9
 10   //back face
 11   glBegin(GL_QUADS);
 12     glNormal3f(0.0,0.0,1.0);
 13         glTexCoord2f(1.0f, 0.0f);
 14         glVertex3f(x+width, y, z);
 15
 16         glTexCoord2f(1.0f, 1.0f);
 17         glVertex3f(x+width, y+height, z);
 18
 19         glTexCoord2f(0.0f, 1.0f);
 20         glVertex3f(x, y+height, z);
 21
 22         glTexCoord2f(0.0f, 0.0f);
 23         glVertex3f(x, y, z);
 24   glEnd();
 25   //front face
 26   glBegin(GL_QUADS);
 27     glNormal3f(0.0,0.0,-1.0);
 28         glTexCoord2f(1.0f, 0.0f);
 29         glVertex3f(x, y, z+len);
 30
 31         glTexCoord2f(1.0f, 1.0f);
 32         glVertex3f(x, y+height, z+len);
 33
 34         glTexCoord2f(0.0f, 1.0f);
 35         glVertex3f(x+width, y+height, z+len);
 36
 37         glTexCoord2f(0.0f, 0.0f);
 38         glVertex3f(x+width, y, z+len);
 39   glEnd();
 40   //bottom face
 41   glBegin(GL_QUADS);
 42     glNormal3f(0.0,1.0,0.0);
 43         glTexCoord2f(1.0f, 0.0f);
 44         glVertex3f(x, y, z);
 45
 46         glTexCoord2f(1.0f, 1.0f);
 47         glVertex3f(x, y, z+len);
 48
 49         glTexCoord2f(0.0f, 1.0f);
 50         glVertex3f(x+width, y, z+len);
 51
 52         glTexCoord2f(0.0f, 0.0f);
 53         glVertex3f(x+width, y, z);
 54   glEnd();
 55   //top face
 56   glBegin(GL_QUADS);
 57     glNormal3f(0.0,-1.0,0.0);
 58         glTexCoord2f(1.0f, 0.0f);
 59         glVertex3f(x+width, y+height, z);
 60
 61
 62         glTexCoord2f(1.0f, 1.0f);
 63         glVertex3f(x+width, y+height, z+len);
 64
 65
 66         glTexCoord2f(0.0f, 1.0f);
 67         glVertex3f(x, y+height, z+len);
 68
 69
 70         glTexCoord2f(0.0f, 0.0f);
 71         glVertex3f(x, y+height, z);
 72   glEnd();
 73   //left face
 74   glBegin(GL_QUADS);
 75     glNormal3f(1.0,0.0,0.0);
 76         glTexCoord2f(1.0f, 0.0f);
 77         glVertex3f(x, y+height, z);
 78
 79         glTexCoord2f(1.0f, 1.0f);
 80         glVertex3f(x, y+height, z+len);
 81
 82         glTexCoord2f(0.0f, 1.0f);
 83         glVertex3f(x, y, z+len);
 84
 85         glTexCoord2f(0.0f, 0.0f);
 86         glVertex3f(x, y, z);
 87   glEnd();
 88
 89   //right face
 90   glBegin(GL_QUADS);
 91     glNormal3f(0.0,0.0,-1.0);
 92         glTexCoord2f(1.0f, 0.0f);
 93         glVertex3f(x+width, y, z);
 94
 95         glTexCoord2f(1.0f, 1.0f);
 96         glVertex3f(x+width, y, z+len);
 97
 98         glTexCoord2f(0.0f, 1.0f);
 99         glVertex3f(x+width, y+height, z+len);
100
101         glTexCoord2f(0.0f, 0.0f);
102         glVertex3f(x+width, y+height, z);
103   glEnd();
104 }

3、彗星尾巴(billboard一种运用)

 1 class glTrail
 2 {
 3 public:
 4     std::vector<vec3> path;
 5     float width;
 6     float color[4];
 7     glTexture* texture;
 8
 9     glTrail(const char* texname) :
10         width(0.2)
11     {
12         color[0] = 1.0f;
13         color[1] = 1.0f;
14         color[2] = 1.0f;
15         color[3] = 1.0f;
16         texture = new glTexture(texname, true);
17     }
18
19     virtual ~glTrail()
20     {
21         delete texture;
22     }
23
24     //设置trail的位置坐标
25     void setPath(vec3 pos)
26     {
27         for (int i = 0; i < 5; i++)
28             path.push_back(vec3((i + 0.5f), 0, 0));
29     }
30
31     void draw(vec3 pos)
32     {
33         vec3 v, v1, v2, v3, z;
34         float f;
35         int i;
36
37         if (path.size() <= 1)
38             return;
39
40         texture->MakeCurrent();
41
42         //深度写入禁止,但是深度比较还是需要的啦
43         glDepthMask(GL_FALSE);
44         glEnable(GL_BLEND);
45         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
46         glBegin(GL_QUAD_STRIP);
47
48         for (i = 0; i < path.size(); i++)
49         {
50             z = pos - path[i];
51             v3.x = v3.y = v3.z = 0.0f;
52             if (i > 0)
53             {
54                 v1 = path[i] - path[i - 1];
55                 v2.cross(z, v1);
56                 v2.normalize();
57                 v3 += v2;
58             }
59             if (i < (path.size() - 1))
60             {
61                 v1 = path[i + 1] - path[i];
62                 v2.cross(z, v1);
63                 v2.normalize();
64                 v3 += v2;
65             }
66             v3.normalize();
67
68             f = (float)i / (path.size() - 1);
69             v = path[i] + v3*width;
70             glTexCoord2f(0, f);
71             glVertex3fv(&v.x);
72             v = path[i] - v3*width;
73             glTexCoord2f(1, f);
74             glVertex3fv(&v.x);
75         }
76         glEnd();
77         glDepthMask(GL_FALSE);
78         glDisable(GL_BLEND);
79     }
80 };

4、粒子系统(billboard另外一种运用)

  1 struct glParticle
  2 {
  3     vec3    m_pos;
  4     vec3    m_prevPos;
  5     vec3    m_velocity;
  6     vec3    m_acceleration;
  7     float   m_energy;
  8
  9     float   m_size;
 10     float   m_sizeDelta;
 11
 12     float   m_weight;
 13     float   m_weightDelta;
 14
 15     float   m_color[4];
 16     float   m_colorDelta[4];
 17 };
 18
 19
 20 class glParticleSystem
 21 {
 22 public:
 23
 24     glParticleSystem(int maxParticles, vec3 origin);
 25
 26     virtual ~glParticleSystem() { KillSystem(); }
 27
 28     virtual void  Update(float elapsedTime) = 0;
 29     virtual void  Render() = 0;
 30
 31     virtual int   Emit(int numParticles);
 32
 33     virtual void  InitializeSystem();
 34     virtual void  KillSystem();
 35
 36 protected:
 37     //纯虚函数,子类override
 38     virtual void  InitializeParticle(int index) = 0;
 39
 40     //指针指向glParticle数组首地址
 41     //数量 = m_maxParticles
 42     //由于粒子系统会产生大量的小对象,因此用预先分配内存方式提高效率
 43     glParticle    *m_particleList;
 44
 45     //最多可以产生的粒子数量
 46     int            m_maxParticles;
 47
 48     //当前的粒子数量
 49     int            m_numParticles;
 50
 51     //粒子发生的位置坐标
 52     vec3           m_origin;
 53
 54     float          m_accumulatedTime;
 55
 56     vec3           m_force;
 57 };
 58
 59 glParticleSystem::glParticleSystem(int maxParticles, vec3 origin)
 60 {
 61     //记录最大数量和原始坐标
 62     m_maxParticles = maxParticles;
 63     m_origin = origin;
 64     m_particleList = NULL;
 65     m_numParticles = 0;
 66     m_accumulatedTime = 0.0f;
 67 }
 68
 69 int glParticleSystem::Emit(int numParticles)
 70 {
 71     //粒子数量最多不能超过m_maxParticles
 72     while (numParticles && (m_numParticles < m_maxParticles))
 73     {
 74
 75         InitializeParticle(m_numParticles++);
 76         --numParticles;
 77     }
 78
 79     return numParticles;
 80 }
 81
 82
 83
 84 void glParticleSystem::InitializeSystem()
 85 {
 86     if (m_particleList)
 87     {
 88         delete[] m_particleList;
 89         m_particleList = NULL;
 90     }
 91
 92     m_particleList = new glParticle[m_maxParticles];
 93
 94     m_numParticles = 0;
 95     m_accumulatedTime = 0.0f;
 96 }
 97
 98 void glParticleSystem::KillSystem()
 99 {
100     if (m_particleList)
101     {
102         delete[] m_particleList;
103         m_particleList = NULL;
104     }
105
106     m_numParticles = 0;
107     m_accumulatedTime = 0.0f;
108 }

5、爆炸粒子系统

  1 #include "glparticle.h"
  2
  3 const vec3      PARTICLE_VELOCITY  (0.0f, 2.0f, 0.0f);
  4 const vec3      VELOCITY_VARIATION  (4.0f, 4.0f, 4.0f);
  5 const vec3      PARTICLE_ACCELERATION  (0.0f, -5.0f, 0.0f);
  6 const float     PARTICLE_SIZE      = 3.0f;//5.0f;
  7 const float     SIZE_VARIATION     = 0.3f;//2.0f;
  8 #define FRAND   (((float)rand()-(float)rand())/RAND_MAX)
  9
 10 class glExplosion : public glParticleSystem
 11 {
 12 public:
 13   glExplosion(int maxParticles, vec3 origin, float spread, GLuint texture);
 14   void  Update(float elapsedTime);
 15   void  Render();
 16   bool  IsDead() { return m_numParticles == 0; }
 17
 18   void    InitializeParticle(int index);
 19   float   m_spread;
 20   GLuint  m_texture;
 21 };
 22
 23 glExplosion::glExplosion(int numParticles, vec3 origin, float spread, GLuint texture)
 24     : m_texture(texture), m_spread(spread), glParticleSystem(numParticles, origin)
 25 {
 26     srand(timeGetTime());
 27     glParticleSystem::InitializeSystem();
 28     Emit(numParticles);
 29 }
 30
 31 void glExplosion::InitializeParticle(int index)//爆炸初始化
 32 {
 33     m_particleList[index].m_pos.x = m_origin.x + FRAND * m_spread;
 34     m_particleList[index].m_pos.y = m_origin.y + FRAND * m_spread;
 35     m_particleList[index].m_pos.z = m_origin.z + FRAND * m_spread;
 36
 37     m_particleList[index].m_size = PARTICLE_SIZE + FRAND * SIZE_VARIATION;
 38
 39     m_particleList[index].m_velocity.x = PARTICLE_VELOCITY.x + FRAND * VELOCITY_VARIATION.x;
 40     m_particleList[index].m_velocity.y = PARTICLE_VELOCITY.y + FRAND * VELOCITY_VARIATION.y;
 41     m_particleList[index].m_velocity.z = PARTICLE_VELOCITY.z + FRAND * VELOCITY_VARIATION.z;
 42
 43
 44     m_particleList[index].m_acceleration = PARTICLE_ACCELERATION;
 45     m_particleList[index].m_color[0] = 1.0;
 46     m_particleList[index].m_color[1] = 0.5f + FRAND * 0.5f;
 47     m_particleList[index].m_color[2] = 0.01f;
 48     m_particleList[index].m_color[3] = 1.0;
 49     m_particleList[index].m_energy = 1.5f + FRAND / 2.0f;
 50     m_particleList[index].m_colorDelta[0] = 0.0;
 51     m_particleList[index].m_colorDelta[1] = -(m_particleList[index].m_color[1] / 2.0f) / m_particleList[index].m_energy;
 52     m_particleList[index].m_colorDelta[2] = 0.0;
 53     m_particleList[index].m_colorDelta[3] = -1.0f / m_particleList[index].m_energy;
 54     m_particleList[index].m_sizeDelta = -m_particleList[index].m_size / m_particleList[index].m_energy;
 55 }
 56 void glExplosion::Update(float elapsedTime)//清除爆炸动画
 57 {
 58     for (int i = 0; i < m_numParticles;)
 59     {
 60         //更新位置s=vt;
 61         m_particleList[i].m_pos = m_particleList[i].m_pos + m_particleList[i].m_velocity * elapsedTime;
 62         //更新速度v=at;
 63         m_particleList[i].m_velocity = m_particleList[i].m_velocity + m_particleList[i].m_acceleration * elapsedTime;
 64         //能量随着时间流逝
 65         m_particleList[i].m_energy -= elapsedTime;
 66
 67         //size以及颜色随着时间变换
 68         m_particleList[i].m_size += m_particleList[i].m_sizeDelta * elapsedTime;
 69         m_particleList[i].m_color[3] += m_particleList[i].m_colorDelta[3] * elapsedTime;
 70         m_particleList[i].m_color[1] += m_particleList[i].m_colorDelta[1] * elapsedTime;
 71
 72         //如果当前粒子的能量<=0,说明没有了
 73         //则将最后一个粒子放入当前位置
 74         if (m_particleList[i].m_energy <= 0.0)
 75         {
 76             m_particleList[i] = m_particleList[--m_numParticles];
 77         }
 78         else
 79         {
 80             ++i;
 81         }
 82     }
 83 }
 84
 85
 86 void glExplosion::Render()//爆炸动画
 87 {
 88     glPushAttrib(GL_CURRENT_BIT);//保存现有颜色属性 glPopAttrib();//恢复前一属性
 89
 90     float viewMatrix[16];
 91     glGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
 92     vec3 right(viewMatrix[0], viewMatrix[4], viewMatrix[8]);
 93     vec3 up(viewMatrix[1], viewMatrix[5], viewMatrix[9]);
 94
 95     glDepthMask(GL_FALSE);
 96     glEnable(GL_BLEND);
 97     glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
 98
 99     glEnable(GL_TEXTURE_2D);
100     glBindTexture(GL_TEXTURE_2D, m_texture);
101     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
102
103     glBegin(GL_QUADS);
104     for (int i = 0; i < m_numParticles; ++i)
105     {
106         GLfloat size = m_particleList[i].m_size / 3;
107         vec3 pos = m_particleList[i].m_pos;
108         glColor4fv(m_particleList[i].m_color);
109
110         glTexCoord2f(0.0, 0.0); glVertex3fv((pos + (right + up) * -size).v);
111         glTexCoord2f(1.0, 0.0); glVertex3fv((pos + (right - up) * size).v);
112         glTexCoord2f(1.0, 1.0); glVertex3fv((pos + (right + up) * size).v);
113         glTexCoord2f(0.0, 1.0); glVertex3fv((pos + (up - right) * size).v);
114     }
115     glEnd();
116     //glDisable(GL_TEXTURE_2D);
117     glDisable(GL_BLEND);
118     glDepthMask(GL_TRUE);
119     glPopAttrib();//恢复前一属性
120 }

6、由于整个系统大部分都是圆形以及像土星一样带光圈的图形,因此在opengl中,二次曲面对象最适合这种显示

 1 void drawInit();
 2 void drawSphere(double radius , int slices, int stack,bool texture);
 3 void drawDisk( GLdouble            innerRadius,
 4                GLdouble            outerRadius,
 5                GLint               slices);
 6 void drawDeInit();
 7
 8 GLUquadricObj * m_quad = NULL;
 9
10 void drawInit()
11 {
12   m_quad = gluNewQuadric();
13 }
14
15 void drawDeInit()
16 {
17   gluDeleteQuadric(m_quad);
18 }
19
20 void drawSphere(double radius , int slices, int stack ,bool texture)
21 {
22
23   gluQuadricTexture(m_quad, true);
24   gluSphere(m_quad,radius,slices,stack);
25 }
26
27 void drawDisk(GLdouble            innerRadius,
28     GLdouble            outerRadius,
29     GLint               slices )
30 {
31   gluDisk(m_quad,innerRadius,
32     outerRadius,
33     slices,
34     true);
35 }

7、纹理载入,使用lodepng库读取png图像,该库最大的好处是只有单独一个文件,不需要依赖zlib和libpng等库就能惊醒png读写。

  1 class glTexture
  2 {
  3 public:
  4   GLuint m_tex;
  5     glTexture(){m_tex=0;}
  6
  7     glTexture(const char* fname,
  8         bool make_mipmaps=true);
  9
 10     ~glTexture();
 11
 12     void MakeCurrent();
 13 };
 14
 15
 16 glTexture::glTexture(const char *fname,
 17     bool make_mipmaps)
 18 {
 19
 20     std::vector<unsigned char> image;
 21     unsigned int width, height;
 22     unsigned int error = lodepng::decode(image, width, height, fname);
 23
 24     if (error != 0)
 25     {
 26         std::cout << "error " << error << ": " << lodepng_error_text(error) << std::endl;
 27         return;
 28     }
 29
 30     m_tex = 0;
 31     glEnable(GL_TEXTURE_2D);
 32     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 33
 34     //Get a texture space and make it active
 35     glGenTextures(1, &m_tex);
 36     glBindTexture(GL_TEXTURE_2D, m_tex);
 37
 38     //Set default(and fastest) texture propoties
 39     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 40     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 41     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 42     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 43     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 44
 45     //Determine if mipmaps are used
 46     if (make_mipmaps)
 47     {
 48         gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]);
 49     }
 50     else
 51     {
 52
 53         double xPow2, yPow2;
 54         int ixPow2, iyPow2;
 55         int xSize2, ySize2;
 56         unsigned char* pData = NULL;
 57
 58         GLint glMaxTexDim;
 59         //Get the maximum texture size
 60         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim);
 61         //Get the powers of 2 that correspond to the width and height of the original
 62         //or of the maxmaximum texture size if widthor height is larger than the maxmaximum texture size
 63         if (width <= glMaxTexDim)
 64             xPow2 = log((double)width) / log((double)2.0);
 65         else
 66             xPow2 = log((double)glMaxTexDim) / log((double)2.0);
 67
 68         if (height <= glMaxTexDim)
 69             yPow2 = log((double)height) / log((double)2.0);
 70         else
 71             yPow2 = log((double)glMaxTexDim) / log((double)2.0);
 72
 73         //round the power of 2 up to the nearest power of 2
 74         ixPow2 = (int)xPow2;
 75         iyPow2 = (int)yPow2;
 76
 77         if (xPow2 != (double)ixPow2)
 78             ixPow2++;
 79         if (yPow2 != (double)iyPow2)
 80             iyPow2++;
 81         //convert power to actual value
 82         xSize2 = 1 << ixPow2;
 83         ySize2 = 1 << iyPow2;
 84         //if the new sizes are different than the old ones
 85         //resize and scale the "RGBAImage"
 86         if (xSize2 != width || ySize2 != height)
 87         {
 88             pData = (unsigned char*)malloc(xSize2 * ySize2 * 4 * sizeof(unsigned char));
 89
 90             if (!pData)
 91                 return;
 92
 93             gluScaleImage(GL_RGBA,
 94                 width,
 95                 height,
 96                 GL_UNSIGNED_BYTE,
 97                 &image[0],
 98                 xSize2,
 99                 ySize2,
100                 GL_UNSIGNED_BYTE,
101                 pData);
102
103             width = xSize2;
104             height = ySize2;
105         }
106
107         glTexImage2D(GL_TEXTURE_2D,
108             0, 4, width,height,
109             0, GL_RGB, GL_UNSIGNED_BYTE,pData);
110
111         if (pData)
112         {
113             free(pData);
114             pData = NULL;
115         }
116     }
117 }
118
119
120 void glTexture::MakeCurrent()
121 {
122     glBindTexture(GL_TEXTURE_2D, m_tex);
123 }
124
125 glTexture::~glTexture()
126 {
127     glDeleteTextures(1, &m_tex);
128 }

8、行星结构的定义

 1 class planet
 2 {
 3 public:
 4   float aroundRotatedSpeed;//公转
 5   float selfRotatedSpeed;//自转
 6   float radius;//行星的半径,影响绘制的大小啦
 7   //下面这个变量代表当前行星离父亲之间的的距离拉
 8   //1.太阳系以太阳为中心进行运动
 9   //2.除地球外其他行星相对于太阳进行自转和公转,因此对于其他行星来说,太阳就是父亲,其他行星就是儿子
10   //3比较特殊的是地球,地球也是相对太阳进行自转和公转的,但是地球还有一个儿子,既月球,因此对于月球来说,他的父亲是地球,他的父亲的父亲是太阳
11   //层次关系总结如下:
12   //   太阳
13   //      除地球和月球外的其他行星
14   //      地球
15   //         月球
16   vec3 pos;
17
18   glTexture *texture;
19 public:
20
21   planet(const char* texname,float as,float ss,float radius,vec3 pos)
22   {
23     texture=new glTexture(texname,true);
24     this->aroundRotatedSpeed =as;
25     this->selfRotatedSpeed =ss;
26     this->radius =radius;
27     this->pos =pos;
28
29   }
30
31   ~planet()
32   {
33       if (!texture)
34       {
35           delete texture;
36           texture = NULL;
37       }
38   }
39
40 };

9、录制与回放,采取最简单的方式,记录当前的angle,所有的星球运动都是基于当前anlge变量,因此其他运动都是当前角度的某个映射关系,因此只要记录当前的angle,就能实现录制和回放功能(其实由上述代码可见,纯粹是为了完成任务,因此采取最简洁有效方式,哈哈哈)

 1 int angle = 0; //核心变量,所有行星的移动和转动的速度是以angle为基础的啦,改变angle旋转速度会影响所有行星的运动速度,包括角速度和距离,所有行星都是按照angle相对比例进行运动
 2
 3 void record()
 4 {
 5     if (filesys.beginWrite("test.txt"))
 6     {
 7         filesys.writeInt(angle);
 8         filesys.closeFile();
 9     }
10 }
11
12 void rePlay()
13 {
14     if (filesys.beginRead("test.txt"))
15     {
16         filesys.readInt(&angle);
17         filesys.closeFile();
18     }
19 }

10、main.cpp

  1 //全局变量声明
  2 bool lighting = true;
  3 fileSystem filesys;//record/replay系统使用
  4 int frontViewOnOff;//开关变量,前视图和正视图转换
  5 glTexture *boxtex;//天空盒纹理贴图,理论上天空盒需要六张无缝拍摄的纹理,现在就用一张贴在天空盒六个面上,简化一下
  6 glTexture *parttex;
  7 glExplosion * glexp = new glExplosion(1, vec3(0, 0, 0), 1.0f, 0);
  8 bool isexp = true;
  9 int numexp;
 10 float px, py, pz;
 11 glTrail* trail;
 12
 13 //行星系统
 14 planet *sun; //太阳
 15 planet *sx;  //水星
 16 planet *jx;  //金星
 17 planet *hx;  //火星
 18 planet *mx;  //木星
 19 planet *tx;  //土星
 20 planet *twx; //天王星
 21 planet *hwx; //海王星
 22
 23 planet * earth; //地球
 24 planet * moon;  //月亮
 25
 26 glCamera camera(vec3(0.0f, 0.0f, 10.0f)); //摄像机初始位置,w/s键控制摄像机前后移动,a/d控制摄像机左右移动,鼠标左键按下拖动控制摄像机的pitch/yaw旋转
 27
 28 int angle = 0; //核心变量,所有行星的移动和转动的速度是以angle为基础的啦,改变angle旋转速度会影响所有行星的运动速度,包括角速度和距离,所有行星都是按照angle相对比例进行运动
 29
 30 void SetLight(bool b)
 31 {
 32     float amb[4] = { 1.0, 0.8, 0.8, 1 };
 33     float dif[4] = { 1.0, 1.0, 1.0, 1 };
 34     float pos[4] = { 0, 10, 0, 1 };
 35     glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
 36     glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
 37     glLightfv(GL_LIGHT0, GL_SPECULAR, dif);
 38     glLightfv(GL_LIGHT0, GL_POSITION, pos);
 39     glColorMaterial(GL_FRONT, GL_DIFFUSE);
 40
 41     if (b)
 42     {
 43         glEnable(GL_LIGHTING);
 44         glEnable(GL_LIGHT0);
 45     }
 46     else
 47     {
 48         glDisable(GL_LIGHTING);
 49         glDisable(GL_LIGHT0);
 50     }
 51
 52     glShadeModel(GL_SMOOTH);
 53 }
 54
 55 void init()
 56 {
 57     boxtex = new glTexture("星空图.png", true);
 58
 59     sun = new planet("太阳.png", 0.0f, 1.0f, 1.0f, vec3(0.0f, 0.0f, 0.0f));
 60     sx = new planet("水星.png", 0.5f, 0.5f, 0.2f, vec3(1.4f, 0.4f, 0.0f));
 61     jx = new planet("金星.png", 0.5f, 0.5f, 0.2f, vec3(3.0f, -0.4f, 0.0f));
 62     earth = new planet("地球.png", 1.0f, 2.0f, 0.5f, vec3(5.0f, 2.0f, 8.0f));
 63     moon = new planet("月亮.png", 0.5f, 0.5f, 0.2f, vec3(1.5f, 0.0f, 0.0f));
 64     hx = new planet("火星.png", 0.2f, 0.3f, 0.3f, vec3(7.0f, 0.0f, 0.0f));
 65     mx = new planet("木星.png", 0.4f, 1.0f, 0.5f, vec3(10.0f, 0.0f, 0.0f));
 66     tx = new planet("土星.png", -0.4f, 0.2f, 1.0f, vec3(15.0f, 1.0f, 0.0f));
 67     twx = new planet("天王星.png", 0.8f, 0.5f, 0.3f, vec3(17.0f, 0.0f, 0.0f));
 68     hwx = new planet("海王星.png", 0.6f, 0.5f, 0.4f, vec3(19.0f, 0.8f, 0.0f));
 69
 70     parttex = new glTexture("particle.png");
 71
 72     trail = new glTrail("spawnflash.png");
 73     trail->setPath(vec3(0, 0, 0));
 74
 75     glFrontFace(GL_CCW);
 76     glCullFace(GL_BACK);
 77
 78     //初始化二次曲面对象
 79     drawInit();
 80 }
 81
 82 void deinit()
 83 {
 84     delete boxtex;
 85     delete sun;
 86     delete sx;
 87     delete jx;
 88     delete earth;
 89     delete moon;
 90     delete hx;
 91     delete mx;
 92     delete tx;
 93     delete twx;
 94     delete hwx;
 95     delete parttex;
 96     delete trail;
 97     delete glexp;
 98     drawDeInit();
 99 }
100
101 void record()
102 {
103     if (filesys.beginWrite("test.txt"))
104     {
105         filesys.writeInt(angle);
106         filesys.closeFile();
107     }
108 }
109
110 void rePlay()
111 {
112     if (filesys.beginRead("test.txt"))
113     {
114         filesys.readInt(&angle);
115         filesys.closeFile();
116     }
117 }
118
119 static void DrawEarthAndMoon(planet *earth, planet *moon)
120 {
121     glPushMatrix();//地球公转+自转(围绕太阳)
122     earth->texture->MakeCurrent();
123
124     glRotatef(angle*earth->aroundRotatedSpeed, 0.0f, 1.0f, 0.0f);
125     glTranslatef(earth->pos.x, earth->pos.y, earth->pos.z);
126     glRotatef(angle*earth->selfRotatedSpeed, 0.0f, 1.0f, 0.0f);
127     drawSphere(earth->radius, 20, 20, true);
128
129     glPushMatrix();//月球公转+自转(围绕地球)
130     moon->texture->MakeCurrent();
131     glRotatef(angle*moon->aroundRotatedSpeed, 0.0f, 1.0f, 0.0f);
132     glTranslatef(moon->pos.x, moon->pos.y, moon->pos.z);
133     glRotatef(angle*moon->selfRotatedSpeed, 0.0f, 1.0f, 0.0f);
134     drawSphere(moon->radius, 20, 20, true);
135     glPopMatrix();
136
137     glPopMatrix();
138 }
139 static void DrawOtherPlanet(planet * p)
140 {
141     glPushMatrix();
142     p->texture->MakeCurrent();
143     glRotatef(angle*p->aroundRotatedSpeed, 0.0f, 1.0f, 0.0f);
144     glTranslatef(p->pos.x, p->pos.y, p->pos.z);
145     glRotatef(angle*p->selfRotatedSpeed, 0.0f, 1.0f, 0.0f);
146     drawSphere(p->radius, 20, 20, true);
147     glPopMatrix();
148 }
149
150 static void DrawTrail(planet * p)
151 {
152     glPushMatrix();
153     glRotatef(angle*p->aroundRotatedSpeed*2.0f, 0.0f, 1.0f, 0.0f);
154     glTranslatef(p->pos.x + 0.4f, p->pos.y + 0.3, p->pos.z);
155     glPushMatrix();
156     glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
157     trail->draw(camera.pos);
158     glPopMatrix();
159     glRotatef(angle*p->selfRotatedSpeed, 0.0f, 1.0f, 0.0f);
160     drawSphere(p->radius, 20, 20, true);
161     glPopMatrix();
162 }
163
164 static void DrawOtherPlanet2(planet * p)
165 {
166     glPushMatrix();
167     p->texture->MakeCurrent();
168
169     glRotatef(angle*p->aroundRotatedSpeed, 0.0f, 1.0f, 0.0f);
170
171     glTranslatef(p->pos.x, p->pos.y, p->pos.z);
172
173
174     glRotatef(angle*p->selfRotatedSpeed, 0.0f, 1.0f, 0.0f);
175
176     drawSphere(p->radius, 20, 20, true);
177
178     glPushMatrix();
179     glRotatef(85, 1.0f, 0.0f, 0.0f);
180
181     drawDisk(1.5, 3, 20);
182
183     glPopMatrix();
184     glPopMatrix();
185
186 }
187 void DrawJX()
188 {
189     glPushMatrix();
190     jx->texture->MakeCurrent();
191
192     glRotatef(angle*jx->aroundRotatedSpeed * 2, 1.0, 1.0, 1.0);
193
194     glTranslatef(5.0f, 0.0, 0.0f);
195     glRotatef(angle*jx->aroundRotatedSpeed * 2, 0.0f, 0.0f, 1.0f);
196
197     drawSphere(jx->radius, 20, 20, true);
198     glPopMatrix();
199 }
200 void DrawHX()
201 {
202     glPushMatrix();
203     hx->texture->MakeCurrent();
204
205     glRotatef(angle*hx->aroundRotatedSpeed * 2, -1.0, -1.0, 0.0);
206
207     glTranslatef(5.0f, 0.0, 0.0f);
208
209     glRotatef(angle*hx->aroundRotatedSpeed * 2, 0.0f, 0.0f, 1.0f);
210
211     drawSphere(hx->radius, 20, 20, true);
212
213     glPopMatrix();
214
215 }
216 void testdraw1(planet *p)
217 {
218     glPushMatrix();
219     p->texture->MakeCurrent();
220
221     glRotatef(45, 1.0, 0.0, 0.0);
222     glRotatef(angle*p->aroundRotatedSpeed * 2, 0.0f, 1.0f, 0.0f);
223
224     glTranslatef(5.0f, 0, 0.0f);
225     glRotatef(angle*p->aroundRotatedSpeed * 2, 0.0f, 0.0f, 1.0f);
226
227     drawSphere(p->radius, 20, 20, true);
228     glPopMatrix();
229 }
230
231 void DrawSolarSystem(planet *sun)
232 {
233     sun->texture->MakeCurrent();
234
235     SetLight(lighting);
236     glTranslatef(sun->pos.x, sun->pos.y, sun->pos.z);
237     glRotatef(angle*sun->selfRotatedSpeed, 0.0f, 1.0f, 0.0f);
238     drawSphere(sun->radius, 50, 50, true);
239     DrawEarthAndMoon(earth, moon);//地月绘制
240     DrawOtherPlanet(sx);
241     DrawOtherPlanet(jx);
242     DrawOtherPlanet(twx);
243     DrawOtherPlanet(hwx);
244     //带光圈绘制
245     DrawOtherPlanet2(mx);
246     DrawOtherPlanet2(tx);
247     DrawTrail(jx);
248 }
249
250 void myKeyboardFunc(unsigned char key, int x, int y)
251 {
252     switch (key)
253     {
254     case 27:        //ESC
255         exit(0);    //退出系统
256         break;
257     case ‘w‘://摄像机向前运动
258
259         camera.pos -= camera.forward*0.5;
260         glutPostRedisplay();
261         break;
262     case ‘s‘://摄像机向后运动
263         camera.pos += camera.forward*0.5;
264
265         glutPostRedisplay();
266         break;
267     case ‘a‘://摄像机向左运动
268
269         camera.pos -= camera.right *0.5;
270         glutPostRedisplay();
271         break;
272     case ‘d‘://摄像机向右运动
273
274         camera.pos += camera.right*0.5;
275         glutPostRedisplay();
276         break;
277     case ‘f‘://正视图和顶视图切换
278
279         frontViewOnOff ^= 1;
280         glutPostRedisplay();
281         break;
282     case ‘r‘://记录
283         record();
284         glutPostRedisplay();
285         break;
286     case ‘p‘://回放
287         rePlay();
288         glutPostRedisplay();
289         break;
290     case ‘l‘://灯源开关
291         lighting = !lighting;
292         glutPostRedisplay();
293         break;
294     }
295
296 }
297
298
299 void myReshape(int w, int h)
300 {
301     glViewport(0, 0, w, h);
302     glMatrixMode(GL_PROJECTION);
303     glLoadIdentity();
304     gluPerspective(60, GLfloat(w) / h, 0.1, 1000);
305     glMatrixMode(GL_MODELVIEW);
306     glLoadIdentity();
307     glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
308     glClearDepth(1.0f);
309     glEnable(GL_DEPTH_TEST);
310     glDepthFunc(GL_LESS);
311     glShadeModel(GL_SMOOTH);
312 }
313
314 void creatExplosion(float x, float y, float z, int num, float spread)
315 {
316     if (glexp != NULL) { delete glexp; glexp = NULL; }
317     glexp = new glExplosion(num, vec3(0, 0, 0), spread, parttex->m_tex);
318     px = x, pz = z, py = y;
319     isexp = false;
320     numexp = 0;
321 }
322
323 void  drawExplosion()
324 {
325     glPushMatrix();
326     glTranslatef(px, py, pz);
327     if (isexp == false)
328     {
329         glexp->Render();
330         isexp = true;
331     }
332     if (isexp)
333     {
334         glexp->Update(0.03f);
335         isexp = false;
336     }
337     glPopMatrix();
338 }
339
340 void myDisplay(void)
341 {
342     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
343
344     camera.update();
345
346     //如果顶视图的话,沿着x轴旋转90度
347     glRotatef(frontViewOnOff*90.0f, 1.0f, 0.0f, 0.0f);
348
349     //绘制天空盒
350     glDrawSkyBox(boxtex, 0.0f, 0.0f, 0.0f, 1000.0f, 1000.0f, 1000.0f);
351
352     DrawJX();
353     DrawHX();
354     DrawSolarSystem(sun);
355
356     if (numexp > 100)
357     {
358         creatExplosion(1.0f, 1.0f, 1.0f, 100, 1.5f);
359     }
360
361     drawExplosion();
362
363     angle += 2;
364     numexp++;
365
366     glutSwapBuffers();
367 }
368
369 void myTimerFunc(int val)
370 {
371     myDisplay();
372     glutTimerFunc(25, myTimerFunc, 0);
373 }
374
375 int  main(int argc, char *argv[])
376 {
377     glutInit(&argc, argv);
378     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
379     glutInitWindowPosition(100, 100);
380     glutInitWindowSize(800, 600);
381     glutCreateWindow("太阳系 w/s/a/d控制摄像机运动 r/录制 p/回放 f/切换正顶视图 l/光源开关");
382     init();
383     glutDisplayFunc(&myDisplay);
384     glutReshapeFunc(&myReshape);
385     glutKeyboardFunc(&myKeyboardFunc);
386     glutTimerFunc(25, myTimerFunc, 0);
387     glutMainLoop();
388     deinit();
389     return 0;
390 }

11、源码下载以及参考文档

完整的源代码可以到 https://github.com/jackyblf/SolarSystem-openGL- 进行下载。

源码中包含了billboardingtut.pdf的文档,讲解了所有的billboard类型以及适用范围,基于opengl描述。强烈推荐这篇文档

时间: 2024-10-18 12:07:09

太阳系Demo(openGL)的相关文章

OpenGL太阳系Demo

这是8年前写的demo,提交的一份作业,按照提出的需求点,以最快和最简单的方式完成功能,因此代码比较简单. 功能点描述: 1.公转,自传 2.基础的摄像机运动 3.正视和顶视 4.天空盒 5.太阳黑子爆炸 6.彗星带尾巴 7.录制重播 实现代码: 到此一游https://github.com/jackyblf/SolarSystem-openGL-

Android OpenGL ES 开发教程 从入门到精通

From:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

[转]Android OpenGL ES 开发教程 从入门到精通

本文转自:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

Opengl绘制计算几何库CGAL三角剖分结果的Demo

Ubuntu下改编了一个用CGAL计算输入点的三角剖分,并用OpenGL显示结果的C++程序. 该Demo可作为一个计算几何及绘图的框架. 代码如下: //编译命令:g++ spatial_sort.cpp -lglut -lGL -lGLU -lCGAL -lCGAL_Core -lgmp #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>   #include <CGAL/Triangulation_eucl

opengl 3D 动画 太阳系

Android OpenGL ES零基础系列(一):理解GLSurfaceView,GLSurfaceView.Render的基本用法

转载请注明出处 前言 OpenGL ES是OpenGL的一个子集,是针对手机.PDA和游戏主机等嵌入式设备而设计的.该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准. 因此OpenGL ES作为第三方库被应用在android中. 到目前为止,OpenGL ES已经发展有了3个版本,OpenGL ES 1.0 , OpenGL ES 2.0 , OpenGL ES 3.0.其中OpenGL ES 1.0 是以OpenGL 1.3

OpenGL ES总结(六)OpenGL ES中EGL

Agenda: EGL是什么? EGL数据类型 EGL在Android中应用 EGL的工作流程 GLSurfaceView与EGL区别 简单Demo EGL是什么? EGL? is an interface between Khronos rendering APIs such as OpenGL ES or OpenVG and the underlying native platform window system. It handles graphics context managemen

OpenGL ES着色语言-光照效果之散射光

OpenGL光照模型,在固定管线中,主要是调用OpenGL函数实现,如果使用着色器,该怎么实现.本文的例子是移植OpenGL 4.0 Shading Language Cookbook中第二章的例子.代码已经移植到Android上. 散射光计算主要涉及到两个向量,第一个是顶点到光源的向量S,以及顶点处的法向量N.光照计算在眼睛坐标中进行.具体见下图所示: 有这两个向量之后,还要考虑顶点处的漫反射系数以及光源强度,最终顶点处的光照强度的结果可以通过下列公式计算: Ld为光源强度,Kd为漫反射系数.

关于OpenGL的绘制上下文

什么是绘制上下文(Rendering Context) 初学OpenGL,打开红宝书,会告诉你OpenGL是个状态机,OpenGL采用了客户端-服务器模式,那时觉得好抽象,直到后来了解了绘制上下文才把这些联系起来.我们可以认为每一个硬件GPU是个服务器,每一个绘制上下文对应于申请的一个客户端,一个客户端维护着一套状态机,如果两个窗口分别对应两个不同的绘制上下文,则两个窗口彼此状态独立.申请绘制上下文,意味着系统资源的申请,每个绘制上下文还是需要不少资源的,记得曾经试过在chrome的TAB页不断