From b825c33cdfade37b49fc9bfc1fde42a497c5f44d Mon Sep 17 00:00:00 2001 From: SilverIce Date: Tue, 9 Nov 2010 00:56:49 +0200 Subject: [PATCH] [10705] Simplify CellArea calculation --- src/game/Cell.h | 19 +++++++---------- src/game/CellImpl.h | 45 +++++++++++----------------------------- src/game/GridDefines.h | 7 +++++++ src/game/Map.cpp | 33 +++++++---------------------- src/shared/revision_nr.h | 2 +- 5 files changed, 35 insertions(+), 71 deletions(-) diff --git a/src/game/Cell.h b/src/game/Cell.h index 031149af2..236c6ae57 100644 --- a/src/game/Cell.h +++ b/src/game/Cell.h @@ -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 diff --git a/src/game/CellImpl.h b/src/game/CellImpl.h index 58a797ae9..2109287b6 100644 --- a/src/game/CellImpl.h +++ b/src/game/CellImpl.h @@ -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(); + if (radius <= 0.0f) + { + 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 @@ -104,10 +85,8 @@ Cell::Visit(const CellPair &standing_cell, TypeContainerVisitor &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 diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h index da5abba03..0079d0b19 100644 --- a/src/game/GridDefines.h +++ b/src/game/GridDefines.h @@ -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; }; diff --git a/src/game/Map.cpp b/src/game/Map.cpp index dc26fec6e..28dc44657 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -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 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e83e0178c..454908ea3 100644 --- a/src/shared/revision_nr.h +++ b/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__