277 lines
6.6 KiB
C++
277 lines
6.6 KiB
C++
#include "stdafx.h"
|
|
//#include "Util.h"
|
|
#include "KRenderDevice.h"
|
|
#include "KResource.h"
|
|
#include "TerrainTextureInfo.h"
|
|
#include "KResourceManager.h"
|
|
#include <kfile/KFileManager.h>
|
|
|
|
#include <mmo/ArTime.h>
|
|
|
|
#ifdef _MEMORY_LEAK_FIX_
|
|
const DWORD TEXTURE_HOLD_TIME = 0;
|
|
#else
|
|
const DWORD TEXTURE_HOLD_TIME = 300000;
|
|
#endif
|
|
|
|
CTerrainTextureInfo::CTerrainTextureInfo()
|
|
: m_pDevice( NULL )
|
|
{
|
|
m_dwLastTextureRemoveTime = GetSafeTickCount();
|
|
}
|
|
|
|
CTerrainTextureInfo::~CTerrainTextureInfo()
|
|
{
|
|
Release();
|
|
}
|
|
|
|
bool CTerrainTextureInfo::Initialize( const char* szTextureInfoFileName, K3DRenderDevice* pDevice )
|
|
{
|
|
THREAD_SYNCRONIZE( m_lckTexture );
|
|
|
|
Release();
|
|
m_pDevice = pDevice;
|
|
|
|
// dummy texture 생성
|
|
if( !InitializeDummyTexture() )
|
|
return false;
|
|
|
|
// 파일로부터 text들을 읽어낸다.
|
|
STRING_VECTOR TextLines;
|
|
{
|
|
KStream* pStream = KFileManager::Instance().CreateStreamFromResource( szTextureInfoFileName, false );
|
|
if( NULL == pStream )
|
|
return false;
|
|
|
|
int nTextLength = int( pStream->GetLength() );
|
|
char* pEntireText = new char[ nTextLength + 1 ];
|
|
|
|
pStream->Read( pEntireText, sizeof(char) * nTextLength );
|
|
pEntireText[ nTextLength ] = '\0';
|
|
delete pStream;
|
|
|
|
CStringUtil::GetTextLinesFromString( pEntireText, TextLines );
|
|
delete [] pEntireText;
|
|
}
|
|
|
|
const char* c_szCategory = "CATEGORY=";
|
|
const char* c_szDetail = "DETAIL=";
|
|
const char* c_szTexture = "TEXTURE=";
|
|
|
|
int nCurrentCategory = 0;
|
|
float fCurrentDetailRatio = 1.f;
|
|
|
|
DWORD stime = GetSafeTickCount();
|
|
|
|
for( size_t n = 0; n < TextLines.size(); ++n )
|
|
{
|
|
std::string strLine = TextLines[n];
|
|
|
|
if( ';' == strLine[0] )
|
|
continue;
|
|
|
|
std::string strContent;
|
|
|
|
// category
|
|
if( CStringUtil::GetContentString( strLine, c_szCategory, strContent ) )
|
|
{
|
|
if( strContent.size() > 0 )
|
|
{
|
|
nCurrentCategory = (-1);
|
|
for( size_t nCategory = 0; nCategory < m_CategoryNames.size(); ++nCategory )
|
|
{
|
|
if( m_CategoryNames[nCategory] == strContent )
|
|
{
|
|
// 이미 존재하는 category명인 경우 그대로 사용
|
|
nCurrentCategory = static_cast<int>(nCategory);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 새로운 category명을 추가
|
|
if( (-1) == nCurrentCategory )
|
|
{
|
|
m_CategoryNames.push_back( strContent );
|
|
nCurrentCategory = static_cast<int>( m_CategoryNames.size() - 1 );
|
|
}
|
|
}
|
|
}
|
|
// detail
|
|
else if( CStringUtil::GetContentString( strLine, c_szDetail, strContent ) )
|
|
{
|
|
fCurrentDetailRatio = (float)(::atof( strContent.c_str() ));
|
|
if( 0.f == fCurrentDetailRatio )
|
|
fCurrentDetailRatio = 1.f;
|
|
}
|
|
// texture
|
|
else if( CStringUtil::GetContentString( strLine, c_szTexture, strContent ) )
|
|
{
|
|
// ',' 문자를 찾는다.
|
|
int nCommaPos = static_cast<int>( strContent.find( ',' ) );
|
|
if( nCommaPos != std::string::npos )
|
|
{
|
|
// ',' 앞의 텍스쳐 번호
|
|
std::string strTexNum;
|
|
strTexNum.assign( strContent, 0, nCommaPos );
|
|
|
|
// ',' 뒤의 텍스쳐 파일명
|
|
std::string strTexFileName;
|
|
strTexFileName.assign( strContent, nCommaPos + 1, strContent.size() - (nCommaPos + 1) );
|
|
|
|
if( strTexNum.size() > 0 && strTexFileName.size() > 0 )
|
|
{
|
|
WORD wTexNum = static_cast<WORD>( ::atoi( strTexNum.c_str() ) );
|
|
|
|
K3DTexture* pTexture = NULL;
|
|
#ifndef _RAC
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
pTexture = KTextureManager::GetManager()->RefreshTexture( strTexFileName.c_str(), &loadpack );
|
|
#endif
|
|
|
|
TEXINFO_STRUCT ts;
|
|
ts.bIsLoadFailed = false;
|
|
ts.nCategory = nCurrentCategory;
|
|
ts.fDetailRatio = fCurrentDetailRatio;
|
|
ts.spTexture = pTexture;
|
|
ts.strName = strTexFileName;
|
|
|
|
m_mapTexInfo[ wTexNum ] = ts;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//_oprint( "TerrainTextureInfo Loading Time : %d\n", GetSafeTickCount()-stime );
|
|
|
|
// category가 한번도 안 나온 경우
|
|
if( m_CategoryNames.size() == 0 )
|
|
m_CategoryNames.push_back( "?" );
|
|
|
|
return true;
|
|
}
|
|
|
|
void CTerrainTextureInfo::Release()
|
|
{
|
|
THREAD_SYNCRONIZE( m_lckTexture );
|
|
|
|
ReleaseDummyTexture();
|
|
|
|
m_mapTexInfo.clear();
|
|
|
|
m_CategoryNames.clear();
|
|
}
|
|
|
|
bool CTerrainTextureInfo::InitializeDummyTexture()
|
|
{
|
|
ReleaseDummyTexture();
|
|
|
|
const int c_nDummyLength = 16;
|
|
|
|
m_spDummyTexture = m_pDevice->CreateTexture( c_nDummyLength, c_nDummyLength, K3DFMT_A1R5G5B5 );
|
|
if( m_spDummyTexture == NULL ) return false;
|
|
|
|
|
|
WORD* pBuf;
|
|
int nPitch;
|
|
|
|
m_spDummyTexture->LockRect( NULL, (void**)&pBuf, nPitch );
|
|
if( pBuf == NULL ) return false;
|
|
|
|
nPitch /= sizeof(WORD);
|
|
|
|
for( int nY = 0; nY < c_nDummyLength; nY++ )
|
|
for( int nX = 0; nX < c_nDummyLength; nX++ )
|
|
pBuf[ (nY * nPitch) + nX ] = ( nX == nY || (c_nDummyLength - nX) == (nY + 1) ) ? 0xFC00 : 0xFFFF;
|
|
|
|
m_spDummyTexture->Unlock();
|
|
return true;
|
|
}
|
|
|
|
void CTerrainTextureInfo::ReleaseDummyTexture()
|
|
{
|
|
}
|
|
|
|
void CTerrainTextureInfo::RemoveUnnecessaryTexture()
|
|
{
|
|
if( m_dwLastTextureRemoveTime + TEXTURE_HOLD_TIME > GetSafeTickCount() ) return;
|
|
|
|
THREAD_SYNCRONIZE( m_lckTexture );
|
|
|
|
DWORD dwCurrentTime = GetSafeTickCount();
|
|
|
|
for( std::map< WORD, TEXINFO_STRUCT >::iterator it = m_mapTexInfo.begin(); it != m_mapTexInfo.end(); ++it )
|
|
{
|
|
if( !(*it).second.spTexture || (*it).second.bIsLoadFailed )
|
|
continue;
|
|
|
|
if( (*it).second.spTexture->GetRefCount() > 1 )
|
|
continue;
|
|
|
|
if( (*it).second.dwLastAccessTime + TEXTURE_HOLD_TIME > dwCurrentTime )
|
|
continue;
|
|
|
|
(*it).second.spTexture = NULL;
|
|
}
|
|
|
|
m_dwLastTextureRemoveTime = GetSafeTickCount();
|
|
}
|
|
|
|
K3DTexture* CTerrainTextureInfo::GetNotFoundTexture()
|
|
{
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
return KTextureManager::GetManager()->RefreshTexture( "NotFound.dds", &loadpack );
|
|
}
|
|
|
|
K3DTexture* CTerrainTextureInfo::GetTexture( WORD wTextureNum )
|
|
{
|
|
std::map< WORD, TEXINFO_STRUCT >::iterator it;
|
|
|
|
{
|
|
THREAD_SYNCRONIZE( m_lckTexture );
|
|
|
|
it = m_mapTexInfo.find( wTextureNum );
|
|
if( it == m_mapTexInfo.end() )
|
|
return NULL;
|
|
|
|
(*it).second.dwLastAccessTime = GetSafeTickCount();
|
|
}
|
|
|
|
// 로딩 실패했던 텍스쳐라면 KIN
|
|
if( (*it).second.bIsLoadFailed )
|
|
return NULL;
|
|
|
|
if( (*it).second.spTexture == NULL)
|
|
{
|
|
// TODO: In the process of adding resource option loading
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
|
|
// Loading
|
|
(*it).second.spTexture = KTextureManager::GetManager()->RefreshTexture( (*it).second.strName.c_str(), &loadpack );
|
|
|
|
if((*it).second.spTexture == NULL)
|
|
{
|
|
std::string str = (*it).second.strName;
|
|
str += "\nNon-existent texture";
|
|
#ifndef _RAC
|
|
AfxMessageBox( str.c_str(), MB_OK | MB_ICONERROR );
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
if( (*it).second.spTexture != NULL)
|
|
{
|
|
//_oprint( "TERRAIN TEXTURE LOADING : %s (%d) (thread:%d)\n", (*it).second.strName.c_str(), wTextureNum, GetCurrentThreadId() );
|
|
}
|
|
else
|
|
{
|
|
(*it).second.bIsLoadFailed = true;
|
|
}
|
|
}
|
|
|
|
|
|
return (*it).second.spTexture;
|
|
} |