From 3c3034d087306d8a4d14f6c4eb1ea3a0f32e9fce Mon Sep 17 00:00:00 2001 From: ikpil Date: Sat, 21 Dec 2024 14:21:27 +0900 Subject: [PATCH] Improved the IDtPolygonByCircleConstraint interface for better memory reuse @wrenge --- src/DotRecast.Core/Buffers/RcRentedArray.cs | 2 -- src/DotRecast.Detour/DtNavMeshQuery.cs | 6 +++--- .../DtNoOpDtPolygonByCircleConstraint.cs | 6 ++++-- .../DtStrictDtPolygonByCircleConstraint.cs | 12 ++++++++---- .../IDtPolygonByCircleConstraint.cs | 2 +- .../PolygonByCircleConstraintTest.cs | 19 +++++++++---------- 6 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/DotRecast.Core/Buffers/RcRentedArray.cs b/src/DotRecast.Core/Buffers/RcRentedArray.cs index 957fcf78..dd7a564a 100644 --- a/src/DotRecast.Core/Buffers/RcRentedArray.cs +++ b/src/DotRecast.Core/Buffers/RcRentedArray.cs @@ -1,8 +1,6 @@ using System; using System.Buffers; -using System.Collections.Generic; using System.Runtime.CompilerServices; -using System.Threading; namespace DotRecast.Core.Buffers { diff --git a/src/DotRecast.Detour/DtNavMeshQuery.cs b/src/DotRecast.Detour/DtNavMeshQuery.cs index ee0e699a..a42b2316 100644 --- a/src/DotRecast.Detour/DtNavMeshQuery.cs +++ b/src/DotRecast.Detour/DtNavMeshQuery.cs @@ -264,7 +264,7 @@ public DtStatus FindRandomPointAroundCircle(long startRef, RcVec3f centerPos, fl DtPoly randomPoly = null; long randomPolyRef = 0; - float[] randomPolyVerts = null; + Span randomPolyVerts = null; while (!m_openList.IsEmpty()) { @@ -288,8 +288,8 @@ public DtStatus FindRandomPointAroundCircle(long startRef, RcVec3f centerPos, fl RcArrays.Copy(bestTile.data.verts, bestPoly.verts[j] * 3, polyVerts, j * 3, 3); } - float[] constrainedVerts = constraint.Apply(polyVerts, centerPos, maxRadius); - if (constrainedVerts != null) + var ncverts = constraint.Apply(polyVerts, centerPos, maxRadius, out var constrainedVerts); + if (!constrainedVerts.IsEmpty) { int vertCount = constrainedVerts.Length / 3; for (int j = 2; j < vertCount; ++j) diff --git a/src/DotRecast.Detour/DtNoOpDtPolygonByCircleConstraint.cs b/src/DotRecast.Detour/DtNoOpDtPolygonByCircleConstraint.cs index e5d26510..d7a497d7 100644 --- a/src/DotRecast.Detour/DtNoOpDtPolygonByCircleConstraint.cs +++ b/src/DotRecast.Detour/DtNoOpDtPolygonByCircleConstraint.cs @@ -1,3 +1,4 @@ +using System; using DotRecast.Core.Numerics; namespace DotRecast.Detour @@ -10,9 +11,10 @@ private DtNoOpDtPolygonByCircleConstraint() { } - public float[] Apply(float[] polyVerts, RcVec3f circleCenter, float radius) + public int Apply(Span polyVerts, RcVec3f circleCenter, float radius, out Span constrainedVerts) { - return polyVerts; + constrainedVerts = polyVerts; + return polyVerts.Length; } } } \ No newline at end of file diff --git a/src/DotRecast.Detour/DtStrictDtPolygonByCircleConstraint.cs b/src/DotRecast.Detour/DtStrictDtPolygonByCircleConstraint.cs index 47bf30e7..8979525e 100644 --- a/src/DotRecast.Detour/DtStrictDtPolygonByCircleConstraint.cs +++ b/src/DotRecast.Detour/DtStrictDtPolygonByCircleConstraint.cs @@ -40,7 +40,7 @@ public static void ScaleCircle(Span src, RcVec3f center, float radius, Sp } - public float[] Apply(float[] verts, RcVec3f center, float radius) + public int Apply(Span verts, RcVec3f center, float radius, out Span constrainedVerts) { float radiusSqr = radius * radius; int outsideVertex = -1; @@ -56,7 +56,8 @@ public float[] Apply(float[] verts, RcVec3f center, float radius) if (outsideVertex == -1) { // polygon inside circle - return verts; + constrainedVerts = verts; + return verts.Length; } Span qCircle = stackalloc float[UnitCircle.Length]; @@ -65,10 +66,13 @@ public float[] Apply(float[] verts, RcVec3f center, float radius) if (intersection == null && DtUtils.PointInPolygon(center, verts, verts.Length / 3)) { // circle inside polygon - return qCircle.ToArray(); + float[] qCircleArray = qCircle.ToArray(); + constrainedVerts = qCircleArray; + return qCircleArray.Length; } - return intersection; + constrainedVerts = intersection; + return intersection?.Length ?? 0; } } } \ No newline at end of file diff --git a/src/DotRecast.Detour/IDtPolygonByCircleConstraint.cs b/src/DotRecast.Detour/IDtPolygonByCircleConstraint.cs index 9f46ff3a..dd473394 100644 --- a/src/DotRecast.Detour/IDtPolygonByCircleConstraint.cs +++ b/src/DotRecast.Detour/IDtPolygonByCircleConstraint.cs @@ -24,6 +24,6 @@ namespace DotRecast.Detour { public interface IDtPolygonByCircleConstraint { - float[] Apply(float[] polyVerts, RcVec3f circleCenter, float radius); + int Apply(Span polyVerts, RcVec3f circleCenter, float radius, out Span constrainedVerts); } } \ No newline at end of file diff --git a/test/DotRecast.Detour.Test/PolygonByCircleConstraintTest.cs b/test/DotRecast.Detour.Test/PolygonByCircleConstraintTest.cs index 7e7c231e..242f172f 100644 --- a/test/DotRecast.Detour.Test/PolygonByCircleConstraintTest.cs +++ b/test/DotRecast.Detour.Test/PolygonByCircleConstraintTest.cs @@ -22,7 +22,6 @@ 3. This notice may not be removed or altered from any source distribution. namespace DotRecast.Detour.Test; - public class PolygonByCircleConstraintTest { private readonly IDtPolygonByCircleConstraint _constraint = DtStrictDtPolygonByCircleConstraint.Shared; @@ -32,9 +31,9 @@ public void ShouldHandlePolygonFullyInsideCircle() { float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 }; RcVec3f center = new RcVec3f(1, 0, 1); - float[] constrained = _constraint.Apply(polygon, center, 6); - Assert.That(constrained, Is.EqualTo(polygon)); + _constraint.Apply(polygon, center, 6, out var constrained); + Assert.That(constrained.ToArray(), Is.EqualTo(polygon)); } [Test] @@ -44,9 +43,9 @@ public void ShouldHandleVerticalSegment() float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 }; RcVec3f center = new RcVec3f(2, 0, 0); - float[] constrained = _constraint.Apply(polygon, center, 3); + _constraint.Apply(polygon, center, 3, out var constrained); Assert.That(constrained.Length, Is.EqualTo(expectedSize)); - Assert.That(constrained, Is.SupersetOf(new[] { 2f, 0f, 2f, 2f, 0f, -2f })); + Assert.That(constrained.ToArray(), Is.SupersetOf(new[] { 2f, 0f, 2f, 2f, 0f, -2f })); } [Test] @@ -55,7 +54,7 @@ public void ShouldHandleCircleFullyInsidePolygon() int expectedSize = 12 * 3; float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 }; RcVec3f center = new RcVec3f(-1, 0, -1); - float[] constrained = _constraint.Apply(polygon, center, 2); + _constraint.Apply(polygon, center, 2, out var constrained); Assert.That(constrained.Length, Is.EqualTo(expectedSize)); @@ -73,10 +72,10 @@ public void ShouldHandleCircleInsidePolygon() int expectedSize = 9 * 3; float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 }; RcVec3f center = new RcVec3f(-2, 0, -1); - float[] constrained = _constraint.Apply(polygon, center, 3); + _constraint.Apply(polygon, center, 3, out var constrained); Assert.That(constrained.Length, Is.EqualTo(expectedSize)); - Assert.That(constrained, Is.SupersetOf(new[] { -2f, 0f, -4f, -4f, 0f, 0f, -3.4641016f, 0.0f, 1.60769534f, -2.0f, 0.0f, 2.0f })); + Assert.That(constrained.ToArray(), Is.SupersetOf(new[] { -2f, 0f, -4f, -4f, 0f, 0f, -3.4641016f, 0.0f, 1.60769534f, -2.0f, 0.0f, 2.0f })); } [Test] @@ -85,9 +84,9 @@ public void ShouldHandleCircleOutsidePolygon() int expectedSize = 7 * 3; float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 }; RcVec3f center = new RcVec3f(4, 0, 0); - float[] constrained = _constraint.Apply(polygon, center, 4); + _constraint.Apply(polygon, center, 4, out var constrained); Assert.That(constrained.Length, Is.EqualTo(expectedSize)); - Assert.That(constrained, Is.SupersetOf(new[] { 1.53589869f, 0f, 3f, 2f, 0f, 3f, 3f, 0f, -3f })); + Assert.That(constrained.ToArray(), Is.SupersetOf(new[] { 1.53589869f, 0f, 3f, 2f, 0f, 3f, 3f, 0f, -3f })); } } \ No newline at end of file