📄 fountain.h
字号:
#ifdef CGE_HEADER_H
#ifndef CGE_FOUNTAIN_H
#define CGE_FOUNTAIN_H
#include "PARTICLE.H"
namespace CGE
{
namespace PARTICLE_SYSTEM
{
enum
{
NONE = 0,
MOVING = 1,
FADING = 2,
};
typedef class FOUNTAIN_PARTICLE
{
public:
BOOL bSpray;
FLOAT fLifeTime;
FLOAT fMaxHeight;
D3DXVECTOR3 vPos0;
D3DXVECTOR3 vPos;
D3DXVECTOR3 vVel;
UINT nType;
FLOAT fAlpha;
FOUNTAIN_PARTICLE *pNext;
}*LPFOUNTAIN_PARTICLE;
typedef struct FOUNTAIN_SURFACE
{
D3DXVECTOR3 vNormal;
D3DXVECTOR3 vPoint;
FLOAT fBounceFactor;
INT LabelPoint(D3DXVECTOR3 vPt);
}*LPFOUNTAIN_SURFACE;
CGE_INLINE INT FOUNTAIN_SURFACE::LabelPoint(D3DXVECTOR3 vPt)
{
D3DXVECTOR3 vDirection = vPoint - vPt;
FLOAT fResult = D3DXVec3Dot( &vDirection, &vNormal );
if( fResult < -0.001f )
return PE_FRONT;
if( fResult > 0.001f )
return PE_BACK;
return PE_ONPLANE;
}
typedef class FOUNTAIN
{
public:
FOUNTAIN();
~FOUNTAIN();
LONG Behavior(FLOAT fElpasedTime);
VOID SetBarSurface(D3DXVECTOR3 vSurfaceNormal, D3DXVECTOR3 vPoint,
FLOAT fBounceFactor = 0.5f);
VOID DrawAliveList(LPDIRECT3DDEVICE8 device,LPDIRECT3DVERTEXBUFFER8 vb);
VOID SetColumnHeight(FLOAT fHeight);
VOID SetColor(FLOAT r,FLOAT g,FLOAT b,FLOAT a);
VOID SetPosition( FLOAT x,FLOAT y,FLOAT z );
VOID SetNumberToCreate( LONG NumberToCreate ) { m_NumberToCreate = NumberToCreate; }
VOID SetMaxNumber( LONG NumberLimit ) { m_MaxParticleNum = NumberLimit; }
VOID SetRadius( FLOAT fRadius ) { m_fSpreadRadius = fRadius; }
VOID SetMouth( FLOAT fRadius ) { m_fFountainRadius = fRadius; }
VOID SetInterValue( FLOAT fInterval ) { m_fInterval = fInterval; }
VOID SetSprayBulk( FLOAT fSpray ) { m_fSprayBulk = fSpray; }
protected:
LPFOUNTAIN_PARTICLE m_pParticleAliveList;
LPFOUNTAIN_PARTICLE m_pParticleDeathList;
LPFOUNTAIN_SURFACE m_pFountainSurface;
D3DXVECTOR3 m_vPosition;
D3DXCOLOR m_clrColor;
LONG m_ParticlesAlive;
LONG m_NumberToCreate;
LONG m_MaxParticleNum;
FLOAT m_fCurrentTime;
FLOAT m_fLastUpdateTime;
FLOAT m_fYAxiaVel;
FLOAT m_fLifeTime;
FLOAT m_fHeight;
FLOAT m_fInterval;
FLOAT m_fFountainRadius;
FLOAT m_fSpreadRadius;
FLOAT m_fSprayBulk;
}*LPFOUNTAIN;
CGE_INLINE VOID FOUNTAIN::SetPosition( FLOAT x,FLOAT y,FLOAT z)
{
m_vPosition = D3DXVECTOR3(x,y,z);
}
CGE_INLINE VOID FOUNTAIN::SetColor(FLOAT r,FLOAT g,FLOAT b,FLOAT a)
{
m_clrColor = D3DXCOLOR(r,g,b,a);
}
CGE_INLINE VOID FOUNTAIN::SetColumnHeight(FLOAT fHeight)
{
m_fLifeTime = sqrt((fHeight*2)/9.8f);
m_fYAxiaVel = 9.8f * m_fLifeTime;
m_fLifeTime = -m_fLifeTime;
m_fHeight = fHeight;
}
CGE_INLINE FOUNTAIN::FOUNTAIN()
{
m_pParticleAliveList = 0;
m_pParticleDeathList = 0;
m_ParticlesAlive = 0;
m_NumberToCreate = 0;
m_MaxParticleNum = 0;
m_pFountainSurface = 0;
m_fLifeTime = 0;
m_fInterval = 0.00f;
m_fSpreadRadius = 3.0f;
m_fSprayBulk = 0.5f;
m_fFountainRadius = 0.005f;
m_fLastUpdateTime = 0.00f;
m_fCurrentTime = 0.00f;
m_clrColor = D3DXCOLOR(1,1,1,1);
}
CGE_INLINE FOUNTAIN::~FOUNTAIN()
{
LPFOUNTAIN_PARTICLE pParticle = NULL;
while( m_pParticleAliveList )
{
pParticle = m_pParticleAliveList;
m_pParticleAliveList = pParticle->pNext;
delete pParticle;
}
while( m_pParticleDeathList )
{
pParticle = m_pParticleDeathList;
m_pParticleDeathList = pParticle->pNext;
delete pParticle;
}
SAFE_DELETE(m_pFountainSurface);
}
CGE_INLINE VOID
FOUNTAIN::SetBarSurface(D3DXVECTOR3 vSurfaceNormal, D3DXVECTOR3 vPoint,
FLOAT fBounceFactor)
{
SAFE_DELETE(m_pFountainSurface);
m_pFountainSurface = new FOUNTAIN_SURFACE;
m_pFountainSurface->vNormal = vSurfaceNormal;
m_pFountainSurface->vPoint = vPoint;
m_pFountainSurface->fBounceFactor = fBounceFactor;
}
CGE_INLINE VOID
FOUNTAIN::DrawAliveList(LPDIRECT3DDEVICE8 device,LPDIRECT3DVERTEXBUFFER8 vb)
{
register INT counter = 0;
static LONG BASE = CONST_DISCARD;
LONG NumberParToRender = 0;
LPFOUNTAIN_PARTICLE pParticle = m_pParticleAliveList;
LPCOLORVERTEX VERT;
if ( pParticle == NULL )
return;
device->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
device->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
device->SetRenderState( D3DRS_POINTSCALEENABLE, TRUE );
device->SetRenderState( D3DRS_POINTSIZE,FTODW(m_fSprayBulk));
device->SetRenderState( D3DRS_POINTSIZE_MIN, FTODW(0.00f) );
device->SetRenderState( D3DRS_POINTSCALE_A, FTODW(0.00f) );
device->SetRenderState( D3DRS_POINTSCALE_B, FTODW(0.00f) );
device->SetRenderState( D3DRS_POINTSCALE_C, FTODW(1.00f) );
device->SetVertexShader( COLORVERTEX::D3DFVF_COLORVERTEX );
device->SetStreamSource( 0, vb ,sizeof(COLORVERTEX));
BASE += CONST_FLUSH;
if(BASE >= CONST_DISCARD)
BASE = 0;
if(FAILED(vb->Lock(BASE * sizeof(COLORVERTEX), CONST_FLUSH * sizeof(COLORVERTEX),
(BYTE **) &VERT, BASE ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD)))
{
goto finally;
}
while( pParticle )
{
D3DXVECTOR3 vPos(pParticle->vPos);
D3DXVECTOR3 vVel(pParticle->vVel);
FLOAT fLength = D3DXVec3Length(&vVel);
UINT nStep = 0;
if( fLength < 1.00f ) nStep = 1;
else if( fLength < 16.00f ) nStep = 2;
else if( fLength < 32.00f ) nStep = 3;
else if( fLength < 64.00f ) nStep = 4;
else nStep = 5;
D3DXVec3Normalize(&vVel,&vVel);
vVel *= RANDOM_LERP_RANGE(1.0f,2.0f,100000);
for( counter = 0; counter < nStep; counter++ )
{
VERT->dvX = vPos.x;
VERT->dvY = vPos.y;
VERT->dvZ = vPos.z;
VERT->dcColor = m_clrColor;
VERT++;
if( ++NumberParToRender == CONST_FLUSH )
{
vb->Unlock();
if(FAILED(device->DrawPrimitive( D3DPT_POINTLIST, BASE, NumberParToRender)))
goto finally;
BASE += CONST_FLUSH;
if(BASE >= CONST_DISCARD)
BASE = 0;
if(FAILED(vb->Lock(BASE * sizeof(COLORVERTEX), CONST_FLUSH * sizeof(COLORVERTEX),
(BYTE **) &VERT, BASE ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD)))
{
goto finally;
}
NumberParToRender = 0;
}
vPos += vVel;
}
pParticle = pParticle->pNext;
}
vb->Unlock();
// 渲染
if( NumberParToRender )
{
if(FAILED(device->DrawPrimitive( D3DPT_POINTLIST, BASE, NumberParToRender )))
goto finally;
}
// 重置渲染状态
finally:
device->SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
device->SetRenderState( D3DRS_POINTSCALEENABLE, FALSE );
device->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
}
CGE_INLINE LONG
FOUNTAIN::Behavior(FLOAT fElpasedTime)
{
LPFOUNTAIN_PARTICLE pParticle,*ppParticle = NULL;
ppParticle = &m_pParticleAliveList;
D3DXVECTOR3 vPrePosition;
m_fCurrentTime += fElpasedTime;
while (*ppParticle)
{
pParticle = *ppParticle;
if ( (pParticle->nType == FADING) || (pParticle->fAlpha <= 0) && (pParticle->bSpray))
{
if ( pParticle->bSpray == FALSE )
{
for ( INT Number = 0; Number< 5 ;Number++)
{
LPFOUNTAIN_PARTICLE pSpray = NULL;
if( m_pParticleDeathList )
{
pSpray = m_pParticleDeathList;
m_pParticleDeathList = pSpray->pNext;
}
else
{
if( NULL == ( pSpray = new FOUNTAIN_PARTICLE ) )
return NULL;
}
if ( pSpray != NULL )
{
pSpray->nType = MOVING;
pSpray->fAlpha = 1;
pSpray->bSpray = TRUE;
pSpray->fLifeTime = - (pParticle->vVel.y / 9.8f);
pSpray->fMaxHeight = 9.8f * ( pSpray->fLifeTime * pSpray->fLifeTime ) / 2;
pSpray->vPos0 = pParticle->vPos;
pSpray->vPos = pSpray->vPos0;
pSpray->pNext = pParticle->pNext;
pParticle->pNext = pSpray;
}
}
}
*ppParticle = pParticle->pNext;
pParticle->pNext = m_pParticleDeathList;
m_pParticleDeathList = pParticle;
m_ParticlesAlive--;
}
else
{
if (pParticle->nType == MOVING)
{
vPrePosition = pParticle->vPos;
pParticle->vPos.x += pParticle->vVel.x*fElpasedTime;
pParticle->vPos.z += pParticle->vVel.z*fElpasedTime;
pParticle->vPos.y = pParticle->vPos0.y - ( 9.8f * (pParticle->fLifeTime*pParticle->fLifeTime))/2+pParticle->fMaxHeight; /* H = gt^2/2 (height of current particle) */
pParticle->vVel.y -= 9.8f * fElpasedTime;
pParticle->fLifeTime += fElpasedTime;
UINT Result = m_pFountainSurface->LabelPoint( pParticle->vPos );
if ( Result == PE_BACK || Result == PE_ONPLANE )
{
pParticle->nType = FADING;
FLOAT fBounce = m_pFountainSurface->fBounceFactor;
D3DXVECTOR3 Vn = D3DXVec3Dot( &m_pFountainSurface->vNormal, &pParticle->vVel ) * m_pFountainSurface->vNormal;
D3DXVECTOR3 Vt = pParticle->vVel - Vn;
D3DXVECTOR3 Vp = Vt - fBounce * Vn;
pParticle->vVel = Vp;
pParticle->vPos = vPrePosition;
}
}
else
{
pParticle->fAlpha -= 0.1f;
}
ppParticle = &pParticle->pNext;
}
}
if ( m_fCurrentTime - m_fLastUpdateTime >= m_fInterval )
{
m_fLastUpdateTime = m_fCurrentTime;
for (INT Counter=0; Counter<m_NumberToCreate; Counter++)
{
if ( m_ParticlesAlive >= m_MaxParticleNum ) break;
if( m_pParticleDeathList )
{
pParticle = m_pParticleDeathList;
m_pParticleDeathList = pParticle->pNext;
}
else
{
if( NULL == ( pParticle = new FOUNTAIN_PARTICLE ) )
return NULL;
}
if ( pParticle != NULL )
{
FLOAT fRadius = RANDOM_LERP_RANGE(-m_fSpreadRadius,m_fSpreadRadius,100000000);
FLOAT fDir = RANDOM_RANGE(0,6.28);
FLOAT fFountainRadius = RANDOM_LERP_RANGE(-m_fFountainRadius,m_fFountainRadius,100000000);
D3DXVECTOR3 vRandPos = D3DXVECTOR3( cos(fDir) * fFountainRadius,0,sin(fDir) * fFountainRadius);
pParticle->bSpray = FALSE;
pParticle->nType = MOVING;
pParticle->fAlpha = 1;
pParticle->fLifeTime = m_fLifeTime;
pParticle->fMaxHeight = m_fHeight;
pParticle->vPos0 = m_vPosition;
pParticle->vPos = pParticle->vPos0 + vRandPos;
pParticle->vVel.x = cos(fDir) * fRadius * 0.5f;
pParticle->vVel.z = sin(fDir) * fRadius * 0.5f;
pParticle->vVel.y = m_fYAxiaVel;
pParticle->pNext = m_pParticleAliveList;
m_pParticleAliveList = pParticle;
m_ParticlesAlive++;
}
}
}
return m_ParticlesAlive;
}
}
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -