mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[10705] Simplify CellArea calculation
This commit is contained in:
parent
7032423d6f
commit
b825c33cdf
5 changed files with 35 additions and 71 deletions
|
|
@ -29,22 +29,19 @@ class WorldObject;
|
|||
|
||||
struct MANGOS_DLL_DECL CellArea
|
||||
{
|
||||
CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {}
|
||||
CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {}
|
||||
bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; }
|
||||
CellArea() {}
|
||||
CellArea(CellPair low, CellPair high) : low_bound(low), high_bound(high) {}
|
||||
|
||||
bool operator!() const { return low_bound == high_bound; }
|
||||
|
||||
void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const
|
||||
{
|
||||
begin_cell << left_offset;
|
||||
begin_cell -= lower_offset;
|
||||
end_cell >> right_offset;
|
||||
end_cell += upper_offset;
|
||||
begin_cell = low_bound;
|
||||
end_cell = high_bound;
|
||||
}
|
||||
|
||||
int right_offset;
|
||||
int left_offset;
|
||||
int upper_offset;
|
||||
int lower_offset;
|
||||
CellPair low_bound;
|
||||
CellPair high_bound;
|
||||
};
|
||||
|
||||
struct MANGOS_DLL_DECL Cell
|
||||
|
|
|
|||
|
|
@ -34,38 +34,19 @@ inline Cell::Cell(CellPair const& p)
|
|||
data.Part.reserved = 0;
|
||||
}
|
||||
|
||||
inline int CellHelper(const float radius)
|
||||
{
|
||||
if(radius < 1.0f)
|
||||
return 0;
|
||||
|
||||
return (int)ceilf(radius/SIZE_OF_GRID_CELL);
|
||||
}
|
||||
|
||||
inline CellArea Cell::CalculateCellArea(float x, float y, float radius)
|
||||
{
|
||||
if (radius <= 0.0f)
|
||||
return CellArea();
|
||||
{
|
||||
CellPair center = MaNGOS::ComputeCellPair(x, y).normalize();
|
||||
return CellArea(center, center);
|
||||
}
|
||||
|
||||
//lets calculate object coord offsets from cell borders.
|
||||
//TODO: add more correct/generic method for this task
|
||||
const float x_offset = (x - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
|
||||
const float y_offset = (y - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
|
||||
|
||||
const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f);
|
||||
const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f);
|
||||
|
||||
const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL;
|
||||
const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL;
|
||||
|
||||
const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET;
|
||||
//lets calculate upper/lower/right/left corners for cell search
|
||||
int right = CellHelper(tmp_diff + x_off);
|
||||
int left = CellHelper(tmp_diff - x_off);
|
||||
int upper = CellHelper(tmp_diff + y_off);
|
||||
int lower = CellHelper(tmp_diff - y_off);
|
||||
|
||||
return CellArea(right, left, upper, lower);
|
||||
return CellArea
|
||||
(
|
||||
MaNGOS::ComputeCellPair(x - radius, y - radius).normalize(),
|
||||
MaNGOS::ComputeCellPair(x + radius, y + radius).normalize()
|
||||
);
|
||||
}
|
||||
|
||||
template<class T, class CONTAINER>
|
||||
|
|
@ -104,10 +85,8 @@ Cell::Visit(const CellPair &standing_cell, TypeContainerVisitor<T, CONTAINER> &v
|
|||
return;
|
||||
}
|
||||
|
||||
CellPair begin_cell = standing_cell;
|
||||
CellPair end_cell = standing_cell;
|
||||
|
||||
area.ResizeBorders(begin_cell, end_cell);
|
||||
CellPair &begin_cell = area.low_bound;
|
||||
CellPair &end_cell = area.high_bound;
|
||||
//visit all cells, found in CalculateCellArea()
|
||||
//if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle
|
||||
//currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values
|
||||
|
|
|
|||
|
|
@ -121,6 +121,13 @@ struct MANGOS_DLL_DECL CoordPair
|
|||
y_coord = LIMIT - 1;
|
||||
}
|
||||
|
||||
CoordPair& normalize()
|
||||
{
|
||||
x_coord = std::min(x_coord, LIMIT);
|
||||
y_coord = std::min(y_coord, LIMIT);
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32 x_coord;
|
||||
uint32 y_coord;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -530,25 +530,15 @@ void Map::Update(uint32 time_, uint32 diff)
|
|||
{
|
||||
Player* plr = m_mapRefIter->getSource();
|
||||
|
||||
if(!plr->IsInWorld())
|
||||
if (!plr->IsInWorld() || !plr->IsPositionValid())
|
||||
continue;
|
||||
|
||||
CellPair standing_cell(MaNGOS::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY()));
|
||||
|
||||
// Check for correctness of standing_cell, it also avoids problems with update_cell
|
||||
if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
|
||||
continue;
|
||||
|
||||
// the overloaded operators handle range checking
|
||||
// so ther's no need for range checking inside the loop
|
||||
CellPair begin_cell(standing_cell), end_cell(standing_cell);
|
||||
//lets update mobs/objects in ALL visible cells around player!
|
||||
CellArea area = Cell::CalculateCellArea(plr->GetPositionX(), plr->GetPositionY(), GetVisibilityDistance());
|
||||
area.ResizeBorders(begin_cell, end_cell);
|
||||
|
||||
for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x)
|
||||
for(uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
|
||||
{
|
||||
for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y)
|
||||
for(uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
|
||||
{
|
||||
// marked cells are those that have been visited
|
||||
// don't visit the same cell twice
|
||||
|
|
@ -594,24 +584,15 @@ void Map::Update(uint32 time_, uint32 diff)
|
|||
// step to next-next, and if we step to end() then newly added objects can wait next update.
|
||||
++m_activeNonPlayersIter;
|
||||
|
||||
if(!obj->IsInWorld())
|
||||
if (!obj->IsInWorld() || !obj->IsPositionValid())
|
||||
continue;
|
||||
|
||||
CellPair standing_cell(MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()));
|
||||
|
||||
// Check for correctness of standing_cell, it also avoids problems with update_cell
|
||||
if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
|
||||
continue;
|
||||
|
||||
// the overloaded operators handle range checking
|
||||
// so ther's no need for range checking inside the loop
|
||||
CellPair begin_cell(standing_cell), end_cell(standing_cell);
|
||||
//lets update mobs/objects in ALL visible cells around player!
|
||||
CellArea area = Cell::CalculateCellArea(obj->GetPositionX(), obj->GetPositionY(), GetVisibilityDistance());
|
||||
area.ResizeBorders(begin_cell, end_cell);
|
||||
|
||||
for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x)
|
||||
for(uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
|
||||
{
|
||||
for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y)
|
||||
for(uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
|
||||
{
|
||||
// marked cells are those that have been visited
|
||||
// don't visit the same cell twice
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "10704"
|
||||
#define REVISION_NR "10705"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue