|
楼主 |
发表于 2013-12-2 21:46:25
|
显示全部楼层
【实例4-2】火焰粒子类 下面是这个例题中完整的火焰粒子类的代码。 a 火焰粒子类头文件- //=============================================================================
- //Desc: CFirePartile.h
- //=============================================================================
- #pragma once
- #include "d3dx9.h"
- #include "Utility.h"
- #include <vector>
- #include <list>
- using namespace std;
- #define PARTICLENUM_FIRE 30
- //顶点结构
- struct CUSTOMVERTEX_PARTICLE
- {
- D3DXVECTOR3 Position; //位置
- D3DCOLOR color; //颜色
- };
- #define D3DFVF_CUSTOMEVERTEX_PARTICLE ( D3DFVF_XYZ | D3DFVF_DIFFUSE )
- struct CParticle
- {
- float m_fWidth; //宽度
- float m_fHeight; //高度
- bool m_bOwnDimension; //是否可控制粒子大小
- DWORD m_Color; //当前颜色(通常指顶点颜色)
- D3DXVECTOR3 m_vPosition; //位置
- D3DXVECTOR3 m_vDirection; //方向(有长度的方向,包含速度)
- float m_fTimeToLive; //剩余生命
- float m_fTotalTimeToLive; //生命周期
- float m_fRotation; //当前的旋转弧度
- float m_fSpeed; //速度
- };
- class CFirePartile
- {
- public:
- CFirePartile(void);
- ~CFirePartile(void);
- typedef std::list<CParticle*> ParticleActiveList; //定义存活粒子链表类型
- typedef std::list<CParticle*> ParticleFreeList; //定义空闲粒子链表类型
- ParticleActiveList m_ActiveParticles; //粒子池中已被使用的粒子对象
- ParticleFreeList m_FreeParticles; //粒子池中未被使用的粒子对象
- UINT m_uiMaxNumVertices;
- HRESULT Init( LPDIRECT3DDEVICE9 pDevice ); //初始化
- void Update( float fElapsedTime); //更新粒子
- void Render(); //设置合适的渲染状态,渲染粒子
- protected:
- LPDIRECT3DVERTEXBUFFER9 m_pVB; //顶点缓冲区
- LPDIRECT3DTEXTURE9 m_pTexture; //纹理对象
- LPDIRECT3DDEVICE9 m_pd3dDevice ; //设备
- float m_fSize; //粒子火焰大小
- bool m_bDeviceSupportsPSIZE; //是否支持点精灵改变大小
- //粒子的生命周期由“最小生命值”和“最大生命值”之间的随机值决定
- float m_fMinTTL; //最小生命值
- float m_fMaxTTL; //最大生命值
- //粒子的速率由“最小速度”和“最大速度”之间的随机值决定
- float m_fMinSpeed;
- float m_fMaxSpeed;
- //创建缓冲区
- void CreateBuffers();
- //创建粒子
- CParticle* CreateParticle();
- ParticleActiveList::iterator DeleteParticle( ParticleActiveList::iterator &i );
- //释放函数
- void FreeData();
- };
复制代码 a 火焰粒子类源文件- //=============================================================================
- //Desc: CFirePartile.cpp
- //=============================================================================
- #include ".\firepartile.h"
- CFirePartile::CFirePartile(void)
- {
- m_uiMaxNumVertices = 2048;
- m_fSize= 5.0f;
- m_fMinTTL = 10.0f;
- m_fMaxTTL = 20.0f;
- m_fMinSpeed = 6.f;
- m_fMaxSpeed = 8.5f;
- }
- CFirePartile::~CFirePartile(void)
- {
- FreeData();
- }
- void CFirePartile::FreeData()
- {
- //释放激活链表中可能存在的数据
- ParticleActiveList::iterator iACur = m_ActiveParticles.begin();
- ParticleActiveList::iterator iAEnd = m_ActiveParticles.end();
- for(; iACur!=iAEnd; iACur++)
- {
- SAFE_DELETE((*iACur));
- }
- //释放空闲链表中可能存在的数据
- ParticleFreeList::iterator iFCur = m_FreeParticles.begin();
- ParticleFreeList::iterator iFEnd = m_FreeParticles.end();
- for(; iFCur!=iFEnd; iFCur++)
- {
- SAFE_DELETE((*iFCur));
- }
- m_ActiveParticles.clear();
- m_FreeParticles.clear();
- //释放顶点、索引缓冲区
- SAFE_RELEASE( m_pVB );
- //释放纹理
- SAFE_RELEASE( m_pTexture );
- }
- HRESULT CFirePartile::Init( LPDIRECT3DDEVICE9 pDevice )
- {
- if(pDevice)
- m_pd3dDevice = pDevice;
- //创建粒子
- CreateBuffers();
- //获取最大值
- D3DCAPS9 d3dCaps;
- m_pd3dDevice->GetDeviceCaps(&d3dCaps);
- //检查是否支持点精灵粒子尺寸更改
- if (d3dCaps.FVFCaps & D3DFVFCAPS_PSIZE)
- {
- m_bDeviceSupportsPSIZE = true;
- }
- else
- {
- m_bDeviceSupportsPSIZE = false;
- return E_FAIL;
- }
- //创建火焰效果纹理
- if( FAILED( D3DXCreateTextureFromFile( m_pd3dDevice, "fire.tga", &m_pTexture )))
- return E_FAIL;
- //初始化粒子空闲链表
- for(int i=0; i<PARTICLENUM_FIRE; i++)
- {
- CParticle * pPar = new CParticle;
- m_FreeParticles.push_back( pPar );
- }
- return S_OK;
- }
- void CFirePartile::CreateBuffers()
- {
- //创建点精灵粒子顶点缓冲区
- if( FAILED( m_pd3dDevice->CreateVertexBuffer(
- m_uiMaxNumVertices * sizeof(CUSTOMVERTEX_PARTICLE),
- D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS,
- D3DFVF_CUSTOMEVERTEX_PARTICLE,
- D3DPOOL_DEFAULT,
- &m_pVB, NULL )))
- {
- MessageBox(NULL,"顶点缓冲创建失败!","错误",MB_OK);
- }
- }
- CParticle* CFirePartile::CreateParticle()
- {
- //检查空闲粒子链表是否为空
- if( m_FreeParticles.empty() )
- {
- return NULL;
- }
- //从空闲链表中取出头一个,放入存活链表
- CParticle *p = m_FreeParticles.front();
- //使用到std::list的splice方法,功能:将源链表中的指定数据插入目标链表的指定位置
- //并从源链表中删除该数据
- m_ActiveParticles.splice( m_ActiveParticles.end(), m_FreeParticles, m_FreeParticles.begin() );
- //给粒子一个随机速度,随机生命以及向上的方向
- p->m_fSpeed = GetRandomMinMax(m_fMinSpeed,m_fMaxSpeed);
- p->m_fTotalTimeToLive = GetRandomMinMax(m_fMinTTL,m_fMaxTTL);
- p->m_vDirection.x = 0.0f;
- p->m_vDirection.y = 1.0f;
- p->m_vDirection.z = 0.0f;
- return p;
- }
- void CFirePartile::Update( float fElapsedTime)
- {
- CUSTOMVERTEX_PARTICLE *pVertices;
- //如果当前的粒子生命已经大于生命周期,则被移到空闲粒子链表
- ParticleActiveList::iterator iCur = m_ActiveParticles.begin();
- ParticleActiveList::iterator iEnd = m_ActiveParticles.end();
- for( ; iCur != iEnd; )
- {
- if((*iCur)->m_fTotalTimeToLive < 0 )
- {
- iCur = DeleteParticle( iCur ); //删除到空闲链表,并返回下一个数据指针
- }
- else
- {
- (*iCur)->m_fTotalTimeToLive -= 1.0; //递减存活时间
- ++iCur; //指向下一个粒子
- }
- }
- //如果粒子数小于当前最大粒子数,则补充新的粒子
- if(m_ActiveParticles.size()<PARTICLENUM_FIRE)
- {
- CParticle * pPar = CreateParticle();
- pPar->m_vPosition.x = GetRandomMinMax(1,2);
- pPar->m_vPosition.y = GetRandomMinMax(0,0);
- pPar->m_vPosition.z = GetRandomMinMax(0,1);
- }
- //重新定向迭代器
- iCur = m_ActiveParticles.begin();
- iEnd = m_ActiveParticles.end();
- //更新缓冲区中粒子的位置属性
- if( FAILED( m_pVB->Lock(0, //给偏移加锁
- PARTICLENUM_FIRE * sizeof(CUSTOMVERTEX_PARTICLE), //给大小加锁
- (void**) &pVertices,
- D3DLOCK_DISCARD)))
- {
- return;
- }
- for( ; iCur != iEnd; iCur++)
- {
- //更新每个粒子的当前位置
- (*iCur)->m_vPosition += (fElapsedTime*(*iCur)->m_fSpeed)*(*iCur)->m_vDirection;
- pVertices->Position = (*iCur)->m_vPosition;
- pVertices->color =D3DCOLOR_XRGB(255,255,255);
- pVertices++;
- }
- m_pVB->Unlock();
- }
- //删除生命周期结束的粒子
- CFirePartile::ParticleActiveList::iterator CFirePartile::DeleteParticle( CFirePartile::ParticleActiveList::iterator &i )
- {
- //增加粒子到空闲链表
- m_FreeParticles.push_back( *i );
- //删除i位置的数据,传回下一个数据的位置
- return m_ActiveParticles.erase( i );
- }
- void CFirePartile::Render()
- {
- //设置渲染属性
- m_pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE ); //启用点精灵
- m_pd3dDevice->SetRenderState( D3DRS_POINTSCALEENABLE, TRUE ); //点大小的计算方式
- m_pd3dDevice->SetRenderState( D3DRS_POINTSIZE, FtoDW(m_fSize) ); //设置点的大小
- m_pd3dDevice->SetRenderState( D3DRS_POINTSIZE_MIN, FtoDW(1.0f) ); //点的最小值
- m_pd3dDevice->SetRenderState( D3DRS_POINTSCALE_A, FtoDW(0.0f) ); //3个系数
- m_pd3dDevice->SetRenderState( D3DRS_POINTSCALE_B, FtoDW(0.0f) );
- m_pd3dDevice->SetRenderState( D3DRS_POINTSCALE_C, FtoDW(1.0f) );
- //半透明效果
- m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
- m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
- //禁用照明效果
- m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE);
- m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
- //..........渲染开始.............
- if( m_ActiveParticles.size() )
- {
- m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX_PARTICLE) );
- m_pd3dDevice->SetFVF( D3DFVF_CUSTOMEVERTEX_PARTICLE );
- m_pd3dDevice->SetTexture(0,m_pTexture);
- m_pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, 0, m_ActiveParticles.size());
- }
- //..........渲染结束.............
- //恢复渲染状态...
- m_pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
- m_pd3dDevice->SetRenderState( D3DRS_POINTSCALEENABLE, FALSE );
- m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
- }
复制代码 a 项目主文件下面是调用CFirePartile类的主文件: - //=============================================================================
- //Desc:项目的主文件
- //=============================================================================
- #include <Windows.h>
- #include <mmsystem.h>
- #include <d3dx9.h>
- #include <strsafe.h>
- #include "FirePartile.h"
- //-----------------------------------------------------------------------------
- //全局变量
- //-----------------------------------------------------------------------------
- LPDIRECT3D9 g_pD3D = NULL; //D3D接口
- LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //D3D设备
- CFirePartile* g_pFirePartile =NULL;//火焰类指针
- //-----------------------------------------------------------------------------
- //Name: InitD3D()
- //Desc: 初始化D3D环境
- //-----------------------------------------------------------------------------
- HRESULT InitD3D( HWND hWnd )
- {
- //创建D3D 对象
- if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
- return E_FAIL;
- //初始化D3D 设备数据结构
- D3DPRESENT_PARAMETERS d3dpp;
- ZeroMemory( &d3dpp, sizeof(d3dpp) );
- d3dpp.Windowed = TRUE;
- d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
- //创建D3D设备
- if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
- D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- &d3dpp, &g_pd3dDevice ) ) )
- {
- return E_FAIL;
- }
- //生成火焰对象
- g_pFirePartile = new CFirePartile;
- //初始化
- g_pFirePartile->Init(g_pd3dDevice);
- //渲染状态关闭灯光
- g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
- return S_OK;
- }
- //-----------------------------------------------------------------------------
- //Name: Cleanup()
- //Desc: 释放所有申请的资源
- //-----------------------------------------------------------------------------
- VOID Cleanup()
- {
- SAFE_DELETE(g_pFirePartile);
- SAFE_RELEASE(g_pd3dDevice);
- SAFE_RELEASE(g_pD3D);
- }
- void Update()
- {
- static float fPreTime = static_cast<float>(timeGetTime());
- float fCurrentTime = static_cast<float>(timeGetTime());
- float fElapsedTime = (fCurrentTime - fPreTime)*0.001f;
- g_pFirePartile->Update(fElapsedTime);
- fPreTime = fCurrentTime;
- }
- //-----------------------------------------------------------------------------
- //Name: SetupMatrices()
- //Desc: 设置世界矩阵,视角变换矩阵和投影变换矩阵
- //-----------------------------------------------------------------------------
- VOID SetupMatrices()
- {
- D3DXVECTOR3 vEyePt( 0.0f,1.0f,-15.0f ); //摄像机位置
- D3DXVECTOR3 vLookatPt( 1.0f, 0.0f, 0.0f ); //观察点位置,前进后退,向左向右,向上向下
- D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); //摄像机正方向(本地坐标系)
- D3DXMATRIXA16 matView;
- D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
- g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ) ;
- D3DXMATRIXA16 matProj;
- //它说明物体如何随着距离而缩小
- //参数定义了屏幕纵横比第四和第五个参数定义最近和最远剪切平面
- D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
- g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
- }
- //-----------------------------------------------------------------------------
- //Name: Render()
- //Desc: 渲染
- //-----------------------------------------------------------------------------
- VOID Render()
- {
- //清屏
- g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
- Update();
- //开始渲染
- if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
- {
- //矩阵变换
- SetupMatrices();
- //渲染火焰
- g_pFirePartile->Render();
- //渲染结束
- g_pd3dDevice->EndScene();
- }
- //翻转缓冲
- g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
- }
- //-----------------------------------------------------------------------------
- //Name: MsgProc()
- //Desc: 消息处理函数
- //-----------------------------------------------------------------------------
- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- switch( msg )
- {
- case WM_DESTROY:
- Cleanup();
- PostQuitMessage( 0 );
- return 0;
- }
- return DefWindowProc( hWnd, msg, wParam, lParam );
- }
- //-----------------------------------------------------------------------------
- //Name: WinMain()
- //Desc: Win32主程序
- //-----------------------------------------------------------------------------
- INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
- {
- //注册窗口类
- WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
- GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
- "D3D Tutorial", NULL };
- RegisterClassEx( &wc );
- //创建窗口
- HWND hWnd = CreateWindow( "D3D Tutorial", "v5.0 粒子系统:火焰粒子效果",
- WS_OVERLAPPEDWINDOW, 100, 100, 400, 400,
- GetDesktopWindow(), NULL, wc.hInstance, NULL );
- //初始化Direct3D
- if( SUCCEEDED( InitD3D( hWnd ) ) )
- {
- //显示窗口
- ShowWindow( hWnd, SW_SHOWDEFAULT );
- UpdateWindow( hWnd );
- //消息循环
- MSG msg;
- ZeroMemory( &msg, sizeof(msg) );
- while( msg.message!=WM_QUIT )
- {
- if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
- {
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- else
- Render(); //渲染
- }
- }
- //注销窗口类
- UnregisterClass( "D3D Tutorial", wc.hInstance );
- return 0;
- }
复制代码 |
|