Skip to content

Commit

Permalink
[10705] Simplify CellArea calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
SilverIce authored and tomrus88 committed Nov 15, 2010
1 parent ac3ad4f commit 40d0f17
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 71 deletions.
19 changes: 8 additions & 11 deletions src/game/Cell.h
Expand Up @@ -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
Expand Down
45 changes: 12 additions & 33 deletions src/game/CellImpl.h
Expand Up @@ -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();

//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);
if (radius <= 0.0f)
{
CellPair center = MaNGOS::ComputeCellPair(x, y).normalize();
return CellArea(center, center);
}

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>
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions src/game/GridDefines.h
Expand Up @@ -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;
};
Expand Down
33 changes: 7 additions & 26 deletions src/game/Map.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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())
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)
if (!obj->IsInWorld() || !obj->IsPositionValid())
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
Expand Down
2 changes: 1 addition & 1 deletion src/shared/revision_nr.h
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10704"
#define REVISION_NR "10705"
#endif // __REVISION_NR_H__

0 comments on commit 40d0f17

Please sign in to comment.