forked from mirror/DotRecast
Code cleanup and small optimizations in RecastFilter.cpp rcFilterLedgeSpans (https://github.com/recastnavigation/recastnavigation/pull/672)
- 3e94c3b6fc
* Code cleanup and minor refactor in RecastFilter.cpp rcFilterLedgeSpans
Because span.smax is always > 0, bot > 0 as well, and (-walkableClimb - bot) is always < -walkableClimb. Furthermore, as long as minNeighborHeight < -walkableClimb' at least once, there is no need to continue the traversal.
* Code cleanup and minor refactor in RecastFilter.cpp rcFilterLedgeSpans
Because span.smax is always > 0, bot > 0 as well, and (-walkableClimb - bot) is always < -walkableClimb. Furthermore, as long as minNeighborHeight < -walkableClimb' at least once, there is no need to continue the traversal.
* Update RecastFilter.cpp
Revise Comment
This commit is contained in:
parent
2d36b5f639
commit
9d01b5243f
|
@ -84,70 +84,79 @@ namespace DotRecast.Recast
|
||||||
/// A span is a ledge if: <tt>RcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt>
|
/// A span is a ledge if: <tt>RcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt>
|
||||||
///
|
///
|
||||||
/// @see rcHeightfield, rcConfig
|
/// @see rcHeightfield, rcConfig
|
||||||
public static void FilterLedgeSpans(RcTelemetry ctx, int walkableHeight, int walkableClimb, RcHeightfield solid)
|
public static void FilterLedgeSpans(RcTelemetry ctx, int walkableHeight, int walkableClimb, RcHeightfield heightfield)
|
||||||
{
|
{
|
||||||
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_FILTER_BORDER);
|
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_FILTER_BORDER);
|
||||||
|
|
||||||
int w = solid.width;
|
int xSize = heightfield.width;
|
||||||
int h = solid.height;
|
int zSize = heightfield.height;
|
||||||
|
|
||||||
// Mark border spans.
|
// Mark border spans.
|
||||||
for (int y = 0; y < h; ++y)
|
for (int z = 0; z < zSize; ++z)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < w; ++x)
|
for (int x = 0; x < xSize; ++x)
|
||||||
{
|
{
|
||||||
for (RcSpan s = solid.spans[x + y * w]; s != null; s = s.next)
|
for (RcSpan span = heightfield.spans[x + z * xSize]; span != null; span = span.next)
|
||||||
{
|
{
|
||||||
// Skip non walkable spans.
|
// Skip non walkable spans.
|
||||||
if (s.area == RC_NULL_AREA)
|
if (span.area == RC_NULL_AREA)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int bot = (s.smax);
|
int bot = (span.smax);
|
||||||
int top = s.next != null ? s.next.smin : SPAN_MAX_HEIGHT;
|
int top = span.next != null ? span.next.smin : SPAN_MAX_HEIGHT;
|
||||||
|
|
||||||
// Find neighbours minimum height.
|
// Find neighbours minimum height.
|
||||||
int minh = SPAN_MAX_HEIGHT;
|
int minNeighborHeight = SPAN_MAX_HEIGHT;
|
||||||
|
|
||||||
// Min and max height of accessible neighbours.
|
// Min and max height of accessible neighbours.
|
||||||
int asmin = s.smax;
|
int accessibleNeighborMinHeight = span.smax;
|
||||||
int asmax = s.smax;
|
int accessibleNeighborMaxHeight = span.smax;
|
||||||
|
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
for (int direction = 0; direction < 4; ++direction)
|
||||||
{
|
{
|
||||||
int dx = x + GetDirOffsetX(dir);
|
int dx = x + GetDirOffsetX(direction);
|
||||||
int dy = y + GetDirOffsetY(dir);
|
int dz = z + GetDirOffsetY(direction);
|
||||||
// Skip neighbours which are out of bounds.
|
// Skip neighbours which are out of bounds.
|
||||||
if (dx < 0 || dy < 0 || dx >= w || dy >= h)
|
if (dx < 0 || dz < 0 || dx >= xSize || dz >= zSize)
|
||||||
{
|
{
|
||||||
minh = Math.Min(minh, -walkableClimb - bot);
|
minNeighborHeight = (-walkableClimb - 1);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// From minus infinity to the first span.
|
// From minus infinity to the first span.
|
||||||
RcSpan ns = solid.spans[dx + dy * w];
|
RcSpan neighborSpan = heightfield.spans[dx + dz * xSize];
|
||||||
int nbot = -walkableClimb;
|
int neighborTop = neighborSpan != null ? neighborSpan.smin : SPAN_MAX_HEIGHT;
|
||||||
int ntop = ns != null ? ns.smin : SPAN_MAX_HEIGHT;
|
|
||||||
// Skip neightbour if the gap between the spans is too small.
|
// Skip neightbour if the gap between the spans is too small.
|
||||||
if (Math.Min(top, ntop) - Math.Max(bot, nbot) > walkableHeight)
|
if (Math.Min(top, neighborTop) - bot >= walkableHeight)
|
||||||
minh = Math.Min(minh, nbot - bot);
|
{
|
||||||
|
minNeighborHeight = (-walkableClimb - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Rest of the spans.
|
// Rest of the spans.
|
||||||
for (ns = solid.spans[dx + dy * w]; ns != null; ns = ns.next)
|
for (neighborSpan = heightfield.spans[dx + dz * xSize]; neighborSpan != null; neighborSpan = neighborSpan.next)
|
||||||
{
|
{
|
||||||
nbot = ns.smax;
|
int neighborBot = neighborSpan.smax;
|
||||||
ntop = ns.next != null ? ns.next.smin : SPAN_MAX_HEIGHT;
|
neighborTop = neighborSpan.next != null ? neighborSpan.next.smin : SPAN_MAX_HEIGHT;
|
||||||
|
|
||||||
// Skip neightbour if the gap between the spans is too small.
|
// Skip neightbour if the gap between the spans is too small.
|
||||||
if (Math.Min(top, ntop) - Math.Max(bot, nbot) > walkableHeight)
|
if (Math.Min(top, neighborTop) - Math.Max(bot, neighborBot) >= walkableHeight)
|
||||||
{
|
{
|
||||||
minh = Math.Min(minh, nbot - bot);
|
int accessibleNeighbourHeight = neighborBot - bot;
|
||||||
|
minNeighborHeight = Math.Min(minNeighborHeight, accessibleNeighbourHeight);
|
||||||
|
|
||||||
// Find min/max accessible neighbour height.
|
// Find min/max accessible neighbour height.
|
||||||
if (MathF.Abs(nbot - bot) <= walkableClimb)
|
if (MathF.Abs(accessibleNeighbourHeight) <= walkableClimb)
|
||||||
{
|
{
|
||||||
if (nbot < asmin)
|
if (neighborBot < accessibleNeighborMinHeight) accessibleNeighborMinHeight = neighborBot;
|
||||||
asmin = nbot;
|
if (neighborBot > accessibleNeighborMaxHeight) accessibleNeighborMaxHeight = neighborBot;
|
||||||
if (nbot > asmax)
|
}
|
||||||
asmax = nbot;
|
else if (accessibleNeighbourHeight < -walkableClimb)
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,14 +164,16 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
// The current span is close to a ledge if the drop to any
|
// The current span is close to a ledge if the drop to any
|
||||||
// neighbour span is less than the walkableClimb.
|
// neighbour span is less than the walkableClimb.
|
||||||
if (minh < -walkableClimb)
|
if (minNeighborHeight < -walkableClimb)
|
||||||
s.area = RC_NULL_AREA;
|
{
|
||||||
|
span.area = RC_NULL_AREA;
|
||||||
|
}
|
||||||
|
|
||||||
// If the difference between all neighbours is too large,
|
// If the difference between all neighbours is too large,
|
||||||
// we are at steep slope, mark the span as ledge.
|
// we are at steep slope, mark the span as ledge.
|
||||||
if ((asmax - asmin) > walkableClimb)
|
if ((accessibleNeighborMaxHeight - accessibleNeighborMinHeight) > walkableClimb)
|
||||||
{
|
{
|
||||||
s.area = RC_NULL_AREA;
|
span.area = RC_NULL_AREA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue