client/EffectLib/ParticleSystemInstance.cpp

520 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "../eterBase/Random.h"
#include "../eterLib/StateManager.h"
#include "ParticleSystemData.h"
#include "ParticleSystemInstance.h"
#include "ParticleInstance.h"
CDynamicPool<CParticleSystemInstance> CParticleSystemInstance::ms_kPool;
using namespace NEffectUpdateDecorator;
void CParticleSystemInstance::DestroySystem()
{
ms_kPool.Destroy();
CParticleInstance::DestroySystem();
//CRayParticleInstance::DestroySystem();
}
CParticleSystemInstance* CParticleSystemInstance::New()
{
return ms_kPool.Alloc();
}
void CParticleSystemInstance::Delete(CParticleSystemInstance* pkPSInst)
{
pkPSInst->Destroy();
ms_kPool.Free(pkPSInst);
}
DWORD CParticleSystemInstance::GetEmissionCount()
{
return m_dwCurrentEmissionCount;
}
void CParticleSystemInstance::CreateParticles(float fElapsedTime)
{
float fEmissionCount;
m_pEmitterProperty->GetEmissionCountPerSecond(m_fLocalTime, &fEmissionCount);
float fCreatingValue = fEmissionCount * (fElapsedTime / 1.0f) + m_fEmissionResidue;
int iCreatingCount = int(fCreatingValue);
m_fEmissionResidue = fCreatingValue - iCreatingCount;
int icurEmissionCount = GetEmissionCount();
int iMaxEmissionCount = int(m_pEmitterProperty->GetMaxEmissionCount());
int iNextEmissionCount = int(icurEmissionCount + iCreatingCount);
iCreatingCount -= max(0, iNextEmissionCount - iMaxEmissionCount);
float fLifeTime = 0.0f;
float fEmittingSize = 0.0f;
D3DXVECTOR3 _v3TimePosition;
D3DXVECTOR3 _v3Velocity;
float fVelocity = 0.0f;
D3DXVECTOR2 v2HalfSize;
float fLieRotation = 0;
if (iCreatingCount)
{
m_pEmitterProperty->GetParticleLifeTime(m_fLocalTime, &fLifeTime);
if (fLifeTime==0.0f)
{
return;
}
m_pEmitterProperty->GetEmittingSize(m_fLocalTime, &fEmittingSize);
m_pData->GetPosition(m_fLocalTime, _v3TimePosition);
m_pEmitterProperty->GetEmittingDirectionX(m_fLocalTime, &_v3Velocity.x);
m_pEmitterProperty->GetEmittingDirectionY(m_fLocalTime, &_v3Velocity.y);
m_pEmitterProperty->GetEmittingDirectionZ(m_fLocalTime, &_v3Velocity.z);
m_pEmitterProperty->GetEmittingVelocity(m_fLocalTime, &fVelocity);
m_pEmitterProperty->GetParticleSizeX(m_fLocalTime, &v2HalfSize.x);
m_pEmitterProperty->GetParticleSizeY(m_fLocalTime, &v2HalfSize.y);
if (BILLBOARD_TYPE_LIE == m_pParticleProperty->m_byBillboardType && mc_pmatLocal)
{
float fsx = mc_pmatLocal->_32;
float fcx = sqrtf(1.0f - fsx * fsx);
if (fcx >= 0.00001f)
fLieRotation = D3DXToDegree(atan2f(-mc_pmatLocal->_12, mc_pmatLocal->_22));
}
}
CParticleInstance * pFirstInstance = 0;
for (int i = 0; i < iCreatingCount; ++i)
{
CParticleInstance * pInstance;
pInstance = CParticleInstance::New();
pInstance->m_pParticleProperty = m_pParticleProperty;
pInstance->m_pEmitterProperty = m_pEmitterProperty;
// LifeTime
pInstance->m_fLifeTime = fLifeTime;
pInstance->m_fLastLifeTime = fLifeTime;
// Position
switch (m_pEmitterProperty->GetEmitterShape())
{
case CEmitterProperty::EMITTER_SHAPE_POINT:
pInstance->m_v3Position.x = 0.0f;
pInstance->m_v3Position.y = 0.0f;
pInstance->m_v3Position.z = 0.0f;
break;
case CEmitterProperty::EMITTER_SHAPE_ELLIPSE:
pInstance->m_v3Position.x = frandom(-500.0f, 500.0f);
pInstance->m_v3Position.y = frandom(-500.0f, 500.0f);
pInstance->m_v3Position.z = 0.0f;
D3DXVec3Normalize(&pInstance->m_v3Position, &pInstance->m_v3Position);
if (m_pEmitterProperty->isEmitFromEdge())
{
pInstance->m_v3Position *= (m_pEmitterProperty->m_fEmittingRadius + fEmittingSize);
}
else
{
pInstance->m_v3Position *= (frandom(0.0f, m_pEmitterProperty->m_fEmittingRadius) + fEmittingSize);
}
break;
case CEmitterProperty::EMITTER_SHAPE_SQUARE:
pInstance->m_v3Position.x = (frandom(-m_pEmitterProperty->m_v3EmittingSize.x/2.0f, m_pEmitterProperty->m_v3EmittingSize.x/2.0f) + fEmittingSize);
pInstance->m_v3Position.y = (frandom(-m_pEmitterProperty->m_v3EmittingSize.y/2.0f, m_pEmitterProperty->m_v3EmittingSize.y/2.0f) + fEmittingSize);
pInstance->m_v3Position.z = (frandom(-m_pEmitterProperty->m_v3EmittingSize.z/2.0f, m_pEmitterProperty->m_v3EmittingSize.z/2.0f) + fEmittingSize);
break;
case CEmitterProperty::EMITTER_SHAPE_SPHERE:
pInstance->m_v3Position.x = frandom(-500.0f, 500.0f);
pInstance->m_v3Position.y = frandom(-500.0f, 500.0f);
pInstance->m_v3Position.z = frandom(-500.0f, 500.0f);
D3DXVec3Normalize(&pInstance->m_v3Position, &pInstance->m_v3Position);
if (m_pEmitterProperty->isEmitFromEdge())
{
pInstance->m_v3Position *= (m_pEmitterProperty->m_fEmittingRadius + fEmittingSize);
}
else
{
pInstance->m_v3Position *= (frandom(0.0f, m_pEmitterProperty->m_fEmittingRadius) + fEmittingSize);
}
break;
}
// Position
D3DXVECTOR3 v3TimePosition=_v3TimePosition;
pInstance->m_v3Position += v3TimePosition;
if (mc_pmatLocal && !m_pParticleProperty->m_bAttachFlag)
{
D3DXVec3TransformCoord(&pInstance->m_v3Position,&pInstance->m_v3Position,mc_pmatLocal);
D3DXVec3TransformCoord(&v3TimePosition, &v3TimePosition, mc_pmatLocal);
}
pInstance->m_v3StartPosition = v3TimePosition;
// NOTE : Update<74><65> ȣ<><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʰ<EFBFBD> Rendering <20>DZ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> length<74><68> 0<><30> <20>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD>.
// Velocity<74><79> <20><><EFBFBD><EFBFBD> <20><> <20>׸<EFBFBD>ŭ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʱ<EFBFBD>ȭ <20><><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD> <20>ٲ<EFBFBD><D9B2><EFBFBD> - [levites]
//pInstance->m_v3LastPosition = pInstance->m_v3Position;
// Direction & Velocity
pInstance->m_v3Velocity.x = 0.0f;
pInstance->m_v3Velocity.y = 0.0f;
pInstance->m_v3Velocity.z = 0.0f;
if (CEmitterProperty::EMITTER_ADVANCED_TYPE_INNER == m_pEmitterProperty->GetEmitterAdvancedType())
{
D3DXVec3Normalize(&pInstance->m_v3Velocity, &(pInstance->m_v3Position-v3TimePosition));
pInstance->m_v3Velocity *= -100.0f;
}
else if (CEmitterProperty::EMITTER_ADVANCED_TYPE_OUTER == m_pEmitterProperty->GetEmitterAdvancedType())
{
if (m_pEmitterProperty->GetEmitterShape() == CEmitterProperty::EMITTER_SHAPE_POINT)
{
pInstance->m_v3Velocity.x = frandom(-100.0f, 100.0f);
pInstance->m_v3Velocity.y = frandom(-100.0f, 100.0f);
pInstance->m_v3Velocity.z = frandom(-100.0f, 100.0f);
}
else
{
D3DXVec3Normalize(&pInstance->m_v3Velocity, &(pInstance->m_v3Position-v3TimePosition));
pInstance->m_v3Velocity *= 100.0f;
}
}
D3DXVECTOR3 v3Velocity = _v3Velocity;
if (mc_pmatLocal && !m_pParticleProperty->m_bAttachFlag)
{
D3DXVec3TransformNormal(&v3Velocity, &v3Velocity, mc_pmatLocal);
}
pInstance->m_v3Velocity += v3Velocity;
if (m_pEmitterProperty->m_v3EmittingDirection.x > 0.0f)
pInstance->m_v3Velocity.x += frandom(-m_pEmitterProperty->m_v3EmittingDirection.x/2.0f, m_pEmitterProperty->m_v3EmittingDirection.x/2.0f) * 1000.0f;
if (m_pEmitterProperty->m_v3EmittingDirection.y > 0.0f)
pInstance->m_v3Velocity.y += frandom(-m_pEmitterProperty->m_v3EmittingDirection.y/2.0f, m_pEmitterProperty->m_v3EmittingDirection.y/2.0f) * 1000.0f;
if (m_pEmitterProperty->m_v3EmittingDirection.z > 0.0f)
pInstance->m_v3Velocity.z += frandom(-m_pEmitterProperty->m_v3EmittingDirection.z/2.0f, m_pEmitterProperty->m_v3EmittingDirection.z/2.0f) * 1000.0f;
pInstance->m_v3Velocity *= fVelocity;
// Size
pInstance->m_v2HalfSize = v2HalfSize;
// Rotation
pInstance->m_fRotation = m_pParticleProperty->m_wRotationRandomStartingBegin;
pInstance->m_fRotation = frandom(m_pParticleProperty->m_wRotationRandomStartingBegin,m_pParticleProperty->m_wRotationRandomStartingEnd);
// Rotation - Lie <20><> <20><><EFBFBD><EFBFBD> LocalMatrix <20><> Rotation <20><><EFBFBD><EFBFBD> Random <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
// <20>Ź<EFBFBD> <20><> <20>ʿ<EFBFBD><CABF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȭ<EFBFBD><C8AD> <20>ʿ<EFBFBD>. - [levites]
if (BILLBOARD_TYPE_LIE == m_pParticleProperty->m_byBillboardType && mc_pmatLocal)
{
pInstance->m_fRotation += fLieRotation;
}
// Texture Animation
pInstance->m_byFrameIndex = 0;
pInstance->m_byTextureAnimationType = m_pParticleProperty->GetTextureAnimationType();
if (m_pParticleProperty->GetTextureAnimationFrameCount() > 1)
{
if (CParticleProperty::TEXTURE_ANIMATION_TYPE_RANDOM_DIRECTION == m_pParticleProperty->GetTextureAnimationType())
{
if (random() & 1)
{
pInstance->m_byFrameIndex = 0;
pInstance->m_byTextureAnimationType = CParticleProperty::TEXTURE_ANIMATION_TYPE_CW;
}
else
{
pInstance->m_byFrameIndex = m_pParticleProperty->GetTextureAnimationFrameCount() - 1;
pInstance->m_byTextureAnimationType = CParticleProperty::TEXTURE_ANIMATION_TYPE_CCW;
}
}
if (m_pParticleProperty->m_bTexAniRandomStartFrameFlag)
{
pInstance->m_byFrameIndex = random_range(0,m_pParticleProperty->GetTextureAnimationFrameCount()-1);
}
}
// Simple Update
{
pInstance->m_v3LastPosition = pInstance->m_v3Position - (pInstance->m_v3Velocity * fElapsedTime);
pInstance->m_v2Scale.x = m_pParticleProperty->m_TimeEventScaleX.front().m_Value;
pInstance->m_v2Scale.y= m_pParticleProperty->m_TimeEventScaleY.front().m_Value;
//pInstance->m_v2Scale = m_pParticleProperty->m_TimeEventScaleXY.front().m_Value;
#ifdef WORLD_EDITOR
pInstance->m_Color.r = m_pParticleProperty->m_TimeEventColorRed.front().m_Value;
pInstance->m_Color.g = m_pParticleProperty->m_TimeEventColorGreen.front().m_Value;
pInstance->m_Color.b = m_pParticleProperty->m_TimeEventColorBlue.front().m_Value;
pInstance->m_Color.a = m_pParticleProperty->m_TimeEventAlpha.front().m_Value;
#else
pInstance->m_dcColor = m_pParticleProperty->m_TimeEventColor.front().m_Value;
#endif
}
if (!pFirstInstance)
{
m_pData->BuildDecorator(pInstance);
pFirstInstance = pInstance;
}
else
{
pInstance->m_pDecorator = pFirstInstance->m_pDecorator->Clone(pFirstInstance,pInstance);
}
m_ParticleInstanceListVector[pInstance->m_byFrameIndex].push_back(pInstance);
m_dwCurrentEmissionCount++;
}
}
bool CParticleSystemInstance::OnUpdate(float fElapsedTime)
{
bool bMakeParticle = true;
/////
if (m_fLocalTime >= m_pEmitterProperty->GetCycleLength())
{
if (m_pEmitterProperty->isCycleLoop() && --m_iLoopCount!=0)
{
if (m_iLoopCount<0)
m_iLoopCount = 0;
m_fLocalTime = m_fLocalTime - m_pEmitterProperty->GetCycleLength();
}
else
{
bMakeParticle = false;
m_iLoopCount=1;
if (GetEmissionCount()==0)
return false;
}
}
/////
int dwFrameIndex;
int dwFrameCount = m_pParticleProperty->GetTextureAnimationFrameCount();
float fAngularVelocity;
m_pEmitterProperty->GetEmittingAngularVelocity(m_fLocalTime,&fAngularVelocity);
if (fAngularVelocity && !m_pParticleProperty->m_bAttachFlag)
{
D3DXVec3TransformNormal(&m_pParticleProperty->m_v3ZAxis,&D3DXVECTOR3(0.0f,0.0f,1.0f),mc_pmatLocal);
}
for (dwFrameIndex = 0; dwFrameIndex < dwFrameCount; dwFrameIndex++)
{
TParticleInstanceList::iterator itor = m_ParticleInstanceListVector[dwFrameIndex].begin();
for (; itor != m_ParticleInstanceListVector[dwFrameIndex].end();)
{
CParticleInstance * pInstance = *itor;
if (!pInstance->Update(fElapsedTime,fAngularVelocity))
{
pInstance->DeleteThis();
itor = m_ParticleInstanceListVector[dwFrameIndex].erase(itor);
m_dwCurrentEmissionCount--;
}
else
{
if (pInstance->m_byFrameIndex != dwFrameIndex)
{
m_ParticleInstanceListVector[dwFrameCount+pInstance->m_byFrameIndex].push_back(*itor);
itor = m_ParticleInstanceListVector[dwFrameIndex].erase(itor);
}
else
++itor;
}
}
}
if (isActive() && bMakeParticle)
CreateParticles(fElapsedTime);
for (dwFrameIndex = 0; dwFrameIndex < dwFrameCount; ++dwFrameIndex)
{
m_ParticleInstanceListVector[dwFrameIndex].splice(m_ParticleInstanceListVector[dwFrameIndex].end(),m_ParticleInstanceListVector[dwFrameIndex+dwFrameCount]);
m_ParticleInstanceListVector[dwFrameIndex+dwFrameCount].clear();
}
return true;
}
namespace NParticleRenderer
{
struct TwoSideRenderer
{
const D3DXMATRIX * pmat;
TwoSideRenderer(const D3DXMATRIX * pmat=NULL)
: pmat(pmat)
{
}
inline void operator () (CParticleInstance * pInstance)
{
pInstance->Transform(pmat,D3DXToRadian(-30.0f));
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
pInstance->Transform(pmat,D3DXToRadian(+30.0f));
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
}
};
struct ThreeSideRenderer
{
const D3DXMATRIX * pmat;
ThreeSideRenderer(const D3DXMATRIX * pmat=NULL)
: pmat(pmat)
{
}
inline void operator () (CParticleInstance * pInstance)
{
pInstance->Transform(pmat);
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
pInstance->Transform(pmat,D3DXToRadian(-60.0f));
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
pInstance->Transform(pmat,D3DXToRadian(+60.0f));
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
}
};
struct NormalRenderer
{
inline void operator () (CParticleInstance * pInstance)
{
pInstance->Transform();
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
}
};
struct AttachRenderer
{
const D3DXMATRIX* pmat;
AttachRenderer(const D3DXMATRIX * pmat)
: pmat(pmat)
{
}
inline void operator () (CParticleInstance * pInstance)
{
pInstance->Transform(pmat);
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
}
};
}
void CParticleSystemInstance::OnRender()
{
CScreen::Identity();
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, m_pParticleProperty->m_bySrcBlendType);
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, m_pParticleProperty->m_byDestBlendType);
STATEMANAGER.SetTextureStageState(0,D3DTSS_COLOROP,m_pParticleProperty->m_byColorOperationType);
if (m_pParticleProperty->m_byBillboardType < BILLBOARD_TYPE_2FACE)
{
if (!m_pParticleProperty->m_bAttachFlag)
{
ForEachParticleRendering(NParticleRenderer::NormalRenderer());
}
else
{
ForEachParticleRendering(NParticleRenderer::AttachRenderer(mc_pmatLocal));
}
}
else if (m_pParticleProperty->m_byBillboardType == BILLBOARD_TYPE_2FACE)
{
if (!m_pParticleProperty->m_bAttachFlag)
{
ForEachParticleRendering(NParticleRenderer::TwoSideRenderer());
}
else
{
ForEachParticleRendering(NParticleRenderer::TwoSideRenderer(mc_pmatLocal));
}
}
else if (m_pParticleProperty->m_byBillboardType == BILLBOARD_TYPE_3FACE)
{
if (!m_pParticleProperty->m_bAttachFlag)
{
ForEachParticleRendering(NParticleRenderer::ThreeSideRenderer());
}
else
{
ForEachParticleRendering(NParticleRenderer::ThreeSideRenderer(mc_pmatLocal));
}
}
}
void CParticleSystemInstance::OnSetDataPointer(CEffectElementBase * pElement)
{
m_pData = (CParticleSystemData *)pElement;
m_dwCurrentEmissionCount = 0;
m_pParticleProperty = m_pData->GetParticlePropertyPointer();
m_pEmitterProperty = m_pData->GetEmitterPropertyPointer();
m_iLoopCount = m_pEmitterProperty->GetLoopCount();
m_ParticleInstanceListVector.resize(m_pParticleProperty->GetTextureAnimationFrameCount()*2+2);
/////
assert(m_kVct_pkImgInst.empty());
m_kVct_pkImgInst.reserve(m_pParticleProperty->m_ImageVector.size());
for (DWORD i = 0; i < m_pParticleProperty->m_ImageVector.size(); ++i)
{
CGraphicImage * pImage = m_pParticleProperty->m_ImageVector[i];
CGraphicImageInstance* pkImgInstNew = CGraphicImageInstance::New();
pkImgInstNew->SetImagePointer(pImage);
m_kVct_pkImgInst.push_back(pkImgInstNew);
}
}
void CParticleSystemInstance::OnInitialize()
{
m_dwCurrentEmissionCount = 0;
m_iLoopCount = 0;
m_fEmissionResidue = 0.0f;
}
void CParticleSystemInstance::OnDestroy()
{
// 2004. 3. 1. myevan. <20><>ƼŬ <20><><EFBFBD><EFBFBD> <20><>ƾ
TParticleInstanceListVector::iterator i;
for(i = m_ParticleInstanceListVector.begin(); i!=m_ParticleInstanceListVector.end(); ++i)
{
TParticleInstanceList& rkLst_kParticleInst=*i;
TParticleInstanceList::iterator j;
for(j = rkLst_kParticleInst.begin(); j!=rkLst_kParticleInst.end(); ++j)
{
CParticleInstance* pkParticleInst=*j;
pkParticleInst->DeleteThis();
}
rkLst_kParticleInst.clear();
}
m_ParticleInstanceListVector.clear();
std::for_each(m_kVct_pkImgInst.begin(), m_kVct_pkImgInst.end(), CGraphicImageInstance::Delete);
m_kVct_pkImgInst.clear();
}
CParticleSystemInstance::CParticleSystemInstance()
{
Initialize();
}
CParticleSystemInstance::~CParticleSystemInstance()
{
assert(m_ParticleInstanceListVector.empty());
assert(m_kVct_pkImgInst.empty());
}