太阳系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 };
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
以上是关于太阳系Demo(openGL)的主要内容,如果未能解决你的问题,请参考以下文章