1205 lines
36 KiB
C++
1205 lines
36 KiB
C++
#include "stdafx.h"
|
|
#include "SGameLowQualityWater.h"
|
|
#include "SGame.h"
|
|
#include "KRenderObject.h"
|
|
#include "SGameViewPort.h"
|
|
#include "K3DTypes.h"
|
|
#include "KResourceManager.h"
|
|
#include "K3DCamera.h"
|
|
#include "EnvironmentInfo.h"
|
|
#include "k3dpccp.h"
|
|
#include "GameRule.h"
|
|
#include "SLowQualityWaterDB.h"
|
|
|
|
#include "SDebug_Util.h"
|
|
|
|
namespace
|
|
{
|
|
//거리 체크
|
|
bool CheckDistance( K3DVector* pTargetPos, K3DVector* pMinVertex, K3DVector* pMaxVertex )
|
|
{
|
|
K3DVector vTargetPos = K3DVector(pTargetPos->x, pTargetPos->y, 0.0f );
|
|
K3DVector vLeftTop = K3DVector(pMinVertex->x, pMinVertex->y, 0.0f );
|
|
K3DVector vRightBottonm = K3DVector(pMaxVertex->x, pMaxVertex->y, 0.0f );
|
|
|
|
K3DVector vLeftBotton = K3DVector(pMinVertex->x, pMaxVertex->y, 0.0f );
|
|
K3DVector vRightTop = K3DVector(pMaxVertex->x, pMinVertex->y, 0.0f );
|
|
|
|
float fD1 = K3DVectorLength( vTargetPos - vLeftTop );
|
|
float fD2 = K3DVectorLength( vTargetPos - vRightBottonm );
|
|
float fD3 = K3DVectorLength( vTargetPos - vLeftBotton );
|
|
float fD4 = K3DVectorLength( vTargetPos - vRightTop );
|
|
|
|
if( fD1 > cTerrainVisibleDistance && fD2 > cTerrainVisibleDistance &&
|
|
fD3 > cTerrainVisibleDistance && fD4 > cTerrainVisibleDistance )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//경계구 충돌 체크
|
|
bool CheckSphere( const K3DVector* pPosition, const K3DVector* pCenter, float fRadius1, float fRadius2 )
|
|
{
|
|
float fXDiff = (float)fabs( pPosition->x - pCenter->x );
|
|
float fYDiff = (float)fabs( pPosition->y - pCenter->y );
|
|
|
|
float fDistance = (float)sqrt( (fXDiff*fXDiff)+(fYDiff*fYDiff) );
|
|
if( fDistance <= (fRadius1 + fRadius2) ) //내 경계구와 물의 경계구가 충돌이 됐다면
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CheckCameraInWater( K3DVector* vMin, K3DVector* vMax, K3DCamera* pCamera )
|
|
{
|
|
K3DVector vCampos = pCamera->GetCamPos();
|
|
|
|
// 카메라 포스와 타겟이 물 사각 안에 있는지 검사
|
|
if( (int)vMin->x <= (int)vCampos.x && (int)vMin->y >= (int)vCampos.y &&
|
|
(int)vMax->x >= (int)vCampos.x && (int)vMax->y <= (int)vCampos.y )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CheckPlayerInWater( K3DVector* vMin, K3DVector* vMax, K3DCamera* pCamera, K3DVector & vPlayerPos )
|
|
{
|
|
// 카메라 포스와 타겟이 물 사각 안에 있는지 검사
|
|
if( (int)vMin->x <= (int)vPlayerPos.x && (int)vMin->y >= (int)vPlayerPos.y &&
|
|
(int)vMax->x >= (int)vPlayerPos.x && (int)vMax->y <= (int)vPlayerPos.y )
|
|
{
|
|
//if( fabs( vPlayerPos.z - vMin->z ) <= 1.0f || vPlayerPos.z <= vMin->z ) return true;
|
|
|
|
//물 높이가 플레이어 보다 높다면
|
|
if( ( vPlayerPos.z - vMin->z ) <= 1.5f || vPlayerPos.z <= vMin->z ) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CheckCameraWaterHeight( K3DVector* vMin, K3DVector* vMax, K3DCamera* pCamera )
|
|
{
|
|
K3DVector vCampos = pCamera->GetCamPos();
|
|
//물이더 높게 있다면
|
|
if( vMin->z > vCampos.z )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void WATER_TEXTURE_SET::CreateTextureSet( int nWaterType, LowQualityWater* pLowQualityWaterData )
|
|
{
|
|
m_nWaterType = nWaterType;
|
|
|
|
if( pLowQualityWaterData == NULL ) return;
|
|
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
|
|
char** ppTextureSetName = pLowQualityWaterData->GetTextureFileName();
|
|
|
|
for( int x = 0; x < cMaxWaterTexture; ++x )
|
|
{
|
|
std::string strTextureName = ppTextureSetName[x];
|
|
strTextureName += ".dds";
|
|
m_spTextureArray[x] = KTextureManager::GetManager()->GetTexture( strTextureName.c_str(), &loadpack, true, KTextureManager::GetManager()->GetMipMapBiasLevel() );
|
|
}
|
|
}
|
|
|
|
K3DTextureSPtr* WATER_TEXTURE_SET::GetTextureSet()
|
|
{
|
|
// ++m_nRef;
|
|
InterlockedIncrement( (volatile LONG *)&m_nRef ); //m_nRef++;
|
|
return m_spTextureArray;
|
|
}
|
|
|
|
bool WATER_TEXTURE_SET::Release()
|
|
{
|
|
InterlockedDecrement( (volatile LONG *)&m_nRef ); ////m_nRef--;
|
|
//이 텍스처 세트를 참조하는 곳이 없다면 0
|
|
return ( m_nRef <= 0 ) ? true : false;
|
|
}
|
|
|
|
//디테일 세그먼트 만들기
|
|
bool WATER_DETAIL_SEGMENT::CreateDetailSegment( K3DVector* vMin, K3DVector* vMax, KColor sColor, K3DVector* vCenter, int nWidth, int nHeight, class SGame* pGame, bool bIsHigh )
|
|
{
|
|
///가로 세로 거리를 세그먼트로 나눈다
|
|
float fWidthLength = (vMax->x - vMin->x) / (float)(env_fx::c_WaterDetailSegment-1);
|
|
float fHeightLength = (vMin->y - vMax->y) / (float)(env_fx::c_WaterDetailSegment-1);
|
|
|
|
bool bCheck = false;
|
|
|
|
if( bIsHigh )
|
|
{
|
|
m_pVertex = new K3DVERTEX_H_WATER[env_fx::c_WaterDetailSegment*env_fx::c_WaterDetailSegment];
|
|
K3DVERTEX_H_WATER* pVertex = m_pVertex;
|
|
for( int h = 0; h < env_fx::c_WaterDetailSegment; ++h )
|
|
{
|
|
for( int w = 0; w < env_fx::c_WaterDetailSegment; ++w )
|
|
{
|
|
pVertex->p = K3DVector4( (float)(vMin->x + (w*fWidthLength) ), (float)( vMin->y - (h*fHeightLength) ), vMin->z, 1.0f );
|
|
if( bCheck == false )
|
|
{
|
|
float fHeight = 0.f;
|
|
WORD wTile=0;
|
|
bool bSucFindTerrain = pGame->GetHeight( pVertex->p.x+vCenter->x, pVertex->p.y+vCenter->y, fHeight,wTile );
|
|
if( bSucFindTerrain && fHeight <= vCenter->z )
|
|
{
|
|
//몰보다 높은게 존재 한다면 더이상 검사 할 필요가 없음
|
|
bCheck = true;
|
|
m_bCheckReservation = false;
|
|
}
|
|
}
|
|
++pVertex;
|
|
}
|
|
}
|
|
|
|
if( bCheck == false )
|
|
{
|
|
//지형을 못찾았다면 보류 대상
|
|
if( m_bCheckReservation == false )
|
|
m_bCheckReservation = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//이 세그먼트의 가로 세로의 거리를 구한후 미터로 환산한다
|
|
//환산한후 c_WaterDetailSegment( 세그먼트 개수 ) 로 나눠 주면 이 세그먼트에
|
|
//물을 몇장을 발라야 하는지 알수있음
|
|
float fTileCountX = ( (vMax->x - vMin->x) / (float)(GameRule::DEFAULT_UNIT_SIZE*6) ) / env_fx::c_WaterDetailSegment;
|
|
float fTileCountY = ( (vMin->y - vMax->y) / (float)(GameRule::DEFAULT_UNIT_SIZE*6) ) / env_fx::c_WaterDetailSegment;
|
|
|
|
//이전 Segment의 UV값을 유지해야한다
|
|
float fUVX = (fTileCountX * (env_fx::c_WaterDetailSegment-1)) * nWidth;
|
|
float fUVY = (fTileCountY * (env_fx::c_WaterDetailSegment-1)) * nHeight;
|
|
|
|
if( m_pVertex )
|
|
{
|
|
assert(false);
|
|
}
|
|
|
|
m_pVertex = new K3DVERTEX_H_WATER[env_fx::c_WaterDetailSegment*env_fx::c_WaterDetailSegment];
|
|
K3DVERTEX_H_WATER* pVertex = m_pVertex;
|
|
for( int h = 0; h < env_fx::c_WaterDetailSegment; ++h )
|
|
{
|
|
for( int w = 0; w < env_fx::c_WaterDetailSegment; ++w )
|
|
{
|
|
pVertex->p = K3DVector4( (float)(vMin->x + (w*fWidthLength) ), (float)( vMin->y - (h*fHeightLength) ), vMin->z, 1.0f );
|
|
// pVertex->normal = K3DVector( 0.f, 0.f, 1.f);
|
|
pVertex->color = sColor;
|
|
pVertex->tu2 = pVertex->tu = (float)( w * fTileCountX ) + fUVX;
|
|
pVertex->tv2 = pVertex->tv = (float)( h * fTileCountY ) + fUVY;
|
|
|
|
if( bCheck == false )
|
|
{
|
|
float fHeight = 0.f;
|
|
WORD wTile=0;
|
|
bool bSucFindTerrain = pGame->GetHeight( pVertex->p.x+vCenter->x, pVertex->p.y+vCenter->y, fHeight,wTile );
|
|
if( bSucFindTerrain && fHeight <= vCenter->z )
|
|
{
|
|
//몰보다 높은게 존재 한다면 더이상 검사 할 필요가 없음
|
|
bCheck = true;
|
|
m_bCheckReservation = false;
|
|
}
|
|
}
|
|
++pVertex;
|
|
}
|
|
}
|
|
|
|
if( bCheck == false )
|
|
{
|
|
//지형을 못찾았다면 보류 대상
|
|
if( m_bCheckReservation == false )
|
|
m_bCheckReservation = true;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WATER_DETAIL_SEGMENT::SetPrimitiveData( K3DINDEXED_WATER* pIndexed, K3DMatrix* pMatrix )
|
|
{
|
|
if( m_pPrimitive )
|
|
{
|
|
assert(false);
|
|
}
|
|
m_pPrimitive = new SLowQualityWaterPrimitive;
|
|
m_pPrimitive->SetCommonVertex( m_pVertex );
|
|
m_pPrimitive->SetCommonIndexed( pIndexed );
|
|
m_pPrimitive->SetTransform( pMatrix, pMatrix );
|
|
|
|
K3DVector vCenterPos;
|
|
vCenterPos.x = m_vMinVertex.x + ( ( m_vMaxVertex.x - m_vMinVertex.x ) / 2.0f );
|
|
vCenterPos.y = m_vMinVertex.y - ( ( m_vMinVertex.y - m_vMaxVertex.y ) / 2.0f );
|
|
vCenterPos.z = m_vMinVertex.z;
|
|
|
|
m_pPrimitive->SetTransparent( true );
|
|
m_pPrimitive->SetCenterPosition( vCenterPos );
|
|
m_pPrimitive->SetBlendMode( K3DMaterial::MBM_LQ_WATER );
|
|
}
|
|
|
|
void WATER_DETAIL_SEGMENT::SetVertexMinMax(K3DVector* vMin, K3DVector* vMax )
|
|
{
|
|
m_BoundCube = K3DBoundRotCube( vMax->x, vMin->x, vMax->y, vMin->y, (vMax->z+1.f), (vMin->z-1.f) );
|
|
m_vMinVertex = *vMin;
|
|
m_vMaxVertex = *vMax;
|
|
}
|
|
|
|
void WATER_DETAIL_SEGMENT::SetChangeColor( KColor Color )
|
|
{
|
|
K3DVERTEX_H_WATER* pVertex = m_pVertex;
|
|
for( int h = 0; h < env_fx::c_WaterDetailSegment; ++h )
|
|
{
|
|
for( int w = 0; w < env_fx::c_WaterDetailSegment; ++w )
|
|
{
|
|
pVertex->color = Color;
|
|
++pVertex;
|
|
}
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////
|
|
SWater::SWater( class SGame* pGame ) : m_pGame(pGame)
|
|
{
|
|
m_pHWaterPrimitive = NULL;
|
|
m_pIndexed = NULL;
|
|
m_spTextureArray = NULL;
|
|
m_pCamera = NULL;
|
|
m_dwStartTime = 0;
|
|
m_nMapX = 0;
|
|
m_nMapY = 0;
|
|
m_nSegMentCount = 0;
|
|
m_nWaterType = 0;
|
|
m_Color = KColor( 255, 255, 255, 255 );
|
|
m_bIsHighQualityWater = false;
|
|
m_vMinVertex = K3DVector( 0.0f, 0.0f, 0.0f );
|
|
m_vMaxVertex = K3DVector( 0.0f, 0.0f, 0.0f );
|
|
m_vCenterPoint = K3DVector( 0.0f, 0.0f, 0.0f );
|
|
|
|
m_fRadius = 0.f; //고사양용 스피어 반지름 값
|
|
|
|
m_fAniCount = 0.0f;
|
|
m_dwChangeTime = 50;
|
|
|
|
|
|
m_bTextureAnimation = true;
|
|
m_bUVAnimation = false;
|
|
|
|
m_dwUAniTime = 30;
|
|
m_dwVAniTime = 0;
|
|
m_dwStartUTime = 0;
|
|
m_dwStartVTime = 0;
|
|
|
|
m_fUCoord = 0.0f;
|
|
m_fVCoord = 0.0f;
|
|
}
|
|
|
|
SWater::~SWater()
|
|
{
|
|
m_spTextureArray = NULL;
|
|
m_pCamera = NULL;
|
|
|
|
SAFE_DELETE( m_pPrimitive );
|
|
SAFE_DELETE_ARRAY(m_pIndexed);
|
|
SAFE_DELETE_ARRAY(m_pHWaterPrimitive);
|
|
|
|
std::vector< WATER_DETAIL_SEGMENT* >::iterator iter = m_vWaterSegment.begin();
|
|
for( ; iter != m_vWaterSegment.end(); )
|
|
{
|
|
SAFE_DELETE( (*iter) );
|
|
iter = m_vWaterSegment.erase( iter );
|
|
}
|
|
}
|
|
|
|
void SWater::Init( K3DRenderDevice *pDevice, K3DIndexBuffer * pIndexBuf )
|
|
{
|
|
}
|
|
|
|
//고사양 물
|
|
void SWater::CreateSegment( K3DVector* vLeftTop, K3DVector* vRightBottom, K3DVector* vCenter )
|
|
{
|
|
//컬링용 바운드 큐브 만들기
|
|
m_vMinVertex = K3DVector( vLeftTop->x - 0.5f, vLeftTop->y + 0.5f, vLeftTop->z );
|
|
m_vMaxVertex = K3DVector( vRightBottom->x + 0.5f, vRightBottom->y - 0.5f, vRightBottom->z );
|
|
m_BoundCube = K3DBoundRotCube( m_vMaxVertex.x, m_vMinVertex.x, m_vMaxVertex.y, m_vMinVertex.y, (m_vMaxVertex.z + 1.f), (m_vMinVertex.z - 1.f) );
|
|
|
|
m_vCenterPoint.x = m_vMinVertex.x + ( ( m_vMaxVertex.x - m_vMinVertex.x ) / 2.0f );
|
|
m_vCenterPoint.y = m_vMinVertex.y - ( ( m_vMinVertex.y - m_vMaxVertex.y ) / 2.0f );
|
|
m_vCenterPoint.z = m_vMinVertex.z;
|
|
|
|
m_fRadius = K3DVectorLength( m_vCenterPoint - m_vMinVertex );
|
|
|
|
m_bIsHighQualityWater = true;
|
|
|
|
if( m_pHWaterPrimitive == NULL )
|
|
{
|
|
m_pHWaterPrimitive = new K3DVERTEX_H_WATER[ SHighQualityWaterPrimitive::NUM_SEGMENTS * 2 ];
|
|
m_pPrimitive = new SHighQualityWaterPrimitive;
|
|
m_pPrimitive->SetCommonVertex(m_pHWaterPrimitive);
|
|
m_pPrimitive->SetHQWaterHeight(vCenter->z);
|
|
m_pPrimitive->SetTransparent( true );
|
|
m_pPrimitive->SetCenterPosition( m_vCenterPoint );
|
|
m_pPrimitive->SetBlendMode( K3DMaterial::MBM_HQ_WATER );
|
|
}
|
|
|
|
int nNumSegment = SHighQualityWaterPrimitive::NUM_SEGMENTS;
|
|
|
|
float fStartU1 = 1.0f;
|
|
float fIncU1 = -1.0f / ( float ) ( nNumSegment - 1 );
|
|
float fV1[ 2 ] = { 0.0f, 1.0f };
|
|
|
|
float fU2[ 2 ] = { 1.0f, 0.0f };
|
|
float fStartV2 = 1.0f;
|
|
float fIncV2 = -1.0f / ( float ) ( nNumSegment - 1 );
|
|
|
|
K3DVector normal( 0.0f, 0.0f, 1.0f );
|
|
for( int i = 0; i < SHighQualityWaterPrimitive::NUM_SEGMENTS * 2; i ++ )
|
|
{
|
|
// m_pHWaterPrimitive[ i ].normal = normal;
|
|
m_pHWaterPrimitive[ i ].color = m_Color;//( DWORD ) D3DCOLOR_ARGB( m_Color.a, m_Color.r, m_Color.g, m_Color.b );
|
|
m_pHWaterPrimitive[ i ].tu = fStartU1 + fIncU1 * ( float ) ( i / 2 );
|
|
m_pHWaterPrimitive[ i ].tv = fV1[ i % 2 ];
|
|
m_pHWaterPrimitive[ i ].tu2 = fU2[ i % 2 ];
|
|
m_pHWaterPrimitive[ i ].tv2 = fStartV2 + fIncV2 * ( float ) ( i / 2 );
|
|
}
|
|
|
|
int iWidth = 32; // 물 반사 맵 은 가로 32개 정도 쪼개자
|
|
int iHeight = 32; // 물 반사 맵 은 세로 32개 정도 쪼개자
|
|
|
|
//느슨하게 만들자
|
|
float flooseX = (vRightBottom->x - vLeftTop->x) / pow((double)2,5);
|
|
float flooseY = (vLeftTop->y - vRightBottom->y) / pow((double)2,5);
|
|
|
|
//세크먼트 개수
|
|
m_nSegMentCount = iWidth*iHeight;
|
|
|
|
//간격 구하기
|
|
float fWidthLength = (vRightBottom->x - vLeftTop->x) / iWidth;
|
|
float fHeightLength = (vLeftTop->y - vRightBottom->y) / iHeight;
|
|
|
|
float fWidthCenter = (vRightBottom->x - vLeftTop->x) / 2.f;
|
|
float fHeightCenter = (vLeftTop->y - vRightBottom->y) / 2.f;
|
|
|
|
for( int h = 0; h < iHeight; ++h )
|
|
{
|
|
for( int w = 0; w < iWidth; ++w )
|
|
{
|
|
WATER_DETAIL_SEGMENT* pWaterSegment = new WATER_DETAIL_SEGMENT;
|
|
K3DVector vMin = K3DVector( (float)(-fWidthCenter) + (w*fWidthLength), (float)( fHeightCenter - (h*fHeightLength) ), 0.f);
|
|
K3DVector vMax = K3DVector( (float)(-fWidthCenter) + ((w+1)*fWidthLength), (float)( fHeightCenter - ((h+1)*fHeightLength) ), 0.f);
|
|
bool bSuc = pWaterSegment->CreateDetailSegment( &vMin, &vMax, m_Color, &m_vCenterPoint, w, h, m_pGame, true );
|
|
|
|
pWaterSegment->SetVertexMinMax( &K3DVector( (vMin.x + m_vCenterPoint.x)-flooseX, (vMin.y + m_vCenterPoint.y)+flooseY, m_vCenterPoint.z ),
|
|
&K3DVector( (vMax.x + m_vCenterPoint.x)+flooseX, (vMax.y + m_vCenterPoint.y)-flooseY, m_vCenterPoint.z ) );
|
|
|
|
if( bSuc ) m_vWaterSegment.push_back( pWaterSegment );
|
|
else SAFE_DELETE( pWaterSegment );
|
|
}
|
|
}
|
|
}
|
|
|
|
//저사양 물
|
|
void SWater::CreateSegment( K3DVector* vLeftTop, K3DVector* vRightBottom, K3DVector* vCenter, float fTileLength )
|
|
{
|
|
//가로 세로 크기를 구한다
|
|
int iWidth = (int)((vRightBottom->x - vLeftTop->x)/fTileLength);
|
|
int iHeight = (int)((vLeftTop->y - vRightBottom->y)/fTileLength);
|
|
float fDepth = 1;
|
|
if( iWidth >= 32 && iHeight >= 32 )
|
|
{
|
|
iWidth = 32;
|
|
iHeight = 32;
|
|
fDepth = 5;
|
|
}
|
|
else if( iWidth >= 16 && iHeight >= 16 )
|
|
{
|
|
iWidth = 16;
|
|
iHeight = 16;
|
|
fDepth = 4;
|
|
}
|
|
else if( iWidth >= 8 && iHeight >= 8 )
|
|
{
|
|
iWidth = 8;
|
|
iHeight = 8;
|
|
fDepth = 3;
|
|
}
|
|
else
|
|
{
|
|
iWidth = 4;
|
|
iHeight = 4;
|
|
fDepth = 2;
|
|
}
|
|
|
|
//느슨하게 만들자
|
|
float flooseX = (vRightBottom->x - vLeftTop->x) / pow((double)2,(double)fDepth);
|
|
float flooseY = (vLeftTop->y - vRightBottom->y) / pow((double)2,(double)fDepth);
|
|
|
|
iWidth -= 1;
|
|
iHeight -= 1;
|
|
|
|
//컬링용 바운드 큐브 만들기
|
|
m_vMinVertex = K3DVector( vLeftTop->x - 0.5f, vLeftTop->y + 0.5f, vLeftTop->z );
|
|
m_vMaxVertex = K3DVector( vRightBottom->x + 0.5f, vRightBottom->y - 0.5f, vRightBottom->z );
|
|
m_BoundCube = K3DBoundRotCube( m_vMaxVertex.x, m_vMinVertex.x, m_vMaxVertex.y, m_vMinVertex.y, (m_vMaxVertex.z + 1.f), (m_vMinVertex.z - 1.f) );
|
|
m_vCenterPoint = *vCenter;
|
|
|
|
//세크먼트 개수
|
|
m_nSegMentCount = iWidth*iHeight;
|
|
|
|
//간격 구하기
|
|
float fWidthLength = (vRightBottom->x - vLeftTop->x) / iWidth;
|
|
float fHeightLength = (vLeftTop->y - vRightBottom->y) / iHeight;
|
|
|
|
float fWidthCenter = (vRightBottom->x - vLeftTop->x) / 2.f;
|
|
float fHeightCenter = (vLeftTop->y - vRightBottom->y) / 2.f;
|
|
|
|
int h;
|
|
for( h = 0; h < iHeight; ++h )
|
|
{
|
|
for( int w = 0; w < iWidth; ++w )
|
|
{
|
|
WATER_DETAIL_SEGMENT* pWaterSegment = new WATER_DETAIL_SEGMENT;
|
|
K3DVector vMin = K3DVector( (float)(-fWidthCenter) + (w*fWidthLength), (float)( fHeightCenter - (h*fHeightLength) ), 0.f);
|
|
K3DVector vMax = K3DVector( (float)(-fWidthCenter) + ((w+1)*fWidthLength), (float)( fHeightCenter - ((h+1)*fHeightLength) ), 0.f);
|
|
bool bSuc = pWaterSegment->CreateDetailSegment( &vMin, &vMax, m_Color, &m_vCenterPoint, w, h, m_pGame );
|
|
|
|
pWaterSegment->SetVertexMinMax( &K3DVector( vMin.x + m_vCenterPoint.x-flooseX, vMin.y + m_vCenterPoint.y+flooseY, m_vCenterPoint.z ),
|
|
&K3DVector( vMax.x + m_vCenterPoint.x+flooseX, vMax.y + m_vCenterPoint.y-flooseY, m_vCenterPoint.z ) );
|
|
|
|
if( bSuc ) m_vWaterSegment.push_back( pWaterSegment );
|
|
else SAFE_DELETE( pWaterSegment );
|
|
}
|
|
}
|
|
|
|
//공용으로 사용될 인덱스
|
|
m_pIndexed = new K3DINDEXED_WATER[env_fx::c_WaterDetailSegmentIndexedCount];
|
|
K3DINDEXED_WATER* pIndexed = m_pIndexed;
|
|
for( h = 0; h < (env_fx::c_WaterDetailSegment-1); ++h )
|
|
{
|
|
for( int w = 0; w < (env_fx::c_WaterDetailSegment-1); ++w )
|
|
{
|
|
pIndexed->a = (WORD)((env_fx::c_WaterDetailSegment*h)+w);
|
|
pIndexed->b = (WORD)((env_fx::c_WaterDetailSegment*h)+w+1);
|
|
pIndexed->c = (WORD)((env_fx::c_WaterDetailSegment*(h+1))+w);
|
|
++pIndexed;
|
|
|
|
pIndexed->a = (WORD)((env_fx::c_WaterDetailSegment*h)+w+1);
|
|
pIndexed->b = (WORD)((env_fx::c_WaterDetailSegment*(h+1))+w+1);
|
|
pIndexed->c = (WORD)((env_fx::c_WaterDetailSegment*(h+1))+w);
|
|
++pIndexed;
|
|
}
|
|
}
|
|
|
|
K3DMatrixIdentity( m_matWorld );
|
|
K3DMatrixTranslation( m_matWorld, m_vCenterPoint.x, m_vCenterPoint.y, m_vCenterPoint.z );
|
|
|
|
std::vector< WATER_DETAIL_SEGMENT* >::iterator iter = m_vWaterSegment.begin();
|
|
for( ; iter != m_vWaterSegment.end(); ++iter )
|
|
(*iter)->SetPrimitiveData( m_pIndexed, &m_matWorld );
|
|
}
|
|
|
|
//사용될 텍스처 세트 및 심리스 월드 좌표
|
|
void SWater::SetWaterInfoData( int nWaterType, int nMapX, int nMapY, K3DCamera* pCamera, WATER_TEXTURE_SET* pTextureSet )
|
|
{
|
|
m_nWaterType = nWaterType;
|
|
m_nMapX = nMapX;
|
|
m_nMapY = nMapY;
|
|
m_pCamera = pCamera;
|
|
|
|
if( pTextureSet )
|
|
m_spTextureArray = pTextureSet->GetTextureSet();
|
|
}
|
|
|
|
void SWater::Process( DWORD dwTime )
|
|
{
|
|
if(m_pHWaterPrimitive) { return; }
|
|
|
|
if( m_bTextureAnimation )
|
|
{
|
|
if( m_dwChangeTime > 0 )
|
|
{
|
|
if( m_dwStartTime == 0 ) m_dwStartTime = dwTime;
|
|
|
|
m_fAniCount = (float)( (dwTime - m_dwStartTime) / m_dwChangeTime );
|
|
if( (int)m_fAniCount >= cMaxWaterTexture )
|
|
{
|
|
m_fAniCount = 0.0f;
|
|
m_dwStartTime = dwTime;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_dwStartTime = 0;
|
|
}
|
|
|
|
if( m_bUVAnimation )
|
|
{
|
|
float fTime = 0.0f;
|
|
if( m_dwUAniTime > 0 )
|
|
{
|
|
if( m_dwStartUTime == 0 ) m_dwStartUTime = dwTime;
|
|
m_fUCoord = (float)((dwTime - m_dwStartUTime) / m_dwUAniTime) * 0.01f;
|
|
if( m_fUCoord > 1.0f )
|
|
{
|
|
m_fUCoord = 0.0f;
|
|
m_dwStartUTime = dwTime;
|
|
}
|
|
}
|
|
|
|
if( m_dwVAniTime > 0 )
|
|
{
|
|
if( m_dwStartVTime == 0 ) m_dwStartVTime = dwTime;
|
|
m_fVCoord = (float)((dwTime - m_dwStartVTime) / m_dwVAniTime) * 0.01f;
|
|
if( m_fVCoord > 1.0f )
|
|
{
|
|
m_fVCoord = 0.0f;
|
|
m_dwStartVTime = dwTime;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_dwStartUTime = 0;
|
|
m_dwStartVTime = 0;
|
|
m_fUCoord = 0.0f;
|
|
m_fVCoord = 0.0f;
|
|
}
|
|
}
|
|
|
|
void SWater::Render( KViewportObject *viewport )
|
|
{
|
|
bool bCheckCameraInWater = false;
|
|
float fHeight = 0.f;
|
|
|
|
std::vector< WATER_DETAIL_SEGMENT* >::iterator iter = m_vWaterSegment.begin();
|
|
if(m_pHWaterPrimitive)
|
|
{
|
|
bool bRenderHQWater = false;
|
|
for( ; iter != m_vWaterSegment.end(); )
|
|
{
|
|
//세부 세그먼트 컬링
|
|
bool bVisible = KPCCP::nonuniformcube_collide_nonuniformcube(viewport->GetFrustum(), (*iter)->GetBoundCube() );
|
|
if( !bVisible ) { ++iter; continue; }
|
|
|
|
if( CheckDistance( &m_pCamera->GetTargetPos(), (*iter)->GetMinVertex(), (*iter)->GetMaxVertex() ) )//거리 체크
|
|
{
|
|
bRenderHQWater = true;
|
|
|
|
if( !bCheckCameraInWater )
|
|
{
|
|
if( CheckCameraInWater( (*iter)->GetMinVertex(), (*iter)->GetMaxVertex(), m_pCamera ) )
|
|
{
|
|
bCheckCameraInWater = true;
|
|
|
|
if( viewport->GetWaterHeight() < (*iter)->GetMinVertex()->z )
|
|
{
|
|
viewport->SetWaterHeight( true, (*iter)->GetMinVertex()->z );
|
|
|
|
if( CheckCameraWaterHeight( (*iter)->GetMinVertex(), (*iter)->GetMaxVertex(), m_pCamera ) )
|
|
viewport->SetInsideWater( true );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
//if( m_spTextureArray[ m_cAniCount ] ) m_pPrimitive->SetTexture( 2, m_spTextureArray[ m_cAniCount ] );
|
|
//else m_pPrimitive->SetTexture( 2, NULL );
|
|
|
|
if( !CheckReservation( (*iter) ) )
|
|
{
|
|
SAFE_DELETE( (*iter) );
|
|
iter = m_vWaterSegment.erase( iter );
|
|
continue;
|
|
}
|
|
}
|
|
++iter;
|
|
}
|
|
|
|
if( bRenderHQWater )
|
|
{
|
|
// sonador 7.0.14 카메라 위치에 따른 물효과 컬링 문제 수정
|
|
viewport->Register( m_pPrimitive , KRenderObject::RENDEREFX_WATER );
|
|
viewport->SetRenderWater(true);
|
|
}
|
|
else
|
|
viewport->SetRenderWater(false);
|
|
|
|
return;
|
|
}
|
|
|
|
for( ; iter != m_vWaterSegment.end(); )
|
|
{
|
|
//세부 세그먼트 컬링
|
|
bool bVisible = KPCCP::nonuniformcube_collide_nonuniformcube( viewport->GetFrustum(), (*iter)->GetBoundCube() );
|
|
if( !bVisible ) { ++iter; continue; }
|
|
|
|
if( CheckDistance( &m_pCamera->GetTargetPos(), (*iter)->GetMinVertex(), (*iter)->GetMaxVertex() ) )//거리 체크
|
|
{
|
|
if( !bCheckCameraInWater )
|
|
{
|
|
//카메라가 물영역 안에 있는지 검사
|
|
if( CheckCameraInWater( (*iter)->GetMinVertex(), (*iter)->GetMaxVertex(), m_pCamera ) )
|
|
{
|
|
bCheckCameraInWater = true;
|
|
|
|
if( viewport->GetWaterHeight() < (*iter)->GetMinVertex()->z )
|
|
{
|
|
viewport->SetWaterHeight( true, (*iter)->GetMinVertex()->z );
|
|
|
|
//수면 밑으로 카메라가 들어갔다면
|
|
if( CheckCameraWaterHeight( (*iter)->GetMinVertex(), (*iter)->GetMaxVertex(), m_pCamera ) )
|
|
viewport->SetInsideWater( true );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( CheckReservation( (*iter) ) )
|
|
{
|
|
SEnvPrimitive* pPrimitive = (*iter)->GetPrimitive();
|
|
|
|
assert( pPrimitive );
|
|
|
|
if( pPrimitive )
|
|
{
|
|
if(m_spTextureArray[(int)m_fAniCount] != NULL) pPrimitive->SetTexture(0, m_spTextureArray[(int)m_fAniCount]);
|
|
else pPrimitive->SetTexture(0, NULL );
|
|
|
|
/* pPrimitive->SetTextureStage(0, m_spTextureArray[0] );
|
|
pPrimitive->SetTextureStage(1, m_spTextureArray[1] );*/
|
|
|
|
pPrimitive->SetTextureUVAnimation( m_fUCoord, m_fVCoord );
|
|
// sonador 7.0.14 카메라 위치에 따른 물효과 컬링 문제 수정
|
|
viewport->Register( pPrimitive , KRenderObject::RENDEREFX_WATER );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SAFE_DELETE( (*iter) );
|
|
iter = m_vWaterSegment.erase( iter );
|
|
continue;
|
|
}
|
|
}
|
|
++iter;
|
|
}
|
|
}
|
|
|
|
bool SWater::CheckReservation( WATER_DETAIL_SEGMENT* pDetail )
|
|
{
|
|
if( !pDetail->IsCheckReservation() ) return true;
|
|
|
|
const K3DVERTEX_H_WATER* pVertex = pDetail->GetVertex();
|
|
for( int h = 0; h < env_fx::c_WaterDetailSegment; ++h )
|
|
{
|
|
for( int w = 0; w < env_fx::c_WaterDetailSegment; ++w )
|
|
{
|
|
float fHeight = 0.f;
|
|
WORD wTile=0;
|
|
bool bSucFindTerrain = m_pGame->GetHeight( pVertex->p.x + m_vCenterPoint.x, pVertex->p.y + m_vCenterPoint.y, fHeight,wTile );
|
|
if( bSucFindTerrain )
|
|
{
|
|
//지형보다 높다면
|
|
if( fHeight <= m_vCenterPoint.z )
|
|
{
|
|
pDetail->SetCheckReservation(false);
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
return true; //여전히 찾기 실패 했다면 기냥 그리자
|
|
|
|
++pVertex;
|
|
}
|
|
}
|
|
|
|
//지형 보다 높은 폴리곤이 없다면 삭제한다
|
|
return false;
|
|
}
|
|
|
|
void SWater::SetChangeColor( KColor Color, bool bNewColor )
|
|
{
|
|
if(m_pHWaterPrimitive) return;
|
|
|
|
std::vector< WATER_DETAIL_SEGMENT* >::iterator iter = m_vWaterSegment.begin();
|
|
for( ; iter != m_vWaterSegment.end(); ++iter )
|
|
{
|
|
if( bNewColor ) (*iter)->SetChangeColor( Color );
|
|
else (*iter)->SetChangeColor( m_Color );
|
|
}
|
|
}
|
|
|
|
void SWater::SetChangeTextureTime( DWORD dwTime )
|
|
{
|
|
m_dwChangeTime = dwTime;
|
|
}
|
|
|
|
K3DVector* SWater::GetBoundCube()
|
|
{
|
|
return (K3DVector*)m_BoundCube.GetVertices();
|
|
}
|
|
|
|
void SWater::SetHqWaterColor( BYTE r, BYTE g, BYTE b, BYTE a )
|
|
{
|
|
DWORD dwColor = ( DWORD ) b | ( DWORD ) g << 8 | ( DWORD ) r << 16 | ( DWORD ) a << 24;
|
|
|
|
if( m_pHWaterPrimitive )
|
|
{
|
|
for ( int i = 0; i < SHighQualityWaterPrimitive::NUM_SEGMENTS * 2; i++ )
|
|
m_pHWaterPrimitive[ i ].color = dwColor;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////
|
|
SGameLowQualityWater::SGameLowQualityWater()
|
|
{
|
|
m_pGame = NULL;
|
|
m_pCamera = NULL;
|
|
}
|
|
|
|
SGameLowQualityWater::~SGameLowQualityWater()
|
|
{
|
|
std::vector< SWater* >::iterator vWaterPrimitive = m_vWaterPrimitive.begin();
|
|
for( ; vWaterPrimitive != m_vWaterPrimitive.end(); )
|
|
{
|
|
SAFE_DELETE( (*vWaterPrimitive) );
|
|
vWaterPrimitive = m_vWaterPrimitive.erase(vWaterPrimitive);
|
|
}
|
|
m_vWaterPrimitive.clear();
|
|
|
|
std::vector< WATER_TEXTURE_SET* >::iterator vTextureSet = m_vTextureSet.begin();
|
|
for( ; vTextureSet != m_vTextureSet.end(); )
|
|
{
|
|
SAFE_DELETE( (*vTextureSet) );
|
|
vTextureSet = m_vTextureSet.erase(vTextureSet);
|
|
}
|
|
m_vTextureSet.clear();
|
|
|
|
m_pGame = NULL;
|
|
m_pCamera = NULL;
|
|
}
|
|
|
|
bool SGameLowQualityWater::Init()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void SGameLowQualityWater::AddLowQualityWater( int nMapX, int nMapY, WATERAREA_HEADER* pWaterInfo, float fTileLength )
|
|
{
|
|
LowQualityWater* pLowQualityWaterData = GetLowQualityWaterDB().GetLowQualityWaterData( pWaterInfo->nWaterType );
|
|
if( pLowQualityWaterData == NULL )
|
|
{
|
|
assert( false && "물정보가 없습니다." );
|
|
_oprint( "물정보가 없습니다. %d\n", pWaterInfo->nWaterType );
|
|
}
|
|
|
|
WATER_TEXTURE_SET* pTextureSet = GetTextureSetData( pWaterInfo->nWaterType );
|
|
//텍스처 세트가 없다면
|
|
if( pTextureSet == NULL )
|
|
{
|
|
pTextureSet = new WATER_TEXTURE_SET;
|
|
pTextureSet->CreateTextureSet( pWaterInfo->nWaterType, pLowQualityWaterData ); //텍스처 이름 DB에서 읽어오자
|
|
m_vTextureSet.push_back(pTextureSet);
|
|
}
|
|
|
|
SWater* pWater = new SWater( m_pGame );
|
|
if( pLowQualityWaterData )
|
|
{
|
|
pWater->SetColor( KColor(pLowQualityWaterData->r, pLowQualityWaterData->g, pLowQualityWaterData->b, pLowQualityWaterData->a) );
|
|
pWater->SetChangeTimeTexture( pLowQualityWaterData->texture_change_time );
|
|
}
|
|
|
|
pWater->CreateSegment(&pWaterInfo->vLeftTop, &pWaterInfo->vRightBottom, &pWaterInfo->vCenter, fTileLength);
|
|
pWater->SetWaterInfoData( pWaterInfo->nWaterType, nMapX, nMapY, m_pCamera, pTextureSet );
|
|
m_vWaterPrimitive.push_back(pWater);
|
|
}
|
|
|
|
void SGameLowQualityWater::AddHighQualityWater( int nMapX, int nMapY, struct WATERAREA_HEADER* pWaterInfo )
|
|
{
|
|
LowQualityWater* pLowQualityWaterData = GetLowQualityWaterDB().GetLowQualityWaterData( pWaterInfo->nWaterType );
|
|
if( pLowQualityWaterData == NULL )
|
|
{
|
|
assert( false && "물정보가 없습니다." );
|
|
_oprint( "물정보가 없습니다. %d\n", pWaterInfo->nWaterType );
|
|
}
|
|
|
|
//// 임시코드 by blackfish ->
|
|
//WATER_TEXTURE_SET* pTextureSet = GetTextureSetData( pWaterInfo->nWaterType );
|
|
////텍스처 세트가 없다면
|
|
//if( pTextureSet == NULL )
|
|
//{
|
|
// pTextureSet = new WATER_TEXTURE_SET;
|
|
// pTextureSet->CreateTextureSet( pWaterInfo->nWaterType, pLowQualityWaterData ); //텍스처 이름 DB에서 읽어오자
|
|
// m_vTextureSet.push_back(pTextureSet);
|
|
//}
|
|
//// <- 임시코드 by blackfish
|
|
|
|
SWater* pWater = new SWater( m_pGame );
|
|
if( pLowQualityWaterData )
|
|
pWater->SetColor( KColor(pLowQualityWaterData->r, pLowQualityWaterData->g, pLowQualityWaterData->b, pLowQualityWaterData->a) );
|
|
else
|
|
pWater->SetColor( KColor(255, 255, 255, 255) ); //컬러값 DB에서 읽어 오자
|
|
|
|
pWater->CreateSegment(&pWaterInfo->vLeftTop, &pWaterInfo->vRightBottom, &pWaterInfo->vCenter);
|
|
//pWater->SetWaterInfoData( 0, nMapX, nMapY, m_pCamera, pTextureSet );
|
|
pWater->SetWaterInfoData( 0, nMapX, nMapY, m_pCamera );
|
|
pWater->SetHighQualityWater(true);
|
|
m_vWaterPrimitive.push_back(pWater);
|
|
}
|
|
|
|
void SGameLowQualityWater::SetGame( SGame* pGame )
|
|
{
|
|
m_pGame = pGame;
|
|
}
|
|
|
|
void SGameLowQualityWater::SetCamera( K3DCamera* pCamera )
|
|
{
|
|
m_pCamera = pCamera;
|
|
}
|
|
|
|
//높낮이 체크해서 렌더 할지 결정한다
|
|
bool SGameLowQualityWater::CheckHeight( K3DVector* vMin, K3DVector* vMax, K3DVector* vCenter )
|
|
{
|
|
K3DVector vCampos = m_pCamera->GetCamPos();
|
|
K3DVector vTarPos = m_pCamera->GetTargetPos();
|
|
|
|
bool bInsideCam = false;
|
|
bool bInsideTar = false;
|
|
|
|
// 카메라 포스와 타겟이 물 사각 안에 있는지 검사
|
|
if( vMin->x <= vCampos.x && vMin->y >= vCampos.y &&
|
|
vMax->x >= vCampos.x && vMax->y <= vCampos.y )
|
|
{
|
|
bInsideCam = true;
|
|
}
|
|
if( vMin->x <= vTarPos.x && vMin->y >= vTarPos.y &&
|
|
vMax->x >= vTarPos.x && vMax->y <= vTarPos.y )
|
|
{
|
|
bInsideTar = true;
|
|
}
|
|
|
|
//카메라 포스나 타겟의 위치가 물 사각안에 있다면 리턴 true
|
|
if( bInsideCam || bInsideTar ) return true;
|
|
|
|
//카메라 포스나 타겟 둘중 하나가 물의 높이보다 높다면 리턴 true
|
|
if( vCenter->z < vCampos.z || vCenter->z < vTarPos.z )
|
|
return true;
|
|
|
|
//둘다 물 높이 보다 작다면 리턴 false
|
|
return false;
|
|
}
|
|
|
|
void SGameLowQualityWater::Process( DWORD dwTime, float fTerrainVisibleDistance )
|
|
{
|
|
std::vector< SWater* >::iterator iter = m_vWaterPrimitive.begin();
|
|
for( ; iter != m_vWaterPrimitive.end(); ++iter )
|
|
{
|
|
(*iter)->Process( dwTime );
|
|
}
|
|
|
|
cTerrainVisibleDistance = m_fTerrainVisibleDistance = fTerrainVisibleDistance;
|
|
}
|
|
|
|
void SGameLowQualityWater::Render( KViewportObject *viewport )
|
|
{
|
|
viewport->SetWaterHeight( false );
|
|
viewport->SetInsideWater( false );
|
|
|
|
bool bSetRenderHqWater = false;
|
|
std::vector< SWater* >::iterator iter = m_vWaterPrimitive.begin();
|
|
for( ; iter != m_vWaterPrimitive.end(); ++iter )
|
|
{
|
|
SWater* pWater = (*iter);
|
|
|
|
bool bVisible = KPCCP::nonuniformcube_collide_nonuniformcube(viewport->GetFrustum(), pWater->GetBoundCube() );
|
|
if(bVisible)
|
|
{
|
|
if( CheckHeight( pWater->GetMinVertex(), pWater->GetMaxVertex(), pWater->GetCenterPoint() ) )
|
|
{
|
|
pWater->Render( viewport );
|
|
if( pWater->IsHighQualityWater() ) //고사양 물일경우 렌더 여부 체크
|
|
bSetRenderHqWater = true;
|
|
}
|
|
else if( pWater->IsHighQualityWater() )
|
|
{
|
|
viewport->SetRenderWater( bSetRenderHqWater );
|
|
}
|
|
}
|
|
else if( pWater->IsHighQualityWater() )
|
|
{
|
|
viewport->SetRenderWater( bSetRenderHqWater );
|
|
}
|
|
}
|
|
}
|
|
|
|
void SGameLowQualityWater::RemoveWater( int nMapX, int nMapY )
|
|
{
|
|
std::vector< SWater* >::iterator iter = m_vWaterPrimitive.begin();
|
|
for( ; iter != m_vWaterPrimitive.end(); )
|
|
{
|
|
// _oprint( "RemoveWater : %d\n", (*iter)->GetWaterType() );
|
|
|
|
if( (*iter)->CheckMap(nMapX, nMapY) )
|
|
{
|
|
//저사양 물만 텍스쳐셋을 갖고 있음.
|
|
if( !(*iter)->IsHighQualityWater() )
|
|
RemoveTextureSet( (*iter)->GetWaterType() );
|
|
|
|
SAFE_DELETE( (*iter) );
|
|
iter = m_vWaterPrimitive.erase(iter);
|
|
}
|
|
else
|
|
++iter;
|
|
}
|
|
}
|
|
|
|
WATER_TEXTURE_SET* SGameLowQualityWater::GetTextureSetData( int nWaterType )
|
|
{
|
|
std::vector< WATER_TEXTURE_SET* >::iterator iter = m_vTextureSet.begin();
|
|
for(; iter != m_vTextureSet.end(); ++iter )
|
|
{
|
|
if( (*iter)->GetWaterType() == nWaterType )
|
|
return (*iter);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void SGameLowQualityWater::RemoveTextureSet( int nWaterType )
|
|
{
|
|
std::vector< WATER_TEXTURE_SET* >::iterator iter = m_vTextureSet.begin();
|
|
for(; iter != m_vTextureSet.end(); )
|
|
{
|
|
// _oprint( "WaterType() : %d\n", nWaterType );
|
|
|
|
if( (*iter)->GetWaterType() == nWaterType )
|
|
{
|
|
if( (*iter)->Release() )
|
|
{
|
|
SAFE_DELETE((*iter));
|
|
iter = m_vTextureSet.erase(iter);
|
|
continue;
|
|
}
|
|
}
|
|
++iter;
|
|
}
|
|
}
|
|
|
|
void SGameLowQualityWater::SetLowQualityWaterColor( KColor Color, bool bNewColor )
|
|
{
|
|
std::vector< SWater* >::iterator iter = m_vWaterPrimitive.begin();
|
|
for( ; iter != m_vWaterPrimitive.end(); ++iter )
|
|
{
|
|
(*iter)->SetChangeColor( Color, bNewColor );
|
|
}
|
|
}
|
|
|
|
void SGameLowQualityWater::SetLowQualityWaterChangeTextureTime( DWORD dwTime )
|
|
{
|
|
std::vector< SWater* >::iterator iter = m_vWaterPrimitive.begin();
|
|
for( ; iter != m_vWaterPrimitive.end(); ++iter )
|
|
{
|
|
(*iter)->SetChangeTextureTime( dwTime );
|
|
}
|
|
}
|
|
|
|
SWater* SGameLowQualityWater::GetHightQualityWater()
|
|
{
|
|
std::vector< SWater* >::iterator iter = m_vWaterPrimitive.begin();
|
|
for( ; iter != m_vWaterPrimitive.end(); ++iter )
|
|
{
|
|
if( (*iter)->IsHighQualityWater() )
|
|
return (*iter);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool SGameLowQualityWater::PlayerInsideWaterExistence( K3DVector & vPlayerPos )
|
|
{
|
|
std::vector< SWater* >::iterator iter = m_vWaterPrimitive.begin();
|
|
for( ; iter != m_vWaterPrimitive.end(); ++iter )
|
|
{
|
|
SWater* pWater = (*iter);
|
|
if( CheckPlayerInWater( pWater->GetMinVertex(), pWater->GetMaxVertex(), m_pCamera, vPlayerPos ) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool SGameLowQualityWater::GetWaterHeight( K3DVector & vPlayerPos, float & fHeight )
|
|
{
|
|
std::vector< SWater* >::iterator iter = m_vWaterPrimitive.begin();
|
|
for( ; iter != m_vWaterPrimitive.end(); ++iter )
|
|
{
|
|
SWater* pWater = (*iter);
|
|
if( CheckPlayerInWater( pWater->GetMinVertex(), pWater->GetMaxVertex(), m_pCamera, vPlayerPos ) )
|
|
{
|
|
fHeight = pWater->GetMinVertex()->z;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// { [sonador][COLLIDABLE_CAMERA]
|
|
bool SGameLowQualityWater::GetLineCrossedPoint( const K3DVector& vNear, const K3DVector& vFar, const float fRadius, float& fNearestT, K3DVector& p )
|
|
{
|
|
// infinite
|
|
if( vNear.z == vFar.z ) return false;
|
|
|
|
K3DVector intersection, candidate, min, max;
|
|
|
|
std::vector< SWater* >::iterator itEnd = m_vWaterPrimitive.end();
|
|
for( std::vector< SWater* >::iterator it = m_vWaterPrimitive.begin();
|
|
it != itEnd; ++it )
|
|
{
|
|
SWater* pWater = (*it);
|
|
min = *pWater->GetMinVertex();
|
|
max = *pWater->GetMaxVertex();
|
|
|
|
if( min.x > max.x ) std::swap( min.x, max.x );
|
|
if( min.y > max.y ) std::swap( min.y, max.y );
|
|
|
|
min.z += fRadius;
|
|
max.z += fRadius;
|
|
|
|
// fast culling
|
|
// xxxx|xxxxxxxxx|xxxx
|
|
// xxxx|xxxxxxxxx|xxxx
|
|
// ----+---------+----
|
|
// xxxx| |xxxx
|
|
// xxxx| |xxxx
|
|
// xxxx| |xxxx
|
|
// xxxx| |xxxx
|
|
// ----+---------+----
|
|
// xxxx|xxxxxxxxx|xxxx
|
|
// xxxx|xxxxxxxxx|xxxx
|
|
if( ( vNear.z < min.z && vFar.z < min.z ) || ( vNear.z > min.z && vFar.z > min.z ) ||
|
|
( vNear.x < min.x && vFar.x < min.x ) || ( vNear.x > max.x && vFar.x > max.x ) ||
|
|
( vNear.y < min.y && vFar.y < min.y ) || ( vNear.y > max.y && vFar.y > max.y ) )
|
|
continue;
|
|
|
|
// min 0 +---------+ 1
|
|
// | left / |
|
|
// | / |
|
|
// | / |
|
|
// | / right |
|
|
// 2 +---------+ 3 max
|
|
K3DVertex polygon[ 4 ];
|
|
polygon[ 0 ].Set( min.x, min.y, min.z ); // 0
|
|
polygon[ 1 ].Set( max.x, min.y, min.z ); // 1
|
|
polygon[ 2 ].Set( min.x, max.y, min.z ); // 2
|
|
polygon[ 3 ].Set( max.x, max.y, min.z ); // 3
|
|
|
|
float fT = 1.0f;
|
|
|
|
// check left plane
|
|
fT = KPCCP::triangle_collide_edge_twosides( polygon[ 2 ], polygon[ 1 ], polygon[ 0 ], vNear, vFar, p );
|
|
if( fNearestT > fT )
|
|
{
|
|
fNearestT = fT;
|
|
return true;
|
|
}
|
|
// check right plane
|
|
fT = KPCCP::triangle_collide_edge_twosides( polygon[ 2 ], polygon[ 3 ], polygon[ 1 ], vNear, vFar, p );
|
|
if( fNearestT > fT )
|
|
{
|
|
fNearestT = fT;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
// }
|
|
// { [sonador][7.1.7]충돌 처리 개선(Swept Shpere Collision Detection)
|
|
bool SGameLowQualityWater::GetEllipsoidCrossedPoint
|
|
( const K3DVector& vBase
|
|
, const K3DVector& vVelocity
|
|
, const K3DVector& vRadius
|
|
, float& fNearestT
|
|
, K3DVector& vPickedPoint
|
|
#ifdef _DEBUG
|
|
, K3DVector* pCollidedPolygon
|
|
#endif
|
|
) const
|
|
{
|
|
bool bFound = false;
|
|
float fT = 1.0f;
|
|
K3DVector vIntersection, vMin, vMax, vFar( vBase + vVelocity );
|
|
K3DVector vBaseInESpace ( vBase.x / vRadius.x, vBase.y / vRadius.y, vBase.z / vRadius.z );
|
|
K3DVector vVelocityInESpace ( vVelocity.x / vRadius.x, vVelocity.y / vRadius.y, vVelocity.z / vRadius.z );
|
|
|
|
std::vector< SWater* >::const_iterator itEnd = m_vWaterPrimitive.end( );
|
|
for( std::vector< SWater* >::const_iterator it = m_vWaterPrimitive.begin( ); it != itEnd; ++it )
|
|
{
|
|
SWater* pWater = (*it);
|
|
vMin = *pWater->GetMinVertex( );
|
|
vMax = *pWater->GetMaxVertex( );
|
|
if( vMin.x > vMax.x ) std::swap( vMin.x, vMax.x );
|
|
if( vMin.y > vMax.y ) std::swap( vMin.y, vMax.y );
|
|
|
|
// fast culling
|
|
// xxxx|xxxxxxxxx|xxxx
|
|
// xxxx|xxxxxxxxx|xxxx
|
|
// ----+---------+----
|
|
// xxxx| |xxxx
|
|
// xxxx| |xxxx
|
|
// xxxx| |xxxx
|
|
// xxxx| |xxxx
|
|
// ----+---------+----
|
|
// xxxx|xxxxxxxxx|xxxx
|
|
// xxxx|xxxxxxxxx|xxxx
|
|
if( ( ( vBase.z + vRadius.z ) < vMin.z && ( vFar.z + vRadius.z ) < vMin.z ) || ( ( vBase.z - vRadius.z ) > vMin.z && ( vFar.z - vRadius.z ) > vMin.z ) ||
|
|
( ( vBase.x + vRadius.x ) < vMin.x && ( vFar.x + vRadius.x ) < vMin.x ) || ( ( vBase.x - vRadius.x ) > vMax.x && ( vFar.x - vRadius.x ) > vMax.x ) ||
|
|
( ( vBase.y + vRadius.y ) < vMin.y && ( vFar.y + vRadius.y ) < vMin.y ) || ( ( vBase.y - vRadius.y ) > vMax.y && ( vFar.y - vRadius.y ) > vMax.y ) )
|
|
continue;
|
|
|
|
// vMin 0 +---------+ 1
|
|
// | left / |
|
|
// | / |
|
|
// | / |
|
|
// | / right |
|
|
// 2 +---------+ 3 vMax
|
|
K3DVertex vPolygon[ 4 ];
|
|
vPolygon[ 0 ].Set( vMin.x / vRadius.x, vMin.y / vRadius.y, vMin.z / vRadius.z ); // 0
|
|
vPolygon[ 1 ].Set( vMax.x / vRadius.x, vMin.y / vRadius.y, vMin.z / vRadius.z ); // 1
|
|
vPolygon[ 2 ].Set( vMin.x / vRadius.x, vMax.y / vRadius.y, vMin.z / vRadius.z ); // 2
|
|
vPolygon[ 3 ].Set( vMax.x / vRadius.x, vMax.y / vRadius.y, vMin.z / vRadius.z ); // 3
|
|
|
|
// check left plane
|
|
if( KPCCP::triangle_collide_swept_unit_sphere( vPolygon[ 0 ], vPolygon[ 1 ], vPolygon[ 2 ], vBaseInESpace, vVelocityInESpace, vIntersection, fT ) && ( fNearestT > fT ) )
|
|
{
|
|
bFound = true;
|
|
fNearestT = fT;
|
|
vPickedPoint = vIntersection;
|
|
#ifdef _DEBUG
|
|
pCollidedPolygon[ 0 ] = vPolygon[ 0 ];
|
|
pCollidedPolygon[ 1 ] = vPolygon[ 1 ];
|
|
pCollidedPolygon[ 2 ] = vPolygon[ 2 ];
|
|
#endif
|
|
}
|
|
// check right plane
|
|
if( KPCCP::triangle_collide_swept_unit_sphere( vPolygon[ 1 ], vPolygon[ 3 ], vPolygon[ 2 ], vBaseInESpace, vVelocityInESpace, vIntersection, fT ) && ( fNearestT > fT ) )
|
|
{
|
|
bFound = true;
|
|
fNearestT = fT;
|
|
vPickedPoint = vIntersection;
|
|
#ifdef _DEBUG
|
|
pCollidedPolygon[ 0 ] = vPolygon[ 1 ];
|
|
pCollidedPolygon[ 1 ] = vPolygon[ 3 ];
|
|
pCollidedPolygon[ 2 ] = vPolygon[ 2 ];
|
|
#endif
|
|
}
|
|
}
|
|
return bFound;
|
|
}
|
|
// }
|