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

581 lines
No EOL
15 KiB
C++

#include "StdAfx.h"
#include "EtSkin.h"
#include "EtMesh.h"
#include "EtLoader.h"
#include "EtOptionController.h"
#include "EtCustomParam.h"
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
CEtSkin::CEtSkin(void)
{
m_nAlphaParamIndex = -1;
m_pAdditionalCustomParam = NULL;
for( int i = 0;i < 5; i++) {
m_EmmisiveColor[i] = EtColor(0,0,0,0);
}
m_pvecExternalParam = NULL;
m_pvecMultiExternalParam = NULL;
}
CEtSkin::~CEtSkin(void)
{
Clear();
}
void CEtSkin::Clear()
{
// 스킨에 들어 있는 리소스들은 스킨 지워질때 바로 같이 지워져야 한다. WaitDeleteBuffer에 들어갈 필요 없다..
int i, j;
SAFE_RELEASE_SPTR( m_MeshHandle );
// 맵툴 컴파일 시 이부분 주석처리 필요 ( Preview 속도때문에 )
#ifndef _TOOLCOMPILE
for( i = 0; i < ( int )m_vecMaterialHandle.size(); i++ )
{
if( m_vecMaterialHandle[ i ] )
{
if( m_vecMaterialHandle[ i ]->Release() <= 0 )
{
delete m_vecMaterialHandle[ i ];
}
}
}
#endif
////////////////////////////////////////////////////////////////
m_vecMaterialHandle.clear();
if( m_hShadowMaterial )
{
if( m_hShadowMaterial->Release() <= 0 )
{
delete m_hShadowMaterial;
}
m_hShadowMaterial.Identity();
}
for( i = 0; i < ( int )m_vecCustomParam.size(); i++ )
{
for( j = 0; j < ( int )m_vecCustomParam[ i ].size(); j++ )
{
if( m_vecCustomParam[ i ][ j ].Type == EPT_TEX )
{
if( m_vecCustomParam[ i ][ j ].nTextureIndex == -1 )
{
continue;
}
EtResourceHandle hHandle = CEtResource::GetResource( m_vecCustomParam[ i ][ j ].nTextureIndex );
if( hHandle )
{
if( hHandle->Release() <= 0 )
{
delete hHandle;
}
}
}
}
}
m_vecCustomParam.clear();
m_vecSubSkinHeader.clear();
}
int CEtSkin::LoadResource( CStream *pStream )
{
ASSERT( pStream && "Invalid Resource Stream( Skin )" );
if( pStream == NULL )
{
return ETERR_INVALIDRESOURCESTREAM;
}
int i, j, nRet;
ASSERT( !m_hShadowMaterial );
ASSERT( !m_MeshHandle );
Clear();
m_hShadowMaterial = ::LoadResource( "Shadow.fx", RT_SHADER, true );
pStream->Read( &m_SkinHeader, sizeof( SSkinFileHeader ) );
pStream->Seek( SKIN_HEADER_RESERVED, SEEK_CUR );
if( strstr( m_SkinHeader.szHeaderString, SKIN_FILE_STRING ) == NULL ) return ETERR_FILENOTFOUND;
nRet = LoadMesh( m_SkinHeader.szMeshName );
if( nRet != ET_OK )
{
ASSERT( false );
return nRet;
}
m_vecCustomParam.resize( m_SkinHeader.nSubMeshCount );
m_vecSubSkinHeader.resize( m_SkinHeader.nSubMeshCount );
m_DiffuseTexIndexList.resize( m_SkinHeader.nSubMeshCount );
m_IsAlphaTextureList.resize( m_SkinHeader.nSubMeshCount );
for( i = 0; i < m_SkinHeader.nSubMeshCount; i++ )
{
m_DiffuseTexIndexList[ i ] = -1;
m_IsAlphaTextureList[ i ] = FALSE;
int nParamCount, nNameLength;
char szParamName[ 256 ];
SCustomParam CustomParam;
pStream->Read( &m_vecSubSkinHeader[ i ], sizeof( SSubSkinHeader ) );
pStream->Seek( SUB_SKIN_HEADER_RESERVED, SEEK_CUR );
nRet = LoadEffect( m_vecSubSkinHeader[ i ].szEffectName );
if( nRet != ET_OK )
{
return nRet;
}
pStream->Read( &nParamCount, sizeof( int ) );
for( j = 0; j < nParamCount; j++ )
{
CustomParam.nVariableCount = 1;
pStream->Read( &nNameLength, sizeof( int ) );
pStream->Read( szParamName, nNameLength );
CustomParam.hParamHandle = m_vecMaterialHandle[ i ]->GetParameterByName( szParamName );
pStream->Read( &CustomParam.Type, sizeof( EffectParamType ) );
if( stricmp( szParamName, "g_MaterialAmbient" ) == 0 )
{
m_nAlphaParamIndex = ( int )m_vecCustomParam[ i ].size();
}
switch( CustomParam.Type )
{
case EPT_INT:
pStream->Read( &CustomParam.nInt, sizeof( int ) );
break;
case EPT_FLOAT:
pStream->Read( &CustomParam.fFloat, sizeof( float ) );
break;
case EPT_VECTOR:
pStream->Read( &CustomParam.fFloat4, sizeof( float ) * 4 );
break;
case EPT_TEX:
{
char szTexName[ 256 ];
pStream->Read( &nNameLength, sizeof( int ) );
pStream->Read( szTexName, nNameLength );
CustomParam.nTextureIndex = LoadTexture( szTexName, m_vecMaterialHandle[ i ]->GetTextureType( CustomParam.hParamHandle ) );
if( stricmp( szParamName, "g_DiffuseTex" ) == 0 || stricmp( szParamName, "g_DiffuseVolumeTex" ) == 0 )
{
m_DiffuseTexIndexList[ i ] = CustomParam.nTextureIndex;
if( m_DiffuseTexIndexList[ i ] == -1 ) break;
EtTextureHandle hTexture = CEtResource::GetResource( m_DiffuseTexIndexList[ i ] );
if( hTexture->IsAlphaTexture() ) {
m_IsAlphaTextureList[ i ] = TRUE;
}
}
}
break;
}
m_vecCustomParam[ i ].push_back( CustomParam );
}
}
CheckTechnique();
CheckMeshStream();
return ET_OK;
}
int CEtSkin::Save( const char *pFileName )
{
CFileStream Stream( pFileName, CFileStream::OPEN_WRITE );
if( !Stream.IsValid() )
{
return ETERR_FILECREATEFAIL;
}
SaveSkin( &Stream );
return ET_OK;
}
int CEtSkin::SaveSkin( CStream *pStream )
{
char cReserved[ 1024 ];
int i, j;
pStream->Write( &m_SkinHeader, sizeof( SSkinFileHeader ) );
memset( cReserved, 0, 1024 );
pStream->Write( cReserved, SKIN_HEADER_RESERVED );
for( i = 0; i < m_SkinHeader.nSubMeshCount; i++ )
{
char szParamName[ 256 ];
int nParamCount, nNameLength;
SCustomParam CustomParam;
pStream->Write( &m_vecSubSkinHeader[ i ], sizeof( SSubSkinHeader ) );
pStream->Write( cReserved, SUB_SKIN_HEADER_RESERVED );
nParamCount = ( int )m_vecCustomParam[ i ].size();
pStream->Write( &nParamCount, sizeof( int ) );
for( j = 0; j < nParamCount; j++ )
{
CustomParam = m_vecCustomParam[ i ][ j ];
strcpy( szParamName, m_vecMaterialHandle[ i ]->GetParameterName( CustomParam.hParamHandle ) );
nNameLength = ( int )strlen( szParamName ) + 1;
pStream->Write( &nNameLength, sizeof( int ) );
pStream->Write( szParamName, nNameLength );
pStream->Write( &CustomParam.Type, sizeof( EffectParamType ) );
switch( CustomParam.Type )
{
case EPT_INT:
pStream->Write( &CustomParam.nInt, sizeof( int ) );
break;
case EPT_FLOAT:
pStream->Write( &CustomParam.fFloat, sizeof( float ) );
break;
case EPT_VECTOR:
pStream->Write( &CustomParam.fFloat4, sizeof( float ) * 4 );
break;
case EPT_TEX:
if( CustomParam.nTextureIndex == -1 ) {
//MessageBox(0, "텍스쳐가 빠진것이 있으니 확인 바래요.", "경고", MB_OK);
MessageBox(0, " Missing textures found ", "Warning", MB_OK);
}
else {
strcpy( szParamName, CEtResource::GetResource( CustomParam.nTextureIndex )->GetFileName() );
}
nNameLength = ( int )strlen( szParamName ) + 1;
pStream->Write( &nNameLength, sizeof( int ) );
pStream->Write( szParamName, nNameLength );
break;
}
}
}
return ET_OK;
}
int CEtSkin::LoadMesh( const char *pMeshName )
{
m_MeshHandle = ::LoadResource( pMeshName, RT_MESH, true );
if( !m_MeshHandle )
{
ASSERT( 0 && "Mesh File Not Found!!!" );
return ETERR_MESHNOTFOUND;
}
if( m_MeshHandle->GetSubMeshCount() != m_SkinHeader.nSubMeshCount )
{
ASSERT( 0 && "스킨과 메쉬파일의 서브메시 갯수가 다릅니다. 확인해주세요!!!" );
return -1;
}
return ET_OK;
}
int CEtSkin::LoadEffect( const char *pEffectName )
{
EtResourceHandle hHandle;
hHandle = ::LoadResource( pEffectName, RT_SHADER, true );
if( !hHandle )
{
ASSERT( 0 && "fx File Not Found!!!" );
return ETERR_EFFECTNOTFOUND;
}
m_vecMaterialHandle.push_back( hHandle );
return ET_OK;
}
int CEtSkin::LoadTexture( const char *pTextureName, EtTextureType Type )
{
EtResourceHandle hHandle;
hHandle = ::LoadResource( pTextureName, RT_TEXTURE, true );
if( !hHandle )
{
ASSERT( 0 && "Texture File Not Found!!!" );
return -1;
}
return hHandle->GetMyIndex();
}
void CEtSkin::CheckTechnique()
{
int i;
m_vecTehiniqueIndex.resize( m_SkinHeader.nSubMeshCount );
for( i = 0; i < m_SkinHeader.nSubMeshCount; i++ )
{
if( m_MeshHandle->GetSubMesh( i )->IsExistStream( MST_BONEINDEX, 0 ) )
{
m_vecTehiniqueIndex[ i ] = 1;
}
else
{
m_vecTehiniqueIndex[ i ] = 0;
}
}
}
void CEtSkin::CheckMeshStream()
{
int i;
for( i = 0; i < m_SkinHeader.nSubMeshCount; i++ )
{
if( m_vecMaterialHandle[ i ]->UseTangentSpace() )
{
m_MeshHandle->GetSubMesh( i )->GenerateTangentSpace();
}
}
}
EtMaterialHandle CEtSkin::GetCurrentMaterial( int nMtlIndex )
{
if( m_hExternalMaterial ) {
return m_hExternalMaterial;
}
else {
return m_vecMaterialHandle[ nMtlIndex ];
}
}
void CEtSkin::SetExternalMaterial( EtMaterialHandle hMaterial, std::vector< SCustomParam > *pvecParam, std::vector< std::vector< SCustomParam > > *pvecMultiParam )
{
m_hExternalMaterial = hMaterial;
m_pvecExternalParam = pvecParam;
m_pvecMultiExternalParam = pvecMultiParam;
}
void CEtSkin::ClearExternalMaterial()
{
m_hExternalMaterial.Identity();
m_pvecExternalParam = NULL;
m_pvecMultiExternalParam = NULL;
}
void CEtSkin::SetEffect( int nSubMeshIndex, int nEffectIndex, SCustomParam *pParam )
{
ASSERT( m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].hParamHandle == pParam->hParamHandle );
ASSERT( m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].Type == pParam->Type );
switch( m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].Type )
{
case EPT_INT:
m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].nInt = pParam->nInt;
break;
case EPT_FLOAT:
m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].fFloat = pParam->fFloat;
break;
case EPT_VECTOR:
memcpy( m_vecCustomParam[ nSubMeshIndex][ nEffectIndex ].fFloat4, pParam->fFloat4, sizeof( pParam->fFloat4 ) );
break;
}
}
void CEtSkin::SetTexture( int nSubMeshIndex, int nEffectIndex, const char *pTexName )
{
ASSERT( nSubMeshIndex < ( int )m_vecCustomParam.size() );
if( m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].Type != EPT_TEX )
{
return;
}
if( m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].nTextureIndex != -1 )
{
EtTextureHandle hTexture;
hTexture = CEtResource::GetResource( m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].nTextureIndex );
SAFE_RELEASE_SPTR( hTexture );
}
m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].nTextureIndex = LoadTexture( pTexName,
m_vecMaterialHandle[ nSubMeshIndex ]->GetTextureType( m_vecCustomParam[ nSubMeshIndex ][ nEffectIndex ].hParamHandle ) );
}
void CEtSkin::SetAlphaValue( int nSubMeshIndex, float fAlphaValue )
{
ASSERT( nSubMeshIndex < ( int )m_vecCustomParam.size() );
m_vecSubSkinHeader[ nSubMeshIndex ].fAlphaValue = fAlphaValue;
}
float CEtSkin::GetAlphaValue( int nSubMeshIndex )
{
ASSERT( nSubMeshIndex < ( int )m_vecCustomParam.size() );
return m_vecSubSkinHeader[ nSubMeshIndex ].fAlphaValue;
}
void CEtSkin::EnableAlphaBlend( int nSubMeshIndex, bool bEnable )
{
ASSERT( nSubMeshIndex < ( int )m_vecCustomParam.size() );
m_vecSubSkinHeader[ nSubMeshIndex ].bEnableAlphablend = bEnable;
}
bool CEtSkin::IsEnableAlphaBlend( int nSubMeshIndex )
{
ASSERT( nSubMeshIndex < ( int )m_vecCustomParam.size() );
return m_vecSubSkinHeader[ nSubMeshIndex ].bEnableAlphablend;
}
void CEtSkin::RenderSubMesh( int nSubMeshIndex, EtMatrix &WorldMat, EtMatrix &PrevWorldMat, bool bShadowReceive, int nSaveMatIndex, float fAlpha )
{
int nCurTechnique, nParentBoneIndex;
EtMaterialHandle hMaterial;
hMaterial = GetCurrentMaterial( nSubMeshIndex );
if( ( nSaveMatIndex != -1 ) && ( m_vecTehiniqueIndex[ nSubMeshIndex ] == 1 ) )
{
nCurTechnique = 1;
}
else
{
nCurTechnique = 0;
}
if( m_nAlphaParamIndex != -1 )
{
m_vecCustomParam[ nSubMeshIndex ][ m_nAlphaParamIndex ].fFloat4[ 3 ] = fAlpha;
}
hMaterial->SetTechnique( nCurTechnique );
hMaterial->SetGlobalParams();
nParentBoneIndex = m_MeshHandle->GetSubMesh( nSubMeshIndex )->GetParentBoneIndex();
if( ( nParentBoneIndex != -1 ) && ( nSaveMatIndex != -1 ) )
{
hMaterial->SetWorldMatParams( &WorldMat, &PrevWorldMat, nSaveMatIndex + nParentBoneIndex );
}
else
{
hMaterial->SetWorldMatParams( &WorldMat, &PrevWorldMat );
}
if( ( bShadowReceive ) && ( GetEtOptionController()->IsEnableDynamicShadow() ) )
{
nCurTechnique += 2;
if( nCurTechnique >= hMaterial->GetTechniqueCount() )
{
nCurTechnique -= 2;
}
}
if( nCurTechnique % 2 == 1 )
{
// 중복셋팅인지 확인 요망 by mapping
if( m_MeshHandle->GetSubMesh( nSubMeshIndex )->GetLinkCount() )
{
hMaterial->SetWorldMatArray( &WorldMat, nSaveMatIndex,
m_MeshHandle->GetSubMesh( nSubMeshIndex )->GetLinkCount(), m_MeshHandle->GetSubMesh( nSubMeshIndex )->GetLinkIndex() );
}
}
SetCustomParams( nSubMeshIndex );
int i, nPasses;
hMaterial->BeginEffect( nPasses );
for( i = 0; i < nPasses; i++ )
{
hMaterial->BeginPass( i );
hMaterial->CommitChanges();
m_MeshHandle->Draw( nSubMeshIndex, hMaterial->GetVertexDeclIndex( nCurTechnique, i ) );
hMaterial->EndPass();
}
hMaterial->EndEffect();
}
void CEtSkin::Render( EtMatrix &WorldMat, EtMatrix &PrevWorldMat, float fObjectAlpha, bool bShadowReceive, std::vector< bool > *pvecShowSubmesh, CEtCustomParam *pCustomParam, int nSaveMatIndex )
{
if( !m_MeshHandle )
{
return;
}
int i;
m_pAdditionalCustomParam = pCustomParam;
for( i = 0; i < ( int )m_MeshHandle->GetSubMeshCount(); i++ )
{
if( ( pvecShowSubmesh ) && ( ( *pvecShowSubmesh )[ i ] == false ) )
{
continue;
}
float fAlpha;
fAlpha = fObjectAlpha * m_vecSubSkinHeader[ i ].fAlphaValue;
if( ( fAlpha < 1.0f ) || ( m_vecSubSkinHeader[ i ].bEnableAlphablend ) )
{
continue;
}
RenderSubMesh( i, WorldMat, PrevWorldMat, bShadowReceive, nSaveMatIndex, 1.0f );
}
m_pAdditionalCustomParam = NULL;
}
void CEtSkin::RenderAlpha( EtMatrix &WorldMat, EtMatrix &PrevWorldMat, float fObjectAlpha, bool bShadowReceive, std::vector< bool > *pvecShowSubmesh, CEtCustomParam *pCustomParam, int nSaveMatIndex )
{
if( !m_MeshHandle )
{
return;
}
int i;
m_pAdditionalCustomParam = pCustomParam;
for( i = 0; i < ( int )m_MeshHandle->GetSubMeshCount(); i++ )
{
if( ( pvecShowSubmesh ) && ( ( *pvecShowSubmesh )[ i ] == false ) )
{
continue;
}
float fAlpha;
fAlpha = fObjectAlpha * m_vecSubSkinHeader[ i ].fAlphaValue;
if( ( fAlpha >= 1.0f ) && ( m_vecSubSkinHeader[ i ].bEnableAlphablend == false ) )
{
continue;
}
RenderSubMesh( i, WorldMat, PrevWorldMat, bShadowReceive, nSaveMatIndex, fAlpha );
}
m_pAdditionalCustomParam = NULL;
}
void CEtSkin::RenderShadow( EtMatrix &WorldMat, EtMatrix &PrevWorldMat, std::vector< bool > *pvecShowSubmesh, int nSaveMatIndex )
{
if( !m_MeshHandle )
{
return;
}
SetExternalMaterial( m_hShadowMaterial, NULL );
int i;
for( i = 0; i < ( int )m_MeshHandle->GetSubMeshCount(); i++ )
{
if( ( pvecShowSubmesh ) && ( ( *pvecShowSubmesh )[ i ] == false ) )
{
continue;
}
RenderSubMesh( i, WorldMat, PrevWorldMat, false, nSaveMatIndex, 1.0f );
}
ClearExternalMaterial();
}
void CEtSkin::SetCustomParams( int nMaterialIndex )
{
if( m_hExternalMaterial )
{
if( m_pvecMultiExternalParam )
{
m_hExternalMaterial->SetCustomParamList( (*m_pvecMultiExternalParam)[nMaterialIndex] );
}
else if( m_pvecExternalParam )
{
m_hExternalMaterial->SetCustomParamList( *m_pvecExternalParam );
}
}
else
{
m_vecMaterialHandle[ nMaterialIndex ]->SetCustomParamList( m_vecCustomParam[ nMaterialIndex ] );
if( m_pAdditionalCustomParam )
{
m_vecMaterialHandle[ nMaterialIndex ]->SetCustomParamList( m_pAdditionalCustomParam->GetCustomParamList( nMaterialIndex ) );
}
}
}