📄 particlesystem.cpp
字号:
/*****************************************************************************
*
*
* Parts of routine, class concept and particle theory
* originally written by Richard Benson
*
* Code written by Brian Tischler 07/2000
* Author e-mail : briandeb@telusplanet.net
*
* The source can be modified, reused & redistributed for non-profitable
* uses. Use for commercial purposes without author's permission prohibited.
*
*****************************************************************************/
// ParticleSystem.cpp: implementation of the CParticleSystem class.
//
//////////////////////////////////////////////////////////////////////
#include "HotSpot.h"
#include "ParticleSystem.h"
#include <math.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CParticleSystem::CParticleSystem()
{
m_fEmissionResidue = 0.0f;
m_bIsSuppressed = FALSE;
fVarx = 0.8f;
}
CParticleSystem::~CParticleSystem()
{
}
//-----------------------------------------------------------------------------
//
// CParticleSystem::IsColliding
//
//-----------------------------------------------------------------------------
bool CParticleSystem::IsColliding()
{
return m_bIsColliding;
}
//////////////////////////////////////////////////
CParticleSystem::Update(float fTime)
{
// fTime is absolute time. So we need to calculate the relative time displacement or fTimeDelta that has elapesed
float fTimeDelta = fTime - m_fTimeLastUpdate;
m_fTimeLastUpdate = fTime;
//TODO
//set location of system here
// sort of a hack (or nice screen saver effect) to test out a moving particle system
if (m_bIsMoving)
{
static float fThetaHoriz = 0.0f;
static float fThetaVert = 180.0f;
fThetaHoriz += 25.0f * fTimeDelta;
fThetaVert += 35.0f * fTimeDelta*fVarx;
if ( fThetaHoriz > 359.0f )
{
fThetaHoriz = 0.0f;
}
if ( fThetaVert > 359.0f )
{
fVarx = RANDOM_NUM*1.0f+1.0f;
fThetaVert = 0.0f;
}
m_vLocation.x = 20.0f * (float)cos( fThetaHoriz * 0.01745f );//*0.75f;
m_vLocation.y = 7.0f * (float)sin( fThetaVert * 0.01745f );//*0.75f;
m_vLocation.z = 20.0f * (float)sin( fThetaHoriz * 0.01745f )*(float)sin( fThetaVert * 0.01745f );//*0.75f;
}
else
{
// this will reset it every frame, but most importantly it will reset it to the origin if it isn't Moving
m_vLocation.x = 0.0f;
m_vLocation.y = 0.0f;
m_vLocation.z = 0.0f;
}
// clear our counter variable before counting how many particles are alive
m_uParticlesAlive = 0;
// update all particles that we own
for ( int i=0; i<MAX_PARTICLES; i++)
{
if (m_rParticles[i].m_fAge >= 0.0f )
if ( m_rParticles[i].Update( fTimeDelta )) // update function returns FALSE if the m_rParticles died
m_uParticlesAlive++;
}
// calculate how many particles we should create from ParticlesPerSec and time elapsed taking the
// previous frame's EmissionResidue into account.
float fParticlesNeeded = m_uParticlesPerSec * fTimeDelta + m_fEmissionResidue;
// cast the float fparticlesNeeded to a INT to see how many particles we really need to create.
unsigned int uParticlesCreated = (unsigned int)fParticlesNeeded;
if ( !m_bIsSuppressed )
{
// remember the difference between what we wanted to create and how many we created.
m_fEmissionResidue = fParticlesNeeded - uParticlesCreated;
}
else
{
m_fEmissionResidue = 0.0f;
uParticlesCreated = 0;
}
// see if actually have any to create
if ( uParticlesCreated > 0 )
{
// loop through all the particles to see if any are available
for ( i=0; i<MAX_PARTICLES; i++ )
{
// if created enough particles, this value will be 0 and so skip the rest
if ( !uParticlesCreated )
break;
// if the age is -1.0f then this Particles is not in use
if ( m_rParticles[i].m_fAge < 0.0f )
{
// New Particle so it's age is 0.0f
// Actually should be some randomization of fTimeDelta since in a perfect world
// particles would have been created between our last update and now.
m_rParticles[i].m_fAge = 0.0f;
m_rParticles[i].m_fLifetime = m_fLifeTime+RANDOM_NUM * m_fLifeVar;
Clamp( m_rParticles[i].m_fLifetime, MIN_LIFETIME, MAX_LIFETIME );
// Calculate our Alpha from the system's AlphaStart and AlphaVar
m_rParticles[i].m_fAlpha = m_fAlphaStart + RANDOM_NUM * m_fAlphaVar;
// clamp any overflow
Clamp( m_rParticles[i].m_fAlpha, MIN_ALPHA, MAX_ALPHA );
// calculate a delta so that by the time the m_rParticles dies, it will have reached it's "AlphaEnd"
m_rParticles[i].m_fAlphaDelta = (m_fAlphaEnd - m_rParticles[i].m_fAlpha) / m_rParticles[i].m_fLifetime;
// our start color is going to be the System's StartColor + the System's color variation
m_rParticles[i].m_vColor.r = m_vColorStart.r+ RANDOM_NUM * m_vColorVar.r;
m_rParticles[i].m_vColor.g = m_vColorStart.g + RANDOM_NUM * m_vColorVar.g;
m_rParticles[i].m_vColor.b = m_vColorStart.b + RANDOM_NUM * m_vColorVar.b;
// clamp any overflow
Clamp( m_rParticles[i].m_vColor.r, 0.0f, 1.0f );
Clamp( m_rParticles[i].m_vColor.g, 0.0f, 1.0f );
Clamp( m_rParticles[i].m_vColor.b, 0.0f, 1.0f );
// calculate a delta so that by the time the m_rParticles dies, it will have reached it's "ColorEnd"
m_rParticles[i].m_vColorDelta.r = ((m_vColorEnd.r+ RANDOM_NUM * m_vColorVar.r) - m_rParticles[i].m_vColor.r) / m_rParticles[i].m_fLifetime;
m_rParticles[i].m_vColorDelta.g = ((m_vColorEnd.g+ RANDOM_NUM * m_vColorVar.g) - m_rParticles[i].m_vColor.g) / m_rParticles[i].m_fLifetime;
m_rParticles[i].m_vColorDelta.b = ((m_vColorEnd.b+ RANDOM_NUM * m_vColorVar.b) - m_rParticles[i].m_vColor.b) / m_rParticles[i].m_fLifetime;
//Start Size and End Size then delta and clamping
m_rParticles[i].m_fSize = m_fSizeStart + RANDOM_NUM * m_fSizeVar;
Clamp( m_rParticles[i].m_fSize, MIN_SIZE, MAX_SIZE );
m_rParticles[i].m_fSizeDelta = (m_fSizeEnd - m_rParticles[i].m_fSize) / m_rParticles[i].m_fLifetime;
//GRAVITY
// It's a percentage of normal gravity.
m_rParticles[i].m_vParticleGravity.x = m_vGravityStart.x * GRAVITY + RANDOM_NUM * m_fGravityVar*GRAVITY;
Clamp( m_rParticles[i].m_vParticleGravity.x, MIN_GRAVITY*GRAVITY, MAX_GRAVITY*GRAVITY );
m_rParticles[i].m_vGravityDelta.x =
( m_vGravityEnd.x*GRAVITY - m_rParticles[i].m_vParticleGravity.x ) / m_rParticles[i].m_fLifetime;
m_rParticles[i].m_vParticleGravity.y = m_vGravityStart.y * GRAVITY + RANDOM_NUM * m_fGravityVar*GRAVITY;
Clamp( m_rParticles[i].m_vParticleGravity.y, MIN_GRAVITY*GRAVITY, MAX_GRAVITY*GRAVITY );
m_rParticles[i].m_vGravityDelta.y =
( m_vGravityEnd.y*GRAVITY - m_rParticles[i].m_vParticleGravity.y ) / m_rParticles[i].m_fLifetime;
m_rParticles[i].m_vParticleGravity.z = m_vGravityStart.z * GRAVITY + RANDOM_NUM * m_fGravityVar*GRAVITY;
Clamp( m_rParticles[i].m_vParticleGravity.z, MIN_GRAVITY*GRAVITY, MAX_GRAVITY*GRAVITY );
m_rParticles[i].m_vGravityDelta.z =
( m_vGravityEnd.z*GRAVITY - m_rParticles[i].m_vParticleGravity.z ) / m_rParticles[i].m_fLifetime;
/* m_rParticles[i].m_fGravity = m_fGravityStart*GRAVITY;// + RANDOM_NUM * m_fGravityVar*GRAVITY;
Clamp( m_rParticles[i].m_fGravity, MIN_GRAVITY*GRAVITY, MAX_GRAVITY*GRAVITY );
m_rParticles[i].m_fGravityDelta =
( m_fGravityEnd*GRAVITY - m_rParticles[i].m_fGravity ) / m_rParticles[i].m_fLifetime;
*/
// since Velocity is a change in position over time,
// calculate a Velocity the Particles would have to
// have travelled to move from PrevLocation to Location in fTimeDelta seconds.
// Then calculate points in that linear path by passing in different Time deltas
m_vTempVelocity.x = (m_vLocation.x - m_vPrevLocation.x)/fTimeDelta;
m_vTempVelocity.y = (m_vLocation.y - m_vPrevLocation.y)/fTimeDelta;
m_vTempVelocity.z = (m_vLocation.z - m_vPrevLocation.z)/fTimeDelta;
// Emit the particles from a location between the last known location and the current location
m_rParticles[i].m_vLocation.x = m_vPrevLocation.x;// + m_vTempVelocity.x * RANDOM_NUM * fTimeDelta;
m_rParticles[i].m_vLocation.y = m_vPrevLocation.y;// + m_vTempVelocity.y * RANDOM_NUM * fTimeDelta;
m_rParticles[i].m_vLocation.z = m_vPrevLocation.z;// + m_vTempVelocity.z * RANDOM_NUM * fTimeDelta;
// Update the previous location so the next update we can remember where we were
m_rParticles[i].m_vPrevLocation.x = m_rParticles[i].m_vLocation.x;
m_rParticles[i].m_vPrevLocation.y = m_rParticles[i].m_vLocation.y;
m_rParticles[i].m_vPrevLocation.z = m_rParticles[i].m_vLocation.z;
// The emitter has a Direction. This code adds some randomness to that direction so
// that we don't emit a Line of particles.
float RandomYaw = RANDOM_NUM * 3.14159f * 2.0f;
float RandomPitch = RANDOM_NUM * m_fTheta * 3.14159f ;/// 180.0f ;
//this uses spherical coordinates to randomize the velocity vector ( or the direction ) of the m_rParticles
m_rParticles[i].m_vVelocity.y = static_cast<float>(cos( RandomPitch ));
m_rParticles[i].m_vVelocity.x = static_cast<float>(sin(RandomPitch) * cos(RandomYaw));
m_rParticles[i].m_vVelocity.z = static_cast<float>(sin(RandomPitch) * sin(RandomYaw));
/*
// Velocity at this point is just a direction (normalized vector ) and needs to be multiplied by
// the speed component to be a true velocity
float fNewSpeed = m_fSpeed + RANDOM_NUM * m_fSpeedVar;
Clamp( fNewSpeed, MIN_SPEED, MAX_SPEED );
*/
// Multiply Velocity by speed
m_rParticles[i].m_vVelocity.x *= m_fSpeed ;
m_rParticles[i].m_vVelocity.y *= m_fSpeed ;
m_rParticles[i].m_vVelocity.z *= m_fSpeed ;
/*
m_rParticles[i].m_vVelocity.y = (0.5f-RANDOM_NUM)* RANDOM_NUM;// * m_fSpeedVar;
m_rParticles[i].m_vVelocity.x = (0.5f-RANDOM_NUM)* RANDOM_NUM;// * m_fSpeedVar;
m_rParticles[i].m_vVelocity.z = (0.5f-RANDOM_NUM)* RANDOM_NUM;// * m_fSpeedVar;
m_rParticles[i].m_vVelocity.x *= m_fSpeed ;
m_rParticles[i].m_vVelocity.y *= m_fSpeed ;
m_rParticles[i].m_vVelocity.z *= m_fSpeed ;
*/
// let the m_rParticles know who it's Daddy is
m_rParticles[i].SetParent(this);
// decrement the number of needed particles
uParticlesCreated--;
}
}
}
///set prevlocation to current location so next frame we know where we were
m_vPrevLocation = m_vLocation;
//return TRUE;
}
//this draws the particle system in the ogl window
CParticleSystem::Draw(float x_Rot,float y_Rot)
{
int loop;
for (loop = 0; loop < MAX_PARTICLES; loop++)
{
//if the particle is still alive, draw it
if (m_rParticles[loop].m_fAge >= 0.0f)
{
glColor4f(m_rParticles[loop].m_vColor.r,m_rParticles[loop].m_vColor.g,
m_rParticles[loop].m_vColor.b,m_rParticles[loop].m_fAlpha);
glPushMatrix();
glTranslatef(m_rParticles[loop].m_vLocation.x,
m_rParticles[loop].m_vLocation.y,
m_rParticles[loop].m_vLocation.z);
//bring the bitmap into view, pointing the cam
glRotatef(y_Rot,0.0f,1.0f,0.0f);
glRotatef(x_Rot,1.0f,0.0f,0.0f);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -