Files
2026-06-01 12:46:52 +02:00

1124 lines
30 KiB
C++

#include "stdafx.h"
#include <toolkit/XStringUtil.h>
#include "MapDefine.h"
#include <kfile/KFileManager.h>
#include <kfile/KStream.h>
#include "PVSObject.h"
#ifdef _DEBUG
#ifdef _RAC
#include "SDebug_Util.h"
#else
#define new DEBUG_NEW
#endif
#endif
PVSObject::PVSObject()
{
m_pHeader = NULL;
m_rcSegment = KRect(0,0,0,0);
}
PVSObject::~PVSObject()
{
SAFE_DELETE( m_pHeader );
{
SEGMENT_ROOT* pDATA=NULL;
bool res;
res = m_hashBySEGMENT.get_first_value( pDATA );
while ( res )
{
if ( pDATA != NULL )
{
delete pDATA;
}
res = m_hashBySEGMENT.get_next_value( pDATA );
}
m_hashBySEGMENT.clear();
}
{
PROP_ROOT* pDATA=NULL;
bool res;
res = m_hashByPROP.get_first_value( pDATA );
while ( res )
{
if ( pDATA != NULL )
{
delete pDATA;
}
res = m_hashByPROP.get_next_value( pDATA );
}
m_hashByPROP.clear();
}
}
bool PVSObject::IsMapCheck( int nMapStartX, int nMapStartY )
{
if( m_pHeader )
{
return ( m_pHeader->nMapStartPosX == nMapStartX && m_pHeader->nMapStartPosY == nMapStartY );
}
return false;
}
bool PVSObject::IsPVSActCheck( int nRootSegmentX, int nRootSegmentY )
{
if( m_pHeader )
{
return ( nRootSegmentX >= m_rcSegment.left && nRootSegmentX <= m_rcSegment.right &&
nRootSegmentY >= m_rcSegment.top && nRootSegmentY <= m_rcSegment.bottom );
}
return false;
}
void PVSObject::Load( const char* pFileName )
{
KStream* pStream = KFileManager::Instance().CreateStreamFromResource( pFileName );
if( NULL == pStream )
{
return;
}
SAFE_DELETE( m_pHeader );
m_pHeader = new NFM_PVS_HEADER_V1;
pStream->Read( m_pHeader, sizeof(NFM_PVS_HEADER_V1) );
for( int i(0); m_pHeader->nSegmentCount>i; i++ )
{
NFM_PVS_SEGMENT_V1 pvs_segment;
pStream->Read( &pvs_segment, sizeof(pvs_segment) );
int nWorldSegmentX = ( m_pHeader->nMapStartPosX*m_pHeader->nSegmentCountPerMap ) + pvs_segment.nSegmentX;
int nWorldSegmentY = ( m_pHeader->nMapStartPosY*m_pHeader->nSegmentCountPerMap ) + pvs_segment.nSegmentY;
SEGMENT_ROOT* pFind = NULL;
if( m_hashBySEGMENT.lookup( hashPr_SEGMENT::Key(nWorldSegmentX, nWorldSegmentY) ,pFind ) )
{
assert(0 && "m_hashBySEGMENT.lookup 이미 존재 함" );
}
else
{
//로컬->월드로 변경됨
SEGMENT_ROOT* pSEGMENT_ROOT = new SEGMENT_ROOT;
pSEGMENT_ROOT->nSegmentX = nWorldSegmentX;
pSEGMENT_ROOT->nSegmentY = nWorldSegmentY;
// _oprint( "Root Segment %d %d\n", nWorldSegmentX, nWorldSegmentY );
m_hashBySEGMENT.add( hashPr_SEGMENT::Key(nWorldSegmentX, nWorldSegmentY), pSEGMENT_ROOT );
for( int n(0); pvs_segment.nIncludeSegmentCount>n; n++ )
{
NFM_SEGMENT_DATA_V1 segment_data;
pStream->Read( &segment_data, sizeof(segment_data) );
int nSegmentX = ( m_pHeader->nMapStartPosX*m_pHeader->nSegmentCountPerMap ) + segment_data.nSegmentX;
int nSegmentY = ( m_pHeader->nMapStartPosY*m_pHeader->nSegmentCountPerMap ) + segment_data.nSegmentY;
SEGMENT_DATA* pDataFind = NULL;
if( pSEGMENT_ROOT->m_hashBySEGMENT.lookup( hashPr_SEGMENT::Key(nSegmentX, nSegmentY), pDataFind ) )
{
assert(0 && "pSEGMENT_ROOT->m_hashBySEGMENT.lookup 이미 존재 함" );
}
else
{
SEGMENT_DATA* pSEGMENT_DATA = new SEGMENT_DATA;
pSEGMENT_DATA->nSegmentX = nSegmentX;
pSEGMENT_DATA->nSegmentY = nSegmentY;
pSEGMENT_ROOT->m_hashBySEGMENT.add( hashPr_SEGMENT::Key(nSegmentX, nSegmentY), pSEGMENT_DATA );
}
}
}
}
for( int i(0); m_pHeader->nPropCount>i; i++ )
{
NFM_PVS_PROP_V1 pvs_prop;
pStream->Read( &pvs_prop, sizeof(pvs_prop) );
int nWorldSegmentX = ( m_pHeader->nMapStartPosX*m_pHeader->nSegmentCountPerMap ) + pvs_prop.nSegmentX;
int nWorldSegmentY = ( m_pHeader->nMapStartPosY*m_pHeader->nSegmentCountPerMap ) + pvs_prop.nSegmentY;
PROP_ROOT* pFind = NULL;
if( m_hashByPROP.lookup( hashPr_SEGMENT::Key( nWorldSegmentX, nWorldSegmentY ), pFind ) )
{
assert(0 && "m_hashByPROP.lookup 이미 존재 함" );
}
else
{
PROP_ROOT* pPROP_ROOT = new PROP_ROOT;
pPROP_ROOT->nSegmentX = nWorldSegmentX;
pPROP_ROOT->nSegmentY = nWorldSegmentY;
m_hashByPROP.add( hashPr_SEGMENT::Key( nWorldSegmentX, nWorldSegmentY ), pPROP_ROOT );
for( int n(0); pvs_prop.nIncludePropCount>n; n++ )
{
NFM_PROP_DATA_V1 prop_data;
pStream->Read( &prop_data, sizeof(prop_data) );
PROP_DATA* pDataFind = NULL;
if( pPROP_ROOT->m_hashByPROP.lookup( hashPr_PROP::Key(prop_data.nSegmentIdx, prop_data.nPropIdx) , pDataFind ) )
{
// assert(0 && "pPROP_ROOT->m_hashByPROP.lookup 이미 존재함" );
_oprint( "pPROP_ROOT->m_hashByPROP.lookup 이미 존재함 %d %d\n", prop_data.nSegmentIdx, prop_data.nPropIdx );
}
else
{
PROP_DATA* pPROP_DATA = new PROP_DATA;
pPROP_DATA->nSegmentIdx = prop_data.nSegmentIdx;
pPROP_DATA->nPropIdx = prop_data.nPropIdx;
pPROP_ROOT->m_hashByPROP.add( hashPr_PROP::Key(prop_data.nSegmentIdx, prop_data.nPropIdx), pPROP_DATA );
}
}
}
}
//World 변환
m_rcSegment.left = (m_pHeader->nMapStartPosX*m_pHeader->nSegmentCountPerMap) + m_pHeader->nSegmentLeft;
m_rcSegment.right = (m_pHeader->nMapStartPosX*m_pHeader->nSegmentCountPerMap) + m_pHeader->nSegmentRight;
m_rcSegment.top = (m_pHeader->nMapStartPosY*m_pHeader->nSegmentCountPerMap) + m_pHeader->nSegmentTop;
m_rcSegment.bottom = (m_pHeader->nMapStartPosY*m_pHeader->nSegmentCountPerMap) + m_pHeader->nSegmentBottom;
delete pStream;
}
struct _SEG_DATA_
{
int nSegX;
int nSegY;
int nSelect;
};
struct _PROP_DATA_
{
size_t nSegmentIdx;
size_t nPropIdx;
int nSelect;
};
struct SegmentCompareFN
{
bool operator() ( _SEG_DATA_& pr1, _SEG_DATA_& pr2 )
{
if( pr1.nSegX != pr2.nSegX )
return pr1.nSegX < pr2.nSegX;
else
return pr1.nSegY < pr2.nSegY;
}
};
struct PropCompareFN
{
bool operator() ( _PROP_DATA_& pr1, _PROP_DATA_& pr2 )
{
if( pr1.nSegmentIdx != pr2.nSegmentIdx )
return pr1.nSegmentIdx < pr2.nSegmentIdx;
else
return pr1.nPropIdx < pr2.nPropIdx;
}
};
void PVSObject::ExportTxt( int nMode, const char* pFileName, int nRootSegmentX, int nRootSegmentY, std::vector<size_t>& vSegXList, std::vector<size_t>& vSegYList, std::vector<size_t>& vPropIdxList, std::vector<size_t>& vPropNumList )
{
if( !m_pHeader ) return;
int nWorldX = m_pHeader->nMapStartPosX*m_pHeader->nSegmentCountPerMap;
int nWorldY = m_pHeader->nMapStartPosY*m_pHeader->nSegmentCountPerMap;
std::vector< _SEG_DATA_ > export_seglist;
std::vector< _PROP_DATA_ > export_proplist;
//Segment
{
SEGMENT_ROOT* pFind = NULL;
if( m_hashBySEGMENT.lookup( hashPr_SEGMENT::Key(nRootSegmentX, nRootSegmentY), pFind ) )
{
SEGMENT_DATA* pDATA=NULL;
bool res;
res = pFind->m_hashBySEGMENT.get_first_value( pDATA );
while ( res )
{
if ( pDATA != NULL )
{ //로컬 변환 됨
_SEG_DATA_ data;
data.nSegX = pDATA->nSegmentX-nWorldX;
data.nSegY = pDATA->nSegmentY-nWorldY;
data.nSelect = 0;
for( unsigned int i(0); vSegXList.size()>i; i++ )
{
if( data.nSegX == vSegXList[i] && data.nSegY == vSegYList[i] )
{
data.nSelect = 333; // Selected props
break;
}
}
export_seglist.push_back( data );
}
res = pFind->m_hashBySEGMENT.get_next_value( pDATA );
}
}
}
std::string strMode = "ROOT";
if( nMode == EXPORT_EXCHANGE )
strMode = "EXCHANGE";
else if( nMode == EXPORT_ADD )
strMode = "ADD";
else if( nMode == EXPORT_SUBTRACT )
strMode = "SUBTRACT";
_performance_print( "%s : %d %d\n", strMode.c_str(), nRootSegmentX-nWorldX, nRootSegmentY-nWorldY );
std::sort( export_seglist.begin(), export_seglist.end(), SegmentCompareFN() );
for( unsigned int i(0); export_seglist.size()>i; i++ )
{
_performance_print( "%d %d %d\n", export_seglist[i].nSegX, export_seglist[i].nSegY, export_seglist[i].nSelect );
}
//Prop
{
PROP_ROOT* pFind = NULL;
if( m_hashByPROP.lookup( hashPr_SEGMENT::Key(nRootSegmentX, nRootSegmentY), pFind ) )
{
PROP_DATA* pDATA=NULL;
bool res;
res = pFind->m_hashByPROP.get_first_value( pDATA );
while ( res )
{
if ( pDATA != NULL )
{
_PROP_DATA_ data;
data.nSegmentIdx = pDATA->nSegmentIdx;
data.nPropIdx = pDATA->nPropIdx;
data.nSelect = 0;
for( unsigned int i(0); vPropIdxList.size()>i; i++ )
{
if( data.nSegmentIdx == vPropIdxList[i] && data.nPropIdx == vPropNumList[i] )
{
data.nSelect = 777; //선택된 프랍들
break;
}
}
export_proplist.push_back( data );
}
res = pFind->m_hashByPROP.get_next_value( pDATA );
}
}
}
std::sort( export_proplist.begin(), export_proplist.end(), PropCompareFN() );
for( unsigned int i(0); export_proplist.size()>i; i++ )
_performance_print( "%d %d %d\n", export_proplist[i].nSegmentIdx, export_proplist[i].nPropIdx, export_proplist[i].nSelect );
FILE* pF = fopen( pFileName, "wt" );
if( pF )
{
//Header
fprintf( pF, "%s|%d|%d|\n", strMode.c_str(), nRootSegmentX-nWorldX, nRootSegmentY-nWorldY );
//Segment
for( unsigned int i(0); export_seglist.size()>i; i++ )
{
if( export_seglist[i].nSelect != 0 )
fprintf( pF, "SEG|%d|%d|%d|\n", export_seglist[i].nSegX, export_seglist[i].nSegY, export_seglist[i].nSelect );
else
fprintf( pF, "SEG|%d|%d|\n", export_seglist[i].nSegX, export_seglist[i].nSegY );
}
//Prop
for( unsigned int i(0); export_proplist.size()>i; i++ )
{
if( export_proplist[i].nSelect != 0 )
fprintf( pF, "PROP|%d|%d|%d|\n", export_proplist[i].nSegmentIdx, export_proplist[i].nPropIdx, export_proplist[i].nSelect );
else
fprintf( pF, "PROP|%d|%d|\n", export_proplist[i].nSegmentIdx, export_proplist[i].nPropIdx );
}
fclose( pF );
}
}
bool PVSObject::IsVisibleSegment( int nRootSegmentX, int nRootSegmentY, int nSegmentX, int nSegmentY )
{
SEGMENT_ROOT* pFind = NULL;
if( m_hashBySEGMENT.lookup( hashPr_SEGMENT::Key(nRootSegmentX, nRootSegmentY), pFind ) )
{
SEGMENT_DATA* pData = NULL;
if( pFind->m_hashBySEGMENT.lookup( hashPr_SEGMENT::Key(nSegmentX, nSegmentY), pData ) )
{
return true;
}
}
return false;
}
bool PVSObject::IsVisibleProp( int nRootSegmentX, int nRootSegmentY, size_t nSegmentIdx, size_t nPropIdx )
{
PROP_ROOT* pFind = NULL;
if( m_hashByPROP.lookup( hashPr_SEGMENT::Key(nRootSegmentX, nRootSegmentY), pFind ) )
{
PROP_DATA* pData = NULL;
if( pFind->m_hashByPROP.lookup( hashPr_PROP::Key(nSegmentIdx, nPropIdx), pData ) )
{
return true;
}
}
return false;
}
int PVSObject::GetCountChildSegment( int nRootSegmentX, int nRootSegmentY )
{
SEGMENT_ROOT* pFind = NULL;
if( m_hashBySEGMENT.lookup( hashPr_SEGMENT::Key(nRootSegmentX, nRootSegmentY), pFind ) )
return (int)pFind->m_hashBySEGMENT.size();
else
return -1; //데이타 없음
return -2;
}
int PVSObject::GetCountChildProp( int nRootSegmentX, int nRootSegmentY )
{
PROP_ROOT* pFind = NULL;
if( m_hashByPROP.lookup( hashPr_SEGMENT::Key(nRootSegmentX, nRootSegmentY), pFind ) )
return (int)pFind->m_hashByPROP.size();
else
return -1; //데이타 없음
return -2;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//PVSObjectManager
bool PVSObjectManager::m_sToggleAct = true;
PVSObjectManager::PVSObjectManager()
{
m_pCurPVSObject = NULL;
m_bIsPVSActive = false;
}
PVSObjectManager::~PVSObjectManager()
{
Clear();
}
//현재 위치 설정
void PVSObjectManager::SetRootSegment( int nSegmentX, int nSegmentY )
{
m_nRootSegmentX = nSegmentX;
m_nRootSegmentY = nSegmentY;
if( m_pCurPVSObject )
m_bIsPVSActive = m_pCurPVSObject->IsPVSActCheck( nSegmentX, nSegmentY );
else
m_bIsPVSActive = false;
}
bool PVSObjectManager::IsPVSActive()
{
if( m_sToggleAct == false ) return false;
return m_bIsPVSActive;
}
bool PVSObjectManager::CheckSegment( int nSegmentX, int nSegmentY )
{
if( m_pCurPVSObject )
{
return m_pCurPVSObject->IsVisibleSegment( m_nRootSegmentX, m_nRootSegmentY, nSegmentX, nSegmentY );
}
return false;
}
bool PVSObjectManager::CheckProp( size_t nSegmentIdx, size_t nPropIdx )
{
if( m_pCurPVSObject )
{
return m_pCurPVSObject->IsVisibleProp( m_nRootSegmentX, m_nRootSegmentY, nSegmentIdx, nPropIdx );
}
return false;
}
void PVSObjectManager::convertWorldToMapPos(int worldPosX, int worldPosY, int& mapX, int& mapY)
{
mapX = worldPosX/16128;
mapY = worldPosY/16128;
}
//Load
//Warp Loading ex) 던전
void PVSObjectManager::WarpLoad( int nWorldPosX, int nWorldPosY )
{
int nStartMapX = nWorldPosX/16128;
int nStartMapY = nWorldPosY/16128;
//이미 로딩 되어 있는가?
for( unsigned int i(0); m_vPVSObjectList.size()>i; i++ )
{
if( m_vPVSObjectList[i]->IsMapCheck( nStartMapX, nStartMapY ) )
return;
}
//새로 로딩
std::string strFileName;
XStringUtil::Format( strFileName, "m%03d_%03d.pvs", nStartMapX, nStartMapY );
if( !KFileManager::Instance().IsValidResource( strFileName.c_str() ) )
return;
PVSObject* pPVSObject = new PVSObject;
pPVSObject->Load( strFileName.c_str() );
m_vPVSObjectList.push_back( pPVSObject );
m_pCurPVSObject = pPVSObject;
}
//Thread Loading ex) 마을
void PVSObjectManager::ThreadLoad( int nWorldPosX, int nWorldPosY )
{
}
void PVSObjectManager::Clear()
{
m_pCurPVSObject = NULL;
SAFE_DELETE_VECTOR( m_vPVSObjectList );
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//PVS Merge
PVSMerge::PVSMerge()
{
}
PVSMerge::~PVSMerge()
{
Clear();
}
void PVSMerge::Init()
{
memset( &m_Mainheader, 0, sizeof(m_Mainheader) );
Clear();
}
void PVSMerge::Clear()
{
for( unsigned int i(0); m_vMergeSegment.size()>i; i++ )
{
delete m_vMergeSegment[i]->pSegment;
for( unsigned int n(0); m_vMergeSegment[i]->vSegmentList.size()>n; n++ )
{
delete m_vMergeSegment[i]->vSegmentList[n];
}
m_vMergeSegment[i]->vSegmentList.clear();
delete m_vMergeSegment[i];
}
m_vMergeSegment.clear();
for( unsigned int i(0); m_vMergeProp.size()>i; i++ )
{
delete m_vMergeProp[i]->pProp;
for( unsigned int n(0); m_vMergeProp[i]->vPropList.size()>n; n++ )
{
delete m_vMergeProp[i]->vPropList[n];
}
m_vMergeProp[i]->vPropList.clear();
delete m_vMergeProp[i];
}
m_vMergeProp.clear();
}
unsigned int PVSMerge::MergeSegment( std::vector< MERGE_SEGMENT* >& main_list, struct NFM_PVS_SEGMENT_V1* pMergeSegment, std::vector<NFM_SEGMENT_DATA_V1>& segment_list )
{
bool bCheckSegment;
for( unsigned int i(0); main_list.size()>i; i++ )
{
//기존에 존재하는 세그먼트
if( main_list[i]->pSegment->nSegmentX == pMergeSegment->nSegmentX &&
main_list[i]->pSegment->nSegmentY == pMergeSegment->nSegmentY )
{
for( unsigned int n(0); segment_list.size()>n; n++ )
{
bCheckSegment = false;
for( unsigned int j(0); main_list[i]->vSegmentList.size()>j; j++ )
{
if( segment_list[n].nSegmentX == main_list[i]->vSegmentList[j]->nSegmentX &&
segment_list[n].nSegmentY == main_list[i]->vSegmentList[j]->nSegmentY )
{ //이미 포함
bCheckSegment = true;
break;
}
}
if( !bCheckSegment )
{ //새로 추가 되는 세그먼트 데이타
NFM_SEGMENT_DATA_V1* pData = new NFM_SEGMENT_DATA_V1;
pData->nSegmentX = segment_list[n].nSegmentX;
pData->nSegmentY = segment_list[n].nSegmentY;
main_list[i]->vSegmentList.push_back( pData );
}
}
//세그먼트 수 변경
main_list[i]->pSegment->nIncludeSegmentCount += main_list[i]->vSegmentList.size();
return main_list.size();
}
}
//새로 추가 되는 것, 모두 포함
MERGE_SEGMENT* pNewMergeSegment = new MERGE_SEGMENT;
pNewMergeSegment->pSegment = new NFM_PVS_SEGMENT_V1;
pNewMergeSegment->pSegment->nSegmentX = pMergeSegment->nSegmentX;
pNewMergeSegment->pSegment->nSegmentY = pMergeSegment->nSegmentY;
pNewMergeSegment->pSegment->nIncludeSegmentCount = pMergeSegment->nIncludeSegmentCount;
for( unsigned int i(0); segment_list.size()>i; i++ )
{
NFM_SEGMENT_DATA_V1* pData = new NFM_SEGMENT_DATA_V1;
pData->nSegmentX = segment_list[i].nSegmentX;
pData->nSegmentY = segment_list[i].nSegmentY;
pNewMergeSegment->vSegmentList.push_back( pData );
}
assert( pNewMergeSegment->pSegment->nIncludeSegmentCount == pNewMergeSegment->vSegmentList.size() );
main_list.push_back( pNewMergeSegment );
return main_list.size();
}
unsigned int PVSMerge::MergeProp( std::vector< MERGE_PROP* >& main_list, struct NFM_PVS_PROP_V1* pMergeProp, std::vector<NFM_PROP_DATA_V1>& prop_list )
{
bool bCheckProp = false;
for( unsigned int i(0); main_list.size()>i; i++ )
{
//기존에 존재하는 프랍
if( main_list[i]->pProp->nSegmentX == pMergeProp->nSegmentX &&
main_list[i]->pProp->nSegmentY == pMergeProp->nSegmentY )
{
for( unsigned int n(0); prop_list.size()>n; n++ )
{
bCheckProp = false;
for( unsigned int j(0); main_list[i]->vPropList.size()>j; j++ )
{
if( prop_list[n].nSegmentIdx == main_list[i]->vPropList[j]->nSegmentIdx &&
prop_list[n].nPropIdx == main_list[i]->vPropList[j]->nPropIdx )
{ //이미 포함
bCheckProp = true;
break;
}
}
if( !bCheckProp )
{ //새로 추가 되는 세그먼트 데이타
NFM_PROP_DATA_V1* pData = new NFM_PROP_DATA_V1;
pData->nSegmentIdx = prop_list[n].nSegmentIdx;
pData->nPropIdx = prop_list[n].nPropIdx ;
main_list[i]->vPropList.push_back( pData );
}
}
//세그먼트 수 변경
main_list[i]->pProp->nIncludePropCount += main_list[i]->vPropList.size();
return main_list.size();
}
}
//새로 추가 되는 프랍
MERGE_PROP* pNewMergeProp = new MERGE_PROP;
pNewMergeProp->pProp = new NFM_PVS_PROP_V1;
pNewMergeProp->pProp->nSegmentX = pMergeProp->nSegmentX;
pNewMergeProp->pProp->nSegmentY = pMergeProp->nSegmentY;
pNewMergeProp->pProp->nIncludePropCount = pMergeProp->nIncludePropCount;
for( unsigned int i(0); prop_list.size()>i; i++ )
{
NFM_PROP_DATA_V1* pData = new NFM_PROP_DATA_V1;
pData->nSegmentIdx = prop_list[i].nSegmentIdx;
pData->nPropIdx = prop_list[i].nPropIdx ;
pNewMergeProp->vPropList.push_back( pData );
}
assert( pNewMergeProp->pProp->nIncludePropCount == pNewMergeProp->vPropList.size() );
main_list.push_back( pNewMergeProp );
return main_list.size();
}
void PVSMerge::MergeFile( const char * pFileName )
{
KStream* pStream = new KFileStream( pFileName );
if( NULL == pStream || !pStream->IsValid() )
{
return;
}
NFM_PVS_HEADER_V1 header;
pStream->Read( &header, sizeof(header) );
if( m_Mainheader.dwVersion == 0 )
{ //처음 값
strcpy_s( m_Mainheader.szSign, NFM_PVS_FILE_SIGN );
m_Mainheader.dwVersion = header.dwVersion;
m_Mainheader.nSegmentCountPerMap = header.nSegmentCountPerMap;
m_Mainheader.nMapStartPosX = header.nMapStartPosX;
m_Mainheader.nMapStartPosY = header.nMapStartPosY;
m_Mainheader.nSegmentLeft = header.nSegmentLeft ;
m_Mainheader.nSegmentTop = header.nSegmentTop ;
m_Mainheader.nSegmentRight = header.nSegmentRight ;
m_Mainheader.nSegmentBottom = header.nSegmentBottom;
}
//가장 크게 설정
if( m_Mainheader.nSegmentLeft > header.nSegmentLeft )
m_Mainheader.nSegmentLeft = header.nSegmentLeft;
if( m_Mainheader.nSegmentTop > header.nSegmentTop )
m_Mainheader.nSegmentTop = header.nSegmentTop;
if( m_Mainheader.nSegmentRight < header.nSegmentRight )
m_Mainheader.nSegmentRight = header.nSegmentRight;
if( m_Mainheader.nSegmentBottom < header.nSegmentBottom )
m_Mainheader.nSegmentBottom = header.nSegmentBottom;
for( int i(0); header.nSegmentCount>i; i++ )
{
NFM_PVS_SEGMENT_V1 pvs_segment;
pStream->Read( &pvs_segment, sizeof(pvs_segment) );
std::vector<NFM_SEGMENT_DATA_V1> segment_list;
for( int n(0); pvs_segment.nIncludeSegmentCount>n; n++ )
{
NFM_SEGMENT_DATA_V1 segment_data;
pStream->Read( &segment_data, sizeof(segment_data) );
segment_list.push_back( segment_data );
}
MergeSegment( m_vMergeSegment, &pvs_segment, segment_list );
}
for( int i(0); header.nPropCount>i; i++ )
{
NFM_PVS_PROP_V1 pvs_prop;
pStream->Read( &pvs_prop, sizeof(pvs_prop) );
std::vector<NFM_PROP_DATA_V1> prop_list;
for( int n(0); pvs_prop.nIncludePropCount>n; n++ )
{
NFM_PROP_DATA_V1 prop_data;
pStream->Read( &prop_data, sizeof(prop_data) );
prop_list.push_back( prop_data );
}
MergeProp( m_vMergeProp, &pvs_prop, prop_list );
}
m_Mainheader.nSegmentCount = m_vMergeSegment.size();
m_Mainheader.nPropCount = m_vMergeProp.size();
delete pStream;
}
bool IsExistSegment( std::vector<struct NFM_SEGMENT_DATA_V1*>& seglist, const int& nSegX, const int& nSegY )
{
for( unsigned int i(0); seglist.size()>i; i++ )
{
NFM_SEGMENT_DATA_V1* pData = seglist[i];
if( pData->nSegmentX == nSegX && pData->nSegmentY == nSegY )
return true;
}
return false;
}
bool IsExistProp( std::vector<struct NFM_PROP_DATA_V1*>& proplist, const size_t& nSegmentIdx, const size_t& nPropIdx )
{
for( unsigned int i(0); proplist.size()>i; i++ )
{
NFM_PROP_DATA_V1* pData = proplist[i];
if( pData->nSegmentIdx == nSegmentIdx && pData->nPropIdx == nPropIdx )
return true;
}
return false;
}
void SubTracrtSegment( std::vector<struct NFM_SEGMENT_DATA_V1*>& seglist, const int& nSegX, const int& nSegY )
{
for( unsigned int i(0); seglist.size()>i; i++ )
{
NFM_SEGMENT_DATA_V1* pData = seglist[i];
if( pData->nSegmentX == nSegX && pData->nSegmentY == nSegY )
{
delete pData;
seglist.erase( seglist.begin()+i );
return;
}
}
}
void SubTracrtProp( std::vector<struct NFM_PROP_DATA_V1*>& proplist, const size_t& nSegmentIdx, const size_t& nPropIdx )
{
for( unsigned int i(0); proplist.size()>i; i++ )
{
NFM_PROP_DATA_V1* pData = proplist[i];
if( pData->nSegmentIdx == nSegmentIdx && pData->nPropIdx == nPropIdx )
{
delete pData;
proplist.erase( proplist.begin()+i );
return;
}
}
}
PVSMerge::MERGE_SEGMENT* FindMergeSegment( int nRootX, int nRootY, std::vector< PVSMerge::MERGE_SEGMENT* >& merge_seg_list )
{
for( unsigned int i(0); merge_seg_list.size()>i; i++ )
{
PVSMerge::MERGE_SEGMENT* pMergeSeg = merge_seg_list[i];
if( pMergeSeg->pSegment->nSegmentX == nRootX && pMergeSeg->pSegment->nSegmentY == nRootY )
{
return pMergeSeg;
}
}
return NULL;
}
PVSMerge::MERGE_PROP* FindMergeProp( int nRootX, int nRootY, std::vector< PVSMerge::MERGE_PROP* >& merge_prop_list )
{
for( unsigned int i(0); merge_prop_list.size()>i; i++ )
{
PVSMerge::MERGE_PROP* pMergeProp = merge_prop_list[i];
if( pMergeProp->pProp->nSegmentX == nRootX && pMergeProp->pProp->nSegmentY == nRootY )
{
return pMergeProp;
}
}
return NULL;
}
void _add_segment_pvs( int nRootX, int nRootY, std::vector< PVSMerge::MERGE_SEGMENT* >& merge_seg_list, std::vector< _SEG_DATA_ >& seglist )
{
int nSegX = -1;
int nSegY = -1;
PVSMerge::MERGE_SEGMENT* pMergeSeg = FindMergeSegment( nRootX, nRootY, merge_seg_list );
if( pMergeSeg )
{
for( unsigned int j(0); seglist.size()>j; j++ )
{
nSegX = seglist[j].nSegX;
nSegY = seglist[j].nSegY;
if( !IsExistSegment( pMergeSeg->vSegmentList, nSegX, nSegY ) )
{
//추가
NFM_SEGMENT_DATA_V1* pNewSeg = new NFM_SEGMENT_DATA_V1;
pNewSeg->nSegmentX = nSegX;
pNewSeg->nSegmentY = nSegY;
pMergeSeg->vSegmentList.push_back( pNewSeg );
}
}
//갯수 수정
pMergeSeg->pSegment->nIncludeSegmentCount = pMergeSeg->vSegmentList.size();
}
}
void _add_prop_pvs( int nRootX, int nRootY, std::vector< PVSMerge::MERGE_PROP* >& merge_prop_list, std::vector< _PROP_DATA_ >& proplist )
{
size_t nSegmentIdx;
size_t nPropIdx;
PVSMerge::MERGE_PROP* pMergeProp = FindMergeProp( nRootX, nRootY, merge_prop_list );
if( pMergeProp )
{
for( unsigned int j(0); proplist.size()>j; j++ )
{
nSegmentIdx = proplist[j].nSegmentIdx;
nPropIdx = proplist[j].nPropIdx;
if( !IsExistProp( pMergeProp->vPropList, nSegmentIdx, nPropIdx ) )
{
//추가
NFM_PROP_DATA_V1* pNewProp = new NFM_PROP_DATA_V1;
pNewProp->nSegmentIdx = nSegmentIdx;
pNewProp->nPropIdx = nPropIdx;
pMergeProp->vPropList.push_back( pNewProp );
}
}
//갯수 수정
pMergeProp->pProp->nIncludePropCount = pMergeProp->vPropList.size();
return;
}
}
void _subtract_segment_pvs( int nRootX, int nRootY, std::vector< PVSMerge::MERGE_SEGMENT* >& merge_seg_list, std::vector< _SEG_DATA_ >& seglist )
{
int nSegX = -1;
int nSegY = -1;
PVSMerge::MERGE_SEGMENT* pMergeSeg = FindMergeSegment( nRootX, nRootY, merge_seg_list );
if( pMergeSeg )
{
for( unsigned int j(0); seglist.size()>j; j++ )
{
nSegX = seglist[j].nSegX;
nSegY = seglist[j].nSegY;
SubTracrtSegment( pMergeSeg->vSegmentList, nSegX, nSegY );
}
//갯수 수정
pMergeSeg->pSegment->nIncludeSegmentCount = pMergeSeg->vSegmentList.size();
}
}
void _subtract_prop_pvs( int nRootX, int nRootY, std::vector< PVSMerge::MERGE_PROP* >& merge_prop_list, std::vector< _PROP_DATA_ >& proplist )
{
size_t nSegmentIdx;
size_t nPropIdx;
PVSMerge::MERGE_PROP* pMergeProp = FindMergeProp( nRootX, nRootY, merge_prop_list );
if( pMergeProp )
{
for( unsigned int j(0); proplist.size()>j; j++ )
{
nSegmentIdx = proplist[j].nSegmentIdx;
nPropIdx = proplist[j].nPropIdx;
SubTracrtProp( pMergeProp->vPropList, nSegmentIdx, nPropIdx );
}
//갯수 수정
pMergeProp->pProp->nIncludePropCount = pMergeProp->vPropList.size();
}
}
void _exchange_segment_pvs( int nRootX, int nRootY, std::vector< PVSMerge::MERGE_SEGMENT* >& merge_seg_list, std::vector< _SEG_DATA_ >& seglist )
{
PVSMerge::MERGE_SEGMENT* pMergeSeg = FindMergeSegment( nRootX, nRootY, merge_seg_list );
if( pMergeSeg )
{
SAFE_DELETE_VECTOR( pMergeSeg->vSegmentList );
for( unsigned int j(0); seglist.size()>j; j++ )
{
//추가
NFM_SEGMENT_DATA_V1* pNewSeg = new NFM_SEGMENT_DATA_V1;
pNewSeg->nSegmentX = seglist[j].nSegX;
pNewSeg->nSegmentY = seglist[j].nSegY;
pMergeSeg->vSegmentList.push_back( pNewSeg );
}
pMergeSeg->pSegment->nIncludeSegmentCount = pMergeSeg->vSegmentList.size();
}
}
void _exchange_prop_pvs( int nRootX, int nRootY, std::vector< PVSMerge::MERGE_PROP* >& merge_prop_list, std::vector< _PROP_DATA_ >& proplist )
{
PVSMerge::MERGE_PROP* pMergeProp = FindMergeProp( nRootX, nRootY, merge_prop_list );
if( pMergeProp )
{
SAFE_DELETE_VECTOR( pMergeProp->vPropList );
for( unsigned int j(0); proplist.size()>j; j++ )
{
//추가
NFM_PROP_DATA_V1* pNewProp = new NFM_PROP_DATA_V1;
pNewProp->nSegmentIdx = proplist[j].nSegmentIdx;
pNewProp->nPropIdx = proplist[j].nPropIdx;
pMergeProp->vPropList.push_back( pNewProp );
}
pMergeProp->pProp->nIncludePropCount = pMergeProp->vPropList.size();
}
}
//Modify
void PVSMerge::Modify( const char * pFileName )
{
KStream* pStream = new KFileStream( pFileName );
if( NULL == pStream )
{
return;
}
size_t nLen = pStream->GetLength();
char * pstrTemp = new char[nLen+1];
pstrTemp[nLen] = '\0';
for( size_t i(0); nLen>i; i++ )
{
pStream->Read( &pstrTemp[i], 1 );
}
std::vector< std::string > vString;
XStringUtil::Split( pstrTemp, vString, "|\r\n" );
int nLoop = (int)vString.size()/3;
int n=0;
std::string strCommand;
int nRootX, nRootY;
std::vector< _SEG_DATA_ > seglist;
std::vector< _PROP_DATA_ > proplist;
for( int i(0); nLoop>i; i++ )
{
std::string strData = vString[n++].c_str();
int nX = atoi( vString[n++].c_str() );
int nY = atoi( vString[n++].c_str() );
if( i==0 )
{
strCommand = strData;
nRootX = nX;
nRootY = nY;
}
else
{
if( !stricmp( strData.c_str(), "SEG" ) )
{
_SEG_DATA_ data;
data.nSegX = nX;
data.nSegY = nY;
seglist.push_back( data );
}
else if( !stricmp( strData.c_str(), "PROP" ) )
{
_PROP_DATA_ data;
data.nSegmentIdx = nX;
data.nPropIdx = nY;
proplist.push_back( data );
}
}
}
if( !stricmp( strCommand.c_str(), "ADD") )
{
_add_segment_pvs( nRootX, nRootY, m_vMergeSegment, seglist );
_add_prop_pvs( nRootX, nRootY, m_vMergeProp, proplist );
}
else if( !stricmp( strCommand.c_str(), "SUBTRACT") )
{
_subtract_segment_pvs( nRootX, nRootY, m_vMergeSegment, seglist );
_subtract_prop_pvs( nRootX, nRootY, m_vMergeProp, proplist );
}
else if( !stricmp( strCommand.c_str(), "EXCHANGE") )
{
_exchange_segment_pvs( nRootX, nRootY, m_vMergeSegment, seglist );
_exchange_prop_pvs( nRootX, nRootY, m_vMergeProp, proplist );
}
delete [] pstrTemp;
delete pStream;
}
void PVSMerge::SaveMerge( const char * pFileName )
{
FILE* pF = fopen( pFileName, "wb" );
if( pF == NULL ) return;
NFM_PVS_HEADER_V1 header;
memcpy( &header, &m_Mainheader, sizeof(header) );
fwrite( &header, sizeof(header), 1, pF );
for( unsigned int i(0); m_vMergeSegment.size()>i; i++ )
{
NFM_PVS_SEGMENT_V1 pvs_segment;
pvs_segment.nSegmentX = m_vMergeSegment[i]->pSegment->nSegmentX;
pvs_segment.nSegmentY = m_vMergeSegment[i]->pSegment->nSegmentY;
pvs_segment.nIncludeSegmentCount = m_vMergeSegment[i]->vSegmentList.size();
int nWorldSegmentX = (header.nMapStartPosX*header.nSegmentCountPerMap)+pvs_segment.nSegmentX;
int nWorldSegmentY = (header.nMapStartPosY*header.nSegmentCountPerMap)+pvs_segment.nSegmentY;
// _oprint( "Segment Index : W[%d %d] - L[%d %d]\n", nWorldSegmentX, nWorldSegmentY, pvs_segment.nSegmentX, pvs_segment.nSegmentY );
fwrite( &pvs_segment, sizeof(pvs_segment), 1, pF );
for( int n(0); pvs_segment.nIncludeSegmentCount>n; n++ )
{
NFM_SEGMENT_DATA_V1 segment_data;
segment_data.nSegmentX = m_vMergeSegment[i]->vSegmentList[n]->nSegmentX;
segment_data.nSegmentY = m_vMergeSegment[i]->vSegmentList[n]->nSegmentY;
// _oprint( "Segment Index : %d %d\n", segment_data.nSegmentX, segment_data.nSegmentY );
fwrite( &segment_data, sizeof(segment_data), 1, pF );
}
}
for( unsigned int i(0); m_vMergeProp.size()>i; i++ )
{
NFM_PVS_PROP_V1 pvs_prop;
pvs_prop.nSegmentX = m_vMergeProp[i]->pProp->nSegmentX;
pvs_prop.nSegmentY = m_vMergeProp[i]->pProp->nSegmentY;
pvs_prop.nIncludePropCount = m_vMergeProp[i]->vPropList.size();
// _oprint( "Segment Index : %d %d\n", pvs_prop.nSegmentX, pvs_prop.nSegmentY );
fwrite( &pvs_prop, sizeof(pvs_prop), 1, pF );
for( int n(0); pvs_prop.nIncludePropCount>n; n++ )
{
NFM_PROP_DATA_V1 prop_data;
prop_data.nSegmentIdx = m_vMergeProp[i]->vPropList[n]->nSegmentIdx;
prop_data.nPropIdx = m_vMergeProp[i]->vPropList[n]->nPropIdx;
fwrite( &prop_data, sizeof(prop_data), 1, pF );
}
}
fclose( pF );
}