Files
2022-10-26 12:25:11 +08:00

630 lines
23 KiB
C++

#include "stdafx.h"
#include <PacketControl/WarMessages_Sync.h>
#include "SectorGrid.h"
#include "Sector.h"
#include "GameZone.h"
#include "GameField.h"
namespace nsGrid {
;
//==================================================================================================
// <SectorGridShared>
//
bool
SectorGridShared::GetAroundSectors(const SECTOR_IDX coordinates,
SectorGrid3x3* const OUT pOutGrid) const
{
memset(pOutGrid->Grid, INVALID_SECTOR_INDEX, sizeof(pOutGrid->Grid));
if ((coordinates == INVALID_SECTOR_INDEX) || !(coordinates < m_SectorCount)) {
return false;
};
const DWORD length_x = m_Length[LEN_X]; // for load to GPR
const DWORD indexX__ = coordinates % length_x;
const DWORD __indexY = coordinates / length_x;
const bool lowerboundX = !indexX__;
const bool lowerboundY = !__indexY;
const bool upperboundX = (indexX__ + 1) == m_Length[LEN_X];
const bool upperboundY = (__indexY + 1) == m_Length[LEN_Y];
//const DWORD indexX__
const DWORD indexXm1 = indexX__ - 1;
const DWORD indexXp1 = indexX__ + 1;
const DWORD indexY__ = __indexY * length_x;
const DWORD indexYm1 = indexY__ - length_x;
const DWORD indexYp1 = indexY__ + length_x;
SECTOR_IDX* pOffset = (pOutGrid->Grid);
#define GRID_ARRAY_CODE(index, cond, x, y) \
if (!(cond)) { *pOffset = (x) + (y); }; \
++pOffset
GRID_ARRAY_CODE(0+0, (lowerboundX || lowerboundY), indexXm1, indexYm1);
GRID_ARRAY_CODE(0+1, ( lowerboundY), indexX__, indexYm1);
GRID_ARRAY_CODE(0+2, (upperboundX || lowerboundY), indexXp1, indexYm1);
GRID_ARRAY_CODE(3+0, (lowerboundX ), indexXm1, indexY__);
GRID_ARRAY_CODE(3+1, (0 ), indexX__, indexY__);
GRID_ARRAY_CODE(3+2, (upperboundX ), indexXp1, indexY__);
GRID_ARRAY_CODE(6+0, (lowerboundX || upperboundY), indexXm1, indexYp1);
GRID_ARRAY_CODE(6+1, ( upperboundY), indexX__, indexYp1);
GRID_ARRAY_CODE(6+2, (upperboundX || upperboundY), indexXp1, indexYp1);
#undef GRID_ARRAY_CODE
return true;
};
bool
SectorGridShared::ChangeSector(const SECTOR_IDX prevSectorXY, const SECTOR_IDX newSectorXY,
SectorGrid3x3_ChangeSector& OUT info) const
{
memset(&info, INVALID_SECTOR_INDEX, sizeof(info));
const bool bNoChange = prevSectorXY == newSectorXY;
if (bNoChange) {
return false;
}
const bool bValidPrevS = (prevSectorXY < m_SectorCount);
const bool bValidNewS = (newSectorXY < m_SectorCount);
// Prev | New Leave | Curr | Enter
// X X -> X X X
// X O -> X O O (C==E)
// O X -> O X X (Leave에서 해당 정보 참조 정보 모두 제거)
// O O -> O O O (C=N, E=N-P, L=P-N)
// (C = N, E = N - P, L = P - N)
// E = N - (P∩N), L = P - (P∩N)
if (bValidPrevS == false && bValidNewS == false) {
return false;
}
if (bValidPrevS == false && bValidNewS == true)
{
GetAroundSectors(newSectorXY, &info.CurrentSectors);
info.EnterSectors = info.CurrentSectors;
return true;
}
if (bValidPrevS == true && bValidNewS == false)
{
GetAroundSectors(prevSectorXY, &info.LeaveSectors);
return true;
}
//
//if ((bValidPrevS==true) && (bValidNewS==true))
{
SectorGrid3x3& currentSectors = info.CurrentSectors;
SectorGrid3x3& leaveSectors = info.LeaveSectors;
SectorGrid3x3& enterSectors = info.EnterSectors;
GetAroundSectors(prevSectorXY, &leaveSectors);
GetAroundSectors(newSectorXY, &currentSectors);
enterSectors = currentSectors;
SectorGrid3x3 tmpSectors = leaveSectors;
typedef SectorGrid3x3::GridArray GA;
// calculation set_difference L = P-N
FOREACH_ARRAY(SECTOR_IDX& rPrev, leaveSectors.Grid, GA)
{
if (INVALID_SECTOR_INDEX == rPrev) {
continue;
}
FOREACH_ARRAY(SECTOR_IDX& rNew, currentSectors.Grid, GA)
{
if (INVALID_SECTOR_INDEX == rNew) {
continue;
}
if (rPrev == rNew)
{
rPrev = INVALID_SECTOR_INDEX;
break;
}
}
}
// calculation set_difference E = N-P
FOREACH_ARRAY(SECTOR_IDX& rNew, enterSectors.Grid, GA)
{
if (INVALID_SECTOR_INDEX == rNew) {
continue;
}
FOREACH_ARRAY(SECTOR_IDX& rPrev, tmpSectors.Grid, GA)
{
if (INVALID_SECTOR_INDEX == rPrev) {
continue;
}
if (rNew == rPrev)
{
rNew = INVALID_SECTOR_INDEX;
break;
}
}
}
}
return true;
}
void
SectorGridShared::Build(const SectorGridShared& rSrc)
{ // 이것은 FieldInfo가 가지는 기본 섹터 정보를 복사하기 위함...
// SectorGridInfo를 복사한다고 생각하자. 이것은 실행 중에 동작하는 함수다.
m_SectorXYdist = rSrc.m_SectorXYdist; //.GetSectorXYDistance();
m_SectorCount = rSrc.SectorCount;
CopyMemory(m_Boundaries, rSrc.m_Boundaries, sizeof(m_Boundaries));
CopyMemory(m_Length, rSrc.m_Length, sizeof(m_Length));
}
void
SectorGridShared::Build(const BvAABB& rSrc, const DWORD sectorDist /*meter*/)
{
m_SectorXYdist = sectorDist;
// input X - boundary
{
m_Boundaries[SG_X_MIN] = (DWORD)min(rSrc.m_wvMin.x, rSrc.m_wvMax.x);
m_Boundaries[SG_Y_MIN] = (DWORD)min(rSrc.m_wvMin.y, rSrc.m_wvMax.y);
m_Boundaries[SG_Z_MIN] = (DWORD)min(rSrc.m_wvMin.z, rSrc.m_wvMax.z);
};
DWORD& rLenX = m_Length[LEN_X];
DWORD& rLenY = m_Length[LEN_Y];
DWORD& rLenZ = m_Length[LEN_Z];
{
rLenX = (DWORD)abs(rSrc.m_wvMax.x - rSrc.m_wvMin.x);
rLenY = (DWORD)abs(rSrc.m_wvMax.y - rSrc.m_wvMin.y);
rLenZ = (DWORD)abs(rSrc.m_wvMax.z - rSrc.m_wvMin.z);
};
{
m_Boundaries[SG_X_MAX] = (DWORD)rLenX;
m_Boundaries[SG_Y_MAX] = (DWORD)rLenY;
m_Boundaries[SG_Z_MAX] = (DWORD)rLenZ;
};
{
rLenX = (DWORD)(rLenX / m_SectorXYdist) + !!(rLenX % m_SectorXYdist);
rLenY = (DWORD)(rLenY / m_SectorXYdist) + !!(rLenY % m_SectorXYdist);
rLenZ = (DWORD)(rLenZ / m_SectorXYdist) + !!(rLenZ % m_SectorXYdist);
};
{
m_SectorCount = rLenX * rLenY;
};
}
//==================================================================================================
// SYNC_MSG_LINKEDLIST
// NOTE: f110112.5L, fix to byte alignment to enhance system architecture address calculator.
#pragma warning(push, 4)
inline SYNC_MSG_LINKEDLIST*
SYNC_MSG_LINKEDLIST::SerializeTo(WAR_MSG_HDR* const IN header,
const WAR_TAG_V* war_msg_in_buffer, uint16_t war_msg_in_buffer_size) const
{
#ifdef BUF_ALIGN_PTR
#error "this macro should be used as local declaration only"
#endif
#define BUF_ALIGN_PTR(__size) (((__size) + ((sizeof(void*)) - 1)) & (~((sizeof(void*)) - 1)))
WAR_MSG_HDR::MSG_SIZE_T header_offset = header->size;
; header_offset = BUF_ALIGN_PTR(header_offset);
//const uint16_t size = GetSize();
WAR_MSG_HDR::MSG_SIZE_T offset = sizeof(*this) + header_offset;
this_type* const dest = reinterpret_cast<this_type*>(
reinterpret_cast<uint8_t*>(header + 1) + header_offset);
;{
util::LList::Init(dest);
dest->war_msg = war_msg_in_buffer;
dest->war_msg_size = war_msg_in_buffer_size;
#ifdef _WIN64
BOOST_STATIC_ASSERT(sizeof(SYNC_MSG_LINKEDLIST) == 32);
#else
BOOST_STATIC_ASSERT(sizeof(SYNC_MSG_LINKEDLIST) == 16);
#endif
};
header->size = offset;
return dest;
#undef BUF_ALIGN_PTR
};
//==================================================================================================
// <SectorGrid>
//
void
SectorGrid::Init()
{
// 너무 큰 맵을 경계한다.
if (!FlowControl::FCAssert(!m_pSectorNodes && m_SectorCount && (m_SectorCount<60000))) {
return;
}
const SIZE_T alloc_size_array = (m_SectorCount+1) * sizeof(Node);
m_pSectorNodes = (Node*)TAllocMalloc(alloc_size_array);
ZeroMemory(m_pSectorNodes, alloc_size_array);
Node* pIt = &m_pSectorNodes[0];
//Node** pItEnd = &m_pSectors[m_SectorCount];
for (DWORD sector_index = 0; sector_index != m_SectorCount; ++sector_index, ++pIt)
{
Sector* const pSector = TAllocNew(Sector);
pSector->Init(sector_index);
Node& rNode = *pIt;
rNode.pSector = pSector;
util::LList::Init(&rNode.m_SectorRoot);
}
//LList::Init(&m_FieldRoot);
//m_Sectors.reserve(m_SectorCount);
//for (DWORD sector_index=0 ; sector_index!=m_SectorCount ; ++sector_index)
//{
// Sector* const pSector = TAllocNew(Sector);
// pSector->Init(sector_index);
// m_Sectors.push_back(pSector);
//}
}
void
SectorGrid::Release()
{
if (!m_pSectorNodes) {
return;
}
Node* pIt = &m_pSectorNodes[0];
Node* pItEnd = &m_pSectorNodes[m_SectorCount];
for (; pIt != pItEnd; ++pIt)
{
Node& rNode = *pIt;
Sector* const pSector = rNode.pSector;
pSector->Release();
TAllocDelete(Sector, pSector);
// pNode->m_Root <- 이것은 초기화 하지 않는다. 필드에 걸린 로드밸런스를 위한 메시지스트림 버퍼는 알아서 초기화 될 것이다.
}
TAllocFree(m_pSectorNodes);
m_pSectorNodes = NULL;
//LList::Init(&m_FieldRoot);
//if (m_Sectors.empty())
// return;
//FOREACH_CONTAINER(SECTORS::value_type& rNode, m_Sectors, SECTORS)
//{
// Sector* const pSector = rNode;
// pSector->Release();
// TAllocDelete(Sector, pSector);
//}
//m_Sectors.clear();
}
// enhanced changed by _NA001605_EP2_CHANGE_SKILL_BROADCASTER_
Sector* SectorGrid::AddSectorMsgNode(WAR_MSG_HDR* const header, const SECTOR_IDX coordinates,
const WAR_TAG_V* war_msg_in_buffer, uint16_t war_msg_size) const
{
// NOTE: f110112.5L, fix to byte alignment to enhance system architecture address calculator.
if ((m_pSectorNodes && coordinates < m_SectorCount) == false) {
return NULL;
}
Node& node = m_pSectorNodes[coordinates];
Sector* const sector = node.pSector;
if (sector == NULL) {
return NULL;
};
;{
// add message to linked list of a sector
SYNC_MSG_LINKEDLIST* linked_list = NULL;
// it is safe to call this null object.
linked_list = linked_list->SerializeTo(header, war_msg_in_buffer, war_msg_size);
util::LList::AddPrev(linked_list, &node.m_SectorRoot);
};
return sector;
}
static void
HighLoadBalanceAppendMsg(MSG_AG_CONNECTION_PACKET_BROADCASTER_ONEtoN_SYN& rMsgBRD,
SYNC_MSG_LINKEDLIST& rLList, WAR_MSG_HDR* const pHeader)
{
using namespace nsSync;
const DWORD FLAG_SINGLE_MSG_SIZE = 8000;
const WORD INVALID_MSG_SIZE = 65000;
DWORD total_sum = 0;
SYNC_MSG_LINKEDLIST* pLIt = rLList.next;
SYNC_MSG_LINKEDLIST* pLItEnd = &rLList;
//for (; pLIt!=pLItEnd ; pLIt=static_cast<SYNC_MSG_LINKEDLIST*>(pLIt->next))
// (080904) (REMOVED) - for Packet Size Control
while (pLIt != pLItEnd)
{
WAR_TAG_V* const pSubMsg = const_cast<WAR_TAG_V*>(pLIt->war_msg);
uint16_t msg_size = pLIt->war_msg_size;
//--------------------------------------------------------------------------------------------------
// Debugging facility
#define WAR_MESSAGE_TOKEN_DEBUGGING (0)
//--------------------------------------------------------------------------------------------------
#if WAR_MESSAGE_TOKEN_DEBUGGING == 0
pHeader->size += msg_size;
rMsgBRD.AppendMsg(reinterpret_cast<BYTE*>(pSubMsg), msg_size);
#endif
//--------------------------------------------------------------------------------------------------
#if WAR_MESSAGE_TOKEN_DEBUGGING
//////////////////////////////////////////////////////////////////////////
#define WAR_MSG_SYNC_CASE_CODE(_subprotocol) \
case _subprotocol: { \
MSGSUB_##_subprotocol& rMsg = static_cast<MSGSUB_##_subprotocol&>(*pSubMsg); \
msg_size = rMsg.GetSize(); \
pHeader->size += msg_size; \
rMsgBRD.AppendMsg(reinterpret_cast<BYTE*>(pSubMsg), msg_size); \
} break
//////////////////////////////////////////////////////////////////////////
switch(pSubMsg->_TAG)
{
//case SYNC_MONSTER_ENTER_BRD :
// {
// MSGSUB_SYNC_MONSTER_ENTER_BRD& rMsg = static_cast<MSGSUB_SYNC_MONSTER_ENTER_BRD&>(*pSubMsg);
// const WORD msg_size = rMsg.GetSize();
// rMsgBRD.AppendMsg(reinterpret_cast<BYTE*>(pSubMsg), msg_size);
// pHeader->size += msg_size;
// }
// break;
////WAR_MSG_SYNC_CASE_CODE( SYNC_MONSTER_ENTER_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_MONSTER_DIR_ENTER_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_MONSTER_LEAVE_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_SUMMONED_ENTER_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_MAPNPC_ENTER_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_FIELDITEM_ENTER_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_FIELDITEM_LEAVE_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_BOSS_MONSTER_ENTER_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_NPC_JUMPRESULT_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_LUCKY_MONSTER_RUNAWY_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_TOTEMNPC_ENTER_BRD );
//////////////////////////////////////////////////////////////////////////
// eSYNC_POS
//WAR_MSG_SYNC_CASE_CODE( SYNC_MOVE_NAK );
WAR_MSG_SYNC_CASE_CODE( SYNC_MOVE_BRD );
WAR_MSG_SYNC_CASE_CODE( SYNC_MOVE_THRUST_BRD );
WAR_MSG_SYNC_CASE_CODE( SYNC_TARGET_MOVE_BRD );
WAR_MSG_SYNC_CASE_CODE( SYNC_KBMOVE_BRD );
WAR_MSG_SYNC_CASE_CODE( SYNC_NPC_JUMP_BRD );
WAR_MSG_SYNC_CASE_CODE( SYNC_STOP_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_NPC_STOP_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_FORCED_WARP_BRD );
WAR_MSG_SYNC_CASE_CODE( SYNC_FAST_KBMOVE_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_JUMP_ACK );
//WAR_MSG_SYNC_CASE_CODE( SYNC_JUMP_NAK );
WAR_MSG_SYNC_CASE_CODE( SYNC_JUMP_BRD );
//WAR_MSG_SYNC_CASE_CODE( SYNC_JUMP_STOP_NAK );
WAR_MSG_SYNC_CASE_CODE( SYNC_CHARACTER_DEAD_BRD);
WAR_MSG_SYNC_CASE_CODE( SYNC_CHARACTER_RESURRECTION_BRD);
//__NA_001290_20090525_SHIELD_SYSTEM
WAR_MSG_SYNC_CASE_CODE( SYNC_STATUS_ADD_BRD);
WAR_MSG_SYNC_CASE_CODE( SYNC_STATUS_REMOVE_BRD);
WAR_MSG_SYNC_CASE_CODE( SYNC_REGENID_BRD); // _NA_0_20100817_HELLON_LAST_TRIGGER
//_NA000000_SPEED_HACK_PREVENTION_SUPPORT
WAR_MSG_SYNC_CASE_CODE(SYNC_SERVER_TIMER_SYNCHRONIZE_BRD);
//------------------------------------------------------------------------------------------
// The Episode II
WAR_MSG_SYNC_CASE_CODE(BATTLE_MONSTER_ATTACK_BRD);
WAR_MSG_SYNC_CASE_CODE(BATTLE_MONSTER_JUMP_ATTACK_BRD);
//
WAR_MSG_SYNC_CASE_CODE(BATTLE_PLAYER_ATTACK_BRD);
WAR_MSG_SYNC_CASE_CODE(BATTLE_PLAYER_AREA_ATTACK_BRD);
//
WAR_MSG_SYNC_CASE_CODE(STYLE_PLAYER_ATTACK_BRD);
WAR_MSG_SYNC_CASE_CODE(STYLE_PLAYER_ATTACK_RESULT_BRD);
//
WAR_MSG_SYNC_CASE_CODE(SKILL_ACTION_INSTANT_RESULT_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_ACTION_DELAY_START_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_ACTION_DELAY_RESULT_BRD);
//
WAR_MSG_SYNC_CASE_CODE(SKILL_CASTING_CANCEL_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_PERIODIC_DAMAGE_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_REFLECT_DAMAGE_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_EFFECT_BOMB_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_SELF_DESTRUCTION_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_TRANSPARENT_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_SUCTION_BRD);
WAR_MSG_SYNC_CASE_CODE(SKILL_VITAL_SUCTION_BRD);
//
//------------------------------------------------------------------------------------------
//
default:
SUNLOG(eCRITICAL_LOG, "Unreadable sync sub-protocol %u", pSubMsg->_TAG);
break;
};
#endif //
{ // Linked List Control - (080904)(REVISION) - for Packet Size Control
pLIt = util::LList::Delete(pLIt);
if (INVALID_MSG_SIZE == msg_size) {
return;
}
total_sum += msg_size;
if (FLAG_SINGLE_MSG_SIZE < total_sum) {
return;
}
};
}
}
void SectorGrid::Update(GameField* const game_field) const
{
if (m_pSectorNodes == NULL) {
return;
};
GameZone* const game_zone = game_field->GetGameZone();
// NOTE: f110531.4L, set to default 'ENABLE_FIELD_HIGH_LOAD_BALANCING'
// CHANGES: f110531.4L, remove the broadcast upper boundary limitation using 1toN broadcaster
// for region events SYNC messages
MSG_AG_CONNECTION_PACKET_BROADCASTER_ONEtoN_SYN& msg_brd =
MSG_ONEtoN_BROADCASTER::InstanceOfBase();
MSG_CG_SYNC_COMPOSED_STREAM_CMD dummy_war_header;
Node* node_it = &m_pSectorNodes[0];
const Node* const node_end = &m_pSectorNodes[m_SectorCount];
for (; node_it != node_end; ++node_it)
{
Node& sector_node = *node_it;
SYNC_MSG_LINKEDLIST& llist_root = sector_node.m_SectorRoot;
if (util::LList::IsEmpty(&llist_root)) {
continue;
}
Sector* const sector = sector_node.pSector;
if (sector->GetPlayerNum() == 0) // list초기화 필요하다.
{
util::LList::Init(&llist_root);
continue;
}
//------------------------------------------------------------------------------------------
do
{ // DONE: 이 부분에 대한 루핑처리가 가능하도록 변경하면 더 큰 버퍼 할당이 가능해진다.
// recycling msg_brd
dummy_war_header.m_Header->size = 0;
msg_brd.Init(&dummy_war_header, sizeof(dummy_war_header));
MSG_CG_SYNC_COMPOSED_STREAM_CMD* war_header =
static_cast<MSG_CG_SYNC_COMPOSED_STREAM_CMD*>(msg_brd.GetBrdPacketPtr());
HighLoadBalanceAppendMsg(msg_brd, llist_root, war_header->m_Header);
//LList::Init(&llist_root); (080904)(REMOVED) - for Packet Size Control
uint16_t* const user_it = msg_brd.GetUsersStartPtr();
ns_object::SearchNodeConstIterator it = sector->GetPlayerRoot();
const ns_object::SearchNodeConstIterator end = sector->GetPlayerEnd();
while (const ns_object::SearchNode::LinkNode* link_node = it.ClimbToNext(end))
{
Player* player = link_node->select.player_node.player;
if (obj_util::IsValid(player) == false)
{
continue;
}
const DWORD object_key = player->GetObjectKey();
DWORD bound_check = msg_brd.AddUser(user_it, object_key);
if (bound_check == msg_brd.MAX_USER_COUNT) {
break;
}
}
//if (msg_brd.m_byUserCount) <- user는 반드시 존재한다.
g_pGameServer->SendToServer(AGENT_SERVER, &msg_brd, msg_brd.GetSendingSize());
} while (util::LList::IsEmpty(&llist_root) == false);
};//end 'foreach sector in sectors'
}
//==================================================================================================
// <SectorGridVR>
//
inline bool
SectorGridVR::CheckAllowMinMaxBoundary(const SECTOR_IDX coordinates, const SectorGridShared& rSrc,
const Boundaries* const IN pB) const
{
const DWORD dist = rSrc.m_SectorXYdist;
const DWORD indexX_len = (coordinates % rSrc.m_Length[LEN_X]) * dist;
const DWORD indexY_len = (coordinates / rSrc.m_Length[LEN_X]) * dist;
Boundaries b;
b.minX = indexX_len ;
b.maxX = indexX_len + (dist);
b.minY = indexY_len ;
b.maxY = indexY_len + (dist);
if ((b.maxX < pB->minX || pB->maxX < b.minX) ||
(b.maxY < pB->minY || pB->maxY < b.minY))
{
return false;
}
return true;
}
inline void
SectorGridVR::Get3x3MinMaxBoundary(const SECTOR_IDX coordinates, const SectorGridVR& rSrc,
Boundaries* const OUT pOut) const
{
const DWORD dist = rSrc.m_SectorXYdist;
const DWORD indexX_len = (coordinates % rSrc.m_Length[LEN_X]) * dist;
const DWORD indexY_len = (coordinates / rSrc.m_Length[LEN_X]) * dist;
pOut->minX = indexX_len - (dist);
pOut->maxX = indexX_len + (dist << 1);
pOut->minY = indexY_len - (dist);
pOut->maxY = indexY_len + (dist << 1);
}
bool
SectorGridVR::GetAroundSectors(const WzVector* IN pPos, SectorGrid3x3* const OUT pOutGrid,
ViewBoxCubic* const OUT pOutBoundary) const
{
// no check ASSERT(m_pProjectionGrid); //로직단에서 제어하기로 한다.
const SECTOR_IDX sector_index = m_pProjectionGrid->GetSectorIndex(pPos);
if (!m_pProjectionGrid->GetAroundSectors(sector_index, pOutGrid)) {
return false;
}
const SECTOR_VRIDX sector_index_VR = GetSectorIndex(pPos);
Boundaries boundary;
Get3x3MinMaxBoundary(sector_index_VR, (const SectorGridVR&)*this, &boundary);
// 해상도가 같으면 더 볼 필요 없다.
if (m_SectorXYdist != m_pProjectionGrid->m_SectorXYdist)
{
typedef SectorGrid3x3::GridArray GA;
SectorGrid3x3& rGrid = *pOutGrid;
FOREACH_ARRAY(SECTOR_IDX& rNode, rGrid.Grid, GA)
{
if (INVALID_SECTOR_INDEX == rNode) {
continue;
}
if (!CheckAllowMinMaxBoundary(rNode, *m_pProjectionGrid, &boundary)) {
rNode = INVALID_SECTOR_INDEX;
}
}
}
if (pOutBoundary)
{
BvAABB& aabb = pOutBoundary->Cubic;
aabb.m_wvMin.x = (float)(int)(boundary.minX + m_Boundaries[SG_X_MIN]);
aabb.m_wvMin.y = (float)(int)(boundary.minY + m_Boundaries[SG_Y_MIN]);
aabb.m_wvMin.z = -5.f;
aabb.m_wvMax.x = (float)(int)(boundary.maxX + m_Boundaries[SG_X_MIN]);
aabb.m_wvMax.y = (float)(int)(boundary.maxY + m_Boundaries[SG_Y_MIN]);
aabb.m_wvMax.z = 5.f;
}
return true;
}
}; // end namespace nsGrid
//==================================================================================================