#pragma once #ifndef GAMESERVER_SECTOR_GRID_H #define GAMESERVER_SECTOR_GRID_H #include #include <3DEngine/Common/BoundingVolume.h> #include class Sector; class GameField; //================================================================================================== // namespace namespace nsGrid { ; typedef DWORD SECTOR_IDX; typedef SECTOR_IDX SECTOR_VRIDX; // SectorGridVR¿¡¼­ »ç¿ëÇÏ´Â À妽º #define INVALID_SECTOR_INDEX static_cast(ULONG_MAX) //================================================================================================== // struct SectorGrid3x3 { enum ePOS { LEFT_UP = 0, UP , RIGHT_UP , LEFT , CENTER , RIGHT , LEFT_DOWN , DOWN , RIGHT_DOWN , MAX_SIZE , }; typedef util::ARRAY_TYPEINFO GridArray; // SectorGridVR¿¡¼­´Â SECTOR_IDX¸¦ SECTOR_VRIDX·Î ó¸®ÇÑ´Ù. GridArray::array_type Grid; }; //================================================================================================== // struct SectorGrid3x3_ChangeSector { SectorGrid3x3 OUT CurrentSectors; SectorGrid3x3 OUT EnterSectors; SectorGrid3x3 OUT LeaveSectors; }; //================================================================================================== // // - Bounding Volume for Variable Broadcast struct ViewBoxCubic { BvAABB Cubic; void SetInit2D(const WzVector* const center_pos, const WzVector* const radius_2d); void SetInit3D(const WzVector* const center_pos, const WzVector* const radius_3d); void SetInit3D_UpsideZ(const WzVector* const center_pos, const WzVector* const radius_3d); void SetInit3D_DownsideZ(const WzVector* const center_pos, const WzVector* const radius_3d); void SetInit3D_Radian(const WzVector* const center_pos, const WzVector* const radius_3d, const WzVector* const direction_and_weight); void SetInit3D_Radian_UpsideZ(const WzVector* const center_pos, const WzVector* const radius_3d, const WzVector* const direction_and_weight); bool IsValidCoordinateXY(const WzVector* const point) const; #ifdef _NA_004830_20120511_1202_SSQ_CLOSESPACE_DAMAGE_RANGE bool IsValidCoordinateXY(const WzVector* const point, const WzVector* const center_point) const; #endif // _NA_004830_20120511_1202_SSQ_CLOSESPACE_DAMAGE_RANGE bool IsValidCoordinateXYZ(const WzVector* const point) const; }; //================================================================================================== // class SectorGridInfo; class SectorGrid; class SectorGridVR; //================================================================================================== // // class SectorGridShared { public: enum eCoord { SG_X_MIN, SG_X_MAX, SG_Y_MIN, SG_Y_MAX, SG_Z_MIN, SG_Z_MAX, SG_XYZ_MAX }; enum eXYZ_LEN { LEN_X, LEN_Y, LEN_Z, LEN_XYZ_MAX }; // SectorGridShared(); const DWORD* GetBoundaries() const { return m_Boundaries; } const DWORD* GetLengths() const { return m_Length; } void Build(const SectorGridShared& rSrc); void Build(const BvAABB& rSrc, const DWORD sectorDist /*meter*/); bool IsValidSector(const SECTOR_IDX coordinates) const; bool IsValidCoordinate(const WzVector* IN point) const; // SECTOR_IDX GetSectorIndex(const WzVector* IN point) const; bool GetCenterPosInSector(const SECTOR_IDX coordinates, WzVector& OUT result_center) const; bool GetAroundSectors(const SECTOR_IDX coordinates, SectorGrid3x3* const OUT result_grid) const; bool ChangeSector(const SECTOR_IDX prevSectorXY, const SECTOR_IDX newSectorXY, SectorGrid3x3_ChangeSector& OUT info) const; protected: bool _IsValidCoordinate(const DWORD x, const DWORD y, const DWORD z) const; // fields public: const DWORD& SectorCount; const DWORD& SectorXYDistance; protected: DWORD m_SectorXYdist; // (x==y), °¢ º¯ ±æÀÌ (1.0f == 1meter == 1) DWORD m_SectorCount; DWORD m_Boundaries[SG_XYZ_MAX]; DWORD m_Length[LEN_XYZ_MAX]; // friend class SectorGridInfo; friend class SectorGrid; friend class SectorGridVR; __DISABLE_COPY(SectorGridShared); }; // end SectorGridShared //================================================================================================== // // template class SectorGridBase : public SectorGridShared { public: ~SectorGridBase() { Destroy(); } void Destroy(); void Build(const SectorGridShared& rSrc); void Build(const BvAABB& rSrc, const DWORD sectorDist /*meter*/); void ReBuild(const SectorGridShared& rSrc, const DWORD sectorDist); }; // end SectorGridBase //================================================================================================== // class SectorGridInfo : public SectorGridBase { typedef SectorGridBase base_type; public: SectorGridInfo() {} private: void Init() {} // SectorGridBase::Build¿¡ ÀÇÇØ ÀÚµ¿ È£ÃâµÈ´Ù. void Release() {} // friend class SectorGridBase; friend class ::Sector; __DISABLE_COPY(SectorGridInfo); }; // //================================================================================================== // SYNC_MSG_LINKEDLIST // NOTE: f110112.5L, fix to byte alignment to enhance system architecture address calculator. struct SYNC_MSG_LINKEDLIST : public util::__LList { typedef SYNC_MSG_LINKEDLIST this_type; // internal method this_type* SerializeTo(WAR_MSG_HDR* const IN header, const WAR_TAG_V* war_msg_in_buffer, uint16_t war_msg_in_buffer_size) const; // const WAR_TAG_V* war_msg; uint16_t war_msg_size; }; // //================================================================================================== // class SectorGrid : public SectorGridBase { typedef SectorGridBase base_type; struct Node { Sector* pSector; SYNC_MSG_LINKEDLIST m_SectorRoot; }; public: SectorGrid() : m_pSectorNodes(0) {} // void Update(GameField* const game_field) const; Sector* GetSector(const SECTOR_IDX coordinates) const; Sector* AddSectorMsgNode(WAR_MSG_HDR* const header, const SECTOR_IDX coordinates, const WAR_TAG_V* war_msg_in_buffer, uint16_t war_msg_size) const; private: void Init(); // SectorGridBase::Build¿¡ ÀÇÇØ ÀÚµ¿ È£ÃâµÈ´Ù. void Release(); // Node* m_pSectorNodes; //SYNC_MSG_LINKEDLIST m_FieldRoot; friend class SectorGridBase; friend class ::Sector; friend class SectorGridVR; }; // //================================================================================================== // // - SectorGrid for Variable-Resolution // - SectorGridVRÀº 1°³ÀÇ SectorVRIndex¸¸ ó¸®ÇÑ´Ù. SectorGrid°¡ 9¸¦ Á¦°øÇÏ´õ¶óµµ // ´Ù¸¥ ºä¸¦ °¡Áö°í ƯÁ¤ Sectorµé¸¸ ó¸®ÇÒ ¼ö ÀÖ°Ô µÈ´Ù. (°è»ê °ø°£ °¨¼Ò) // - (WARNING) // - ÀÌ °ªÀ» »ç¿ëÇÒ ½Ã¿¡´Â m_pProjectionGrid°¡ not NULLÀ̶ó´Â ·ÎÁ÷ Á¦¾î Á¦¾àÀÌ Á¸ÀçÇÑ´Ù. // - ¹Ýµå½Ã Rebuild¸¦ È£ÃâÇÑ´Ù. class SectorGridVR : public SectorGridBase { typedef SectorGridBase base_type; public: // CHANGES: f110415.3L, prevent constructor usage to solve sun:r53320 case struct ProjectionGridWrapper { ProjectionGridWrapper(const SectorGridShared* projection_grid) : projection_grid_(projection_grid) {} const SectorGridShared* projection_grid_; }; SectorGridVR() : m_pProjectionGrid(NULL) {} // don't use it SectorGridVR(const ProjectionGridWrapper& projection) : m_pProjectionGrid(projection.projection_grid_) {} // void Rebuild(const DWORD sectorDist); // Resolution º¯°æ bool GetAroundSectors(const WzVector* IN point, // ±âÁØÀÌ µÇ´Â ÁÂÇ¥ SectorGrid3x3* const OUT result_grid, // (ÁÂÇ¥ ±âÁØ) Çö VRGrid¿¡ ¸Â´Â ProjectionGrid ¼½ÅÍ À妽º ¾î·¹ÀÌ ¹Ýȯ ViewBoxCubic* const OUT pOutBoundary) const; // (ÁÂÇ¥ ±âÁØ) Çö VRGrid°¡ °¡Áö´Â ViewBox private: void Init() {} // SectorGridBase::Build¿¡ ÀÇÇØ ÀÚµ¿ È£ÃâµÈ´Ù. void Release() {} struct Boundaries { int minX, minY, maxX, maxY; }; // (WAVERIX) (090403) type change bool CheckAllowMinMaxBoundary(const SECTOR_IDX coordinates, const SectorGridShared& rSrc, const Boundaries* const IN pBoundary) const; void Get3x3MinMaxBoundary(const SECTOR_IDX coordinates, const SectorGridVR& rSrc, Boundaries* const OUT pOut) const; // const SectorGridShared* m_pProjectionGrid; // friend class SectorGridBase; friend class ::Sector; }; // //================================================================================================== // // - SectorGrid based user-specific control // - SectorGrid ±â¹ÝÀ¸·Î º°µµÀÇ ÀڷᱸÁ¶¸¦ À¯ÁöÇÒ Çʿ䰡 ÀÖÀ» ¶§ »ç¿ë. template class SectorGridProxy : public SectorGridBase<_SUBTYPE> { typedef SectorGridBase<_SUBTYPE> base_type; public: SectorGridProxy() : m_pProjectionGrid(0) {} void Build(const DWORD sectorDist); // ´ÙÀ½ ÇÔ¼öµéÀº _SUBTYPE¿¡¼­ ±¸ÇöÇØ Init, Release¸¦ ó¸®ÇÒ °Í. //void Init(); // SectorGridBase::Build¿¡ ÀÇÇØ ÀÚµ¿ È£ÃâµÈ´Ù. //void Release(); // SectorGridBase::Destroy¿¡ ÀÇÇØ ÀÚµ¿ È£ÃâµÈ´Ù. protected: SectorGrid* m_pProjectionGrid; private: // friend class SectorGridBase<_SUBTYPE>; friend class ::Sector; __DISABLE_COPY(SectorGridProxy<_SUBTYPE>); }; }; //end of namespace 'nsGrid' //================================================================================================== //================================================================================================== //================================================================================================== // Around°è¿­¿¡¼­ Center¸¦ ¸ÕÀú ó¸®ÇÒ °æ¿ì¸¸ »ç¿ëÇÒ °Í. #define GRID3x3_CENTER_PRIOR_SWAP(_grid_) \ ;{ \ const SECTOR_IDX __center_index__ = (_grid_).Grid[ SectorGrid3x3::CENTER ]; \ (_grid_).Grid[ SectorGrid3x3::CENTER ] = (_grid_).Grid[ SectorGrid3x3::LEFT_UP ]; \ (_grid_).Grid[ SectorGrid3x3::LEFT_UP ] = __center_index__; \ }; //================================================================================================== // // - Bounding Volume for Variable Broadcast inline void nsGrid::ViewBoxCubic::SetInit2D( const WzVector* const center_pos, const WzVector* const radius_2d) { // ASSERT(pRadius.x > .0f && pRadius.y > .0f && pRadius.z == .0f); Cubic.m_wvMin.x = center_pos->x - radius_2d->x; Cubic.m_wvMin.y = center_pos->y - radius_2d->y; Cubic.m_wvMin.z = -5.0f; Cubic.m_wvMax.x = center_pos->x + radius_2d->x; Cubic.m_wvMax.y = center_pos->y + radius_2d->y; Cubic.m_wvMax.z = +5.0f; } inline void nsGrid::ViewBoxCubic::SetInit3D( const WzVector* const center_pos, const WzVector* const radius_3d) { // ASSERT(pRadius.x > .0f && pRadius.y > .0f && pRadius.z > .0f); Cubic.m_wvMin.x = center_pos->x - radius_3d->x; Cubic.m_wvMin.y = center_pos->y - radius_3d->y; Cubic.m_wvMin.z = center_pos->z - radius_3d->z - 5.0f; Cubic.m_wvMax.x = center_pos->x + radius_3d->x; Cubic.m_wvMax.y = center_pos->y + radius_3d->y; Cubic.m_wvMax.z = center_pos->z + radius_3d->z + 5.0f; } inline void nsGrid::ViewBoxCubic::SetInit3D_UpsideZ( const WzVector* const center_pos, const WzVector* const radius_3d) { // Ãþ °³³äÀÌ ÀÖ´Â 'Àúž'°°Àº °÷¿¡¼­ À¯¿ëÇÏ°Ô »ç¿ëÀÌ °¡´ÉÇÒ °ÍÀÌ´Ù. // ASSERT(pRadius.x > .0f && pRadius.y > .0f && pRadius.z > .0f); Cubic.m_wvMin.x = center_pos->x - radius_3d->x; Cubic.m_wvMin.y = center_pos->y - radius_3d->y; Cubic.m_wvMin.z = center_pos->z - 5.f; // °æ»çÁø ¸é, Àúž °°Àº °÷¿¡¼­ ¹Ì¹¦ÇÑ ¹®Á¦¸¦ ¾ß±âÇÒ ¼ö ÀÖÀ¸¹Ç·Î... Cubic.m_wvMax.x = center_pos->x + radius_3d->x; Cubic.m_wvMax.y = center_pos->y + radius_3d->y; Cubic.m_wvMax.z = center_pos->z + radius_3d->z + 5.0f; } inline void nsGrid::ViewBoxCubic::SetInit3D_DownsideZ( const WzVector* const center_pos, const WzVector* const radius_3d) { // Ãþ °³³äÀÌ ÀÖ´Â 'Àúž'°°Àº °÷¿¡¼­ À¯¿ëÇÏ°Ô »ç¿ëÀÌ °¡´ÉÇÒ °ÍÀÌ´Ù. (°è´Ü¿¡¼­ÀÇ Èú »ç¿ë °æ¿ì º¸Á¤ ÇÏÇâ ¼³Á¤) // ASSERT(pRadius.x > .0f && pRadius.y > .0f && pRadius.z > .0f); Cubic.m_wvMin.x = center_pos->x - radius_3d->x; Cubic.m_wvMin.y = center_pos->y - radius_3d->y; Cubic.m_wvMin.z = center_pos->z - radius_3d->z - 5.f; // °æ»çÁø ¸é, Àúž °°Àº °÷¿¡¼­ ¹Ì¹¦ÇÑ ¹®Á¦¸¦ ¾ß±âÇÒ ¼ö ÀÖÀ¸¹Ç·Î... Cubic.m_wvMax.x = center_pos->x + radius_3d->x; Cubic.m_wvMax.y = center_pos->y + radius_3d->y; Cubic.m_wvMax.z = center_pos->z + 5.0f; } // ÁÖ¾îÁø ¹æÇâÀ¸·Î °¡ÁßÄ¡ ¼³Á¤ (ÁÖ¾îÁø ¹æÇâÀ¸·Î ´õ ¸¹Àº °Å¸®¸¦ ÇÒ´çÇÑ´Ù.) // XXXXX XXXXX // XXXXX XXXXX // XXOXX => XXXXX // XXXXX XOXXX // XXXXX XXXXX inline void nsGrid::ViewBoxCubic::SetInit3D_Radian( const WzVector* const center_pos, const WzVector* const radius_3d, const WzVector* const direction_and_weight) { SetInit3D(center_pos, radius_3d); WzVector clone = *direction_and_weight; Cubic.m_wvMax += clone; } inline void nsGrid::ViewBoxCubic::SetInit3D_Radian_UpsideZ( const WzVector* const center_pos, const WzVector* const radius_3d, const WzVector* const direction_and_weight) { SetInit3D_UpsideZ(center_pos, radius_3d); WzVector clone = *direction_and_weight; clone.z = 0.f; // ³ôÀÌ·Î °¡ÁßÄ¡ ÁÖ´Â °ÍÀº ºñÇà½Ã¹Ä·¹À̼ǿ¡¼­³ª ÇÏ¸é µÈ´Ù. Cubic.m_wvMax += clone; } inline bool nsGrid::ViewBoxCubic::IsValidCoordinateXY(const WzVector* const point) const { const float fx = point->x; const float fy = point->y; if (fx < Cubic.m_wvMin.x || Cubic.m_wvMax.x < fx || fy < Cubic.m_wvMin.y || Cubic.m_wvMax.y < fy) { return false; } return true; } #ifdef _NA_004830_20120511_1202_SSQ_CLOSESPACE_DAMAGE_RANGE inline bool nsGrid::ViewBoxCubic::IsValidCoordinateXY(const WzVector* const point, const WzVector* const center_point) const { // »ç°¢Çü¿¡ ³»Á¢ÇÏ´Â ¿øÀ¸·Î Ãæµ¹Ã¼Å© ÇÏ´Â ÇÔ¼ö( ÀÚ½ÅÀÇ À§Ä¡, »ç°¢ÇüÀÇ ÁßÁ¡) // ij¸¯ÅÍÀÇ À§Ä¡.. const float fx = point->x; const float fy = point->y; // µÎ Á¡ÀÇ °Å¸® ±¸ÇÏ´Â °ø½Ä.. WzVector vector_distance; vector_distance.x = fx - center_point->x; vector_distance.y = fy - center_point->y; vector_distance.z = 0.0f; const float distance = VectorLength2(&vector_distance); // ¹ÝÁö¸§À» ±¸ÇÏ´Â °ø½Ä.. const float radius = (center_point->x - Cubic.m_wvMin.x); //Ãæµ¹ üũ.. if (distance > (radius*radius)) { return false; } return true; } #endif //_NA_004830_20120511_1202_SSQ_CLOSESPACE_DAMAGE_RANGE inline bool nsGrid::ViewBoxCubic::IsValidCoordinateXYZ(const WzVector* const point) const { // IsValidCoordinateXY º¸´Ù´Â À̰ÍÀ» »ç¿ëÇÏ´Â °ÍÀÌ ´õ ÁÁÀ» µí. º°µµÀÇ ¿¹¿Ü ó¸® ÇÊ¿ä ¾øÀ¸¹Ç·Î... const float fx = point->x; const float fy = point->y; const float fz = point->z; if (fx < Cubic.m_wvMin.x || Cubic.m_wvMax.x < fx || fy < Cubic.m_wvMin.y || Cubic.m_wvMax.y < fy || fz < Cubic.m_wvMin.z || Cubic.m_wvMax.z < fz) { return false; } return true; } //================================================================================================== // // inline nsGrid::SectorGridShared::SectorGridShared() : SectorCount(m_SectorCount) , SectorXYDistance(m_SectorXYdist) , m_SectorXYdist(0) , m_SectorCount(0) { ZeroMemory(m_Boundaries, sizeof(m_Boundaries)); ZeroMemory(m_Length, sizeof(m_Length)); } inline bool nsGrid::SectorGridShared::IsValidSector(const SECTOR_IDX coordinates) const { if ((coordinates < m_SectorCount) == false) { return false; } const DWORD indexX = coordinates % m_Length[LEN_X]; const DWORD indexY = coordinates / m_Length[LEN_X]; if (indexX >= m_Length[LEN_X] || indexY >= m_Length[LEN_Y]) { return false; } return true; } inline bool nsGrid::SectorGridShared::IsValidCoordinate(const WzVector* IN point) const { const DWORD x = (DWORD)point->x - m_Boundaries[SG_X_MIN]; const DWORD y = (DWORD)point->y - m_Boundaries[SG_Y_MIN]; return (0 <= x && x < m_Boundaries[SG_X_MAX]) && (0 <= y && y < m_Boundaries[SG_Y_MAX]); } inline bool nsGrid::SectorGridShared::_IsValidCoordinate( const DWORD x, const DWORD y, const DWORD z) const { __UNUSED(z); return (0 <= x && x < m_Boundaries[SG_X_MAX]) && (0 <= y && y < m_Boundaries[SG_Y_MAX]); } inline nsGrid::SECTOR_IDX nsGrid::SectorGridShared::GetSectorIndex(const WzVector* IN point) const { ulong cur_pos_x = static_cast(point->x) - m_Boundaries[SG_X_MIN]; ulong cur_pos_y = static_cast(point->y) - m_Boundaries[SG_Y_MIN]; if (_IsValidCoordinate(cur_pos_x, cur_pos_y, 0)) { ulong index_x = static_cast(cur_pos_x / m_SectorXYdist); ulong index_y = static_cast(cur_pos_y / m_SectorXYdist); return index_x + index_y * m_Length[LEN_X]; } return INVALID_SECTOR_INDEX; } inline bool nsGrid::SectorGridShared::GetCenterPosInSector( const SECTOR_IDX coordinates, WzVector& OUT result_center) const { if ((coordinates < m_SectorCount) == false) { return false; } const DWORD indexX = coordinates%m_Length[LEN_X]; const DWORD indexY = coordinates/m_Length[LEN_X]; result_center.x = (float)((indexX*m_SectorXYdist) + m_Boundaries[SG_X_MIN]); result_center.y = (float)((indexY*m_SectorXYdist) + m_Boundaries[SG_Y_MIN]); result_center.z = 0.f; return true; } //================================================================================================== // SectorGridBase<_SUBCLASS> // template void nsGrid::SectorGridBase<_SUBCLASS>::Destroy() { static_cast<_SUBCLASS*>(this)->Release(); m_SectorXYdist = 0; m_SectorCount = 0; ZeroMemory(m_Boundaries, sizeof(m_Boundaries)); ZeroMemory(m_Length, sizeof(m_Length)); } template inline void nsGrid::SectorGridBase<_SUBCLASS>::Build(const SectorGridShared& rSrc) { SectorGridShared::Build(rSrc); static_cast<_SUBCLASS*>(this)->Init(); } template inline void nsGrid::SectorGridBase<_SUBCLASS>::Build(const BvAABB& rSrc, const DWORD sectorDist) { SectorGridShared::Build(rSrc, sectorDist); static_cast<_SUBCLASS*>(this)->Init(); } template inline void nsGrid::SectorGridBase<_SUBCLASS>::ReBuild( const SectorGridShared& rSrc, const DWORD sectorDist) { const DWORD* const pBoundaries = rSrc.GetBoundaries(); BvAABB aabb; aabb.m_wvMin.x = (float)(int)pBoundaries[SG_X_MIN]; aabb.m_wvMin.y = (float)(int)pBoundaries[SG_Y_MIN]; aabb.m_wvMin.z = (float)(int)pBoundaries[SG_Z_MIN]; aabb.m_wvMax.x = aabb.m_wvMin.x + (float)(int)pBoundaries[SG_X_MAX]; aabb.m_wvMax.y = aabb.m_wvMin.y + (float)(int)pBoundaries[SG_Y_MAX]; aabb.m_wvMax.z = aabb.m_wvMin.z + (float)(int)pBoundaries[SG_Z_MAX]; Build(aabb, sectorDist); } //================================================================================================== // inline Sector* nsGrid::SectorGrid::GetSector(const SECTOR_IDX coordinates) const { if (m_pSectorNodes && coordinates < m_SectorCount) { return m_pSectorNodes[coordinates].pSector; } return NULL; } //================================================================================================== // inline void nsGrid::SectorGridVR::Rebuild(const DWORD sectorDist) { base_type::ReBuild(*m_pProjectionGrid, sectorDist); } template inline void nsGrid::SectorGridProxy<_SUBTYPE>::Build(const DWORD sectorDist) { if (m_pProjectionGrid) { base_type::ReBuild(*m_pProjectionGrid, sectorDist); } } #endif //GAMESERVER_SECTOR_GRID_H