refactor: rename

This commit is contained in:
ikpil 2023-09-22 23:42:21 +09:00
parent 087582c42e
commit 07e6b08517
54 changed files with 589 additions and 639 deletions

View File

@ -63,7 +63,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
{
RecastFilledVolumeRasterization.RasterizeBox(
RcFilledVolumeRasterization.RasterizeBox(
hf, center, halfEdges, area, (int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
}

View File

@ -39,8 +39,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
{
RecastFilledVolumeRasterization.RasterizeCapsule(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
telemetry);
RcFilledVolumeRasterization.RasterizeCapsule(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
}
private static float[] Bounds(RcVec3f start, RcVec3f end, float radius)

View File

@ -44,7 +44,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
{
RecastFilledVolumeRasterization.RasterizeConvex(hf, vertices, triangles, area,
RcFilledVolumeRasterization.RasterizeConvex(hf, vertices, triangles, area,
(int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
}
}

View File

@ -39,7 +39,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
{
RecastFilledVolumeRasterization.RasterizeCylinder(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
RcFilledVolumeRasterization.RasterizeCylinder(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
telemetry);
}

View File

@ -37,7 +37,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
{
RecastFilledVolumeRasterization.RasterizeSphere(hf, center, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
RcFilledVolumeRasterization.RasterizeSphere(hf, center, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
telemetry);
}

View File

@ -62,7 +62,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
{
for (int i = 0; i < triangles.Length; i += 3)
{
RecastRasterization.RasterizeTriangle(hf, vertices, triangles[i], triangles[i + 1], triangles[i + 2], area,
RcRasterizations.RasterizeTriangle(hf, vertices, triangles[i], triangles[i + 1], triangles[i + 2], area,
(int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
}
}

View File

@ -33,7 +33,7 @@ namespace DotRecast.Detour.Dynamic
{
public const int MAX_VERTS_PER_POLY = 6;
public readonly DtDynamicNavMeshConfig config;
private readonly RecastBuilder builder;
private readonly RcBuilder builder;
private readonly Dictionary<long, DtDynamicTile> _tiles = new Dictionary<long, DtDynamicTile>();
private readonly RcTelemetry telemetry;
private readonly DtNavMeshParams navMeshParams;
@ -57,7 +57,7 @@ namespace DotRecast.Detour.Dynamic
config.buildDetailMesh = voxelFile.buildMeshDetail;
config.detailSampleDistance = voxelFile.detailSampleDistance;
config.detailSampleMaxError = voxelFile.detailSampleMaxError;
builder = new RecastBuilder();
builder = new RcBuilder();
navMeshParams = new DtNavMeshParams();
navMeshParams.orig.x = voxelFile.bounds[0];
navMeshParams.orig.y = voxelFile.bounds[1];
@ -254,7 +254,7 @@ namespace DotRecast.Detour.Dynamic
return _tiles.Values.Select(t => t.voxelTile).ToList();
}
public List<RecastBuilderResult> RecastResults()
public List<RcBuilderResult> RecastResults()
{
return _tiles.Values.Select(t => t.recastResult).ToList();
}

View File

@ -33,7 +33,7 @@ namespace DotRecast.Detour.Dynamic
{
public readonly DtVoxelTile voxelTile;
public DtDynamicTileCheckpoint checkpoint;
public RecastBuilderResult recastResult;
public RcBuilderResult recastResult;
private DtMeshData meshData;
private readonly ConcurrentDictionary<long, IDtCollider> colliders = new ConcurrentDictionary<long, IDtCollider>();
private bool dirty = true;
@ -44,12 +44,12 @@ namespace DotRecast.Detour.Dynamic
this.voxelTile = voxelTile;
}
public bool Build(RecastBuilder builder, DtDynamicNavMeshConfig config, RcTelemetry telemetry)
public bool Build(RcBuilder builder, DtDynamicNavMeshConfig config, RcTelemetry telemetry)
{
if (dirty)
{
RcHeightfield heightfield = BuildHeightfield(config, telemetry);
RecastBuilderResult r = BuildRecast(builder, config, voxelTile, heightfield, telemetry);
RcBuilderResult r = BuildRecast(builder, config, voxelTile, heightfield, telemetry);
DtNavMeshCreateParams option = NavMeshCreateParams(voxelTile.tileX, voxelTile.tileZ, voxelTile.cellSize,
voxelTile.cellHeight, config, r);
meshData = DtNavMeshBuilder.CreateNavMeshData(option);
@ -86,7 +86,7 @@ namespace DotRecast.Detour.Dynamic
return heightfield;
}
private RecastBuilderResult BuildRecast(RecastBuilder builder, DtDynamicNavMeshConfig config, DtVoxelTile vt,
private RcBuilderResult BuildRecast(RcBuilder builder, DtDynamicNavMeshConfig config, DtVoxelTile vt,
RcHeightfield heightfield, RcTelemetry telemetry)
{
RcConfig rcConfig = new RcConfig(
@ -100,7 +100,7 @@ namespace DotRecast.Detour.Dynamic
Math.Min(DtDynamicNavMesh.MAX_VERTS_PER_POLY, config.vertsPerPoly),
config.detailSampleDistance, config.detailSampleMaxError,
true, true, true, null, true);
RecastBuilderResult r = builder.Build(vt.tileX, vt.tileZ, null, rcConfig, heightfield, telemetry);
RcBuilderResult r = builder.Build(vt.tileX, vt.tileZ, null, rcConfig, heightfield, telemetry);
if (config.keepIntermediateResults)
{
recastResult = r;
@ -130,7 +130,7 @@ namespace DotRecast.Detour.Dynamic
}
private DtNavMeshCreateParams NavMeshCreateParams(int tilex, int tileZ, float cellSize, float cellHeight,
DtDynamicNavMeshConfig config, RecastBuilderResult rcResult)
DtDynamicNavMeshConfig config, RcBuilderResult rcResult)
{
RcPolyMesh m_pmesh = rcResult.GetMesh();
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();

View File

@ -77,7 +77,7 @@ namespace DotRecast.Detour.Dynamic.Io
walkbableAreaMod, buildMeshDetail);
}
public static DtVoxelFile From(RcConfig config, List<RecastBuilderResult> results)
public static DtVoxelFile From(RcConfig config, List<RcBuilderResult> results)
{
DtVoxelFile f = new DtVoxelFile();
f.version = 1;
@ -106,7 +106,7 @@ namespace DotRecast.Detour.Dynamic.Io
float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity,
float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity
};
foreach (RecastBuilderResult r in results)
foreach (RcBuilderResult r in results)
{
f.tiles.Add(new DtVoxelTile(r.tileX, r.tileZ, r.GetSolidHeightfield()));
f.bounds[0] = Math.Min(f.bounds[0], r.GetSolidHeightfield().bmin.x);

View File

@ -1,7 +1,6 @@
using System;
using DotRecast.Core;
using DotRecast.Recast;
using static DotRecast.Core.RcMath;
namespace DotRecast.Detour.Extras.Jumplink
{
@ -22,7 +21,7 @@ namespace DotRecast.Detour.Extras.Jumplink
}
}
public abstract void Sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es);
public abstract void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es);
protected void SampleGroundSegment(ComputeNavMeshHeight heightFunc, GroundSegment seg, int nsamples)
{

View File

@ -4,6 +4,6 @@ namespace DotRecast.Detour.Extras.Jumplink
{
public interface IGroundSampler
{
void Sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es);
void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es);
}
}

View File

@ -15,9 +15,9 @@ namespace DotRecast.Detour.Extras.Jumplink
private readonly JumpSegmentBuilder jumpSegmentBuilder = new JumpSegmentBuilder();
private readonly List<JumpEdge[]> edges;
private readonly IList<RecastBuilderResult> results;
private readonly IList<RcBuilderResult> results;
public JumpLinkBuilder(IList<RecastBuilderResult> results)
public JumpLinkBuilder(IList<RcBuilderResult> results)
{
this.results = results;
edges = results.Select(r => edgeExtractor.ExtractEdges(r.GetMesh())).ToList();
@ -38,7 +38,7 @@ namespace DotRecast.Detour.Extras.Jumplink
return links;
}
private List<JumpLink> ProcessEdge(JumpLinkBuilderConfig acfg, RecastBuilderResult result, JumpLinkType type, JumpEdge edge)
private List<JumpLink> ProcessEdge(JumpLinkBuilderConfig acfg, RcBuilderResult result, JumpLinkType type, JumpEdge edge)
{
EdgeSampler es = edgeSamplerFactory.Get(acfg, type, edge);
groundSampler.Sample(acfg, result, es);

View File

@ -7,13 +7,13 @@ namespace DotRecast.Detour.Extras.Jumplink
{
class NavMeshGroundSampler : AbstractGroundSampler
{
public override void Sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es)
public override void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es)
{
DtNavMeshQuery navMeshQuery = CreateNavMesh(result, acfg.agentRadius, acfg.agentHeight, acfg.agentClimb);
SampleGround(acfg, es, (RcVec3f pt, float heightRange, out float height) => GetNavMeshHeight(navMeshQuery, pt, acfg.cellSize, heightRange, out height));
}
private DtNavMeshQuery CreateNavMesh(RecastBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
private DtNavMeshQuery CreateNavMesh(RcBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
{
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
option.verts = r.GetMesh().verts;

View File

@ -86,10 +86,10 @@ namespace DotRecast.Detour.TileCache
protected virtual RcHeightfieldLayerSet BuildHeightfieldLayerSet(IInputGeomProvider geom, RcConfig cfg, int tx, int ty)
{
RecastBuilder rcBuilder = new RecastBuilder();
RcBuilder rcBuilder = new RcBuilder();
RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax();
RecastBuilderConfig builderCfg = new RecastBuilderConfig(cfg, bmin, bmax, tx, ty);
RcBuilderConfig builderCfg = new RcBuilderConfig(cfg, bmin, bmax, tx, ty);
RcHeightfieldLayerSet lset = rcBuilder.BuildLayers(geom, builderCfg);
return lset;
}

View File

@ -32,10 +32,10 @@ namespace DotRecast.Recast.Demo
private DtNavMesh _navMesh;
private DtNavMeshQuery _navMeshQuery;
private readonly RcNavMeshBuildSettings _settings;
private IList<RecastBuilderResult> _recastResults;
private IList<RcBuilderResult> _recastResults;
private bool _changed;
public DemoSample(DemoInputGeomProvider geom, IList<RecastBuilderResult> recastResults, DtNavMesh navMesh)
public DemoSample(DemoInputGeomProvider geom, IList<RcBuilderResult> recastResults, DtNavMesh navMesh)
{
_geom = geom;
_recastResults = recastResults;
@ -56,7 +56,7 @@ namespace DotRecast.Recast.Demo
return _geom;
}
public IList<RecastBuilderResult> GetRecastResults()
public IList<RcBuilderResult> GetRecastResults()
{
return _recastResults;
}
@ -86,7 +86,7 @@ namespace DotRecast.Recast.Demo
_changed = changed;
}
public void Update(DemoInputGeomProvider geom, IList<RecastBuilderResult> recastResults, DtNavMesh navMesh)
public void Update(DemoInputGeomProvider geom, IList<RcBuilderResult> recastResults, DtNavMesh navMesh)
{
_geom = geom;
_recastResults = recastResults;

View File

@ -23,6 +23,7 @@ using DotRecast.Core;
using DotRecast.Detour;
using DotRecast.Recast.Toolset.Builder;
using DotRecast.Recast.Toolset.Geom;
using static DotRecast.Recast.RcCommons;
namespace DotRecast.Recast.Demo.Draw;
@ -50,7 +51,7 @@ public class NavMeshRenderer
DtNavMeshQuery navQuery = sample.GetNavMeshQuery();
DemoInputGeomProvider geom = sample.GetInputGeom();
IList<RecastBuilderResult> rcBuilderResults = sample.GetRecastResults();
IList<RcBuilderResult> rcBuilderResults = sample.GetRecastResults();
DtNavMesh navMesh = sample.GetNavMesh();
var settings = sample.GetSettings();
_debugDraw.Fog(true);
@ -81,7 +82,7 @@ public class NavMeshRenderer
int gw = 0, gh = 0;
RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax();
RcUtils.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
int tw = (gw + settings.tileSize - 1) / settings.tileSize;
int th = (gh + settings.tileSize - 1) / settings.tileSize;
float s = settings.tileSize * settings.cellSize;
@ -120,7 +121,7 @@ public class NavMeshRenderer
_debugDraw.DepthMask(true);
foreach (RecastBuilderResult rcBuilderResult in rcBuilderResults)
foreach (RcBuilderResult rcBuilderResult in rcBuilderResults)
{
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT)
{

View File

@ -324,7 +324,7 @@ public class RecastDemo : IRecastDemoChannel
if (null != mesh)
{
_sample.Update(_sample.GetInputGeom(), ImmutableArray<RecastBuilderResult>.Empty, mesh);
_sample.Update(_sample.GetInputGeom(), ImmutableArray<RcBuilderResult>.Empty, mesh);
toolset.SetEnabled(true);
}
}
@ -375,7 +375,7 @@ public class RecastDemo : IRecastDemoChannel
_imgui = new ImGuiController(_gl, window, _input, imGuiFontConfig);
DemoInputGeomProvider geom = LoadInputMesh("nav_test.obj");
_sample = new DemoSample(geom, ImmutableArray<RecastBuilderResult>.Empty, null);
_sample = new DemoSample(geom, ImmutableArray<RcBuilderResult>.Empty, null);
settingsView = new RcSettingsView(this);
settingsView.SetSample(_sample);
@ -454,7 +454,7 @@ public class RecastDemo : IRecastDemoChannel
var settings = _sample.GetSettings();
RcVec3f bmin = _sample.GetInputGeom().GetMeshBoundsMin();
RcVec3f bmax = _sample.GetInputGeom().GetMeshBoundsMax();
RcUtils.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh);
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh);
settingsView.SetVoxels(gw, gh);
settingsView.SetTiles(tileNavMeshBuilder.GetTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
settingsView.SetMaxTiles(tileNavMeshBuilder.GetMaxTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
@ -542,7 +542,7 @@ public class RecastDemo : IRecastDemoChannel
}
else if (0 < _sample.GetRecastResults().Count)
{
foreach (RecastBuilderResult result in _sample.GetRecastResults())
foreach (RcBuilderResult result in _sample.GetRecastResults())
{
if (result.GetSolidHeightfield() != null)
{
@ -662,7 +662,7 @@ public class RecastDemo : IRecastDemoChannel
{
var geom = LoadInputMesh(args.FilePath);
_sample.Update(geom, ImmutableArray<RecastBuilderResult>.Empty, null);
_sample.Update(geom, ImmutableArray<RcBuilderResult>.Empty, null);
}
private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args)

View File

@ -8,7 +8,7 @@ namespace DotRecast.Recast.Toolset.Builder
{
public static DtNavMeshCreateParams GetNavMeshCreateParams(IInputGeomProvider geom, float cellSize,
float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
RecastBuilderResult rcResult)
RcBuilderResult rcResult)
{
RcPolyMesh pmesh = rcResult.GetMesh();
RcPolyMeshDetail dmesh = rcResult.GetMeshDetail();

View File

@ -7,17 +7,17 @@ namespace DotRecast.Recast.Toolset.Builder
public class NavMeshBuildResult
{
public readonly bool Success;
public readonly IList<RecastBuilderResult> RecastBuilderResults;
public readonly IList<RcBuilderResult> RecastBuilderResults;
public readonly DtNavMesh NavMesh;
public NavMeshBuildResult()
{
Success = false;
RecastBuilderResults = Array.Empty<RecastBuilderResult>();
RecastBuilderResults = Array.Empty<RcBuilderResult>();
NavMesh = null;
}
public NavMeshBuildResult(IList<RecastBuilderResult> recastBuilderResults, DtNavMesh navMesh)
public NavMeshBuildResult(IList<RcBuilderResult> recastBuilderResults, DtNavMesh navMesh)
{
Success = true;
RecastBuilderResults = recastBuilderResults;

View File

@ -60,7 +60,7 @@ namespace DotRecast.Recast.Toolset.Builder
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
RecastBuilderResult rcResult = BuildRecastResult(geom, cfg);
RcBuilderResult rcResult = BuildRecastResult(geom, cfg);
var meshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult);
if (null == meshData)
{
@ -76,17 +76,17 @@ namespace DotRecast.Recast.Toolset.Builder
return new DtNavMesh(meshData, vertsPerPoly, 0);
}
private RecastBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg)
private RcBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg)
{
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
RecastBuilder rcBuilder = new RecastBuilder();
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
RcBuilder rcBuilder = new RcBuilder();
return rcBuilder.Build(geom, bcfg);
}
public DtMeshData BuildMeshData(DemoInputGeomProvider geom,
float cellSize, float cellHeight,
float agentHeight, float agentRadius, float agentMaxClimb,
RecastBuilderResult result)
RcBuilderResult result)
{
DtNavMeshCreateParams option = DemoNavMeshBuilder
.GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result);

View File

@ -55,7 +55,7 @@ namespace DotRecast.Recast.Toolset.Builder
float detailSampleDist, float detailSampleMaxError,
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
{
List<RecastBuilderResult> results = BuildRecastResult(
List<RcBuilderResult> results = BuildRecastResult(
geom,
tileSize,
partitionType,
@ -73,7 +73,7 @@ namespace DotRecast.Recast.Toolset.Builder
return new NavMeshBuildResult(results, tileNavMesh);
}
public List<RecastBuilderResult> BuildRecastResult(IInputGeomProvider geom,
public List<RcBuilderResult> BuildRecastResult(IInputGeomProvider geom,
int tileSize,
RcPartition partitionType,
float cellSize, float cellHeight,
@ -96,7 +96,7 @@ namespace DotRecast.Recast.Toolset.Builder
detailSampleDist, detailSampleMaxError,
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
RecastBuilder rcBuilder = new RecastBuilder();
RcBuilder rcBuilder = new RcBuilder();
return rcBuilder.BuildTiles(geom, cfg, Task.Factory);
}
@ -117,11 +117,11 @@ namespace DotRecast.Recast.Toolset.Builder
}
public List<DtMeshData> BuildMeshData(IInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight,
float agentRadius, float agentMaxClimb, IList<RecastBuilderResult> results)
float agentRadius, float agentMaxClimb, IList<RcBuilderResult> results)
{
// Add tiles to nav mesh
List<DtMeshData> meshData = new List<DtMeshData>();
foreach (RecastBuilderResult result in results)
foreach (RcBuilderResult result in results)
{
int x = result.tileX;
int z = result.tileZ;
@ -155,7 +155,7 @@ namespace DotRecast.Recast.Toolset.Builder
private int GetTileBits(IInputGeomProvider geom, float cellSize, int tileSize)
{
RcUtils.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
RcCommons.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
int tw = (gw + tileSize - 1) / tileSize;
int th = (gh + tileSize - 1) / tileSize;
int tileBits = Math.Min(DtUtils.Ilog2(DtUtils.NextPow2(tw * th)), 14);
@ -164,7 +164,7 @@ namespace DotRecast.Recast.Toolset.Builder
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
{
RcUtils.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
RcCommons.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
int tw = (gw + tileSize - 1) / tileSize;
int th = (gh + tileSize - 1) / tileSize;
return new int[] { tw, th };

View File

@ -80,7 +80,7 @@ namespace DotRecast.Recast.Toolset.Tools
IList<RcConvexVolume> vols = geom.ConvexVolumes();
for (int i = 0; i < vols.Count; ++i)
{
if (PolyUtils.PointInPoly(vols[i].verts, pos) && pos.y >= vols[i].hmin
if (RcAreas.PointInPoly(vols[i].verts, pos) && pos.y >= vols[i].hmin
&& pos.y <= vols[i].hmax)
{
nearestIndex = i;
@ -130,7 +130,7 @@ namespace DotRecast.Recast.Toolset.Tools
if (polyOffset > 0.01f)
{
float[] offset = new float[verts.Length * 2];
int noffset = PolyUtils.OffsetPoly(verts, hull.Count, polyOffset, offset, offset.Length);
int noffset = RcAreas.OffsetPoly(verts, hull.Count, polyOffset, offset, offset.Length);
if (noffset > 0)
{
verts = RcArrayUtils.CopyOf(offset, 0, noffset * 3);

View File

@ -44,7 +44,7 @@ namespace DotRecast.Recast.Toolset.Tools
return _links;
}
public void Build(IInputGeomProvider geom, RcNavMeshBuildSettings settings, IList<RecastBuilderResult> results, RcJumpLinkBuilderToolConfig cfg)
public void Build(IInputGeomProvider geom, RcNavMeshBuildSettings settings, IList<RcBuilderResult> results, RcJumpLinkBuilderToolConfig cfg)
{
if (_annotationBuilder == null)
{

View File

@ -41,7 +41,7 @@ namespace DotRecast.Recast.Toolset.Tools
// Init cache
var bmin = geom.GetMeshBoundsMin();
var bmax = geom.GetMeshBoundsMax();
RcUtils.CalcGridSize(bmin, bmax, setting.cellSize, out var gw, out var gh);
RcCommons.CalcGridSize(bmin, bmax, setting.cellSize, out var gw, out var gh);
int ts = setting.tileSize;
int tw = (gw + ts - 1) / ts;
int th = (gh + ts - 1) / ts;
@ -77,7 +77,7 @@ namespace DotRecast.Recast.Toolset.Tools
_tc.BuildNavMeshTile(refs);
}
return new NavMeshBuildResult(RcImmutableArray<RecastBuilderResult>.Empty, _tc.GetNavMesh());
return new NavMeshBuildResult(RcImmutableArray<RcBuilderResult>.Empty, _tc.GetNavMesh());
}
public void ClearAllTempObstacles()

View File

@ -21,7 +21,7 @@ namespace DotRecast.Recast.Toolset.Tools
var bmin = geom.GetMeshBoundsMin();
var bmax = geom.GetMeshBoundsMax();
int gw = 0, gh = 0;
RcUtils.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
int ts = settings.tileSize;
int tw = (gw + ts - 1) / ts;
@ -45,7 +45,7 @@ namespace DotRecast.Recast.Toolset.Tools
var bmin = geom.GetMeshBoundsMin();
var bmax = geom.GetMeshBoundsMax();
int gw = 0, gh = 0;
RcUtils.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
int ts = settings.tileSize;
int tw = (gw + ts - 1) / ts;
@ -91,7 +91,7 @@ namespace DotRecast.Recast.Toolset.Tools
);
var beginTick = RcFrequency.Ticks;
var rb = new RecastBuilder();
var rb = new RcBuilder();
var result = rb.BuildTile(geom, cfg, bmin, bmax, tx, ty, new RcAtomicInteger(0), 1);
var tb = new TileNavMeshBuilder();

View File

@ -1,187 +0,0 @@
/*
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
using System;
using DotRecast.Core;
namespace DotRecast.Recast
{
public static class PolyUtils
{
// public static bool PointInPoly(float[] verts, RcVec3f p)
// {
// bool c = false;
// int i, j;
// for (i = 0, j = verts.Length - 3; i < verts.Length; j = i, i += 3)
// {
// int vi = i;
// int vj = j;
// if (((verts[vi + 2] > p.z) != (verts[vj + 2] > p.z))
// && (p.x < (verts[vj] - verts[vi]) * (p.z - verts[vi + 2]) / (verts[vj + 2] - verts[vi + 2])
// + verts[vi]))
// c = !c;
// }
//
// return c;
// }
// TODO (graham): This is duplicated in the ConvexVolumeTool in RecastDemo
/// Checks if a point is contained within a polygon
///
/// @param[in] numVerts Number of vertices in the polygon
/// @param[in] verts The polygon vertices
/// @param[in] point The point to check
/// @returns true if the point lies within the polygon, false otherwise.
public static bool PointInPoly(float[] verts, RcVec3f point)
{
bool inPoly = false;
for (int i = 0, j = verts.Length / 3 - 1; i < verts.Length / 3; j = i++)
{
RcVec3f vi = RcVec3f.Of(verts[i * 3], verts[i * 3 + 1], verts[i * 3 + 2]);
RcVec3f vj = RcVec3f.Of(verts[j * 3], verts[j * 3 + 1], verts[j * 3 + 2]);
if (vi.z > point.z == vj.z > point.z)
{
continue;
}
if (point.x >= (vj.x - vi.x) * (point.z - vi.z) / (vj.z - vi.z) + vi.x)
{
continue;
}
inPoly = !inPoly;
}
return inPoly;
}
/// Expands a convex polygon along its vertex normals by the given offset amount.
/// Inserts extra vertices to bevel sharp corners.
///
/// Helper function to offset convex polygons for rcMarkConvexPolyArea.
///
/// @ingroup recast
///
/// @param[in] verts The vertices of the polygon [Form: (x, y, z) * @p numVerts]
/// @param[in] numVerts The number of vertices in the polygon.
/// @param[in] offset How much to offset the polygon by. [Units: wu]
/// @param[out] outVerts The offset vertices (should hold up to 2 * @p numVerts) [Form: (x, y, z) * return value]
/// @param[in] maxOutVerts The max number of vertices that can be stored to @p outVerts.
/// @returns Number of vertices in the offset polygon or 0 if too few vertices in @p outVerts.
public static int OffsetPoly(float[] verts, int numVerts, float offset, float[] outVerts, int maxOutVerts)
{
// Defines the limit at which a miter becomes a bevel.
// Similar in behavior to https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit
const float MITER_LIMIT = 1.20f;
int numOutVerts = 0;
for (int vertIndex = 0; vertIndex < numVerts; vertIndex++)
{
int vertIndexA = (vertIndex + numVerts - 1) % numVerts;
int vertIndexB = vertIndex;
int vertIndexC = (vertIndex + 1) % numVerts;
RcVec3f vertA = RcVec3f.Of(verts, vertIndexA * 3);
RcVec3f vertB = RcVec3f.Of(verts, vertIndexB * 3);
RcVec3f vertC = RcVec3f.Of(verts, vertIndexC * 3);
// From A to B on the x/z plane
RcVec3f prevSegmentDir = vertB.Subtract(vertA);
prevSegmentDir.y = 0; // Squash onto x/z plane
prevSegmentDir.SafeNormalize();
// From B to C on the x/z plane
RcVec3f currSegmentDir = vertC.Subtract(vertB);
currSegmentDir.y = 0; // Squash onto x/z plane
currSegmentDir.SafeNormalize();
// The y component of the cross product of the two normalized segment directions.
// The X and Z components of the cross product are both zero because the two
// segment direction vectors fall within the x/z plane.
float cross = currSegmentDir.x * prevSegmentDir.z - prevSegmentDir.x * currSegmentDir.z;
// CCW perpendicular vector to AB. The segment normal.
float prevSegmentNormX = -prevSegmentDir.z;
float prevSegmentNormZ = prevSegmentDir.x;
// CCW perpendicular vector to BC. The segment normal.
float currSegmentNormX = -currSegmentDir.z;
float currSegmentNormZ = currSegmentDir.x;
// Average the two segment normals to get the proportional miter offset for B.
// This isn't normalized because it's defining the distance and direction the corner will need to be
// adjusted proportionally to the edge offsets to properly miter the adjoining edges.
float cornerMiterX = (prevSegmentNormX + currSegmentNormX) * 0.5f;
float cornerMiterZ = (prevSegmentNormZ + currSegmentNormZ) * 0.5f;
float cornerMiterSqMag = RcMath.Sqr(cornerMiterX) + RcMath.Sqr(cornerMiterZ);
// If the magnitude of the segment normal average is less than about .69444,
// the corner is an acute enough angle that the result should be beveled.
bool bevel = cornerMiterSqMag * MITER_LIMIT * MITER_LIMIT < 1.0f;
// Scale the corner miter so it's proportional to how much the corner should be offset compared to the edges.
if (cornerMiterSqMag > RcVec3f.EPSILON)
{
float scale = 1.0f / cornerMiterSqMag;
cornerMiterX *= scale;
cornerMiterZ *= scale;
}
if (bevel && cross < 0.0f) // If the corner is convex and an acute enough angle, generate a bevel.
{
if (numOutVerts + 2 > maxOutVerts)
{
return 0;
}
// Generate two bevel vertices at a distances from B proportional to the angle between the two segments.
// Move each bevel vertex out proportional to the given offset.
float d = (1.0f - (prevSegmentDir.x * currSegmentDir.x + prevSegmentDir.z * currSegmentDir.z)) * 0.5f;
outVerts[numOutVerts * 3 + 0] = vertB.x + (-prevSegmentNormX + prevSegmentDir.x * d) * offset;
outVerts[numOutVerts * 3 + 1] = vertB.y;
outVerts[numOutVerts * 3 + 2] = vertB.z + (-prevSegmentNormZ + prevSegmentDir.z * d) * offset;
numOutVerts++;
outVerts[numOutVerts * 3 + 0] = vertB.x + (-currSegmentNormX - currSegmentDir.x * d) * offset;
outVerts[numOutVerts * 3 + 1] = vertB.y;
outVerts[numOutVerts * 3 + 2] = vertB.z + (-currSegmentNormZ - currSegmentDir.z * d) * offset;
numOutVerts++;
}
else
{
if (numOutVerts + 1 > maxOutVerts)
{
return 0;
}
// Move B along the miter direction by the specified offset.
outVerts[numOutVerts * 3 + 0] = vertB.x - cornerMiterX * offset;
outVerts[numOutVerts * 3 + 1] = vertB.y;
outVerts[numOutVerts * 3 + 2] = vertB.z - cornerMiterZ * offset;
numOutVerts++;
}
}
return numOutVerts;
}
}
}

View File

@ -24,8 +24,9 @@ using DotRecast.Core;
namespace DotRecast.Recast
{
using static RcConstants;
using static RcCommons;
public static class RecastArea
public static class RcAreas
{
/// Erodes the walkable area within the heightfield by the specified radius.
///
@ -72,15 +73,15 @@ namespace DotRecast.Recast
int neighborCount = 0;
for (int direction = 0; direction < 4; ++direction)
{
int neighborConnection = RecastCommon.GetCon(span, direction);
int neighborConnection = GetCon(span, direction);
if (neighborConnection == RC_NOT_CONNECTED)
{
break;
}
int neighborX = x + RecastCommon.GetDirOffsetX(direction);
int neighborZ = z + RecastCommon.GetDirOffsetY(direction);
int neighborSpanIndex = compactHeightfield.cells[neighborX + neighborZ * zStride].index + RecastCommon.GetCon(span, direction);
int neighborX = x + GetDirOffsetX(direction);
int neighborZ = z + GetDirOffsetY(direction);
int neighborSpanIndex = compactHeightfield.cells[neighborX + neighborZ * zStride].index + GetCon(span, direction);
if (compactHeightfield.areas[neighborSpanIndex] == RC_NULL_AREA)
{
break;
@ -112,12 +113,12 @@ namespace DotRecast.Recast
{
RcCompactSpan span = compactHeightfield.spans[spanIndex];
if (RecastCommon.GetCon(span, 0) != RC_NOT_CONNECTED)
if (GetCon(span, 0) != RC_NOT_CONNECTED)
{
// (-1,0)
int aX = x + RecastCommon.GetDirOffsetX(0);
int aY = z + RecastCommon.GetDirOffsetY(0);
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + RecastCommon.GetCon(span, 0);
int aX = x + GetDirOffsetX(0);
int aY = z + GetDirOffsetY(0);
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + GetCon(span, 0);
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
if (newDistance < distanceToBoundary[spanIndex])
@ -126,11 +127,11 @@ namespace DotRecast.Recast
}
// (-1,-1)
if (RecastCommon.GetCon(aSpan, 3) != RC_NOT_CONNECTED)
if (GetCon(aSpan, 3) != RC_NOT_CONNECTED)
{
int bX = aX + RecastCommon.GetDirOffsetX(3);
int bY = aY + RecastCommon.GetDirOffsetY(3);
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + RecastCommon.GetCon(aSpan, 3);
int bX = aX + GetDirOffsetX(3);
int bY = aY + GetDirOffsetY(3);
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + GetCon(aSpan, 3);
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
if (newDistance < distanceToBoundary[spanIndex])
{
@ -139,12 +140,12 @@ namespace DotRecast.Recast
}
}
if (RecastCommon.GetCon(span, 3) != RC_NOT_CONNECTED)
if (GetCon(span, 3) != RC_NOT_CONNECTED)
{
// (0,-1)
int aX = x + RecastCommon.GetDirOffsetX(3);
int aY = z + RecastCommon.GetDirOffsetY(3);
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + RecastCommon.GetCon(span, 3);
int aX = x + GetDirOffsetX(3);
int aY = z + GetDirOffsetY(3);
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + GetCon(span, 3);
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
if (newDistance < distanceToBoundary[spanIndex])
@ -153,11 +154,11 @@ namespace DotRecast.Recast
}
// (1,-1)
if (RecastCommon.GetCon(aSpan, 2) != RC_NOT_CONNECTED)
if (GetCon(aSpan, 2) != RC_NOT_CONNECTED)
{
int bX = aX + RecastCommon.GetDirOffsetX(2);
int bY = aY + RecastCommon.GetDirOffsetY(2);
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + RecastCommon.GetCon(aSpan, 2);
int bX = aX + GetDirOffsetX(2);
int bY = aY + GetDirOffsetY(2);
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + GetCon(aSpan, 2);
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
if (newDistance < distanceToBoundary[spanIndex])
{
@ -180,12 +181,12 @@ namespace DotRecast.Recast
{
RcCompactSpan span = compactHeightfield.spans[i];
if (RecastCommon.GetCon(span, 2) != RC_NOT_CONNECTED)
if (GetCon(span, 2) != RC_NOT_CONNECTED)
{
// (1,0)
int aX = x + RecastCommon.GetDirOffsetX(2);
int aY = z + RecastCommon.GetDirOffsetY(2);
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + RecastCommon.GetCon(span, 2);
int aX = x + GetDirOffsetX(2);
int aY = z + GetDirOffsetY(2);
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + GetCon(span, 2);
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
if (newDistance < distanceToBoundary[i])
@ -194,11 +195,11 @@ namespace DotRecast.Recast
}
// (1,1)
if (RecastCommon.GetCon(aSpan, 1) != RC_NOT_CONNECTED)
if (GetCon(aSpan, 1) != RC_NOT_CONNECTED)
{
int bX = aX + RecastCommon.GetDirOffsetX(1);
int bY = aY + RecastCommon.GetDirOffsetY(1);
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + RecastCommon.GetCon(aSpan, 1);
int bX = aX + GetDirOffsetX(1);
int bY = aY + GetDirOffsetY(1);
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + GetCon(aSpan, 1);
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
if (newDistance < distanceToBoundary[i])
{
@ -207,12 +208,12 @@ namespace DotRecast.Recast
}
}
if (RecastCommon.GetCon(span, 1) != RC_NOT_CONNECTED)
if (GetCon(span, 1) != RC_NOT_CONNECTED)
{
// (0,1)
int aX = x + RecastCommon.GetDirOffsetX(1);
int aY = z + RecastCommon.GetDirOffsetY(1);
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + RecastCommon.GetCon(span, 1);
int aX = x + GetDirOffsetX(1);
int aY = z + GetDirOffsetY(1);
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + GetCon(span, 1);
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
if (newDistance < distanceToBoundary[i])
@ -221,11 +222,11 @@ namespace DotRecast.Recast
}
// (-1,1)
if (RecastCommon.GetCon(aSpan, 0) != RC_NOT_CONNECTED)
if (GetCon(aSpan, 0) != RC_NOT_CONNECTED)
{
int bX = aX + RecastCommon.GetDirOffsetX(0);
int bY = aY + RecastCommon.GetDirOffsetY(0);
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + RecastCommon.GetCon(aSpan, 0);
int bX = aX + GetDirOffsetX(0);
int bY = aY + GetDirOffsetY(0);
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + GetCon(aSpan, 0);
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
if (newDistance < distanceToBoundary[i])
{
@ -291,14 +292,14 @@ namespace DotRecast.Recast
for (int dir = 0; dir < 4; ++dir)
{
if (RecastCommon.GetCon(span, dir) == RC_NOT_CONNECTED)
if (GetCon(span, dir) == RC_NOT_CONNECTED)
{
continue;
}
int aX = x + RecastCommon.GetDirOffsetX(dir);
int aZ = z + RecastCommon.GetDirOffsetY(dir);
int aIndex = compactHeightfield.cells[aX + aZ * zStride].index + RecastCommon.GetCon(span, dir);
int aX = x + GetDirOffsetX(dir);
int aZ = z + GetDirOffsetY(dir);
int aIndex = compactHeightfield.cells[aX + aZ * zStride].index + GetCon(span, dir);
if (compactHeightfield.areas[aIndex] != RC_NULL_AREA)
{
neighborAreas[dir * 2 + 0] = compactHeightfield.areas[aIndex];
@ -306,12 +307,12 @@ namespace DotRecast.Recast
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
int dir2 = (dir + 1) & 0x3;
int neighborConnection2 = RecastCommon.GetCon(aSpan, dir2);
int neighborConnection2 = GetCon(aSpan, dir2);
if (neighborConnection2 != RC_NOT_CONNECTED)
{
int bX = aX + RecastCommon.GetDirOffsetX(dir2);
int bZ = aZ + RecastCommon.GetDirOffsetY(dir2);
int bIndex = compactHeightfield.cells[bX + bZ * zStride].index + RecastCommon.GetCon(aSpan, dir2);
int bX = aX + GetDirOffsetX(dir2);
int bZ = aZ + GetDirOffsetY(dir2);
int bIndex = compactHeightfield.cells[bX + bZ * zStride].index + GetCon(aSpan, dir2);
if (compactHeightfield.areas[bIndex] != RC_NULL_AREA)
{
neighborAreas[dir * 2 + 1] = compactHeightfield.areas[bIndex];
@ -544,7 +545,7 @@ namespace DotRecast.Recast
compactHeightfield.bmin.z + (z + 0.5f) * compactHeightfield.cs
);
if (PolyUtils.PointInPoly(verts, point))
if (PointInPoly(verts, point))
{
compactHeightfield.areas[spanIndex] = areaId.Apply(compactHeightfield.areas[spanIndex]);
}
@ -677,5 +678,164 @@ namespace DotRecast.Recast
}
}
}
// public static bool PointInPoly(float[] verts, RcVec3f p)
// {
// bool c = false;
// int i, j;
// for (i = 0, j = verts.Length - 3; i < verts.Length; j = i, i += 3)
// {
// int vi = i;
// int vj = j;
// if (((verts[vi + 2] > p.z) != (verts[vj + 2] > p.z))
// && (p.x < (verts[vj] - verts[vi]) * (p.z - verts[vi + 2]) / (verts[vj + 2] - verts[vi + 2])
// + verts[vi]))
// c = !c;
// }
//
// return c;
// }
// TODO (graham): This is duplicated in the ConvexVolumeTool in RecastDemo
/// Checks if a point is contained within a polygon
///
/// @param[in] numVerts Number of vertices in the polygon
/// @param[in] verts The polygon vertices
/// @param[in] point The point to check
/// @returns true if the point lies within the polygon, false otherwise.
public static bool PointInPoly(float[] verts, RcVec3f point)
{
bool inPoly = false;
for (int i = 0, j = verts.Length / 3 - 1; i < verts.Length / 3; j = i++)
{
RcVec3f vi = RcVec3f.Of(verts[i * 3], verts[i * 3 + 1], verts[i * 3 + 2]);
RcVec3f vj = RcVec3f.Of(verts[j * 3], verts[j * 3 + 1], verts[j * 3 + 2]);
if (vi.z > point.z == vj.z > point.z)
{
continue;
}
if (point.x >= (vj.x - vi.x) * (point.z - vi.z) / (vj.z - vi.z) + vi.x)
{
continue;
}
inPoly = !inPoly;
}
return inPoly;
}
/// Expands a convex polygon along its vertex normals by the given offset amount.
/// Inserts extra vertices to bevel sharp corners.
///
/// Helper function to offset convex polygons for rcMarkConvexPolyArea.
///
/// @ingroup recast
///
/// @param[in] verts The vertices of the polygon [Form: (x, y, z) * @p numVerts]
/// @param[in] numVerts The number of vertices in the polygon.
/// @param[in] offset How much to offset the polygon by. [Units: wu]
/// @param[out] outVerts The offset vertices (should hold up to 2 * @p numVerts) [Form: (x, y, z) * return value]
/// @param[in] maxOutVerts The max number of vertices that can be stored to @p outVerts.
/// @returns Number of vertices in the offset polygon or 0 if too few vertices in @p outVerts.
public static int OffsetPoly(float[] verts, int numVerts, float offset, float[] outVerts, int maxOutVerts)
{
// Defines the limit at which a miter becomes a bevel.
// Similar in behavior to https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit
const float MITER_LIMIT = 1.20f;
int numOutVerts = 0;
for (int vertIndex = 0; vertIndex < numVerts; vertIndex++)
{
int vertIndexA = (vertIndex + numVerts - 1) % numVerts;
int vertIndexB = vertIndex;
int vertIndexC = (vertIndex + 1) % numVerts;
RcVec3f vertA = RcVec3f.Of(verts, vertIndexA * 3);
RcVec3f vertB = RcVec3f.Of(verts, vertIndexB * 3);
RcVec3f vertC = RcVec3f.Of(verts, vertIndexC * 3);
// From A to B on the x/z plane
RcVec3f prevSegmentDir = vertB.Subtract(vertA);
prevSegmentDir.y = 0; // Squash onto x/z plane
prevSegmentDir.SafeNormalize();
// From B to C on the x/z plane
RcVec3f currSegmentDir = vertC.Subtract(vertB);
currSegmentDir.y = 0; // Squash onto x/z plane
currSegmentDir.SafeNormalize();
// The y component of the cross product of the two normalized segment directions.
// The X and Z components of the cross product are both zero because the two
// segment direction vectors fall within the x/z plane.
float cross = currSegmentDir.x * prevSegmentDir.z - prevSegmentDir.x * currSegmentDir.z;
// CCW perpendicular vector to AB. The segment normal.
float prevSegmentNormX = -prevSegmentDir.z;
float prevSegmentNormZ = prevSegmentDir.x;
// CCW perpendicular vector to BC. The segment normal.
float currSegmentNormX = -currSegmentDir.z;
float currSegmentNormZ = currSegmentDir.x;
// Average the two segment normals to get the proportional miter offset for B.
// This isn't normalized because it's defining the distance and direction the corner will need to be
// adjusted proportionally to the edge offsets to properly miter the adjoining edges.
float cornerMiterX = (prevSegmentNormX + currSegmentNormX) * 0.5f;
float cornerMiterZ = (prevSegmentNormZ + currSegmentNormZ) * 0.5f;
float cornerMiterSqMag = RcMath.Sqr(cornerMiterX) + RcMath.Sqr(cornerMiterZ);
// If the magnitude of the segment normal average is less than about .69444,
// the corner is an acute enough angle that the result should be beveled.
bool bevel = cornerMiterSqMag * MITER_LIMIT * MITER_LIMIT < 1.0f;
// Scale the corner miter so it's proportional to how much the corner should be offset compared to the edges.
if (cornerMiterSqMag > RcVec3f.EPSILON)
{
float scale = 1.0f / cornerMiterSqMag;
cornerMiterX *= scale;
cornerMiterZ *= scale;
}
if (bevel && cross < 0.0f) // If the corner is convex and an acute enough angle, generate a bevel.
{
if (numOutVerts + 2 > maxOutVerts)
{
return 0;
}
// Generate two bevel vertices at a distances from B proportional to the angle between the two segments.
// Move each bevel vertex out proportional to the given offset.
float d = (1.0f - (prevSegmentDir.x * currSegmentDir.x + prevSegmentDir.z * currSegmentDir.z)) * 0.5f;
outVerts[numOutVerts * 3 + 0] = vertB.x + (-prevSegmentNormX + prevSegmentDir.x * d) * offset;
outVerts[numOutVerts * 3 + 1] = vertB.y;
outVerts[numOutVerts * 3 + 2] = vertB.z + (-prevSegmentNormZ + prevSegmentDir.z * d) * offset;
numOutVerts++;
outVerts[numOutVerts * 3 + 0] = vertB.x + (-currSegmentNormX - currSegmentDir.x * d) * offset;
outVerts[numOutVerts * 3 + 1] = vertB.y;
outVerts[numOutVerts * 3 + 2] = vertB.z + (-currSegmentNormZ - currSegmentDir.z * d) * offset;
numOutVerts++;
}
else
{
if (numOutVerts + 1 > maxOutVerts)
{
return 0;
}
// Move B along the miter direction by the specified offset.
outVerts[numOutVerts * 3 + 0] = vertB.x - cornerMiterX * offset;
outVerts[numOutVerts * 3 + 1] = vertB.y;
outVerts[numOutVerts * 3 + 2] = vertB.z - cornerMiterZ * offset;
numOutVerts++;
}
}
return numOutVerts;
}
}
}

View File

@ -27,26 +27,29 @@ using DotRecast.Recast.Geom;
namespace DotRecast.Recast
{
public class RecastBuilder
using static RcCommons;
using static RcAreas;
public class RcBuilder
{
private readonly IRecastBuilderProgressListener progressListener;
public RecastBuilder()
public RcBuilder()
{
progressListener = null;
}
public RecastBuilder(IRecastBuilderProgressListener progressListener)
public RcBuilder(IRecastBuilderProgressListener progressListener)
{
this.progressListener = progressListener;
}
public List<RecastBuilderResult> BuildTiles(IInputGeomProvider geom, RcConfig cfg, TaskFactory taskFactory)
public List<RcBuilderResult> BuildTiles(IInputGeomProvider geom, RcConfig cfg, TaskFactory taskFactory)
{
RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax();
RcUtils.CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
List<RecastBuilderResult> results = new List<RecastBuilderResult>();
CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
List<RcBuilderResult> results = new List<RcBuilderResult>();
if (null != taskFactory)
{
BuildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, default);
@ -60,11 +63,11 @@ namespace DotRecast.Recast
}
public Task BuildTilesAsync(IInputGeomProvider geom, RcConfig cfg, int threads, List<RecastBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
public Task BuildTilesAsync(IInputGeomProvider geom, RcConfig cfg, int threads, List<RcBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
{
RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax();
RcUtils.CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
Task task;
if (1 < threads)
{
@ -79,7 +82,7 @@ namespace DotRecast.Recast
}
private Task BuildSingleThreadAsync(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax,
int tw, int th, List<RecastBuilderResult> results)
int tw, int th, List<RcBuilderResult> results)
{
RcAtomicInteger counter = new RcAtomicInteger(0);
for (int y = 0; y < th; ++y)
@ -94,7 +97,7 @@ namespace DotRecast.Recast
}
private Task BuildMultiThreadAsync(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax,
int tw, int th, List<RecastBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
int tw, int th, List<RcBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
{
RcAtomicInteger counter = new RcAtomicInteger(0);
CountdownEvent latch = new CountdownEvent(tw * th);
@ -113,7 +116,7 @@ namespace DotRecast.Recast
try
{
RecastBuilderResult tile = BuildTile(geom, cfg, bmin, bmax, tx, ty, counter, tw * th);
RcBuilderResult tile = BuildTile(geom, cfg, bmin, bmax, tx, ty, counter, tw * th);
lock (results)
{
results.Add(tile);
@ -143,10 +146,10 @@ namespace DotRecast.Recast
return Task.WhenAll(tasks.ToArray());
}
public RecastBuilderResult BuildTile(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tx,
public RcBuilderResult BuildTile(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tx,
int ty, RcAtomicInteger counter, int total)
{
RecastBuilderResult result = Build(geom, new RecastBuilderConfig(cfg, bmin, bmax, tx, ty));
RcBuilderResult result = Build(geom, new RcBuilderConfig(cfg, bmin, bmax, tx, ty));
if (progressListener != null)
{
progressListener.OnProgress(counter.IncrementAndGet(), total);
@ -155,18 +158,18 @@ namespace DotRecast.Recast
return result;
}
public RecastBuilderResult Build(IInputGeomProvider geom, RecastBuilderConfig builderCfg)
public RcBuilderResult Build(IInputGeomProvider geom, RcBuilderConfig builderCfg)
{
RcConfig cfg = builderCfg.cfg;
RcTelemetry ctx = new RcTelemetry();
//
// Step 1. Rasterize input polygon soup.
//
RcHeightfield solid = RecastVoxelization.BuildSolidHeightfield(geom, builderCfg, ctx);
RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(geom, builderCfg, ctx);
return Build(builderCfg.tileX, builderCfg.tileZ, geom, cfg, solid, ctx);
}
public RecastBuilderResult Build(int tileX, int tileZ, IInputGeomProvider geom, RcConfig cfg, RcHeightfield solid, RcTelemetry ctx)
public RcBuilderResult Build(int tileX, int tileZ, IInputGeomProvider geom, RcConfig cfg, RcHeightfield solid, RcTelemetry ctx)
{
FilterHeightfield(solid, cfg, ctx);
RcCompactHeightfield chf = BuildCompactHeightfield(geom, cfg, ctx, solid);
@ -213,20 +216,20 @@ namespace DotRecast.Recast
{
// Prepare for region partitioning, by calculating distance field
// along the walkable surface.
RecastRegion.BuildDistanceField(ctx, chf);
RcRegions.BuildDistanceField(ctx, chf);
// Partition the walkable surface into simple regions without holes.
RecastRegion.BuildRegions(ctx, chf, cfg.MinRegionArea, cfg.MergeRegionArea);
RcRegions.BuildRegions(ctx, chf, cfg.MinRegionArea, cfg.MergeRegionArea);
}
else if (cfg.Partition == RcPartitionType.MONOTONE.Value)
{
// Partition the walkable surface into simple regions without holes.
// Monotone partitioning does not need distancefield.
RecastRegion.BuildRegionsMonotone(ctx, chf, cfg.MinRegionArea, cfg.MergeRegionArea);
RcRegions.BuildRegionsMonotone(ctx, chf, cfg.MinRegionArea, cfg.MergeRegionArea);
}
else
{
// Partition the walkable surface into simple regions without holes.
RecastRegion.BuildLayerRegions(ctx, chf, cfg.MinRegionArea);
RcRegions.BuildLayerRegions(ctx, chf, cfg.MinRegionArea);
}
//
@ -234,23 +237,23 @@ namespace DotRecast.Recast
//
// Create contours.
RcContourSet cset = RecastContour.BuildContours(ctx, chf, cfg.MaxSimplificationError, cfg.MaxEdgeLen,
RcContourSet cset = RcContours.BuildContours(ctx, chf, cfg.MaxSimplificationError, cfg.MaxEdgeLen,
RcConstants.RC_CONTOUR_TESS_WALL_EDGES);
//
// Step 6. Build polygons mesh from contours.
//
RcPolyMesh pmesh = RecastMesh.BuildPolyMesh(ctx, cset, cfg.MaxVertsPerPoly);
RcPolyMesh pmesh = RcMeshs.BuildPolyMesh(ctx, cset, cfg.MaxVertsPerPoly);
//
// Step 7. Create detail mesh which allows to access approximate height
// on each polygon.
//
RcPolyMeshDetail dmesh = cfg.BuildMeshDetail
? RecastMeshDetail.BuildPolyMeshDetail(ctx, pmesh, chf, cfg.DetailSampleDist, cfg.DetailSampleMaxError)
? RcMeshDetails.BuildPolyMeshDetail(ctx, pmesh, chf, cfg.DetailSampleDist, cfg.DetailSampleMaxError)
: null;
return new RecastBuilderResult(tileX, tileZ, solid, chf, cset, pmesh, dmesh, ctx);
return new RcBuilderResult(tileX, tileZ, solid, chf, cset, pmesh, dmesh, ctx);
}
/*
@ -263,17 +266,17 @@ namespace DotRecast.Recast
// as well as filter spans where the character cannot possibly stand.
if (cfg.FilterLowHangingObstacles)
{
RecastFilter.FilterLowHangingWalkableObstacles(ctx, cfg.WalkableClimb, solid);
RcFilters.FilterLowHangingWalkableObstacles(ctx, cfg.WalkableClimb, solid);
}
if (cfg.FilterLedgeSpans)
{
RecastFilter.FilterLedgeSpans(ctx, cfg.WalkableHeight, cfg.WalkableClimb, solid);
RcFilters.FilterLedgeSpans(ctx, cfg.WalkableHeight, cfg.WalkableClimb, solid);
}
if (cfg.FilterWalkableLowHeightSpans)
{
RecastFilter.FilterWalkableLowHeightSpans(ctx, cfg.WalkableHeight, solid);
RcFilters.FilterWalkableLowHeightSpans(ctx, cfg.WalkableHeight, solid);
}
}
@ -286,29 +289,29 @@ namespace DotRecast.Recast
// Compact the heightfield so that it is faster to handle from now on.
// This will result more cache coherent data as well as the neighbours
// between walkable cells will be calculated.
RcCompactHeightfield chf = RecastCompact.BuildCompactHeightfield(ctx, cfg.WalkableHeight, cfg.WalkableClimb, solid);
RcCompactHeightfield chf = RcCompacts.BuildCompactHeightfield(ctx, cfg.WalkableHeight, cfg.WalkableClimb, solid);
// Erode the walkable area by agent radius.
RecastArea.ErodeWalkableArea(ctx, cfg.WalkableRadius, chf);
ErodeWalkableArea(ctx, cfg.WalkableRadius, chf);
// (Optional) Mark areas.
if (geom != null)
{
foreach (RcConvexVolume vol in geom.ConvexVolumes())
{
RecastArea.MarkConvexPolyArea(ctx, vol.verts, vol.hmin, vol.hmax, vol.areaMod, chf);
MarkConvexPolyArea(ctx, vol.verts, vol.hmin, vol.hmax, vol.areaMod, chf);
}
}
return chf;
}
public RcHeightfieldLayerSet BuildLayers(IInputGeomProvider geom, RecastBuilderConfig builderCfg)
public RcHeightfieldLayerSet BuildLayers(IInputGeomProvider geom, RcBuilderConfig builderCfg)
{
RcTelemetry ctx = new RcTelemetry();
RcHeightfield solid = RecastVoxelization.BuildSolidHeightfield(geom, builderCfg, ctx);
RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(geom, builderCfg, ctx);
FilterHeightfield(solid, builderCfg.cfg, ctx);
RcCompactHeightfield chf = BuildCompactHeightfield(geom, builderCfg.cfg, ctx, solid);
return RecastLayers.BuildHeightfieldLayers(ctx, chf, builderCfg.cfg.WalkableHeight);
return RcLayers.BuildHeightfieldLayers(ctx, chf, builderCfg.cfg.WalkableHeight);
}
}
}

View File

@ -22,7 +22,7 @@ using DotRecast.Core;
namespace DotRecast.Recast
{
public class RecastBuilderConfig
public class RcBuilderConfig
{
public readonly RcConfig cfg;
@ -41,11 +41,11 @@ namespace DotRecast.Recast
/** The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] **/
public readonly RcVec3f bmax = new RcVec3f();
public RecastBuilderConfig(RcConfig cfg, RcVec3f bmin, RcVec3f bmax) : this(cfg, bmin, bmax, 0, 0)
public RcBuilderConfig(RcConfig cfg, RcVec3f bmin, RcVec3f bmax) : this(cfg, bmin, bmax, 0, 0)
{
}
public RecastBuilderConfig(RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tileX, int tileZ)
public RcBuilderConfig(RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tileX, int tileZ)
{
this.tileX = tileX;
this.tileZ = tileZ;
@ -92,7 +92,7 @@ namespace DotRecast.Recast
}
else
{
RcUtils.CalcGridSize(this.bmin, this.bmax, cfg.Cs, out width, out height);
RcCommons.CalcGridSize(this.bmin, this.bmax, cfg.Cs, out width, out height);
}
}
}

View File

@ -2,7 +2,7 @@
namespace DotRecast.Recast
{
public class RecastBuilderResult
public class RcBuilderResult
{
public readonly int tileX;
public readonly int tileZ;
@ -14,7 +14,7 @@ namespace DotRecast.Recast
private readonly RcHeightfield solid;
private readonly RcTelemetry telemetry;
public RecastBuilderResult(int tileX, int tileZ, RcHeightfield solid, RcCompactHeightfield chf, RcContourSet cs, RcPolyMesh pmesh, RcPolyMeshDetail dmesh, RcTelemetry ctx)
public RcBuilderResult(int tileX, int tileZ, RcHeightfield solid, RcCompactHeightfield chf, RcContourSet cs, RcPolyMesh pmesh, RcPolyMeshDetail dmesh, RcTelemetry ctx)
{
this.tileX = tileX;
this.tileZ = tileZ;

View File

@ -23,10 +23,61 @@ using DotRecast.Core;
namespace DotRecast.Recast
{
using static DotRecast.Recast.RcConstants;
using static RcConstants;
public static class RcUtils
public static class RcCommons
{
private static readonly int[] DirOffsetX = { -1, 0, 1, 0, };
private static readonly int[] DirOffsetY = { 0, 1, 0, -1 };
private static readonly int[] DirForOffset = { 3, 0, -1, 2, 1 };
/// Sets the neighbor connection data for the specified direction.
/// @param[in] span The span to update.
/// @param[in] direction The direction to set. [Limits: 0 <= value < 4]
/// @param[in] neighborIndex The index of the neighbor span.
public static void SetCon(RcCompactSpan span, int direction, int neighborIndex)
{
int shift = direction * 6;
int con = span.con;
span.con = (con & ~(0x3f << shift)) | ((neighborIndex & 0x3f) << shift);
}
/// Gets neighbor connection data for the specified direction.
/// @param[in] span The span to check.
/// @param[in] direction The direction to check. [Limits: 0 <= value < 4]
/// @return The neighbor connection data for the specified direction, or #RC_NOT_CONNECTED if there is no connection.
public static int GetCon(RcCompactSpan s, int dir)
{
int shift = dir * 6;
return (s.con >> shift) & 0x3f;
}
/// Gets the standard width (x-axis) offset for the specified direction.
/// @param[in] direction The direction. [Limits: 0 <= value < 4]
/// @return The width offset to apply to the current cell position to move in the direction.
public static int GetDirOffsetX(int dir)
{
return DirOffsetX[dir & 0x03];
}
// TODO (graham): Rename this to rcGetDirOffsetZ
/// Gets the standard height (z-axis) offset for the specified direction.
/// @param[in] direction The direction. [Limits: 0 <= value < 4]
/// @return The height offset to apply to the current cell position to move in the direction.
public static int GetDirOffsetY(int dir)
{
return DirOffsetY[dir & 0x03];
}
/// Gets the direction for the specified offset. One of x and y should be 0.
/// @param[in] offsetX The x offset. [Limits: -1 <= value <= 1]
/// @param[in] offsetZ The z offset. [Limits: -1 <= value <= 1]
/// @return The direction that represents the offset.
public static int GetDirForOffset(int x, int y)
{
return DirForOffset[((y + 1) << 1) + x];
}
public static void CalcBounds(float[] verts, int nv, float[] bmin, float[] bmax)
{
for (int i = 0; i < 3; i++)

View File

@ -25,7 +25,9 @@ using static DotRecast.Recast.RcConstants;
namespace DotRecast.Recast
{
public static class RecastCompact
using static RcCommons;
public static class RcCompacts
{
private const int MAX_LAYERS = RC_NOT_CONNECTED - 1;
private const int MAX_HEIGHT = RcConstants.SPAN_MAX_HEIGHT;
@ -117,9 +119,9 @@ namespace DotRecast.Recast
for (int dir = 0; dir < 4; ++dir)
{
RecastCommon.SetCon(s, dir, RC_NOT_CONNECTED);
int nx = x + RecastCommon.GetDirOffsetX(dir);
int ny = y + RecastCommon.GetDirOffsetY(dir);
SetCon(s, dir, RC_NOT_CONNECTED);
int nx = x + GetDirOffsetX(dir);
int ny = y + GetDirOffsetY(dir);
// First check that the neighbour cell is in bounds.
if (nx < 0 || ny < 0 || nx >= w || ny >= h)
continue;
@ -145,7 +147,7 @@ namespace DotRecast.Recast
continue;
}
RecastCommon.SetCon(s, dir, lidx);
SetCon(s, dir, lidx);
break;
}
}

View File

@ -25,8 +25,9 @@ using DotRecast.Core;
namespace DotRecast.Recast
{
using static RcConstants;
using static RcCommons;
public static class RecastContour
public static class RcContours
{
private static int GetCornerHeight(int x, int y, int i, int dir, RcCompactHeightfield chf, out bool isBorderVertex)
{
@ -45,38 +46,38 @@ namespace DotRecast.Recast
// border vertices which are in between two areas to be removed.
regs[0] = chf.spans[i].reg | (chf.areas[i] << 16);
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dir);
RcCompactSpan @as = chf.spans[ai];
ch = Math.Max(ch, @as.y);
regs[1] = chf.spans[ai].reg | (chf.areas[ai] << 16);
if (RecastCommon.GetCon(@as, dirp) != RC_NOT_CONNECTED)
if (GetCon(@as, dirp) != RC_NOT_CONNECTED)
{
int ax2 = ax + RecastCommon.GetDirOffsetX(dirp);
int ay2 = ay + RecastCommon.GetDirOffsetY(dirp);
int ai2 = chf.cells[ax2 + ay2 * chf.width].index + RecastCommon.GetCon(@as, dirp);
int ax2 = ax + GetDirOffsetX(dirp);
int ay2 = ay + GetDirOffsetY(dirp);
int ai2 = chf.cells[ax2 + ay2 * chf.width].index + GetCon(@as, dirp);
RcCompactSpan as2 = chf.spans[ai2];
ch = Math.Max(ch, as2.y);
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
}
}
if (RecastCommon.GetCon(s, dirp) != RC_NOT_CONNECTED)
if (GetCon(s, dirp) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dirp);
int ay = y + RecastCommon.GetDirOffsetY(dirp);
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dirp);
int ax = x + GetDirOffsetX(dirp);
int ay = y + GetDirOffsetY(dirp);
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dirp);
RcCompactSpan @as = chf.spans[ai];
ch = Math.Max(ch, @as.y);
regs[3] = chf.spans[ai].reg | (chf.areas[ai] << 16);
if (RecastCommon.GetCon(@as, dir) != RC_NOT_CONNECTED)
if (GetCon(@as, dir) != RC_NOT_CONNECTED)
{
int ax2 = ax + RecastCommon.GetDirOffsetX(dir);
int ay2 = ay + RecastCommon.GetDirOffsetY(dir);
int ai2 = chf.cells[ax2 + ay2 * chf.width].index + RecastCommon.GetCon(@as, dir);
int ax2 = ax + GetDirOffsetX(dir);
int ay2 = ay + GetDirOffsetY(dir);
int ai2 = chf.cells[ax2 + ay2 * chf.width].index + GetCon(@as, dir);
RcCompactSpan as2 = chf.spans[ai2];
ch = Math.Max(ch, as2.y);
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
@ -146,11 +147,11 @@ namespace DotRecast.Recast
int r = 0;
RcCompactSpan s = chf.spans[i];
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dir);
r = chf.spans[ai].reg;
if (area != chf.areas[ai])
isAreaBorder = true;
@ -171,13 +172,13 @@ namespace DotRecast.Recast
else
{
int ni = -1;
int nx = x + RecastCommon.GetDirOffsetX(dir);
int ny = y + RecastCommon.GetDirOffsetY(dir);
int nx = x + GetDirOffsetX(dir);
int ny = y + GetDirOffsetY(dir);
RcCompactSpan s = chf.spans[i];
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
RcCompactCell nc = chf.cells[nx + ny * chf.width];
ni = nc.index + RecastCommon.GetCon(s, dir);
ni = nc.index + GetCon(s, dir);
}
if (ni == -1)
@ -475,7 +476,7 @@ namespace DotRecast.Recast
d1 = 4;
for (int k = 0; k < n; k++)
{
int k1 = RecastMesh.Next(k, n);
int k1 = RcMeshs.Next(k, n);
// Skip edges incident to i.
if (i == k || i == k1)
continue;
@ -489,11 +490,11 @@ namespace DotRecast.Recast
p0 = 8;
p1 = 12;
if (RecastMesh.VEqual(pverts, d0, p0) || RecastMesh.VEqual(pverts, d1, p0) ||
RecastMesh.VEqual(pverts, d0, p1) || RecastMesh.VEqual(pverts, d1, p1))
if (RcMeshs.VEqual(pverts, d0, p0) || RcMeshs.VEqual(pverts, d1, p0) ||
RcMeshs.VEqual(pverts, d0, p1) || RcMeshs.VEqual(pverts, d1, p1))
continue;
if (RecastMesh.Intersect(pverts, d0, d1, p0, p1))
if (RcMeshs.Intersect(pverts, d0, d1, p0, p1))
return true;
}
@ -503,8 +504,8 @@ namespace DotRecast.Recast
private static bool InCone(int i, int n, int[] verts, int pj, int[] vertpj)
{
int pi = i * 4;
int pi1 = RecastMesh.Next(i, n) * 4;
int pin1 = RecastMesh.Prev(i, n) * 4;
int pi1 = RcMeshs.Next(i, n) * 4;
int pin1 = RcMeshs.Prev(i, n) * 4;
int[] pverts = new int[4 * 4];
for (int g = 0; g < 4; g++)
{
@ -519,11 +520,11 @@ namespace DotRecast.Recast
pin1 = 8;
pj = 12;
// If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
if (RecastMesh.LeftOn(pverts, pin1, pi, pi1))
return RecastMesh.Left(pverts, pi, pj, pin1) && RecastMesh.Left(pverts, pj, pi, pi1);
if (RcMeshs.LeftOn(pverts, pin1, pi, pi1))
return RcMeshs.Left(pverts, pi, pj, pin1) && RcMeshs.Left(pverts, pj, pi, pi1);
// Assume (i-1,i,i+1) not collinear.
// else P[i] is reflex.
return !(RecastMesh.LeftOn(pverts, pi, pj, pi1) && RecastMesh.LeftOn(pverts, pj, pi, pin1));
return !(RcMeshs.LeftOn(pverts, pi, pj, pi1) && RcMeshs.LeftOn(pverts, pj, pi, pin1));
}
private static void RemoveDegenerateSegments(List<int> simplified)
@ -533,7 +534,7 @@ namespace DotRecast.Recast
int npts = simplified.Count / 4;
for (int i = 0; i < npts; ++i)
{
int ni = RecastMesh.Next(i, npts);
int ni = RcMeshs.Next(i, npts);
// if (Vequal(&simplified[i*4], &simplified[ni*4]))
if (simplified[i * 4] == simplified[ni * 4]
@ -766,11 +767,11 @@ namespace DotRecast.Recast
for (int dir = 0; dir < 4; ++dir)
{
int r = 0;
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
r = chf.spans[ai].reg;
}

View File

@ -25,7 +25,7 @@ using static DotRecast.Recast.RcConstants;
namespace DotRecast.Recast
{
public static class RecastFilledVolumeRasterization
public static class RcFilledVolumeRasterization
{
private const float EPSILON = 0.00001f;
private static readonly int[] BOX_EDGES = new[] { 0, 1, 0, 2, 0, 4, 1, 3, 1, 5, 2, 3, 2, 6, 3, 7, 4, 5, 4, 6, 5, 7, 6, 7 };
@ -56,8 +56,7 @@ namespace DotRecast.Recast
rectangle => IntersectCapsule(rectangle, start, end, axis, radius * radius));
}
public static void RasterizeCylinder(RcHeightfield hf, RcVec3f start, RcVec3f end, float radius, int area, int flagMergeThr,
RcTelemetry ctx)
public static void RasterizeCylinder(RcHeightfield hf, RcVec3f start, RcVec3f end, float radius, int area, int flagMergeThr, RcTelemetry ctx)
{
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_CYLINDER);
float[] bounds =
@ -71,8 +70,7 @@ namespace DotRecast.Recast
rectangle => IntersectCylinder(rectangle, start, end, axis, radius * radius));
}
public static void RasterizeBox(RcHeightfield hf, RcVec3f center, RcVec3f[] halfEdges, int area, int flagMergeThr,
RcTelemetry ctx)
public static void RasterizeBox(RcHeightfield hf, RcVec3f center, RcVec3f[] halfEdges, int area, int flagMergeThr, RcTelemetry ctx)
{
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_BOX);
RcVec3f[] normals =
@ -122,8 +120,7 @@ namespace DotRecast.Recast
RasterizationFilledShape(hf, bounds, area, flagMergeThr, rectangle => IntersectBox(rectangle, vertices, planes));
}
public static void RasterizeConvex(RcHeightfield hf, float[] vertices, int[] triangles, int area, int flagMergeThr,
RcTelemetry ctx)
public static void RasterizeConvex(RcHeightfield hf, float[] vertices, int[] triangles, int area, int flagMergeThr, RcTelemetry ctx)
{
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_CONVEX);
float[] bounds = new float[] { vertices[0], vertices[1], vertices[2], vertices[0], vertices[1], vertices[2] };
@ -226,7 +223,7 @@ namespace DotRecast.Recast
{
int ismin = Clamp(smin, 0, SPAN_MAX_HEIGHT);
int ismax = Clamp(smax, ismin + 1, SPAN_MAX_HEIGHT);
RecastRasterization.AddSpan(hf, x, z, ismin, ismax, area, flagMergeThr);
RcRasterizations.AddSpan(hf, x, z, ismin, ismax, area, flagMergeThr);
}
}
}

View File

@ -24,8 +24,9 @@ using DotRecast.Core;
namespace DotRecast.Recast
{
using static RcConstants;
using static RcCommons;
public static class RecastFilter
public static class RcFilters
{
/// @par
///
@ -113,8 +114,8 @@ namespace DotRecast.Recast
for (int dir = 0; dir < 4; ++dir)
{
int dx = x + RecastCommon.GetDirOffsetX(dir);
int dy = y + RecastCommon.GetDirOffsetY(dir);
int dx = x + GetDirOffsetX(dir);
int dy = y + GetDirOffsetY(dir);
// Skip neighbours which are out of bounds.
if (dx < 0 || dy < 0 || dx >= w || dy >= h)
{

View File

@ -24,10 +24,10 @@ using DotRecast.Core;
namespace DotRecast.Recast
{
using static RecastCommon;
using static RcConstants;
using static RcCommons;
public static class RecastLayers
public static class RcLayers
{
const int RC_MAX_LAYERS = RcConstants.RC_NOT_CONNECTED;
const int RC_MAX_NEIS = 16;

View File

@ -22,12 +22,13 @@ using System;
using System.Collections.Generic;
using DotRecast.Core;
using static DotRecast.Core.RcMath;
using static DotRecast.Recast.RecastCommon;
using static DotRecast.Recast.RcConstants;
namespace DotRecast.Recast
{
public static class RecastMeshDetail
using static RcCommons;
public static class RcMeshDetails
{
public const int MAX_VERTS = 127;
public const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
@ -764,8 +765,8 @@ namespace DotRecast.Recast
}
// segments on edges
int pi = RecastMesh.Prev(i, nhull);
int ni = RecastMesh.Next(i, nhull);
int pi = RcMeshs.Prev(i, nhull);
int ni = RcMeshs.Next(i, nhull);
int pv = hull[pi] * 3;
int cv = hull[i] * 3;
int nv = hull[ni] * 3;
@ -789,11 +790,11 @@ namespace DotRecast.Recast
// depending on which triangle has shorter perimeter.
// This heuristic was chose empirically, since it seems
// handle tessellated straight edges well.
while (RecastMesh.Next(left, nhull) != right)
while (RcMeshs.Next(left, nhull) != right)
{
// Check to see if se should advance left or right.
int nleft = RecastMesh.Next(left, nhull);
int nright = RecastMesh.Prev(right, nhull);
int nleft = RcMeshs.Next(left, nhull);
int nright = RcMeshs.Prev(right, nhull);
int cvleft = hull[left] * 3;
int nvleft = hull[nleft] * 3;

View File

@ -25,7 +25,7 @@ namespace DotRecast.Recast
{
using static RcConstants;
public static class RecastMesh
public static class RcMeshs
{
public const int MAX_MESH_VERTS_POLY = 0xffff;
public const int VERTEX_BUCKET_COUNT = (1 << 12);

View File

@ -24,10 +24,10 @@ namespace DotRecast.Recast
{
public static class RcPolyMeshRaycast
{
public static bool Raycast(IList<RecastBuilderResult> results, RcVec3f src, RcVec3f dst, out float hitTime)
public static bool Raycast(IList<RcBuilderResult> results, RcVec3f src, RcVec3f dst, out float hitTime)
{
hitTime = 0.0f;
foreach (RecastBuilderResult result in results)
foreach (RcBuilderResult result in results)
{
if (result.GetMeshDetail() != null)
{

View File

@ -25,7 +25,7 @@ using static DotRecast.Recast.RcConstants;
namespace DotRecast.Recast
{
public static class RecastRasterization
public static class RcRasterizations
{
/**
* Check whether two bounding boxes overlap

View File

@ -26,12 +26,12 @@ using DotRecast.Core;
namespace DotRecast.Recast
{
using static RcConstants;
using static RcCommons;
public static class RecastRegion
public static class RcRegions
{
const int RC_NULL_NEI = 0xffff;
public static int CalculateDistanceField(RcCompactHeightfield chf, int[] src)
{
int maxDist;
@ -58,11 +58,11 @@ namespace DotRecast.Recast
int nc = 0;
for (int dir = 0; dir < 4; ++dir)
{
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
if (area == chf.areas[ai])
{
nc++;
@ -88,12 +88,12 @@ namespace DotRecast.Recast
{
RcCompactSpan s = chf.spans[i];
if (RecastCommon.GetCon(s, 0) != RC_NOT_CONNECTED)
if (GetCon(s, 0) != RC_NOT_CONNECTED)
{
// (-1,0)
int ax = x + RecastCommon.GetDirOffsetX(0);
int ay = y + RecastCommon.GetDirOffsetY(0);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 0);
int ax = x + GetDirOffsetX(0);
int ay = y + GetDirOffsetY(0);
int ai = chf.cells[ax + ay * w].index + GetCon(s, 0);
RcCompactSpan @as = chf.spans[ai];
if (src[ai] + 2 < src[i])
{
@ -101,11 +101,11 @@ namespace DotRecast.Recast
}
// (-1,-1)
if (RecastCommon.GetCon(@as, 3) != RC_NOT_CONNECTED)
if (GetCon(@as, 3) != RC_NOT_CONNECTED)
{
int aax = ax + RecastCommon.GetDirOffsetX(3);
int aay = ay + RecastCommon.GetDirOffsetY(3);
int aai = chf.cells[aax + aay * w].index + RecastCommon.GetCon(@as, 3);
int aax = ax + GetDirOffsetX(3);
int aay = ay + GetDirOffsetY(3);
int aai = chf.cells[aax + aay * w].index + GetCon(@as, 3);
if (src[aai] + 3 < src[i])
{
src[i] = src[aai] + 3;
@ -113,12 +113,12 @@ namespace DotRecast.Recast
}
}
if (RecastCommon.GetCon(s, 3) != RC_NOT_CONNECTED)
if (GetCon(s, 3) != RC_NOT_CONNECTED)
{
// (0,-1)
int ax = x + RecastCommon.GetDirOffsetX(3);
int ay = y + RecastCommon.GetDirOffsetY(3);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 3);
int ax = x + GetDirOffsetX(3);
int ay = y + GetDirOffsetY(3);
int ai = chf.cells[ax + ay * w].index + GetCon(s, 3);
RcCompactSpan @as = chf.spans[ai];
if (src[ai] + 2 < src[i])
{
@ -126,11 +126,11 @@ namespace DotRecast.Recast
}
// (1,-1)
if (RecastCommon.GetCon(@as, 2) != RC_NOT_CONNECTED)
if (GetCon(@as, 2) != RC_NOT_CONNECTED)
{
int aax = ax + RecastCommon.GetDirOffsetX(2);
int aay = ay + RecastCommon.GetDirOffsetY(2);
int aai = chf.cells[aax + aay * w].index + RecastCommon.GetCon(@as, 2);
int aax = ax + GetDirOffsetX(2);
int aay = ay + GetDirOffsetY(2);
int aai = chf.cells[aax + aay * w].index + GetCon(@as, 2);
if (src[aai] + 3 < src[i])
{
src[i] = src[aai] + 3;
@ -151,12 +151,12 @@ namespace DotRecast.Recast
{
RcCompactSpan s = chf.spans[i];
if (RecastCommon.GetCon(s, 2) != RC_NOT_CONNECTED)
if (GetCon(s, 2) != RC_NOT_CONNECTED)
{
// (1,0)
int ax = x + RecastCommon.GetDirOffsetX(2);
int ay = y + RecastCommon.GetDirOffsetY(2);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 2);
int ax = x + GetDirOffsetX(2);
int ay = y + GetDirOffsetY(2);
int ai = chf.cells[ax + ay * w].index + GetCon(s, 2);
RcCompactSpan @as = chf.spans[ai];
if (src[ai] + 2 < src[i])
{
@ -164,11 +164,11 @@ namespace DotRecast.Recast
}
// (1,1)
if (RecastCommon.GetCon(@as, 1) != RC_NOT_CONNECTED)
if (GetCon(@as, 1) != RC_NOT_CONNECTED)
{
int aax = ax + RecastCommon.GetDirOffsetX(1);
int aay = ay + RecastCommon.GetDirOffsetY(1);
int aai = chf.cells[aax + aay * w].index + RecastCommon.GetCon(@as, 1);
int aax = ax + GetDirOffsetX(1);
int aay = ay + GetDirOffsetY(1);
int aai = chf.cells[aax + aay * w].index + GetCon(@as, 1);
if (src[aai] + 3 < src[i])
{
src[i] = src[aai] + 3;
@ -176,12 +176,12 @@ namespace DotRecast.Recast
}
}
if (RecastCommon.GetCon(s, 1) != RC_NOT_CONNECTED)
if (GetCon(s, 1) != RC_NOT_CONNECTED)
{
// (0,1)
int ax = x + RecastCommon.GetDirOffsetX(1);
int ay = y + RecastCommon.GetDirOffsetY(1);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 1);
int ax = x + GetDirOffsetX(1);
int ay = y + GetDirOffsetY(1);
int ai = chf.cells[ax + ay * w].index + GetCon(s, 1);
RcCompactSpan @as = chf.spans[ai];
if (src[ai] + 2 < src[i])
{
@ -189,11 +189,11 @@ namespace DotRecast.Recast
}
// (-1,1)
if (RecastCommon.GetCon(@as, 0) != RC_NOT_CONNECTED)
if (GetCon(@as, 0) != RC_NOT_CONNECTED)
{
int aax = ax + RecastCommon.GetDirOffsetX(0);
int aay = ay + RecastCommon.GetDirOffsetY(0);
int aai = chf.cells[aax + aay * w].index + RecastCommon.GetCon(@as, 0);
int aax = ax + GetDirOffsetX(0);
int aay = ay + GetDirOffsetY(0);
int aai = chf.cells[aax + aay * w].index + GetCon(@as, 0);
if (src[aai] + 3 < src[i])
{
src[i] = src[aai] + 3;
@ -239,20 +239,20 @@ namespace DotRecast.Recast
int d = cd;
for (int dir = 0; dir < 4; ++dir)
{
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
d += src[ai];
RcCompactSpan @as = chf.spans[ai];
int dir2 = (dir + 1) & 0x3;
if (RecastCommon.GetCon(@as, dir2) != RC_NOT_CONNECTED)
if (GetCon(@as, dir2) != RC_NOT_CONNECTED)
{
int ax2 = ax + RecastCommon.GetDirOffsetX(dir2);
int ay2 = ay + RecastCommon.GetDirOffsetY(dir2);
int ai2 = chf.cells[ax2 + ay2 * w].index + RecastCommon.GetCon(@as, dir2);
int ax2 = ax + GetDirOffsetX(dir2);
int ay2 = ay + GetDirOffsetY(dir2);
int ai2 = chf.cells[ax2 + ay2 * w].index + GetCon(@as, dir2);
d += src[ai2];
}
else
@ -311,11 +311,11 @@ namespace DotRecast.Recast
for (int dir = 0; dir < 4; ++dir)
{
// 8 connected
if (RecastCommon.GetCon(cs, dir) != RC_NOT_CONNECTED)
if (GetCon(cs, dir) != RC_NOT_CONNECTED)
{
int ax = cx + RecastCommon.GetDirOffsetX(dir);
int ay = cy + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(cs, dir);
int ax = cx + GetDirOffsetX(dir);
int ay = cy + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + GetCon(cs, dir);
if (chf.areas[ai] != area)
{
continue;
@ -336,11 +336,11 @@ namespace DotRecast.Recast
RcCompactSpan @as = chf.spans[ai];
int dir2 = (dir + 1) & 0x3;
if (RecastCommon.GetCon(@as, dir2) != RC_NOT_CONNECTED)
if (GetCon(@as, dir2) != RC_NOT_CONNECTED)
{
int ax2 = ax + RecastCommon.GetDirOffsetX(dir2);
int ay2 = ay + RecastCommon.GetDirOffsetY(dir2);
int ai2 = chf.cells[ax2 + ay2 * w].index + RecastCommon.GetCon(@as, dir2);
int ax2 = ax + GetDirOffsetX(dir2);
int ay2 = ay + GetDirOffsetY(dir2);
int ai2 = chf.cells[ax2 + ay2 * w].index + GetCon(@as, dir2);
if (chf.areas[ai2] != area)
{
continue;
@ -367,11 +367,11 @@ namespace DotRecast.Recast
// Expand neighbours.
for (int dir = 0; dir < 4; ++dir)
{
if (RecastCommon.GetCon(cs, dir) != RC_NOT_CONNECTED)
if (GetCon(cs, dir) != RC_NOT_CONNECTED)
{
int ax = cx + RecastCommon.GetDirOffsetX(dir);
int ay = cy + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(cs, dir);
int ax = cx + GetDirOffsetX(dir);
int ay = cy + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + GetCon(cs, dir);
if (chf.areas[ai] != area)
{
continue;
@ -456,14 +456,14 @@ namespace DotRecast.Recast
RcCompactSpan s = chf.spans[i];
for (int dir = 0; dir < 4; ++dir)
{
if (RecastCommon.GetCon(s, dir) == RC_NOT_CONNECTED)
if (GetCon(s, dir) == RC_NOT_CONNECTED)
{
continue;
}
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
if (chf.areas[ai] != area)
{
continue;
@ -741,11 +741,11 @@ namespace DotRecast.Recast
{
RcCompactSpan s = chf.spans[i];
int r = 0;
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dir);
r = srcReg[ai];
}
@ -765,11 +765,11 @@ namespace DotRecast.Recast
RcCompactSpan ss = chf.spans[i];
int curReg = 0;
if (RecastCommon.GetCon(ss, dir) != RC_NOT_CONNECTED)
if (GetCon(ss, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(ss, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + GetCon(ss, dir);
curReg = srcReg[ai];
}
@ -784,11 +784,11 @@ namespace DotRecast.Recast
{
// Choose the edge corner
int r = 0;
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dir);
r = srcReg[ai];
}
@ -803,12 +803,12 @@ namespace DotRecast.Recast
else
{
int ni = -1;
int nx = x + RecastCommon.GetDirOffsetX(dir);
int ny = y + RecastCommon.GetDirOffsetY(dir);
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
int nx = x + GetDirOffsetX(dir);
int ny = y + GetDirOffsetY(dir);
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
RcCompactCell nc = chf.cells[nx + ny * chf.width];
ni = nc.index + RecastCommon.GetCon(s, dir);
ni = nc.index + GetCon(s, dir);
}
if (ni == -1)
@ -1215,11 +1215,11 @@ namespace DotRecast.Recast
// Update neighbours
for (int dir = 0; dir < 4; ++dir)
{
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
if (GetCon(s, dir) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(dir);
int ay = y + RecastCommon.GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
int ax = x + GetDirOffsetX(dir);
int ay = y + GetDirOffsetY(dir);
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
int rai = srcReg[ai];
if (rai > 0 && rai < nreg && rai != ri)
{
@ -1543,11 +1543,11 @@ namespace DotRecast.Recast
// -x
int previd = 0;
if (RecastCommon.GetCon(s, 0) != RC_NOT_CONNECTED)
if (GetCon(s, 0) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(0);
int ay = y + RecastCommon.GetDirOffsetY(0);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 0);
int ax = x + GetDirOffsetX(0);
int ay = y + GetDirOffsetY(0);
int ai = chf.cells[ax + ay * w].index + GetCon(s, 0);
if ((srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai])
{
previd = srcReg[ai];
@ -1563,11 +1563,11 @@ namespace DotRecast.Recast
}
// -y
if (RecastCommon.GetCon(s, 3) != RC_NOT_CONNECTED)
if (GetCon(s, 3) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(3);
int ay = y + RecastCommon.GetDirOffsetY(3);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 3);
int ax = x + GetDirOffsetX(3);
int ay = y + GetDirOffsetY(3);
int ai = chf.cells[ax + ay * w].index + GetCon(s, 3);
if (srcReg[ai] != 0 && (srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai])
{
int nr = srcReg[ai];
@ -1843,11 +1843,11 @@ namespace DotRecast.Recast
// -x
int previd = 0;
if (RecastCommon.GetCon(s, 0) != RC_NOT_CONNECTED)
if (GetCon(s, 0) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(0);
int ay = y + RecastCommon.GetDirOffsetY(0);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 0);
int ax = x + GetDirOffsetX(0);
int ay = y + GetDirOffsetY(0);
int ai = chf.cells[ax + ay * w].index + GetCon(s, 0);
if ((srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai])
{
previd = srcReg[ai];
@ -1863,11 +1863,11 @@ namespace DotRecast.Recast
}
// -y
if (RecastCommon.GetCon(s, 3) != RC_NOT_CONNECTED)
if (GetCon(s, 3) != RC_NOT_CONNECTED)
{
int ax = x + RecastCommon.GetDirOffsetX(3);
int ay = y + RecastCommon.GetDirOffsetY(3);
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 3);
int ax = x + GetDirOffsetX(3);
int ay = y + GetDirOffsetY(3);
int ai = chf.cells[ax + ay * w].index + GetCon(s, 3);
if (srcReg[ai] != 0 && (srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai])
{
int nr = srcReg[ai];

View File

@ -23,9 +23,9 @@ using DotRecast.Recast.Geom;
namespace DotRecast.Recast
{
public static class RecastVoxelization
public static class RcVoxelizations
{
public static RcHeightfield BuildSolidHeightfield(IInputGeomProvider geomProvider, RecastBuilderConfig builderCfg, RcTelemetry ctx)
public static RcHeightfield BuildSolidHeightfield(IInputGeomProvider geomProvider, RcBuilderConfig builderCfg, RcTelemetry ctx)
{
RcConfig cfg = builderCfg.cfg;
@ -58,16 +58,16 @@ namespace DotRecast.Recast
{
int[] tris = node.tris;
int ntris = tris.Length / 3;
int[] m_triareas = RcUtils.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RecastRasterization.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx);
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx);
}
}
else
{
int[] tris = geom.GetTris();
int ntris = tris.Length / 3;
int[] m_triareas = RcUtils.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RecastRasterization.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx);
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx);
}
}

View File

@ -1,78 +0,0 @@
/*
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
using System;
namespace DotRecast.Recast
{
public static class RecastCommon
{
private static readonly int[] DirOffsetX = { -1, 0, 1, 0, };
private static readonly int[] DirOffsetY = { 0, 1, 0, -1 };
private static readonly int[] DirForOffset = { 3, 0, -1, 2, 1 };
/// Sets the neighbor connection data for the specified direction.
/// @param[in] span The span to update.
/// @param[in] direction The direction to set. [Limits: 0 <= value < 4]
/// @param[in] neighborIndex The index of the neighbor span.
public static void SetCon(RcCompactSpan span, int direction, int neighborIndex)
{
int shift = direction * 6;
int con = span.con;
span.con = (con & ~(0x3f << shift)) | ((neighborIndex & 0x3f) << shift);
}
/// Gets neighbor connection data for the specified direction.
/// @param[in] span The span to check.
/// @param[in] direction The direction to check. [Limits: 0 <= value < 4]
/// @return The neighbor connection data for the specified direction, or #RC_NOT_CONNECTED if there is no connection.
public static int GetCon(RcCompactSpan s, int dir)
{
int shift = dir * 6;
return (s.con >> shift) & 0x3f;
}
/// Gets the standard width (x-axis) offset for the specified direction.
/// @param[in] direction The direction. [Limits: 0 <= value < 4]
/// @return The width offset to apply to the current cell position to move in the direction.
public static int GetDirOffsetX(int dir)
{
return DirOffsetX[dir & 0x03];
}
// TODO (graham): Rename this to rcGetDirOffsetZ
/// Gets the standard height (z-axis) offset for the specified direction.
/// @param[in] direction The direction. [Limits: 0 <= value < 4]
/// @return The height offset to apply to the current cell position to move in the direction.
public static int GetDirOffsetY(int dir)
{
return DirOffsetY[dir & 0x03];
}
/// Gets the direction for the specified offset. One of x and y should be 0.
/// @param[in] offsetX The x offset. [Limits: -1 <= value <= 1]
/// @param[in] offsetZ The z offset. [Limits: -1 <= value <= 1]
/// @return The direction that represents the offset.
public static int GetDirForOffset(int x, int y)
{
return DirForOffset[((y + 1) << 1) + x];
}
}
}

View File

@ -70,9 +70,9 @@ public class RecastTestMeshBuilder
detailSampleDist, detailSampleMaxError,
true, true, true,
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
RecastBuilder rcBuilder = new RecastBuilder();
RecastBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
RcBuilder rcBuilder = new RcBuilder();
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
RcPolyMesh m_pmesh = rcResult.GetMesh();
for (int i = 0; i < m_pmesh.npolys; ++i)
{

View File

@ -69,7 +69,7 @@ public class MeshSetReaderWriterTest
RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax();
RcUtils.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
RcCommons.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
for (int y = 0; y < th; ++y)
{
for (int x = 0; x < tw; ++x)
@ -85,7 +85,7 @@ public class MeshSetReaderWriterTest
m_detailSampleDist, m_detailSampleMaxError,
true, true, true,
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, bmin, bmax, x, y);
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, bmin, bmax, x, y);
TestDetourBuilder db = new TestDetourBuilder();
DtMeshData data = db.Build(geom, bcfg, m_agentHeight, m_agentRadius, m_agentMaxClimb, x, y, true);
if (data != null)

View File

@ -70,9 +70,9 @@ public class RecastTestMeshBuilder
detailSampleDist, detailSampleMaxError,
true, true, true,
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
RecastBuilder rcBuilder = new RecastBuilder();
RecastBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
RcBuilder rcBuilder = new RcBuilder();
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
RcPolyMesh m_pmesh = rcResult.GetMesh();
for (int i = 0; i < m_pmesh.npolys; ++i)
{

View File

@ -23,11 +23,11 @@ namespace DotRecast.Detour.Test;
public class TestDetourBuilder : DetourBuilder
{
public DtMeshData Build(IInputGeomProvider geom, RecastBuilderConfig rcConfig, float agentHeight, float agentRadius,
public DtMeshData Build(IInputGeomProvider geom, RcBuilderConfig rcConfig, float agentHeight, float agentRadius,
float agentMaxClimb, int x, int y, bool applyRecastDemoFlags)
{
RecastBuilder rcBuilder = new RecastBuilder();
RecastBuilderResult rcResult = rcBuilder.Build(geom, rcConfig);
RcBuilder rcBuilder = new RcBuilder();
RcBuilderResult rcResult = rcBuilder.Build(geom, rcConfig);
RcPolyMesh pmesh = rcResult.GetMesh();
if (applyRecastDemoFlags)

View File

@ -77,12 +77,12 @@ public class TestTiledNavMeshBuilder
detailSampleDist, detailSampleMaxError,
true, true, true,
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
RecastBuilder rcBuilder = new RecastBuilder();
List<RecastBuilderResult> rcResult = rcBuilder.BuildTiles(geom, cfg, null);
RcBuilder rcBuilder = new RcBuilder();
List<RcBuilderResult> rcResult = rcBuilder.BuildTiles(geom, cfg, null);
// Add tiles to nav mesh
foreach (RecastBuilderResult result in rcResult)
foreach (RcBuilderResult result in rcResult)
{
RcPolyMesh pmesh = result.GetMesh();
if (pmesh.npolys == 0)

View File

@ -46,7 +46,7 @@ public class AbstractTileCacheTest
public DtTileCache GetTileCache(IInputGeomProvider geom, RcByteOrder order, bool cCompatibility)
{
DtTileCacheParams option = new DtTileCacheParams();
RcUtils.CalcTileCount(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
RcCommons.CalcTileCount(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
option.ch = m_cellHeight;
option.cs = m_cellSize;
option.orig = geom.GetMeshBoundsMin();

View File

@ -73,7 +73,7 @@ public class TestTileLayerBuilder : DtTileCacheLayerBuilder
RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax();
RcUtils.CalcTileCount(bmin, bmax, CellSize, m_tileSize, m_tileSize, out tw, out th);
RcCommons.CalcTileCount(bmin, bmax, CellSize, m_tileSize, m_tileSize, out tw, out th);
}
public List<byte[]> Build(RcByteOrder order, bool cCompatibility, int threads)

View File

@ -146,7 +146,7 @@ public class RecastLayersTest
private RcHeightfieldLayerSet Build(string filename, int x, int y)
{
IInputGeomProvider geom = ObjImporter.Load(RcResources.Load(filename));
RecastBuilder builder = new RecastBuilder();
RcBuilder builder = new RcBuilder();
RcConfig cfg = new RcConfig(true, m_tileSize, m_tileSize,
RcConfig.CalcBorder(m_agentRadius, m_cellSize),
RcPartitionType.OfValue(m_partitionType),
@ -158,7 +158,7 @@ public class RecastLayersTest
m_detailSampleDist, m_detailSampleMaxError,
true, true, true,
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), x, y);
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), x, y);
RcHeightfieldLayerSet lset = builder.BuildLayers(geom, bcfg);
return lset;
}

View File

@ -26,6 +26,7 @@ using NUnit.Framework;
namespace DotRecast.Recast.Test;
using static RcConstants;
using static RcAreas;
[Parallelizable]
public class RecastSoloMeshTest
@ -116,7 +117,7 @@ public class RecastSoloMeshTest
m_detailSampleDist, m_detailSampleMaxError,
true, true, true,
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, bmin, bmax);
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, bmin, bmax);
//
// Step 2. Rasterize input polygon soup.
@ -138,8 +139,8 @@ public class RecastSoloMeshTest
// Find triangles which are walkable based on their slope and rasterize them.
// If your input data is multiple meshes, you can transform them here, calculate
// the are type for each of the meshes and rasterize them.
int[] m_triareas = RcUtils.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RecastRasterization.RasterizeTriangles(m_solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, m_ctx);
int[] m_triareas = RcCommons.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(m_solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, m_ctx);
}
//
@ -149,9 +150,9 @@ public class RecastSoloMeshTest
// Once all geometry is rasterized, we do initial pass of filtering to
// remove unwanted overhangs caused by the conservative rasterization
// as well as filter spans where the character cannot possibly stand.
RecastFilter.FilterLowHangingWalkableObstacles(m_ctx, cfg.WalkableClimb, m_solid);
RecastFilter.FilterLedgeSpans(m_ctx, cfg.WalkableHeight, cfg.WalkableClimb, m_solid);
RecastFilter.FilterWalkableLowHeightSpans(m_ctx, cfg.WalkableHeight, m_solid);
RcFilters.FilterLowHangingWalkableObstacles(m_ctx, cfg.WalkableClimb, m_solid);
RcFilters.FilterLedgeSpans(m_ctx, cfg.WalkableHeight, cfg.WalkableClimb, m_solid);
RcFilters.FilterWalkableLowHeightSpans(m_ctx, cfg.WalkableHeight, m_solid);
//
// Step 4. Partition walkable surface to simple regions.
@ -160,11 +161,10 @@ public class RecastSoloMeshTest
// Compact the heightfield so that it is faster to handle from now on.
// This will result more cache coherent data as well as the neighbours
// between walkable cells will be calculated.
RcCompactHeightfield m_chf = RecastCompact.BuildCompactHeightfield(m_ctx, cfg.WalkableHeight, cfg.WalkableClimb,
m_solid);
RcCompactHeightfield m_chf = RcCompacts.BuildCompactHeightfield(m_ctx, cfg.WalkableHeight, cfg.WalkableClimb, m_solid);
// Erode the walkable area by agent radius.
RecastArea.ErodeWalkableArea(m_ctx, cfg.WalkableRadius, m_chf);
ErodeWalkableArea(m_ctx, cfg.WalkableRadius, m_chf);
// (Optional) Mark areas.
/*
@ -216,20 +216,20 @@ public class RecastSoloMeshTest
{
// Prepare for region partitioning, by calculating distance field
// along the walkable surface.
RecastRegion.BuildDistanceField(m_ctx, m_chf);
RcRegions.BuildDistanceField(m_ctx, m_chf);
// Partition the walkable surface into simple regions without holes.
RecastRegion.BuildRegions(m_ctx, m_chf, cfg.MinRegionArea, cfg.MergeRegionArea);
RcRegions.BuildRegions(m_ctx, m_chf, cfg.MinRegionArea, cfg.MergeRegionArea);
}
else if (m_partitionType == RcPartition.MONOTONE)
{
// Partition the walkable surface into simple regions without holes.
// Monotone partitioning does not need distancefield.
RecastRegion.BuildRegionsMonotone(m_ctx, m_chf, cfg.MinRegionArea, cfg.MergeRegionArea);
RcRegions.BuildRegionsMonotone(m_ctx, m_chf, cfg.MinRegionArea, cfg.MergeRegionArea);
}
else
{
// Partition the walkable surface into simple regions without holes.
RecastRegion.BuildLayerRegions(m_ctx, m_chf, cfg.MinRegionArea);
RcRegions.BuildLayerRegions(m_ctx, m_chf, cfg.MinRegionArea);
}
Assert.That(m_chf.maxDistance, Is.EqualTo(expDistance), "maxDistance");
@ -239,7 +239,7 @@ public class RecastSoloMeshTest
//
// Create contours.
RcContourSet m_cset = RecastContour.BuildContours(m_ctx, m_chf, cfg.MaxSimplificationError, cfg.MaxEdgeLen,
RcContourSet m_cset = RcContours.BuildContours(m_ctx, m_chf, cfg.MaxSimplificationError, cfg.MaxEdgeLen,
RcConstants.RC_CONTOUR_TESS_WALL_EDGES);
Assert.That(m_cset.conts.Count, Is.EqualTo(expContours), "Contours");
@ -248,7 +248,7 @@ public class RecastSoloMeshTest
//
// Build polygon navmesh from the contours.
RcPolyMesh m_pmesh = RecastMesh.BuildPolyMesh(m_ctx, m_cset, cfg.MaxVertsPerPoly);
RcPolyMesh m_pmesh = RcMeshs.BuildPolyMesh(m_ctx, m_cset, cfg.MaxVertsPerPoly);
Assert.That(m_pmesh.nverts, Is.EqualTo(expVerts), "Mesh Verts");
Assert.That(m_pmesh.npolys, Is.EqualTo(expPolys), "Mesh Polys");
@ -257,7 +257,7 @@ public class RecastSoloMeshTest
// on each polygon.
//
RcPolyMeshDetail m_dmesh = RecastMeshDetail.BuildPolyMeshDetail(m_ctx, m_pmesh, m_chf, cfg.DetailSampleDist,
RcPolyMeshDetail m_dmesh = RcMeshDetails.BuildPolyMeshDetail(m_ctx, m_pmesh, m_chf, cfg.DetailSampleDist,
cfg.DetailSampleMaxError);
Assert.That(m_dmesh.nmeshes, Is.EqualTo(expDetMeshes), "Mesh Detail Meshes");
Assert.That(m_dmesh.nverts, Is.EqualTo(expDetVerts), "Mesh Detail Verts");

View File

@ -39,18 +39,18 @@ public class RecastTest
RcTelemetry ctx = new RcTelemetry();
{
int[] areas = { 42 };
RcUtils.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Sets area ID of unwalkable triangle to RC_NULL_AREA");
}
{
int[] areas = { 42 };
RcUtils.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(42), "Does not modify walkable triangle aread ID's");
}
{
int[] areas = { 42 };
walkableSlopeAngle = 0;
RcUtils.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Slopes equal to the max slope are considered unwalkable.");
}
}

View File

@ -59,7 +59,7 @@ public class RecastTileMeshTest
public void TestBuild(string filename)
{
IInputGeomProvider geom = ObjImporter.Load(RcResources.Load(filename));
RecastBuilder builder = new RecastBuilder();
RcBuilder builder = new RcBuilder();
RcConfig cfg = new RcConfig(
true, m_tileSize, m_tileSize, RcConfig.CalcBorder(m_agentRadius, m_cellSize),
m_partitionType,
@ -71,27 +71,27 @@ public class RecastTileMeshTest
m_detailSampleDist, m_detailSampleMaxError,
true, true, true,
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 7, 8);
RecastBuilderResult rcResult = builder.Build(geom, bcfg);
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 7, 8);
RcBuilderResult rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 6, 9);
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 6, 9);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(7));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 9);
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 9);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(9));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 4, 3);
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 4, 3);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(6));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 8);
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 8);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(17));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 0, 8);
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 0, 8);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
@ -101,7 +101,7 @@ public class RecastTileMeshTest
public void TestPerformance()
{
IInputGeomProvider geom = ObjImporter.Load(RcResources.Load("dungeon.obj"));
RecastBuilder builder = new RecastBuilder();
RcBuilder builder = new RcBuilder();
RcConfig cfg = new RcConfig(
true, m_tileSize, m_tileSize,
RcConfig.CalcBorder(m_agentRadius, m_cellSize),
@ -137,14 +137,14 @@ public class RecastTileMeshTest
Console.WriteLine(" Time MT : " + (t3 - t2) / TimeSpan.TicksPerMillisecond);
}
private void Build(IInputGeomProvider geom, RecastBuilder builder, RcConfig cfg, int threads, bool validate)
private void Build(IInputGeomProvider geom, RcBuilder builder, RcConfig cfg, int threads, bool validate)
{
CancellationTokenSource cts = new CancellationTokenSource();
List<RecastBuilderResult> tiles = new();
List<RcBuilderResult> tiles = new();
var task = builder.BuildTilesAsync(geom, cfg, threads, tiles, Task.Factory, cts.Token);
if (validate)
{
RecastBuilderResult rcResult = GetTile(tiles, 7, 8);
RcBuilderResult rcResult = GetTile(tiles, 7, 8);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
rcResult = GetTile(tiles, 6, 9);
@ -175,7 +175,7 @@ public class RecastTileMeshTest
}
}
private RecastBuilderResult GetTile(List<RecastBuilderResult> tiles, int x, int z)
private RcBuilderResult GetTile(List<RcBuilderResult> tiles, int x, int z)
{
return tiles.FirstOrDefault(tile => tile.tileX == x && tile.tileZ == z);
}