#include "stdafx.h" #include #include "MapDefine.h" #include #include #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& vSegXList, std::vector& vSegYList, std::vector& vPropIdxList, std::vector& 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& 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& 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 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 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& 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& 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& 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& 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 ); }