403 lines
10 KiB
C++
403 lines
10 KiB
C++
// HEADERS -------------------------------------------------------
|
|
// foward include
|
|
#include "stdafx.h"
|
|
|
|
//#include <vector>
|
|
#include <queue>
|
|
#include <deque>
|
|
|
|
#include "KRenderDeviceDX.h"
|
|
#include "SEnvPrimitive.h"
|
|
#include "KViewport.h"
|
|
#include "KRenderObject.h"
|
|
|
|
// header
|
|
#include "SGameLightning.h"
|
|
#include <kfile/KFileManager.h>
|
|
#include <toolkit/XStringUtil.h>
|
|
#include "KResourceManager.h"
|
|
|
|
// namespaces ----------------------------------------------------
|
|
using namespace env_fx;
|
|
|
|
// SLightningThread ----------------------------------------------
|
|
SLightningThread::SLightningThread()
|
|
: m_dwTime_msec_ ( 0 )
|
|
, m_dwBirthTime_msec_ ( 0 )
|
|
, m_vPosition ( 0, 0, 0 )
|
|
, m_bAlive ( false )
|
|
, m_nGeomIndex ( -1 )
|
|
{
|
|
}
|
|
|
|
SLightningThread::~SLightningThread()
|
|
{
|
|
}
|
|
|
|
void SLightningThread::Process( DWORD dwTime_msec_, const SLightningAttr& Attr )
|
|
{
|
|
if( m_dwTime_msec_ == 0 )
|
|
{
|
|
m_dwTime_msec_ = dwTime_msec_;
|
|
}
|
|
|
|
DWORD dwTimeDiff_msec_ = dwTime_msec_ - m_dwBirthTime_msec_;
|
|
m_dwTime_msec_ = dwTime_msec_;
|
|
|
|
if( dwTimeDiff_msec_ < Attr.dwLife_msec_ )
|
|
{
|
|
// twinkling
|
|
|
|
float ftheta = K3D_PI * Attr.nTwinklingCount
|
|
* (float)( dwTimeDiff_msec_ ) / (float)Attr.dwLife_msec_;
|
|
float fwave = sinf( ftheta );
|
|
fwave = fabs( fwave );
|
|
|
|
m_dwDiffuse = Attr.dwColor;
|
|
m_dwDiffuse.a = (unsigned char)( fwave * 255.0f );
|
|
}
|
|
else if( dwTimeDiff_msec_ >= Attr.dwLife_msec_ &&
|
|
dwTimeDiff_msec_ < ( Attr.dwLife_msec_ + Attr.dwFadeOut_msec_ ) )
|
|
{
|
|
// fade out
|
|
|
|
if( Attr.dwFadeOut_msec_ > 0 )
|
|
{
|
|
DWORD dwFadeoutDiff_msec_ = dwTimeDiff_msec_ - Attr.dwLife_msec_;
|
|
float fFadeoutFactor = 1.0f - (float)dwFadeoutDiff_msec_ / (float)Attr.dwFadeOut_msec_;
|
|
fFadeoutFactor = ::max( ::min( 1.0f, fFadeoutFactor ), 0.0f );
|
|
|
|
m_dwDiffuse = Attr.dwColor;
|
|
m_dwDiffuse.a = (unsigned char)( fFadeoutFactor * 255.0f );
|
|
}
|
|
else
|
|
{
|
|
m_dwDiffuse.a = (unsigned char)0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// die
|
|
|
|
this->SetAlive( false );
|
|
}
|
|
}
|
|
|
|
void SLightningThread::Primitive( const SLightningAttr& Attr
|
|
, K3DSPRITEVERTEX* pVtx
|
|
, const K3DVector& vCameraPosition )
|
|
{
|
|
K3DVector vNewNormal = vCameraPosition - m_vPosition;
|
|
vNewNormal.z = 0;
|
|
K3DVectorNormalize( vNewNormal, vNewNormal );
|
|
K3DMatrix mBill = util::GetRotationMatrixByNormal( K3DVector( 0, 1, 0 ), vNewNormal );
|
|
|
|
float fHalfWidth = Attr.fWidth / 2.0f;
|
|
float fHalfHeight = Attr.fHeight / 2.0f;
|
|
|
|
K3DVector vLocal[ 4 ] = {
|
|
K3DVector( -fHalfWidth, 0, 0 ),
|
|
K3DVector( fHalfWidth, 0, 0 ),
|
|
K3DVector( -fHalfWidth, 0, -Attr.fHeight ),
|
|
K3DVector( fHalfWidth, 0, -Attr.fHeight )
|
|
};
|
|
|
|
for( int i = 0; i < 4; ++i )
|
|
{
|
|
K3DVectorTransform( vLocal[ i ], vLocal[ i ], mBill );
|
|
}
|
|
|
|
pVtx[ 0 ].pos = m_vPosition + vLocal[ 0 ];
|
|
pVtx[ 1 ].pos = m_vPosition + vLocal[ 1 ];
|
|
pVtx[ 2 ].pos = m_vPosition + vLocal[ 2 ];
|
|
pVtx[ 3 ].pos = m_vPosition + vLocal[ 3 ];
|
|
|
|
pVtx[ 0 ].diffuse = m_dwDiffuse;
|
|
pVtx[ 1 ].diffuse = m_dwDiffuse;
|
|
pVtx[ 2 ].diffuse = m_dwDiffuse;
|
|
pVtx[ 3 ].diffuse = m_dwDiffuse;
|
|
}
|
|
|
|
void SLightningThread::SetAlive( bool bAlive )
|
|
{
|
|
m_bAlive = bAlive;
|
|
}
|
|
|
|
bool SLightningThread::IsActive( const SLightningAttr& Attr ) const
|
|
{
|
|
return ( ( m_dwBirthTime_msec_ + Attr.dwLife_msec_ ) > m_dwTime_msec_ ) ? true : false;
|
|
}
|
|
|
|
void SLightningThread::SetPosition( const K3DVector& vPosition )
|
|
{
|
|
m_vPosition = vPosition;
|
|
}
|
|
|
|
void SLightningThread::SetBirthTime( DWORD dwBirthTime_msec_ )
|
|
{
|
|
m_dwBirthTime_msec_ = dwBirthTime_msec_;
|
|
}
|
|
|
|
// SGameLightning ----------------------------------------------
|
|
SGameLightning::SGameLightning( int nMaxLightning )
|
|
: m_dwTime_msec_ ( 0 )
|
|
, m_dwTimeDiff_msec_ ( 0 )
|
|
, m_dwTimeBirth_msec_ ( 0 )
|
|
, m_bAlive ( true )
|
|
, m_vPosition ( 0, 0, 0 )
|
|
, m_nMaxLightning ( nMaxLightning )
|
|
, m_pmParent ( 0 )
|
|
, m_pRenderDevice ( 0 )
|
|
, m_pPrimitive ( 0 )
|
|
, m_spTexture ( 0 )
|
|
, m_pMtrl ( 0 )
|
|
, m_pVtx ( 0 )
|
|
, m_pIdx ( 0 )
|
|
{
|
|
m_ctLightningThreads.reserve( m_nMaxLightning );
|
|
K3DMatrixIdentity( m_mWorld );
|
|
K3DMatrixIdentity( m_mBillboard );
|
|
}
|
|
|
|
SGameLightning::~SGameLightning()
|
|
{
|
|
SAFE_DELETE( m_pPrimitive );
|
|
SAFE_DELETE( m_pMtrl );
|
|
SAFE_DELETE_ARRAY( m_pVtx );
|
|
SAFE_DELETE_ARRAY( m_pIdx );
|
|
util::wipe_seq( m_ctLightningThreads );
|
|
}
|
|
|
|
void SGameLightning::Init( K3DRenderDevice* pDevice )
|
|
{
|
|
this->SetRenderDevice( pDevice );
|
|
this->initGeometry();
|
|
this->createLightningThread();
|
|
}
|
|
|
|
void SGameLightning::Process( DWORD dwTime_msec_ )
|
|
{
|
|
if( m_dwTime_msec_ == 0 )
|
|
{
|
|
this->SetTime( dwTime_msec_ );
|
|
return;
|
|
}
|
|
|
|
this->SetTime( dwTime_msec_ );
|
|
|
|
K3DSPRITEVERTEX* pVtx = m_pVtx;
|
|
int nThreadSize = (int)m_ctLightningThreads.size();
|
|
|
|
//K3DVector vBill( m_Attribute.fWidth / 2.0f, 0, 0 );
|
|
//K3DVectorTransform( vBill, vBill, m_mBillboard );
|
|
|
|
if( !m_ctLightningThreads.empty() )
|
|
{
|
|
SWeatherLightningPrimitive* primitive =
|
|
static_cast< SWeatherLightningPrimitive* >( m_pPrimitive );
|
|
|
|
primitive->ResetGeometryCount();
|
|
|
|
std::sort( m_ctLightningThreads.begin(),
|
|
m_ctLightningThreads.end(),
|
|
env_fx::_private::SSortThreadsByGeomIndex() );
|
|
|
|
for( int n = 0; n < nThreadSize; ++n )
|
|
{
|
|
SLightningThread* pThread = m_ctLightningThreads[ n ];
|
|
if( pThread && pThread->IsAlive() )
|
|
{
|
|
pThread->Process( m_dwTime_msec_, m_Attribute );
|
|
|
|
int geom_index = pThread->GetGeomIndex();
|
|
SWeatherLightningPrimitive::SGeometryInfo& geom_info =
|
|
primitive->GetGeometryInfoAt( geom_index );
|
|
|
|
pThread->Primitive( m_Attribute, pVtx, K3DVector( 0, 0, 0 ) );
|
|
geom_info.IncreasePrimitiveCount();
|
|
pVtx += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
//m_pPrimitive->SetVertexCnt( nPrimCount * 4 );
|
|
}
|
|
|
|
void SGameLightning::Render( KViewportObject* pViewport )
|
|
{
|
|
if( m_pPrimitive && m_pPrimitive->GetVertexCnt() > 0 )
|
|
{
|
|
pViewport->Register( m_pPrimitive, KRenderObject::RENDEREFX_WEATHER );
|
|
}
|
|
}
|
|
|
|
void SGameLightning::Emit( const K3DVector& vPosition )
|
|
{
|
|
if( vPosition.Magnitude() < m_Attribute.fVisibleDistance )
|
|
return;
|
|
|
|
LightningThreadVector::const_iterator iDeadThread = std::find_if(
|
|
m_ctLightningThreads.begin(),
|
|
m_ctLightningThreads.end(),
|
|
_private::SFindDeadThread() );
|
|
|
|
if( iDeadThread != m_ctLightningThreads.end() )
|
|
{
|
|
size_t geom_size = static_cast< SWeatherLightningPrimitive* >( m_pPrimitive )->GetGeometrySize();
|
|
if( geom_size > 0 )
|
|
{
|
|
int geom_index = rand() % geom_size;
|
|
(*iDeadThread)->SetGeomIndex( geom_index );
|
|
(*iDeadThread)->SetAlive( true );
|
|
(*iDeadThread)->SetPosition( vPosition );
|
|
(*iDeadThread)->SetBirthTime( m_dwTime_msec_ );
|
|
}
|
|
}
|
|
}
|
|
|
|
void SGameLightning::SetRenderDevice( K3DRenderDevice* pDevice )
|
|
{
|
|
m_pRenderDevice = pDevice;
|
|
}
|
|
|
|
void SGameLightning::SetBillboardMatrix( const K3DMatrix& mBillboard )
|
|
{
|
|
m_mBillboard = mBillboard;
|
|
}
|
|
|
|
void SGameLightning::SetCameraPosition( const K3DVector& vCamPos )
|
|
{
|
|
m_vCamPos = vCamPos;
|
|
}
|
|
|
|
void SGameLightning::SetTime( DWORD dwTime_msec_ )
|
|
{
|
|
m_dwTime_msec_ = dwTime_msec_;
|
|
//if( m_dwTimeBirth_msec_ + m_Attribute.dwLife_msec_ <= m_dwTime_msec_ )
|
|
// m_bAlive = false;
|
|
//else
|
|
// m_bAlive = true;
|
|
}
|
|
|
|
void SGameLightning::SetTexture( K3DTexture* pTexture )
|
|
{
|
|
m_spTexture = pTexture;
|
|
}
|
|
|
|
void SGameLightning::SetAttribute( const SLightningAttr& Attr )
|
|
{
|
|
m_Attribute = Attr;
|
|
|
|
if( !m_Attribute.strTextures.empty() )
|
|
{
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
|
|
size_t size = m_Attribute.strTextures.size();
|
|
for( size_t n = 0; n < size; ++n )
|
|
{
|
|
K3DTextureSPtr spTexture;
|
|
spTexture = KTextureManager::GetManager()->GetTexture(
|
|
m_Attribute.strTextures.at( n ).c_str(), &loadpack, true,
|
|
KTextureManager::GetManager()->GetMipMapBiasLevel() );
|
|
assert( m_spTexture && "Lightning texture not loaded!!" );
|
|
|
|
if( m_pPrimitive )
|
|
{
|
|
SWeatherLightningPrimitive::SGeometryInfo info;
|
|
info.texture = spTexture;
|
|
static_cast< SWeatherLightningPrimitive* >( m_pPrimitive )->AddGeometryInfo( info );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SGameLightning::SetPosition( const K3DVector& vPosition )
|
|
{
|
|
m_vPosition = vPosition;
|
|
}
|
|
|
|
void SGameLightning::SetParentMatrix( K3DMatrix* pmParent )
|
|
{
|
|
m_pmParent = pmParent;
|
|
m_pPrimitive->SetTransform( m_pmParent, m_pmParent );
|
|
}
|
|
|
|
const env_fx::SLightningAttr& SGameLightning::GetAttribute() const
|
|
{
|
|
return m_Attribute;
|
|
}
|
|
|
|
void SGameLightning::initGeometry()
|
|
{
|
|
if( m_pRenderDevice )
|
|
{
|
|
srand( 0 );
|
|
|
|
// vertex buffer
|
|
m_pVtx = new K3DSPRITEVERTEX[ m_nMaxLightning * 4 ];
|
|
|
|
for( int n = 0; n < m_nMaxLightning; ++n )
|
|
{
|
|
m_pVtx[ 4 * n + 0 ].pos = K3DVector( 0, 0, 0 );
|
|
m_pVtx[ 4 * n + 0 ].texel = K3DTexel( 0, 0 );
|
|
m_pVtx[ 4 * n + 0 ].diffuse = KColor( 255, 255, 255, 255 );
|
|
|
|
m_pVtx[ 4 * n + 1 ].pos = K3DVector( 0, 0, 0 );
|
|
m_pVtx[ 4 * n + 1 ].texel = K3DTexel( 1, 0 );
|
|
m_pVtx[ 4 * n + 1 ].diffuse = KColor( 255, 255, 255, 255 );
|
|
|
|
m_pVtx[ 4 * n + 2 ].pos = K3DVector( 0, 0, 0 );
|
|
m_pVtx[ 4 * n + 2 ].texel = K3DTexel( 0, 1 );
|
|
m_pVtx[ 4 * n + 2 ].diffuse = KColor( 255, 255, 255, 255 );
|
|
|
|
m_pVtx[ 4 * n + 3 ].pos = K3DVector( 0, 0, 0 );
|
|
m_pVtx[ 4 * n + 3 ].texel = K3DTexel( 1, 1 );
|
|
m_pVtx[ 4 * n + 3 ].diffuse = KColor( 255, 255, 255, 255 );
|
|
}
|
|
|
|
// index buffer
|
|
m_pIdx = new WORD[ m_nMaxLightning * 6 ];
|
|
|
|
for( int n = 0; n < m_nMaxLightning; ++n )
|
|
{
|
|
m_pIdx[ 6 * n + 0 ] = 4 * n + 2;
|
|
m_pIdx[ 6 * n + 1 ] = 4 * n + 1;
|
|
m_pIdx[ 6 * n + 2 ] = 4 * n + 0;
|
|
m_pIdx[ 6 * n + 3 ] = 4 * n + 2;
|
|
m_pIdx[ 6 * n + 4 ] = 4 * n + 3;
|
|
m_pIdx[ 6 * n + 5 ] = 4 * n + 1;
|
|
}
|
|
|
|
m_pPrimitive = new SWeatherLightningPrimitive();
|
|
|
|
if( m_pPrimitive )
|
|
{
|
|
m_pMtrl = new K3DMaterial;
|
|
m_pMtrl->SetAmbient( K3DColor( 1.f, 1.f, 1.f, 1.f ) );
|
|
m_pMtrl->SetDiffuse( K3DColor( 1.f, 1.f, 1.f, 1.f ) );
|
|
m_pMtrl->SetSpecular( K3DColor( 0.f, 0.f, 0.f, 1.f ) );
|
|
m_pMtrl->SetSpecularPower( 1.0f );
|
|
|
|
K3DMatrix mParent;
|
|
K3DMatrixIdentity( mParent );
|
|
m_pPrimitive->SetBlendMode( K3DMaterial::MBM_ADDITIVE );
|
|
m_pPrimitive->SetMaterial( m_pMtrl );
|
|
m_pPrimitive->SetTransparent( true );
|
|
m_pPrimitive->SetTransform( &m_mWorld, &mParent );
|
|
m_pPrimitive->SetTexture( 0, m_spTexture );
|
|
m_pPrimitive->SetCommonVertex( m_pVtx );
|
|
m_pPrimitive->SetCommonIndexed( m_pIdx );
|
|
m_pPrimitive->SetVertexFmt( K3DFVF_SPRITE );
|
|
m_pPrimitive->SetVertexStride( sizeof( K3DSPRITEVERTEX ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void SGameLightning::createLightningThread()
|
|
{
|
|
for( int n = 0; n < m_nMaxLightning; ++n )
|
|
{
|
|
m_ctLightningThreads.push_back( new SLightningThread() );
|
|
}
|
|
} |