继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

OpenGL版太阳系Demo(一)

jackyBu
关注TA
已关注
手记 22
粉丝 34
获赞 314

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

功能点描述:

   1、公转,自传

   2、基础的摄像机运动

   3、正视和顶视

   4、天空盒

   5、太阳黑子爆炸

   6、彗星带尾巴

   7、录制重播

实现代码:

1、简单的摄像机代码(目前仅支持移动,不支持旋转)
#ifndef CAMERA_H
#define CAMERA_H
#include "base.h"
struct glCamera
{
  vec3  pos;//摄像机的世界空间坐标
  float viewMatrix[16];
  vec3  forward;
  vec3  right;
  vec3  up;

public :

  glCamera( vec3 at)
  {
    pos=at;
  }

  void getViewMatrix()
  {
    glMatrixMode(GL_MODELVIEW);
    glGetFloatv(GL_MODELVIEW_MATRIX,viewMatrix);
  }

  void update()
  {
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

   glTranslatef(-pos.x,-pos.y,-pos.z);

   getViewMatrix();

   right=vec3(viewMatrix[0],viewMatrix[4],viewMatrix[8]);
   up=vec3(viewMatrix[1],viewMatrix[5],viewMatrix[9]);
   forward=vec3(viewMatrix[2],viewMatrix[6],viewMatrix[10]);
  } 
};
#endif
2、天空盒
#ifndef GLSKYBOX
#define GLSKYBOX
#include "base.h"
#include "gltexture.h"

void glDrawSkyBox(glTexture *tex,float x,float y,float z,float width,float height,float len)
{
  tex->MakeCurrent();

  //获取中心点
  x=x-width/2;
  y=y-height/2;
  z=z-len/2;

  //back face
  glBegin(GL_QUADS);
    glNormal3f(0.0,0.0,1.0);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x+width, y, z);

        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x+width, y+height, z);

        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x, y+height, z);

        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x, y, z);
  glEnd();
  //front face
  glBegin(GL_QUADS);
    glNormal3f(0.0,0.0,-1.0);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x, y, z+len);

        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x, y+height, z+len);

        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x+width, y+height, z+len);

        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x+width, y, z+len);
  glEnd();
  //bottom face
  glBegin(GL_QUADS);
    glNormal3f(0.0,1.0,0.0);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x, y, z);

        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x, y, z+len);

        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x+width, y, z+len);

        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x+width, y, z);
  glEnd();
  //top face
  glBegin(GL_QUADS);
    glNormal3f(0.0,-1.0,0.0);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x+width, y+height, z);

        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x+width, y+height, z+len);

        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x, y+height, z+len);

        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x, y+height, z);
  glEnd();
  //left face
  glBegin(GL_QUADS);
    glNormal3f(1.0,0.0,0.0);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x, y+height, z);

        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x, y+height, z+len);

        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x, y, z+len);

        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x, y, z);
  glEnd();

  //right face
  glBegin(GL_QUADS);
    glNormal3f(0.0,0.0,-1.0);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x+width, y, z);

        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x+width, y, z+len);

        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x+width, y+height, z+len);

        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x+width, y+height, z);
  glEnd();
}
#endif
 3、彗星尾巴(billboard一种运用)
#ifndef TRAIL_H
#define TRAIL_H
#include "base.h"
#include <vector>
#include "glTexture.h"
class glTrail
{
public:
    std::vector<vec3> path;
    float width;
    float color[4];
    glTexture* texture;

    glTrail(const char* texname) :
        width(0.2)
    {
        color[0] = 1.0f;
        color[1] = 1.0f;
        color[2] = 1.0f;
        color[3] = 1.0f;
        texture = new glTexture(texname, true);
    }

    virtual ~glTrail()
    {
        delete texture;
    }

    //设置trail的位置坐标
    void setPath(vec3 pos)
    {
        for (int i = 0; i < 5; i++)
            path.push_back(vec3((i + 0.5f), 0, 0));
    }

    void draw(vec3 pos)
    {
        vec3 v, v1, v2, v3, z;
        float f;
        int i;

        if (path.size() <= 1)
            return;

        texture->MakeCurrent();

        //深度写入禁止,但是深度比较还是需要的啦
        glDepthMask(GL_FALSE);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        glBegin(GL_QUAD_STRIP);

        for (i = 0; i < path.size(); i++)
        {
            z = pos - path[i];
            v3.x = v3.y = v3.z = 0.0f;
            if (i > 0)
            {
                v1 = path[i] - path[i - 1];
                v2.cross(z, v1);
                v2.normalize();
                v3 += v2;
            }
            if (i < (path.size() - 1))
            {
                v1 = path[i + 1] - path[i];
                v2.cross(z, v1);
                v2.normalize();
                v3 += v2;
            }
            v3.normalize();

            f = (float)i / (path.size() - 1);
            v = path[i] + v3*width;
            glTexCoord2f(0, f);
            glVertex3fv(&v.x);
            v = path[i] - v3*width;
            glTexCoord2f(1, f);
            glVertex3fv(&v.x);
        }
        glEnd();
        glDepthMask(GL_FALSE);
        glDisable(GL_BLEND);
    }
};
#endif
4、粒子系统(billboard另外一种运用)
struct glParticle
{
    vec3    m_pos;
    vec3    m_prevPos;
    vec3    m_velocity;
    vec3    m_acceleration;
    float   m_energy;

    float   m_size;
    float   m_sizeDelta;

    float   m_weight;
    float   m_weightDelta;

    float   m_color[4];
    float   m_colorDelta[4];
};

class glParticleSystem
{
public:

    glParticleSystem(int maxParticles, vec3 origin);

    virtual ~glParticleSystem() { KillSystem(); }

    virtual void  Update(float elapsedTime) = 0;
    virtual void  Render() = 0;

    virtual int   Emit(int numParticles);

    virtual void  InitializeSystem();
    virtual void  KillSystem();

protected:
    //纯虚函数,子类override
    virtual void  InitializeParticle(int index) = 0;

    //指针指向glParticle数组首地址
    //数量 = m_maxParticles
    //由于粒子系统会产生大量的小对象,因此用预先分配内存方式提高效率
    glParticle    *m_particleList;

    //最多可以产生的粒子数量
    int            m_maxParticles;

    //当前的粒子数量
    int            m_numParticles;

    //粒子发生的位置坐标
    vec3           m_origin;

    float          m_accumulatedTime;

    vec3           m_force;
};

glParticleSystem::glParticleSystem(int maxParticles, vec3 origin)
{
    //记录最大数量和原始坐标
    m_maxParticles = maxParticles;
    m_origin = origin;
    m_particleList = NULL;
    m_numParticles = 0;
    m_accumulatedTime = 0.0f;
}

int glParticleSystem::Emit(int numParticles)
{
    //粒子数量最多不能超过m_maxParticles
    while (numParticles && (m_numParticles < m_maxParticles))
    {

        InitializeParticle(m_numParticles++);
        --numParticles;
    }

    return numParticles;
}

void glParticleSystem::InitializeSystem()
{
    if (m_particleList)
    {
        delete[] m_particleList;
        m_particleList = NULL;
    }

    m_particleList = new glParticle[m_maxParticles];

    m_numParticles = 0;
    m_accumulatedTime = 0.0f;
}

void glParticleSystem::KillSystem()
{
    if (m_particleList)
    {
        delete[] m_particleList;
        m_particleList = NULL;
    }

    m_numParticles = 0;
    m_accumulatedTime = 0.0f;
}
打开App,阅读手记
13人推荐
发表评论
随时随地看视频慕课网APP