forked from mirror/DotRecast
refactor: rename
This commit is contained in:
parent
087582c42e
commit
07e6b08517
|
@ -63,7 +63,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
|
||||||
|
|
||||||
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
|
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
|
||||||
{
|
{
|
||||||
RecastFilledVolumeRasterization.RasterizeBox(
|
RcFilledVolumeRasterization.RasterizeBox(
|
||||||
hf, center, halfEdges, area, (int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
|
hf, center, halfEdges, area, (int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
|
||||||
|
|
||||||
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
|
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
|
||||||
{
|
{
|
||||||
RecastFilledVolumeRasterization.RasterizeCapsule(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
|
RcFilledVolumeRasterization.RasterizeCapsule(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
|
||||||
telemetry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float[] Bounds(RcVec3f start, RcVec3f end, float radius)
|
private static float[] Bounds(RcVec3f start, RcVec3f end, float radius)
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
|
||||||
|
|
||||||
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
|
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);
|
(int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
|
||||||
|
|
||||||
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
|
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);
|
telemetry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
|
||||||
|
|
||||||
public override void Rasterize(RcHeightfield hf, RcTelemetry telemetry)
|
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);
|
telemetry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
|
||||||
{
|
{
|
||||||
for (int i = 0; i < triangles.Length; i += 3)
|
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);
|
(int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
{
|
{
|
||||||
public const int MAX_VERTS_PER_POLY = 6;
|
public const int MAX_VERTS_PER_POLY = 6;
|
||||||
public readonly DtDynamicNavMeshConfig config;
|
public readonly DtDynamicNavMeshConfig config;
|
||||||
private readonly RecastBuilder builder;
|
private readonly RcBuilder builder;
|
||||||
private readonly Dictionary<long, DtDynamicTile> _tiles = new Dictionary<long, DtDynamicTile>();
|
private readonly Dictionary<long, DtDynamicTile> _tiles = new Dictionary<long, DtDynamicTile>();
|
||||||
private readonly RcTelemetry telemetry;
|
private readonly RcTelemetry telemetry;
|
||||||
private readonly DtNavMeshParams navMeshParams;
|
private readonly DtNavMeshParams navMeshParams;
|
||||||
|
@ -57,7 +57,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
config.buildDetailMesh = voxelFile.buildMeshDetail;
|
config.buildDetailMesh = voxelFile.buildMeshDetail;
|
||||||
config.detailSampleDistance = voxelFile.detailSampleDistance;
|
config.detailSampleDistance = voxelFile.detailSampleDistance;
|
||||||
config.detailSampleMaxError = voxelFile.detailSampleMaxError;
|
config.detailSampleMaxError = voxelFile.detailSampleMaxError;
|
||||||
builder = new RecastBuilder();
|
builder = new RcBuilder();
|
||||||
navMeshParams = new DtNavMeshParams();
|
navMeshParams = new DtNavMeshParams();
|
||||||
navMeshParams.orig.x = voxelFile.bounds[0];
|
navMeshParams.orig.x = voxelFile.bounds[0];
|
||||||
navMeshParams.orig.y = voxelFile.bounds[1];
|
navMeshParams.orig.y = voxelFile.bounds[1];
|
||||||
|
@ -254,7 +254,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
return _tiles.Values.Select(t => t.voxelTile).ToList();
|
return _tiles.Values.Select(t => t.voxelTile).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RecastBuilderResult> RecastResults()
|
public List<RcBuilderResult> RecastResults()
|
||||||
{
|
{
|
||||||
return _tiles.Values.Select(t => t.recastResult).ToList();
|
return _tiles.Values.Select(t => t.recastResult).ToList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
{
|
{
|
||||||
public readonly DtVoxelTile voxelTile;
|
public readonly DtVoxelTile voxelTile;
|
||||||
public DtDynamicTileCheckpoint checkpoint;
|
public DtDynamicTileCheckpoint checkpoint;
|
||||||
public RecastBuilderResult recastResult;
|
public RcBuilderResult recastResult;
|
||||||
private DtMeshData meshData;
|
private DtMeshData meshData;
|
||||||
private readonly ConcurrentDictionary<long, IDtCollider> colliders = new ConcurrentDictionary<long, IDtCollider>();
|
private readonly ConcurrentDictionary<long, IDtCollider> colliders = new ConcurrentDictionary<long, IDtCollider>();
|
||||||
private bool dirty = true;
|
private bool dirty = true;
|
||||||
|
@ -44,12 +44,12 @@ namespace DotRecast.Detour.Dynamic
|
||||||
this.voxelTile = voxelTile;
|
this.voxelTile = voxelTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Build(RecastBuilder builder, DtDynamicNavMeshConfig config, RcTelemetry telemetry)
|
public bool Build(RcBuilder builder, DtDynamicNavMeshConfig config, RcTelemetry telemetry)
|
||||||
{
|
{
|
||||||
if (dirty)
|
if (dirty)
|
||||||
{
|
{
|
||||||
RcHeightfield heightfield = BuildHeightfield(config, telemetry);
|
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,
|
DtNavMeshCreateParams option = NavMeshCreateParams(voxelTile.tileX, voxelTile.tileZ, voxelTile.cellSize,
|
||||||
voxelTile.cellHeight, config, r);
|
voxelTile.cellHeight, config, r);
|
||||||
meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
||||||
|
@ -86,7 +86,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
return heightfield;
|
return heightfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RecastBuilderResult BuildRecast(RecastBuilder builder, DtDynamicNavMeshConfig config, DtVoxelTile vt,
|
private RcBuilderResult BuildRecast(RcBuilder builder, DtDynamicNavMeshConfig config, DtVoxelTile vt,
|
||||||
RcHeightfield heightfield, RcTelemetry telemetry)
|
RcHeightfield heightfield, RcTelemetry telemetry)
|
||||||
{
|
{
|
||||||
RcConfig rcConfig = new RcConfig(
|
RcConfig rcConfig = new RcConfig(
|
||||||
|
@ -100,7 +100,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
Math.Min(DtDynamicNavMesh.MAX_VERTS_PER_POLY, config.vertsPerPoly),
|
Math.Min(DtDynamicNavMesh.MAX_VERTS_PER_POLY, config.vertsPerPoly),
|
||||||
config.detailSampleDistance, config.detailSampleMaxError,
|
config.detailSampleDistance, config.detailSampleMaxError,
|
||||||
true, true, true, null, true);
|
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)
|
if (config.keepIntermediateResults)
|
||||||
{
|
{
|
||||||
recastResult = r;
|
recastResult = r;
|
||||||
|
@ -130,7 +130,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
}
|
}
|
||||||
|
|
||||||
private DtNavMeshCreateParams NavMeshCreateParams(int tilex, int tileZ, float cellSize, float cellHeight,
|
private DtNavMeshCreateParams NavMeshCreateParams(int tilex, int tileZ, float cellSize, float cellHeight,
|
||||||
DtDynamicNavMeshConfig config, RecastBuilderResult rcResult)
|
DtDynamicNavMeshConfig config, RcBuilderResult rcResult)
|
||||||
{
|
{
|
||||||
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||||
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
walkbableAreaMod, buildMeshDetail);
|
walkbableAreaMod, buildMeshDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DtVoxelFile From(RcConfig config, List<RecastBuilderResult> results)
|
public static DtVoxelFile From(RcConfig config, List<RcBuilderResult> results)
|
||||||
{
|
{
|
||||||
DtVoxelFile f = new DtVoxelFile();
|
DtVoxelFile f = new DtVoxelFile();
|
||||||
f.version = 1;
|
f.version = 1;
|
||||||
|
@ -106,7 +106,7 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity,
|
float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity,
|
||||||
float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity
|
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.tiles.Add(new DtVoxelTile(r.tileX, r.tileZ, r.GetSolidHeightfield()));
|
||||||
f.bounds[0] = Math.Min(f.bounds[0], r.GetSolidHeightfield().bmin.x);
|
f.bounds[0] = Math.Min(f.bounds[0], r.GetSolidHeightfield().bmin.x);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Recast;
|
using DotRecast.Recast;
|
||||||
using static DotRecast.Core.RcMath;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
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)
|
protected void SampleGroundSegment(ComputeNavMeshHeight heightFunc, GroundSegment seg, int nsamples)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,6 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
public interface IGroundSampler
|
public interface IGroundSampler
|
||||||
{
|
{
|
||||||
void Sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es);
|
void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,9 +15,9 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
private readonly JumpSegmentBuilder jumpSegmentBuilder = new JumpSegmentBuilder();
|
private readonly JumpSegmentBuilder jumpSegmentBuilder = new JumpSegmentBuilder();
|
||||||
|
|
||||||
private readonly List<JumpEdge[]> edges;
|
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;
|
this.results = results;
|
||||||
edges = results.Select(r => edgeExtractor.ExtractEdges(r.GetMesh())).ToList();
|
edges = results.Select(r => edgeExtractor.ExtractEdges(r.GetMesh())).ToList();
|
||||||
|
@ -38,7 +38,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
return links;
|
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);
|
EdgeSampler es = edgeSamplerFactory.Get(acfg, type, edge);
|
||||||
groundSampler.Sample(acfg, result, es);
|
groundSampler.Sample(acfg, result, es);
|
||||||
|
|
|
@ -7,13 +7,13 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
class NavMeshGroundSampler : AbstractGroundSampler
|
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);
|
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));
|
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();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
option.verts = r.GetMesh().verts;
|
option.verts = r.GetMesh().verts;
|
||||||
|
|
|
@ -86,10 +86,10 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
protected virtual RcHeightfieldLayerSet BuildHeightfieldLayerSet(IInputGeomProvider geom, RcConfig cfg, int tx, int ty)
|
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 bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
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);
|
RcHeightfieldLayerSet lset = rcBuilder.BuildLayers(geom, builderCfg);
|
||||||
return lset;
|
return lset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,10 @@ namespace DotRecast.Recast.Demo
|
||||||
private DtNavMesh _navMesh;
|
private DtNavMesh _navMesh;
|
||||||
private DtNavMeshQuery _navMeshQuery;
|
private DtNavMeshQuery _navMeshQuery;
|
||||||
private readonly RcNavMeshBuildSettings _settings;
|
private readonly RcNavMeshBuildSettings _settings;
|
||||||
private IList<RecastBuilderResult> _recastResults;
|
private IList<RcBuilderResult> _recastResults;
|
||||||
private bool _changed;
|
private bool _changed;
|
||||||
|
|
||||||
public DemoSample(DemoInputGeomProvider geom, IList<RecastBuilderResult> recastResults, DtNavMesh navMesh)
|
public DemoSample(DemoInputGeomProvider geom, IList<RcBuilderResult> recastResults, DtNavMesh navMesh)
|
||||||
{
|
{
|
||||||
_geom = geom;
|
_geom = geom;
|
||||||
_recastResults = recastResults;
|
_recastResults = recastResults;
|
||||||
|
@ -56,7 +56,7 @@ namespace DotRecast.Recast.Demo
|
||||||
return _geom;
|
return _geom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<RecastBuilderResult> GetRecastResults()
|
public IList<RcBuilderResult> GetRecastResults()
|
||||||
{
|
{
|
||||||
return _recastResults;
|
return _recastResults;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ namespace DotRecast.Recast.Demo
|
||||||
_changed = changed;
|
_changed = changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(DemoInputGeomProvider geom, IList<RecastBuilderResult> recastResults, DtNavMesh navMesh)
|
public void Update(DemoInputGeomProvider geom, IList<RcBuilderResult> recastResults, DtNavMesh navMesh)
|
||||||
{
|
{
|
||||||
_geom = geom;
|
_geom = geom;
|
||||||
_recastResults = recastResults;
|
_recastResults = recastResults;
|
||||||
|
|
|
@ -23,6 +23,7 @@ using DotRecast.Core;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Recast.Toolset.Builder;
|
using DotRecast.Recast.Toolset.Builder;
|
||||||
using DotRecast.Recast.Toolset.Geom;
|
using DotRecast.Recast.Toolset.Geom;
|
||||||
|
using static DotRecast.Recast.RcCommons;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ public class NavMeshRenderer
|
||||||
|
|
||||||
DtNavMeshQuery navQuery = sample.GetNavMeshQuery();
|
DtNavMeshQuery navQuery = sample.GetNavMeshQuery();
|
||||||
DemoInputGeomProvider geom = sample.GetInputGeom();
|
DemoInputGeomProvider geom = sample.GetInputGeom();
|
||||||
IList<RecastBuilderResult> rcBuilderResults = sample.GetRecastResults();
|
IList<RcBuilderResult> rcBuilderResults = sample.GetRecastResults();
|
||||||
DtNavMesh navMesh = sample.GetNavMesh();
|
DtNavMesh navMesh = sample.GetNavMesh();
|
||||||
var settings = sample.GetSettings();
|
var settings = sample.GetSettings();
|
||||||
_debugDraw.Fog(true);
|
_debugDraw.Fog(true);
|
||||||
|
@ -81,7 +82,7 @@ public class NavMeshRenderer
|
||||||
int gw = 0, gh = 0;
|
int gw = 0, gh = 0;
|
||||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
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 tw = (gw + settings.tileSize - 1) / settings.tileSize;
|
||||||
int th = (gh + settings.tileSize - 1) / settings.tileSize;
|
int th = (gh + settings.tileSize - 1) / settings.tileSize;
|
||||||
float s = settings.tileSize * settings.cellSize;
|
float s = settings.tileSize * settings.cellSize;
|
||||||
|
@ -120,7 +121,7 @@ public class NavMeshRenderer
|
||||||
|
|
||||||
_debugDraw.DepthMask(true);
|
_debugDraw.DepthMask(true);
|
||||||
|
|
||||||
foreach (RecastBuilderResult rcBuilderResult in rcBuilderResults)
|
foreach (RcBuilderResult rcBuilderResult in rcBuilderResults)
|
||||||
{
|
{
|
||||||
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT)
|
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT)
|
||||||
{
|
{
|
||||||
|
|
|
@ -324,7 +324,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
|
|
||||||
if (null != mesh)
|
if (null != mesh)
|
||||||
{
|
{
|
||||||
_sample.Update(_sample.GetInputGeom(), ImmutableArray<RecastBuilderResult>.Empty, mesh);
|
_sample.Update(_sample.GetInputGeom(), ImmutableArray<RcBuilderResult>.Empty, mesh);
|
||||||
toolset.SetEnabled(true);
|
toolset.SetEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,7 +375,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
_imgui = new ImGuiController(_gl, window, _input, imGuiFontConfig);
|
_imgui = new ImGuiController(_gl, window, _input, imGuiFontConfig);
|
||||||
|
|
||||||
DemoInputGeomProvider geom = LoadInputMesh("nav_test.obj");
|
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 = new RcSettingsView(this);
|
||||||
settingsView.SetSample(_sample);
|
settingsView.SetSample(_sample);
|
||||||
|
@ -454,7 +454,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
var settings = _sample.GetSettings();
|
var settings = _sample.GetSettings();
|
||||||
RcVec3f bmin = _sample.GetInputGeom().GetMeshBoundsMin();
|
RcVec3f bmin = _sample.GetInputGeom().GetMeshBoundsMin();
|
||||||
RcVec3f bmax = _sample.GetInputGeom().GetMeshBoundsMax();
|
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.SetVoxels(gw, gh);
|
||||||
settingsView.SetTiles(tileNavMeshBuilder.GetTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
settingsView.SetTiles(tileNavMeshBuilder.GetTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
||||||
settingsView.SetMaxTiles(tileNavMeshBuilder.GetMaxTiles(_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)
|
else if (0 < _sample.GetRecastResults().Count)
|
||||||
{
|
{
|
||||||
foreach (RecastBuilderResult result in _sample.GetRecastResults())
|
foreach (RcBuilderResult result in _sample.GetRecastResults())
|
||||||
{
|
{
|
||||||
if (result.GetSolidHeightfield() != null)
|
if (result.GetSolidHeightfield() != null)
|
||||||
{
|
{
|
||||||
|
@ -662,7 +662,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
{
|
{
|
||||||
var geom = LoadInputMesh(args.FilePath);
|
var geom = LoadInputMesh(args.FilePath);
|
||||||
|
|
||||||
_sample.Update(geom, ImmutableArray<RecastBuilderResult>.Empty, null);
|
_sample.Update(geom, ImmutableArray<RcBuilderResult>.Empty, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args)
|
private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args)
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
{
|
{
|
||||||
public static DtNavMeshCreateParams GetNavMeshCreateParams(IInputGeomProvider geom, float cellSize,
|
public static DtNavMeshCreateParams GetNavMeshCreateParams(IInputGeomProvider geom, float cellSize,
|
||||||
float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
||||||
RecastBuilderResult rcResult)
|
RcBuilderResult rcResult)
|
||||||
{
|
{
|
||||||
RcPolyMesh pmesh = rcResult.GetMesh();
|
RcPolyMesh pmesh = rcResult.GetMesh();
|
||||||
RcPolyMeshDetail dmesh = rcResult.GetMeshDetail();
|
RcPolyMeshDetail dmesh = rcResult.GetMeshDetail();
|
||||||
|
|
|
@ -7,17 +7,17 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
public class NavMeshBuildResult
|
public class NavMeshBuildResult
|
||||||
{
|
{
|
||||||
public readonly bool Success;
|
public readonly bool Success;
|
||||||
public readonly IList<RecastBuilderResult> RecastBuilderResults;
|
public readonly IList<RcBuilderResult> RecastBuilderResults;
|
||||||
public readonly DtNavMesh NavMesh;
|
public readonly DtNavMesh NavMesh;
|
||||||
|
|
||||||
public NavMeshBuildResult()
|
public NavMeshBuildResult()
|
||||||
{
|
{
|
||||||
Success = false;
|
Success = false;
|
||||||
RecastBuilderResults = Array.Empty<RecastBuilderResult>();
|
RecastBuilderResults = Array.Empty<RcBuilderResult>();
|
||||||
NavMesh = null;
|
NavMesh = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavMeshBuildResult(IList<RecastBuilderResult> recastBuilderResults, DtNavMesh navMesh)
|
public NavMeshBuildResult(IList<RcBuilderResult> recastBuilderResults, DtNavMesh navMesh)
|
||||||
{
|
{
|
||||||
Success = true;
|
Success = true;
|
||||||
RecastBuilderResults = recastBuilderResults;
|
RecastBuilderResults = recastBuilderResults;
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
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);
|
var meshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult);
|
||||||
if (null == meshData)
|
if (null == meshData)
|
||||||
{
|
{
|
||||||
|
@ -76,17 +76,17 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
return new DtNavMesh(meshData, vertsPerPoly, 0);
|
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());
|
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||||
RecastBuilder rcBuilder = new RecastBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
return rcBuilder.Build(geom, bcfg);
|
return rcBuilder.Build(geom, bcfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtMeshData BuildMeshData(DemoInputGeomProvider geom,
|
public DtMeshData BuildMeshData(DemoInputGeomProvider geom,
|
||||||
float cellSize, float cellHeight,
|
float cellSize, float cellHeight,
|
||||||
float agentHeight, float agentRadius, float agentMaxClimb,
|
float agentHeight, float agentRadius, float agentMaxClimb,
|
||||||
RecastBuilderResult result)
|
RcBuilderResult result)
|
||||||
{
|
{
|
||||||
DtNavMeshCreateParams option = DemoNavMeshBuilder
|
DtNavMeshCreateParams option = DemoNavMeshBuilder
|
||||||
.GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result);
|
.GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result);
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
float detailSampleDist, float detailSampleMaxError,
|
float detailSampleDist, float detailSampleMaxError,
|
||||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
||||||
{
|
{
|
||||||
List<RecastBuilderResult> results = BuildRecastResult(
|
List<RcBuilderResult> results = BuildRecastResult(
|
||||||
geom,
|
geom,
|
||||||
tileSize,
|
tileSize,
|
||||||
partitionType,
|
partitionType,
|
||||||
|
@ -73,7 +73,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
return new NavMeshBuildResult(results, tileNavMesh);
|
return new NavMeshBuildResult(results, tileNavMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RecastBuilderResult> BuildRecastResult(IInputGeomProvider geom,
|
public List<RcBuilderResult> BuildRecastResult(IInputGeomProvider geom,
|
||||||
int tileSize,
|
int tileSize,
|
||||||
RcPartition partitionType,
|
RcPartition partitionType,
|
||||||
float cellSize, float cellHeight,
|
float cellSize, float cellHeight,
|
||||||
|
@ -96,7 +96,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
detailSampleDist, detailSampleMaxError,
|
detailSampleDist, detailSampleMaxError,
|
||||||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
||||||
RecastBuilder rcBuilder = new RecastBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
return rcBuilder.BuildTiles(geom, cfg, Task.Factory);
|
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,
|
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
|
// Add tiles to nav mesh
|
||||||
List<DtMeshData> meshData = new List<DtMeshData>();
|
List<DtMeshData> meshData = new List<DtMeshData>();
|
||||||
foreach (RecastBuilderResult result in results)
|
foreach (RcBuilderResult result in results)
|
||||||
{
|
{
|
||||||
int x = result.tileX;
|
int x = result.tileX;
|
||||||
int z = result.tileZ;
|
int z = result.tileZ;
|
||||||
|
@ -155,7 +155,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
|
|
||||||
private int GetTileBits(IInputGeomProvider geom, float cellSize, int tileSize)
|
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 tw = (gw + tileSize - 1) / tileSize;
|
||||||
int th = (gh + tileSize - 1) / tileSize;
|
int th = (gh + tileSize - 1) / tileSize;
|
||||||
int tileBits = Math.Min(DtUtils.Ilog2(DtUtils.NextPow2(tw * th)), 14);
|
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)
|
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 tw = (gw + tileSize - 1) / tileSize;
|
||||||
int th = (gh + tileSize - 1) / tileSize;
|
int th = (gh + tileSize - 1) / tileSize;
|
||||||
return new int[] { tw, th };
|
return new int[] { tw, th };
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
IList<RcConvexVolume> vols = geom.ConvexVolumes();
|
IList<RcConvexVolume> vols = geom.ConvexVolumes();
|
||||||
for (int i = 0; i < vols.Count; ++i)
|
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)
|
&& pos.y <= vols[i].hmax)
|
||||||
{
|
{
|
||||||
nearestIndex = i;
|
nearestIndex = i;
|
||||||
|
@ -130,7 +130,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
if (polyOffset > 0.01f)
|
if (polyOffset > 0.01f)
|
||||||
{
|
{
|
||||||
float[] offset = new float[verts.Length * 2];
|
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)
|
if (noffset > 0)
|
||||||
{
|
{
|
||||||
verts = RcArrayUtils.CopyOf(offset, 0, noffset * 3);
|
verts = RcArrayUtils.CopyOf(offset, 0, noffset * 3);
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
return _links;
|
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)
|
if (_annotationBuilder == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
// Init cache
|
// Init cache
|
||||||
var bmin = geom.GetMeshBoundsMin();
|
var bmin = geom.GetMeshBoundsMin();
|
||||||
var bmax = geom.GetMeshBoundsMax();
|
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 ts = setting.tileSize;
|
||||||
int tw = (gw + ts - 1) / ts;
|
int tw = (gw + ts - 1) / ts;
|
||||||
int th = (gh + ts - 1) / ts;
|
int th = (gh + ts - 1) / ts;
|
||||||
|
@ -77,7 +77,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
_tc.BuildNavMeshTile(refs);
|
_tc.BuildNavMeshTile(refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NavMeshBuildResult(RcImmutableArray<RecastBuilderResult>.Empty, _tc.GetNavMesh());
|
return new NavMeshBuildResult(RcImmutableArray<RcBuilderResult>.Empty, _tc.GetNavMesh());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearAllTempObstacles()
|
public void ClearAllTempObstacles()
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
var bmin = geom.GetMeshBoundsMin();
|
var bmin = geom.GetMeshBoundsMin();
|
||||||
var bmax = geom.GetMeshBoundsMax();
|
var bmax = geom.GetMeshBoundsMax();
|
||||||
int gw = 0, gh = 0;
|
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 ts = settings.tileSize;
|
||||||
int tw = (gw + ts - 1) / ts;
|
int tw = (gw + ts - 1) / ts;
|
||||||
|
@ -45,7 +45,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
var bmin = geom.GetMeshBoundsMin();
|
var bmin = geom.GetMeshBoundsMin();
|
||||||
var bmax = geom.GetMeshBoundsMax();
|
var bmax = geom.GetMeshBoundsMax();
|
||||||
int gw = 0, gh = 0;
|
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 ts = settings.tileSize;
|
||||||
int tw = (gw + ts - 1) / ts;
|
int tw = (gw + ts - 1) / ts;
|
||||||
|
@ -91,7 +91,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
);
|
);
|
||||||
|
|
||||||
var beginTick = RcFrequency.Ticks;
|
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 result = rb.BuildTile(geom, cfg, bmin, bmax, tx, ty, new RcAtomicInteger(0), 1);
|
||||||
|
|
||||||
var tb = new TileNavMeshBuilder();
|
var tb = new TileNavMeshBuilder();
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,8 +24,9 @@ using DotRecast.Core;
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
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.
|
/// Erodes the walkable area within the heightfield by the specified radius.
|
||||||
///
|
///
|
||||||
|
@ -72,15 +73,15 @@ namespace DotRecast.Recast
|
||||||
int neighborCount = 0;
|
int neighborCount = 0;
|
||||||
for (int direction = 0; direction < 4; ++direction)
|
for (int direction = 0; direction < 4; ++direction)
|
||||||
{
|
{
|
||||||
int neighborConnection = RecastCommon.GetCon(span, direction);
|
int neighborConnection = GetCon(span, direction);
|
||||||
if (neighborConnection == RC_NOT_CONNECTED)
|
if (neighborConnection == RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int neighborX = x + RecastCommon.GetDirOffsetX(direction);
|
int neighborX = x + GetDirOffsetX(direction);
|
||||||
int neighborZ = z + RecastCommon.GetDirOffsetY(direction);
|
int neighborZ = z + GetDirOffsetY(direction);
|
||||||
int neighborSpanIndex = compactHeightfield.cells[neighborX + neighborZ * zStride].index + RecastCommon.GetCon(span, direction);
|
int neighborSpanIndex = compactHeightfield.cells[neighborX + neighborZ * zStride].index + GetCon(span, direction);
|
||||||
if (compactHeightfield.areas[neighborSpanIndex] == RC_NULL_AREA)
|
if (compactHeightfield.areas[neighborSpanIndex] == RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -112,12 +113,12 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
RcCompactSpan span = compactHeightfield.spans[spanIndex];
|
RcCompactSpan span = compactHeightfield.spans[spanIndex];
|
||||||
|
|
||||||
if (RecastCommon.GetCon(span, 0) != RC_NOT_CONNECTED)
|
if (GetCon(span, 0) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
// (-1,0)
|
// (-1,0)
|
||||||
int aX = x + RecastCommon.GetDirOffsetX(0);
|
int aX = x + GetDirOffsetX(0);
|
||||||
int aY = z + RecastCommon.GetDirOffsetY(0);
|
int aY = z + GetDirOffsetY(0);
|
||||||
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + RecastCommon.GetCon(span, 0);
|
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + GetCon(span, 0);
|
||||||
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
||||||
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
|
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
|
||||||
if (newDistance < distanceToBoundary[spanIndex])
|
if (newDistance < distanceToBoundary[spanIndex])
|
||||||
|
@ -126,11 +127,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// (-1,-1)
|
// (-1,-1)
|
||||||
if (RecastCommon.GetCon(aSpan, 3) != RC_NOT_CONNECTED)
|
if (GetCon(aSpan, 3) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int bX = aX + RecastCommon.GetDirOffsetX(3);
|
int bX = aX + GetDirOffsetX(3);
|
||||||
int bY = aY + RecastCommon.GetDirOffsetY(3);
|
int bY = aY + GetDirOffsetY(3);
|
||||||
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + RecastCommon.GetCon(aSpan, 3);
|
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + GetCon(aSpan, 3);
|
||||||
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
|
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
|
||||||
if (newDistance < distanceToBoundary[spanIndex])
|
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)
|
// (0,-1)
|
||||||
int aX = x + RecastCommon.GetDirOffsetX(3);
|
int aX = x + GetDirOffsetX(3);
|
||||||
int aY = z + RecastCommon.GetDirOffsetY(3);
|
int aY = z + GetDirOffsetY(3);
|
||||||
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + RecastCommon.GetCon(span, 3);
|
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + GetCon(span, 3);
|
||||||
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
||||||
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
|
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
|
||||||
if (newDistance < distanceToBoundary[spanIndex])
|
if (newDistance < distanceToBoundary[spanIndex])
|
||||||
|
@ -153,11 +154,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// (1,-1)
|
// (1,-1)
|
||||||
if (RecastCommon.GetCon(aSpan, 2) != RC_NOT_CONNECTED)
|
if (GetCon(aSpan, 2) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int bX = aX + RecastCommon.GetDirOffsetX(2);
|
int bX = aX + GetDirOffsetX(2);
|
||||||
int bY = aY + RecastCommon.GetDirOffsetY(2);
|
int bY = aY + GetDirOffsetY(2);
|
||||||
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + RecastCommon.GetCon(aSpan, 2);
|
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + GetCon(aSpan, 2);
|
||||||
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
|
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
|
||||||
if (newDistance < distanceToBoundary[spanIndex])
|
if (newDistance < distanceToBoundary[spanIndex])
|
||||||
{
|
{
|
||||||
|
@ -180,12 +181,12 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
RcCompactSpan span = compactHeightfield.spans[i];
|
RcCompactSpan span = compactHeightfield.spans[i];
|
||||||
|
|
||||||
if (RecastCommon.GetCon(span, 2) != RC_NOT_CONNECTED)
|
if (GetCon(span, 2) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
// (1,0)
|
// (1,0)
|
||||||
int aX = x + RecastCommon.GetDirOffsetX(2);
|
int aX = x + GetDirOffsetX(2);
|
||||||
int aY = z + RecastCommon.GetDirOffsetY(2);
|
int aY = z + GetDirOffsetY(2);
|
||||||
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + RecastCommon.GetCon(span, 2);
|
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + GetCon(span, 2);
|
||||||
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
||||||
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
|
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
|
||||||
if (newDistance < distanceToBoundary[i])
|
if (newDistance < distanceToBoundary[i])
|
||||||
|
@ -194,11 +195,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// (1,1)
|
// (1,1)
|
||||||
if (RecastCommon.GetCon(aSpan, 1) != RC_NOT_CONNECTED)
|
if (GetCon(aSpan, 1) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int bX = aX + RecastCommon.GetDirOffsetX(1);
|
int bX = aX + GetDirOffsetX(1);
|
||||||
int bY = aY + RecastCommon.GetDirOffsetY(1);
|
int bY = aY + GetDirOffsetY(1);
|
||||||
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + RecastCommon.GetCon(aSpan, 1);
|
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + GetCon(aSpan, 1);
|
||||||
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
|
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
|
||||||
if (newDistance < distanceToBoundary[i])
|
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)
|
// (0,1)
|
||||||
int aX = x + RecastCommon.GetDirOffsetX(1);
|
int aX = x + GetDirOffsetX(1);
|
||||||
int aY = z + RecastCommon.GetDirOffsetY(1);
|
int aY = z + GetDirOffsetY(1);
|
||||||
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + RecastCommon.GetCon(span, 1);
|
int aIndex = compactHeightfield.cells[aX + aY * xSize].index + GetCon(span, 1);
|
||||||
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
||||||
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
|
newDistance = Math.Min(distanceToBoundary[aIndex] + 2, 255);
|
||||||
if (newDistance < distanceToBoundary[i])
|
if (newDistance < distanceToBoundary[i])
|
||||||
|
@ -221,11 +222,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// (-1,1)
|
// (-1,1)
|
||||||
if (RecastCommon.GetCon(aSpan, 0) != RC_NOT_CONNECTED)
|
if (GetCon(aSpan, 0) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int bX = aX + RecastCommon.GetDirOffsetX(0);
|
int bX = aX + GetDirOffsetX(0);
|
||||||
int bY = aY + RecastCommon.GetDirOffsetY(0);
|
int bY = aY + GetDirOffsetY(0);
|
||||||
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + RecastCommon.GetCon(aSpan, 0);
|
int bIndex = compactHeightfield.cells[bX + bY * xSize].index + GetCon(aSpan, 0);
|
||||||
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
|
newDistance = Math.Min(distanceToBoundary[bIndex] + 3, 255);
|
||||||
if (newDistance < distanceToBoundary[i])
|
if (newDistance < distanceToBoundary[i])
|
||||||
{
|
{
|
||||||
|
@ -291,14 +292,14 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
for (int dir = 0; dir < 4; ++dir)
|
||||||
{
|
{
|
||||||
if (RecastCommon.GetCon(span, dir) == RC_NOT_CONNECTED)
|
if (GetCon(span, dir) == RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int aX = x + RecastCommon.GetDirOffsetX(dir);
|
int aX = x + GetDirOffsetX(dir);
|
||||||
int aZ = z + RecastCommon.GetDirOffsetY(dir);
|
int aZ = z + GetDirOffsetY(dir);
|
||||||
int aIndex = compactHeightfield.cells[aX + aZ * zStride].index + RecastCommon.GetCon(span, dir);
|
int aIndex = compactHeightfield.cells[aX + aZ * zStride].index + GetCon(span, dir);
|
||||||
if (compactHeightfield.areas[aIndex] != RC_NULL_AREA)
|
if (compactHeightfield.areas[aIndex] != RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
neighborAreas[dir * 2 + 0] = compactHeightfield.areas[aIndex];
|
neighborAreas[dir * 2 + 0] = compactHeightfield.areas[aIndex];
|
||||||
|
@ -306,12 +307,12 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
RcCompactSpan aSpan = compactHeightfield.spans[aIndex];
|
||||||
int dir2 = (dir + 1) & 0x3;
|
int dir2 = (dir + 1) & 0x3;
|
||||||
int neighborConnection2 = RecastCommon.GetCon(aSpan, dir2);
|
int neighborConnection2 = GetCon(aSpan, dir2);
|
||||||
if (neighborConnection2 != RC_NOT_CONNECTED)
|
if (neighborConnection2 != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int bX = aX + RecastCommon.GetDirOffsetX(dir2);
|
int bX = aX + GetDirOffsetX(dir2);
|
||||||
int bZ = aZ + RecastCommon.GetDirOffsetY(dir2);
|
int bZ = aZ + GetDirOffsetY(dir2);
|
||||||
int bIndex = compactHeightfield.cells[bX + bZ * zStride].index + RecastCommon.GetCon(aSpan, dir2);
|
int bIndex = compactHeightfield.cells[bX + bZ * zStride].index + GetCon(aSpan, dir2);
|
||||||
if (compactHeightfield.areas[bIndex] != RC_NULL_AREA)
|
if (compactHeightfield.areas[bIndex] != RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
neighborAreas[dir * 2 + 1] = compactHeightfield.areas[bIndex];
|
neighborAreas[dir * 2 + 1] = compactHeightfield.areas[bIndex];
|
||||||
|
@ -544,7 +545,7 @@ namespace DotRecast.Recast
|
||||||
compactHeightfield.bmin.z + (z + 0.5f) * compactHeightfield.cs
|
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]);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,26 +27,29 @@ using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RecastBuilder
|
using static RcCommons;
|
||||||
|
using static RcAreas;
|
||||||
|
|
||||||
|
public class RcBuilder
|
||||||
{
|
{
|
||||||
private readonly IRecastBuilderProgressListener progressListener;
|
private readonly IRecastBuilderProgressListener progressListener;
|
||||||
|
|
||||||
public RecastBuilder()
|
public RcBuilder()
|
||||||
{
|
{
|
||||||
progressListener = null;
|
progressListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecastBuilder(IRecastBuilderProgressListener progressListener)
|
public RcBuilder(IRecastBuilderProgressListener progressListener)
|
||||||
{
|
{
|
||||||
this.progressListener = 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 bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
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);
|
||||||
List<RecastBuilderResult> results = new List<RecastBuilderResult>();
|
List<RcBuilderResult> results = new List<RcBuilderResult>();
|
||||||
if (null != taskFactory)
|
if (null != taskFactory)
|
||||||
{
|
{
|
||||||
BuildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, default);
|
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 bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
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;
|
Task task;
|
||||||
if (1 < threads)
|
if (1 < threads)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +82,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task BuildSingleThreadAsync(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax,
|
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);
|
RcAtomicInteger counter = new RcAtomicInteger(0);
|
||||||
for (int y = 0; y < th; ++y)
|
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,
|
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);
|
RcAtomicInteger counter = new RcAtomicInteger(0);
|
||||||
CountdownEvent latch = new CountdownEvent(tw * th);
|
CountdownEvent latch = new CountdownEvent(tw * th);
|
||||||
|
@ -113,7 +116,7 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
try
|
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)
|
lock (results)
|
||||||
{
|
{
|
||||||
results.Add(tile);
|
results.Add(tile);
|
||||||
|
@ -143,10 +146,10 @@ namespace DotRecast.Recast
|
||||||
return Task.WhenAll(tasks.ToArray());
|
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)
|
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)
|
if (progressListener != null)
|
||||||
{
|
{
|
||||||
progressListener.OnProgress(counter.IncrementAndGet(), total);
|
progressListener.OnProgress(counter.IncrementAndGet(), total);
|
||||||
|
@ -155,18 +158,18 @@ namespace DotRecast.Recast
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecastBuilderResult Build(IInputGeomProvider geom, RecastBuilderConfig builderCfg)
|
public RcBuilderResult Build(IInputGeomProvider geom, RcBuilderConfig builderCfg)
|
||||||
{
|
{
|
||||||
RcConfig cfg = builderCfg.cfg;
|
RcConfig cfg = builderCfg.cfg;
|
||||||
RcTelemetry ctx = new RcTelemetry();
|
RcTelemetry ctx = new RcTelemetry();
|
||||||
//
|
//
|
||||||
// Step 1. Rasterize input polygon soup.
|
// 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);
|
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);
|
FilterHeightfield(solid, cfg, ctx);
|
||||||
RcCompactHeightfield chf = BuildCompactHeightfield(geom, cfg, ctx, solid);
|
RcCompactHeightfield chf = BuildCompactHeightfield(geom, cfg, ctx, solid);
|
||||||
|
@ -213,20 +216,20 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
// Prepare for region partitioning, by calculating distance field
|
// Prepare for region partitioning, by calculating distance field
|
||||||
// along the walkable surface.
|
// along the walkable surface.
|
||||||
RecastRegion.BuildDistanceField(ctx, chf);
|
RcRegions.BuildDistanceField(ctx, chf);
|
||||||
// Partition the walkable surface into simple regions without holes.
|
// 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)
|
else if (cfg.Partition == RcPartitionType.MONOTONE.Value)
|
||||||
{
|
{
|
||||||
// Partition the walkable surface into simple regions without holes.
|
// Partition the walkable surface into simple regions without holes.
|
||||||
// Monotone partitioning does not need distancefield.
|
// Monotone partitioning does not need distancefield.
|
||||||
RecastRegion.BuildRegionsMonotone(ctx, chf, cfg.MinRegionArea, cfg.MergeRegionArea);
|
RcRegions.BuildRegionsMonotone(ctx, chf, cfg.MinRegionArea, cfg.MergeRegionArea);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Partition the walkable surface into simple regions without holes.
|
// 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.
|
// 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);
|
RcConstants.RC_CONTOUR_TESS_WALL_EDGES);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Step 6. Build polygons mesh from contours.
|
// 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
|
// Step 7. Create detail mesh which allows to access approximate height
|
||||||
// on each polygon.
|
// on each polygon.
|
||||||
//
|
//
|
||||||
RcPolyMeshDetail dmesh = cfg.BuildMeshDetail
|
RcPolyMeshDetail dmesh = cfg.BuildMeshDetail
|
||||||
? RecastMeshDetail.BuildPolyMeshDetail(ctx, pmesh, chf, cfg.DetailSampleDist, cfg.DetailSampleMaxError)
|
? RcMeshDetails.BuildPolyMeshDetail(ctx, pmesh, chf, cfg.DetailSampleDist, cfg.DetailSampleMaxError)
|
||||||
: null;
|
: 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.
|
// as well as filter spans where the character cannot possibly stand.
|
||||||
if (cfg.FilterLowHangingObstacles)
|
if (cfg.FilterLowHangingObstacles)
|
||||||
{
|
{
|
||||||
RecastFilter.FilterLowHangingWalkableObstacles(ctx, cfg.WalkableClimb, solid);
|
RcFilters.FilterLowHangingWalkableObstacles(ctx, cfg.WalkableClimb, solid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.FilterLedgeSpans)
|
if (cfg.FilterLedgeSpans)
|
||||||
{
|
{
|
||||||
RecastFilter.FilterLedgeSpans(ctx, cfg.WalkableHeight, cfg.WalkableClimb, solid);
|
RcFilters.FilterLedgeSpans(ctx, cfg.WalkableHeight, cfg.WalkableClimb, solid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.FilterWalkableLowHeightSpans)
|
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.
|
// 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
|
// This will result more cache coherent data as well as the neighbours
|
||||||
// between walkable cells will be calculated.
|
// 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.
|
// Erode the walkable area by agent radius.
|
||||||
RecastArea.ErodeWalkableArea(ctx, cfg.WalkableRadius, chf);
|
ErodeWalkableArea(ctx, cfg.WalkableRadius, chf);
|
||||||
// (Optional) Mark areas.
|
// (Optional) Mark areas.
|
||||||
if (geom != null)
|
if (geom != null)
|
||||||
{
|
{
|
||||||
foreach (RcConvexVolume vol in geom.ConvexVolumes())
|
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;
|
return chf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcHeightfieldLayerSet BuildLayers(IInputGeomProvider geom, RecastBuilderConfig builderCfg)
|
public RcHeightfieldLayerSet BuildLayers(IInputGeomProvider geom, RcBuilderConfig builderCfg)
|
||||||
{
|
{
|
||||||
RcTelemetry ctx = new RcTelemetry();
|
RcTelemetry ctx = new RcTelemetry();
|
||||||
RcHeightfield solid = RecastVoxelization.BuildSolidHeightfield(geom, builderCfg, ctx);
|
RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(geom, builderCfg, ctx);
|
||||||
FilterHeightfield(solid, builderCfg.cfg, ctx);
|
FilterHeightfield(solid, builderCfg.cfg, ctx);
|
||||||
RcCompactHeightfield chf = BuildCompactHeightfield(geom, builderCfg.cfg, ctx, solid);
|
RcCompactHeightfield chf = BuildCompactHeightfield(geom, builderCfg.cfg, ctx, solid);
|
||||||
return RecastLayers.BuildHeightfieldLayers(ctx, chf, builderCfg.cfg.WalkableHeight);
|
return RcLayers.BuildHeightfieldLayers(ctx, chf, builderCfg.cfg.WalkableHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RecastBuilderConfig
|
public class RcBuilderConfig
|
||||||
{
|
{
|
||||||
public readonly RcConfig cfg;
|
public readonly RcConfig cfg;
|
||||||
|
|
||||||
|
@ -41,11 +41,11 @@ namespace DotRecast.Recast
|
||||||
/** The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] **/
|
/** The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] **/
|
||||||
public readonly RcVec3f bmax = new RcVec3f();
|
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.tileX = tileX;
|
||||||
this.tileZ = tileZ;
|
this.tileZ = tileZ;
|
||||||
|
@ -92,7 +92,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
else
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RecastBuilderResult
|
public class RcBuilderResult
|
||||||
{
|
{
|
||||||
public readonly int tileX;
|
public readonly int tileX;
|
||||||
public readonly int tileZ;
|
public readonly int tileZ;
|
||||||
|
@ -14,7 +14,7 @@ namespace DotRecast.Recast
|
||||||
private readonly RcHeightfield solid;
|
private readonly RcHeightfield solid;
|
||||||
private readonly RcTelemetry telemetry;
|
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.tileX = tileX;
|
||||||
this.tileZ = tileZ;
|
this.tileZ = tileZ;
|
|
@ -23,10 +23,61 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
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)
|
public static void CalcBounds(float[] verts, int nv, float[] bmin, float[] bmax)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
|
@ -25,7 +25,9 @@ using static DotRecast.Recast.RcConstants;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
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_LAYERS = RC_NOT_CONNECTED - 1;
|
||||||
private const int MAX_HEIGHT = RcConstants.SPAN_MAX_HEIGHT;
|
private const int MAX_HEIGHT = RcConstants.SPAN_MAX_HEIGHT;
|
||||||
|
@ -117,9 +119,9 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
for (int dir = 0; dir < 4; ++dir)
|
||||||
{
|
{
|
||||||
RecastCommon.SetCon(s, dir, RC_NOT_CONNECTED);
|
SetCon(s, dir, RC_NOT_CONNECTED);
|
||||||
int nx = x + RecastCommon.GetDirOffsetX(dir);
|
int nx = x + GetDirOffsetX(dir);
|
||||||
int ny = y + RecastCommon.GetDirOffsetY(dir);
|
int ny = y + GetDirOffsetY(dir);
|
||||||
// First check that the neighbour cell is in bounds.
|
// First check that the neighbour cell is in bounds.
|
||||||
if (nx < 0 || ny < 0 || nx >= w || ny >= h)
|
if (nx < 0 || ny < 0 || nx >= w || ny >= h)
|
||||||
continue;
|
continue;
|
||||||
|
@ -145,7 +147,7 @@ namespace DotRecast.Recast
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
RecastCommon.SetCon(s, dir, lidx);
|
SetCon(s, dir, lidx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,8 +25,9 @@ using DotRecast.Core;
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
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)
|
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.
|
// border vertices which are in between two areas to be removed.
|
||||||
regs[0] = chf.spans[i].reg | (chf.areas[i] << 16);
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dir);
|
||||||
RcCompactSpan @as = chf.spans[ai];
|
RcCompactSpan @as = chf.spans[ai];
|
||||||
ch = Math.Max(ch, @as.y);
|
ch = Math.Max(ch, @as.y);
|
||||||
regs[1] = chf.spans[ai].reg | (chf.areas[ai] << 16);
|
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 ax2 = ax + GetDirOffsetX(dirp);
|
||||||
int ay2 = ay + RecastCommon.GetDirOffsetY(dirp);
|
int ay2 = ay + GetDirOffsetY(dirp);
|
||||||
int ai2 = chf.cells[ax2 + ay2 * chf.width].index + RecastCommon.GetCon(@as, dirp);
|
int ai2 = chf.cells[ax2 + ay2 * chf.width].index + GetCon(@as, dirp);
|
||||||
RcCompactSpan as2 = chf.spans[ai2];
|
RcCompactSpan as2 = chf.spans[ai2];
|
||||||
ch = Math.Max(ch, as2.y);
|
ch = Math.Max(ch, as2.y);
|
||||||
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
|
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 ax = x + GetDirOffsetX(dirp);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dirp);
|
int ay = y + GetDirOffsetY(dirp);
|
||||||
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dirp);
|
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dirp);
|
||||||
RcCompactSpan @as = chf.spans[ai];
|
RcCompactSpan @as = chf.spans[ai];
|
||||||
ch = Math.Max(ch, @as.y);
|
ch = Math.Max(ch, @as.y);
|
||||||
regs[3] = chf.spans[ai].reg | (chf.areas[ai] << 16);
|
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 ax2 = ax + GetDirOffsetX(dir);
|
||||||
int ay2 = ay + RecastCommon.GetDirOffsetY(dir);
|
int ay2 = ay + GetDirOffsetY(dir);
|
||||||
int ai2 = chf.cells[ax2 + ay2 * chf.width].index + RecastCommon.GetCon(@as, dir);
|
int ai2 = chf.cells[ax2 + ay2 * chf.width].index + GetCon(@as, dir);
|
||||||
RcCompactSpan as2 = chf.spans[ai2];
|
RcCompactSpan as2 = chf.spans[ai2];
|
||||||
ch = Math.Max(ch, as2.y);
|
ch = Math.Max(ch, as2.y);
|
||||||
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
|
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
|
||||||
|
@ -146,11 +147,11 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
int r = 0;
|
int r = 0;
|
||||||
RcCompactSpan s = chf.spans[i];
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dir);
|
||||||
r = chf.spans[ai].reg;
|
r = chf.spans[ai].reg;
|
||||||
if (area != chf.areas[ai])
|
if (area != chf.areas[ai])
|
||||||
isAreaBorder = true;
|
isAreaBorder = true;
|
||||||
|
@ -171,13 +172,13 @@ namespace DotRecast.Recast
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int ni = -1;
|
int ni = -1;
|
||||||
int nx = x + RecastCommon.GetDirOffsetX(dir);
|
int nx = x + GetDirOffsetX(dir);
|
||||||
int ny = y + RecastCommon.GetDirOffsetY(dir);
|
int ny = y + GetDirOffsetY(dir);
|
||||||
RcCompactSpan s = chf.spans[i];
|
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];
|
RcCompactCell nc = chf.cells[nx + ny * chf.width];
|
||||||
ni = nc.index + RecastCommon.GetCon(s, dir);
|
ni = nc.index + GetCon(s, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ni == -1)
|
if (ni == -1)
|
||||||
|
@ -475,7 +476,7 @@ namespace DotRecast.Recast
|
||||||
d1 = 4;
|
d1 = 4;
|
||||||
for (int k = 0; k < n; k++)
|
for (int k = 0; k < n; k++)
|
||||||
{
|
{
|
||||||
int k1 = RecastMesh.Next(k, n);
|
int k1 = RcMeshs.Next(k, n);
|
||||||
// Skip edges incident to i.
|
// Skip edges incident to i.
|
||||||
if (i == k || i == k1)
|
if (i == k || i == k1)
|
||||||
continue;
|
continue;
|
||||||
|
@ -489,11 +490,11 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
p0 = 8;
|
p0 = 8;
|
||||||
p1 = 12;
|
p1 = 12;
|
||||||
if (RecastMesh.VEqual(pverts, d0, p0) || RecastMesh.VEqual(pverts, d1, p0) ||
|
if (RcMeshs.VEqual(pverts, d0, p0) || RcMeshs.VEqual(pverts, d1, p0) ||
|
||||||
RecastMesh.VEqual(pverts, d0, p1) || RecastMesh.VEqual(pverts, d1, p1))
|
RcMeshs.VEqual(pverts, d0, p1) || RcMeshs.VEqual(pverts, d1, p1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (RecastMesh.Intersect(pverts, d0, d1, p0, p1))
|
if (RcMeshs.Intersect(pverts, d0, d1, p0, p1))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,8 +504,8 @@ namespace DotRecast.Recast
|
||||||
private static bool InCone(int i, int n, int[] verts, int pj, int[] vertpj)
|
private static bool InCone(int i, int n, int[] verts, int pj, int[] vertpj)
|
||||||
{
|
{
|
||||||
int pi = i * 4;
|
int pi = i * 4;
|
||||||
int pi1 = RecastMesh.Next(i, n) * 4;
|
int pi1 = RcMeshs.Next(i, n) * 4;
|
||||||
int pin1 = RecastMesh.Prev(i, n) * 4;
|
int pin1 = RcMeshs.Prev(i, n) * 4;
|
||||||
int[] pverts = new int[4 * 4];
|
int[] pverts = new int[4 * 4];
|
||||||
for (int g = 0; g < 4; g++)
|
for (int g = 0; g < 4; g++)
|
||||||
{
|
{
|
||||||
|
@ -519,11 +520,11 @@ namespace DotRecast.Recast
|
||||||
pin1 = 8;
|
pin1 = 8;
|
||||||
pj = 12;
|
pj = 12;
|
||||||
// If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
|
// If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
|
||||||
if (RecastMesh.LeftOn(pverts, pin1, pi, pi1))
|
if (RcMeshs.LeftOn(pverts, pin1, pi, pi1))
|
||||||
return RecastMesh.Left(pverts, pi, pj, pin1) && RecastMesh.Left(pverts, pj, pi, pi1);
|
return RcMeshs.Left(pverts, pi, pj, pin1) && RcMeshs.Left(pverts, pj, pi, pi1);
|
||||||
// Assume (i-1,i,i+1) not collinear.
|
// Assume (i-1,i,i+1) not collinear.
|
||||||
// else P[i] is reflex.
|
// 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)
|
private static void RemoveDegenerateSegments(List<int> simplified)
|
||||||
|
@ -533,7 +534,7 @@ namespace DotRecast.Recast
|
||||||
int npts = simplified.Count / 4;
|
int npts = simplified.Count / 4;
|
||||||
for (int i = 0; i < npts; ++i)
|
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 (Vequal(&simplified[i*4], &simplified[ni*4]))
|
||||||
if (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)
|
for (int dir = 0; dir < 4; ++dir)
|
||||||
{
|
{
|
||||||
int r = 0;
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
|
||||||
r = chf.spans[ai].reg;
|
r = chf.spans[ai].reg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ using static DotRecast.Recast.RcConstants;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public static class RecastFilledVolumeRasterization
|
public static class RcFilledVolumeRasterization
|
||||||
{
|
{
|
||||||
private const float EPSILON = 0.00001f;
|
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 };
|
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));
|
rectangle => IntersectCapsule(rectangle, start, end, axis, radius * radius));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RasterizeCylinder(RcHeightfield hf, RcVec3f start, RcVec3f end, float radius, int area, int flagMergeThr,
|
public static void RasterizeCylinder(RcHeightfield hf, RcVec3f start, RcVec3f end, float radius, int area, int flagMergeThr, RcTelemetry ctx)
|
||||||
RcTelemetry ctx)
|
|
||||||
{
|
{
|
||||||
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_CYLINDER);
|
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_CYLINDER);
|
||||||
float[] bounds =
|
float[] bounds =
|
||||||
|
@ -71,8 +70,7 @@ namespace DotRecast.Recast
|
||||||
rectangle => IntersectCylinder(rectangle, start, end, axis, radius * radius));
|
rectangle => IntersectCylinder(rectangle, start, end, axis, radius * radius));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RasterizeBox(RcHeightfield hf, RcVec3f center, RcVec3f[] halfEdges, int area, int flagMergeThr,
|
public static void RasterizeBox(RcHeightfield hf, RcVec3f center, RcVec3f[] halfEdges, int area, int flagMergeThr, RcTelemetry ctx)
|
||||||
RcTelemetry ctx)
|
|
||||||
{
|
{
|
||||||
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_BOX);
|
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_BOX);
|
||||||
RcVec3f[] normals =
|
RcVec3f[] normals =
|
||||||
|
@ -122,8 +120,7 @@ namespace DotRecast.Recast
|
||||||
RasterizationFilledShape(hf, bounds, area, flagMergeThr, rectangle => IntersectBox(rectangle, vertices, planes));
|
RasterizationFilledShape(hf, bounds, area, flagMergeThr, rectangle => IntersectBox(rectangle, vertices, planes));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RasterizeConvex(RcHeightfield hf, float[] vertices, int[] triangles, int area, int flagMergeThr,
|
public static void RasterizeConvex(RcHeightfield hf, float[] vertices, int[] triangles, int area, int flagMergeThr, RcTelemetry ctx)
|
||||||
RcTelemetry ctx)
|
|
||||||
{
|
{
|
||||||
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_CONVEX);
|
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] };
|
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 ismin = Clamp(smin, 0, SPAN_MAX_HEIGHT);
|
||||||
int ismax = Clamp(smax, ismin + 1, 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,8 +24,9 @@ using DotRecast.Core;
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
using static RcConstants;
|
||||||
|
using static RcCommons;
|
||||||
|
|
||||||
public static class RecastFilter
|
public static class RcFilters
|
||||||
{
|
{
|
||||||
/// @par
|
/// @par
|
||||||
///
|
///
|
||||||
|
@ -113,8 +114,8 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
for (int dir = 0; dir < 4; ++dir)
|
||||||
{
|
{
|
||||||
int dx = x + RecastCommon.GetDirOffsetX(dir);
|
int dx = x + GetDirOffsetX(dir);
|
||||||
int dy = y + RecastCommon.GetDirOffsetY(dir);
|
int dy = y + GetDirOffsetY(dir);
|
||||||
// Skip neighbours which are out of bounds.
|
// Skip neighbours which are out of bounds.
|
||||||
if (dx < 0 || dy < 0 || dx >= w || dy >= h)
|
if (dx < 0 || dy < 0 || dx >= w || dy >= h)
|
||||||
{
|
{
|
|
@ -24,10 +24,10 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RecastCommon;
|
|
||||||
using static RcConstants;
|
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_LAYERS = RcConstants.RC_NOT_CONNECTED;
|
||||||
const int RC_MAX_NEIS = 16;
|
const int RC_MAX_NEIS = 16;
|
|
@ -22,12 +22,13 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using static DotRecast.Core.RcMath;
|
using static DotRecast.Core.RcMath;
|
||||||
using static DotRecast.Recast.RecastCommon;
|
|
||||||
using static DotRecast.Recast.RcConstants;
|
using static DotRecast.Recast.RcConstants;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public static class RecastMeshDetail
|
using static RcCommons;
|
||||||
|
|
||||||
|
public static class RcMeshDetails
|
||||||
{
|
{
|
||||||
public const int MAX_VERTS = 127;
|
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).
|
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
|
// segments on edges
|
||||||
int pi = RecastMesh.Prev(i, nhull);
|
int pi = RcMeshs.Prev(i, nhull);
|
||||||
int ni = RecastMesh.Next(i, nhull);
|
int ni = RcMeshs.Next(i, nhull);
|
||||||
int pv = hull[pi] * 3;
|
int pv = hull[pi] * 3;
|
||||||
int cv = hull[i] * 3;
|
int cv = hull[i] * 3;
|
||||||
int nv = hull[ni] * 3;
|
int nv = hull[ni] * 3;
|
||||||
|
@ -789,11 +790,11 @@ namespace DotRecast.Recast
|
||||||
// depending on which triangle has shorter perimeter.
|
// depending on which triangle has shorter perimeter.
|
||||||
// This heuristic was chose empirically, since it seems
|
// This heuristic was chose empirically, since it seems
|
||||||
// handle tessellated straight edges well.
|
// 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.
|
// Check to see if se should advance left or right.
|
||||||
int nleft = RecastMesh.Next(left, nhull);
|
int nleft = RcMeshs.Next(left, nhull);
|
||||||
int nright = RecastMesh.Prev(right, nhull);
|
int nright = RcMeshs.Prev(right, nhull);
|
||||||
|
|
||||||
int cvleft = hull[left] * 3;
|
int cvleft = hull[left] * 3;
|
||||||
int nvleft = hull[nleft] * 3;
|
int nvleft = hull[nleft] * 3;
|
|
@ -25,7 +25,7 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
using static RcConstants;
|
||||||
|
|
||||||
public static class RecastMesh
|
public static class RcMeshs
|
||||||
{
|
{
|
||||||
public const int MAX_MESH_VERTS_POLY = 0xffff;
|
public const int MAX_MESH_VERTS_POLY = 0xffff;
|
||||||
public const int VERTEX_BUCKET_COUNT = (1 << 12);
|
public const int VERTEX_BUCKET_COUNT = (1 << 12);
|
|
@ -24,10 +24,10 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public static class RcPolyMeshRaycast
|
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;
|
hitTime = 0.0f;
|
||||||
foreach (RecastBuilderResult result in results)
|
foreach (RcBuilderResult result in results)
|
||||||
{
|
{
|
||||||
if (result.GetMeshDetail() != null)
|
if (result.GetMeshDetail() != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@ using static DotRecast.Recast.RcConstants;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public static class RecastRasterization
|
public static class RcRasterizations
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Check whether two bounding boxes overlap
|
* Check whether two bounding boxes overlap
|
|
@ -26,12 +26,12 @@ using DotRecast.Core;
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
using static RcConstants;
|
||||||
|
using static RcCommons;
|
||||||
|
|
||||||
public static class RecastRegion
|
public static class RcRegions
|
||||||
{
|
{
|
||||||
const int RC_NULL_NEI = 0xffff;
|
const int RC_NULL_NEI = 0xffff;
|
||||||
|
|
||||||
|
|
||||||
public static int CalculateDistanceField(RcCompactHeightfield chf, int[] src)
|
public static int CalculateDistanceField(RcCompactHeightfield chf, int[] src)
|
||||||
{
|
{
|
||||||
int maxDist;
|
int maxDist;
|
||||||
|
@ -58,11 +58,11 @@ namespace DotRecast.Recast
|
||||||
int nc = 0;
|
int nc = 0;
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
|
||||||
if (area == chf.areas[ai])
|
if (area == chf.areas[ai])
|
||||||
{
|
{
|
||||||
nc++;
|
nc++;
|
||||||
|
@ -88,12 +88,12 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
RcCompactSpan s = chf.spans[i];
|
RcCompactSpan s = chf.spans[i];
|
||||||
|
|
||||||
if (RecastCommon.GetCon(s, 0) != RC_NOT_CONNECTED)
|
if (GetCon(s, 0) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
// (-1,0)
|
// (-1,0)
|
||||||
int ax = x + RecastCommon.GetDirOffsetX(0);
|
int ax = x + GetDirOffsetX(0);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(0);
|
int ay = y + GetDirOffsetY(0);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 0);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, 0);
|
||||||
RcCompactSpan @as = chf.spans[ai];
|
RcCompactSpan @as = chf.spans[ai];
|
||||||
if (src[ai] + 2 < src[i])
|
if (src[ai] + 2 < src[i])
|
||||||
{
|
{
|
||||||
|
@ -101,11 +101,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// (-1,-1)
|
// (-1,-1)
|
||||||
if (RecastCommon.GetCon(@as, 3) != RC_NOT_CONNECTED)
|
if (GetCon(@as, 3) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int aax = ax + RecastCommon.GetDirOffsetX(3);
|
int aax = ax + GetDirOffsetX(3);
|
||||||
int aay = ay + RecastCommon.GetDirOffsetY(3);
|
int aay = ay + GetDirOffsetY(3);
|
||||||
int aai = chf.cells[aax + aay * w].index + RecastCommon.GetCon(@as, 3);
|
int aai = chf.cells[aax + aay * w].index + GetCon(@as, 3);
|
||||||
if (src[aai] + 3 < src[i])
|
if (src[aai] + 3 < src[i])
|
||||||
{
|
{
|
||||||
src[i] = src[aai] + 3;
|
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)
|
// (0,-1)
|
||||||
int ax = x + RecastCommon.GetDirOffsetX(3);
|
int ax = x + GetDirOffsetX(3);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(3);
|
int ay = y + GetDirOffsetY(3);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 3);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, 3);
|
||||||
RcCompactSpan @as = chf.spans[ai];
|
RcCompactSpan @as = chf.spans[ai];
|
||||||
if (src[ai] + 2 < src[i])
|
if (src[ai] + 2 < src[i])
|
||||||
{
|
{
|
||||||
|
@ -126,11 +126,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// (1,-1)
|
// (1,-1)
|
||||||
if (RecastCommon.GetCon(@as, 2) != RC_NOT_CONNECTED)
|
if (GetCon(@as, 2) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int aax = ax + RecastCommon.GetDirOffsetX(2);
|
int aax = ax + GetDirOffsetX(2);
|
||||||
int aay = ay + RecastCommon.GetDirOffsetY(2);
|
int aay = ay + GetDirOffsetY(2);
|
||||||
int aai = chf.cells[aax + aay * w].index + RecastCommon.GetCon(@as, 2);
|
int aai = chf.cells[aax + aay * w].index + GetCon(@as, 2);
|
||||||
if (src[aai] + 3 < src[i])
|
if (src[aai] + 3 < src[i])
|
||||||
{
|
{
|
||||||
src[i] = src[aai] + 3;
|
src[i] = src[aai] + 3;
|
||||||
|
@ -151,12 +151,12 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
RcCompactSpan s = chf.spans[i];
|
RcCompactSpan s = chf.spans[i];
|
||||||
|
|
||||||
if (RecastCommon.GetCon(s, 2) != RC_NOT_CONNECTED)
|
if (GetCon(s, 2) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
// (1,0)
|
// (1,0)
|
||||||
int ax = x + RecastCommon.GetDirOffsetX(2);
|
int ax = x + GetDirOffsetX(2);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(2);
|
int ay = y + GetDirOffsetY(2);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 2);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, 2);
|
||||||
RcCompactSpan @as = chf.spans[ai];
|
RcCompactSpan @as = chf.spans[ai];
|
||||||
if (src[ai] + 2 < src[i])
|
if (src[ai] + 2 < src[i])
|
||||||
{
|
{
|
||||||
|
@ -164,11 +164,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// (1,1)
|
// (1,1)
|
||||||
if (RecastCommon.GetCon(@as, 1) != RC_NOT_CONNECTED)
|
if (GetCon(@as, 1) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int aax = ax + RecastCommon.GetDirOffsetX(1);
|
int aax = ax + GetDirOffsetX(1);
|
||||||
int aay = ay + RecastCommon.GetDirOffsetY(1);
|
int aay = ay + GetDirOffsetY(1);
|
||||||
int aai = chf.cells[aax + aay * w].index + RecastCommon.GetCon(@as, 1);
|
int aai = chf.cells[aax + aay * w].index + GetCon(@as, 1);
|
||||||
if (src[aai] + 3 < src[i])
|
if (src[aai] + 3 < src[i])
|
||||||
{
|
{
|
||||||
src[i] = src[aai] + 3;
|
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)
|
// (0,1)
|
||||||
int ax = x + RecastCommon.GetDirOffsetX(1);
|
int ax = x + GetDirOffsetX(1);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(1);
|
int ay = y + GetDirOffsetY(1);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 1);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, 1);
|
||||||
RcCompactSpan @as = chf.spans[ai];
|
RcCompactSpan @as = chf.spans[ai];
|
||||||
if (src[ai] + 2 < src[i])
|
if (src[ai] + 2 < src[i])
|
||||||
{
|
{
|
||||||
|
@ -189,11 +189,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// (-1,1)
|
// (-1,1)
|
||||||
if (RecastCommon.GetCon(@as, 0) != RC_NOT_CONNECTED)
|
if (GetCon(@as, 0) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int aax = ax + RecastCommon.GetDirOffsetX(0);
|
int aax = ax + GetDirOffsetX(0);
|
||||||
int aay = ay + RecastCommon.GetDirOffsetY(0);
|
int aay = ay + GetDirOffsetY(0);
|
||||||
int aai = chf.cells[aax + aay * w].index + RecastCommon.GetCon(@as, 0);
|
int aai = chf.cells[aax + aay * w].index + GetCon(@as, 0);
|
||||||
if (src[aai] + 3 < src[i])
|
if (src[aai] + 3 < src[i])
|
||||||
{
|
{
|
||||||
src[i] = src[aai] + 3;
|
src[i] = src[aai] + 3;
|
||||||
|
@ -239,20 +239,20 @@ namespace DotRecast.Recast
|
||||||
int d = cd;
|
int d = cd;
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
|
||||||
d += src[ai];
|
d += src[ai];
|
||||||
|
|
||||||
RcCompactSpan @as = chf.spans[ai];
|
RcCompactSpan @as = chf.spans[ai];
|
||||||
int dir2 = (dir + 1) & 0x3;
|
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 ax2 = ax + GetDirOffsetX(dir2);
|
||||||
int ay2 = ay + RecastCommon.GetDirOffsetY(dir2);
|
int ay2 = ay + GetDirOffsetY(dir2);
|
||||||
int ai2 = chf.cells[ax2 + ay2 * w].index + RecastCommon.GetCon(@as, dir2);
|
int ai2 = chf.cells[ax2 + ay2 * w].index + GetCon(@as, dir2);
|
||||||
d += src[ai2];
|
d += src[ai2];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -311,11 +311,11 @@ namespace DotRecast.Recast
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
for (int dir = 0; dir < 4; ++dir)
|
||||||
{
|
{
|
||||||
// 8 connected
|
// 8 connected
|
||||||
if (RecastCommon.GetCon(cs, dir) != RC_NOT_CONNECTED)
|
if (GetCon(cs, dir) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int ax = cx + RecastCommon.GetDirOffsetX(dir);
|
int ax = cx + GetDirOffsetX(dir);
|
||||||
int ay = cy + RecastCommon.GetDirOffsetY(dir);
|
int ay = cy + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(cs, dir);
|
int ai = chf.cells[ax + ay * w].index + GetCon(cs, dir);
|
||||||
if (chf.areas[ai] != area)
|
if (chf.areas[ai] != area)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -336,11 +336,11 @@ namespace DotRecast.Recast
|
||||||
RcCompactSpan @as = chf.spans[ai];
|
RcCompactSpan @as = chf.spans[ai];
|
||||||
|
|
||||||
int dir2 = (dir + 1) & 0x3;
|
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 ax2 = ax + GetDirOffsetX(dir2);
|
||||||
int ay2 = ay + RecastCommon.GetDirOffsetY(dir2);
|
int ay2 = ay + GetDirOffsetY(dir2);
|
||||||
int ai2 = chf.cells[ax2 + ay2 * w].index + RecastCommon.GetCon(@as, dir2);
|
int ai2 = chf.cells[ax2 + ay2 * w].index + GetCon(@as, dir2);
|
||||||
if (chf.areas[ai2] != area)
|
if (chf.areas[ai2] != area)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -367,11 +367,11 @@ namespace DotRecast.Recast
|
||||||
// Expand neighbours.
|
// Expand neighbours.
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
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 ax = cx + GetDirOffsetX(dir);
|
||||||
int ay = cy + RecastCommon.GetDirOffsetY(dir);
|
int ay = cy + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(cs, dir);
|
int ai = chf.cells[ax + ay * w].index + GetCon(cs, dir);
|
||||||
if (chf.areas[ai] != area)
|
if (chf.areas[ai] != area)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -456,14 +456,14 @@ namespace DotRecast.Recast
|
||||||
RcCompactSpan s = chf.spans[i];
|
RcCompactSpan s = chf.spans[i];
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
for (int dir = 0; dir < 4; ++dir)
|
||||||
{
|
{
|
||||||
if (RecastCommon.GetCon(s, dir) == RC_NOT_CONNECTED)
|
if (GetCon(s, dir) == RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ax = x + RecastCommon.GetDirOffsetX(dir);
|
int ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
|
||||||
if (chf.areas[ai] != area)
|
if (chf.areas[ai] != area)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -741,11 +741,11 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
RcCompactSpan s = chf.spans[i];
|
RcCompactSpan s = chf.spans[i];
|
||||||
int r = 0;
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dir);
|
||||||
r = srcReg[ai];
|
r = srcReg[ai];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,11 +765,11 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
RcCompactSpan ss = chf.spans[i];
|
RcCompactSpan ss = chf.spans[i];
|
||||||
int curReg = 0;
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(ss, dir);
|
int ai = chf.cells[ax + ay * chf.width].index + GetCon(ss, dir);
|
||||||
curReg = srcReg[ai];
|
curReg = srcReg[ai];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,11 +784,11 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
// Choose the edge corner
|
// Choose the edge corner
|
||||||
int r = 0;
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * chf.width].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * chf.width].index + GetCon(s, dir);
|
||||||
r = srcReg[ai];
|
r = srcReg[ai];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,12 +803,12 @@ namespace DotRecast.Recast
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int ni = -1;
|
int ni = -1;
|
||||||
int nx = x + RecastCommon.GetDirOffsetX(dir);
|
int nx = x + GetDirOffsetX(dir);
|
||||||
int ny = y + RecastCommon.GetDirOffsetY(dir);
|
int ny = y + GetDirOffsetY(dir);
|
||||||
if (RecastCommon.GetCon(s, dir) != RC_NOT_CONNECTED)
|
if (GetCon(s, dir) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
RcCompactCell nc = chf.cells[nx + ny * chf.width];
|
RcCompactCell nc = chf.cells[nx + ny * chf.width];
|
||||||
ni = nc.index + RecastCommon.GetCon(s, dir);
|
ni = nc.index + GetCon(s, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ni == -1)
|
if (ni == -1)
|
||||||
|
@ -1215,11 +1215,11 @@ namespace DotRecast.Recast
|
||||||
// Update neighbours
|
// Update neighbours
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
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 ax = x + GetDirOffsetX(dir);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(dir);
|
int ay = y + GetDirOffsetY(dir);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, dir);
|
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
|
||||||
int rai = srcReg[ai];
|
int rai = srcReg[ai];
|
||||||
if (rai > 0 && rai < nreg && rai != ri)
|
if (rai > 0 && rai < nreg && rai != ri)
|
||||||
{
|
{
|
||||||
|
@ -1543,11 +1543,11 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
// -x
|
// -x
|
||||||
int previd = 0;
|
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 ax = x + GetDirOffsetX(0);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(0);
|
int ay = y + GetDirOffsetY(0);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 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])
|
if ((srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai])
|
||||||
{
|
{
|
||||||
previd = srcReg[ai];
|
previd = srcReg[ai];
|
||||||
|
@ -1563,11 +1563,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// -y
|
// -y
|
||||||
if (RecastCommon.GetCon(s, 3) != RC_NOT_CONNECTED)
|
if (GetCon(s, 3) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int ax = x + RecastCommon.GetDirOffsetX(3);
|
int ax = x + GetDirOffsetX(3);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(3);
|
int ay = y + GetDirOffsetY(3);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 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])
|
if (srcReg[ai] != 0 && (srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai])
|
||||||
{
|
{
|
||||||
int nr = srcReg[ai];
|
int nr = srcReg[ai];
|
||||||
|
@ -1843,11 +1843,11 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
// -x
|
// -x
|
||||||
int previd = 0;
|
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 ax = x + GetDirOffsetX(0);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(0);
|
int ay = y + GetDirOffsetY(0);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 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])
|
if ((srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai])
|
||||||
{
|
{
|
||||||
previd = srcReg[ai];
|
previd = srcReg[ai];
|
||||||
|
@ -1863,11 +1863,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// -y
|
// -y
|
||||||
if (RecastCommon.GetCon(s, 3) != RC_NOT_CONNECTED)
|
if (GetCon(s, 3) != RC_NOT_CONNECTED)
|
||||||
{
|
{
|
||||||
int ax = x + RecastCommon.GetDirOffsetX(3);
|
int ax = x + GetDirOffsetX(3);
|
||||||
int ay = y + RecastCommon.GetDirOffsetY(3);
|
int ay = y + GetDirOffsetY(3);
|
||||||
int ai = chf.cells[ax + ay * w].index + RecastCommon.GetCon(s, 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])
|
if (srcReg[ai] != 0 && (srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai])
|
||||||
{
|
{
|
||||||
int nr = srcReg[ai];
|
int nr = srcReg[ai];
|
|
@ -23,9 +23,9 @@ using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
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;
|
RcConfig cfg = builderCfg.cfg;
|
||||||
|
|
||||||
|
@ -58,16 +58,16 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
int[] tris = node.tris;
|
int[] tris = node.tris;
|
||||||
int ntris = tris.Length / 3;
|
int ntris = tris.Length / 3;
|
||||||
int[] m_triareas = RcUtils.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
||||||
RecastRasterization.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx);
|
RcRasterizations.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int[] tris = geom.GetTris();
|
int[] tris = geom.GetTris();
|
||||||
int ntris = tris.Length / 3;
|
int ntris = tris.Length / 3;
|
||||||
int[] m_triareas = RcUtils.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
||||||
RecastRasterization.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx);
|
RcRasterizations.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -70,9 +70,9 @@ public class RecastTestMeshBuilder
|
||||||
detailSampleDist, detailSampleMaxError,
|
detailSampleDist, detailSampleMaxError,
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||||
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||||
RecastBuilder rcBuilder = new RecastBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
RecastBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
|
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
|
||||||
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class MeshSetReaderWriterTest
|
||||||
|
|
||||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
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 y = 0; y < th; ++y)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < tw; ++x)
|
for (int x = 0; x < tw; ++x)
|
||||||
|
@ -85,7 +85,7 @@ public class MeshSetReaderWriterTest
|
||||||
m_detailSampleDist, m_detailSampleMaxError,
|
m_detailSampleDist, m_detailSampleMaxError,
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, 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();
|
TestDetourBuilder db = new TestDetourBuilder();
|
||||||
DtMeshData data = db.Build(geom, bcfg, m_agentHeight, m_agentRadius, m_agentMaxClimb, x, y, true);
|
DtMeshData data = db.Build(geom, bcfg, m_agentHeight, m_agentRadius, m_agentMaxClimb, x, y, true);
|
||||||
if (data != null)
|
if (data != null)
|
||||||
|
|
|
@ -70,9 +70,9 @@ public class RecastTestMeshBuilder
|
||||||
detailSampleDist, detailSampleMaxError,
|
detailSampleDist, detailSampleMaxError,
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||||
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||||
RecastBuilder rcBuilder = new RecastBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
RecastBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
|
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
|
||||||
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,11 +23,11 @@ namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
public class TestDetourBuilder : DetourBuilder
|
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)
|
float agentMaxClimb, int x, int y, bool applyRecastDemoFlags)
|
||||||
{
|
{
|
||||||
RecastBuilder rcBuilder = new RecastBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
RecastBuilderResult rcResult = rcBuilder.Build(geom, rcConfig);
|
RcBuilderResult rcResult = rcBuilder.Build(geom, rcConfig);
|
||||||
RcPolyMesh pmesh = rcResult.GetMesh();
|
RcPolyMesh pmesh = rcResult.GetMesh();
|
||||||
|
|
||||||
if (applyRecastDemoFlags)
|
if (applyRecastDemoFlags)
|
||||||
|
|
|
@ -77,12 +77,12 @@ public class TestTiledNavMeshBuilder
|
||||||
detailSampleDist, detailSampleMaxError,
|
detailSampleDist, detailSampleMaxError,
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||||
RecastBuilder rcBuilder = new RecastBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
List<RecastBuilderResult> rcResult = rcBuilder.BuildTiles(geom, cfg, null);
|
List<RcBuilderResult> rcResult = rcBuilder.BuildTiles(geom, cfg, null);
|
||||||
|
|
||||||
// Add tiles to nav mesh
|
// Add tiles to nav mesh
|
||||||
|
|
||||||
foreach (RecastBuilderResult result in rcResult)
|
foreach (RcBuilderResult result in rcResult)
|
||||||
{
|
{
|
||||||
RcPolyMesh pmesh = result.GetMesh();
|
RcPolyMesh pmesh = result.GetMesh();
|
||||||
if (pmesh.npolys == 0)
|
if (pmesh.npolys == 0)
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class AbstractTileCacheTest
|
||||||
public DtTileCache GetTileCache(IInputGeomProvider geom, RcByteOrder order, bool cCompatibility)
|
public DtTileCache GetTileCache(IInputGeomProvider geom, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
DtTileCacheParams option = new DtTileCacheParams();
|
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.ch = m_cellHeight;
|
||||||
option.cs = m_cellSize;
|
option.cs = m_cellSize;
|
||||||
option.orig = geom.GetMeshBoundsMin();
|
option.orig = geom.GetMeshBoundsMin();
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class TestTileLayerBuilder : DtTileCacheLayerBuilder
|
||||||
|
|
||||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
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)
|
public List<byte[]> Build(RcByteOrder order, bool cCompatibility, int threads)
|
||||||
|
|
|
@ -146,7 +146,7 @@ public class RecastLayersTest
|
||||||
private RcHeightfieldLayerSet Build(string filename, int x, int y)
|
private RcHeightfieldLayerSet Build(string filename, int x, int y)
|
||||||
{
|
{
|
||||||
IInputGeomProvider geom = ObjImporter.Load(RcResources.Load(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 cfg = new RcConfig(true, m_tileSize, m_tileSize,
|
||||||
RcConfig.CalcBorder(m_agentRadius, m_cellSize),
|
RcConfig.CalcBorder(m_agentRadius, m_cellSize),
|
||||||
RcPartitionType.OfValue(m_partitionType),
|
RcPartitionType.OfValue(m_partitionType),
|
||||||
|
@ -158,7 +158,7 @@ public class RecastLayersTest
|
||||||
m_detailSampleDist, m_detailSampleMaxError,
|
m_detailSampleDist, m_detailSampleMaxError,
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, 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);
|
RcHeightfieldLayerSet lset = builder.BuildLayers(geom, bcfg);
|
||||||
return lset;
|
return lset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ using NUnit.Framework;
|
||||||
namespace DotRecast.Recast.Test;
|
namespace DotRecast.Recast.Test;
|
||||||
|
|
||||||
using static RcConstants;
|
using static RcConstants;
|
||||||
|
using static RcAreas;
|
||||||
|
|
||||||
[Parallelizable]
|
[Parallelizable]
|
||||||
public class RecastSoloMeshTest
|
public class RecastSoloMeshTest
|
||||||
|
@ -116,7 +117,7 @@ public class RecastSoloMeshTest
|
||||||
m_detailSampleDist, m_detailSampleMaxError,
|
m_detailSampleDist, m_detailSampleMaxError,
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, 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.
|
// 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.
|
// 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
|
// If your input data is multiple meshes, you can transform them here, calculate
|
||||||
// the are type for each of the meshes and rasterize them.
|
// 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);
|
int[] m_triareas = RcCommons.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
||||||
RecastRasterization.RasterizeTriangles(m_solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, m_ctx);
|
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
|
// Once all geometry is rasterized, we do initial pass of filtering to
|
||||||
// remove unwanted overhangs caused by the conservative rasterization
|
// remove unwanted overhangs caused by the conservative rasterization
|
||||||
// as well as filter spans where the character cannot possibly stand.
|
// as well as filter spans where the character cannot possibly stand.
|
||||||
RecastFilter.FilterLowHangingWalkableObstacles(m_ctx, cfg.WalkableClimb, m_solid);
|
RcFilters.FilterLowHangingWalkableObstacles(m_ctx, cfg.WalkableClimb, m_solid);
|
||||||
RecastFilter.FilterLedgeSpans(m_ctx, cfg.WalkableHeight, cfg.WalkableClimb, m_solid);
|
RcFilters.FilterLedgeSpans(m_ctx, cfg.WalkableHeight, cfg.WalkableClimb, m_solid);
|
||||||
RecastFilter.FilterWalkableLowHeightSpans(m_ctx, cfg.WalkableHeight, m_solid);
|
RcFilters.FilterWalkableLowHeightSpans(m_ctx, cfg.WalkableHeight, m_solid);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Step 4. Partition walkable surface to simple regions.
|
// 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.
|
// 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
|
// This will result more cache coherent data as well as the neighbours
|
||||||
// between walkable cells will be calculated.
|
// between walkable cells will be calculated.
|
||||||
RcCompactHeightfield m_chf = RecastCompact.BuildCompactHeightfield(m_ctx, cfg.WalkableHeight, cfg.WalkableClimb,
|
RcCompactHeightfield m_chf = RcCompacts.BuildCompactHeightfield(m_ctx, cfg.WalkableHeight, cfg.WalkableClimb, m_solid);
|
||||||
m_solid);
|
|
||||||
|
|
||||||
// Erode the walkable area by agent radius.
|
// 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.
|
// (Optional) Mark areas.
|
||||||
/*
|
/*
|
||||||
|
@ -216,20 +216,20 @@ public class RecastSoloMeshTest
|
||||||
{
|
{
|
||||||
// Prepare for region partitioning, by calculating distance field
|
// Prepare for region partitioning, by calculating distance field
|
||||||
// along the walkable surface.
|
// 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.
|
// 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)
|
else if (m_partitionType == RcPartition.MONOTONE)
|
||||||
{
|
{
|
||||||
// Partition the walkable surface into simple regions without holes.
|
// Partition the walkable surface into simple regions without holes.
|
||||||
// Monotone partitioning does not need distancefield.
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// Partition the walkable surface into simple regions without holes.
|
// 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");
|
Assert.That(m_chf.maxDistance, Is.EqualTo(expDistance), "maxDistance");
|
||||||
|
@ -239,7 +239,7 @@ public class RecastSoloMeshTest
|
||||||
//
|
//
|
||||||
|
|
||||||
// Create contours.
|
// 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);
|
RcConstants.RC_CONTOUR_TESS_WALL_EDGES);
|
||||||
|
|
||||||
Assert.That(m_cset.conts.Count, Is.EqualTo(expContours), "Contours");
|
Assert.That(m_cset.conts.Count, Is.EqualTo(expContours), "Contours");
|
||||||
|
@ -248,7 +248,7 @@ public class RecastSoloMeshTest
|
||||||
//
|
//
|
||||||
|
|
||||||
// Build polygon navmesh from the contours.
|
// 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.nverts, Is.EqualTo(expVerts), "Mesh Verts");
|
||||||
Assert.That(m_pmesh.npolys, Is.EqualTo(expPolys), "Mesh Polys");
|
Assert.That(m_pmesh.npolys, Is.EqualTo(expPolys), "Mesh Polys");
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ public class RecastSoloMeshTest
|
||||||
// on each polygon.
|
// 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);
|
cfg.DetailSampleMaxError);
|
||||||
Assert.That(m_dmesh.nmeshes, Is.EqualTo(expDetMeshes), "Mesh Detail Meshes");
|
Assert.That(m_dmesh.nmeshes, Is.EqualTo(expDetMeshes), "Mesh Detail Meshes");
|
||||||
Assert.That(m_dmesh.nverts, Is.EqualTo(expDetVerts), "Mesh Detail Verts");
|
Assert.That(m_dmesh.nverts, Is.EqualTo(expDetVerts), "Mesh Detail Verts");
|
||||||
|
|
|
@ -39,18 +39,18 @@ public class RecastTest
|
||||||
RcTelemetry ctx = new RcTelemetry();
|
RcTelemetry ctx = new RcTelemetry();
|
||||||
{
|
{
|
||||||
int[] areas = { 42 };
|
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");
|
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Sets area ID of unwalkable triangle to RC_NULL_AREA");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int[] areas = { 42 };
|
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");
|
Assert.That(areas[0], Is.EqualTo(42), "Does not modify walkable triangle aread ID's");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int[] areas = { 42 };
|
int[] areas = { 42 };
|
||||||
walkableSlopeAngle = 0;
|
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.");
|
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Slopes equal to the max slope are considered unwalkable.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ public class RecastTileMeshTest
|
||||||
public void TestBuild(string filename)
|
public void TestBuild(string filename)
|
||||||
{
|
{
|
||||||
IInputGeomProvider geom = ObjImporter.Load(RcResources.Load(filename));
|
IInputGeomProvider geom = ObjImporter.Load(RcResources.Load(filename));
|
||||||
RecastBuilder builder = new RecastBuilder();
|
RcBuilder builder = new RcBuilder();
|
||||||
RcConfig cfg = new RcConfig(
|
RcConfig cfg = new RcConfig(
|
||||||
true, m_tileSize, m_tileSize, RcConfig.CalcBorder(m_agentRadius, m_cellSize),
|
true, m_tileSize, m_tileSize, RcConfig.CalcBorder(m_agentRadius, m_cellSize),
|
||||||
m_partitionType,
|
m_partitionType,
|
||||||
|
@ -71,27 +71,27 @@ public class RecastTileMeshTest
|
||||||
m_detailSampleDist, m_detailSampleMaxError,
|
m_detailSampleDist, m_detailSampleMaxError,
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||||
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 7, 8);
|
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 7, 8);
|
||||||
RecastBuilderResult rcResult = builder.Build(geom, bcfg);
|
RcBuilderResult rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
|
||||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
|
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);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(7));
|
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);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(9));
|
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);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
|
||||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(6));
|
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);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
|
||||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(17));
|
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);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
|
||||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
|
||||||
|
@ -101,7 +101,7 @@ public class RecastTileMeshTest
|
||||||
public void TestPerformance()
|
public void TestPerformance()
|
||||||
{
|
{
|
||||||
IInputGeomProvider geom = ObjImporter.Load(RcResources.Load("dungeon.obj"));
|
IInputGeomProvider geom = ObjImporter.Load(RcResources.Load("dungeon.obj"));
|
||||||
RecastBuilder builder = new RecastBuilder();
|
RcBuilder builder = new RcBuilder();
|
||||||
RcConfig cfg = new RcConfig(
|
RcConfig cfg = new RcConfig(
|
||||||
true, m_tileSize, m_tileSize,
|
true, m_tileSize, m_tileSize,
|
||||||
RcConfig.CalcBorder(m_agentRadius, m_cellSize),
|
RcConfig.CalcBorder(m_agentRadius, m_cellSize),
|
||||||
|
@ -137,14 +137,14 @@ public class RecastTileMeshTest
|
||||||
Console.WriteLine(" Time MT : " + (t3 - t2) / TimeSpan.TicksPerMillisecond);
|
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();
|
CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
List<RecastBuilderResult> tiles = new();
|
List<RcBuilderResult> tiles = new();
|
||||||
var task = builder.BuildTilesAsync(geom, cfg, threads, tiles, Task.Factory, cts.Token);
|
var task = builder.BuildTilesAsync(geom, cfg, threads, tiles, Task.Factory, cts.Token);
|
||||||
if (validate)
|
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().npolys, Is.EqualTo(1));
|
||||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
|
||||||
rcResult = GetTile(tiles, 6, 9);
|
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);
|
return tiles.FirstOrDefault(tile => tile.tileX == x && tile.tileZ == z);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue