DragonNest/Client/EtUITool/GenTexture.cpp

356 lines
9.9 KiB
C++
Raw Normal View History

2024-12-19 09:48:26 +08:00
#include "Stdafx.h"
#include "GenTexture.h"
#include "UIToolTemplate.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
struct STemplateTexture
{
EtTextureHandle hTexture;
int nIndex1;
int nIndex2;
SUICoord UVCoord;
};
bool TemplateTextureSortFunc( STemplateTexture Obj1, STemplateTexture Obj2 )
{
int nWidth1 = 0, nWidth2 = 0, nHeight1 = 0, nHeight2 = 0;
if( Obj1.hTexture )
{
nWidth1 = Obj1.hTexture->Width();
nHeight1 = Obj1.hTexture->Height();
}
if( Obj2.hTexture )
{
nWidth2 = Obj2.hTexture->Width();
nHeight2 = Obj2.hTexture->Height();
}
if( nWidth1 > nWidth2 )
{
return true;
}
else if( nWidth1 == nWidth2 )
{
if( nHeight1 > nHeight2 )
{
return true;
}
}
return false;
}
bool EmptySpaceSortFunc( SEmptySpaceTexGen Obj1, SEmptySpaceTexGen Obj2 )
{
if( Obj1.GetSpace() < Obj2.GetSpace() )
{
return true;
}
return false;
}
bool ArrangeTexture( std::vector< STemplateTexture > &vecTemplateTexture, std::vector< SEmptySpaceTexGen > &vecTexLayout, int &nWidth, int &nHeight )
{
int i, j;
std::vector< SEmptySpaceTexGen > vecEmptySpace;
SEmptySpaceTexGen CurEmptySpace;
CurEmptySpace.Set( 0, 0, nWidth, nHeight );
vecEmptySpace.push_back( CurEmptySpace );
vecTexLayout.resize( vecTemplateTexture.size() );
for( i = 0; i < ( int )vecTemplateTexture.size(); i++ )
{
int nSameTexIndex;
int nTexWidth, nTexHeight;
if( ( !vecTemplateTexture[ i ].hTexture ) || ( vecTemplateTexture[ i ].hTexture->GetTexturePtr() == NULL ) )
{
SEmptySpaceTexGen TempEmptySpace;
TempEmptySpace.Set( 0, 0, 0, 0 );
vecTexLayout[ i ] = TempEmptySpace;
continue;
}
nSameTexIndex = -1;
for( j = 0; j < i; j++ )
{
if( vecTemplateTexture[ i ].hTexture == vecTemplateTexture[ j ].hTexture )
{
nSameTexIndex = j;
}
}
if( nSameTexIndex == -1 )
{
float fBestSpaceRatio = 0.0f;
int nBestFitIndex = -1;
nTexWidth = vecTemplateTexture[ i ].hTexture->Width() + 2;
nTexHeight = vecTemplateTexture[ i ].hTexture->Height() + 2;
for( j = 0; j < ( int )vecEmptySpace.size(); j++ )
{
if( ( nTexWidth <= vecEmptySpace[ j ].nWidth ) && ( nTexHeight <= vecEmptySpace[ j ].nHeight ) )
{
float fRatio;
fRatio = nTexWidth * nTexHeight / ( float )vecEmptySpace[ j ].nWidth * vecEmptySpace[ j ].nHeight;
if( fRatio > fBestSpaceRatio )
{
fRatio = fBestSpaceRatio;
nBestFitIndex = j;
}
}
}
if( nBestFitIndex != -1 )
{
SEmptySpaceTexGen Temp1, Temp2;
int nModWidth, nModHeight;
nModWidth = vecEmptySpace[ nBestFitIndex ].nWidth - nTexWidth;
nModHeight = vecEmptySpace[ nBestFitIndex ].nHeight - nTexHeight;
if( nModWidth >= nModHeight )
{
Temp1.nX = vecEmptySpace[ nBestFitIndex ].nX + nTexWidth;
Temp1.nWidth = vecEmptySpace[ nBestFitIndex ].nWidth - nTexWidth;
Temp1.nY = vecEmptySpace[ nBestFitIndex ].nY;
Temp1.nHeight = vecEmptySpace[ nBestFitIndex ].nHeight;
Temp2.nX = vecEmptySpace[ nBestFitIndex ].nX;
Temp2.nWidth = nTexWidth;
Temp2.nY = vecEmptySpace[ nBestFitIndex ].nY + nTexHeight;
Temp2.nHeight = vecEmptySpace[ nBestFitIndex ].nHeight - nTexHeight;
}
else
{
Temp1.nX = vecEmptySpace[ nBestFitIndex ].nX + nTexWidth;
Temp1.nWidth = vecEmptySpace[ nBestFitIndex ].nWidth - nTexWidth;
Temp1.nY = vecEmptySpace[ nBestFitIndex ].nY;
Temp1.nHeight = nTexHeight;
Temp2.nX = vecEmptySpace[ nBestFitIndex ].nX;
Temp2.nWidth = vecEmptySpace[ nBestFitIndex ].nWidth;
Temp2.nY = vecEmptySpace[ nBestFitIndex ].nY + nTexHeight;
Temp2.nHeight = vecEmptySpace[ nBestFitIndex ].nHeight - nTexHeight;
}
CurEmptySpace = vecEmptySpace[ nBestFitIndex ];
vecEmptySpace.erase( vecEmptySpace.begin() + nBestFitIndex );
if( ( Temp1.nWidth > 2 ) && ( Temp1.nHeight > 2 ) )
{
vecEmptySpace.push_back( Temp1 );
}
if( ( Temp2.nWidth > 2 ) && ( Temp2.nHeight > 2 ) )
{
vecEmptySpace.push_back( Temp2 );
}
std::sort( vecEmptySpace.begin(), vecEmptySpace.end(), EmptySpaceSortFunc );
}
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..
{
return false;
}
}
if( nSameTexIndex == -1 )
{
vecTexLayout[ i ] = CurEmptySpace;
}
else
{
vecTexLayout[ i ] = vecTexLayout[ nSameTexIndex ];
}
}
int nMaxY = 0;
// <20><> <20>Ʒ<EFBFBD> üũ<C3BC><C5A9> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
// Height<68><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʾƼ<CABE> 50x29¥<39><C2A5> 2<><32><EFBFBD><EFBFBD> 64x64<36><34> <20>־<EFBFBD><D6BE><EFBFBD><EFBFBD>ϴµ<CFB4>, 64x32<33>ؽ<EFBFBD>ó<EFBFBD><C3B3> <20>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD>.
//for( i = 0; i < ( int )vecEmptySpace.size(); i++ )
//{
// if( vecEmptySpace[ i ].nY > nMaxY )
// {
// nMaxY = vecEmptySpace[ i ].nY;
// }
//}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ȵǼ<C8B5> <20>ٷ<EFBFBD> Ŀ<><C4BF><EFBFBD>ϱ<EFBFBD> <20><> <20>׷<EFBFBD><D7B7><EFBFBD>. -> <20>ƹ<EFBFBD><C6B9><EFBFBD><EFBFBD><EFBFBD> <20>ʿ<EFBFBD><CABF>Ѱ<EFBFBD> <20><><EFBFBD>Ƽ<EFBFBD> Ŀ<><C4BF>.
for( i = 0; i < ( int )vecTemplateTexture.size(); i++ )
{
if( vecTemplateTexture[ i ].hTexture )
{
int nTexHeight = vecTemplateTexture[ i ].hTexture->Height() + 2;
if( vecTexLayout[ i ].nY + nTexHeight > nMaxY )
{
nMaxY = vecTexLayout[ i ].nY + nTexHeight;
}
}
}
if( nMaxY != 0 )
{
while( nHeight / 2 >= nMaxY )
{
nHeight /= 2;
if( nHeight == 0 )
{
return true;
}
}
}
return true;
}
int g_anOffsetX[] = { -1, 1, -1, 1, -1, 1, 0, 0, 0 };
int g_anOffsetY[] = { -1, -1, 1, 1, 0, 0, -1, 1, 0 };
void MakeTexture( EtTextureHandle hArrangeTexture, std::vector< CUIToolTemplate * > &vecToolTemplate, std::vector< STemplateTexture > &vecTemplateTexture, std::vector< SEmptySpaceTexGen > &vecTexLayout, int nWidth, int nHeight, bool bUseTemplateUVCoord )
{
int i, j;
for( i = 0; i < ( int )vecTemplateTexture.size(); i++ )
{
if( vecTexLayout[ i ].nWidth == 0 )
{
SUICoord TempCoord;
memset( &TempCoord, 0, sizeof( SUICoord ) );
if( bUseTemplateUVCoord )
vecToolTemplate[ vecTemplateTexture[ i ].nIndex1 ]->m_Template.m_vecElement[ vecTemplateTexture[ i ].nIndex2 ].TemplateUVCoord = TempCoord;
else
vecToolTemplate[ vecTemplateTexture[ i ].nIndex1 ]->m_Template.m_vecElement[ vecTemplateTexture[ i ].nIndex2 ].UVCoord = TempCoord;
continue;
}
LPDIRECT3DSURFACE9 pTargetSurface, pSourceSurface;
RECT DestRect, TempRect;
int nTexWidth = vecTemplateTexture[ i ].hTexture->Width() + 2;
int nTexHeight = vecTemplateTexture[ i ].hTexture->Height() + 2;
DestRect.left = vecTexLayout[ i ].nX + 1;
DestRect.right = DestRect.left + ( nTexWidth - 2 );
DestRect.top = vecTexLayout[ i ].nY + 1;
DestRect.bottom = DestRect.top + ( nTexHeight - 2 );
int nIndex1, nIndex2;
SUICoord UVCoord;
UVCoord.fX = ( vecTexLayout[ i ].nX + 1 ) / ( float )nWidth;
UVCoord.fY = ( vecTexLayout[ i ].nY + 1 ) / ( float )nHeight;
UVCoord.fWidth = ( nTexWidth - 2 ) / ( float )nWidth;
UVCoord.fHeight = ( nTexHeight - 2 ) / ( float )nHeight;
nIndex1 = vecTemplateTexture[ i ].nIndex1;
nIndex2 = vecTemplateTexture[ i ].nIndex2;
if( bUseTemplateUVCoord )
vecToolTemplate[ nIndex1 ]->m_Template.m_vecElement[ nIndex2 ].TemplateUVCoord = UVCoord;
else
vecToolTemplate[ nIndex1 ]->m_Template.m_vecElement[ nIndex2 ].UVCoord = UVCoord;
vecTemplateTexture[ i ].UVCoord = UVCoord;
pTargetSurface = hArrangeTexture->GetSurfaceLevel();
pSourceSurface = vecTemplateTexture[ i ].hTexture->GetSurfaceLevel();
for( j = 0; j < 9; j++ )
{
TempRect = DestRect;
OffsetRect( &TempRect, g_anOffsetX[ j ], g_anOffsetY[ j ] );
D3DXLoadSurfaceFromSurface( pTargetSurface, NULL, &TempRect, pSourceSurface, NULL, NULL, D3DX_FILTER_NONE, 0 );
}
}
}
EtTextureHandle GenerateTexture( std::vector< CUIToolTemplate * > &vecToolTemplate, bool bUseTemplateUVCoord )
{
int i, j, nTotalSpace, nReqWidth, nReqHeight;
EtTextureHandle hTexture, hGenerateTexture;
std::vector< STemplateTexture > vecTemplateTexture;
// <20>̷<EFBFBD><CCB7><EFBFBD> <20>ϸ<EFBFBD> LayoutView<65><77><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>Ϲ<EFBFBD> <20><><EFBFBD>̾<EFBFBD><CCBE>α׿<CEB1><D7BF><EFBFBD><EFBFBD><EFBFBD>,
// TemplateView<65><77><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD>ø<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD> <20><><EFBFBD>̾<EFBFBD><CCBE>α׿<CEB1><D7BF><EFBFBD><EFBFBD><EFBFBD>, <20>ؽ<EFBFBD>ó<EFBFBD><C3B3> <20>ȸ<EFBFBD><C8B8><EFBFBD><EFBFBD><EFBFBD> <20>ȴ<EFBFBD>.
// <20><><EFBFBD>̾<EFBFBD><CCBE>α׸<CEB1><D7B8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ؽ<EFBFBD>ó<EFBFBD><C3B3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ü<EFBFBD><C3BC> <20><><EFBFBD>ϱ<CFB1><E2B6A7><EFBFBD><EFBFBD>, <20>̰<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD> <20><>.
// (<28><EFBFBD><ECBCB1> <20>ؿܶ<D8BF><DCB6><EFBFBD><EFBFBD><EFBFBD> Ŀ<><C4BF> <20>Ұ<EFBFBD>)
//if( bUseTemplateUVCoord == false ) // <20><><EFBFBD><EFBFBD>
// return hGenerateTexture;
nTotalSpace = 0;
for( i = 0; i < ( int )vecToolTemplate.size(); i++ )
{
for( j = 0; j < ( int )vecToolTemplate[ i ]->m_vecTextureName.size(); j++ )
{
STemplateTexture TemplateTexture;
TemplateTexture.hTexture = LoadResource( vecToolTemplate[ i ]->m_vecTextureName[ j ].c_str(), RT_TEXTURE );
if( TemplateTexture.hTexture )
{
nTotalSpace += ( TemplateTexture.hTexture->Width() + 2 ) * ( TemplateTexture.hTexture->Height() + 2 );
}
TemplateTexture.nIndex1 = i;
TemplateTexture.nIndex2 = j;
vecTemplateTexture.push_back( TemplateTexture );
}
}
nReqWidth = 2;
nReqHeight = 2;
while( nReqWidth * nReqHeight < nTotalSpace )
{
if( nReqWidth == nReqHeight )
{
nReqWidth *= 2;
}
else
{
nReqHeight *= 2;
}
}
std::sort( vecTemplateTexture.begin(), vecTemplateTexture.end(), TemplateTextureSortFunc );
std::vector< SEmptySpaceTexGen > vecTexLayout;
while( 1 )
{
if( ArrangeTexture( vecTemplateTexture, vecTexLayout, nReqWidth, nReqHeight ) )
{
break;
}
if( nReqWidth == nReqHeight )
{
nReqWidth *= 2;
}
else
{
nReqHeight *= 2;
}
}
D3DLOCKED_RECT LockedRect;
if( bUseTemplateUVCoord && nReqWidth == 2 && nReqHeight == 2 )
{
// <20><><EFBFBD>ø<EFBFBD> <20>ؽ<EFBFBD>ó<EFBFBD><C3B3> <20><><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD> <20>ؽ<EFBFBD>ó <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ؽ<EFBFBD>ó<EFBFBD><C3B3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʰ<EFBFBD> <20>׳<EFBFBD> <20>н<EFBFBD><D0BD>Ѵ<EFBFBD>.
}
else if( nReqWidth * nReqHeight == 0 )
{
hGenerateTexture = CEtTexture::CreateNormalTexture( 16, 16, FMT_A8R8G8B8, USAGE_DYNAMIC, POOL_DEFAULT );
}
else
{
hGenerateTexture = CEtTexture::CreateNormalTexture( nReqWidth, nReqHeight, FMT_A8R8G8B8, USAGE_DYNAMIC, POOL_DEFAULT );
( ( EtTexture * )hGenerateTexture->GetTexturePtr() )->LockRect( 0, &LockedRect, NULL, D3DLOCK_DISCARD );
memset( LockedRect.pBits, 0, hGenerateTexture->Height() * LockedRect.Pitch );
( ( EtTexture * )hGenerateTexture->GetTexturePtr() )->UnlockRect( 0 );
MakeTexture( hGenerateTexture, vecToolTemplate, vecTemplateTexture, vecTexLayout, nReqWidth, nReqHeight, bUseTemplateUVCoord );
}
for( i = 0; i < ( int )vecTemplateTexture.size(); i++ )
{
SAFE_RELEASE_SPTR( vecTemplateTexture[ i ].hTexture );
}
CEtResource::FlushWaitDelete();
return hGenerateTexture;
}