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
|
struct MANGOS_DLL_DECL CellArea
|
||||||
{
|
{
|
||||||
CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {}
|
CellArea() {}
|
||||||
CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {}
|
CellArea(CellPair low, CellPair high) : low_bound(low), high_bound(high) {}
|
||||||
bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; }
|
|
||||||
|
bool operator!() const { return low_bound == high_bound; }
|
||||||
|
|
||||||
void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const
|
void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const
|
||||||
{
|
{
|
||||||
begin_cell << left_offset;
|
begin_cell = low_bound;
|
||||||
begin_cell -= lower_offset;
|
end_cell = high_bound;
|
||||||
end_cell >> right_offset;
|
|
||||||
end_cell += upper_offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int right_offset;
|
CellPair low_bound;
|
||||||
int left_offset;
|
CellPair high_bound;
|
||||||
int upper_offset;
|
|
||||||
int lower_offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MANGOS_DLL_DECL Cell
|
struct MANGOS_DLL_DECL Cell
|
||||||
|
|
|
||||||
|
|
@ -34,38 +34,19 @@ inline Cell::Cell(CellPair const& p)
|
||||||
data.Part.reserved = 0;
|
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)
|
inline CellArea Cell::CalculateCellArea(float x, float y, float radius)
|
||||||
{
|
{
|
||||||
if(radius <= 0.0f)
|
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.
|
return CellArea
|
||||||
//TODO: add more correct/generic method for this task
|
(
|
||||||
const float x_offset = (x - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
|
MaNGOS::ComputeCellPair(x - radius, y - radius).normalize(),
|
||||||
const float y_offset = (y - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
|
MaNGOS::ComputeCellPair(x + radius, y + radius).normalize()
|
||||||
|
);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, class CONTAINER>
|
template<class T, class CONTAINER>
|
||||||
|
|
@ -104,10 +85,8 @@ Cell::Visit(const CellPair &standing_cell, TypeContainerVisitor<T, CONTAINER> &v
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CellPair begin_cell = standing_cell;
|
CellPair &begin_cell = area.low_bound;
|
||||||
CellPair end_cell = standing_cell;
|
CellPair &end_cell = area.high_bound;
|
||||||
|
|
||||||
area.ResizeBorders(begin_cell, end_cell);
|
|
||||||
//visit all cells, found in CalculateCellArea()
|
//visit all cells, found in CalculateCellArea()
|
||||||
//if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle
|
//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
|
//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;
|
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 x_coord;
|
||||||
uint32 y_coord;
|
uint32 y_coord;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -530,25 +530,15 @@ void Map::Update(uint32 time_, uint32 diff)
|
||||||
{
|
{
|
||||||
Player* plr = m_mapRefIter->getSource();
|
Player* plr = m_mapRefIter->getSource();
|
||||||
|
|
||||||
if(!plr->IsInWorld())
|
if (!plr->IsInWorld() || !plr->IsPositionValid())
|
||||||
continue;
|
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!
|
//lets update mobs/objects in ALL visible cells around player!
|
||||||
CellArea area = Cell::CalculateCellArea(plr->GetPositionX(), plr->GetPositionY(), GetVisibilityDistance());
|
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
|
// marked cells are those that have been visited
|
||||||
// don't visit the same cell twice
|
// 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.
|
// step to next-next, and if we step to end() then newly added objects can wait next update.
|
||||||
++m_activeNonPlayersIter;
|
++m_activeNonPlayersIter;
|
||||||
|
|
||||||
if(!obj->IsInWorld())
|
if (!obj->IsInWorld() || !obj->IsPositionValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CellPair standing_cell(MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()));
|
//lets update mobs/objects in ALL visible cells around player!
|
||||||
|
|
||||||
// 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);
|
|
||||||
CellArea area = Cell::CalculateCellArea(obj->GetPositionX(), obj->GetPositionY(), GetVisibilityDistance());
|
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
|
// marked cells are those that have been visited
|
||||||
// don't visit the same cell twice
|
// don't visit the same cell twice
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "10704"
|
#define REVISION_NR "10705"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue