太阳系Demo(openGL)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了太阳系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 };
View Code

  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 }
View Code

 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 };
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

 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 

以上是关于太阳系Demo(openGL)的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL太阳系Demo

如何在openGL中制作一个光球?

OpenGL简单实现太阳系模拟

基于Opengl的太阳系动画实现

OpenGL:光照模型视图投影变换

如何在 OpenGL 中创建 3D 太阳系中的星空背景?