786 lines
20 KiB
C++
786 lines
20 KiB
C++
#include "StdAfx.h"
|
|
#include "EtTerrain.h"
|
|
#include "EtConvexVolume.h"
|
|
#include "EtCollisionFunc.h"
|
|
#include "EtLoader.h"
|
|
#include "EtOptionController.h"
|
|
#include "EtRenderStack.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
|
#endif
|
|
|
|
using namespace EternityEngine;
|
|
|
|
char *CEtTerrain::s_szTerrainMaterial[ 6 ] =
|
|
{
|
|
"LayeredTerrain.fx",
|
|
"LayeredCliffTerrain.fx",
|
|
"LowDetailTerrain.fx",
|
|
"LayeredTerrainOpti.fx",
|
|
"LayeredCliffTerrainOpti.fx",
|
|
"LayeredCliffTerrainLow.fx",
|
|
};
|
|
|
|
CEtTerrain::CEtTerrain(void)
|
|
{
|
|
m_bEnable = false;
|
|
m_bDrawGrid = false;
|
|
m_dwGridColor = 0xffffffff;
|
|
m_BoundingBox.Reset();
|
|
|
|
m_nTechniqueIndex = 0;
|
|
SetTextureLayerCount( 4 );
|
|
|
|
m_nBlockOffsetX = 0;
|
|
m_nBlockOffsetY = 0;
|
|
|
|
m_nMaterialName = 0;
|
|
m_nRenderUniqueID = -1;
|
|
|
|
m_nBakeDepthType = DT_OPAQUE;
|
|
|
|
m_nStride = 0;
|
|
m_nStrideVert = 0;
|
|
}
|
|
|
|
CEtTerrain::~CEtTerrain(void)
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void CEtTerrain::Clear()
|
|
{
|
|
int i;
|
|
|
|
SAFE_RELEASE_SPTR( m_hMaterial );
|
|
SAFE_RELEASE_SPTR( m_hLightMap );
|
|
|
|
for( i = 0; i < ( int )m_vecCustomParam.size(); i++ )
|
|
{
|
|
if( m_vecCustomParam[ i ].Type == EPT_TEX )
|
|
{
|
|
EtResourceHandle hHandle;
|
|
|
|
if( m_vecCustomParam[ i ].nTextureIndex != -1 )
|
|
{
|
|
hHandle = CEtResource::GetResource( m_vecCustomParam[ i ].nTextureIndex );
|
|
if( hHandle && hHandle->GetRefCount() > 0 ) {
|
|
SAFE_RELEASE_SPTR( hHandle );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
m_vecCustomParam.clear();
|
|
m_MeshStream.Clear();
|
|
}
|
|
|
|
void CEtTerrain::SetTextureLayerCount( int nCount )
|
|
{
|
|
int i;
|
|
|
|
m_vecTextureDist.resize( nCount );
|
|
m_vecTextureHandle.resize( nCount );
|
|
m_vecTextureRotation.resize( nCount );
|
|
m_vecTextureRotationParam.resize( nCount * 2 );
|
|
for( i = 0; i < nCount; i++ )
|
|
{
|
|
m_vecTextureHandle[ i ].Identity();
|
|
m_vecTextureDist[ i ] = FLT_MAX;
|
|
|
|
m_vecTextureRotation[ i ] = 0.0f;
|
|
// cos, sin 값 두개를 저장하는 것인데, 기본값은 cos 0, sin 0 이다.
|
|
m_vecTextureRotationParam[ i*2 ] = 1.0f;
|
|
m_vecTextureRotationParam[ i*2+1 ] = 0.0f;
|
|
}
|
|
}
|
|
|
|
void CEtTerrain::Initialize()
|
|
{
|
|
Clear();
|
|
CreateMaterial( s_szTerrainMaterial[ m_nMaterialName ] );
|
|
GenerateVertexBuffer();
|
|
GenerateTexureCoord();
|
|
CalcBoundingBox();
|
|
#if 0
|
|
int i, j;
|
|
int nLayer1 = 0;
|
|
int nLayer2 = 0;
|
|
int nLayer3 = 0;
|
|
int nLayer4 = 0;
|
|
for( i = 0; i < ( m_TerrainInfo.nSizeY + 1 ); i++ )
|
|
{
|
|
for( j = 0; j < ( m_TerrainInfo.nSizeX + 1 ); j++ )
|
|
{
|
|
DWORD dwValue = GetLayerValue( j, i );
|
|
if( dwValue & 0xff000000 )
|
|
{
|
|
nLayer1++;
|
|
}
|
|
if( dwValue & 0xff0000 )
|
|
{
|
|
nLayer2++;
|
|
}
|
|
if( dwValue & 0xff00 )
|
|
{
|
|
nLayer3++;
|
|
}
|
|
if( dwValue & 0xff )
|
|
{
|
|
nLayer4++;
|
|
}
|
|
}
|
|
}
|
|
OutputDebug( "Layer Count %d %d %d %d\n", nLayer1, nLayer2, nLayer3, nLayer4 );
|
|
#endif
|
|
}
|
|
|
|
void CEtTerrain::CreateMaterial( const char *pEffectName )
|
|
{
|
|
int i;
|
|
char szParamName[ 64 ];
|
|
|
|
m_hMaterial = LoadResource( pEffectName, RT_SHADER, true );
|
|
#ifdef PRE_FIX_MATERIAL_DUMP
|
|
if( !m_hMaterial ) return;
|
|
#endif
|
|
|
|
for( i = 0; i < ( int )m_vecTextureDist.size(); i++ )
|
|
{
|
|
if( m_vecTextureDist[ i ] == FLT_MAX )
|
|
{
|
|
m_vecTextureDist[ i ] = m_TerrainInfo.fTileSize / m_TerrainInfo.fTextureDistance;
|
|
}
|
|
}
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_fTextureDistance", &m_vecTextureDist[ 0 ] );
|
|
AddCustomParam( m_vecCustomParam, EPT_FLOAT_PTR, m_hMaterial, "g_fTileSize", &m_TerrainInfo.fTileSize );
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_WorldOffset", &m_TerrainInfo.TerrainOffset );
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_fTextureRotate12", &m_vecTextureRotationParam[ 0 ] );
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_fTextureRotate34", &m_vecTextureRotationParam[ 4 ] );
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
int nTexIndex = -1;
|
|
sprintf( szParamName, "g_LayerTex%d", i + 1 );
|
|
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, szParamName, &nTexIndex );
|
|
SetTextureParam( i );
|
|
}
|
|
}
|
|
|
|
void CEtTerrain::SetTerrainInfo( STerrainInfo *pInfo )
|
|
{
|
|
memcpy( &m_TerrainInfo, pInfo, sizeof( STerrainInfo ) );
|
|
CheckLayerCount();
|
|
}
|
|
|
|
void CEtTerrain::GenerateTexureCoord()
|
|
{
|
|
}
|
|
|
|
void CEtTerrain::GeneratePosition( EtVector3 * pBuffer )
|
|
{
|
|
CMemoryStream *pStream;
|
|
int nVertexCount;
|
|
|
|
nVertexCount = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
|
|
CalcPosition( pBuffer, nVertexCount );
|
|
pStream = new CMemoryStream( pBuffer, nVertexCount * sizeof( EtVector3 ) );
|
|
m_MeshStream.LoadVertexStream( pStream, MST_POSITION, 0, nVertexCount );
|
|
delete pStream;
|
|
}
|
|
|
|
void CEtTerrain::GenerateNormal( EtVector3 * pBuffer )
|
|
{
|
|
CMemoryStream *pStream;
|
|
int nVertexCount;
|
|
|
|
nVertexCount = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
|
|
CalcNormal( pBuffer, nVertexCount );
|
|
pStream = new CMemoryStream( pBuffer, nVertexCount * sizeof( EtVector3 ) );
|
|
m_MeshStream.LoadVertexStream( pStream, MST_NORMAL, 0, nVertexCount );
|
|
delete pStream;
|
|
}
|
|
|
|
DWORD CEtTerrain::ConvertLayerValue( DWORD dwLayer )
|
|
{
|
|
DWORD dwRet = 0;
|
|
float fValue1, fValue2, fValue3, fValue4;
|
|
float fValue12, fValue123, fValue1234;
|
|
|
|
fValue1 = ( dwLayer >> 24 ) / 255.0f;
|
|
fValue2 = ( ( dwLayer >> 16 ) & 0xff ) / 255.0f;
|
|
fValue3 = ( ( dwLayer >> 8 ) & 0xff ) / 255.0f;
|
|
fValue4 = ( dwLayer & 0xff ) / 255.0f;
|
|
|
|
fValue12 = fValue1 + fValue2;
|
|
fValue123 = fValue12 + fValue3;
|
|
fValue1234 = fValue123 + fValue4;
|
|
|
|
if( fValue12 != 0.0f )
|
|
{
|
|
dwRet |= ( ( DWORD )( fValue2 / ( fValue12 ) * 255 ) & 0xff ) << 24;
|
|
}
|
|
if( fValue123 != 0.0f )
|
|
{
|
|
dwRet |= ( ( DWORD )( fValue3 / ( fValue123 ) * 255 ) & 0xff ) << 16;
|
|
}
|
|
if( fValue1234 != 0.0f )
|
|
{
|
|
dwRet |= ( ( DWORD )( fValue4 / ( fValue1234 ) * 255 ) & 0xff ) << 8;
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
void CEtTerrain::GenerateLayer( DWORD *pBuffer )
|
|
{
|
|
CMemoryStream *pStream;
|
|
int i, j, nVertexCount;
|
|
|
|
nVertexCount = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
|
|
for( i = 0; i <= m_TerrainInfo.nSizeY; i++ )
|
|
{
|
|
int nVertexOffset;
|
|
|
|
nVertexOffset = VertexOffset( 0, i );
|
|
for( j = 0; j <= m_TerrainInfo.nSizeX; j++ )
|
|
{
|
|
pBuffer[ nVertexOffset + j ] = ConvertLayerValue( GetLayerValue( j, i ) );
|
|
}
|
|
}
|
|
pStream = new CMemoryStream( pBuffer, nVertexCount * sizeof( DWORD ) );
|
|
m_MeshStream.LoadVertexStream( pStream, MST_COLOR, 0, nVertexCount );
|
|
delete pStream;
|
|
}
|
|
|
|
void CEtTerrain::GenerateVertexBuffer()
|
|
{
|
|
EtVector3 *pBuffer;
|
|
int nVertexCount;
|
|
|
|
nVertexCount = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
|
|
|
|
pBuffer = new EtVector3[ nVertexCount ];
|
|
GeneratePosition( pBuffer );
|
|
GenerateNormal( pBuffer );
|
|
GenerateLayer( ( DWORD *)pBuffer );
|
|
|
|
delete [] pBuffer;
|
|
}
|
|
|
|
void CEtTerrain::CalcPosition( EtVector3 *pPosition, int nCount )
|
|
{
|
|
int i, j;
|
|
int nSizeX, nSizeY;
|
|
|
|
nSizeX = m_TerrainInfo.nSizeX + 1;
|
|
nSizeY = m_TerrainInfo.nSizeY + 1;
|
|
for( i = 0; i < nSizeY; i++ )
|
|
{
|
|
for( j = 0; j < nSizeX; j++ )
|
|
{
|
|
pPosition[ i * nSizeX + j ].x = j * m_TerrainInfo.fTileSize;
|
|
pPosition[ i * nSizeX + j ].y = GetHeight( j, i );
|
|
pPosition[ i * nSizeX + j ].z = i * m_TerrainInfo.fTileSize;
|
|
if( pPosition[ i * nSizeX + j ].y > m_BoundingBox.Max.y )
|
|
{
|
|
m_BoundingBox.Max.y = pPosition[ i * nSizeX + j ].y;
|
|
}
|
|
if( pPosition[ i * nSizeX + j ].y < m_BoundingBox.Min.y )
|
|
{
|
|
m_BoundingBox.Min.y = pPosition[ i * nSizeX + j ].y;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEtTerrain::CalcNormal( EtVector3 *pNormal, int nCount )
|
|
{
|
|
int i, j;
|
|
int nSizeX, nSizeY;
|
|
|
|
nSizeX = m_TerrainInfo.nSizeX + 1;
|
|
nSizeY = m_TerrainInfo.nSizeY + 1;
|
|
for( i = 0; i < nSizeY; i++ )
|
|
{
|
|
for( j = 0; j < nSizeX; j++ )
|
|
{
|
|
pNormal[ i * nSizeX + j ] = GetVertexNormal( j, i );
|
|
}
|
|
}
|
|
}
|
|
|
|
EtVector3 CEtTerrain::GetVertexNormal( int nIndexX, int nIndexY )
|
|
{
|
|
EtVector3 Return;
|
|
|
|
Return.x = ( GetHeight( nIndexX - 1, nIndexY ) - GetHeight( nIndexX + 1, nIndexY ) ) / ( m_TerrainInfo.fTileSize * 2 );
|
|
Return.y = 1.414f * m_TerrainInfo.fHeightMultiply;
|
|
Return.z = ( GetHeight( nIndexX, nIndexY - 1 ) - GetHeight( nIndexX, nIndexY + 1 ) ) / ( m_TerrainInfo.fTileSize * 2 );
|
|
EtVec3Normalize( &Return, &Return );
|
|
|
|
return Return;
|
|
}
|
|
|
|
void CEtTerrain::UpdateHeight()
|
|
{
|
|
int nVertexCount;
|
|
EtVector3 *pBuffer;
|
|
|
|
nVertexCount = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
|
|
pBuffer = new EtVector3[ nVertexCount ];
|
|
GeneratePosition( pBuffer );
|
|
delete [] pBuffer;
|
|
}
|
|
|
|
void CEtTerrain::UpdateLayer()
|
|
{
|
|
int nVertexCount;
|
|
DWORD *pBuffer;
|
|
|
|
nVertexCount = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
|
|
pBuffer = new DWORD[ nVertexCount ];
|
|
GenerateLayer( pBuffer );
|
|
delete [] pBuffer;
|
|
}
|
|
|
|
void CEtTerrain::UpdateNormal()
|
|
{
|
|
int nVertexCount;
|
|
EtVector3 *pBuffer;
|
|
|
|
nVertexCount = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
|
|
pBuffer = new EtVector3[ nVertexCount ];
|
|
GenerateNormal( pBuffer );
|
|
delete [] pBuffer;
|
|
}
|
|
|
|
void CEtTerrain::UpdateAll()
|
|
{
|
|
int nVertexCount;
|
|
EtVector3 *pBuffer;
|
|
|
|
nVertexCount = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
|
|
pBuffer = new EtVector3[ nVertexCount ];
|
|
GeneratePosition( pBuffer );
|
|
GenerateNormal( pBuffer );
|
|
GenerateLayer( ( DWORD * )pBuffer );
|
|
GenerateTexureCoord();
|
|
delete [] pBuffer;
|
|
}
|
|
|
|
void CEtTerrain::Render()
|
|
{
|
|
SRenderStackElement RenderElement;
|
|
EtMatrix WorldMat;
|
|
EtCameraHandle hCamera;
|
|
EtVector3 vDist;
|
|
|
|
EtMatrixTranslation( &WorldMat, m_TerrainInfo.TerrainOffset.x, m_TerrainInfo.TerrainOffset.y, m_TerrainInfo.TerrainOffset.z );
|
|
|
|
hCamera = CEtCamera::GetActiveCamera();
|
|
EtVector3 vCamDir = (*hCamera->GetDirection());
|
|
RenderElement.fDist = EtVec3Dot( (EtVector3*)&WorldMat._41, &vCamDir);
|
|
|
|
RenderElement.hMaterial = m_hMaterial;
|
|
RenderElement.nTechniqueIndex = m_nTechniqueIndex;
|
|
RenderElement.WorldMat = WorldMat;
|
|
RenderElement.PrevWorldMat = WorldMat;
|
|
RenderElement.nSaveMatIndex = -1;
|
|
RenderElement.pvecCustomParam = &m_vecCustomParam;
|
|
RenderElement.pRenderMeshStream = &m_MeshStream;
|
|
RenderElement.nDiffuseTexIndex = ( m_vecTextureHandle[0] ) ? m_vecTextureHandle[ 0 ]->GetMyIndex() : -1;
|
|
RenderElement.nBakeDepthIndex = m_nBakeDepthType;
|
|
// RenderElement.renderPriority = RP_HIGH; // Overdraw 문제는 해결 됬으므로, 부하가 큰 지형부터 렌더링 큐에 넣어서, GPU Idle time 을 줄인다.
|
|
m_nRenderUniqueID = GetCurRenderStack()->AddNormalRenderElement( RenderElement, m_nRenderUniqueID );
|
|
|
|
if( m_bDrawGrid )
|
|
{
|
|
int i, j;
|
|
|
|
for( i = 0; i < m_TerrainInfo.nSizeY; i++ )
|
|
{
|
|
for( j = 0; j < m_TerrainInfo.nSizeX; j++ )
|
|
{
|
|
DrawRect( j, i, m_dwGridColor );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEtTerrain::RenderWater( int index )
|
|
{
|
|
SRenderStackElement RenderElement;
|
|
EtMatrix WorldMat;
|
|
EtCameraHandle hCamera;
|
|
EtVector3 vDist;
|
|
|
|
EtMatrixTranslation( &WorldMat, m_TerrainInfo.TerrainOffset.x, m_TerrainInfo.TerrainOffset.y, m_TerrainInfo.TerrainOffset.z );
|
|
|
|
hCamera = CEtCamera::GetActiveCamera();
|
|
EtVector3 vCamDir = (*hCamera->GetDirection());
|
|
vCamDir.y = 0.f;
|
|
RenderElement.fDist = EtVec3Dot( &EtVector3(WorldMat._41, 0, WorldMat._43) , &vCamDir);
|
|
|
|
RenderElement.hMaterial = m_hMaterial;
|
|
RenderElement.nTechniqueIndex = m_nTechniqueIndex;
|
|
RenderElement.WorldMat = WorldMat;
|
|
RenderElement.PrevWorldMat = WorldMat;
|
|
RenderElement.nSaveMatIndex = -1;
|
|
RenderElement.pvecCustomParam = &m_vecCustomParam;
|
|
RenderElement.pRenderMeshStream = &m_MeshStream;
|
|
RenderElement.renderPriority = RP_HIGH;
|
|
GetCurRenderStack()->AddWaterRenderElement( index, RenderElement );
|
|
|
|
}
|
|
|
|
void CEtTerrain::GetExtent( EtVector3 &Origin, EtVector3 &Extent )
|
|
{
|
|
Origin = ( m_BoundingBox.Max + m_BoundingBox.Min ) / 2;
|
|
Extent = ( m_BoundingBox.Max - m_BoundingBox.Min ) / 2;
|
|
}
|
|
|
|
void CEtTerrain::CalcBoundingBox()
|
|
{
|
|
m_BoundingBox.Max.x = m_TerrainInfo.TerrainOffset.x + m_TerrainInfo.nSizeX * m_TerrainInfo.fTileSize;
|
|
m_BoundingBox.Max.z = m_TerrainInfo.TerrainOffset.z + m_TerrainInfo.nSizeY * m_TerrainInfo.fTileSize;
|
|
|
|
m_BoundingBox.Min.x = m_TerrainInfo.TerrainOffset.x;
|
|
m_BoundingBox.Min.z = m_TerrainInfo.TerrainOffset.z;
|
|
|
|
m_BoundingBox.Max.y += 1.0f;
|
|
m_BoundingBox.Min.y -= 1.0f;
|
|
}
|
|
|
|
float CEtTerrain::Pick( EtVector3 &Origin, EtVector3 &Direction, EtVector3 &PickPos )
|
|
{
|
|
int nTileX, nTileY, nDirX, nDirY;
|
|
EtVector2 Origin2D, Direction2D;
|
|
float fTileSize, fDistX, fDistY, fRet;
|
|
|
|
fTileSize = m_TerrainInfo.fTileSize;
|
|
if( Direction.x >= 0.0f )
|
|
{
|
|
nDirX = 1;
|
|
Direction2D.x = Direction.x;
|
|
Origin2D.x = Origin.x - m_TerrainInfo.TerrainOffset.x;
|
|
}
|
|
else
|
|
{
|
|
nDirX = -1;
|
|
Direction2D.x = -Direction.x;
|
|
Origin2D.x = m_TerrainInfo.nSizeX * fTileSize - ( Origin.x - m_TerrainInfo.TerrainOffset.x );
|
|
}
|
|
if( Direction.z >= 0.0f )
|
|
{
|
|
nDirY = 1;
|
|
Direction2D.y = Direction.z;
|
|
Origin2D.y = Origin.z - m_TerrainInfo.TerrainOffset.z;
|
|
}
|
|
else
|
|
{
|
|
nDirY = -1;
|
|
Direction2D.y = -Direction.z;
|
|
Origin2D.y = m_TerrainInfo.nSizeY * fTileSize - ( Origin.z - m_TerrainInfo.TerrainOffset.z );
|
|
}
|
|
|
|
while( 1 )
|
|
{
|
|
nTileX = ( int )( Origin2D.x / fTileSize );
|
|
if( nDirX < 0 )
|
|
{
|
|
nTileX = m_TerrainInfo.nSizeX - nTileX - 1;
|
|
}
|
|
nTileY = ( int )( Origin2D.y / fTileSize );
|
|
if( nDirY < 0 )
|
|
{
|
|
nTileY = m_TerrainInfo.nSizeY - nTileY - 1;
|
|
}
|
|
if( !IsInTerrain( nTileX, nTileY ) )
|
|
{
|
|
break;
|
|
}
|
|
fRet = TestLintToTile( Origin, Direction, nTileX, nTileY );
|
|
if( ( fRet != FLT_MAX ) && ( fRet >= 0.0f ) )
|
|
{
|
|
PickPos = Origin + Direction * fRet;
|
|
return fRet;
|
|
}
|
|
|
|
fDistX = ( ( ( int )( Origin2D.x / fTileSize ) + 1 ) * fTileSize - Origin2D.x ) / Direction2D.x;
|
|
fDistY = ( ( ( int )( Origin2D.y / fTileSize ) + 1 ) * fTileSize - Origin2D.y ) / Direction2D.y;
|
|
if( fDistX >= fDistY )
|
|
{
|
|
Origin2D += fDistY * Direction2D;
|
|
}
|
|
else if( fDistX < fDistY )
|
|
{
|
|
Origin2D += fDistX * Direction2D;
|
|
}
|
|
}
|
|
|
|
return FLT_MAX;
|
|
}
|
|
|
|
bool CEtTerrain::IsInTerrain( int nX, int nY )
|
|
{
|
|
if( ( nX < 0 ) || ( nX >= m_TerrainInfo.nSizeX ) )
|
|
{
|
|
return false;
|
|
}
|
|
if( ( nY < 0 ) || ( nY >= m_TerrainInfo.nSizeY ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
float CEtTerrain::TestLintToTile( EtVector3 &Origin, EtVector3 &Direction, int nTileX, int nTileY )
|
|
{
|
|
float fTileSize;
|
|
float fDist1, fDist2, fBary1, fBary2;
|
|
EtVector3 V1, V2, V3, ExtraOrigin;
|
|
|
|
fTileSize = m_TerrainInfo.fTileSize;
|
|
|
|
ExtraOrigin = Origin - m_TerrainInfo.TerrainOffset;
|
|
|
|
V1 = EtVector3( nTileX * fTileSize, GetHeight( nTileX, nTileY ), nTileY * fTileSize );
|
|
nTileY++;
|
|
V2 = EtVector3( nTileX * fTileSize, GetHeight( nTileX, nTileY ), nTileY * fTileSize );
|
|
nTileX++;
|
|
V3 = EtVector3( nTileX * fTileSize, GetHeight( nTileX, nTileY ), nTileY * fTileSize );
|
|
TestLineToTriangle( ExtraOrigin, Direction, V1, V2, V3, fDist1, fBary1, fBary2 );
|
|
|
|
nTileY--;
|
|
V2 = EtVector3( nTileX * fTileSize, GetHeight( nTileX, nTileY ), nTileY * fTileSize );
|
|
TestLineToTriangle( ExtraOrigin, Direction, V1, V3, V2, fDist2, fBary1, fBary2 );
|
|
|
|
return min( fDist1, fDist2 );
|
|
}
|
|
|
|
SCustomParam *CEtTerrain::FindEffectParam( EffectParamType Type, int nIndex )
|
|
{
|
|
int i, nCount;
|
|
|
|
nCount = 0;
|
|
for( i = 0; i < ( int )m_vecCustomParam.size(); i++ )
|
|
{
|
|
if( m_vecCustomParam[ i ].Type == Type )
|
|
{
|
|
if( nCount == nIndex )
|
|
{
|
|
return &m_vecCustomParam[ i ];
|
|
}
|
|
nCount++;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const char *CEtTerrain::GetTextureName( int nTexIndex )
|
|
{
|
|
int nFindTexIndex;
|
|
SCustomParam *pParam;
|
|
|
|
pParam = FindEffectParam( EPT_TEX, nTexIndex );
|
|
if( pParam == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
nFindTexIndex = pParam->nTextureIndex;
|
|
if( nFindTexIndex == -1 )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
EtTextureHandle hTexture;
|
|
|
|
hTexture = CEtResource::GetResource( nFindTexIndex );
|
|
|
|
// return hTexture->GetFullName();
|
|
return hTexture->GetFileName();
|
|
}
|
|
|
|
bool CEtTerrain::SetTexture( int nTexIndex, const char *pTexName )
|
|
{
|
|
ASSERT( nTexIndex < ( int )m_vecTextureHandle.size() );
|
|
|
|
EtTextureHandle hTexture, hLoadTex;
|
|
|
|
hLoadTex = LoadResource( pTexName, RT_TEXTURE );
|
|
if( !hLoadTex )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
m_vecTextureHandle[ nTexIndex ] = hLoadTex;
|
|
SetTextureParam( nTexIndex );
|
|
|
|
return true;
|
|
}
|
|
|
|
void CEtTerrain::SetTextureParam( int nTexIndex )
|
|
{
|
|
int nFindTexIndex;
|
|
SCustomParam *pParam;
|
|
EtTextureHandle hTexture;
|
|
|
|
if( !m_vecTextureHandle[ nTexIndex ] )
|
|
{
|
|
return;
|
|
}
|
|
|
|
pParam = FindEffectParam( EPT_TEX, nTexIndex );
|
|
if( pParam == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
nFindTexIndex = pParam->nTextureIndex;
|
|
if( nFindTexIndex != -1 )
|
|
{
|
|
hTexture = CEtResource::GetResource( nFindTexIndex );
|
|
if( hTexture && hTexture->GetRefCount() > 0 ) {
|
|
SAFE_RELEASE_SPTR( hTexture );
|
|
}
|
|
}
|
|
pParam->nTextureIndex = m_vecTextureHandle[ nTexIndex ]->GetMyIndex();
|
|
}
|
|
|
|
const char *CEtTerrain::GetTextureSemanticName( int nTexIndex )
|
|
{
|
|
SCustomParam *pParam;
|
|
|
|
pParam = FindEffectParam( EPT_TEX, nTexIndex );
|
|
if( pParam == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return m_hMaterial->GetSemantic( pParam->hParamHandle );
|
|
}
|
|
|
|
void CEtTerrain::SetTextureDistance( int nTexLayer, float fDistance )
|
|
{
|
|
ASSERT( nTexLayer < ( int )m_vecTextureDist.size() );
|
|
|
|
m_vecTextureDist[ nTexLayer ] = m_TerrainInfo.fTileSize / fDistance;
|
|
}
|
|
|
|
float CEtTerrain::GetTextureDistance( int nTexLayer )
|
|
{
|
|
ASSERT( nTexLayer < ( int )m_vecTextureDist.size() );
|
|
|
|
return m_TerrainInfo.fTileSize / m_vecTextureDist[ nTexLayer ];
|
|
}
|
|
|
|
void CEtTerrain::SetTextureRotation( int nTexLayer, float fRotate )
|
|
{
|
|
ASSERT( nTexLayer < ( int )m_vecTextureRotation.size() );
|
|
|
|
m_vecTextureRotation[ nTexLayer ] = fRotate;
|
|
float fRotateRadian = EtToRadian( fRotate );
|
|
m_vecTextureRotationParam[ nTexLayer * 2 ] = cosf( fRotateRadian );
|
|
m_vecTextureRotationParam[ nTexLayer * 2 + 1 ] = sinf( fRotateRadian );
|
|
}
|
|
|
|
float CEtTerrain::GetTextureRotation( int nTexLayer )
|
|
{
|
|
ASSERT( nTexLayer < ( int )m_vecTextureRotation.size() );
|
|
|
|
return m_vecTextureRotation[ nTexLayer ];
|
|
}
|
|
|
|
void CEtTerrain::DrawRect( int nX, int nY, DWORD dwColor )
|
|
{
|
|
EtVector3 Start, End;
|
|
|
|
Start.x = m_TerrainInfo.TerrainOffset.x + nX * m_TerrainInfo.fTileSize;
|
|
Start.y = GetHeight( nX, nY ) + 1.0f;
|
|
Start.z = m_TerrainInfo.TerrainOffset.z + nY * m_TerrainInfo.fTileSize;
|
|
nX++;
|
|
End.x = m_TerrainInfo.TerrainOffset.x + nX * m_TerrainInfo.fTileSize;
|
|
End.y = GetHeight( nX, nY ) + 1.0f;
|
|
End.z = m_TerrainInfo.TerrainOffset.z + nY * m_TerrainInfo.fTileSize;
|
|
DrawLine3D( Start, End, dwColor );
|
|
|
|
nY++;
|
|
End.x = m_TerrainInfo.TerrainOffset.x + nX * m_TerrainInfo.fTileSize;
|
|
End.y = GetHeight( nX, nY ) + 1.0f;
|
|
End.z = m_TerrainInfo.TerrainOffset.z + nY * m_TerrainInfo.fTileSize;
|
|
DrawLine3D( Start, End, dwColor );
|
|
|
|
nX--;
|
|
nY--;
|
|
End.x = m_TerrainInfo.TerrainOffset.x + nX * m_TerrainInfo.fTileSize;
|
|
End.y = GetHeight( nX, nY ) + 1.0f;
|
|
End.z = m_TerrainInfo.TerrainOffset.z + nY * m_TerrainInfo.fTileSize;
|
|
DrawLine3D( Start, End, dwColor );
|
|
|
|
nY++;
|
|
End.x = m_TerrainInfo.TerrainOffset.x + nX * m_TerrainInfo.fTileSize;
|
|
End.y = GetHeight( nX, nY ) + 1.0f;
|
|
End.z = m_TerrainInfo.TerrainOffset.z + nY * m_TerrainInfo.fTileSize;
|
|
DrawLine3D( Start, End, dwColor );
|
|
|
|
nX++;
|
|
End.x = m_TerrainInfo.TerrainOffset.x + nX * m_TerrainInfo.fTileSize;
|
|
End.y = GetHeight( nX, nY ) + 1.0f;
|
|
End.z = m_TerrainInfo.TerrainOffset.z + nY * m_TerrainInfo.fTileSize;
|
|
DrawLine3D( Start, End, dwColor );
|
|
}
|
|
|
|
void CEtTerrain::SetLightMap( EtTextureHandle hLightMap )
|
|
{
|
|
SAFE_RELEASE_SPTR( m_hLightMap );
|
|
m_hLightMap = hLightMap;
|
|
|
|
EtVector4 TerrainBlockSize;
|
|
EtVector4 vPixelSize;
|
|
int nTexIndex = -1;
|
|
nTexIndex = m_hLightMap->GetMyIndex();
|
|
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, "g_LightMap", &nTexIndex );
|
|
TerrainBlockSize.x = ( m_TerrainInfo.nSizeX + m_TerrainInfo.nSizeX * 2.0f / m_hLightMap->Width() ) * m_TerrainInfo.fTileSize;
|
|
TerrainBlockSize.y = ( m_TerrainInfo.nSizeY + m_TerrainInfo.nSizeY * 2.0f / m_hLightMap->Height() ) * m_TerrainInfo.fTileSize;
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR, m_hMaterial, "g_TerrainBlockSize", &TerrainBlockSize );
|
|
vPixelSize.x = 1.0f / m_hLightMap->Width();
|
|
vPixelSize.y = 1.0f / m_hLightMap->Height();
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR, m_hMaterial, "g_fPixelSize", &vPixelSize );
|
|
}
|
|
|
|
EtTextureHandle CEtTerrain::GetLightMap()
|
|
{
|
|
return m_hLightMap ? m_hLightMap : CEtTexture::GetWhiteTexture();
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// CEtDetailTerrain
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
CEtDetailTerrain::CEtDetailTerrain()
|
|
{
|
|
m_nTechniqueIndex = 1;
|
|
SetTextureLayerCount( 8 );
|
|
}
|
|
|
|
CEtDetailTerrain::~CEtDetailTerrain()
|
|
{
|
|
}
|
|
|
|
void CEtDetailTerrain::CreateMaterial( const char *pEffectName )
|
|
{
|
|
CEtTerrain::CreateMaterial( pEffectName );
|
|
|
|
int i;
|
|
char szParamName[ 64 ];
|
|
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_fTextureDistance2", &m_vecTextureDist[ 4 ] );
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
int nTexIndex = -1;
|
|
sprintf( szParamName, "g_LayerFarTex%d", i + 1 );
|
|
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, szParamName, &nTexIndex );
|
|
SetTextureParam( i + 4 );
|
|
}
|
|
}
|
|
|