DragonNest/Common/EternityEngine/EtTerrainArea.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

1758 lines
No EOL
52 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "EtConvexVolume.h"
#include "EtCollisionFunc.h"
#include "EtLoader.h"
#include "EtTerrainArea.h"
#include "EtLayeredMultiUVTerrain.h"
#include "EtOptionController.h"
#include "EtGrassBlock.h"
#include "EtDrawQuad.h"
#include "EtWater.h"
#include "EtShadowMap.h"
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
using namespace EternityEngine;
DECL_SMART_PTR_STATIC( CEtTerrainArea, 20 )
extern CSyncLock *g_pEtRenderLock;
bool CEtTerrainArea::s_bOptimize = false;
bool CEtTerrainArea::s_bEnableFrustumCull = true;
CEtTerrainArea::CEtTerrainArea(void)
{
m_BoundingBox.Reset();
m_pCommonIndexBuffer = NULL;
m_pCommonLowIndexBuffer = NULL;
m_pLightMapInfluenceBuffer = NULL;
m_nLightMapInfluenceStride = 0;
m_bShow = true;
m_nBlockCountX = 0;
m_nBlockCountY = 0;
m_nBlockSizeX = 0;
m_nBlockSizeY = 0;
m_nGrassBlockCountX = 0;
m_nGrassBlockCountY = 0;
}
CEtTerrainArea::~CEtTerrainArea(void)
{
Clear();
}
void CEtTerrainArea::Clear()
{
SAFE_DELETE_PVEC( m_vecTerrain );
SAFE_DELETE_PVEC( m_vecGrassBlock );
SAFE_RELEASE( m_pCommonIndexBuffer );
SAFE_RELEASE( m_pCommonLowIndexBuffer );
SAFE_DELETEA( m_pLightMapInfluenceBuffer );
}
void CEtTerrainArea::CalcSelectCount( int nBlockIndex, int &nStart, int &nEnd )
{
if( nBlockIndex == -1 )
{
nStart = 0;
nEnd = ( int )m_vecTerrain.size();
}
else
{
nStart = nBlockIndex;
nEnd = nStart + 1;
}
}
void CEtTerrainArea::DrawGrid( bool bDraw, int nBlockIndex )
{
int i, nStart, nEnd;
CalcSelectCount( nBlockIndex, nStart, nEnd );
for( i = nStart; i < nEnd; i++ )
{
m_vecTerrain[ i ]->DrawGrid( bDraw );
}
}
void CEtTerrainArea::SetGridColor( DWORD dwColor, int nBlockIndex )
{
int i, nStart, nEnd;
CalcSelectCount( nBlockIndex, nStart, nEnd );
for( i = nStart; i < nEnd; i++ )
{
m_vecTerrain[ i ]->SetGridColor( dwColor );
}
}
void CEtTerrainArea::SetTextureDistance( int nTexLayer, float fDistance, int nBlockIndex )
{
int i, nStart, nEnd;
CalcSelectCount( nBlockIndex, nStart, nEnd );
for( i = nStart; i < nEnd; i++ )
{
m_vecTerrain[ i ]->SetTextureDistance( nTexLayer, fDistance );
}
}
void CEtTerrainArea::SetTextureRotation( int nTexLayer, float fRotation, int nBlockIndex )
{
int i, nStart, nEnd;
CalcSelectCount( nBlockIndex, nStart, nEnd );
for( i = nStart; i < nEnd; i++ )
{
m_vecTerrain[ i ]->SetTextureRotation( nTexLayer, fRotation );
}
}
void CEtTerrainArea::Initialize( STerrainInfo *pInfo )
{
CEtTerrain *pTerrain;
int i, j;
Clear();
m_TerrainInfo = *pInfo;
// <20><>Ƽ<EFBFBD><C6BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ķ<EFBFBD><C4B7>̾<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD> <20>ؼ<EFBFBD>.. <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..
if( s_bOptimize )
{
int nSize = ( m_TerrainInfo.nSizeX + 1 ) * ( m_TerrainInfo.nSizeY + 1 );
DWORD *pAlphaLayer = new DWORD[ nSize ];
memcpy( pAlphaLayer, m_TerrainInfo.pLayerDensity, nSize * sizeof( DWORD ) );
m_TerrainInfo.pLayerDensity = pAlphaLayer;
}
m_nBlockCountX = pInfo->nSizeX / DEFAULT_TERRAIN_SIZE;
if( pInfo->nSizeX % DEFAULT_TERRAIN_SIZE )
{
m_nBlockCountX++;
}
m_nBlockSizeX = DEFAULT_TERRAIN_SIZE;
m_nBlockCountY = pInfo->nSizeY / DEFAULT_TERRAIN_SIZE;
if( pInfo->nSizeY % DEFAULT_TERRAIN_SIZE )
{
m_nBlockCountY++;
}
m_nBlockSizeY = DEFAULT_TERRAIN_SIZE;
STerrainInfo TerrainInfo;
memcpy( &TerrainInfo, &m_TerrainInfo, sizeof( STerrainInfo ) );
TerrainInfo.nSizeX = m_nBlockSizeX;
TerrainInfo.nSizeY = m_nBlockSizeY;
for( i = 0; i < m_nBlockCountY; i++ )
{
for( j = 0; j < m_nBlockCountX; j++ )
{
TerrainInfo.pHeight = pInfo->pHeight + ( i * m_nBlockSizeY ) * ( pInfo->nSizeX + 1 ) + j * m_nBlockSizeX;
TerrainInfo.pLayerDensity = pInfo->pLayerDensity + ( i * m_nBlockSizeY ) * ( pInfo->nSizeX + 1 ) + j * m_nBlockSizeX;
TerrainInfo.TerrainOffset = pInfo->TerrainOffset
+ EtVector3( pInfo->fTileSize * j * m_nBlockSizeX, 0.0f, pInfo->fTileSize * i * m_nBlockSizeY );
pTerrain = CreateBlock( pInfo->Type );
pTerrain->SetBlockOffset( j * m_nBlockSizeX, i * m_nBlockSizeY );
pTerrain->SetStride( pInfo->nSizeX + 1, pInfo->nSizeY + 1 );
pTerrain->SetTerrainInfo( &TerrainInfo );
m_vecTerrain.push_back( pTerrain );
}
}
float fWorldSizeX, fWorldSizeY, fWorldSizeZ;
fWorldSizeX = m_TerrainInfo.nSizeX * m_TerrainInfo.fTileSize;
fWorldSizeY = m_TerrainInfo.nSizeY * m_TerrainInfo.fTileSize;
fWorldSizeZ = pInfo->fHeightMultiply * 65535.f;
CEtObject::SetWorldSize( EtVector3( fWorldSizeX * 0.5f, 0.0f, fWorldSizeY * 0.5f ), max( max( fWorldSizeX, fWorldSizeY ), fWorldSizeZ ) );
CalcBoundingBox();
SGraphicOption Option;
GetEtOptionController()->GetGraphicOption( Option );
if( Option.bDrawGrass )
{
CreateGrassBlock();
}
if( s_bOptimize )
{
delete [] m_TerrainInfo.pLayerDensity;
}
}
void CEtTerrainArea::CreateCommonIndexBuffer()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ɼ<EFBFBD><C9BC>̶<EFBFBD><CCB6><EFBFBD> low <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴ<EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20>ʿ<EFBFBD><CABF><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ϳ<EFBFBD><CFB3><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
SGraphicOption Option;
GetEtOptionController()->GetGraphicOption( Option );
// #40097 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ɼ<EFBFBD><C9BC>̰ų<CCB0>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰<EFBFBD>, 2<><32>¥<EFBFBD><C2A5> <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> <20><><EFBFBD>̴<EFBFBD><CCB4><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ<EFBFBD> <20>׷<EFBFBD><D7B7><EFBFBD> ī<><C4AB><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20>׷<EFBFBD><D7B7><EFBFBD> <20><><EFBFBD>ؼ<EFBFBD> m_pCommonIndexBuffer <20><> <20>ʿ<EFBFBD><CABF>ϴ<EFBFBD>.
if( true == Option.bUseSplatting ||
(false == Option.bUseSplatting && true == Option.bIsOnlyLowShaderAvailable) )
{
if( m_pCommonIndexBuffer == NULL )
{
int i, j, nIndexCount;
WORD *pIndexBuffer;
int nFaceCount;
nFaceCount = m_nBlockSizeX * m_nBlockSizeY * 2;
nIndexCount = 0;
m_pCommonIndexBuffer = GetEtDevice()->CreateIndexBuffer( nFaceCount * 3 * sizeof( WORD ) );
m_pCommonIndexBuffer->Lock( 0, sizeof( WORD ) * nFaceCount * 3, ( void ** )&pIndexBuffer, 0 );
for( i = 0; i < m_nBlockSizeY; i++ )
{
for( j = 0; j < m_nBlockSizeX; j++ )
{
int nOffset;
nOffset = ( m_nBlockSizeX + 1 ) * i + j;
pIndexBuffer[ nIndexCount ] = nOffset;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset + m_nBlockSizeX + 1;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset + m_nBlockSizeX + 2;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset + m_nBlockSizeX + 2;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset + 1;
nIndexCount++;
}
}
m_pCommonIndexBuffer->Unlock();
}
}
if( false == Option.bUseSplatting )
{
if( m_pCommonLowIndexBuffer == NULL )
{
int i, j, nIndexCount;
WORD *pIndexBuffer;
int nFaceCount;
nFaceCount = (m_nBlockSizeX / 2) * (m_nBlockSizeY / 2) * 2;
nIndexCount = 0;
m_pCommonLowIndexBuffer = GetEtDevice()->CreateIndexBuffer( nFaceCount * 3 * sizeof( WORD ) );
m_pCommonLowIndexBuffer->Lock( 0, sizeof( WORD ) * nFaceCount * 3, ( void ** )&pIndexBuffer, 0 );
for( i = 0; i < m_nBlockSizeY / 2; i++ )
{
for( j = 0; j < m_nBlockSizeX / 2; j++ )
{
int nOffset;
nOffset = ( m_nBlockSizeX / 2 + 1 ) * i + j;
pIndexBuffer[ nIndexCount ] = nOffset;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset + m_nBlockSizeX / 2 + 1;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset + m_nBlockSizeX / 2 + 2;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset + m_nBlockSizeX / 2 + 2;
nIndexCount++;
pIndexBuffer[ nIndexCount ] = nOffset + 1;
nIndexCount++;
}
}
m_pCommonLowIndexBuffer->Unlock();
}
}
}
void CEtTerrainArea::InitializeBlock( int nBlockIndex )
{
SGraphicOption Option;
GetEtOptionController()->GetGraphicOption( Option );
int i, nStart, nEnd;
CreateCommonIndexBuffer();
CalcSelectCount( nBlockIndex, nStart, nEnd );
for( i = nStart; i < nEnd; i++ )
{
if( true == Option.bUseSplatting ||
(false == Option.bUseSplatting && true == Option.bIsOnlyLowShaderAvailable) )
{
m_vecTerrain[ i ]->SetCommonIndexBuffer( m_pCommonIndexBuffer, m_nBlockSizeX * m_nBlockSizeY * 2 );
}
else
{
m_vecTerrain[ i ]->SetCommonIndexBuffer( m_pCommonLowIndexBuffer, (m_nBlockSizeX/2) * (m_nBlockSizeY/2) * 2 );
}
m_vecTerrain[ i ]->Initialize();
m_vecTerrain[ i ]->Enable( true );
if( !m_vecGrassBlock.empty() )
{
int nGrassBlockIndex;
nGrassBlockIndex = ( i % m_nBlockCountX ) * 2 + ( i / m_nBlockCountX ) * m_nBlockCountX * 4;
if( m_vecGrassBlock[ nGrassBlockIndex ] )
{
m_vecGrassBlock[ nGrassBlockIndex ]->Initialize( this );
}
nGrassBlockIndex++;
if( m_vecGrassBlock[ nGrassBlockIndex ] )
{
m_vecGrassBlock[ nGrassBlockIndex ]->Initialize( this );
}
nGrassBlockIndex += m_nBlockCountX * 2;
if( m_vecGrassBlock[ nGrassBlockIndex ] )
{
m_vecGrassBlock[ nGrassBlockIndex ]->Initialize( this );
}
nGrassBlockIndex--;
if( m_vecGrassBlock[ nGrassBlockIndex ] )
{
m_vecGrassBlock[ nGrassBlockIndex ]->Initialize( this );
}
}
}
CalcBoundingBox();
}
CEtTerrain *CEtTerrainArea::CreateBlock( TerrainType Type )
{
SGraphicOption Option;
GetEtOptionController()->GetGraphicOption( Option );
if( !Option.bUseSplatting )
{
if( Option.bIsOnlyLowShaderAvailable )
{
return new CEtLowDetailTerrain();
}
else
{
return new CEtLowSplatTerrain();
}
}
if( s_bOptimize )
{
return new CEtTerrainOpti();
}
else
{
switch( Type )
{
case TT_NORMAL:
return new CEtTerrain();
case TT_DETAILNORMAL:
return new CEtDetailTerrain();
case TT_CLIFF:
return new CEtCliffTerrain();
case TT_DETAILCLIFF:
return new CEtDetailCliffTerrain();
}
}
return NULL;
}
void CEtTerrainArea::ChangeBlockType( TerrainType Type, int nBlockIndex )
{
// <20><>Ƽ<EFBFBD><C6BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ÿ<><C5B8> <20>ϳ<EFBFBD><CFB3><EFBFBD>.. <20><><EFBFBD><EFBFBD>Ÿ<EFBFBD><C5B8> <20>ٲ<EFBFBD> <20>ʿ<EFBFBD> <20><><EFBFBD><EFBFBD>..
if( s_bOptimize )
{
return;
}
bool bEnable;
int i, j, nStart, nEnd, nTexCount;
STerrainInfo TerrainInfo;
std::vector< std::string > vecTexName;
std::vector< float > vecTexDist;
std::vector< float > vecTexRotation;
CalcSelectCount( nBlockIndex, nStart, nEnd );
for( i = nStart; i < nEnd; i++ )
{
bEnable = m_vecTerrain[ i ]->IsEnable();
memcpy( &TerrainInfo, m_vecTerrain[ i ]->GetTerrainInfo(), sizeof( STerrainInfo ) );
TerrainInfo.Type = Type;
vecTexName.clear();
vecTexDist.clear();
const char *szTextureName;
for( j = 0; j < m_vecTerrain[ i ]->GetTextureCount(); j++ )
{
szTextureName = m_vecTerrain[ i ]->GetTextureName( j );
if( szTextureName )
vecTexName.push_back( szTextureName );
else
vecTexName.push_back( "" );
vecTexDist.push_back( m_vecTerrain[ i ]->GetTextureDistance( j ) );
vecTexRotation.push_back( m_vecTerrain[ i ]->GetTextureRotation( j ) );
}
delete m_vecTerrain[ i ];
m_vecTerrain[ i ] = CreateBlock( Type );
m_vecTerrain[ i ]->SetStride( m_TerrainInfo.nSizeX + 1, m_TerrainInfo.nSizeY + 1 );
m_vecTerrain[ i ]->SetBlockOffset( i % m_nBlockCountX * m_nBlockSizeX, i / m_nBlockCountX * m_nBlockSizeY );
m_vecTerrain[ i ]->SetTerrainInfo( &TerrainInfo );
m_vecTerrain[ i ]->SetCommonIndexBuffer( m_pCommonIndexBuffer, m_nBlockSizeX * m_nBlockSizeY * 2 );
if( bEnable )
{
m_vecTerrain[ i ]->Initialize();
m_vecTerrain[ i ]->Enable( true );
}
nTexCount = min( m_vecTerrain[ i ]->GetTextureCount(), ( int )vecTexName.size() );
for( j = 0; j < nTexCount; j++ )
{
if( vecTexName[ j ].size() )
{
m_vecTerrain[ i ]->SetTexture( j, vecTexName[ j ].c_str() );
}
m_vecTerrain[ i ]->SetTextureDistance( j, vecTexDist[ j ] );
m_vecTerrain[ i ]->SetTextureRotation( j, vecTexRotation[ j ] );
}
}
}
TerrainType CEtTerrainArea::GetBlockType( int nBlockIndex )
{
return m_vecTerrain[nBlockIndex]->GetTerrainInfo()->Type;
}
void CEtTerrainArea::Render( CEtConvexVolume *pFrustum )
{
int i, nSize;
EtVector3 Origin, Extent;
static std::vector< bool > vecFrustumCull;
nSize = (int)m_vecTerrain.size();
vecFrustumCull.clear();
vecFrustumCull.resize( nSize );
for( i = 0; i < nSize; i++ )
{
if( m_vecTerrain[ i ]->IsEnable() == false )
{
vecFrustumCull[ i ] = false;
continue;
}
if( s_bEnableFrustumCull ) {
m_vecTerrain[ i ]->GetExtent( Origin, Extent );
if( pFrustum->TesToBox( Origin, Extent ) == false )
{
vecFrustumCull[ i ] = false;
continue;
}
}
vecFrustumCull[ i ] = true;
}
nSize = ( int )m_vecGrassBlock.size();
for( i = 0; i < nSize; i++ )
{
if( ( m_vecGrassBlock[ i ] ) && ( m_vecGrassBlock[ i ]->GetGrassCount() > 0 ) )
{
int nTerrainIndex;
nTerrainIndex = i / ( m_nGrassBlockCountX * 2 ) * m_nBlockCountX + i % ( m_nGrassBlockCountX ) / 2;
if( !vecFrustumCull[ nTerrainIndex ] )
{
continue;
}
m_vecGrassBlock[ i ]->GetExtent( Origin, Extent );
if( pFrustum->TesToBox( Origin, Extent ) == true || !s_bEnableFrustumCull )
{
m_vecGrassBlock[ i ]->Render();
}
}
}
nSize = ( int )m_vecTerrain.size();
for( i = 0; i < nSize; i++ )
{
if( !vecFrustumCull[ i ] )
{
continue;
}
m_vecTerrain[ i ]->Render();
}
}
void CEtTerrainArea::RenderWater( int index, CEtConvexVolume *pFrustum )
{
int i;
EtVector3 Origin, Extent;
static std::vector< bool > vecFrustumCull;
int nSize = (int)m_vecTerrain.size();
vecFrustumCull.clear();
vecFrustumCull.resize( nSize );
for( i = 0; i < nSize; i++ )
{
if( m_vecTerrain[ i ]->IsEnable() == false )
{
vecFrustumCull[ i ] = false;
continue;
}
if( s_bEnableFrustumCull ) {
m_vecTerrain[ i ]->GetExtent( Origin, Extent );
if( pFrustum->TesToBox( Origin, Extent ) == false )
{
vecFrustumCull[ i ] = false;
continue;
}
}
vecFrustumCull[ i ] = true;
}
for( i = 0; i < nSize; i++ )
{
if( !vecFrustumCull[ i ] )
{
continue;
}
m_vecTerrain[ i ]->RenderWater( index );
}
}
void CEtTerrainArea::GetExtent( EtVector3 &Origin, EtVector3 &Extent )
{
Origin = ( m_BoundingBox.Max + m_BoundingBox.Min ) / 2;
Extent = ( m_BoundingBox.Max - m_BoundingBox.Min ) / 2;
}
void CEtTerrainArea::CalcBoundingBox()
{
int i;
SAABox *pBoundingBox;
for( i = 0; i < ( int )m_vecTerrain.size(); i++ )
{
pBoundingBox = m_vecTerrain[ i ]->GetBoundingBox();
if( m_BoundingBox.Min.y > pBoundingBox->Min.y )
{
m_BoundingBox.Min.y = pBoundingBox->Min.y;
}
if( m_BoundingBox.Max.y < pBoundingBox->Max.y )
{
m_BoundingBox.Max.y = pBoundingBox->Max.y;
}
}
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;
}
void CEtTerrainArea::RenderTerrainBlockList( CEtConvexVolume *pFrustum)
{
int i, nCount, nWaterCount;
EtVector3 Origin, Extent;
EtTerrainHandle hHandle;
nWaterCount = GetEtWater()->GetWaterCount();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Water <20>ø<EFBFBD> <20>Ÿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ߴ<EFBFBD><DFB4><EFBFBD> <20><><EFBFBD>߰<EFBFBD><DFB0><EFBFBD> <20>Ÿ<EFBFBD><C5B8><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڰŸ<DAB0><C5B8><EFBFBD>..
float fWaterRatio = CEtCamera::GetActiveCamera()->GetWaterFarRatio();
CEtCamera::GetActiveCamera()->SetWaterFarRatio( 1.0f );
std::vector< CEtConvexVolume > vecWaterFrustum;
vecWaterFrustum.resize( nWaterCount );
for( int j = 0; j < nWaterCount; j++)
{
vecWaterFrustum[j].Initialize( GetEtWater()->GetViewProjMat( j ) );
}
CEtCamera::GetActiveCamera()->SetWaterFarRatio( fWaterRatio );
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
hHandle = GetItem( i );
if( ( hHandle ) && ( hHandle->IsShow() ) )
{
hHandle->GetExtent( Origin, Extent );
if( pFrustum->TesToBox( Origin, Extent ) || !s_bEnableFrustumCull )
{
hHandle->Render( pFrustum );
}
if( GetEtOptionController()->GetWaterQuality() != WQ_LOW )
{
for( int j = 0; j < nWaterCount; j++)
{
if( GetEtWater()->GetWaterIgnoreBake( j ) )
continue;
if( vecWaterFrustum[j].TesToBox( Origin, Extent) || !s_bEnableFrustumCull )
{
hHandle->RenderWater( j, &vecWaterFrustum[j]);
}
}
}
}
}
}
void CEtTerrainArea::UpdateHeight( int nStartX, int nStartY, int nEndX, int nEndY )
{
int i, j;
int nStartBlockX, nStartBlockY, nEndBlockX, nEndBlockY;
nStartBlockX = nStartX / m_nBlockSizeX;
nStartBlockY = nStartY / m_nBlockSizeY;
nEndBlockX = nEndX / m_nBlockSizeX;
nEndBlockY = nEndY / m_nBlockSizeY;
if( nStartBlockX < 0 ) nStartBlockX = 0;
else if( nStartBlockX >= m_nBlockCountX ) nStartBlockX = m_nBlockCountX - 1;
if( nStartBlockY < 0 ) nStartBlockY = 0;
else if( nStartBlockY >= m_nBlockCountY ) nStartBlockY = m_nBlockCountY - 1;
if( nEndBlockX < 0 ) nEndBlockX = 0;
else if( nEndBlockX >= m_nBlockCountX ) nEndBlockX = m_nBlockCountX - 1;
if( nEndBlockY < 0 ) nStartBlockY = 0;
else if( nEndBlockY >= m_nBlockCountY ) nEndBlockY = m_nBlockCountY - 1;
for( i = nStartBlockY; i <= nEndBlockY; i++ )
{
for( j = nStartBlockX; j <= nEndBlockX; j++ )
{
if( m_vecTerrain[ i * m_nBlockCountX + j ]->IsEnable() == false )
{
continue;
}
m_vecTerrain[ i * m_nBlockCountX + j ]->UpdateHeight();
}
}
CalcBoundingBox();
}
void CEtTerrainArea::UpdateLayer( int nStartX, int nStartY, int nEndX, int nEndY )
{
int i, j;
int nStartBlockX, nStartBlockY, nEndBlockX, nEndBlockY;
nStartBlockX = nStartX / m_nBlockSizeX;
nStartBlockY = nStartY / m_nBlockSizeY;
nEndBlockX = nEndX / m_nBlockSizeX;
nEndBlockY = nEndY / m_nBlockSizeY;
if( nStartBlockX < 0 ) nStartBlockX = 0;
else if( nStartBlockX >= m_nBlockCountX ) nStartBlockX = m_nBlockCountX - 1;
if( nStartBlockY < 0 ) nStartBlockY = 0;
else if( nStartBlockY >= m_nBlockCountY ) nStartBlockY = m_nBlockCountY - 1;
if( nEndBlockX < 0 ) nEndBlockX = 0;
else if( nEndBlockX >= m_nBlockCountX ) nEndBlockX = m_nBlockCountX - 1;
if( nEndBlockY < 0 ) nStartBlockY = 0;
else if( nEndBlockY >= m_nBlockCountY ) nEndBlockY = m_nBlockCountY - 1;
for( i = nStartBlockY; i <= nEndBlockY; i++ )
{
for( j = nStartBlockX; j <= nEndBlockX; j++ )
{
if( m_vecTerrain[ i * m_nBlockCountX + j ]->IsEnable() == false )
{
continue;
}
m_vecTerrain[ i * m_nBlockCountX + j ]->UpdateLayer();
}
}
}
void CEtTerrainArea::UpdateNormal( int nStartX, int nStartY, int nEndX, int nEndY )
{
int i, j;
int nStartBlockX, nStartBlockY, nEndBlockX, nEndBlockY;
nStartBlockX = nStartX / m_nBlockSizeX;
nStartBlockY = nStartY / m_nBlockSizeY;
nEndBlockX = nEndX / m_nBlockSizeX;
nEndBlockY = nEndY / m_nBlockSizeY;
if( nStartBlockX < 0 ) nStartBlockX = 0;
else if( nStartBlockX >= m_nBlockCountX ) nStartBlockX = m_nBlockCountX - 1;
if( nStartBlockY < 0 ) nStartBlockY = 0;
else if( nStartBlockY >= m_nBlockCountY ) nStartBlockY = m_nBlockCountY - 1;
if( nEndBlockX < 0 ) nEndBlockX = 0;
else if( nEndBlockX >= m_nBlockCountX ) nEndBlockX = m_nBlockCountX - 1;
if( nEndBlockY < 0 ) nStartBlockY = 0;
else if( nEndBlockY >= m_nBlockCountY ) nEndBlockY = m_nBlockCountY - 1;
for( i = nStartBlockY; i <= nEndBlockY; i++ )
{
for( j = nStartBlockX; j <= nEndBlockX; j++ )
{
if( m_vecTerrain[ i * m_nBlockCountX + j ]->IsEnable() == false )
{
continue;
}
m_vecTerrain[ i * m_nBlockCountX + j ]->UpdateNormal();
}
}
}
void CEtTerrainArea::UpdateTextureCoord( int nStartX, int nStartY, int nEndX, int nEndY )
{
int i, j;
int nStartBlockX, nStartBlockY, nEndBlockX, nEndBlockY;
nStartBlockX = nStartX / m_nBlockSizeX;
nStartBlockY = nStartY / m_nBlockSizeY;
nEndBlockX = nEndX / m_nBlockSizeX;
nEndBlockY = nEndY / m_nBlockSizeY;
if( nStartBlockX < 0 ) nStartBlockX = 0;
else if( nStartBlockX >= m_nBlockCountX ) nStartBlockX = m_nBlockCountX - 1;
if( nStartBlockY < 0 ) nStartBlockY = 0;
else if( nStartBlockY >= m_nBlockCountY ) nStartBlockY = m_nBlockCountY - 1;
if( nEndBlockX < 0 ) nEndBlockX = 0;
else if( nEndBlockX >= m_nBlockCountX ) nEndBlockX = m_nBlockCountX - 1;
if( nEndBlockY < 0 ) nStartBlockY = 0;
else if( nEndBlockY >= m_nBlockCountY ) nEndBlockY = m_nBlockCountY - 1;
for( i = nStartBlockY; i <= nEndBlockY; i++ )
{
for( j = nStartBlockX; j <= nEndBlockX; j++ )
{
if( m_vecTerrain[ i * m_nBlockCountX + j ]->IsEnable() == false )
{
continue;
}
m_vecTerrain[ i * m_nBlockCountX + j ]->GenerateTexureCoord();
}
}
}
void CEtTerrainArea::UpdateGrassBlock( int nStartX, int nStartY, int nEndX, int nEndY )
{
int i, j;
int nStartBlockX, nStartBlockY, nEndBlockX, nEndBlockY;
nStartBlockX = nStartX / ( m_nBlockSizeX / 2 );
nStartBlockY = nStartY / ( m_nBlockSizeY / 2 );
nEndBlockX = nEndX / ( m_nBlockSizeX / 2 );
nEndBlockY = nEndY / ( m_nBlockSizeY / 2 );
if( nStartBlockX < 0 ) nStartBlockX = 0;
else if( nStartBlockX >= m_nGrassBlockCountX ) nStartBlockX = m_nGrassBlockCountX - 1;
if( nStartBlockY < 0 ) nStartBlockY = 0;
else if( nStartBlockY >= m_nGrassBlockCountY ) nStartBlockY = m_nGrassBlockCountY - 1;
if( nEndBlockX < 0 ) nEndBlockX = 0;
else if( nEndBlockX >= m_nGrassBlockCountX ) nEndBlockX = m_nGrassBlockCountX - 1;
if( nEndBlockY < 0 ) nStartBlockY = 0;
else if( nEndBlockY >= m_nGrassBlockCountY ) nEndBlockY = m_nGrassBlockCountY - 1;
for( i = nStartBlockY; i <= nEndBlockY; i++ )
{
for( j = nStartBlockX; j <= nEndBlockX; j++ )
{
if( !m_vecGrassBlock[ i * m_nGrassBlockCountX + j ] )
{
continue;
}
m_vecGrassBlock[ i * m_nGrassBlockCountX + j ]->Initialize( this );
}
}
}
int CEtTerrainArea::GetGrassBlockCount()
{
return (int)m_vecGrassBlock.size();
}
void CEtTerrainArea::SetGrassInfo( int nBlockIndex, SGrassBlockInfo &Info )
{
if( nBlockIndex == -1 )
{
for( DWORD i=0; i<m_vecGrassBlock.size(); i++ )
{
m_vecGrassBlock[i]->SetGrassBlockInfo( &Info );
m_vecGrassBlock[i]->Initialize( this );
}
}
else
{
m_vecGrassBlock[nBlockIndex]->SetGrassBlockInfo( &Info );
m_vecGrassBlock[nBlockIndex]->Initialize( this );
}
}
SGrassBlockInfo *CEtTerrainArea::GetGrassInfo( int nBlockIndex )
{
if( nBlockIndex < 0 || nBlockIndex >= (int)m_vecGrassBlock.size() ) return NULL;
return m_vecGrassBlock[nBlockIndex]->GetGrassBlockInfo();
}
bool CEtTerrainArea::Pick( EtVector3 &Origin, EtVector3 &Direction, EtVector3 &PickPos )
{
int i;
float fMinDist, fFindDist, fDistToBox;
EtVector3 FindPos, ModifyOrigin;
fMinDist = FLT_MAX;
for( i = 0; i < ( int )m_vecTerrain.size(); i++ )
{
SAABox *pBoundingBox;
pBoundingBox = m_vecTerrain[ i ]->GetBoundingBox();
if( !TestLineToBox( Origin, Direction, *pBoundingBox, fDistToBox ) )
{
continue;
}
if( fDistToBox == 0.0f )
{
ModifyOrigin = Origin;
}
else
{
ModifyOrigin = Origin + Direction * fDistToBox;
}
fFindDist = m_vecTerrain[ i ]->Pick( ModifyOrigin, Direction, FindPos ) + fDistToBox;
if(fFindDist < fMinDist )
{
fMinDist = fFindDist;
PickPos = FindPos;
}
}
if( fMinDist != FLT_MAX )
{
return true;
}
return false;
}
bool CEtTerrainArea::Pick( int nX, int nY, EtVector3 &PickPos, int nCameraIndex )
{
EtVector3 Direction, Origin;
CEtCamera::GetItem( nCameraIndex )->CalcPositionAndDir( nX, nY, Origin, Direction );
return Pick( Origin, Direction, PickPos );
}
bool CEtTerrainArea::SetTexture( int nTexIndex, const char *pTexName, int nBlockIndex )
{
int i, nStart, nEnd;
bool bRet;
bRet = true;
CalcSelectCount( nBlockIndex, nStart, nEnd );
for( i = nStart; i < nEnd; i++ )
{
if( m_vecTerrain[ i ]->SetTexture( nTexIndex, pTexName ) == false )
{
bRet = false;
}
}
return bRet;
}
void CEtTerrainArea::SetGrassTexture( const char *pFileName )
{
int i;
for( i = 0; i < ( int )m_vecGrassBlock.size(); i++ )
{
if( m_vecGrassBlock[ i ] )
{
m_vecGrassBlock[ i ]->SetTexture( pFileName );
}
}
}
const char *CEtTerrainArea::GetGrassTexture()
{
if( m_vecGrassBlock.empty() ) return NULL;
return m_vecGrassBlock[0]->GetTextureName();
}
bool CEtTerrainArea::IsInside( float fX, float fZ )
{
if( fX < m_TerrainInfo.TerrainOffset.x )
{
return false;
}
if( fX > m_TerrainInfo.TerrainOffset.x + m_TerrainInfo.nSizeX * m_TerrainInfo.fTileSize )
{
return false;
}
if( fZ < m_TerrainInfo.TerrainOffset.z )
{
return false;
}
if( fZ > m_TerrainInfo.TerrainOffset.z + m_TerrainInfo.nSizeY * m_TerrainInfo.fTileSize )
{
return false;
}
return true;
}
void CEtTerrainArea::BakeLightMap( int nBlockIndex, int nWidth, int nHeight, float fBlurSize, int nBakeRange, float fSlopeBias )
{
SBakeLightMapParam Param;
Param.nBlockIndex = nBlockIndex;
Param.nWidth = nWidth;
Param.nHeight = nHeight;
Param.fBlurSize = fBlurSize;
Param.nBakeRange = nBakeRange;
Param.fSlopeBias = fSlopeBias;
m_vecBakeLightMapParam.push_back( Param );
}
void CEtTerrainArea::_BakeLightMap( int nBlockIndex, int nWidth, int nHeight, float fBlurSize, int nBakeRange, float fSlopeBias )
{
if( !CEtLight::GetShadowCastDirLightInfo() ) return;
SGraphicOption Option;
GetEtOptionController()->GetGraphicOption( Option );
if( !Option.bUseTerrainLightMap )
{
Option.bUseTerrainLightMap = true;
GetEtOptionController()->SetGraphicOption( Option );
}
#ifdef PRE_FIX_MATERIAL_DUMP
EtMaterialHandle hBakeLightMapMaterial = LoadResource( "BakeTerrainLightMap.fx", RT_SHADER );
EtMaterialHandle hGaussianFilter = LoadResource( "GaussianFilter.fx", RT_SHADER );
if( !hBakeLightMapMaterial ) return;
if( !hGaussianFilter ) return;
#endif
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> ũ<><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
bool bBakeLightMap = true;
if( false == Option.bUseSplatting )
{
if( false == Option.bIsOnlyLowShaderAvailable )
{
nWidth /= 2;
nHeight /= 2;
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ɼ<EFBFBD><C9BC>̶<EFBFBD><CCB6><EFBFBD> 2<><20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
// <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> <20><><EFBFBD>̴<EFBFBD><CCB4><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׷<EFBFBD><D7B7><EFBFBD> ī<><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD> <20>׳<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD> ó<><C3B3>.
BakeLowDetailMap();
bBakeLightMap = false;
}
}
if( bBakeLightMap )
{
int i, nStart, nEnd;
static EtMatrix LightMapViewProjMat;
EtTextureHandle hBlurLightMap = CEtTexture::CreateRenderTargetTexture( nWidth * 2, nHeight * 2, FMT_A8R8G8B8 );
EtTextureHandle hBlurMoreLightMap = CEtTexture::CreateRenderTargetTexture( nWidth * 2, nHeight * 2, FMT_A8R8G8B8 );
EtTextureHandle hRoughLightMap = CEtTexture::CreateRenderTargetTexture( nWidth * 2, nHeight * 2, FMT_A8R8G8B8 );
EtTextureHandle hFinalLightMap = CEtTexture::CreateRenderTargetTexture( nWidth, nHeight, FMT_A8R8G8B8 );
EtTextureHandle hDepthLightMap = CEtTexture::CreateRenderTargetTexture( nWidth * 2, nHeight * 2, FMT_R32F );
LPD3DXRENDERTOSURFACE pBlurSurfaceMng = NULL, pFinalSurfaceMng = NULL, pDepthSurfaceMng = NULL;
GetEtDevice()->CreateRenderToSurface( nWidth * 2, nHeight * 2, FMT_A8R8G8B8, FALSE, FMT_UNKNOWN, &pBlurSurfaceMng );
GetEtDevice()->CreateRenderToSurface( nWidth * 2, nHeight * 2, FMT_R32F, TRUE, FMT_D24S8, &pDepthSurfaceMng );
GetEtDevice()->CreateRenderToSurface( nWidth, nHeight, FMT_A8R8G8B8, FALSE, FMT_UNKNOWN, &pFinalSurfaceMng );
EtTextureHandle hInfluenceMap = CEtTexture::CreateNormalTexture( nWidth, nHeight, FMT_A8R8G8B8, USAGE_DEFAULT, POOL_SYSTEMMEM );
//EtDepthHandle hDepth = CEtDepth::CreateDepthStencil( nWidth * 2, nHeight * 2 );
#ifdef PRE_FIX_MATERIAL_DUMP
#else
EtMaterialHandle hBakeLightMapMaterial = LoadResource( "BakeTerrainLightMap.fx", RT_SHADER );
EtMaterialHandle hGaussianFilter = LoadResource( "GaussianFilter.fx", RT_SHADER );
#endif
SCameraInfo CameraInfo;
EtCameraHandle hCamera;
CameraInfo.fViewWidth = m_TerrainInfo.fTileSize * m_nBlockSizeX;
CameraInfo.fViewHeight = m_TerrainInfo.fTileSize * m_nBlockSizeY;
CameraInfo.fWidth = ( float )nWidth;
CameraInfo.fHeight = ( float )nHeight;
CameraInfo.Type = CT_ORTHOGONAL;
CameraInfo.Target = CT_RENDERTARGET_NO_GENERATE_BACKBUFFER;
hCamera = CreateCamera( &CameraInfo );
EtViewPort viewPort;
GetEtDevice()->GetViewport( &viewPort );
CalcSelectCount( nBlockIndex, nStart, nEnd );
for( i = nStart; i < nEnd; i++ )
{
std::vector< SCustomParam > vecCustomParam;
SAABox BoundingBox;
int nTexIndex;
EtVector3 Eye, At, TerrainOffset;
BakeDepthLightMap( i, hDepthLightMap, pDepthSurfaceMng, hBakeLightMapMaterial, LightMapViewProjMat, nBakeRange, fSlopeBias );
BakeRoughLightMap( i, hRoughLightMap, hDepthLightMap, pBlurSurfaceMng, hBakeLightMapMaterial, hCamera, nWidth * 2, nHeight * 2, LightMapViewProjMat );
float fStart, fEnd;
EtVector4 FilterRadius;
GetEtDevice()->EnableZ( false );
GetEtDevice()->SetCullMode( CULL_NONE );
//GetEtDevice()->SetDepthStencilSurface( NULL );
vecCustomParam.clear();
FilterRadius.x = fBlurSize * 2 / nWidth;
FilterRadius.y = fBlurSize * 2 / nHeight;
AddCustomParam( vecCustomParam, EPT_VECTOR, hGaussianFilter, "g_fBlurRadius", &FilterRadius );
nTexIndex = hRoughLightMap->GetMyIndex();
AddCustomParam( vecCustomParam, EPT_TEX, hGaussianFilter, "g_GaussianSource", &nTexIndex );
if( SUCCEEDED(pBlurSurfaceMng->BeginScene( hBlurLightMap->GetSurfaceLevel(), NULL ) ) ) {
DrawQuadIm( hGaussianFilter, vecCustomParam, 0, EtVector2( 0.0f, 0.0f ), EtVector2( 1.0f, 1.0f ), EtVector2( 0.0f, 0.0f ), EtVector2( 1.0f, 1.0f ) );
pBlurSurfaceMng->EndScene( 0 );
}
nTexIndex = hBlurLightMap->GetMyIndex();
AddCustomParam( vecCustomParam, EPT_TEX, hGaussianFilter, "g_GaussianSource", &nTexIndex );
if( SUCCEEDED(pBlurSurfaceMng->BeginScene( hBlurMoreLightMap->GetSurfaceLevel(), NULL ) ) ) {
DrawQuadIm( hGaussianFilter, vecCustomParam, 1, EtVector2( 0.0f, 0.0f ), EtVector2( 1.0f, 1.0f ), EtVector2( 0.0f, 0.0f ), EtVector2( 1.0f, 1.0f ) );
pBlurSurfaceMng->EndScene( 0 );
}
vecCustomParam.clear();
nTexIndex = hBlurMoreLightMap->GetMyIndex();
AddCustomParam( vecCustomParam, EPT_TEX, hBakeLightMapMaterial, "g_LightMapTex", &nTexIndex );
if( SUCCEEDED(pFinalSurfaceMng->BeginScene( hFinalLightMap->GetSurfaceLevel(), NULL ) ) ) {
fStart = ( nWidth / 2.0f - 1.0f ) / ( nWidth * 2.0f );
fEnd = ( nWidth * 3.0f / 2.0f + 1.0f ) / ( nWidth * 2.0f );
DrawQuadIm( hBakeLightMapMaterial, vecCustomParam, 2, EtVector2( 0.0f, 0.0f ), EtVector2( 1.0f, 1.0f ), EtVector2( fStart, fStart ), EtVector2( fEnd, fEnd ) );
pFinalSurfaceMng->EndScene( 0 );
}
GetEtDevice()->SetCullMode( CULL_CCW );
GetEtDevice()->EnableZ( true );
HRESULT hResult = ( ( IDirect3DDevice9 * )GetEtDevice()->GetDevicePtr() )->GetRenderTargetData( hFinalLightMap->GetSurfaceLevel(), hInfluenceMap->GetSurfaceLevel() );
if( SUCCEEDED( hResult ) ) {
int nTexStride;
char *pTexBuffer;
pTexBuffer = ( char * )hInfluenceMap->Lock( nTexStride );
SetLightMapInfluence( i, pTexBuffer, nTexStride, hFinalLightMap->Width(), hFinalLightMap->Height() );
hInfluenceMap->Unlock();
EtTextureHandle hLightMap = CEtTexture::CreateNormalTexture( nWidth, nHeight, FMT_DXT1, USAGE_DEFAULT, POOL_MANAGED );
hLightMap->Copy( hInfluenceMap );
m_vecTerrain[ i ]->SetLightMap( hLightMap );
}
}
GetEtDevice()->SetViewport( &viewPort );
SAFE_RELEASE_SPTR( hCamera );
SAFE_RELEASE_SPTR( hGaussianFilter );
SAFE_RELEASE_SPTR( hInfluenceMap );
SAFE_RELEASE_SPTR( hFinalLightMap );
SAFE_RELEASE_SPTR( hRoughLightMap );
SAFE_RELEASE_SPTR( hBakeLightMapMaterial );
SAFE_RELEASE_SPTR( hDepthLightMap );
SAFE_RELEASE_SPTR( hBlurLightMap );
SAFE_RELEASE_SPTR( hBlurMoreLightMap );
SAFE_RELEASE( pBlurSurfaceMng );
SAFE_RELEASE( pFinalSurfaceMng );
SAFE_RELEASE( pDepthSurfaceMng );
}
CEtObject::RecalcLightMapInfluence();
}
bool CEtTerrainArea::_BakeLightMapFromFile( int nBlockIndex, EtTextureHandle hTexture )
{
EtTextureHandle hInfluenceMap = CEtTexture::CreateNormalTexture( hTexture->Width(), hTexture->Height(), FMT_A8R8G8B8, USAGE_DEFAULT, POOL_SYSTEMMEM );
if( !hInfluenceMap ) return false;
hInfluenceMap->Copy( hTexture );
int nTexStride;
char *pTexBuffer;
pTexBuffer = ( char * )hInfluenceMap->Lock( nTexStride );
SetLightMapInfluence( nBlockIndex, pTexBuffer, nTexStride, hTexture->Width(), hTexture->Height() );
hInfluenceMap->Unlock();
m_vecTerrain[ nBlockIndex ]->SetLightMap( hTexture );
SAFE_RELEASE_SPTR( hInfluenceMap );
return true;
}
void CEtTerrainArea::BakeLowDetailMap()
{
GetEtShadowMap()->ResetShadowMap();
int i, nSize;
nSize = (int)m_vecTerrain.size();
for( i = 0; i < nSize; i++) {
m_vecTerrain[ i ]->BakeLowDetailMap();
m_vecTerrain[ i ]->SetCommonIndexBuffer( m_pCommonLowIndexBuffer, (m_nBlockSizeX/2) * (m_nBlockSizeY/2) * 2 );
}
}
void CEtTerrainArea::CreateLightCamera( int nBlockIndex, EtCameraHandle &hCamera, int nWidth, int nHeight, EtMatrix &LightMapViewProjMat )
{
SAABox BoundingBox;
SCameraInfo CameraInfo;
EtVector3 Eye, At, LightDir, TerrainOffset;
EtMatrix ScaleMat, TransMat, *pProjMat, *pViewMat;
LightDir = -CEtLight::GetShadowCastDirLightInfo()->Direction;
TerrainOffset = m_vecTerrain[ nBlockIndex ]->GetTerrainInfo()->TerrainOffset;
BoundingBox = *GetBoundingBox( nBlockIndex );
BoundingBox.Max.y = m_BoundingBox.Max.y;
BoundingBox.Min.y = m_BoundingBox.Min.y;
BoundingBox.Max.x -= TerrainOffset.x;
BoundingBox.Max.z -= TerrainOffset.z;
BoundingBox.Min.x -= TerrainOffset.x;
BoundingBox.Min.z -= TerrainOffset.z;
if( BoundingBox.Max.y - BoundingBox.Min.y < 3000.0f )
{
BoundingBox.Max.y = BoundingBox.Min.y + 3000.0f;
}
BoundingBox.Max.y += ( BoundingBox.Max.y - BoundingBox.Min.y ) * 0.05f;
BoundingBox.Min.y -= ( BoundingBox.Max.y - BoundingBox.Min.y ) * 0.05f;
CameraInfo.fViewWidth = m_TerrainInfo.fTileSize * m_nBlockSizeX;
CameraInfo.fViewHeight = m_TerrainInfo.fTileSize * m_nBlockSizeY;
CameraInfo.fWidth = ( float )nWidth;
CameraInfo.fHeight = ( float )nHeight;
CameraInfo.Target = CT_RENDERTARGET_NO_GENERATE_BACKBUFFER;
CameraInfo.Type = CT_ORTHOGONAL;
CameraInfo.fFar = ( BoundingBox.Max.y - BoundingBox.Min.y );
hCamera = CreateCamera( &CameraInfo );
At = ( BoundingBox.Max + BoundingBox.Min ) / 2.0f;
At.y = BoundingBox.Min.y;
Eye = At + LightDir * ( BoundingBox.Max.y - BoundingBox.Min.y );
hCamera->LookAt( Eye, At, EtVector3( 0.0f, 1.0f, 0.0f ) );
pViewMat = hCamera->GetViewMat();
pViewMat->_13 = 0.0f;
pViewMat->_23 = -1.0f;
pViewMat->_33 = 0.0f;
BoundingBox.Transform( *hCamera->GetViewProjMat() );
EtMatrixScaling( &ScaleMat, 1.0f / ( BoundingBox.Max.x - BoundingBox.Min.x ), 1.0f / ( BoundingBox.Max.y - BoundingBox.Min.y ),
1.0f / ( BoundingBox.Max.z - BoundingBox.Min.z ) );
EtMatrixTranslation( &TransMat, -( BoundingBox.Max.x + BoundingBox.Min.x ) / ( BoundingBox.Max.x - BoundingBox.Min.x ),
-( BoundingBox.Max.y + BoundingBox.Min.y ) / ( BoundingBox.Max.y - BoundingBox.Min.y ), -BoundingBox.Min.z );
pProjMat = hCamera->GetProjMat();
EtMatrixMultiply( pProjMat, pProjMat, &ScaleMat );
EtMatrixMultiply( pProjMat, pProjMat, &TransMat );
LightMapViewProjMat = *hCamera->GetViewProjMat();
}
EtTextureHandle CEtTerrainArea::BakeDepthLightMap( int nBlockIndex, EtTextureHandle hLightMap, LPD3DXRENDERTOSURFACE pDepthSurface, EtMaterialHandle hMaterial,
EtMatrix &LightMapViewProjMat, int nBakeRange, float fSlopeBias )
{
EtCameraHandle hCamera;
CreateLightCamera( nBlockIndex, hCamera, hLightMap->Width(), hLightMap->Height(), LightMapViewProjMat );
hCamera->Activate();
if( SUCCEEDED( pDepthSurface->BeginScene( hLightMap->GetSurfaceLevel(), NULL ) ) )
{
GetEtDevice()->EnableZ( true );
GetEtDevice()->ClearBuffer( 0xffffffff, 1.0f, 0 );
GetEtDevice()->SetCullMode( CULL_CW );
int i, j, nCount;
EtMatrix WorldMat;
EtVector3 TerrainOffset;
float fBlockWidth, fBlockHeight;
fBlockWidth = m_nBlockSizeX * m_TerrainInfo.fTileSize;
fBlockHeight = m_nBlockSizeY * m_TerrainInfo.fTileSize;
TerrainOffset = m_vecTerrain[ nBlockIndex ]->GetTerrainInfo()->TerrainOffset;
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
nCount = CEtObject::GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hObject;
EtSkinHandle hSkin;
hObject = CEtObject::GetItem( i );
if( !hObject )
{
continue;
}
if( !hObject->IsLightMapCast() )
{
continue;
}
WorldMat = *hObject->GetWorldMat();
WorldMat._41 -= TerrainOffset.x;
WorldMat._43 -= TerrainOffset.z;
if( ( WorldMat._41 > -fBlockWidth ) && ( WorldMat._41 < fBlockWidth * 2 ) && ( WorldMat._43 > -fBlockHeight ) && ( WorldMat._43 < fBlockHeight * 2 ) )
{
int nTexIndex;
hSkin = hObject->GetSkin();
if( hSkin && hSkin->GetMeshHandle() )
{
std::vector< std::vector< SCustomParam > > vecCustomParam;
vecCustomParam.resize( hSkin->GetMeshHandle()->GetSubMeshCount() );
for( int j = 0; j < hSkin->GetMeshHandle()->GetSubMeshCount(); j++) {
AddCustomParam( vecCustomParam[j], EPT_FLOAT, hMaterial, "g_fSlopeBias", &fSlopeBias );
nTexIndex = hSkin->GetDiffuseTexIndex( j );
AddCustomParam( vecCustomParam[j], EPT_TEX, hMaterial, "g_DiffuseTex", &nTexIndex );
}
hSkin->SetExternalMaterial( hMaterial, NULL, &vecCustomParam );
hSkin->Render( WorldMat, WorldMat, 1.0f, false );
hSkin->ClearExternalMaterial();
}
}
}
}
std::vector< SCustomParam > vecCustomParam;
AddCustomParam( vecCustomParam, EPT_FLOAT, hMaterial, "g_fSlopeBias", &fSlopeBias );
int nTexIndex = -1;
AddCustomParam( vecCustomParam, EPT_TEX, hMaterial, "g_DiffuseTex", &nTexIndex );
for( i = -nBakeRange; i <= nBakeRange; i++ )
{
for( j = -nBakeRange; j <= nBakeRange; j++ )
{
int nCurTerrainIndex;
EtMatrixIdentity( &WorldMat );
nCurTerrainIndex = nBlockIndex + i * m_nBlockCountX + j;
if( ( nCurTerrainIndex < 0 ) || ( nCurTerrainIndex >= ( int )m_vecTerrain.size() ) )
{
continue;
}
EtMatrixTranslation( &WorldMat, j * m_nBlockSizeX * m_TerrainInfo.fTileSize, 0.0f, i * m_nBlockSizeY * m_TerrainInfo.fTileSize );
hMaterial->SetTechnique( 0 );
hMaterial->SetWorldMatParams( &WorldMat, &WorldMat );
hMaterial->SetCustomParamList( vecCustomParam );
int nPasses;
hMaterial->BeginEffect( nPasses );
hMaterial->BeginPass( 0 );
hMaterial->CommitChanges();
m_vecTerrain[ nCurTerrainIndex ]->GetMeshStream().Draw( hMaterial->GetVertexDeclIndex( 0, 0 ) );
hMaterial->EndPass();
hMaterial->EndEffect();
}
}
pDepthSurface->EndScene( 0 );
}
GetEtDevice()->SetCullMode( CULL_NONE );
SAFE_RELEASE_SPTR( hCamera );
return hLightMap;
}
void CEtTerrainArea::BakeRoughLightMap( int nBlockIndex, EtTextureHandle hRoughLightMap, EtTextureHandle hDepthLightMap, LPD3DXRENDERTOSURFACE pRoughSurface, EtMaterialHandle hMaterial, EtCameraHandle hCamera, int nWidth, int nHeight, EtMatrix &LightMapViewProjMat )
{
std::vector< SCustomParam > vecCustomParam;
SAABox BoundingBox;
int i, j, nTexIndex;
EtVector3 Eye, At, TerrainOffset;
EtMatrix WorldLightViewProjMat;
SCameraInfo CameraInfo;
CameraInfo.fViewWidth = m_TerrainInfo.fTileSize * m_nBlockSizeX * 2.0f;
CameraInfo.fViewHeight = m_TerrainInfo.fTileSize * m_nBlockSizeY * 2.0f;
CameraInfo.fWidth = ( float )nWidth;
CameraInfo.fHeight = ( float )nHeight;
CameraInfo.Type = CT_ORTHOGONAL;
CameraInfo.Target = CT_RENDERTARGET_NO_GENERATE_BACKBUFFER;
TerrainOffset = m_vecTerrain[ nBlockIndex ]->GetTerrainInfo()->TerrainOffset;
BoundingBox = *GetBoundingBox( nBlockIndex );
BoundingBox.Max.y = m_BoundingBox.Max.y;
BoundingBox.Min.y = m_BoundingBox.Min.y;
BoundingBox.Max.x -= TerrainOffset.x;
BoundingBox.Max.z -= TerrainOffset.z;
BoundingBox.Min.x -= TerrainOffset.x;
BoundingBox.Min.z -= TerrainOffset.z;
if( BoundingBox.Max.y - BoundingBox.Min.y < 1000.0f )
{
BoundingBox.Max.y = BoundingBox.Min.y + 1000.0f;
}
CameraInfo.fFar = ( BoundingBox.Max.y - BoundingBox.Min.y ) * 1.1f;
hCamera->Initialize( &CameraInfo );
At = ( BoundingBox.Max + BoundingBox.Min ) / 2.0f;
At.y = BoundingBox.Min.y;
Eye = At;
Eye.y += ( BoundingBox.Max.y - BoundingBox.Min.y ) * 1.05f;
hCamera->LookAt( Eye, At, EtVector3( 0.0f, 0.0f, 1.0f ) );
nTexIndex = hDepthLightMap->GetMyIndex();
AddCustomParam( vecCustomParam, EPT_TEX, hMaterial, "g_LightMapTex", &nTexIndex );
AddCustomParam( vecCustomParam, EPT_MATRIX_PTR, hMaterial, "g_BakeLightViewProjMat", &WorldLightViewProjMat );
EtMatrix WorldMat;
int nPasses;
GetEtDevice()->EnableZ( false );
GetEtDevice()->SetCullMode( CULL_NONE );
hCamera->Activate();
if( SUCCEEDED( pRoughSurface->BeginScene( hRoughLightMap->GetSurfaceLevel() , NULL) ) )
{
GetEtDevice()->ClearBuffer( 0xffffffff, 1.0f, 0 );
CEtLight::SetDirLightAttenuation( 1.0f );
for( i = -1; i <= 1; i++ )
{
for( j = -1; j <= 1; j++ )
{
int nCurTerrainIndex;
EtMatrixIdentity( &WorldMat );
nCurTerrainIndex = nBlockIndex + i * m_nBlockCountX + j;
if( ( nCurTerrainIndex < 0 ) || ( nCurTerrainIndex >= ( int )m_vecTerrain.size() ) )
{
continue;
}
EtMatrixTranslation( &WorldMat, j * m_nBlockSizeX * m_TerrainInfo.fTileSize, 0.0f, i * m_nBlockSizeY * m_TerrainInfo.fTileSize );
EtMatrixMultiply( &WorldLightViewProjMat, &WorldMat, &LightMapViewProjMat );
hMaterial->SetTechnique( 1 );
hMaterial->SetGlobalParams();
hMaterial->SetWorldMatParams( &WorldMat, &WorldMat );
hMaterial->SetCustomParamList( vecCustomParam );
hMaterial->BeginEffect( nPasses );
hMaterial->BeginPass( 0 );
hMaterial->CommitChanges();
m_vecTerrain[ nCurTerrainIndex ]->GetMeshStream().Draw( hMaterial->GetVertexDeclIndex( 1, 0 ) );
hMaterial->EndPass();
hMaterial->EndEffect();
}
}
GetEtDevice()->SetCullMode( CULL_CCW );
GetEtDevice()->EnableZ( true );
pRoughSurface->EndScene( 0 );
}
}
void CEtTerrainArea::CreateLightMapInfluenceBuffer()
{
if( m_pLightMapInfluenceBuffer )
{
return;
}
m_nLightMapInfluenceStride = m_TerrainInfo.nSizeX / 8;
if( m_TerrainInfo.nSizeX % 8 )
{
m_nLightMapInfluenceStride++;
}
m_pLightMapInfluenceBuffer = new char[ m_nLightMapInfluenceStride * (m_TerrainInfo.nSizeY+1) ];
memset( m_pLightMapInfluenceBuffer, 0, m_nLightMapInfluenceStride * (m_TerrainInfo.nSizeY+1) );
}
void CEtTerrainArea::SetLightMapInfluence( int nBlockIndex, char *pTexBuffer, int nTexStride, int nTexWidth, int nTexHeight )
{
CreateLightMapInfluenceBuffer();
int i, j, nBlockStartX, nBlockStartY;
nBlockStartX = nBlockIndex % m_nBlockCountX * m_nBlockSizeX;
nBlockStartY = nBlockIndex / m_nBlockCountX * m_nBlockSizeY;
for( i = 0; i < m_nBlockSizeY; i++ )
{
for( j = 0; j < m_nBlockSizeX; j++ )
{
int nHori, nVert;
int nOffset, nTexOffset;
char cShift;
nHori = ( int )( j / ( m_nBlockSizeX - 1.0f ) * ( nTexWidth - 1 ) );
nVert = ( int )( i / ( m_nBlockSizeY - 1.0f ) * ( nTexHeight - 1 ) );
nTexOffset = nVert * nTexStride + nHori * 4;
if( pTexBuffer[ nTexOffset + 1 ] == 0 )
{
nOffset = ( i + nBlockStartY ) * m_nLightMapInfluenceStride + ( j + nBlockStartX ) / 8;
cShift = ( ( char )( 0x1 ) ) << ( ( j + nBlockStartX ) % 8 );
m_pLightMapInfluenceBuffer[ nOffset ] |= cShift;
}
}
}
if( !m_vecGrassBlock.empty() )
{
int nGrassBlockIndex;
nGrassBlockIndex = ( nBlockIndex % m_nBlockCountX ) * 2 + ( nBlockIndex / m_nBlockCountX ) * m_nBlockCountX * 4;
if( m_vecGrassBlock[ nGrassBlockIndex ] )
{
m_vecGrassBlock[ nGrassBlockIndex ]->SetLightMapInfluence( pTexBuffer, nTexStride, nTexWidth, nTexHeight, 0.0f, 0.0f );
}
nGrassBlockIndex++;
if( m_vecGrassBlock[ nGrassBlockIndex ] )
{
m_vecGrassBlock[ nGrassBlockIndex ]->SetLightMapInfluence( pTexBuffer, nTexStride, nTexWidth, nTexHeight, 0.5f, 0.0f );
}
nGrassBlockIndex += m_nBlockCountX * 2;
if( m_vecGrassBlock[ nGrassBlockIndex ] )
{
m_vecGrassBlock[ nGrassBlockIndex ]->SetLightMapInfluence( pTexBuffer, nTexStride, nTexWidth, nTexHeight, 0.5f, 0.5f );
}
nGrassBlockIndex--;
if( m_vecGrassBlock[ nGrassBlockIndex ] )
{
m_vecGrassBlock[ nGrassBlockIndex ]->SetLightMapInfluence( pTexBuffer, nTexStride, nTexWidth, nTexHeight, 0.0f, 0.5f );
}
}
}
float CEtTerrainArea::GetLightMapInfluence( float fX, float fZ )
{
if( m_pLightMapInfluenceBuffer == NULL )
{
return 1.0f;
}
int nCellX = 0 , nCellZ = 0;
float fWeight[ 4 ], fValue;
char cShift;
CalcCellPosition( fX, fZ, nCellX, nCellZ, fWeight );
if ( nCellX < 0 || nCellZ < 0 )
return 1.0f;
cShift = ( ( char )( 0x1 ) ) << ( nCellX % 8 );
fValue = m_pLightMapInfluenceBuffer[ nCellZ * m_nLightMapInfluenceStride + nCellX / 8 ] & cShift ? fWeight[ 0 ] : 0.0f;
nCellX++;
cShift = ( ( char )( 0x1 ) ) << ( nCellX % 8 );
fValue += m_pLightMapInfluenceBuffer[ nCellZ * m_nLightMapInfluenceStride + nCellX / 8 ] & cShift ? fWeight[ 1 ] : 0.0f;
nCellZ++;
cShift = ( ( char )( 0x1 ) ) << ( nCellX % 8 );
fValue += m_pLightMapInfluenceBuffer[ nCellZ * m_nLightMapInfluenceStride + nCellX / 8 ] & cShift ? fWeight[ 3 ] : 0.0f;
nCellX--;
cShift = ( ( char )( 0x1 ) ) << ( nCellX % 8 );
fValue += m_pLightMapInfluenceBuffer[ nCellZ * m_nLightMapInfluenceStride + nCellX / 8 ] & cShift ? fWeight[ 2 ] : 0.0f;
return 1.0f - fValue;
}
float CEtTerrainArea::CalcLightMapInfluence( float fX, float fZ )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i;
for( i = 0; i < GetItemCount(); i++ )
{
EtTerrainHandle hTerrainArea;
hTerrainArea = GetItem( i );
if( hTerrainArea->IsInside( fX, fZ ) )
{
return hTerrainArea->GetLightMapInfluence( fX, fZ );
}
}
return 1.0f;
}
void CEtTerrainArea::CalcCellPosition( float fX, float fZ, int &nCellX, int &nCellZ, float *pWeight, int nScale )
{
float fModX, fModZ;
fX -= m_TerrainInfo.TerrainOffset.x;
fZ -= m_TerrainInfo.TerrainOffset.z;
if( fX < 0.0f )
{
fX = 0.f;
}
else if( fX >= m_TerrainInfo.nSizeX * m_TerrainInfo.fTileSize )
{
fX = m_TerrainInfo.nSizeX * m_TerrainInfo.fTileSize - 0.1f;
}
if( fZ < 0.f )
{
fZ = 0.f;
}
else if( fZ >= m_TerrainInfo.nSizeY * m_TerrainInfo.fTileSize )
{
fZ = m_TerrainInfo.nSizeY * m_TerrainInfo.fTileSize - 0.1f;
}
nCellX = ( int )( fX / (m_TerrainInfo.fTileSize*nScale) );
nCellZ = ( int )( fZ / (m_TerrainInfo.fTileSize*nScale) );
fModX = fX / (m_TerrainInfo.fTileSize*nScale) - nCellX;
fModZ = fZ / (m_TerrainInfo.fTileSize*nScale) - nCellZ;
if( fModX > fModZ )
{
pWeight[ 0 ] = 1.0f - fModX;
pWeight[ 1 ] = fModX - fModZ;
pWeight[ 2 ] = 0.0f;
pWeight[ 3 ] = fModZ;
}
else if( fModX < fModZ )
{
pWeight[ 0 ] = 1.0f - fModZ;
pWeight[ 1 ] = 0.0f;
pWeight[ 2 ] = fModZ - fModX;
pWeight[ 3 ] = fModX;
}
else
{
pWeight[ 0 ] = 1.0f - fModZ;
pWeight[ 1 ] = 0.0f;
pWeight[ 2 ] = 0.0f;
pWeight[ 3 ] = fModZ;
}
}
float CEtTerrainArea::GetLandHeight( float fX, float fZ, EtVector3 *pNormal, int nScale )
{
int i;
float fRet;
int nCellX, nCellZ;
float fHeight[ 4 ], fWeight[ 4 ];
DWORD dwSectorWidth = m_TerrainInfo.nSizeX + 1;
CalcCellPosition( fX, fZ, nCellX, nCellZ, fWeight, nScale );
fHeight[ 0 ] = m_TerrainInfo.pHeight[ nCellZ * dwSectorWidth + nCellX ];
fHeight[ 1 ] = m_TerrainInfo.pHeight[ nCellZ * dwSectorWidth + nCellX + nScale ];
fHeight[ 2 ] = m_TerrainInfo.pHeight[ ( nCellZ + nScale ) * dwSectorWidth + nCellX ];
fHeight[ 3 ] = m_TerrainInfo.pHeight[ ( nCellZ + nScale ) * dwSectorWidth + nCellX + nScale ];
fRet = 0.0f;
for( i = 0; i < 4; i++ )
{
fRet += fHeight[ i ] * fWeight[ i ];
}
if( pNormal )
{
GetVertexNormal( *pNormal, nCellX, nCellZ );
}
return fRet * m_TerrainInfo.fHeightMultiply;
}
void CEtTerrainArea::GetLandNormal( EtVector3 &Normal, float fX, float fZ )
{
int i;
EtVector3 ReturnVec, VertexNormal[ 4 ];
int nCellX, nCellZ;
float fWeight[ 4 ];
CalcCellPosition( fX, fZ, nCellX, nCellZ, fWeight );
GetVertexNormal( VertexNormal[ 0 ], nCellX, nCellZ );
GetVertexNormal( VertexNormal[ 1 ], nCellX + 1, nCellZ );
GetVertexNormal( VertexNormal[ 2 ], nCellX, nCellZ + 1 );
GetVertexNormal( VertexNormal[ 3 ], nCellX + 1, nCellZ + 1 );
ReturnVec = EtVector3( 0.0f, 0.0f, 0.0f );;
for( i = 0; i < 4; i++ )
{
ReturnVec += VertexNormal[ i ] * fWeight[ i ];
}
EtVec3Normalize( &Normal, &ReturnVec );
}
void CEtTerrainArea::GetVertexNormal( EtVector3 &Normal, int nCellX, int nCellZ )
{
int nHeightIndex;
float fDX, fDZ;
EtVector3 Return;
DWORD dwTileWidth = m_TerrainInfo.nSizeX + 1;
DWORD dwTileHeight = m_TerrainInfo.nSizeY + 1;
nHeightIndex = dwTileWidth * nCellZ + nCellX;
if( nCellX == 0 )
{
fDX = ( m_TerrainInfo.pHeight[ nHeightIndex ] - m_TerrainInfo.pHeight[ nHeightIndex + 1 ] ) / m_TerrainInfo.fTileSize;
}
else if( nCellX == dwTileWidth - 1 )
{
fDX = ( m_TerrainInfo.pHeight[ nHeightIndex - 1 ] - m_TerrainInfo.pHeight[ nHeightIndex ] ) / m_TerrainInfo.fTileSize;
}
else
{
fDX = ( m_TerrainInfo.pHeight[ nHeightIndex - 1 ] - m_TerrainInfo.pHeight[ nHeightIndex + 1 ] ) / ( m_TerrainInfo.fTileSize * 2 );
}
if( nCellZ == 0 )
{
fDZ = ( m_TerrainInfo.pHeight[ nHeightIndex ] - m_TerrainInfo.pHeight[ nHeightIndex + dwTileWidth ] ) / m_TerrainInfo.fTileSize;
}
else if( nCellZ == dwTileHeight - 1 )
{
fDZ = ( m_TerrainInfo.pHeight[ nHeightIndex - dwTileWidth ] - m_TerrainInfo.pHeight[ nHeightIndex ] ) / m_TerrainInfo.fTileSize;
}
else
{
fDZ = ( m_TerrainInfo.pHeight[ nHeightIndex - dwTileWidth ] - m_TerrainInfo.pHeight[ nHeightIndex + dwTileWidth ] ) / ( m_TerrainInfo.fTileSize * 2 );
}
Return.x = fDX;
Return.y = 1.414f;
Return.z = fDZ;
EtVec3Normalize( &Normal, &Return );
}
void CEtTerrainArea::CreateGrassBlock()
{
if( m_TerrainInfo.pGrassBuffer == NULL )
{
return;
}
int i, j;
int nGrassBlockSize;
m_nGrassBlockCountX = m_nBlockCountX * 2;
m_nGrassBlockCountY = m_nBlockCountY * 2;
nGrassBlockSize = DEFAULT_TERRAIN_SIZE / 2;
for( i = 0; i < m_nGrassBlockCountY; i++ )
{
for( j = 0; j < m_nGrassBlockCountX; j++ )
{
CEtGrassBlock *pGrassBlock;
SGrassBlockInfo BlockInfo;
if( ( j + 1 ) * nGrassBlockSize <= m_TerrainInfo.nSizeX )
{
BlockInfo.nSizeX = nGrassBlockSize;
}
else
{
BlockInfo.nSizeX = m_TerrainInfo.nSizeX - j * nGrassBlockSize;
}
if( ( i + 1 ) * nGrassBlockSize <= m_TerrainInfo.nSizeY )
{
BlockInfo.nSizeY = nGrassBlockSize;
}
else
{
BlockInfo.nSizeY = m_TerrainInfo.nSizeY - i * nGrassBlockSize;
}
if( ( BlockInfo.nSizeX > 0 ) && ( BlockInfo.nSizeY > 0 ) )
{
pGrassBlock = new CEtGrassBlock();
// int nDivide = ( m_TerrainInfo.nSizeX / ( nGrassBlockSize * i ) ) ;
BlockInfo.pGrassBuffer = m_TerrainInfo.pGrassBuffer + ( i * m_TerrainInfo.nSizeX * nGrassBlockSize ) + ( j * nGrassBlockSize );
BlockInfo.nStride = m_TerrainInfo.nSizeX;
BlockInfo.fTileSize = m_TerrainInfo.fTileSize;
BlockInfo.GrassOffset.x = m_TerrainInfo.TerrainOffset.x + nGrassBlockSize * j * m_TerrainInfo.fTileSize;
BlockInfo.GrassOffset.y = m_TerrainInfo.TerrainOffset.y;
BlockInfo.GrassOffset.z = m_TerrainInfo.TerrainOffset.z + nGrassBlockSize * i * m_TerrainInfo.fTileSize;
memcpy( BlockInfo.fGrassWidth, m_TerrainInfo.fGrassWidth, sizeof( float ) * 4 );
memcpy( BlockInfo.fMaxGrassHeight, m_TerrainInfo.fMaxGrassHeight, sizeof( float ) * 4 );;
memcpy( BlockInfo.fMinGrassHeight, m_TerrainInfo.fMinGrassHeight, sizeof( float ) * 4 );;;
BlockInfo.fMaxShake = m_TerrainInfo.fMaxShake;
BlockInfo.fMinShake = m_TerrainInfo.fMinShake;
pGrassBlock->SetGrassBlockInfo( &BlockInfo );
}
else
{
pGrassBlock = NULL;
}
m_vecGrassBlock.push_back( pGrassBlock );
}
}
}
void CEtTerrainArea::CheckBakeLightMap()
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i, j, nCount;
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtTerrainHandle hTerrainArea;
hTerrainArea = GetItem( i );
if( hTerrainArea )
{
int nBakeLightMapCount = hTerrainArea->GetBakeLightMapParamCount();
SBakeLightMapParam Param;
for( j = 0; j < nBakeLightMapCount; j++ )
{
hTerrainArea->GetBakeLightMapParam( j, Param );
hTerrainArea->_BakeLightMap( Param.nBlockIndex, Param.nWidth, Param.nHeight, Param.fBlurSize, Param.nBakeRange, Param.fSlopeBias );
}
hTerrainArea->m_vecBakeLightMapParam.clear();
}
}
}
void CEtTerrainArea::ReloadMaterial()
{
CEtResource::FlushWaitDelete(); // RefCount 0 <20><> Material <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
EtMaterialHandle hMaterial;
hMaterial = CEtResource::GetResource( "LayeredTerrain.fx" );
if( hMaterial )
{
hMaterial->Reload();
// SAFE_RELEASE_SPTR( hMaterial );
//ASSERT( hMaterial->GetRefCount() > 0 );
}
hMaterial = CEtResource::GetResource( "LayeredCliffTerrain.fx" );
if( hMaterial )
{
hMaterial->Reload();
// SAFE_RELEASE_SPTR( hMaterial );
//ASSERT( hMaterial->GetRefCount() > 0 );b
}
}
EtTerrainHandle CEtTerrainArea::GetTerrainArea( float fX, float fZ )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i;
for( i = 0; i < GetItemCount(); i++ )
{
EtTerrainHandle hTerrainArea;
hTerrainArea = GetItem( i );
if( hTerrainArea->IsInside( fX, fZ ) )
{
return hTerrainArea;
}
}
return CEtTerrainArea::Identity();
}
void CEtTerrainArea::SetInteractivePos( EtVector3 *vPos, float fDelta )
{
int i, nSize;
nSize = ( int )m_vecGrassBlock.size();
for( i = 0; i < nSize; i++ )
{
if( ( m_vecGrassBlock[ i ] ) && ( m_vecGrassBlock[ i ]->GetGrassCount() > 0 ) )
{
m_vecGrassBlock[ i ]->SetInteractivePos( vPos, fDelta );
}
}
}