📄 particles.cpp
字号:
#include "particles.h"
ParticleSystem::ParticleSystem(const char *textureFilename, int numberOfParticles, GLfixed x, GLfixed y, GLfixed z)
{
srand(GetTickCount()); //set the random number generator seed
//set the emmiter position
m_emmiter[0] = x;
m_emmiter[1] = y;
m_emmiter[2] = z;
//Create the particles texture: if it is a .raw texture, it must be 16x16 with two channels (16 bits)
m_texture = new Texture(textureFilename, GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE,GL_CLAMP_TO_EDGE,64,64,16);
m_numberOfParticles = numberOfParticles;
m_totalLifeTime = new GLfixed[m_numberOfParticles];
m_lifeTime = new GLfixed[m_numberOfParticles];
m_startSpeed = new GLfixed[m_numberOfParticles];
m_startAngle = new int[m_numberOfParticles];
m_color = new GLubyte[m_numberOfParticles * 4]; //RGBA
m_position = new GLfixed[m_numberOfParticles * 3]; //XYZ
//Initialize all particles
for(int i=0;i< m_numberOfParticles;++i)
ResetParticle(i);
//Initialize trigonometric tables
for(i=0;i<360;++i)
{
m_sin[i] = FixedFromFloat((float)sin(DEGTORAD(i)));
m_cos[i] = FixedFromFloat((float)cos(DEGTORAD(i)));
}
}
//----------------------------------------------------------------------------
ParticleSystem::~ParticleSystem()
{
delete [] m_totalLifeTime;
delete [] m_lifeTime;
delete [] m_startSpeed;
delete [] m_startAngle;
delete [] m_color;
delete [] m_position;
delete m_texture;
}
//----------------------------------------------------------------------------
void ParticleSystem::ResetParticle(int index)
{
m_totalLifeTime[index] = FixedFromInt(2 + rand()%1);//random number between 2 and 3 (seconds)
m_lifeTime[index] = m_totalLifeTime[index];
m_startSpeed[index] = FixedFromInt(5 + rand()%3); //random number between 5 and 8 (m/s)
//Random number between 0 and 360 degrees
m_startAngle[index] = rand() % 360;
//random number between 0 and 255 (color is in GLubyte format: 0-255)
int colorIndex = index * 4;
m_color[colorIndex] = rand()%255;
m_color[colorIndex + 1] = rand()%255;
m_color[colorIndex + 2] = rand()%255;
m_color[colorIndex + 3] = 255;
//set starting position at emmiter
int positionIndex = index * 3;
m_position[positionIndex] = m_emmiter[0];
m_position[positionIndex + 1] = m_emmiter[1];
m_position[positionIndex + 2] = m_emmiter[2];
}
//----------------------------------------------------------------------------
void ParticleSystem::UpdateParticles(unsigned int elapsedTime)
{
//convert elapsed time from milliseconds to seconds
GLfixed felapsed = DivideFixed(FixedFromInt(elapsedTime), FixedFromInt(1000));
//iterate throught all particles
for(int i=0;i< m_numberOfParticles;++i)
{
m_lifeTime[i] -= felapsed; //reduce the particle's lifetime
if((m_lifeTime[i] <= 0)||(m_position[i * 3 + 1] < 0))
ResetParticle(i); //reset the partice if has died or of touched the floor(y < 0)
else
{
GLfixed flife = m_totalLifeTime[i] - m_lifeTime[i]; //current life time
//we will set an alpha transparency based on the particle's life time: (lifetime/totaltime)*255
GLfixed aux = DivideFixed(m_lifeTime[i],m_totalLifeTime[i]);
m_color[i * 4 + 3] = (GLubyte)IntFromFixed(MultiplyFixed(aux,FixedFromInt(255)));
/*Compute the particle's position. for the vertical axis, we will use the vertical axis
ecuation of the parabolic shot(-0.5*g*t*t)+(V0*t)
For the horizontal ones, we will use the horizontal component, in a radial direction given by
m_startAngle: (1/8)*(V0*sin(angle)) (the 1/8 factor is handcoded, to simulate an high elevation angle
of the parabolic shot*/
GLfixed temp1, temp2;
temp1 = MultiplyFixed(flife,flife);
temp1 = MultiplyFixed(GRAVITY, temp1);
temp2 = MultiplyFixed(m_startSpeed[i],flife);
GLfixed fHorizontalFactor = MultiplyFixed(FixedFromFloat(0.125f), flife);
int positionIndex = i * 3;
m_position[positionIndex] += MultiplyFixed(MultiplyFixed(m_startSpeed[i], m_sin[m_startAngle[i]]), fHorizontalFactor);
m_position[positionIndex + 1] += temp1 + temp2;
m_position[positionIndex + 2] += MultiplyFixed(MultiplyFixed(m_startSpeed[i], m_cos[m_startAngle[i]]), fHorizontalFactor);
}
}
}
//----------------------------------------------------------------------------
void ParticleSystem::DrawParticles(unsigned int elapsedTime)
{
//Update all particles before drawing
UpdateParticles(elapsedTime);
//Enable blending and disable the alpha test.
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
//Setup point sprites coordinate generation
glEnable(GL_POINT_SPRITE_OES);
glTexEnvx(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
glPointSize(15);
m_texture->BindTexture();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FIXED, 0, m_position);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, m_color);
glDrawArrays(GL_POINTS,0,m_numberOfParticles);
//restore all states
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glTexEnvx(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_FALSE);
glDisable(GL_TEXTURE_2D);
glDisable(GL_POINT_SPRITE_OES);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -