228 lines
6.7 KiB
C++
228 lines
6.7 KiB
C++
#include "StdAfx.h"
|
|
#include "EtRainEffect.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
|
#endif
|
|
|
|
CEtRainEffect::CEtRainEffect(void)
|
|
{
|
|
m_fRainSpeed = 1.0f;
|
|
m_fRaniStretchValue = 1.0f;
|
|
m_vCurUp = EtVector3( 0.0f, 1.0f, 0.0f );
|
|
m_vVertexOffset = EtVector4( 0.0f, 0.0f, 0.0f, 0.0f );
|
|
m_vRainDir = EtVector3( 0.0f, -1.0f, 0.0f );
|
|
m_vMovement = EtVector3( 0.0f, 0.0f, 0.0f );
|
|
m_vPrevMoveDir = EtVector3( 0.0f, 0.0f, 0.0f );
|
|
EtMatrixIdentity( &m_RotationMat );
|
|
|
|
m_nLayerCount = 1;
|
|
m_fRainSpeedDecreaseRate = 0.9f;
|
|
|
|
// 외부 파라메터로 빼놓지 않고 상수 형태로 쓴다..
|
|
// 필요하면 외부 파라메터로 빼도록 하자.
|
|
m_fMaxRainAngle = 30.0f;
|
|
m_fInterpolationSpeed = 300.0f;
|
|
m_fRainOffset = 0.0f;
|
|
}
|
|
|
|
CEtRainEffect::~CEtRainEffect(void)
|
|
{
|
|
}
|
|
|
|
void CEtRainEffect::SetRainDir( EtVector3 &vDir )
|
|
{
|
|
m_vRainDir = vDir;
|
|
|
|
EtVector3 vCross, vInverseDir, vWorldUp;
|
|
|
|
vInverseDir = -vDir;
|
|
vWorldUp = EtVector3( 0.0f, 1.0f, 0.0f );
|
|
EtVec3Cross( &vCross, &vWorldUp, &vInverseDir );
|
|
EtMatrixRotationAxis( &m_RotationMat, &vCross, EtAcos( EtVec3Dot( &vWorldUp, &vInverseDir ) ) );
|
|
}
|
|
|
|
void CEtRainEffect::Initialize( const char *pRainTexture )
|
|
{
|
|
int i, nIndexCount, nVertexCount;
|
|
EtVector3 *pvPosition;
|
|
EtVector2 *pTexCoord;
|
|
WORD *pwIndex;
|
|
|
|
nVertexCount = ( RAIN_CYLINDER_SIDE_COUNT + 1 ) * 2;
|
|
nIndexCount = RAIN_CYLINDER_SIDE_COUNT * 2 + 2;
|
|
|
|
pvPosition = new EtVector3[ nVertexCount ];
|
|
pTexCoord = new EtVector2[ nVertexCount ];
|
|
pwIndex = new WORD[ nIndexCount ];
|
|
for( i = 0; i < nVertexCount; i += 2 )
|
|
{
|
|
float fRadian, fWeight;
|
|
|
|
fWeight = ( 1.0f - ( i / ( nVertexCount - 2.0f ) ) );
|
|
fRadian = ET_PI * 2.0f * fWeight;
|
|
pvPosition[ i ] = EtVector3( sin( fRadian ) * RAIN_CYLINDER_RADIUS, RAIN_CYLINDER_HEIGHT, cos( fRadian ) * RAIN_CYLINDER_RADIUS );
|
|
pvPosition[ i + 1 ] = EtVector3( sin( fRadian ) * RAIN_CYLINDER_RADIUS, -RAIN_CYLINDER_HEIGHT, cos( fRadian ) * RAIN_CYLINDER_RADIUS );
|
|
|
|
pTexCoord[ i ] = EtVector2( fWeight * 4.0f, 0.0f );
|
|
pTexCoord[ i + 1 ] = EtVector2( fWeight * 4.0f, 10.0f );
|
|
}
|
|
for( i = 0; i < nIndexCount; i++ )
|
|
{
|
|
pwIndex[ i ] = i;
|
|
}
|
|
|
|
CMemoryStream Stream;
|
|
|
|
Stream.Initialize( pvPosition, nVertexCount * sizeof( EtVector3 ) );
|
|
m_MeshStream.LoadVertexStream( &Stream, MST_POSITION, 0, nVertexCount );
|
|
Stream.Initialize( pTexCoord, nVertexCount * sizeof( EtVector2 ) );
|
|
m_MeshStream.LoadVertexStream( &Stream, MST_TEXCOORD, 0, nVertexCount );
|
|
Stream.Initialize( pwIndex, nIndexCount * sizeof( WORD ) );
|
|
m_MeshStream.LoadIndexStream( &Stream, true, nIndexCount );
|
|
|
|
delete [] pvPosition;
|
|
delete [] pTexCoord;
|
|
delete [] pwIndex;
|
|
|
|
int nTexIndex;
|
|
|
|
m_hMaterial = LoadResource( "Rainfall.fx", RT_SHADER );
|
|
m_hTexture = LoadResource( pRainTexture, RT_TEXTURE );
|
|
if( m_hTexture )
|
|
{
|
|
nTexIndex = m_hTexture->GetMyIndex();
|
|
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, "g_RainfallTex", &nTexIndex );
|
|
}
|
|
AddCustomParam( m_vecCustomParam, EPT_FLOAT_PTR, m_hMaterial, "g_fRainSpeed", &m_fRainSpeed );
|
|
AddCustomParam( m_vecCustomParam, EPT_FLOAT_PTR, m_hMaterial, "g_fRainStretchValue", &m_fRaniStretchValue );
|
|
AddCustomParam( m_vecCustomParam, EPT_FLOAT_PTR, m_hMaterial, "g_fRainOffset", &m_fRainOffset );
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_RainVertexOffset", &m_vVertexOffset );
|
|
}
|
|
|
|
void CEtRainEffect::SetMovement( EtVector3 &vMovement )
|
|
{
|
|
EtVector3 vMoveDir;
|
|
float fMoveDist;
|
|
|
|
m_vMovement = vMovement;
|
|
fMoveDist = EtVec3Length( &m_vMovement );
|
|
if( fMoveDist > 0.0f )
|
|
{
|
|
vMoveDir = m_vMovement / fMoveDist;
|
|
if( EtVec3Dot( &vMoveDir, &m_vPrevMoveDir ) > 0.965925f ) // 15도 이하로 차이나면 같은 방향으로 움직이는 걸로 간주해서 예전 방향대로 움직인다.
|
|
{
|
|
m_vMovement = m_vPrevMoveDir * fMoveDist;
|
|
}
|
|
else
|
|
{
|
|
m_vPrevMoveDir = vMoveDir;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEtRainEffect::CalcRotationMat( float fElapsedTime )
|
|
{
|
|
EtVector3 vTargetUp, vWorldUp;
|
|
float fCurDegree, fTargetDegree, fDiffDegree;
|
|
|
|
vTargetUp = m_vMovement / fElapsedTime;
|
|
vTargetUp.y = 980.0f * m_fRainSpeed;
|
|
EtVec3Normalize( &vTargetUp, &vTargetUp );
|
|
|
|
vWorldUp = EtVector3( 0.0f, 1.0f, 0.0f );
|
|
fCurDegree = EtToDegree( EtAcos( EtVec3Dot( &vWorldUp, &m_vCurUp ) ) );
|
|
fTargetDegree = EtToDegree( EtAcos( EtVec3Dot( &vWorldUp, &vTargetUp ) ) );
|
|
if( fTargetDegree > m_fMaxRainAngle )
|
|
{
|
|
EtVector3 vUp;
|
|
EtMatrix AxisMat;
|
|
|
|
EtVec3Cross( &vUp, &vWorldUp, &vTargetUp );
|
|
EtMatrixRotationAxis( &AxisMat, &vUp, EtToRadian( m_fMaxRainAngle ) );
|
|
EtVec3TransformNormal( &vTargetUp, &vWorldUp, &AxisMat );
|
|
fTargetDegree = m_fMaxRainAngle;
|
|
}
|
|
|
|
fDiffDegree = fabs( fCurDegree - fTargetDegree ) / fElapsedTime;
|
|
|
|
if( fDiffDegree > m_fInterpolationSpeed )
|
|
{
|
|
EtVec3Lerp( &vTargetUp, &m_vCurUp, &vTargetUp, m_fInterpolationSpeed / fDiffDegree );
|
|
EtVec3Normalize( &vTargetUp, &vTargetUp );
|
|
}
|
|
|
|
m_vCurUp = vTargetUp;
|
|
}
|
|
|
|
void CEtRainEffect::RenderRainCylinder( EtVector3 &vPosition, EtVector3 &vScale )
|
|
{
|
|
EtMatrix WorldMat, ScaleMat;
|
|
|
|
EtMatrixTranslation( &WorldMat, vPosition.x, vPosition.y, vPosition.z );
|
|
EtMatrixScaling( &ScaleMat, vScale.x, vScale.y, vScale.z );
|
|
EtMatrixMultiply( &WorldMat, &ScaleMat, &WorldMat );
|
|
|
|
SRenderStackElement RenderElement;
|
|
|
|
RenderElement.hMaterial = m_hMaterial;
|
|
RenderElement.nTechniqueIndex = 0;
|
|
RenderElement.WorldMat = WorldMat;
|
|
RenderElement.nSaveMatIndex = -1;
|
|
RenderElement.pvecCustomParam = &m_vecCustomParam;
|
|
RenderElement.pRenderMeshStream = &m_MeshStream;
|
|
RenderElement.nBakeDepthIndex = DT_NONE;
|
|
GetCurRenderStack()->AddAlphaRenderElement( RenderElement );
|
|
}
|
|
|
|
void CEtRainEffect::Render( float fElapsedTime )
|
|
{
|
|
int i;
|
|
EtCameraHandle hCamera;
|
|
EtVector3 *pvCamPosition, vFinalUp;
|
|
float fRainSpeed;
|
|
|
|
hCamera = CEtCamera::GetActiveCamera();
|
|
pvCamPosition = hCamera->GetPosition();
|
|
|
|
CalcRotationMat( fElapsedTime );
|
|
|
|
fRainSpeed = m_fRainSpeed;
|
|
EtVec3TransformNormal( &vFinalUp, &m_vCurUp, &m_RotationMat );
|
|
m_vVertexOffset.x = vFinalUp.x * 500.0f;
|
|
m_vVertexOffset.y = vFinalUp.y * 500.0f;
|
|
m_vVertexOffset.z = vFinalUp.z * 500.0f;
|
|
m_vVertexOffset.y = 0.0f;
|
|
|
|
float fRainSpeedTable[ MAX_RAIN_CYLINDER_COUNT ];
|
|
float fCylinderScale[ MAX_RAIN_CYLINDER_COUNT ] = { 1.0f, 4.0f, 6.0f, 8.0f };
|
|
|
|
fRainSpeedTable[ 0 ] = m_fRainSpeed;
|
|
for( i = 1; i < MAX_RAIN_CYLINDER_COUNT; i++ )
|
|
{
|
|
fRainSpeedTable[ i ] = fRainSpeedTable[ i - 1 ] * m_fRainSpeedDecreaseRate;
|
|
}
|
|
for( i = m_nLayerCount - 1; i >= 0; i-- )
|
|
{
|
|
m_fRainOffset = i * 0.25f;
|
|
m_fRainSpeed = fRainSpeedTable[ i ];
|
|
if( i == 0 )
|
|
{
|
|
GetEtDevice()->EnableZ( false );
|
|
}
|
|
RenderRainCylinder( *pvCamPosition, EtVector3( fCylinderScale[ i ], fCylinderScale[ i ], fCylinderScale[ i ] ) );
|
|
GetEtDevice()->EnableZ( true );
|
|
}
|
|
|
|
m_fRainSpeed = fRainSpeed;
|
|
}
|
|
|
|
EtRainHandle CEtRainEffect::CreateRainEffect( const char *pRainTexture )
|
|
{
|
|
CEtRainEffect *pRainEffect;
|
|
|
|
pRainEffect = new CEtRainEffect();
|
|
pRainEffect->Initialize( pRainTexture );
|
|
|
|
return pRainEffect->GetMySmartPtr();
|
|
}
|