这是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;
}