⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 particlesystem.cpp

📁 粒子系统编辑器 包括了很多特效
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 *
 * 
 * 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 + -