DragonNest/Client/EtWorldPainter/TEtWorldWaterRiver.cpp
2024-12-19 09:48:26 +08:00

1246 lines
40 KiB
C++

#include "StdAfx.h"
#include "TEtWorldWaterRiver.h"
#include "UnionValueProperty.h"
#include "PropertyGridCreator.h"
#include "PointAxisRenderObject.h"
#include "RenderBase.h"
#include "TEtWorldWater.h"
#include "TEtWorldSector.h"
#include "UnionValueProperty.h"
#include "resource.h"
#include "UserMessage.h"
#include "PaneDefine.h"
#include "MainFrm.h"
#include "TEtWorldGrid.h"
#include "SundriesFuncEx.h"
#include "EtWater.h"
#include "EngineUtil.h"
#include <map>
using namespace std;
PropertyGridBaseDefine g_WaterRiverPropertyDefine[] = {
{ "Shader", "Effect Name", CUnionValueProperty::String_FileOpen, "Shader File Name|Shader Effect File|*.fx", FALSE },
{ "Common", "Interpolation", CUnionValueProperty::Integer_Combo, "타입으로 사용되지 않으며 Lerp체크시 반사하지 않는 물로 바뀝니다.|Linear|Lerp|Hermite", TRUE },
{ "Common", "Width", CUnionValueProperty::Float, "River Width|0.f|10000.f|1.f", TRUE },
{ "Common", "UV U Ratio", CUnionValueProperty::Float, "Texture UV", TRUE },
{ "Common", "UV V Ratio", CUnionValueProperty::Float, "Texture UV", TRUE },
{ "Alphamap", "Width", CUnionValueProperty::Integer_Combo, "알파맵 가로 사이즈|32|64|128|256|512|1024|2048", TRUE },
{ "Alphamap", "Height", CUnionValueProperty::Integer_Combo, "알파맵 세로 사이즈|32|64|128|256|512|1024|2048", TRUE },
{ "Alphamap", "Border Reduction", CUnionValueProperty::Integer, "경계면 축소 카운트(Default=10)|0|50|1", TRUE },
{ "Alphamap", "Blur Value", CUnionValueProperty::Integer, "블러값(Default=10)|0|30|1", TRUE },
{ "Alphamap", "Blur Epsilon", CUnionValueProperty::Float, "블러값2 위의 값이 커지면 가치 커져야 한다.(Default=7.f)|0.1f|30.f|0.01f", TRUE },
{ "Alphamap", "Min Alpha", CUnionValueProperty::Integer, "알파 최소값|0|255|1", TRUE },
{ "Alphamap", "Max Alpha", CUnionValueProperty::Integer, "알파 최대값|0|255|1", TRUE },
{ "Alphamap", "Revision Alpha", CUnionValueProperty::Float, "계산 후 알파값 보정|0.f|5.f|0.001f", TRUE },
{ NULL },
};
CTEtWorldWaterRiver::CTEtWorldWaterRiver( CEtWorldWater *pWater )
: CEtWorldWaterRiver( pWater )
{
m_pMesh = NULL;
m_szShaderName = "water.fx";
m_bDestroy = false;
SAFE_DELETEA( m_pAlphaTable );
if( m_pAlphaTable == NULL ) {
m_pAlphaTable = new BYTE[ m_nAlphaTableWidth * m_nAlphaTableHeight ];
for( int i=0; i<m_nAlphaTableHeight; i++ ) {
for( int j=0; j<m_nAlphaTableWidth; j++ ) {
m_pAlphaTable[ i * m_nAlphaTableWidth + j ] = 128;
}
}
}
((CTEtWorldWater*)m_pWater)->AddEngineWaterCount();
CreateMesh();
RefreshShader();
if( !m_hAlphaTexture ) {
RefreshTexture();
RefreshTextureAlpha();
}
}
CTEtWorldWaterRiver::~CTEtWorldWaterRiver()
{
m_bDestroy = true;
((CTEtWorldWater*)m_pWater)->DelEngineWaterCount();
std::map<std::string, EtTextureHandle>::iterator it;
for( it = m_MapTextureList.begin(); it!=m_MapTextureList.end(); it++ ) {
SAFE_RELEASE_SPTR( it->second );
}
m_MapTextureList.clear();
SAFE_RELEASE_SPTR( m_hAlphaTexture );
SAFE_DELETE_PVEC( m_pVecPropertyList );
SAFE_RELEASE_SPTR( m_hMaterial );
SAFE_RELEASE_SPTR( m_hAlphaTexture );
SAFE_DELETE( m_pMesh );
SAFE_DELETEA( m_pAlphaTable );
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
SAFE_DELETE( m_pVecPointList[i]->pAxis );
}
SAFE_DELETE_PVEC( m_pVecPointList );
SAFE_DELETE_VEC( m_VecPrimitiveList );
}
CTEtWorldWaterRiver::RiverPoint *CTEtWorldWaterRiver::InsertPoint( EtVector3 &vPos, EtVector3 *pInsertAfter )
{
RiverPoint *pPoint = new RiverPoint;
pPoint->vPos = vPos;
pPoint->bSelect = false;
pPoint->pAxis = new CPointAxisRenderObject( &pPoint->vPos );
pPoint->pAxis->Initialize();
pPoint->pAxis->Show( pPoint->bSelect );
if( pInsertAfter ) {
for( DWORD i=(int)m_pVecPointList.size()-1; i>=0; i-- ) {
if( m_pVecPointList[i]->vPos == *pInsertAfter ) {
m_pVecPointList.insert( m_pVecPointList.begin() + i + 1, pPoint );
break;
}
}
}
else {
m_pVecPointList.push_back( pPoint );
}
UpdatePoint();
return pPoint;
}
bool CTEtWorldWaterRiver::RemovePoint( RiverPoint *pPoint )
{
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( m_pVecPointList[i] == pPoint ) {
m_pVecPointList[i]->bSelect = false;
m_pVecPointList[i]->pAxis->Show( false );
SAFE_DELETE( m_pVecPointList[i]->pAxis );
SAFE_DELETE( m_pVecPointList[i] );
m_pVecPointList.erase( m_pVecPointList.begin() + i );
UpdatePoint();
return true;
}
}
return false;
}
void CTEtWorldWaterRiver::Render( LOCAL_TIME LocalTime )
{
EtVector3 vLine[2];
DWORD dwColor;
if( CGlobalValue::GetInstance().m_nActiveView == CGlobalValue::WATER ) {
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( i < m_pVecPointList.size() - 1 ) {
vLine[0] = m_pVecPointList[i]->vPos;
vLine[1] = m_pVecPointList[i+1]->vPos;
EternityEngine::DrawLine3D( vLine[0], vLine[1], 0xFF2222FF );
}
if( m_pVecPointList[i]->bSelect ) dwColor = 0xFFFF0000;
else dwColor = 0xFFFFFFFF;
EternityEngine::DrawPoint3D( m_pVecPointList[i]->vPos, dwColor, NULL, false );
}
if( m_VecPrimitiveList.size() >= 4 ) {
for( DWORD i=0; i<m_VecPrimitiveList.size() - 3; i+=2 ) {
EternityEngine::DrawLine3D( m_VecPrimitiveList[i], m_VecPrimitiveList[i+1] );
EternityEngine::DrawLine3D( m_VecPrimitiveList[i], m_VecPrimitiveList[i+2] );
EternityEngine::DrawLine3D( m_VecPrimitiveList[i], m_VecPrimitiveList[i+3] );
EternityEngine::DrawLine3D( m_VecPrimitiveList[i+1], m_VecPrimitiveList[i+3] );
}
EternityEngine::DrawLine3D( m_VecPrimitiveList[m_VecPrimitiveList.size()-2], m_VecPrimitiveList[m_VecPrimitiveList.size()-1] );
}
}
if( m_pVecPointList.empty() ) return;
GetEtWater()->SetWaterHeight( ((CTEtWorldWater*)m_pWater)->GetEngineWaterIndex(this), m_pVecPointList[0]->vPos.y );
GetEtWater()->SetWaterIgnoreBake( ((CTEtWorldWater*)m_pWater)->GetEngineWaterIndex(this), m_InterpolationType == CEtWorldWaterRiver::CatmullRom );
if( m_pVecPointList.size() > 1 ) {
SRenderStackElement RenderElement;
EtMatrix WorldMat;
EtMatrixIdentity( &WorldMat );
RenderElement.hMaterial = m_hMaterial;
RenderElement.nTechniqueIndex = 0;
RenderElement.WorldMat = WorldMat;
RenderElement.PrevWorldMat = WorldMat;
RenderElement.nSaveMatIndex = -1;
RenderElement.pvecCustomParam = &m_vecCustomParam;
RenderElement.pRenderMeshStream = m_pMesh;
RenderElement.renderPriority = RP_HIGH;
GetCurRenderStack()->AddAlphaRenderElement( RenderElement );
}
}
void CTEtWorldWaterRiver::RenderCustom( float fElapsedTime )
{
}
bool CTEtWorldWaterRiver::CheckSelect( EtVector2 vMin, EtVector2 vMax, char cFlag )
{
EtMatrix matWorld, matTemp;
MatrixEx *pVec = CRenderBase::GetInstance().GetLastUpdateCamera();
EtMatrix matView = *(*pVec);
EtMatrixInverse( &matView, NULL, &matView );
EtMatrix matProj = *CRenderBase::GetInstance().GetCameraHandle()->GetProjMat();
EtMatrixIdentity( &matWorld );
EtMatrixMultiply( &matTemp, &matView, &matWorld );
EtMatrixMultiply( &matTemp, &matTemp, &matProj );
D3DXMatrixInverse( &matView, NULL, &matView );
EtVector3 Pos, Normal;
bool bFlag = false;
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
Pos = m_pVecPointList[i]->vPos;
EtVec3Normalize( &Normal, &Pos );
EtVec3TransformCoord( &Pos, &Pos, &matTemp );
if( CheckRect( Pos.x, Pos.y, vMin, vMax ) == true )
{
switch( cFlag ) {
case -1:
case 0:
case 1:
m_pVecPointList[i]->bSelect = true;
m_pVecPointList[i]->pAxis->Show( true );
if( std::find( CGlobalValue::GetInstance().m_pVecSelectPointList.begin(), CGlobalValue::GetInstance().m_pVecSelectPointList.end(), m_pVecPointList[i] )
== CGlobalValue::GetInstance().m_pVecSelectPointList.end() )
CGlobalValue::GetInstance().m_pVecSelectPointList.push_back( m_pVecPointList[i] );
if( std::find( CGlobalValue::GetInstance().m_pVecSelectRiverList.begin(), CGlobalValue::GetInstance().m_pVecSelectRiverList.end(), this )
== CGlobalValue::GetInstance().m_pVecSelectRiverList.end() )
CGlobalValue::GetInstance().m_pVecSelectRiverList.push_back( this );
if( cFlag == -1 ) return true;
bFlag = true;
break;
case 2: //삭제
{
m_pVecPointList[i]->bSelect = false;
m_pVecPointList[i]->pAxis->Show( false );
std::vector<RiverPoint *>::iterator it = std::find( CGlobalValue::GetInstance().m_pVecSelectPointList.begin(), CGlobalValue::GetInstance().m_pVecSelectPointList.end(), m_pVecPointList[i] );
if( it != CGlobalValue::GetInstance().m_pVecSelectPointList.end() ) {
CGlobalValue::GetInstance().m_pVecSelectPointList.erase( it );
}
bFlag = false;
}
break;
}
}
else {
switch( cFlag )
{
case -1:
case 0:
m_pVecPointList[i]->bSelect = false;
m_pVecPointList[i]->pAxis->Show( false );
std::vector<RiverPoint *>::iterator it = std::find( CGlobalValue::GetInstance().m_pVecSelectPointList.begin(), CGlobalValue::GetInstance().m_pVecSelectPointList.end(), m_pVecPointList[i] );
if( it != CGlobalValue::GetInstance().m_pVecSelectPointList.end() ) {
CGlobalValue::GetInstance().m_pVecSelectPointList.erase( it );
}
break;
}
}
}
bool bSelect = false;
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( m_pVecPointList[i]->bSelect == true ) {
bSelect = true;
break;
}
}
if( bSelect ) {
if( std::find( CGlobalValue::GetInstance().m_pVecSelectRiverList.begin(), CGlobalValue::GetInstance().m_pVecSelectRiverList.end(), this )
== CGlobalValue::GetInstance().m_pVecSelectRiverList.end() )
CGlobalValue::GetInstance().m_pVecSelectRiverList.push_back( this );
}
else {
std::vector<CTEtWorldWaterRiver *>::iterator it = std::find( CGlobalValue::GetInstance().m_pVecSelectRiverList.begin(), CGlobalValue::GetInstance().m_pVecSelectRiverList.end(), this );
if( it != CGlobalValue::GetInstance().m_pVecSelectRiverList.end() )
CGlobalValue::GetInstance().m_pVecSelectRiverList.erase( it );
}
return bFlag;
}
void CTEtWorldWaterRiver::RefreshPrimitive()
{
switch( m_InterpolationType ) {
case Linear:
{
if( (int)m_pVecPointList.size() < 2 ) return;
EtVector3 vDir, vCross;
EtVector3 vVertex;
m_VecPrimitiveList.clear();
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( i == m_pVecPointList.size() - 1 ) {
vDir = m_pVecPointList[i]->vPos - m_pVecPointList[i-1]->vPos;
}
else {
vDir = m_pVecPointList[i+1]->vPos - m_pVecPointList[i]->vPos;
}
EtVec3Normalize( &vDir, &vDir );
EtVec3Cross( &vCross, &vDir, &EtVector3( 0.f, 1.f, 0.f ) );
vVertex = m_pVecPointList[i]->vPos + ( vCross * ( m_fWidth / 2.f ) );
vVertex.y = m_pVecPointList[i]->vPos.y;
m_VecPrimitiveList.push_back( vVertex );
vVertex = m_pVecPointList[i]->vPos - ( vCross * ( m_fWidth / 2.f ) );
vVertex.y = m_pVecPointList[i]->vPos.y;
m_VecPrimitiveList.push_back( vVertex );
}
}
break;
case CatmullRom:
{
// m_InterpolationType을 어쩔 수 없이 다른 의미로 사용하게 되었다.
// EtWorldWaterRiver.h의 m_InterpolationType 참고하기 바란다.
// Linear내용 그대로 복사.
if( (int)m_pVecPointList.size() < 2 ) return;
EtVector3 vDir, vCross;
EtVector3 vVertex;
m_VecPrimitiveList.clear();
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( i == m_pVecPointList.size() - 1 ) {
vDir = m_pVecPointList[i]->vPos - m_pVecPointList[i-1]->vPos;
}
else {
vDir = m_pVecPointList[i+1]->vPos - m_pVecPointList[i]->vPos;
}
EtVec3Normalize( &vDir, &vDir );
EtVec3Cross( &vCross, &vDir, &EtVector3( 0.f, 1.f, 0.f ) );
vVertex = m_pVecPointList[i]->vPos + ( vCross * ( m_fWidth / 2.f ) );
vVertex.y = m_pVecPointList[i]->vPos.y;
m_VecPrimitiveList.push_back( vVertex );
vVertex = m_pVecPointList[i]->vPos - ( vCross * ( m_fWidth / 2.f ) );
vVertex.y = m_pVecPointList[i]->vPos.y;
m_VecPrimitiveList.push_back( vVertex );
}
}
break;
case Helmite:
{
}
break;
}
}
bool CTEtWorldWaterRiver::CreateMesh()
{
SAFE_DELETE( m_pMesh );
m_pMesh = new CEtMeshStream;
RefreshVertex();
RefreshIndex();
RefreshNormal();
RefreshTextureCoord();
return true;
}
void CTEtWorldWaterRiver::RefreshTextureCoord()
{
if( !m_pMesh ) return;
if( m_pVecPointList.size() < 2 ) return;
float fWidth = (float)GetWater()->GetSector()->GetParentGrid()->GetGridWidth() * 100.f;
float fHeight = (float)GetWater()->GetSector()->GetParentGrid()->GetGridHeight() * 100.f;
EtVector3 vOffset = *GetWater()->GetSector()->GetOffset();
vOffset.x -= ( GetWater()->GetSector()->GetTileWidthCount() * GetWater()->GetSector()->GetTileSize() ) / 2.f;
vOffset.z -= ( GetWater()->GetSector()->GetTileHeightCount() * GetWater()->GetSector()->GetTileSize() ) / 2.f;
int nSize = (int)m_pVecPointList.size() * 2;
EtVector2 *pUV = new EtVector2[ nSize ];
EtVector3 vDir, vCross;
EtVector3 vVertex;
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( i == m_pVecPointList.size() - 1 ) {
vDir = m_pVecPointList[i]->vPos - m_pVecPointList[i-1]->vPos;
}
else {
vDir = m_pVecPointList[i+1]->vPos - m_pVecPointList[i]->vPos;
}
EtVec3Normalize( &vDir, &vDir );
EtVec3Cross( &vCross, &vDir, &EtVector3( 0.f, 1.f, 0.f ) );
vVertex = m_pVecPointList[i]->vPos + ( vCross * ( m_fWidth / 2.f ) ) - vOffset;
pUV[(i*2)].x = ( m_vUVRatio.x / fWidth ) * vVertex.x;
pUV[(i*2)].y = ( m_vUVRatio.y / fHeight ) * vVertex.z;
vVertex = m_pVecPointList[i]->vPos - ( vCross * ( m_fWidth / 2.f ) ) - vOffset;
pUV[(i*2)+1].x = ( m_vUVRatio.x / fWidth ) * vVertex.x;
pUV[(i*2)+1].y = ( m_vUVRatio.y / fHeight ) * vVertex.z;
}
CMemoryStream Stream( pUV, sizeof(EtVector2) * nSize );
m_pMesh->LoadVertexStream( &Stream, MST_TEXCOORD, 0, nSize );
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( i == m_pVecPointList.size() - 1 ) {
vDir = m_pVecPointList[i]->vPos - m_pVecPointList[i-1]->vPos;
}
else {
vDir = m_pVecPointList[i+1]->vPos - m_pVecPointList[i]->vPos;
}
EtVec3Normalize( &vDir, &vDir );
EtVec3Cross( &vCross, &vDir, &EtVector3( 0.f, 1.f, 0.f ) );
vVertex = m_pVecPointList[i]->vPos + ( vCross * ( m_fWidth / 2.f ) );
pUV[(i*2)].x = ( 1.f / m_vSize.x ) * ( vVertex.x - m_vOffset.x );
pUV[(i*2)].y = ( 1.f / m_vSize.y ) * ( vVertex.z - m_vOffset.y );
vVertex = m_pVecPointList[i]->vPos - ( vCross * ( m_fWidth / 2.f ) );
pUV[(i*2)+1].x = ( 1.f / m_vSize.x ) * ( vVertex.x - m_vOffset.x );
pUV[(i*2)+1].y = ( 1.f / m_vSize.y ) * ( vVertex.z - m_vOffset.y );
}
Stream.Initialize( pUV, sizeof(EtVector2) * nSize );
m_pMesh->LoadVertexStream( &Stream, MST_TEXCOORD, 1, nSize );
SAFE_DELETE( pUV );
}
void CTEtWorldWaterRiver::RefreshVertex()
{
if( !m_pMesh ) return;
if( m_pVecPointList.size() < 2 ) return;
int nSize = (int)m_pVecPointList.size() * 2;
EtVector3 *pVertex = new EtVector3[ nSize ];
EtVector3 vDir, vCross;
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( i == m_pVecPointList.size() - 1 ) {
vDir = m_pVecPointList[i]->vPos - m_pVecPointList[i-1]->vPos;
}
else {
vDir = m_pVecPointList[i+1]->vPos - m_pVecPointList[i]->vPos;
}
EtVec3Normalize( &vDir, &vDir );
EtVec3Cross( &vCross, &vDir, &EtVector3( 0.f, 1.f, 0.f ) );
pVertex[ i*2 ] = m_pVecPointList[i]->vPos + ( vCross * ( m_fWidth / 2.f ) );
pVertex[ (i*2) + 1 ] = m_pVecPointList[i]->vPos - ( vCross * ( m_fWidth / 2.f ) );
}
CMemoryStream Stream( pVertex, sizeof(EtVector3) * nSize );
m_pMesh->LoadVertexStream( &Stream, MST_POSITION, 0, nSize );
SAFE_DELETE( pVertex );
}
void CTEtWorldWaterRiver::RefreshIndex()
{
if( !m_pMesh ) return;
if( m_pVecPointList.size() < 2 ) return;
int nSize = ( (int)m_pVecPointList.size() - 1 ) * 6;
WORD *pIndex = new WORD[ nSize ];
int nOffset;
for( int i=0; i<(int)m_pVecPointList.size()-1; i++ ) {
nOffset = (i*6);
pIndex[nOffset] = (i*2);
pIndex[nOffset+1] = ((i+1)*2);
pIndex[nOffset+2] = (i*2)+1;
pIndex[nOffset+3] = (i*2)+1;
pIndex[nOffset+4] = ((i+1)*2);
pIndex[nOffset+5] = ((i+1)*2)+1;
}
CMemoryStream Stream( pIndex, sizeof(WORD) * nSize );
m_pMesh->LoadIndexStream( &Stream, false, nSize );
SAFE_DELETE( pIndex );
}
void CTEtWorldWaterRiver::RefreshNormal()
{
if( !m_pMesh ) return;
if( m_pVecPointList.size() < 2 ) return;
int nSize = (int)m_pVecPointList.size() * 2;
EtVector3 *pVertex = new EtVector3[ nSize ];
EtVector3 vDir, vCross;
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( i == m_pVecPointList.size() - 1 ) {
vDir = m_pVecPointList[i]->vPos - m_pVecPointList[i-1]->vPos;
}
else {
vDir = m_pVecPointList[i+1]->vPos - m_pVecPointList[i]->vPos;
}
EtVec3Normalize( &vDir, &vDir );
EtVec3Cross( &vCross, &vDir, &EtVector3( 0.f, 1.f, 0.f ) );
pVertex[ i*2 ] = EtVector3( 0.f, 1.f, 0.f );
pVertex[ (i*2) + 1 ] = EtVector3( 0.f, 1.f, 0.f );
}
CMemoryStream Stream( pVertex, sizeof(EtVector3) * nSize );
m_pMesh->LoadVertexStream( &Stream, MST_NORMAL, 0, nSize );
SAFE_DELETE( pVertex );
}
void CTEtWorldWaterRiver::RefreshShader()
{
SAFE_RELEASE_SPTR( m_hMaterial );
RefreshPropertyList();
CUnionValueProperty *pVariable;
m_hMaterial = LoadResource( m_szShaderName.c_str(), RT_SHADER );
EtParameterHandle hParam;
EffectParamType Type;
for( int i=0; i<m_hMaterial->GetCustomParamCount(); i++ ) {
hParam = m_hMaterial->GetCustomParamHandle(i);
Type = m_hMaterial->GetCustomParamType(i);
const char *szName = m_hMaterial->GetParameterName( hParam );
// 보여줄 필요 없는 파라메터 여기서 걸러주자.
if( _stricmp( szName, "g_TransparencyTex" ) == NULL ) continue;
if( _stricmp( szName, "g_WaterMapTex" ) == NULL ) continue;
if( _stricmp( szName, "g_LastViewMat" ) == NULL ) continue;
///////////////////////////////////////////////
if( Type == EPT_TEX ) {
pVariable = new CUnionValueProperty( CUnionValueProperty::String_FileOpen );
pVariable->SetCategory( "Texture" );
pVariable->SetDescription( szName );
pVariable->SetSubDescription( "Texture File|All Texture Files|*.dds;*.jpg;*.tga;*.bmp" );
pVariable->SetDefaultEnable( TRUE );
int nIndex = -1;
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, szName, &nIndex );
}
else {
switch( Type ) {
case EPT_VECTOR:
{
pVariable = new CUnionValueProperty( CUnionValueProperty::Vector4Color );
EtVector4 vVec = pVariable->GetVariableVector4();
AddCustomParam( m_vecCustomParam, EPT_VECTOR, m_hMaterial, szName, &vVec );
}
break;
case EPT_FLOAT:
{
pVariable = new CUnionValueProperty( CUnionValueProperty::Float );
float fValue = pVariable->GetVariableFloat();
AddCustomParam( m_vecCustomParam, EPT_FLOAT, m_hMaterial, szName, &fValue );
}
break;
case EPT_INT:
{
pVariable = new CUnionValueProperty( CUnionValueProperty::Integer );
int nValue = pVariable->GetVariableInt();
AddCustomParam( m_vecCustomParam, EPT_INT, m_hMaterial, szName, &nValue );
}
break;
}
pVariable->SetCategory( "Shader Parameter" );
pVariable->SetDescription( szName );
pVariable->SetSubDescription( "Shader Setting Value" );
pVariable->SetDefaultEnable( TRUE );
}
m_pVecPropertyList.push_back( pVariable );
}
CWnd *pWnd = GetPaneWnd( WATERPROP_PANE );
if( pWnd ) pWnd->SendMessage( UM_REFRESH_PANE_VIEW, 2, (LPARAM)this );
}
void CTEtWorldWaterRiver::RefreshTexture( bool bInit )
{
SAFE_RELEASE_SPTR( m_hAlphaTexture );
m_hAlphaTexture = CEtTexture::CreateNormalTexture( m_nAlphaTableWidth, m_nAlphaTableHeight, FMT_A8R8G8B8, USAGE_DEFAULT, POOL_MANAGED );
if( bInit ) {
int nStride;
DWORD *pPtr = (DWORD*)m_hAlphaTexture->Lock( nStride, true );
for( int j=0; j<m_nAlphaTableHeight; j++ ) {
for( int i=0; i<m_nAlphaTableWidth; i++ ) {
*pPtr = D3DCOLOR_ARGB( 128, 0, 0, 0 );
pPtr++;
}
}
m_hAlphaTexture->Unlock();
}
if( m_hAlphaTexture ) {
int nTexIndex = m_hAlphaTexture.GetIndex();
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, "g_TransparencyTex", &nTexIndex );
}
RefreshWaterTexture();
}
void CTEtWorldWaterRiver::RefreshWaterTexture()
{
if( !m_hMaterial ) return;
int nIndex = ((CTEtWorldWater*)m_pWater)->GetEngineWaterIndex(this);
int nTexIndex = -1;
if( nIndex >= 0 ) {
EtTextureHandle hTexture = GetEtWater()->GetWaterMapTexture( nIndex );
nTexIndex = hTexture.GetIndex();
}
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, "g_WaterMapTex", &nTexIndex );
}
void CTEtWorldWaterRiver::RefreshTextureAlpha()
{
int nStride;
float fValue;
DWORD *pPtr = (DWORD*)m_hAlphaTexture->Lock( nStride, true );
for( int j=0; j<m_nAlphaTableHeight; j++ ) {
for( int i=0; i<m_nAlphaTableWidth; i++ ) {
fValue = m_pAlphaTable[j*m_nAlphaTableWidth+i] * m_fRevisionAlpha;
if( fValue < 0.f ) fValue = 0.f;
if( fValue > 255.f ) fValue = 255.f;
*pPtr = D3DCOLOR_ARGB( (BYTE)fValue, 0, 0, 0 );
pPtr++;
}
}
m_hAlphaTexture->Unlock();
}
bool CTEtWorldWaterRiver::GetRiverHeight( EtVector2 &vPos, float &fHeight )
{
EtVector3 vVertex[3];
EtVector3 vPosTemp = EtVector3( vPos.x, -10000.f, vPos.y );
float fDist, fBary1, fBary2;
for( DWORD i=0; i<m_VecPrimitiveList.size() - 3; i+=2 ) {
vVertex[0] = m_VecPrimitiveList[i];
vVertex[1] = m_VecPrimitiveList[i+2];
vVertex[2] = m_VecPrimitiveList[i+1];
if( TestLineToTriangle( vPosTemp, EtVector3( 0.f, 1.f, 0.f ), vVertex[0], vVertex[1], vVertex[2], fDist, fBary1, fBary2 ) == true ) {
fHeight = vPosTemp.y + fDist;
return true;
}
vVertex[0] = m_VecPrimitiveList[i+1];
vVertex[1] = m_VecPrimitiveList[i+2];
vVertex[2] = m_VecPrimitiveList[i+3];
if( TestLineToTriangle( vPosTemp, EtVector3( 0.f, 1.f, 0.f ), vVertex[0], vVertex[1], vVertex[2], fDist, fBary1, fBary2 ) == true ) {
fHeight = vPosTemp.y + fDist;
return true;
}
}
return false;
}
void CTEtWorldWaterRiver::GenerationAlphaMap()
{
SAFE_DELETEA( m_pAlphaTable );
m_pAlphaTable = new BYTE[ m_nAlphaTableWidth * m_nAlphaTableHeight ];
EtVector2 vPos;
float fValue;
float fMin = (float)m_nMinAlpha;
float fMax = (float)m_nMaxAlpha;
float fHeight;
for( int j=0; j<m_nAlphaTableHeight; j++ ) {
for( int i=0; i<m_nAlphaTableWidth; i++ ) {
vPos.x = m_vOffset.x + ( ( m_vSize.x / (float)m_nAlphaTableWidth ) * i );
vPos.y = m_vOffset.y + ( ( m_vSize.y / (float)m_nAlphaTableHeight ) * j );
fValue = GetWater()->GetSector()->GetHeightToWorld( vPos.x, vPos.y );
if( GetRiverHeight( vPos, fHeight ) == true ) {
if( fValue > fHeight )
m_pAlphaTable[j*m_nAlphaTableWidth+i] = (BYTE)fMin;
else m_pAlphaTable[j*m_nAlphaTableWidth+i] = (BYTE)fMax;
}
else {
m_pAlphaTable[j*m_nAlphaTableWidth+i] = (BYTE)fMin;
}
}
}
// 버퍼를 Float 로 변형한 담에 하자.
int nBufferSize = m_nAlphaTableWidth * m_nAlphaTableHeight;
float *pTable = new float[nBufferSize];
for( int j=0; j<m_nAlphaTableHeight; j++ ) {
for( int i=0; i<m_nAlphaTableWidth; i++ ) {
int nIndex = j * m_nAlphaTableWidth + i;
pTable[nIndex] = (float)m_pAlphaTable[nIndex];
}
}
float *pTempBuf1 = new float[nBufferSize];
float *pTempBuf2 = new float[nBufferSize];
int nTempWidth = m_nAlphaTableWidth - 1;
int nTempHeight = m_nAlphaTableHeight - 1;
float fReduction = ( fMax - fMin ) / (float)m_nBorderReduction;
for( int g=0; g<m_nBorderReduction; g++ ) {
memcpy( pTempBuf1, pTable, sizeof(float) * m_nAlphaTableWidth * m_nAlphaTableHeight );
memcpy( pTempBuf2, pTable, sizeof(float) * m_nAlphaTableWidth * m_nAlphaTableHeight );
fMin = fReduction * g;
fValue = fReduction * (g+1);
for( int j=0; j<nTempHeight; j++ ) {
for( int i=0; i<nTempWidth; i++ ) {
int nIndex = j * m_nAlphaTableWidth + i;
if( pTable[nIndex] == fMin && pTable[nIndex+1] == fMax ) {
pTempBuf1[nIndex+1] = fValue;
}
else if( pTable[nIndex] == fMax && pTable[nIndex+1] == fMin ) {
pTempBuf1[nIndex] = fValue;
}
}
}
for( int j=0; j<nTempHeight; j++ ) {
for( int i=0; i<nTempWidth; i++ ) {
int nIndex = j * m_nAlphaTableWidth + i;
int nIndex2 = (j+1) * m_nAlphaTableWidth + i;
if( pTable[nIndex] == fMin && pTable[nIndex2] == fMax ) {
pTempBuf2[nIndex2] = fValue;
}
else if( pTable[nIndex] == fMax && pTable[nIndex2] == fMin ) {
pTempBuf2[nIndex] = fValue;
}
}
}
for( int j=0; j<m_nAlphaTableHeight; j++ ) {
for( int i=0; i<m_nAlphaTableWidth; i++ ) {
int nIndex = j*m_nAlphaTableWidth+i;
if( pTempBuf1[nIndex] == fValue || pTempBuf2[nIndex] == fValue ) pTable[nIndex] = fValue;
}
}
}
SAFE_DELETE( pTempBuf1 );
SAFE_DELETE( pTempBuf2 );
if( m_nGaussianValue > 0 ) {
int nBlurValue = m_nGaussianValue;
float **ppfGaussianTable;
int nTableSize = ( nBlurValue * 2 ) + 1;
ppfGaussianTable = new float*[nTableSize];
for( int i=0; i<nTableSize; i++ )
ppfGaussianTable[i] = new float[nTableSize];
CalcGaussianTable( nBlurValue, m_fGaussianEpsilon, ppfGaussianTable );
float *pTempBuf = new float[nBufferSize];
memcpy( pTempBuf, pTable, sizeof(float) * m_nAlphaTableWidth * m_nAlphaTableHeight );
for( int j=0; j<m_nAlphaTableHeight; j++ ) {
for( int i=0; i<m_nAlphaTableWidth; i++ ) {
if( i < nBlurValue ) continue;
if( i >= m_nAlphaTableWidth - nBlurValue ) continue;
if( j < nBlurValue ) continue;
if( j >= m_nAlphaTableHeight - nBlurValue ) continue;
pTable[j*m_nAlphaTableWidth+i] = GetNewAlpha( pTempBuf, i, j, nBlurValue, ppfGaussianTable );
}
}
for( int i=0; i<nTableSize; i++ ) {
SAFE_DELETE( ppfGaussianTable[i] );
}
SAFE_DELETE( ppfGaussianTable );
SAFE_DELETE( pTempBuf );
}
for( int j=0; j<m_nAlphaTableHeight; j++ ) {
for( int i=0; i<m_nAlphaTableWidth; i++ ) {
int nIndex = j * m_nAlphaTableWidth + i;
m_pAlphaTable[nIndex] = (BYTE)pTable[nIndex];
}
}
SAFE_DELETE( pTable );
RefreshTexture();
RefreshTextureAlpha();
}
float CTEtWorldWaterRiver::GetNewAlpha( float *pBuffer, int x, int y, int nBlurValue, float **ppfTable )
{
int nTableSize = ( nBlurValue * 2 ) + 1;
x -= nBlurValue;
y -= nBlurValue;
float fValue = 0.f;
for( int j=0; j<nTableSize; j++ ) {
for( int i=0; i<nTableSize; i++ ) {
int nOffset = (y+j) * m_nAlphaTableWidth + (x+i);
fValue += pBuffer[nOffset] * ppfTable[i][j];
}
}
if( fValue > 255.f ) fValue = 255.f;
else if( fValue < 0.f ) fValue = 0.f;
return fValue;
}
void CTEtWorldWaterRiver::RefreshPropertyList()
{
SAFE_DELETE_PVEC( m_pVecPropertyList );
CUnionValueProperty *pVariable;
for( DWORD i=0; ; i++ ) {
if( g_WaterRiverPropertyDefine[i].szCategory == NULL ) break;
pVariable = new CUnionValueProperty( g_WaterRiverPropertyDefine[i].Type );
pVariable->SetCategory( g_WaterRiverPropertyDefine[i].szCategory );
pVariable->SetDescription( g_WaterRiverPropertyDefine[i].szStr );
pVariable->SetSubDescription( g_WaterRiverPropertyDefine[i].szDescription, true );
pVariable->SetDefaultEnable( g_WaterRiverPropertyDefine[i].bEnable );
pVariable->SetCustomDialog( g_WaterRiverPropertyDefine[i].bCustomDialog );
m_pVecPropertyList.push_back( pVariable );
}
}
void CTEtWorldWaterRiver::OnSetValue( CUnionValueProperty *pVariable, DWORD dwIndex, CPropertyGridImp *pImp )
{
switch( dwIndex ) {
case 0:
pVariable->SetVariable( (char*)m_szShaderName.c_str() );
break;
case 1:
pVariable->SetVariable( (int)m_InterpolationType );
break;
case 2:
pVariable->SetVariable( m_fWidth );
break;
case 3:
pVariable->SetVariable( m_vUVRatio.x );
break;
case 4:
pVariable->SetVariable( m_vUVRatio.y );
break;
case 5:
switch( m_nAlphaTableWidth ) {
case 32: pVariable->SetVariable(0); break;
case 64: pVariable->SetVariable(1); break;
case 128: pVariable->SetVariable(2); break;
case 256: pVariable->SetVariable(3); break;
case 512: pVariable->SetVariable(4); break;
case 1024: pVariable->SetVariable(5); break;
case 2048: pVariable->SetVariable(6); break;
}
break;
case 6:
switch( m_nAlphaTableHeight ) {
case 32: pVariable->SetVariable(0); break;
case 64: pVariable->SetVariable(1); break;
case 128: pVariable->SetVariable(2); break;
case 256: pVariable->SetVariable(3); break;
case 512: pVariable->SetVariable(4); break;
case 1024: pVariable->SetVariable(5); break;
case 2048: pVariable->SetVariable(6); break;
}
break;
case 7:
pVariable->SetVariable( m_nBorderReduction );
break;
case 8:
pVariable->SetVariable( m_nGaussianValue );
break;
case 9:
pVariable->SetVariable( m_fGaussianEpsilon );
break;
case 10:
pVariable->SetVariable( m_nMinAlpha );
break;
case 11:
pVariable->SetVariable( m_nMaxAlpha );
break;
case 12:
pVariable->SetVariable( m_fRevisionAlpha );
break;
}
int nOffset = ( sizeof(g_WaterRiverPropertyDefine) / sizeof(PropertyGridBaseDefine) ) - 1;
if( dwIndex - nOffset >= 0 && dwIndex - nOffset < m_pVecPropertyList.size() ) {
EtParameterHandle hParam;
EffectParamType Type;
for( DWORD i=0; i<m_vecCustomParam.size(); i++ ) {
hParam = m_hMaterial->GetCustomParamHandle(i);
Type = m_hMaterial->GetCustomParamType(i);
const char *szName = m_hMaterial->GetParameterName( hParam );
if( _stricmp( szName, pVariable->GetDescription() ) == NULL ) {
switch( pVariable->GetType() ) {
case CUnionValueProperty::Float:
pVariable->SetVariable( m_vecCustomParam[i].fFloat );
break;
case CUnionValueProperty::Integer:
pVariable->SetVariable( m_vecCustomParam[i].nInt );
break;
case CUnionValueProperty::Vector4Color:
pVariable->SetVariable( *(EtVector4*)m_vecCustomParam[i].fFloat4 );
break;
case CUnionValueProperty::String_FileOpen:
{
std::map<std::string, EtTextureHandle>::iterator it = m_MapTextureList.find(pVariable->GetDescription());
if( it != m_MapTextureList.end() ) {
if( it->second )
pVariable->SetVariable( (char*)it->second->GetFileName() );
}
}
break;
}
break;
}
}
}
}
void CTEtWorldWaterRiver::OnChangeValue( CUnionValueProperty *pVariable, DWORD dwIndex, CPropertyGridImp *pImp )
{
CGlobalValue::GetInstance().SetModify();
switch( dwIndex ) {
case 0:
m_szShaderName = pVariable->GetVariableString();
RefreshShader();
{
CWnd *pWnd = GetPaneWnd( WATERPROP_PANE );
if( pWnd ) pWnd->SendMessage( UM_REFRESH_PANE_VIEW, 1, (LPARAM)this );
}
break;
case 1:
m_InterpolationType = (InterpolationType)pVariable->GetVariableInt();
break;
case 2:
m_fWidth = pVariable->GetVariableFloat();
break;
case 3:
m_vUVRatio.x = pVariable->GetVariableFloat();
RefreshTextureCoord();
break;
case 4:
m_vUVRatio.y = pVariable->GetVariableFloat();
RefreshTextureCoord();
break;
case 5:
switch( pVariable->GetVariableInt() ) {
case 0: m_nAlphaTableWidth = 32; break;
case 1: m_nAlphaTableWidth = 64; break;
case 2: m_nAlphaTableWidth = 128; break;
case 3: m_nAlphaTableWidth = 256; break;
case 4: m_nAlphaTableWidth = 512; break;
case 5: m_nAlphaTableWidth = 1024; break;
case 6: m_nAlphaTableWidth = 2048; break;
}
break;
case 6:
switch( pVariable->GetVariableInt() ) {
case 0: m_nAlphaTableHeight = 32; break;
case 1: m_nAlphaTableHeight = 64; break;
case 2: m_nAlphaTableHeight = 128; break;
case 3: m_nAlphaTableHeight = 256; break;
case 4: m_nAlphaTableHeight = 512; break;
case 5: m_nAlphaTableHeight = 1024; break;
case 6: m_nAlphaTableHeight = 2048; break;
}
break;
case 7:
m_nBorderReduction = pVariable->GetVariableInt();
break;
case 8:
m_nGaussianValue = pVariable->GetVariableInt();
break;
case 9:
m_fGaussianEpsilon = pVariable->GetVariableFloat();
break;
case 10:
m_nMinAlpha = pVariable->GetVariableInt();
break;
case 11:
m_nMaxAlpha = pVariable->GetVariableInt();
break;
case 12:
m_fRevisionAlpha = pVariable->GetVariableFloat();
RefreshTextureAlpha();
break;
}
int nOffset = ( sizeof(g_WaterRiverPropertyDefine) / sizeof(PropertyGridBaseDefine) ) - 1;
if( dwIndex - nOffset >= 0 && dwIndex - nOffset < m_pVecPropertyList.size() ) {
switch( pVariable->GetType() ) {
case CUnionValueProperty::Float:
{
float fValue = pVariable->GetVariableFloat();
AddCustomParam( m_vecCustomParam, EPT_FLOAT, m_hMaterial, pVariable->GetDescription(), &fValue );
}
break;
case CUnionValueProperty::Integer:
{
int nValue = pVariable->GetVariableInt();
AddCustomParam( m_vecCustomParam, EPT_INT, m_hMaterial, pVariable->GetDescription(), &nValue );
}
break;
case CUnionValueProperty::Vector4Color:
{
EtVector4 vVec = pVariable->GetVariableVector4();
AddCustomParam( m_vecCustomParam, EPT_VECTOR, m_hMaterial, pVariable->GetDescription(), &vVec );
}
break;
case CUnionValueProperty::String_FileOpen:
{
OutputDebug( "Tex : %s %s\n", pVariable->GetDescription(), pVariable->GetVariableString() );
std::map<std::string, EtTextureHandle>::iterator it = m_MapTextureList.find(pVariable->GetDescription());
if( it != m_MapTextureList.end() ) {
SAFE_RELEASE_SPTR( it->second );
m_MapTextureList.erase( it );
}
EtTextureHandle hTexture = LoadResource( pVariable->GetVariableString(), RT_TEXTURE );
int nTexIndex = hTexture.GetIndex();
m_MapTextureList.insert( make_pair( pVariable->GetDescription(), hTexture ) );
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, pVariable->GetDescription(), &nTexIndex );
}
break;
}
}
UpdatePoint();
CGlobalValue::GetInstance().RefreshRender();
}
void CTEtWorldWaterRiver::OnSelectChangeValue( CUnionValueProperty *pVariable, DWORD dwIndex, CPropertyGridImp *pImp )
{
}
void CTEtWorldWaterRiver::RefreshSize()
{
if( m_pVecPointList.size() < 2 ) return;
EtVector2 vMin = EtVector2( FLT_MAX, FLT_MAX );
EtVector2 vMax = EtVector2( FLT_MAX, FLT_MAX );
EtVector3 vDir, vVertex, vCross;
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
if( i == m_pVecPointList.size() - 1 ) {
vDir = m_pVecPointList[i]->vPos - m_pVecPointList[i-1]->vPos;
}
else {
vDir = m_pVecPointList[i+1]->vPos - m_pVecPointList[i]->vPos;
}
EtVec3Normalize( &vDir, &vDir );
EtVec3Cross( &vCross, &vDir, &EtVector3( 0.f, 1.f, 0.f ) );
vVertex = m_pVecPointList[i]->vPos + ( vCross * ( m_fWidth / 2.f ) );
if( vMin.x == FLT_MAX || vVertex.x < vMin.x ) vMin.x = vVertex.x;
if( vMax.x == FLT_MAX || vVertex.x > vMax.x ) vMax.x = vVertex.x;
if( vMin.y == FLT_MAX || vVertex.z < vMin.y ) vMin.y = vVertex.z;
if( vMax.y == FLT_MAX || vVertex.z > vMax.y ) vMax.y = vVertex.z;
vVertex = m_pVecPointList[i]->vPos - ( vCross * ( m_fWidth / 2.f ) );
if( vMin.x == FLT_MAX || vVertex.x < vMin.x ) vMin.x = vVertex.x;
if( vMax.x == FLT_MAX || vVertex.x > vMax.x ) vMax.x = vVertex.x;
if( vMin.y == FLT_MAX || vVertex.z < vMin.y ) vMin.y = vVertex.z;
if( vMax.y == FLT_MAX || vVertex.z > vMax.y ) vMax.y = vVertex.z;
}
m_vOffset = vMin;
m_vSize.x = vMax.x - vMin.x;
m_vSize.y = vMax.y - vMin.y;
}
void CTEtWorldWaterRiver::UpdatePoint()
{
RefreshPrimitive();
SAFE_DELETE( m_pMesh );
m_pMesh = new CEtMeshStream;
RefreshSize();
RefreshVertex();
RefreshIndex();
RefreshNormal();
RefreshTextureCoord();
}
bool CTEtWorldWaterRiver::Save( FILE *fp )
{
CString szName;
// 실제 데이터들
WriteCString( &CString(m_szName.c_str()), fp );
fwrite( &m_InterpolationType, sizeof(int), 1, fp );
fwrite( &m_fWidth, sizeof(float), 1, fp );
fwrite( &m_nAlphaTableWidth, sizeof(int), 1, fp );
fwrite( &m_nAlphaTableHeight, sizeof(int), 1, fp );
fwrite( &m_vUVRatio, sizeof(EtVector2), 1, fp );
int nCount = (int)m_pVecPointList.size();
fwrite( &nCount, sizeof(int), 1, fp );
EtVector3 vOffset = *GetWater()->GetSector()->GetOffset();
vOffset.x -= ( GetWater()->GetSector()->GetTileWidthCount() * GetWater()->GetSector()->GetTileSize() ) / 2.f;
vOffset.z -= ( GetWater()->GetSector()->GetTileHeightCount() * GetWater()->GetSector()->GetTileSize() ) / 2.f;
vOffset.y = 0.f;
EtVector3 vPos;
for( int i=0; i<nCount; i++ ) {
vPos = m_pVecPointList[i]->vPos - vOffset;
fwrite( &vPos, sizeof(EtVector3), 1, fp );
}
fwrite( m_pAlphaTable, sizeof(BYTE) * ( m_nAlphaTableWidth * m_nAlphaTableHeight ), 1, fp );
// 툴에서만 사용하는 파라매터지만 가치 저장하자.
fwrite( &m_nBorderReduction, sizeof(int), 1, fp );
fwrite( &m_nGaussianValue, sizeof(int), 1, fp );
fwrite( &m_fGaussianEpsilon, sizeof(float), 1, fp );
fwrite( &m_nMinAlpha, sizeof(int), 1, fp );
fwrite( &m_nMaxAlpha, sizeof(int), 1, fp );
fwrite( &m_fRevisionAlpha, sizeof(float), 1, fp );
szName = m_szShaderName.c_str();
WriteCString( &szName, fp );
long nOffset = ftell(fp);
int nCustomParamCount = 0;
fwrite( &nCustomParamCount, sizeof(int), 1, fp );
EtParameterHandle hParam;
EffectParamType Type;
for( int i=0; i<m_hMaterial->GetCustomParamCount(); i++ ) {
hParam = m_hMaterial->GetCustomParamHandle(i);
Type = m_hMaterial->GetCustomParamType(i);
szName = m_hMaterial->GetParameterName( hParam );
SCustomParam *pParam = NULL;
for( DWORD j=0; j<m_vecCustomParam.size(); j++ ) {
if( m_vecCustomParam[j].hParamHandle == hParam &&
m_vecCustomParam[j].Type == Type ) {
pParam = &m_vecCustomParam[j];
break;
}
}
if( pParam == NULL ) continue;
if( _stricmp( szName, "g_TransparencyTex" ) == NULL ) continue;
if( _stricmp( szName, "g_WaterMapTex" ) == NULL ) continue;
if( _stricmp( szName, "g_LastViewMat" ) == NULL ) continue;
WriteCString( &szName, fp );
fwrite( &Type, sizeof(EffectParamType), 1, fp );
switch( Type ) {
case EPT_INT: fwrite( &pParam->nInt, sizeof(int), 1, fp ); break;
case EPT_FLOAT: fwrite( &pParam->fFloat, sizeof(float), 1, fp ); break;
case EPT_VECTOR: fwrite( pParam->fFloat4, sizeof(float)*4, 1, fp ); break;
case EPT_TEX:
{
if( pParam->nTextureIndex == -1 ) {
szName.Empty();
WriteCString( &szName, fp );
break;
}
EtTextureHandle hTexture = CEtResource::GetResource( pParam->nTextureIndex );
if( !hTexture ) continue;
szName = hTexture->GetFileName();
if( szName.IsEmpty() ) continue;
WriteCString( &szName, fp );
break;
}
case EPT_MATRIX: fwrite( pParam->fFloat4, sizeof(float)*16, 1, fp ); break;
}
nCustomParamCount++;
}
long nLastSeek = ftell(fp);
fseek( fp, nOffset, SEEK_SET );
fwrite( &nCustomParamCount, sizeof(int), 1, fp );
fseek( fp, nLastSeek, SEEK_SET );
return true;
}
bool CTEtWorldWaterRiver::Load( CStream *pStream )
{
bool bResult = CEtWorldWaterRiver::Load( pStream );
if( !bResult ) return false;
for( DWORD i=0; i<m_pVecPointList.size(); i++ ) {
SAFE_DELETE( m_pVecPointList[i]->pAxis );
}
SAFE_DELETE_PVEC( m_pVecPointList );
EtVector3 vOffset = *GetWater()->GetSector()->GetOffset();
vOffset.x -= ( GetWater()->GetSector()->GetTileWidthCount() * GetWater()->GetSector()->GetTileSize() ) / 2.f;
vOffset.z -= ( GetWater()->GetSector()->GetTileHeightCount() * GetWater()->GetSector()->GetTileSize() ) / 2.f;
for( DWORD i=0; i<m_vVecPointList.size(); i++ ) {
InsertPoint( m_vVecPointList[i] + vOffset );
}
UpdatePoint();
RefreshShader();
for( DWORD i=0; i<m_pVecCustomParamList.size(); i++ ) {
CUnionValueProperty *pVariable = NULL;
for( DWORD j=0; j<m_pVecPropertyList.size(); j++ ) {
if( _stricmp( m_pVecCustomParamList[i]->szName.c_str(), m_pVecPropertyList[j]->GetDescription() ) == NULL ) {
pVariable = m_pVecPropertyList[j];
break;
}
}
if( pVariable == NULL ) continue;
switch( m_pVecCustomParamList[i]->nType ) {
case EPT_INT:
pVariable->SetVariable( m_pVecCustomParamList[i]->nInt );
AddCustomParam( m_vecCustomParam, EPT_INT, m_hMaterial, m_pVecCustomParamList[i]->szName.c_str(), &m_pVecCustomParamList[i]->nInt );
break;
case EPT_FLOAT:
pVariable->SetVariable( m_pVecCustomParamList[i]->fFloat );
AddCustomParam( m_vecCustomParam, EPT_FLOAT, m_hMaterial, m_pVecCustomParamList[i]->szName.c_str(), &m_pVecCustomParamList[i]->fFloat );
break;
case EPT_VECTOR:
pVariable->SetVariable( *(EtVector4*)m_pVecCustomParamList[i]->fFloat4 );
AddCustomParam( m_vecCustomParam, EPT_VECTOR, m_hMaterial, m_pVecCustomParamList[i]->szName.c_str(), &m_pVecCustomParamList[i]->fFloat4 );
break;
case EPT_TEX:
{
pVariable->SetVariable( m_pVecCustomParamList[i]->szTexName );
std::map<std::string, EtTextureHandle>::iterator it = m_MapTextureList.find(m_pVecCustomParamList[i]->szName);
if( it != m_MapTextureList.end() ) {
SAFE_RELEASE_SPTR( it->second );
m_MapTextureList.erase( it );
}
EtTextureHandle hTexture = LoadResource( pVariable->GetVariableString(), RT_TEXTURE );
int nTexIndex = hTexture.GetIndex();
m_MapTextureList.insert( make_pair( m_pVecCustomParamList[i]->szName, hTexture ) );
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, m_pVecCustomParamList[i]->szName.c_str(), &nTexIndex );
}
break;
}
}
AddCustomParam( m_vecCustomParam, EPT_MATRIX_PTR, m_hMaterial, "g_LastViewMat", GetEtWater()->GetWaterBakeViewMat() );
if( m_pAlphaTable == NULL ) {
m_pAlphaTable = new BYTE[ m_nAlphaTableWidth * m_nAlphaTableHeight ];
for( int i=0; i<m_nAlphaTableHeight; i++ ) {
for( int j=0; j<m_nAlphaTableWidth; j++ ) {
m_pAlphaTable[ i * m_nAlphaTableWidth + j ] = 128;
}
}
}
RefreshTexture();
RefreshTextureAlpha();
return bResult;
}