📄 particlesystem.cpp
字号:
//-----------------------------------------------------------------------------
// Name: particlesystem.h
// Author: Kevin Harris
// Last Modified: 02/01/05
// Description: Implementation file for the CParticleSystem Class
//-----------------------------------------------------------------------------
#include <tchar.h>
#include "particlesystem.h"
//-----------------------------------------------------------------------------
// Name: getRandomMinMax()
// Desc: Gets a random number between min/max boundaries
//-----------------------------------------------------------------------------
float getRandomMinMax( float fMin, float fMax )
{
float fRandNum = (float)rand () / RAND_MAX;
return fMin + (fMax - fMin) * fRandNum;
}
//-----------------------------------------------------------------------------
// Name: getRandomVector()
// Desc: Generates a random vector where X,Y, and Z components are between
// -1.0 and 1.0
//-----------------------------------------------------------------------------
D3DXVECTOR3 getRandomVector( void )
{
D3DXVECTOR3 vVector;
// Pick a random Z between -1.0f and 1.0f.
vVector.z = getRandomMinMax( -1.0f, 1.0f );
// Get radius of this circle
float radius = (float)sqrt(1 - vVector.z * vVector.z);
// Pick a random point on a circle.
float t = getRandomMinMax( -D3DX_PI, D3DX_PI );
// Compute matching X and Y for our Z.
vVector.x = (float)cosf(t) * radius;
vVector.y = (float)sinf(t) * radius;
return vVector;
}
//-----------------------------------------------------------------------------
// Name : classifyPoint()
// Desc : Classifies a point against the plane passed
//-----------------------------------------------------------------------------
int classifyPoint( D3DXVECTOR3 *vPoint, Plane *pPlane )
{
D3DXVECTOR3 vDirection = pPlane->m_vPoint - *vPoint;
float fResult = D3DXVec3Dot( &vDirection, &pPlane->m_vNormal );
if( fResult < -0.001f )
return CP_FRONT;
if( fResult > 0.001f )
return CP_BACK;
return CP_ONPLANE;
}
//-----------------------------------------------------------------------------
// Name: CParticleSystem()
// Desc:
//-----------------------------------------------------------------------------
CParticleSystem::CParticleSystem()
{
m_dwVBOffset = 0; // Gives the offset of the vertex buffer chunk that's currently being filled
m_dwFlush = 512; // Number of point sprites to load before sending them to hardware(512 = 2048 divided into 4 chunks)
m_dwDiscard = 2048; // Max number of point sprites the vertex buffer can load until we are forced to discard and start over
m_pActiveList = NULL; // Head node of point sprites that are active
m_pFreeList = NULL; // Head node of point sprites that are inactive and waiting to be recycled.
m_pPlanes = NULL;
m_dwActiveCount = 0;
m_fCurrentTime = 0.0f;
m_fLastUpdate = 0.0f;
m_pVB = NULL; // The vertex buffer where point sprites are to be stored
m_chTexFile = NULL;
m_ptexParticle = NULL;
m_dwMaxParticles = 1;
m_dwNumToRelease = 1;
m_fReleaseInterval = 1.0f;
m_fLifeCycle = 1.0f;
m_fSize = 1.0f;
m_clrColor = D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);
m_vPosition = D3DXVECTOR3(0.0f,0.0f,0.0f);
m_vVelocity = D3DXVECTOR3(0.0f,0.0f,0.0f);
m_vGravity = D3DXVECTOR3(0.0f,0.0f,0.0f);
m_vWind = D3DXVECTOR3(0.0f,0.0f,0.0f);
m_bAirResistence = true;
m_fVelocityVar = 1.0f;
SetTexture("particle.bmp");
}
//-----------------------------------------------------------------------------
// Name: ~CParticleSystem()
// Desc:
//-----------------------------------------------------------------------------
CParticleSystem::~CParticleSystem()
{
InvalidateDeviceObjects();
while( m_pPlanes ) // Repeat till null...
{
Plane *pPlane = m_pPlanes; // Hold onto the first one
m_pPlanes = pPlane->m_pNext; // Move down to the next one
delete pPlane; // Delete the one we're holding
}
while( m_pActiveList )
{
Particle* pParticle = m_pActiveList;
m_pActiveList = pParticle->m_pNext;
delete pParticle;
}
m_pActiveList = NULL;
while( m_pFreeList )
{
Particle *pParticle = m_pFreeList;
m_pFreeList = pParticle->m_pNext;
delete pParticle;
}
m_pFreeList = NULL;
if( m_chTexFile != NULL )
{
delete [] m_chTexFile;
m_chTexFile = NULL;
}
if( m_ptexParticle != NULL )
m_ptexParticle->Release();
}
//-----------------------------------------------------------------------------
// Name: SetTexture()
// Desc:
//-----------------------------------------------------------------------------
void CParticleSystem::SetTexture( char *chTexFile )
{
// Deallocate the memory that was previously reserved for this string.
if( m_chTexFile != NULL )
{
delete [] m_chTexFile;
m_chTexFile = NULL;
}
// Dynamically allocate the correct amount of memory.
m_chTexFile = new char[strlen( chTexFile ) + 1];
// If the allocation succeeds, copy the initialization string.
if( m_chTexFile != NULL )
strcpy( m_chTexFile, chTexFile );
}
//-----------------------------------------------------------------------------
// Name: GetTextureObject()
// Desc:
//-----------------------------------------------------------------------------
LPDIRECT3DTEXTURE9 &CParticleSystem::GetTextureObject()
{
return m_ptexParticle;
}
//-----------------------------------------------------------------------------
// Name: SetCollisionPlane()
// Desc:
//-----------------------------------------------------------------------------
void CParticleSystem::SetCollisionPlane( D3DXVECTOR3 vPlaneNormal, D3DXVECTOR3 vPoint,
float fBounceFactor, int nCollisionResult )
{
Plane *pPlane = new Plane;
pPlane->m_vNormal = vPlaneNormal;
pPlane->m_vPoint = vPoint;
pPlane->m_fBounceFactor = fBounceFactor;
pPlane->m_nCollisionResult = nCollisionResult;
pPlane->m_pNext = m_pPlanes; // Attach the current list to it...
m_pPlanes = pPlane; // ... and make it the new head.
}
//-----------------------------------------------------------------------------
// Name: Init()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CParticleSystem::Init( LPDIRECT3DDEVICE9 pd3dDevice )
{
HRESULT hr;
// Initialize the particle system
if( FAILED( hr = RestoreDeviceObjects( pd3dDevice ) ) )
return hr;
// Get max point size
D3DCAPS9 d3dCaps;
pd3dDevice->GetDeviceCaps( &d3dCaps );
m_fMaxPointSize = d3dCaps.MaxPointSize;
// Check and see if we can change the size of point sprites
// in hardware by sending D3DFVF_PSIZE with the FVF.
if( d3dCaps.FVFCaps & D3DFVFCAPS_PSIZE )
m_bDeviceSupportsPSIZE = true;
else
m_bDeviceSupportsPSIZE = false;
// Load Texture Map for particles
if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, m_chTexFile, &m_ptexParticle ) ) )
return E_FAIL;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Update()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CParticleSystem::Update( FLOAT fElpasedTime )
{
Particle *pParticle;
Particle **ppParticle;
Plane *pPlane;
Plane **ppPlane;
D3DXVECTOR3 vOldPosition;
m_fCurrentTime += fElpasedTime; // Update our particle system timer...
ppParticle = &m_pActiveList; // Start at the head of the active list
while( *ppParticle )
{
pParticle = *ppParticle; // Set a pointer to the head
// Calculate new position
float fTimePassed = m_fCurrentTime - pParticle->m_fInitTime;
if( fTimePassed >= m_fLifeCycle )
{
// Time is up, put the particle back on the free list...
*ppParticle = pParticle->m_pNext;
pParticle->m_pNext = m_pFreeList;
m_pFreeList = pParticle;
--m_dwActiveCount;
}
else
{
// Update particle position and velocity
// Update velocity with respect to Gravity (Constant Acceleration)
pParticle->m_vCurVel += m_vGravity * fElpasedTime;
// Update velocity with respect to Wind (Acceleration based on
// difference of vectors)
if( m_bAirResistence == true )
pParticle->m_vCurVel += (m_vWind - pParticle->m_vCurVel) * fElpasedTime;
// Finally, update position with respect to velocity
vOldPosition = pParticle->m_vCurPos;
pParticle->m_vCurPos += pParticle->m_vCurVel * fElpasedTime;
//-----------------------------------------------------------------
// BEGIN Checking the particle against each plane that was set up
ppPlane = &m_pPlanes; // Set a pointer to the head
while( *ppPlane )
{
pPlane = *ppPlane;
int result = classifyPoint( &pParticle->m_vCurPos, pPlane );
if( result == CP_BACK /*|| result == CP_ONPLANE */ )
{
if( pPlane->m_nCollisionResult == CR_BOUNCE )
{
pParticle->m_vCurPos = vOldPosition;
//-----------------------------------------------------------------
//
// The new velocity vector of a particle that is bouncing off
// a plane is computed as follows:
//
// Vn = (N.V) * N
// Vt = V - Vn
// Vp = Vt - Kr * Vn
//
// Where:
//
// . = Dot product operation
// N = The normal of the plane from which we bounced
// V = Velocity vector prior to bounce
// Vn = Normal force
// Kr = The coefficient of restitution ( Ex. 1 = Full Bounce,
// 0 = Particle Sticks )
// Vp = New velocity vector after bounce
//
//-----------------------------------------------------------------
float Kr = pPlane->m_fBounceFactor;
D3DXVECTOR3 Vn = D3DXVec3Dot( &pPlane->m_vNormal,
&pParticle->m_vCurVel ) *
pPlane->m_vNormal;
D3DXVECTOR3 Vt = pParticle->m_vCurVel - Vn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -