鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 软件教程 > 图形图像 > >

太阳系Demo(openGL)

来源:互联网 作者:佚名 时间:2017-09-09 17:42
这个是8年前写的demo,提交的一份作业,按照提出的需求点,以最快和最简单的方式完成功能,因此代码比较简单。 1)截图 2) 功能点描述: 1、公转,自传 2、基础的摄像机运动 3、正视和顶视 4、天空盒 5、太阳黑子爆炸 6、彗星带尾巴 7、录制重播 3) 实现代码:

这个是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 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 }
View Code

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

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

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

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

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

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

 

网友评论
<