Skip to content

Commit

Permalink
[11659] Rewrite object pos selector.
Browse files Browse the repository at this point in the history
* Instead coordinates use angle projections to expected pos distance circle.
  This let do mostly only angle comparison and then speedup checks.
* Fixed some long existed bugs in algo and simplify code. Possible more work need.
  • Loading branch information
VladimirMangos committed Jun 21, 2011
1 parent f8bb645 commit a9b961d
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 285 deletions.
127 changes: 49 additions & 78 deletions src/game/Object.cpp
Expand Up @@ -1703,22 +1703,21 @@ namespace MaNGOS
class NearUsedPosDo
{
public:
NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float angle, ObjectPosSelector& selector)
: i_object(obj), i_searcher(searcher), i_angle(angle), i_selector(selector) {}
NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float absAngle, ObjectPosSelector& selector)
: i_object(obj), i_searcher(searcher), i_absAngle(absAngle), i_selector(selector) {}

void operator()(Corpse*) const {}
void operator()(DynamicObject*) const {}

void operator()(Creature* c) const
{
// skip self or target
if(c==i_searcher || c==&i_object)
if (c == i_searcher || c == &i_object)
return;

float x,y,z;
float x, y, z;

if( !c->isAlive() || c->hasUnitState(UNIT_STAT_NOT_MOVE) ||
!c->GetMotionMaster()->GetDestination(x,y,z) )
if (c->IsStopped() || !c->GetMotionMaster()->GetDestination(x, y, z))
{
x = c->GetPositionX();
y = c->GetPositionY();
Expand All @@ -1728,10 +1727,10 @@ namespace MaNGOS
}

template<class T>
void operator()(T* u) const
void operator()(T* u) const
{
// skip self or target
if(u==i_searcher || u==&i_object)
if (u == i_searcher || u == &i_object)
return;

float x,y;
Expand All @@ -1745,26 +1744,32 @@ namespace MaNGOS
// we must add used pos that can fill places around center
void add(WorldObject* u, float x, float y) const
{
// dist include size of u and i_object
float dx = i_object.GetPositionX() - x;
float dy = i_object.GetPositionY() - y;
float dist2d = sqrt((dx * dx) + (dy * dy));

float delta = i_selector.m_searcherSize + u->GetObjectBoundingRadius();

// u is too nearest/far away to i_object
if(!i_object.IsInRange2d(x,y,i_selector.m_dist - i_selector.m_size,i_selector.m_dist + i_selector.m_size))
if (dist2d < i_selector.m_searcherDist - delta ||
dist2d >= i_selector.m_searcherDist + delta)
return;

float angle = i_object.GetAngle(u)-i_angle;
float angle = i_object.GetAngle(u) - i_absAngle;

// move angle to range -pi ... +pi
while( angle > M_PI_F)
while (angle > M_PI_F)
angle -= 2.0f * M_PI_F;
while(angle < -M_PI_F)
while (angle < -M_PI_F)
angle += 2.0f * M_PI_F;

// dist include size of u
float dist2d = i_object.GetDistance2d(x,y);
i_selector.AddUsedPos(u->GetObjectBoundingRadius(), angle, dist2d + i_object.GetObjectBoundingRadius());
i_selector.AddUsedArea(u->GetObjectBoundingRadius(), angle, dist2d);
}
private:
WorldObject const& i_object;
WorldObject const* i_searcher;
float i_angle;
float i_absAngle;
ObjectPosSelector& i_selector;
};
} // namespace MaNGOS
Expand All @@ -1782,16 +1787,16 @@ void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float abs

void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float searcher_bounding_radius, float distance2d, float absAngle) const
{
GetNearPoint2D(x, y, distance2d+searcher_bounding_radius, absAngle);
GetNearPoint2D(x, y, distance2d + searcher_bounding_radius, absAngle);
z = GetPositionZ();

// if detection disabled, return first point
if(!sWorld.getConfig(CONFIG_BOOL_DETECT_POS_COLLISION))
{
if (searcher)
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x,y,z);
UpdateGroundPositionZ(x, y, z);
return;
}

Expand All @@ -1801,113 +1806,79 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
bool first_los_conflict = false; // first point LOS problems

// prepare selector for work
ObjectPosSelector selector(GetPositionX(), GetPositionY(), GetObjectBoundingRadius(), distance2d+searcher_bounding_radius);
ObjectPosSelector selector(GetPositionX(), GetPositionY(), distance2d + searcher_bounding_radius + GetObjectBoundingRadius(), searcher_bounding_radius);

// adding used positions around object
{
MaNGOS::NearUsedPosDo u_do(*this,searcher,absAngle,selector);
MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo> worker(this,u_do);
MaNGOS::NearUsedPosDo u_do(*this, searcher, absAngle, selector);
MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo> worker(this, u_do);

Cell::VisitAllObjects(this, worker, distance2d);
Cell::VisitAllObjects(this, worker, distance2d + searcher_bounding_radius);
}

// maybe can just place in primary position
if( selector.CheckOriginal() )
if (selector.CheckOriginalAngle())
{
if (searcher)
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x,y,z);
UpdateGroundPositionZ(x, y, z);

if(IsWithinLOS(x,y,z))
if (IsWithinLOS(x, y, z))
return;

first_los_conflict = true; // first point have LOS problems
}

float angle; // candidate of angle for free pos

// special case when one from list empty and then empty side preferred
if(selector.FirstAngle(angle))
{
GetNearPoint2D(x,y,distance2d,absAngle+angle);
z = GetPositionZ();

if (searcher)
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
else
UpdateGroundPositionZ(x,y,z);

if(IsWithinLOS(x,y,z))
return;
}

// set first used pos in lists
selector.InitializeAngle();

float angle; // candidate of angle for free pos

// select in positions after current nodes (selection one by one)
while(selector.NextAngle(angle)) // angle for free pos
while (selector.NextAngle(angle)) // angle for free pos
{
GetNearPoint2D(x,y,distance2d,absAngle+angle);
GetNearPoint2D(x, y, distance2d + searcher_bounding_radius, absAngle + angle);
z = GetPositionZ();

if (searcher)
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x,y,z);
UpdateGroundPositionZ(x, y, z);

if(IsWithinLOS(x,y,z))
if (IsWithinLOS(x, y, z))
return;
}

// BAD NEWS: not free pos (or used or have LOS problems)
// Attempt find _used_ pos without LOS problem

if(!first_los_conflict)
if (!first_los_conflict)
{
x = first_x;
y = first_y;

if (searcher)
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x,y,z);
UpdateGroundPositionZ(x, y, z);
return;
}

// special case when one from list empty and then empty side preferred
if( selector.IsNonBalanced() )
{
if(!selector.FirstAngle(angle)) // _used_ pos
{
GetNearPoint2D(x,y,distance2d,absAngle+angle);
z = GetPositionZ();

if (searcher)
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
else
UpdateGroundPositionZ(x,y,z);

if(IsWithinLOS(x,y,z))
return;
}
}

// set first used pos in lists
selector.InitializeAngle();

// select in positions after current nodes (selection one by one)
while(selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
while (selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
{
GetNearPoint2D(x,y,distance2d,absAngle+angle);
GetNearPoint2D(x, y, distance2d + searcher_bounding_radius, absAngle + angle);
z = GetPositionZ();

if (searcher)
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x,y,z);
UpdateGroundPositionZ(x, y, z);

if(IsWithinLOS(x,y,z))
if (IsWithinLOS(x, y, z))
return;
}

Expand All @@ -1916,9 +1887,9 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
y = first_y;

if (searcher)
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x,y,z);
UpdateGroundPositionZ(x, y, z);
}

void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
Expand Down

5 comments on commit a9b961d

@PSZ
Copy link
Contributor

@PSZ PSZ commented on a9b961d Jun 24, 2011

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this commit I've got server freezes (with bang crashes) every 2-3 minutes on online 50-60.
Crashdump (with all threads): https://gist.github.com/1044692

Added: when reverted this commit - everything became fine.

@VladimirMangos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in core clean sources no line numbers from crash log so hard research problem by it...

@VladimirMangos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add in [11675] some checks for possible source of problems. Please inform is this help.

@PSZ
Copy link
Contributor

@PSZ PSZ commented on a9b961d Jun 29, 2011

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, forgot to report. After 11675 freezes has gone, thanks.

@VladimirMangos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for confirm!

Please sign in to comment.