Changed to reuse samples and edges list in BuildPolyDetail()

This commit is contained in:
ikpil 2024-06-08 12:08:31 +09:00
parent 759e335961
commit face8eb48e
4 changed files with 69 additions and 66 deletions

View File

@ -13,7 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Nothing
### Changed
- Nothing
- Changed to reuse samples and edges list in BuildPolyDetail()
### Removed
- Removed RcVecUtils.Dot()

View File

@ -63,17 +63,6 @@ namespace DotRecast.Core.Numerics
@this.Z * v[vi + 2];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static RcVec3f Add(RcVec3f a, float[] verts, int i)
{
return new RcVec3f(
a.X + verts[i],
a.Y + verts[i + 1],
a.Z + verts[i + 2]
);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Cross(float[] dest, float[] v1, float[] v2)
{

View File

@ -0,0 +1,8 @@
namespace DotRecast.Recast
{
public static class EdgeValues
{
public const int EV_UNDEF = -1;
public const int EV_HULL = -2;
}
}

View File

@ -27,50 +27,43 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Recast
{
using static RcRecast;
using static EdgeValues;
public static class RcMeshDetails
{
public const int MAX_VERTS = 127;
public const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
public const int MAX_VERTS_PER_EDGE = 32;
public const int RC_UNSET_HEIGHT = RC_SPAN_MAX_HEIGHT;
public const int RC_UNSET_HEIGHT = RcRecast.RC_SPAN_MAX_HEIGHT;
public const int EV_UNDEF = -1;
public const int EV_HULL = -2;
private static float Vdot2(RcVec3f a, RcVec3f b)
public static float Vdot2(RcVec3f a, RcVec3f b)
{
return a.X * b.X + a.Z * b.Z;
}
private static float VdistSq2(float[] verts, int p, int q)
public static float VdistSq2(float[] verts, int p, int q)
{
float dx = verts[q + 0] - verts[p + 0];
float dy = verts[q + 2] - verts[p + 2];
return dx * dx + dy * dy;
}
private static float Vdist2(float[] verts, int p, int q)
public static float Vdist2(float[] verts, int p, int q)
{
return MathF.Sqrt(VdistSq2(verts, p, q));
}
private static float VdistSq2(RcVec3f p, RcVec3f q)
public static float VdistSq2(RcVec3f p, RcVec3f q)
{
float dx = q.X - p.X;
float dy = q.Z - p.Z;
return dx * dx + dy * dy;
}
private static float Vdist2(RcVec3f p, RcVec3f q)
public static float Vdist2(RcVec3f p, RcVec3f q)
{
return MathF.Sqrt(VdistSq2(p, q));
}
private static float Vcross2(float[] verts, int p1, int p2, int p3)
public static float Vcross2(float[] verts, int p1, int p2, int p3)
{
float u1 = verts[p2 + 0] - verts[p1 + 0];
float v1 = verts[p2 + 2] - verts[p1 + 2];
@ -79,7 +72,7 @@ namespace DotRecast.Recast
return u1 * v2 - v1 * u2;
}
private static float Vcross2(RcVec3f p1, RcVec3f p2, RcVec3f p3)
public static float Vcross2(RcVec3f p1, RcVec3f p2, RcVec3f p3)
{
float u1 = p2.X - p1.X;
float v1 = p2.Z - p1.Z;
@ -89,7 +82,7 @@ namespace DotRecast.Recast
}
private static bool CircumCircle(RcVec3f p1, RcVec3f p2, RcVec3f p3, ref RcVec3f c, out float r)
public static bool CircumCircle(RcVec3f p1, RcVec3f p2, RcVec3f p3, ref RcVec3f c, out float r)
{
const float EPS = 1e-6f;
// Calculate the circle relative to p1, to avoid some precision issues.
@ -116,7 +109,7 @@ namespace DotRecast.Recast
return false;
}
private static float DistPtTri(RcVec3f p, RcVec3f a, RcVec3f b, RcVec3f c)
public static float DistPtTri(RcVec3f p, RcVec3f a, RcVec3f b, RcVec3f c)
{
var v0 = c - a;
var v1 = b - a;
@ -144,7 +137,7 @@ namespace DotRecast.Recast
return float.MaxValue;
}
private static float DistancePtSeg(float[] verts, int pt, int p, int q)
public static float DistancePtSeg(float[] verts, int pt, int p, int q)
{
float pqx = verts[q + 0] - verts[p + 0];
float pqy = verts[q + 1] - verts[p + 1];
@ -175,7 +168,7 @@ namespace DotRecast.Recast
return dx * dx + dy * dy + dz * dz;
}
private static float DistancePtSeg2d(RcVec3f verts, float[] poly, int p, int q)
public static float DistancePtSeg2d(RcVec3f verts, float[] poly, int p, int q)
{
float pqx = poly[q + 0] - poly[p + 0];
float pqz = poly[q + 2] - poly[p + 2];
@ -203,7 +196,7 @@ namespace DotRecast.Recast
return dx * dx + dz * dz;
}
private static float DistancePtSeg2d(float[] verts, int pt, float[] poly, int p, int q)
public static float DistancePtSeg2d(float[] verts, int pt, float[] poly, int p, int q)
{
float pqx = poly[q + 0] - poly[p + 0];
float pqz = poly[q + 2] - poly[p + 2];
@ -231,7 +224,7 @@ namespace DotRecast.Recast
return dx * dx + dz * dz;
}
private static float DistToTriMesh(RcVec3f p, float[] verts, int nverts, List<int> tris, int ntris)
public static float DistToTriMesh(RcVec3f p, float[] verts, int nverts, List<int> tris, int ntris)
{
float dmin = float.MaxValue;
for (int i = 0; i < ntris; ++i)
@ -254,7 +247,7 @@ namespace DotRecast.Recast
return dmin;
}
private static float DistToPoly(int nvert, float[] verts, RcVec3f p)
public static float DistToPoly(int nvert, float[] verts, RcVec3f p)
{
float dmin = float.MaxValue;
int i, j;
@ -275,7 +268,7 @@ namespace DotRecast.Recast
return c ? -dmin : dmin;
}
private static int GetHeight(float fx, float fy, float fz, float cs, float ics, float ch, int radius,
public static int GetHeight(float fx, float fy, float fz, float cs, float ics, float ch, int radius,
RcHeightPatch hp)
{
int ix = (int)MathF.Floor(fx * ics + 0.01f);
@ -358,7 +351,7 @@ namespace DotRecast.Recast
return h;
}
private static int FindEdge(List<int> edges, int s, int t)
public static int FindEdge(List<int> edges, int s, int t)
{
for (int i = 0; i < edges.Count / 4; i++)
{
@ -372,7 +365,7 @@ namespace DotRecast.Recast
return EV_UNDEF;
}
private static void AddEdge(RcContext ctx, List<int> edges, int maxEdges, int s, int t, int l, int r)
public static void AddEdge(RcContext ctx, List<int> edges, int maxEdges, int s, int t, int l, int r)
{
if (edges.Count / 4 >= maxEdges)
{
@ -390,7 +383,7 @@ namespace DotRecast.Recast
}
}
private static void UpdateLeftFace(List<int> edges, int e, int s, int t, int f)
public static void UpdateLeftFace(List<int> edges, int e, int s, int t, int f)
{
if (edges[e + 0] == s && edges[e + 1] == t && edges[e + 2] == EV_UNDEF)
{
@ -402,7 +395,7 @@ namespace DotRecast.Recast
}
}
private static bool OverlapSegSeg2d(float[] verts, int a, int b, int c, int d)
public static bool OverlapSegSeg2d(float[] verts, int a, int b, int c, int d)
{
float a1 = Vcross2(verts, a, b, d);
float a2 = Vcross2(verts, a, b, c);
@ -419,7 +412,7 @@ namespace DotRecast.Recast
return false;
}
private static bool OverlapEdges(float[] pts, List<int> edges, int s1, int t1)
public static bool OverlapEdges(float[] pts, List<int> edges, int s1, int t1)
{
for (int i = 0; i < edges.Count / 4; ++i)
{
@ -440,7 +433,7 @@ namespace DotRecast.Recast
return false;
}
static int CompleteFacet(RcContext ctx, float[] pts, int npts, List<int> edges, int maxEdges, int nfaces, int e)
public static int CompleteFacet(RcContext ctx, float[] pts, int npts, List<int> edges, int maxEdges, int nfaces, int e)
{
const float EPS = 1e-5f;
@ -561,7 +554,7 @@ namespace DotRecast.Recast
return nfaces;
}
private static void DelaunayHull(RcContext ctx, int npts, float[] pts, int nhull, int[] hull, List<int> tris)
public static void DelaunayHull(RcContext ctx, int npts, float[] pts, int nhull, int[] hull, List<int> tris)
{
int nfaces = 0;
int maxEdges = npts * 10;
@ -657,7 +650,7 @@ namespace DotRecast.Recast
}
// Calculate minimum extend of the polygon.
private static float PolyMinExtent(float[] verts, int nverts)
public static float PolyMinExtent(float[] verts, int nverts)
{
float minDist = float.MaxValue;
for (int i = 0; i < nverts; i++)
@ -683,7 +676,7 @@ namespace DotRecast.Recast
return MathF.Sqrt(minDist);
}
private static void TriangulateHull(int nverts, float[] verts, int nhull, int[] hull, int nin, List<int> tris)
public static void TriangulateHull(int nverts, float[] verts, int nhull, int[] hull, int nin, List<int> tris)
{
int start = 0, left = 1, right = nhull - 1;
@ -755,33 +748,37 @@ namespace DotRecast.Recast
}
}
private static float GetJitterX(int i)
public static float GetJitterX(int i)
{
return (((i * 0x8da6b343) & 0xffff) / 65535.0f * 2.0f) - 1.0f;
}
private static float GetJitterY(int i)
public static float GetJitterY(int i)
{
return (((i * 0xd8163841) & 0xffff) / 65535.0f * 2.0f) - 1.0f;
}
static int BuildPolyDetail(RcContext ctx, float[] @in, int nin, float sampleDist, float sampleMaxError,
int heightSearchRadius, RcCompactHeightfield chf, RcHeightPatch hp, float[] verts, List<int> tris)
public static int BuildPolyDetail(RcContext ctx, float[] @in, int nin,
float sampleDist, float sampleMaxError,
int heightSearchRadius, RcCompactHeightfield chf,
RcHeightPatch hp, float[] verts,
ref List<int> tris, ref List<int> edges, ref List<int> samples)
{
List<int> samples = new List<int>(512);
int nverts = 0;
const int MAX_VERTS = 127;
const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
const int MAX_VERTS_PER_EDGE = 32;
float[] edge = new float[(MAX_VERTS_PER_EDGE + 1) * 3];
int[] hull = new int[MAX_VERTS];
int nhull = 0;
nverts = nin;
int nverts = nin;
for (int i = 0; i < nin; ++i)
{
RcVecUtils.Copy(verts, i * 3, @in, i * 3);
}
edges.Clear();
tris.Clear();
float cs = chf.cs;
@ -1042,7 +1039,7 @@ namespace DotRecast.Recast
return nverts;
}
static bool OnHull(int a, int b, int nhull, int[] hull)
public static bool OnHull(int a, int b, int nhull, int[] hull)
{
// All internal sampled points come after the hull so we can early out for those.
if (a >= nhull || b >= nhull)
@ -1058,7 +1055,7 @@ namespace DotRecast.Recast
}
// Find edges that lie on hull and mark them as such.
static void SetTriFlags(List<int> tris, int nhull, int[] hull)
public static void SetTriFlags(List<int> tris, int nhull, int[] hull)
{
// Matches DT_DETAIL_EDGE_BOUNDARY
const int DETAIL_EDGE_BOUNDARY = 0x1;
@ -1077,7 +1074,7 @@ namespace DotRecast.Recast
}
static void SeedArrayWithPolyCenter(RcContext ctx, RcCompactHeightfield chf, int[] meshpoly, int poly, int npoly,
public static void SeedArrayWithPolyCenter(RcContext ctx, RcCompactHeightfield chf, int[] meshpoly, int poly, int npoly,
int[] verts, int bs, RcHeightPatch hp, List<int> array)
{
// Note: Reads to the compact heightfield are offset by border size (bs)
@ -1226,22 +1223,25 @@ namespace DotRecast.Recast
hp.data[cx - hp.xmin + (cy - hp.ymin) * hp.width] = cs2.y;
}
const int RETRACT_SIZE = 256;
static void Push3(List<int> queue, int v1, int v2, int v3)
public static void Push3(List<int> queue, int v1, int v2, int v3)
{
queue.Add(v1);
queue.Add(v2);
queue.Add(v3);
}
static void GetHeightData(RcContext ctx, RcCompactHeightfield chf, int[] meshpolys, int poly, int npoly, int[] verts,
int bs, RcHeightPatch hp, int region)
public static void GetHeightData(RcContext ctx, RcCompactHeightfield chf,
int[] meshpolys, int poly, int npoly,
int[] verts, int bs,
ref RcHeightPatch hp, ref List<int> queue,
int region)
{
// Note: Reads to the compact heightfield are offset by border size (bs)
// since border size offset is already removed from the polymesh vertices.
List<int> queue = new List<int>(512);
queue.Clear();
// Set all heights to RC_UNSET_HEIGHT.
Array.Fill(hp.data, RC_UNSET_HEIGHT, 0, (hp.width * hp.height) - (0));
bool empty = true;
@ -1307,6 +1307,7 @@ namespace DotRecast.Recast
SeedArrayWithPolyCenter(ctx, chf, meshpolys, poly, npoly, verts, bs, hp, queue);
}
const int RETRACT_SIZE = 256;
int head = 0;
// We assume the seed is centered in the polygon, so a BFS to collect
@ -1378,7 +1379,10 @@ namespace DotRecast.Recast
int borderSize = mesh.borderSize;
int heightSearchRadius = (int)Math.Max(1, MathF.Ceiling(mesh.maxEdgeError));
List<int> edges = new List<int>(64);
List<int> tris = new List<int>(512);
List<int> arr = new List<int>(512);
List<int> samples = new List<int>(512);
float[] verts = new float[256 * 3];
RcHeightPatch hp = new RcHeightPatch();
int nPolyVerts = 0;
@ -1463,18 +1467,20 @@ namespace DotRecast.Recast
hp.ymin = bounds[i * 4 + 2];
hp.width = bounds[i * 4 + 1] - bounds[i * 4 + 0];
hp.height = bounds[i * 4 + 3] - bounds[i * 4 + 2];
GetHeightData(ctx, chf, mesh.polys, p, npoly, mesh.verts, borderSize, hp, mesh.regs[i]);
GetHeightData(ctx, chf, mesh.polys, p, npoly, mesh.verts, borderSize, ref hp, ref arr, mesh.regs[i]);
// Build detail mesh.
int nverts = BuildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, heightSearchRadius, chf, hp,
verts, tris);
int nverts = BuildPolyDetail(ctx, poly, npoly,
sampleDist, sampleMaxError,
heightSearchRadius, chf, hp,
verts, ref tris,
ref edges, ref samples);
// Move detail verts to world space.
for (int j = 0; j < nverts; ++j)
{
verts[j * 3 + 0] += orig.X;
verts[j * 3 + 1] += orig.Y + chf.ch; // Is this offset necessary? See
// https://groups.google.com/d/msg/recastnavigation/UQFN6BGCcV0/-1Ny4koOBpkJ
verts[j * 3 + 2] += orig.Z;
}
@ -1551,7 +1557,7 @@ namespace DotRecast.Recast
}
/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
private static RcPolyMeshDetail MergePolyMeshDetails(RcContext ctx, RcPolyMeshDetail[] meshes, int nmeshes)
public static RcPolyMeshDetail MergePolyMeshDetails(RcContext ctx, RcPolyMeshDetail[] meshes, int nmeshes)
{
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MERGE_POLYMESHDETAIL);