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

📄 fountain.h

📁 VC++ DEMO, used for the beginners and the amour
💻 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 + -