#include "StdAfx.h" #include "EtWorldWater.h" #include "EtWorldWaterRiver.h" #include "EtWorldGrid.h" #include "EtWorldSector.h" #include "EngineUtil.h" //#include "EtWater.h" #if !defined( USE_BOOST_MEMPOOL ) #ifdef _DEBUG #define new new(_NORMAL_BLOCK,__FILE__,__LINE__) #endif #endif // #if !defined( USE_BOOST_MEMPOOL ) float CEtQuadtreeNode::s_fMinRadius = 1000.f; CEtWorldWater::CEtWorldWater( CEtWorldSector *pSector ) : m_vUVRatio( 5.f, 5.f ) , m_vOffset( 0.f, 0.f ) { m_pSector = pSector; m_fWaterLevel = 0.f; m_fGridSize = 200.f; m_pAlphaTable = NULL; m_nAlphaTableWidth = 512; m_nAlphaTableHeight = 512; m_nBorderReduction = 10; m_nGaussianValue = 5; m_fGaussianEpsilon = 3.f; m_nMinAlpha = 0; m_nMaxAlpha = 200; m_fRevisionAlpha = 1.f; m_bEnable = false; m_pRiverQuadtree = NULL; } CEtWorldWater::~CEtWorldWater() { for( DWORD i=0; iRemove( m_pVecRiver[i], m_pVecRiver[i]->GetCurQuadtreeNode() ); } SAFE_DELETE( m_pRiverQuadtree ); SAFE_DELETEA( m_pAlphaTable ); SAFE_DELETE_PVEC( m_pVecCustomParamList ); SAFE_DELETE_PVEC( m_pVecRiver ); } CEtWorldWaterRiver *CEtWorldWater::AllocRiver() { return new CEtWorldWaterRiver( this ); } bool CEtWorldWater::Initialize() { float fSize = max( GetSector()->GetParentGrid()->GetGridWidth() * 100.f, GetSector()->GetParentGrid()->GetGridHeight() * 100.f ); m_pRiverQuadtree = new CEtQuadtree; m_pRiverQuadtree->Initialize( EtVector2( GetSector()->GetOffset()->x, GetSector()->GetOffset()->z ), fSize ); m_vOffset = EtVec3toVec2( *GetSector()->GetOffset() ); m_vOffset.x -= ( GetSector()->GetTileWidthCount() * GetSector()->GetTileSize() ) / 2.f; m_vOffset.y -= ( GetSector()->GetTileHeightCount() * GetSector()->GetTileSize() ) / 2.f; return true; } bool CEtWorldWater::Load( const char *szFileName ) { CResMngStream Stream( szFileName ); if( !Stream.IsValid() ) return true; // ½ÇÁ¦ µ¥ÀÌÅ͵é Stream.Read( &m_bEnable, sizeof(bool) ); Stream.Read( &m_nAlphaTableWidth, sizeof(int) ); Stream.Read( &m_nAlphaTableHeight, sizeof(int) ); Stream.Read( &m_fGridSize, sizeof(float) ); Stream.Read( &m_vUVRatio, sizeof(EtVector2) ); Stream.Read( &m_fWaterLevel, sizeof(float) ); SAFE_DELETE( m_pAlphaTable ); m_pAlphaTable = new BYTE[ m_nAlphaTableWidth * m_nAlphaTableHeight ]; Stream.Read( m_pAlphaTable, sizeof(BYTE) * ( m_nAlphaTableWidth * m_nAlphaTableHeight ) ); Stream.Read( &m_nBorderReduction, sizeof(int) ); Stream.Read( &m_nGaussianValue, sizeof(int) ); Stream.Read( &m_fGaussianEpsilon, sizeof(float) ); Stream.Read( &m_nMinAlpha, sizeof(int) ); Stream.Read( &m_nMaxAlpha, sizeof(int) ); Stream.Read( &m_fRevisionAlpha, sizeof(float) ); ReadStdString( m_szShaderName, &Stream ); int nCustomParamCount = 0; Stream.Read( &nCustomParamCount, sizeof(int) ); SAFE_DELETE_PVEC( m_pVecCustomParamList ); for( int i=0; iszName, &Stream ); Stream.Read( &pStruct->nType, sizeof(int) ); switch( pStruct->nType ) { case EPT_INT: Stream.Read( &pStruct->nInt, sizeof(int) ); break; case EPT_FLOAT: Stream.Read( &pStruct->fFloat, sizeof(float) ); break; case EPT_VECTOR: Stream.Read( pStruct->fFloat4, sizeof(float)*4 ); break; case EPT_TEX: { std::string szTemp; ReadStdString( szTemp, &Stream ); if( szTemp.empty() ) szTemp = "(null)"; pStruct->szTexName = new char[szTemp.size()+1]; memset( pStruct->szTexName, 0, szTemp.size()+1 ); strcpy_s( pStruct->szTexName, szTemp.size()+1, szTemp.c_str() ); } } m_pVecCustomParamList.push_back( pStruct ); } int nRiverCount = 0; Stream.Read( &nRiverCount, sizeof(int) ); for( int i=0; iLoad( &Stream ) == false ) { SAFE_DELETE( pRiver ); continue; } m_pVecRiver.push_back( pRiver ); SCircle Circle; pRiver->GetBoundingCircle( Circle ); pRiver->SetCurQuadtreeNode( m_pRiverQuadtree->Insert( pRiver, Circle ) ); } return true; } DWORD CEtWorldWater::GetRiverCount() { return (DWORD)m_pVecRiver.size(); } CEtWorldWaterRiver *CEtWorldWater::GetRiverFromIndex( DWORD dwIndex ) { if( dwIndex >= m_pVecRiver.size() ) return NULL; return m_pVecRiver[dwIndex]; } CEtWorldWaterRiver *CEtWorldWater::GetRiverFromName( const char *szName ) { for( DWORD i=0; iGetName(), szName ) == NULL ) return m_pVecRiver[i]; } return NULL; } bool CEtWorldWater::GetHeight( float fX, float fZ, float *pfHeight ) { std::vector vecResult; ScanRiver( EtVector2( fX + m_vOffset.x, fZ + m_vOffset.y ), 100.f, &vecResult ); if( !vecResult.empty() ) { CEtWorldWaterRiver *pRiver; for( DWORD i=0; iGetRevisionAlpha() > 3.0f ) continue; // RevisionAlpha°¡ ³ôÀº ¸®¹ö´Â ¸ð·¡°­ °°Àº ¾ÖµéÀÌ¶ó ¿¹¿Üó¸®ÇÑ´Ù. if( pRiver->GetHeight( fX, fZ, *pfHeight ) == true ) return true; } } if( m_bEnable ) { if( pfHeight ) *pfHeight = m_fWaterLevel; return true; } return false; } void CEtWorldWater::ScanRiver( EtVector2 &vPos, float fRadius, std::vector *pVecResult ) { if( !m_pRiverQuadtree ) return; SCircle Circle; Circle.Center = vPos; Circle.fRadius = fRadius; m_pRiverQuadtree->Pick( Circle, *pVecResult, false ); } bool CEtWorldWater::Pick( EtVector3 &vOrig, EtVector3 &vDir, EtVector3 &vPickPos ) { if( !m_bEnable ) return false; SAABox Box; Box.Reset(); std::vector pVecList; ScanRiver( EtVec3toVec2( vOrig ), EtVec3Length( &vDir ), &pVecList ); float fDistance; float fMinDist = FLT_MAX; EtVector3 vTempPick, vMinPick; for( DWORD i=0; iPick( vOrig, vDir, vTempPick ); if( fDistance < fMinDist ) { vMinPick = vTempPick; } } if( fMinDist != FLT_MAX ) { vPickPos = vMinPick; return true; } EtVector3 *vOffset = m_pSector->GetOffset(); float fWidth = ( m_pSector->GetTileWidthCount() * m_pSector->GetTileSize() ) / 2.f; float fHeight = ( m_pSector->GetTileHeightCount() * m_pSector->GetTileSize() ) / 2.f; Box.AddPoint( EtVector3( vOffset->x - fWidth, m_fWaterLevel, vOffset->z - fHeight ) ); Box.AddPoint( EtVector3( vOffset->x + fWidth, m_fWaterLevel, vOffset->z + fHeight ) ); if( TestLineToBox( vOrig, vDir, Box, fDistance ) ) { vPickPos = vOrig + ( vDir * fDistance ); return true; } return false; }