463 lines
No EOL
14 KiB
C++
463 lines
No EOL
14 KiB
C++
#include "StdAfx.h"
|
|
#include "EtBillboardEffectData.h"
|
|
|
|
EtBlendOP g_nBlendOPList[] =
|
|
{
|
|
BLENDOP_ADD,
|
|
BLENDOP_SUBTRACT,
|
|
BLENDOP_REVSUBTRACT,
|
|
BLENDOP_MIN,
|
|
BLENDOP_MAX,
|
|
};
|
|
|
|
EtBlendMode g_nBlendModeList[] =
|
|
{
|
|
BLEND_ZERO,
|
|
BLEND_ONE,
|
|
BLEND_SRCCOLOR,
|
|
BLEND_INVSRCCOLOR,
|
|
BLEND_SRCALPHA,
|
|
BLEND_INVSRCALPHA,
|
|
BLEND_DESTALPHA,
|
|
BLEND_INVDESTALPHA,
|
|
BLEND_DESTCOLOR,
|
|
BLEND_INVDESTCOLOR,
|
|
BLEND_SRCALPHASAT,
|
|
};
|
|
|
|
CEtBillboardEffectData::CEtBillboardEffectData()
|
|
{
|
|
m_nTotalEffectCount = 0;
|
|
m_nMaxBillboardEffectLife = 0;
|
|
m_bAlphaFog = false;
|
|
}
|
|
|
|
CEtBillboardEffectData::~CEtBillboardEffectData()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void CEtBillboardEffectData::Clear()
|
|
{
|
|
SAFE_RELEASE_SPTR( m_hMaterial );
|
|
SAFE_DELETE_PVEC( m_vecEmitter );
|
|
SAFE_DELETE_PVEC( m_InstancePool );
|
|
}
|
|
|
|
int CEtBillboardEffectData::LoadResource( CStream *pStream )
|
|
{
|
|
SBillboardEffectHeader Header;
|
|
|
|
Clear();
|
|
m_hMaterial = ::LoadResource( "Particle.fx", RT_SHADER );
|
|
|
|
pStream->Read( &Header, sizeof(SBillboardEffectHeader) );
|
|
assert( strstr(Header.szHeader, "Eternity Engine Particle File") );
|
|
|
|
if( strstr(Header.szHeader, BILLBOARD_EFFECT_HEADER) == NULL ) return ETERR_FILENOTFOUND;
|
|
|
|
pStream->Seek( BILLBOARD_EFFECT_HEADER_RESERVED, SEEK_CUR );
|
|
m_vecEmitter.resize( Header.nEmitterCount );
|
|
for( int i = 0; i < Header.nEmitterCount; i++ )
|
|
{
|
|
m_vecEmitter[ i ] = new CEtBillboardEffectEmitter();
|
|
m_vecEmitter[ i ]->LoadEmitter(pStream, Header.nVersion);
|
|
}
|
|
CreateBillboardEffectBuffer();
|
|
|
|
return ET_OK;
|
|
}
|
|
|
|
int CEtBillboardEffectData::Save( const char *pFileName )
|
|
{
|
|
CFileStream Stream( pFileName, CFileStream::OPEN_WRITE );
|
|
|
|
if( !Stream.IsValid() )
|
|
{
|
|
return ETERR_FILECREATEFAIL;
|
|
}
|
|
|
|
int i;
|
|
SBillboardEffectHeader Header;
|
|
char cDummy[ BILLBOARD_EFFECT_HEADER_RESERVED ];
|
|
|
|
memset( &Header, 0, sizeof( SBillboardEffectHeader ) );
|
|
Header.nVersion = EMITTER_VER;
|
|
Header.nEmitterCount = ( int )m_vecEmitter.size();
|
|
//strcpy( Header.szHeader, BILLBOARD_EFFECT_HEADER );
|
|
strncpy_s(Header.szHeader, _countof(Header.szHeader), BILLBOARD_EFFECT_HEADER, _TRUNCATE);
|
|
Stream.Write( &Header, sizeof( SBillboardEffectHeader ) );
|
|
memset( cDummy, 0, BILLBOARD_EFFECT_HEADER_RESERVED );
|
|
Stream.Write( cDummy, BILLBOARD_EFFECT_HEADER_RESERVED );
|
|
|
|
for( i = 0; i < Header.nEmitterCount; i++ )
|
|
{
|
|
m_vecEmitter[ i ]->SaveEmitter( &Stream );
|
|
}
|
|
|
|
return ET_OK;
|
|
}
|
|
|
|
void CEtBillboardEffectData::CreateBillboardEffectBuffer()
|
|
{
|
|
int i;
|
|
|
|
CheckLifeTime();
|
|
#ifdef PRE_FIX_MATERIAL_DUMP
|
|
if( !m_hMaterial ) return;
|
|
#endif
|
|
|
|
for( i = 0; i < ( int )m_vecEmitter.size(); i++ )
|
|
{
|
|
m_vecEmitter[ i ]->CreateEmitterBuffer();
|
|
m_vecEmitter[ i ]->SetEffectParam( m_hMaterial );
|
|
}
|
|
}
|
|
|
|
void CEtBillboardEffectData::CheckLifeTime()
|
|
{
|
|
int i;
|
|
m_nMaxBillboardEffectLife = 0;
|
|
m_nTotalEffectCount = 0;
|
|
for( i = 0; i < ( int )m_vecEmitter.size(); i++ )
|
|
{
|
|
m_nTotalEffectCount += m_vecEmitter[ i ]->GetGenerateCount();
|
|
if( m_nMaxBillboardEffectLife < m_vecEmitter[ i ]->GetLifeDuration() )
|
|
{
|
|
m_nMaxBillboardEffectLife = m_vecEmitter[ i ]->GetLifeDuration();
|
|
}
|
|
}
|
|
|
|
for( i = 0; i < ( int )m_vecEmitter.size(); i++ )
|
|
{
|
|
m_vecEmitter[ i ]->SetMaxEffectLifeTime( m_nMaxBillboardEffectLife );
|
|
}
|
|
}
|
|
|
|
int CEtBillboardEffectData::AddEmitter( SEmitter *pEmitterInfo )
|
|
{
|
|
CEtBillboardEffectEmitter *pEmitter;
|
|
|
|
pEmitter = new CEtBillboardEffectEmitter();
|
|
m_vecEmitter.push_back( pEmitter );
|
|
if( pEmitterInfo )
|
|
{
|
|
pEmitter->SetEmitterInfo( pEmitterInfo );
|
|
pEmitter->LoadTexture( pEmitterInfo->szTextureName );
|
|
}
|
|
CheckLifeTime();
|
|
CreateBillboardEffectBuffer();
|
|
|
|
return ( int )m_vecEmitter.size() - 1;
|
|
}
|
|
|
|
int CEtBillboardEffectData::CopyEmitter( int nIndex )
|
|
{
|
|
AddEmitter();
|
|
( *m_vecEmitter.end() )->SetEmitterInfo( m_vecEmitter[ nIndex ]->GetEmitterInfo() );
|
|
CreateBillboardEffectBuffer();
|
|
|
|
return ( int )m_vecEmitter.size() - 1;
|
|
}
|
|
|
|
void CEtBillboardEffectData::DeleteEmitter( int nIndex )
|
|
{
|
|
if( nIndex < ( int )m_vecEmitter.size() )
|
|
{
|
|
delete m_vecEmitter[ nIndex ];
|
|
m_vecEmitter.erase( m_vecEmitter.begin() + nIndex );
|
|
}
|
|
}
|
|
|
|
void CEtBillboardEffectData::ChangeEmitter( int nIndex1, int nIndex2 )
|
|
{
|
|
int nSize = (int)m_vecEmitter.size();
|
|
if( nIndex1 < 0 || nIndex1 >= nSize ) return;
|
|
if( nIndex2 < 0 || nIndex2 >= nSize ) return;
|
|
CEtBillboardEffectEmitter *pEmitter = m_vecEmitter[nIndex1];
|
|
m_vecEmitter[nIndex1] = m_vecEmitter[nIndex2];
|
|
m_vecEmitter[nIndex2] = pEmitter;
|
|
}
|
|
|
|
void CEtBillboardEffectData::LoadTexture( int nIndex, const char *pFileName )
|
|
{
|
|
m_vecEmitter[ nIndex ]->LoadTexture( pFileName );
|
|
m_vecEmitter[ nIndex ]->SetEffectParam( m_hMaterial );
|
|
}
|
|
|
|
CEtBillboardEffectDataInstance* CEtBillboardEffectData::GetInstance()
|
|
{
|
|
if( m_InstanceFreeSlots.empty() )
|
|
{
|
|
CEtBillboardEffectDataInstance *pDataInstance = new CEtBillboardEffectDataInstance;
|
|
pDataInstance->CopyDataInfo( GetMySmartPtr() );
|
|
m_InstancePool.push_back( pDataInstance );
|
|
return pDataInstance;
|
|
}
|
|
else
|
|
{
|
|
int nIndex = m_InstanceFreeSlots.back();
|
|
m_InstanceFreeSlots.pop_back();
|
|
m_InstancePool[ nIndex ]->Reset();
|
|
return m_InstancePool[ nIndex ];
|
|
}
|
|
}
|
|
|
|
void CEtBillboardEffectData::ReleaseInstance( CEtBillboardEffectDataInstance *pInstance )
|
|
{
|
|
if( pInstance == NULL )
|
|
return;
|
|
|
|
int i, nSize;
|
|
nSize = (int)m_InstancePool.size();
|
|
for( i = 0; i < nSize; i++ )
|
|
{
|
|
if( m_InstancePool[ i ] == pInstance )
|
|
{
|
|
m_InstanceFreeSlots.push_back( i );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CEtBillboardEffectDataInstance::CEtBillboardEffectDataInstance()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
CEtBillboardEffectDataInstance::~CEtBillboardEffectDataInstance()
|
|
{
|
|
}
|
|
|
|
void CEtBillboardEffectDataInstance::Reset()
|
|
{
|
|
m_bAlphaFog = true;
|
|
m_pTracePos = NULL;
|
|
}
|
|
|
|
void CEtBillboardEffectDataInstance::CopyDataInfo( EtBillboardEffectDataHandle hData )
|
|
{
|
|
int i;
|
|
|
|
m_hData = hData;
|
|
m_vecCustomParams.resize( hData->GetEmitterCount() );
|
|
m_vecRenderInfo.resize( hData->GetEmitterCount() );
|
|
#ifdef PRE_FIX_MATERIAL_DUMP
|
|
if( !hData->m_hMaterial ) return;
|
|
#endif
|
|
for( i = 0; i < ( int )m_vecCustomParams.size(); i++ )
|
|
{
|
|
m_vecCustomParams[ i ] = hData->m_vecEmitter[ i ]->m_vecCustomParam;
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_FLOAT_PTR, hData->m_hMaterial, "g_fParticleTime", &m_vecRenderInfo[ i ].fTime );
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_VECTOR_PTR, hData->m_hMaterial, "g_Origin", &m_vecRenderInfo[ i ].Origin );
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_FLOAT_PTR, hData->m_hMaterial, "g_fGravityAccel", &m_vecRenderInfo[ i ].fGravitySpeed );
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_VECTOR_PTR, hData->m_hMaterial, "g_GravityVecView", &m_vecRenderInfo[ i ].vGravity );
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_VECTOR_PTR, hData->m_hMaterial, "g_fParticleColor", &m_vecRenderInfo[ i ].Color );
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_FLOAT_PTR, hData->m_hMaterial, "g_fParticleScale", &m_vecRenderInfo[ i ].fScale );
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_MATRIX_PTR, hData->m_hMaterial, "g_BillBoardMat", &m_vecRenderInfo[ i ].BillBoardMatrix );
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_VECTOR_PTR, hData->m_hMaterial, "g_IteratePos", NULL, TRACE_POS_COUNT );
|
|
}
|
|
}
|
|
|
|
void CEtBillboardEffectDataInstance::SetTracePosCustomParam( std::vector< EtVector4 > &vecTracePos )
|
|
{
|
|
if( !vecTracePos.empty() )
|
|
{
|
|
if( m_pTracePos != &vecTracePos[ 0 ] )
|
|
{
|
|
m_pTracePos = &vecTracePos[ 0 ];
|
|
|
|
if( vecTracePos.size() < TRACE_POS_COUNT )
|
|
vecTracePos.resize( TRACE_POS_COUNT );
|
|
|
|
for( int i = 0; i < ( int )m_vecCustomParams.size(); i++ )
|
|
{
|
|
AddCustomParam( m_vecCustomParams[ i ], EPT_VECTOR_PTR, m_hData->m_hMaterial, "g_IteratePos", m_pTracePos, TRACE_POS_COUNT );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int CEtBillboardEffectDataInstance::CalcTechnique( SEmitter *pEmitter, bool bTracePosMode )
|
|
{
|
|
int nTechniqueIndex;
|
|
bool bApplyTracePos = false;
|
|
if( ( bTracePosMode ) && ( !pEmitter->bDisregardTracePos ) )
|
|
bApplyTracePos = true;
|
|
|
|
if( bApplyTracePos ) nTechniqueIndex = 1;
|
|
else nTechniqueIndex = 0;
|
|
|
|
if( pEmitter->bUseBumpEffectTexture )
|
|
nTechniqueIndex += 2;
|
|
|
|
return nTechniqueIndex;
|
|
}
|
|
|
|
void CEtBillboardEffectDataInstance::Render( EtMatrix &WorldMat, int nTick, bool bTracePos, std::vector< EtVector4 > &vecTracePos, EtColor &Color, float fScale, bool bReduceFillRate )
|
|
{
|
|
#ifdef PRE_FIX_MATERIAL_DUMP
|
|
if( !m_hData->m_hMaterial ) return;
|
|
#endif
|
|
|
|
int i, nSize;
|
|
EtVector4 Time, vCurOrigin;
|
|
EtColor CurColor;
|
|
SEmitter EmitterInfo;
|
|
|
|
SetTracePosCustomParam( vecTracePos );
|
|
|
|
nSize = ( int )m_hData->m_vecEmitter.size();
|
|
EtVec4Transform( &vCurOrigin, ( EtVector4 * )&WorldMat._41, CEtCamera::GetActiveCamera()->GetViewMat() );
|
|
CurColor = Color;
|
|
|
|
if( m_bAlphaFog )
|
|
{
|
|
float fFogValue = ( CEtCamera::GetActiveCamera()->GetFogFar() - vCurOrigin.z ) / ( CEtCamera::GetActiveCamera()->GetFogFar() - CEtCamera::GetActiveCamera()->GetFogNear() );
|
|
fFogValue = min( fFogValue, 1.0f );
|
|
CurColor.a *= fFogValue;
|
|
}
|
|
|
|
for( i = 0; i < nSize; i++ )
|
|
{
|
|
CEtBillboardEffectEmitter *pEmitter;
|
|
|
|
pEmitter = m_hData->m_vecEmitter[ i ];
|
|
if( !pEmitter->IsDraw() )
|
|
continue;
|
|
if( nTick >= pEmitter->GetLifeDuration() * 2 )
|
|
continue;
|
|
|
|
pEmitter->GetEmitterInfo( &EmitterInfo );
|
|
int nTechniqueIndex = CalcTechnique( &EmitterInfo, bTracePos );
|
|
m_vecRenderInfo[ i ].fTime = nTick / ( float )m_hData->GetMaxBillboardEffectLife();
|
|
m_vecRenderInfo[ i ].fGravitySpeed = EmitterInfo.fFallSpeed * fScale;
|
|
EtVec3TransformNormal( &m_vecRenderInfo[ i ].vGravity, &EmitterInfo.vFallVector, CEtCamera::GetActiveCamera()->GetViewMat() );
|
|
m_vecRenderInfo[ i ].fScale = fScale;
|
|
m_vecRenderInfo[ i ].Origin = vCurOrigin;
|
|
m_vecRenderInfo[ i ].Color = CurColor;
|
|
|
|
if( EmitterInfo.bUseYBillBoard )
|
|
{
|
|
EtMatrix ViewMat = *CEtCamera::GetActiveCamera()->GetViewMat();
|
|
EtMatrix InvViewMat = *CEtCamera::GetActiveCamera()->GetInvViewMat();
|
|
EtMatrix MatRot;
|
|
EtMatrixRotationY( &MatRot, atan2f( InvViewMat._31, InvViewMat._33 ) );
|
|
EtMatrixMultiply( &m_vecRenderInfo[ i ].BillBoardMatrix, &MatRot, &ViewMat );
|
|
}
|
|
else
|
|
{
|
|
EtMatrixIdentity( &m_vecRenderInfo[ i ].BillBoardMatrix );
|
|
}
|
|
|
|
SRenderStackElement RenderElement;
|
|
|
|
RenderElement.hMaterial = m_hData->m_hMaterial;
|
|
RenderElement.nTechniqueIndex = nTechniqueIndex;
|
|
RenderElement.WorldMat = WorldMat;
|
|
RenderElement.nSaveMatIndex = -1;
|
|
RenderElement.pvecCustomParam = &m_vecCustomParams[ i ];
|
|
RenderElement.pRenderMeshStream = &pEmitter->m_EmitterMeshStream;
|
|
|
|
DWORD dwSrcBlend = g_nBlendModeList[ EmitterInfo.nSourceBlendMode ];
|
|
DWORD dwDestBlend = g_nBlendModeList[ EmitterInfo.nDestBlendMode ];
|
|
SStateBlock RenderStateBlock;
|
|
RenderStateBlock.AddRenderState( D3DRS_BLENDOP, g_nBlendOPList[ EmitterInfo.nBlendOP ] );
|
|
RenderStateBlock.AddRenderState( D3DRS_SRCBLEND, dwSrcBlend );
|
|
RenderStateBlock.AddRenderState( D3DRS_DESTBLEND, dwDestBlend );
|
|
RenderElement.nStateBlockIndex = CEtStateBlockManager::GetInstance().CreateStateBlock( &RenderStateBlock );
|
|
RenderElement.nBakeDepthIndex = DT_NONE;
|
|
RenderElement.fDist = -FLT_MAX;
|
|
|
|
if( EmitterInfo.bUseBumpEffectTexture )
|
|
{
|
|
RenderElement.renderPriority = RP_NORMAL;
|
|
RenderElement.nBakeDepthIndex = DT_NORMAL;
|
|
GetCurRenderStack()->AddUseBackBufferRenderElement( RenderElement );
|
|
}
|
|
else
|
|
{
|
|
GetCurRenderStack()->AddAlphaRenderElement( RenderElement );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEtBillboardEffectDataInstance::RenderImmediate( EtMatrix &WorldMat, int nTick, bool bTracePos, std::vector< EtVector4 > &vecTracePos, EtColor &Color, float fScale, bool bReduceFillRate )
|
|
{
|
|
int i, nSize;
|
|
EtVector4 Time, vCurOrigin;
|
|
EtColor CurColor;
|
|
SEmitter EmitterInfo;
|
|
|
|
SetTracePosCustomParam( vecTracePos );
|
|
|
|
nSize = ( int )m_hData->m_vecEmitter.size();
|
|
EtVec4Transform( &vCurOrigin, ( EtVector4 * )&WorldMat._41, CEtCamera::GetActiveCamera()->GetViewMat() );
|
|
CurColor = Color;
|
|
|
|
if( m_bAlphaFog )
|
|
{
|
|
float fFogValue = ( CEtCamera::GetActiveCamera()->GetFogFar() - vCurOrigin.z ) / ( CEtCamera::GetActiveCamera()->GetFogFar() - CEtCamera::GetActiveCamera()->GetFogNear() );
|
|
fFogValue = min( fFogValue, 1.0f );
|
|
CurColor.a *= fFogValue;
|
|
}
|
|
|
|
for( i = 0; i < nSize; i++ )
|
|
{
|
|
CEtBillboardEffectEmitter *pEmitter;
|
|
|
|
pEmitter = m_hData->m_vecEmitter[ i ];
|
|
if( !pEmitter->IsDraw() )
|
|
continue;
|
|
if( nTick >= pEmitter->GetLifeDuration() * 2 )
|
|
continue;
|
|
pEmitter->GetEmitterInfo( &EmitterInfo );
|
|
if( EmitterInfo.bUseBumpEffectTexture )
|
|
continue;
|
|
|
|
int nTechniqueIndex = CalcTechnique( &EmitterInfo, bTracePos );
|
|
m_vecRenderInfo[ i ].fTime = nTick / ( float )m_hData->GetMaxBillboardEffectLife();
|
|
m_vecRenderInfo[ i ].fGravitySpeed = EmitterInfo.fFallSpeed * fScale;
|
|
EtVec3TransformNormal( &m_vecRenderInfo[ i ].vGravity, &EmitterInfo.vFallVector, CEtCamera::GetActiveCamera()->GetViewMat() );
|
|
m_vecRenderInfo[ i ].fScale = fScale;
|
|
m_vecRenderInfo[ i ].Origin = vCurOrigin;
|
|
m_vecRenderInfo[ i ].Color = CurColor;
|
|
|
|
if( EmitterInfo.bUseYBillBoard )
|
|
{
|
|
EtMatrix ViewMat = *CEtCamera::GetActiveCamera()->GetViewMat();
|
|
EtMatrix InvViewMat = *CEtCamera::GetActiveCamera()->GetInvViewMat();
|
|
EtMatrix MatRot;
|
|
EtMatrixRotationY( &MatRot, atan2f( InvViewMat._31, InvViewMat._33 ) );
|
|
EtMatrixMultiply( &m_vecRenderInfo[ i ].BillBoardMatrix, &MatRot, &ViewMat );
|
|
}
|
|
else
|
|
{
|
|
EtMatrixIdentity( &m_vecRenderInfo[ i ].BillBoardMatrix );
|
|
}
|
|
|
|
GetEtDevice()->SetBlendOP( g_nBlendOPList[ EmitterInfo.nBlendOP ] );
|
|
GetEtDevice()->SetSrcBlend( g_nBlendModeList[ EmitterInfo.nSourceBlendMode ] );
|
|
GetEtDevice()->SetDestBlend( g_nBlendModeList[ EmitterInfo.nDestBlendMode ] );
|
|
|
|
GetEtDevice()->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
|
|
|
|
EtMaterialHandle hParticleMaterial = m_hData->m_hMaterial;
|
|
hParticleMaterial->SetTechnique( nTechniqueIndex );
|
|
int nPasses = 0;
|
|
hParticleMaterial->BeginEffect( nPasses );
|
|
hParticleMaterial->BeginPass( 0 );
|
|
hParticleMaterial->SetGlobalParams();
|
|
hParticleMaterial->SetWorldMatParams( &WorldMat, &WorldMat );
|
|
hParticleMaterial->SetCustomParamList( m_vecCustomParams[ i ] );
|
|
hParticleMaterial->CommitChanges();
|
|
pEmitter->m_EmitterMeshStream.Draw( hParticleMaterial->GetVertexDeclIndex( nTechniqueIndex, 0 ) );
|
|
hParticleMaterial->EndPass();
|
|
hParticleMaterial->EndEffect();
|
|
}
|
|
GetEtDevice()->SetBlendOP( BLENDOP_ADD );
|
|
GetEtDevice()->SetSrcBlend( BLEND_SRCALPHA );
|
|
GetEtDevice()->SetDestBlend( BLEND_INVSRCALPHA );
|
|
GetEtDevice()->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
|
|
} |