refactor: update comments

This commit is contained in:
ikpil 2024-01-10 01:20:03 +09:00
parent ebca91e64d
commit 85c3cfdcf6
2 changed files with 57 additions and 25 deletions

View File

@ -310,7 +310,9 @@ namespace DotRecast.Recast
RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(geom, builderCfg, ctx); RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(geom, builderCfg, ctx);
FilterHeightfield(solid, builderCfg.cfg, ctx); FilterHeightfield(solid, builderCfg.cfg, ctx);
RcCompactHeightfield chf = BuildCompactHeightfield(geom, builderCfg.cfg, ctx, solid); RcCompactHeightfield chf = BuildCompactHeightfield(geom, builderCfg.cfg, ctx, solid);
return RcLayers.BuildHeightfieldLayers(ctx, chf, builderCfg.cfg.WalkableHeight);
RcLayers.BuildHeightfieldLayers(ctx, chf, builderCfg.cfg.BorderSize, builderCfg.cfg.WalkableHeight, out var lset);
return lset;
} }
} }
} }

View File

@ -52,15 +52,37 @@ namespace DotRecast.Recast
return (amin > bmax || amax < bmin) ? false : true; return (amin > bmax || amax < bmin) ? false : true;
} }
public static RcHeightfieldLayerSet BuildHeightfieldLayers(RcContext ctx, RcCompactHeightfield chf, int walkableHeight) /// @par
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocHeightfieldLayerSet, rcCompactHeightfield, rcHeightfieldLayerSet, rcConfig
/// @}
/// @name Layer, Contour, Polymesh, and Detail Mesh Functions
/// @see rcHeightfieldLayer, rcContourSet, rcPolyMesh, rcPolyMeshDetail
/// @{
/// Builds a layer set from the specified compact heightfield.
/// @ingroup recast
/// @param[in,out] ctx The build context to use during the operation.
/// @param[in] chf A fully built compact heightfield.
/// @param[in] borderSize The size of the non-navigable border around the heightfield. [Limit: >=0]
/// [Units: vx]
/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area
/// to be considered walkable. [Limit: >= 3] [Units: vx]
/// @param[out] lset The resulting layer set. (Must be pre-allocated.)
/// @returns True if the operation completed successfully.
public static bool BuildHeightfieldLayers(RcContext ctx, RcCompactHeightfield chf, int borderSize, int walkableHeight, out RcHeightfieldLayerSet lset)
{ {
lset = null;
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_LAYERS); using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_LAYERS);
int w = chf.width; int w = chf.width;
int h = chf.height; int h = chf.height;
int borderSize = chf.borderSize;
int[] srcReg = new int[chf.spanCount]; int[] srcReg = new int[chf.spanCount];
Array.Fill(srcReg, 0xFF); Array.Fill(srcReg, 0xFF);
int nsweeps = chf.width; // Math.Max(chf.width, chf.height); int nsweeps = chf.width; // Math.Max(chf.width, chf.height);
RcLayerSweepSpan[] sweeps = new RcLayerSweepSpan[nsweeps]; RcLayerSweepSpan[] sweeps = new RcLayerSweepSpan[nsweeps];
for (int i = 0; i < sweeps.Length; i++) for (int i = 0; i < sweeps.Length; i++)
@ -71,11 +93,12 @@ namespace DotRecast.Recast
// Partition walkable area into monotone regions. // Partition walkable area into monotone regions.
int[] prevCount = new int[256]; int[] prevCount = new int[256];
int regId = 0; int regId = 0;
// Sweep one line at a time. // Sweep one line at a time.
for (int y = borderSize; y < h - borderSize; ++y) for (int y = borderSize; y < h - borderSize; ++y)
{ {
// Collect spans from this row. // Collect spans from this row.
Array.Fill(prevCount, 0, 0, (regId) - (0)); Array.Fill(prevCount, 0);
int sweepId = 0; int sweepId = 0;
for (int x = borderSize; x < w - borderSize; ++x) for (int x = borderSize; x < w - borderSize; ++x)
@ -87,9 +110,10 @@ namespace DotRecast.Recast
ref RcCompactSpan s = ref chf.spans[i]; ref RcCompactSpan s = ref chf.spans[i];
if (chf.areas[i] == RC_NULL_AREA) if (chf.areas[i] == RC_NULL_AREA)
continue; continue;
int sid = 0xFF;
// -x
int sid = 0xFF;
// -x
if (GetCon(ref s, 0) != RC_NOT_CONNECTED) if (GetCon(ref s, 0) != RC_NOT_CONNECTED)
{ {
int ax = x + GetDirOffsetX(0); int ax = x + GetDirOffsetX(0);
@ -115,8 +139,7 @@ namespace DotRecast.Recast
int nr = srcReg[ai]; int nr = srcReg[ai];
if (nr != 0xff) if (nr != 0xff)
{ {
// Set neighbour when first valid neighbour is // Set neighbour when first valid neighbour is encoutered.
// encoutered.
if (sweeps[sid].ns == 0) if (sweeps[sid].ns == 0)
sweeps[sid].nei = nr; sweeps[sid].nei = nr;
@ -128,8 +151,7 @@ namespace DotRecast.Recast
} }
else else
{ {
// This is hit if there is nore than one // This is hit if there is nore than one neighbour.
// neighbour.
// Invalidate the neighbour. // Invalidate the neighbour.
sweeps[sid].nei = 0xff; sweeps[sid].nei = 0xff;
} }
@ -143,10 +165,8 @@ namespace DotRecast.Recast
// Create unique ID. // Create unique ID.
for (int i = 0; i < sweepId; ++i) for (int i = 0; i < sweepId; ++i)
{ {
// If the neighbour is set and there is only one continuous // If the neighbour is set and there is only one continuous connection to it,
// connection to it, // the sweep will be merged with the previous one, else new region is created.
// the sweep will be merged with the previous one, else new
// region is created.
if (sweeps[i].nei != 0xff && prevCount[sweeps[i].nei] == sweeps[i].ns) if (sweeps[i].nei != 0xff && prevCount[sweeps[i].nei] == sweeps[i].ns)
{ {
sweeps[i].id = sweeps[i].nei; sweeps[i].id = sweeps[i].nei;
@ -156,6 +176,7 @@ namespace DotRecast.Recast
if (regId == 255) if (regId == 255)
{ {
throw new Exception("rcBuildHeightfieldLayers: Region ID overflow."); throw new Exception("rcBuildHeightfieldLayers: Region ID overflow.");
return false;
} }
sweeps[i].id = regId++; sweeps[i].id = regId++;
@ -174,6 +195,7 @@ namespace DotRecast.Recast
} }
} }
// Allocate and init layer regions.
int nregs = regId; int nregs = regId;
RcLayerRegion[] regs = new RcLayerRegion[nregs]; RcLayerRegion[] regs = new RcLayerRegion[nregs];
@ -216,7 +238,12 @@ namespace DotRecast.Recast
int ai = chf.cells[ax + ay * w].index + GetCon(ref s, dir); int ai = chf.cells[ax + ay * w].index + GetCon(ref s, dir);
int rai = srcReg[ai]; int rai = srcReg[ai];
if (rai != 0xff && rai != ri) if (rai != 0xff && rai != ri)
{
// Don't check return value -- if we cannot add the neighbor
// it will just cause a few more regions to be created, which
// is fine.
AddUnique(regs[ri].neis, rai); AddUnique(regs[ri].neis, rai);
}
} }
} }
} }
@ -287,7 +314,10 @@ namespace DotRecast.Recast
regn.layerId = layerId; regn.layerId = layerId;
// Merge current layers to root. // Merge current layers to root.
foreach (int layer in regn.layers) foreach (int layer in regn.layers)
{
AddUnique(root.layers, layer); AddUnique(root.layers, layer);
}
root.ymin = Math.Min(root.ymin, regn.ymin); root.ymin = Math.Min(root.ymin, regn.ymin);
root.ymax = Math.Max(root.ymax, regn.ymax); root.ymax = Math.Max(root.ymax, regn.ymax);
} }
@ -328,11 +358,9 @@ namespace DotRecast.Recast
if ((ymax - ymin) >= 255) if ((ymax - ymin) >= 255)
continue; continue;
// Make sure that there is no overlap when merging 'ri' and // Make sure that there is no overlap when merging 'ri' and 'rj'.
// 'rj'.
bool overlap = false; bool overlap = false;
// Iterate over all regions which have the same layerId as // Iterate over all regions which have the same layerId as 'rj'
// 'rj'
for (int k = 0; k < nregs; ++k) for (int k = 0; k < nregs; ++k)
{ {
if (regs[k].layerId != rj.layerId) if (regs[k].layerId != rj.layerId)
@ -370,7 +398,10 @@ namespace DotRecast.Recast
rj.layerId = newId; rj.layerId = newId;
// Add overlaid layers from 'rj' to 'ri'. // Add overlaid layers from 'rj' to 'ri'.
foreach (int layer in rj.layers) foreach (int layer in rj.layers)
{
AddUnique(ri.layers, layer); AddUnique(ri.layers, layer);
}
// Update height bounds. // Update height bounds.
ri.ymin = Math.Min(ri.ymin, rj.ymin); ri.ymin = Math.Min(ri.ymin, rj.ymin);
ri.ymax = Math.Max(ri.ymax, rj.ymax); ri.ymax = Math.Max(ri.ymax, rj.ymax);
@ -396,13 +427,14 @@ namespace DotRecast.Recast
// Remap ids. // Remap ids.
for (int i = 0; i < nregs; ++i) for (int i = 0; i < nregs; ++i)
{
regs[i].layerId = remap[regs[i].layerId]; regs[i].layerId = remap[regs[i].layerId];
}
// No layers, return empty. // No layers, return empty.
if (layerId == 0) if (layerId == 0)
{ {
// ctx.Stop(RC_TIMER_BUILD_LAYERS); return true;
return null;
} }
// Create layers. // Create layers.
@ -419,7 +451,7 @@ namespace DotRecast.Recast
bmax.X -= borderSize * chf.cs; bmax.X -= borderSize * chf.cs;
bmax.Z -= borderSize * chf.cs; bmax.Z -= borderSize * chf.cs;
RcHeightfieldLayerSet lset = new RcHeightfieldLayerSet(); lset = new RcHeightfieldLayerSet();
lset.layers = new RcHeightfieldLayer[layerId]; lset.layers = new RcHeightfieldLayer[layerId];
for (int i = 0; i < lset.layers.Length; i++) for (int i = 0; i < lset.layers.Length; i++)
{ {
@ -515,8 +547,7 @@ namespace DotRecast.Recast
if (chf.areas[ai] != RC_NULL_AREA && lid != alid) if (chf.areas[ai] != RC_NULL_AREA && lid != alid)
{ {
portal |= (char)(1 << dir); portal |= (char)(1 << dir);
// Update height so that it matches on both // Update height so that it matches on both sides of the portal.
// sides of the portal.
ref RcCompactSpan @as = ref chf.spans[ai]; ref RcCompactSpan @as = ref chf.spans[ai];
if (@as.y > hmin) if (@as.y > hmin)
layer.heights[idx] = Math.Max(layer.heights[idx], (char)(@as.y - hmin)); layer.heights[idx] = Math.Max(layer.heights[idx], (char)(@as.y - hmin));
@ -544,8 +575,7 @@ namespace DotRecast.Recast
layer.miny = layer.maxy = 0; layer.miny = layer.maxy = 0;
} }
// ctx->StopTimer(RC_TIMER_BUILD_LAYERS); return true;
return lset;
} }
} }
} }