一、程序的效果图:
二、程序源代码位置:http://download.csdn.net/detail/sh15285118586/8570989
三、核心代码提炼:
1、单个粒子的代码:
Particle.h内容:(BMPLoader相关文件请参考我的博客“加载bmp文件方法二”)
#include "BMPLoader.h"
/** 粒子结构 */
struct Particle
{
float x,y,z; /**< 粒子的位置 */
unsigned int r,g,b; /**< 粒子的颜色 */
float vx,vy,vz; /**< 粒子的速度(x,y,z方向) */
float ax,ay,az; /**< 粒子在x,y,z上的加速度 */
float lifetime; /**< 粒子生命值 */
float size; /**< 粒子尺寸 */
float dec; /**< 粒子消失的速度 */
};
/** 粒子类 */
class CParticle
{
private:
CBMPLoader texture[2]; /**< 载入位图 */
Particle* data; /**< 粒子指针 */
int numparticle; /**< 粒子数目 */
public:
CParticle(); /**< 构造函数 */
~CParticle(); /**< 析构函数 */
/** 创建粒子数组 */
int Create(long num);
/** 设置和获取颜色属性 */
int SetColor(GLint r,GLint g,GLint b);
int SetColor(GLint index,GLint r,GLint g,GLint b);
int GetColor(GLint index,GLint &r,GLint &g,GLint &b);
/** 设置和获取速度属性 */
int SetVelocity(GLfloat vx,GLfloat vy,GLfloat vz);
int SetVelocity(GLint index,GLfloat vx,GLfloat vy,GLfloat vz);
int GetVelocity(GLint index,GLfloat &vx,GLfloat &vy,GLfloat &vz);
/** 设置和获取位置属性 */
int SetPosition(GLfloat x,GLfloat y,GLfloat z);
int SetPosition(GLint index,GLfloat x,GLfloat y,GLfloat z);
int GetPosition(GLint index,GLfloat &x,GLfloat &y,GLfloat &z);
/** 设置和获取加速度属性 */
int SetAcceleration(GLfloat ax,GLfloat ay,GLfloat az);
int SetAcceleration(GLint index,GLfloat ax,GLfloat ay,GLfloat az);
int GetAcceletation(GLint index,GLfloat &ax,GLfloat &ay,GLfloat &az);
/** 设置和获取尺寸属性 */
int SetSize(GLfloat size);
int SetSize(GLint index,GLfloat size);
int GetSize(GLint index,GLfloat &size);
/** 设置和获取消失速度属性 */
int SetDec(GLfloat dec);
int SetDec(GLint index,GLfloat dec);
int GetDec(GLint index,GLfloat &dec);
/** 设置和获取生命值属性 */
int SetLifeTime(GLfloat lifetime);
int SetLifeTime(GLint index,GLfloat lifetime);
int GetLifeTime(GLint index,GLfloat &lifetime);
/** 载入和获取纹理 */
bool LoadTextures();
unsigned int GetTexture(int index);
/** 获取粒子数组地址 */
Particle *GetParticle() { return data; }
/** 获得粒子的数目 */
int GetNumOfParticle() { return numparticle; }
/** 获得粒子所有的属性 */
int GetAll(int index, /**< 索引 */
GLint &r,GLint &g,GLint &b, /**< 粒子的颜色 */
GLfloat &x,GLfloat &y,GLfloat &z, /**< 位置 */
GLfloat &vx,GLfloat &vy,GLfloat &vz, /**< 速度 */
GLfloat &ax,GLfloat &ay,GLfloat &az, /**< 加速度 */
GLfloat &size, /**< 大小 */
GLfloat &lifetime, /**< 生命时间 */
GLfloat &dec /**< 消失速度 */
);
/** 设置粒子的所有属性 */
int SetAll(int index, /**< 索引 */
GLint r,GLint g,GLint b, /**< 粒子的颜色 */
GLfloat x,GLfloat y,GLfloat z, /**< 位置 */
GLfloat vx,GLfloat vy,GLfloat vz, /**< 速度 */
GLfloat ax,GLfloat ay,GLfloat az, /**< 加速度 */
GLfloat size, /**< 大小 */
GLfloat lifetime, /**< 生命时间 */
GLfloat dec /**< 消失速度 */
);
};
Particle.cpp内容:
#include "Particle.h"
/** 构造函数 */
CParticle::CParticle()
{
data = NULL;
numparticle = 0;
}
/** 析构函数 */
CParticle::~CParticle()
{
delete []data;
data = NULL;
}
/** 创建一个包含num个元素的粒子数组 */
int CParticle::Create(long num)
{
/** 删除粒子数组 */
if (data)
delete []data;
/** 创建数组 */
if(data = new Particle[num])
{
numparticle = num;
memset(data,0,sizeof(Particle)*numparticle);
/** 返回粒子个数 */
return numparticle;
}
return 0;
}
/** 载入纹理 */
bool CParticle::LoadTextures()
{
char* fileName[] = {"Data/wall.bmp","Data/flare.bmp" };
for(int i=0; i<2; i++)
{
if(!texture[i].LoadBitmap(fileName[i]))
{
MessageBox(NULL,"载入纹理失败!","错误",MB_OK);
exit(-1);
}
glGenTextures(1,&texture[i].ID);
/** 创建纹理对象 */
glBindTexture(GL_TEXTURE_2D, texture[i].ID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, texture[i].imageWidth,texture[i].imageHeight, GL_RGB, GL_UNSIGNED_BYTE,texture[i].image);
}
return true;
}
/** 返回纹理ID */
unsigned int CParticle::GetTexture(int index)
{
if(index == 0 || index == 1)
return texture[index].ID;
}
/** 设置和获取颜色Color的函数实现 */
int CParticle::SetColor(GLint r,GLint g,GLint b)
{
for (int index=0;index<numparticle;++index)
{
data[index].r=r;
data[index].g=g;
data[index].b=b;
}
return TRUE;
}
int CParticle::SetColor(GLint index,GLint r,GLint g,GLint b)
{
if(index>=0 && index<numparticle)
{
data[index].r=r;
data[index].g=g;
data[index].b=b;
return TRUE;
}
return FALSE;
}
int CParticle::GetColor(GLint index,GLint &r,GLint &g,GLint &b)
{
if(index>=0 && index<numparticle)
{
r=data[index].r;
g=data[index].g;
b=data[index].b;
return TRUE;
}
return FALSE;
}
/** 设置和获取位置Position的函数实现 */
int CParticle::SetPosition(GLfloat x,GLfloat y,GLfloat z)
{
for(int index=0;index<numparticle;++index)
{
data[index].x=x;
data[index].y=y;
data[index].z=z;
}
return TRUE;
}
int CParticle::SetPosition(GLint index,GLfloat x,GLfloat y,GLfloat z)
{
if(index>=0 && index<numparticle)
{
data[index].x=x;
data[index].y=y;
data[index].z=z;
return TRUE;
}
return FALSE;
}
int CParticle::GetPosition(GLint index,GLfloat &x,GLfloat &y,GLfloat &z)
{
if(index>=0 && index<numparticle)
{
x=data[index].x;
y=data[index].y;
z=data[index].z;
return TRUE;
}
return FALSE;
}
/** 设置和获取加速度Acceleration的函数实现 */
int CParticle::SetAcceleration(GLfloat ax,GLfloat ay,GLfloat az)
{
for (int index=0;index<numparticle;++index)
{
data[index].ax=ax;
data[index].ay=ay;
data[index].az=az;
}
return TRUE;
}
int CParticle::SetAcceleration(GLint index,GLfloat ax,GLfloat ay,GLfloat az)
{
if(index>=0 && index<numparticle)
{
data[index].ax=ax;
data[index].ay=ay;
data[index].az=az;
return TRUE;
}
return FALSE;
}
int CParticle::GetAcceletation(GLint index,GLfloat &ax,GLfloat &ay,GLfloat &az)
{
if(index>=0 && index<numparticle)
{
ax=data[index].ax;
ay=data[index].ay;
az=data[index].az;
return TRUE;
}
return FALSE;
}
/** Velocity函数的实现 */
int CParticle::SetVelocity(GLfloat vx,GLfloat vy,GLfloat vz)
{
for (int index=0;index<numparticle;++index)
{
data[index].vx=vx;
data[index].vy=vy;
data[index].vz=vz;
}
return TRUE;
}
int CParticle::SetVelocity(GLint index,GLfloat vx,GLfloat vy,GLfloat vz)
{
if(index>=0 && index<numparticle)
{
data[index].vx=vx;
data[index].vy=vy;
data[index].vz=vz;
return TRUE;
}
return FALSE;
}
int CParticle::GetVelocity(GLint index,GLfloat &vx,GLfloat &vy,GLfloat &vz)
{
if(index>=0 && index<numparticle)
{
vx=data[index].vx;
vy=data[index].vy;
vz=data[index].vz;
return TRUE;
}
return FALSE;
}
/** Size函数的实现 */
int CParticle::SetSize(GLfloat size)
{
for (int index=0;index<numparticle;++index)
{
data[index].size=size;
}
return TRUE;
}
int CParticle::SetSize(GLint index,GLfloat size)
{
if (index>=0 && index<numparticle)
{
data[index].size=size;
return TRUE;
}
return FALSE;
}
int CParticle::GetSize(GLint index,GLfloat &size)
{
if(index >= 0 && index < numparticle)
{
size=data[index].size;
return TRUE;
}
return FALSE;
}
/** 消失速度Dec函数 */
int CParticle::SetDec(GLfloat dec)
{
for (int index=0;index<numparticle;++index)
{
data[index].dec=dec;
}
return TRUE;
}
int CParticle::SetDec(GLint index,GLfloat dec)
{
if(index >= 0 && index < numparticle)
{
data[index].dec=dec;
return TRUE;
}
return FALSE;
}
int CParticle::GetDec(GLint index,GLfloat &dec)
{
if(index >= 0 && index < numparticle)
{
dec=data[index].dec;
return TRUE;
}
return FALSE;
}
/** 设置粒子的lifetime 属性 */
int CParticle::SetLifeTime(GLfloat lifetime)
{
for (int index=0;index<numparticle;++index)
{
data[index].lifetime=lifetime;
}
return TRUE;
}
int CParticle::SetLifeTime(GLint index,GLfloat lifetime)
{
if(index >= 0 && index < numparticle)
{
data[index].lifetime=lifetime;
return TRUE;
}
return FALSE;
}
/** 获得粒子的lifetime属性 */
int CParticle::GetLifeTime(GLint index,GLfloat &lifetime)
{
if(index >= 0 && index < numparticle)
{
lifetime=data[index].lifetime;
return TRUE;
}
return FALSE;
}
/** 获取粒子的所有属性 */
int CParticle::GetAll(int index,GLint &r,GLint &g,GLint &b, /**< 粒子的颜色 */
GLfloat &x,GLfloat &y,GLfloat &z, /**< 位置 */
GLfloat &vx,GLfloat &vy,GLfloat &vz, /**< 速度 */
GLfloat &ax,GLfloat &ay,GLfloat &az, /**< 加速度 */
GLfloat &size, /**< 大小 */
GLfloat &lifetime, /**< 生命时间 */
GLfloat &dec /**< 消失速度 */
)
{
if (index>=0 && index<numparticle)
{
r=data[index].r;
g=data[index].g;
b=data[index].b;
x=data[index].x;
y=data[index].y;
z=data[index].z;
vx=data[index].vx;
vy=data[index].vy;
vz=data[index].vz;
ax=data[index].ax;
ay=data[index].ay;
az=data[index].az;
lifetime=data[index].lifetime;
size=data[index].size;
dec=data[index].dec;
return TRUE;
}
return FALSE;
}
/** 设置粒子的所有属性 */
int CParticle::SetAll(int index,GLint r,GLint g,GLint b, /**< 粒子的颜色 */
GLfloat x,GLfloat y,GLfloat z, /**< 位置 */
GLfloat vx,GLfloat vy,GLfloat vz, /**< 速度 */
GLfloat ax,GLfloat ay,GLfloat az, /**< 加速度 */
GLfloat size, /**< 大小 */
GLfloat lifetime, /**< 生命时间 */
GLfloat dec /**< 消失速度 */
)
{
if(index>=0 && index<numparticle)
{
data[index].r=r;
data[index].g=g;
data[index].b=b;
data[index].x=x;
data[index].y=y;
data[index].z=z;
data[index].vx=vx;
data[index].vy=vy;
data[index].vz=vz;
data[index].ax=ax;
data[index].ay=ay;
data[index].az=az;
data[index].lifetime=lifetime;
data[index].size=size;
data[index].dec=dec;
return TRUE;
}
return FALSE;
}
2、WaterFall的代码:
WaterFall.h内容:
#include "BMPLoader.h"
#include "Particle.h"
/** 从GL_Application派生出一个子类 */
class Test : GLApplication
{
public:
bool<span style="white-space:pre"> </span>Init();<span style="white-space:pre"> </span>
void Draw();
void DrawParticle();
bool InitWaterfall();
void UpdateWaterfall();
private:
friend class GLApplication;
Test(const char * class_name); /**< 构造函数 */
/** 用户自定义的程序变量 */
CParticle* Waterfall; /**< 粒子系统的对象 */
};
WaterFall.cpp内容:
bool Test::Init()
{
/** 用户自定义的初始化过程 */
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
ResizeDraw(true);
glEnable(GL_TEXTURE_2D); /**< 开启纹理映射 */
glBlendFunc(GL_SRC_ALPHA,GL_ONE); /**< 设置混合因子获得半透明效果 */
glEnable(GL_BLEND); /**< 启用混和 */
if(!Waterfall->LoadTextures())
{
MessageBox(NULL,"载入纹理失败!","错误",MB_OK);
exit(-1);
}
/** 创建5000个粒子 */
Waterfall->Create(5000);
/** 初始化粒子 */
InitWaterfall();
return true; /**< 成功返回 */
}
/** 初始化粒子 */
bool Test::InitWaterfall()
{
for (int i=0; i < Waterfall->GetNumOfParticle(); ++i)
{
///初始化颜色
//r = rand()%255;
//g = rand()%255;
//b = rand()%255;
r = 100;
g = 100;
b = 100;
Waterfall->SetColor(i,r,g,b);
///初始化坐标
x = 0.005f * (rand()%9) - 1;
y = 0.005f * (rand()%9) + 1.6;
z = 0.0001f * (rand()%15000);
Waterfall->SetPosition(i,x,y,z);
///初始化速度
vz = 0;
vx = 0.000001f*(rand()%9000);
vy = -rand()%5400 * vx * vx;
Waterfall->SetVelocity(i,vx,vy,vz);
///初始化加速度
ax = 0;
ay = -0.0001;
az = 0;
Waterfall->SetAcceleration(i,ax,ay,az);
///初始化生命周期
lifetime = 100;
Waterfall->SetLifeTime(i,lifetime);
///消失速度
dec = 0.05 * (rand()%50);
Waterfall->SetDec(i,dec);
///初始化大小
Waterfall->SetSize(i,0.02f);
}
return true;
}
/** 绘制粒子 */
void Test::DrawParticle()
{
/** 绑定纹理 */
glBindTexture(GL_TEXTURE_2D,Waterfall->GetTexture(1));
for(int i = 0; i<Waterfall->GetNumOfParticle(); ++i)
{
/** 获得粒子的所有属性 */
Waterfall->GetAll(i,r,g,b,x,y,z,vx,vy,vz,ax,ay,az,size,lifetime,dec);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f);
glColor4ub(r,g,b,255);
glNormal3f(0.0f,0.0f,1.0f); /**< 定义法线方向 */
/** 画出粒子 */
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f);glVertex3f(x-size,y-size,z);
glTexCoord2f(1.0f,0.0f);glVertex3f(x-size,y+size,z);
glTexCoord2f(1.0f,1.0f);glVertex3f(x+size,y+size,z);
glTexCoord2f(0.0f,1.0f);glVertex3f(x+size,y-size,z);
glEnd();
/** 更新粒子属性 */
UpdateWaterfall();
Waterfall->SetAll(i,r,g,b,x,y,z,vx,vy,vz,ax,ay,az,size,lifetime,dec);
}
}
/** 更新粒子 */
void Test::UpdateWaterfall()
{
/** 更新位置 */
x += vx;
y += vy;
/** 更新速度 */
vy += ay;
/** 更新生存时间 */
lifetime -= dec;
/** 如果粒子消失或生命结束 */
if (y <= -1 || lifetime <= 0)
{
/** 初始化位置 */
x = 0.005f * (rand()%9) - 1;
y = 0.005f * (rand()%9) + 1.6;
z = 0.0001f * (rand()%15000);
/** 初始化速度 */
vz = 0;
vx = 0.000001f * (rand()%9000);
vy = -rand()%500 * vx * vx;
lifetime = 100;
dec = 0.05 * (rand()%50);
}
}
/** 绘制函数 */
void Test::Draw()
{
/** 用户自定义的绘制过程 */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
DrawParticle();
glFlush(); /**< 强制执行所有的OpenGL命令 */
}