remove warn

This commit is contained in:
ikpil 2023-06-02 00:13:25 +09:00
parent 75aaaefbc3
commit 1ed0d41218
22 changed files with 144 additions and 571 deletions

View File

@ -17,8 +17,6 @@ freely, subject to the following restrictions:
*/ */
using System; using System;
using DotRecast.Core;
using static DotRecast.Core.RcMath;
namespace DotRecast.Core namespace DotRecast.Core
{ {
@ -78,16 +76,16 @@ namespace DotRecast.Core
return t; return t;
} }
public static float[] IntersectSegmentAABB(Vector3f sp, Vector3f sq, Vector3f amin, Vector3f amax) public static bool IsectSegAABB(Vector3f sp, Vector3f sq, Vector3f amin, Vector3f amax, out float tmin, out float tmax)
{ {
float EPS = 1e-6f; const float EPS = 1e-6f;
Vector3f d = new Vector3f(); Vector3f d = new Vector3f();
d.x = sq.x - sp.x; d.x = sq.x - sp.x;
d.y = sq.y - sp.y; d.y = sq.y - sp.y;
d.z = sq.z - sp.z; d.z = sq.z - sp.z;
float tmin = 0.0f; tmin = 0.0f;
float tmax = 1.0f; tmax = float.MaxValue;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
@ -95,7 +93,7 @@ namespace DotRecast.Core
{ {
if (sp[i] < amin[i] || sp[i] > amax[i]) if (sp[i] < amin[i] || sp[i] > amax[i])
{ {
return null; return false;
} }
} }
else else
@ -103,11 +101,10 @@ namespace DotRecast.Core
float ood = 1.0f / d[i]; float ood = 1.0f / d[i];
float t1 = (amin[i] - sp[i]) * ood; float t1 = (amin[i] - sp[i]) * ood;
float t2 = (amax[i] - sp[i]) * ood; float t2 = (amax[i] - sp[i]) * ood;
if (t1 > t2) if (t1 > t2)
{ {
float tmp = t1; (t1, t2) = (t2, t1);
t1 = t2;
t2 = tmp;
} }
if (t1 > tmin) if (t1 > tmin)
@ -122,12 +119,12 @@ namespace DotRecast.Core
if (tmin > tmax) if (tmin > tmax)
{ {
return null; return false;
} }
} }
} }
return new float[] { tmin, tmax }; return true;
} }
} }
} }

View File

@ -24,31 +24,11 @@ namespace DotRecast.Core
{ {
public static class RcMath public static class RcMath
{ {
public const float EPS = 1e-4f;
private static readonly float EQUAL_THRESHOLD = Sqr(1.0f / 16384.0f);
public static float Sqr(float f) public static float Sqr(float f)
{ {
return f * f; return f * f;
} }
public static float GetPathLen(float[] path, int npath)
{
float totd = 0;
for (int i = 0; i < npath - 1; ++i)
{
totd += (float)Math.Sqrt(Vector3f.DistSqr(path, i * 3, (i + 1) * 3));
}
return totd;
}
public static float Step(float threshold, float v)
{
return v < threshold ? 0.0f : 1.0f;
}
public static float Clamp(float v, float min, float max) public static float Clamp(float v, float min, float max)
{ {
return Math.Max(Math.Min(v, max), min); return Math.Max(Math.Min(v, max), min);
@ -58,431 +38,5 @@ namespace DotRecast.Core
{ {
return Math.Max(Math.Min(v, max), min); return Math.Max(Math.Min(v, max), min);
} }
public static float Lerp(float f, float g, float u)
{
return u * g + (1f - u) * f;
}
/// Performs a 'sloppy' colocation check of the specified points.
/// @param[in] p0 A point. [(x, y, z)]
/// @param[in] p1 A point. [(x, y, z)]
/// @return True if the points are considered to be at the same location.
///
/// Basically, this function will return true if the specified points are
/// close enough to eachother to be considered colocated.
public static bool VEqual(Vector3f p0, Vector3f p1)
{
return VEqual(p0, p1, EQUAL_THRESHOLD);
}
public static bool VEqual(Vector3f p0, Vector3f p1, float thresholdSqr)
{
float d = Vector3f.DistSqr(p0, p1);
return d < thresholdSqr;
}
/// @}
/// @name Computational geometry helper functions.
/// @{
/// Derives the signed xz-plane area of the triangle ABC, or the
/// relationship of line AB to point C.
/// @param[in] a Vertex A. [(x, y, z)]
/// @param[in] b Vertex B. [(x, y, z)]
/// @param[in] c Vertex C. [(x, y, z)]
/// @return The signed xz-plane area of the triangle.
public static float TriArea2D(float[] verts, int a, int b, int c)
{
float abx = verts[b] - verts[a];
float abz = verts[b + 2] - verts[a + 2];
float acx = verts[c] - verts[a];
float acz = verts[c + 2] - verts[a + 2];
return acx * abz - abx * acz;
}
public static float TriArea2D(Vector3f a, Vector3f b, Vector3f c)
{
float abx = b.x - a.x;
float abz = b.z - a.z;
float acx = c.x - a.x;
float acz = c.z - a.z;
return acx * abz - abx * acz;
}
/// Determines if two axis-aligned bounding boxes overlap.
/// @param[in] amin Minimum bounds of box A. [(x, y, z)]
/// @param[in] amax Maximum bounds of box A. [(x, y, z)]
/// @param[in] bmin Minimum bounds of box B. [(x, y, z)]
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
/// @return True if the two AABB's overlap.
/// @see dtOverlapBounds
public static bool OverlapQuantBounds(int[] amin, int[] amax, int[] bmin, int[] bmax)
{
bool overlap = true;
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
return overlap;
}
/// Determines if two axis-aligned bounding boxes overlap.
/// @param[in] amin Minimum bounds of box A. [(x, y, z)]
/// @param[in] amax Maximum bounds of box A. [(x, y, z)]
/// @param[in] bmin Minimum bounds of box B. [(x, y, z)]
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
/// @return True if the two AABB's overlap.
/// @see dtOverlapQuantBounds
public static bool OverlapBounds(Vector3f amin, Vector3f amax, Vector3f bmin, Vector3f bmax)
{
bool overlap = true;
overlap = (amin.x > bmax.x || amax.x < bmin.x) ? false : overlap;
overlap = (amin.y > bmax.y || amax.y < bmin.y) ? false : overlap;
overlap = (amin.z > bmax.z || amax.z < bmin.z) ? false : overlap;
return overlap;
}
public static float DistancePtSegSqr2D(Vector3f pt, float[] verts, int p, int q, out float t)
{
var vp = Vector3f.Of(verts, p);
var vq = Vector3f.Of(verts, q);
return DistancePtSegSqr2D(pt, vp, vq, out t);
}
public static float DistancePtSegSqr2D(Vector3f pt, Vector3f p, Vector3f q, out float t)
{
float pqx = q.x - p.x;
float pqz = q.z - p.z;
float dx = pt.x - p.x;
float dz = pt.z - p.z;
float d = pqx * pqx + pqz * pqz;
t = pqx * dx + pqz * dz;
if (d > 0)
{
t /= d;
}
if (t < 0)
{
t = 0;
}
else if (t > 1)
{
t = 1;
}
dx = p.x + t * pqx - pt.x;
dz = p.z + t * pqz - pt.z;
return dx * dx + dz * dz;
}
public static float? ClosestHeightPointTriangle(Vector3f p, Vector3f a, Vector3f b, Vector3f c)
{
Vector3f v0 = c.Subtract(a);
Vector3f v1 = b.Subtract(a);
Vector3f v2 = p.Subtract(a);
// Compute scaled barycentric coordinates
float denom = v0.x * v1.z - v0.z * v1.x;
if (Math.Abs(denom) < EPS)
{
return null;
}
float u = v1.z * v2.x - v1.x * v2.z;
float v = v0.x * v2.z - v0.z * v2.x;
if (denom < 0)
{
denom = -denom;
u = -u;
v = -v;
}
// If point lies inside the triangle, return interpolated ycoord.
if (u >= 0.0f && v >= 0.0f && (u + v) <= denom)
{
float h = a.y + (v0.y * u + v1.y * v) / denom;
return h;
}
return null;
}
/// @par
///
/// All points are projected onto the xz-plane, so the y-values are ignored.
public static bool PointInPolygon(Vector3f pt, float[] verts, int nverts)
{
// TODO: Replace pnpoly with triArea2D tests?
int i, j;
bool c = false;
for (i = 0, j = nverts - 1; i < nverts; j = i++)
{
int vi = i * 3;
int vj = j * 3;
if (((verts[vi + 2] > pt.z) != (verts[vj + 2] > pt.z)) && (pt.x < (verts[vj + 0] - verts[vi + 0])
* (pt.z - verts[vi + 2]) / (verts[vj + 2] - verts[vi + 2]) + verts[vi + 0]))
{
c = !c;
}
}
return c;
}
public static bool DistancePtPolyEdgesSqr(Vector3f pt, float[] verts, int nverts, float[] ed, float[] et)
{
// TODO: Replace pnpoly with triArea2D tests?
int i, j;
bool c = false;
for (i = 0, j = nverts - 1; i < nverts; j = i++)
{
int vi = i * 3;
int vj = j * 3;
if (((verts[vi + 2] > pt.z) != (verts[vj + 2] > pt.z)) &&
(pt.x < (verts[vj + 0] - verts[vi + 0]) * (pt.z - verts[vi + 2]) / (verts[vj + 2] - verts[vi + 2]) + verts[vi + 0]))
{
c = !c;
}
ed[j] = DistancePtSegSqr2D(pt, verts, vj, vi, out et[j]);
}
return c;
}
public static Vector2f ProjectPoly(Vector3f axis, float[] poly, int npoly)
{
float rmin, rmax;
rmin = rmax = axis.Dot2D(poly, 0);
for (int i = 1; i < npoly; ++i)
{
float d = axis.Dot2D(poly, i * 3);
rmin = Math.Min(rmin, d);
rmax = Math.Max(rmax, d);
}
return new Vector2f
{
x = rmin,
y = rmax,
};
}
public static bool OverlapRange(float amin, float amax, float bmin, float bmax, float eps)
{
return ((amin + eps) > bmax || (amax - eps) < bmin) ? false : true;
}
const float eps = 1e-4f;
/// @par
///
/// All vertices are projected onto the xz-plane, so the y-values are ignored.
public static bool OverlapPolyPoly2D(float[] polya, int npolya, float[] polyb, int npolyb)
{
for (int i = 0, j = npolya - 1; i < npolya; j = i++)
{
int va = j * 3;
int vb = i * 3;
Vector3f n = Vector3f.Of(polya[vb + 2] - polya[va + 2], 0, -(polya[vb + 0] - polya[va + 0]));
Vector2f aminmax = ProjectPoly(n, polya, npolya);
Vector2f bminmax = ProjectPoly(n, polyb, npolyb);
if (!OverlapRange(aminmax.x, aminmax.y, bminmax.x, bminmax.y, eps))
{
// Found separating axis
return false;
}
}
for (int i = 0, j = npolyb - 1; i < npolyb; j = i++)
{
int va = j * 3;
int vb = i * 3;
Vector3f n = Vector3f.Of(polyb[vb + 2] - polyb[va + 2], 0, -(polyb[vb + 0] - polyb[va + 0]));
Vector2f aminmax = ProjectPoly(n, polya, npolya);
Vector2f bminmax = ProjectPoly(n, polyb, npolyb);
if (!OverlapRange(aminmax.x, aminmax.y, bminmax.x, bminmax.y, eps))
{
// Found separating axis
return false;
}
}
return true;
}
// Returns a random point in a convex polygon.
// Adapted from Graphics Gems article.
public static Vector3f RandomPointInConvexPoly(float[] pts, int npts, float[] areas, float s, float t)
{
// Calc triangle araes
float areasum = 0.0f;
for (int i = 2; i < npts; i++)
{
areas[i] = TriArea2D(pts, 0, (i - 1) * 3, i * 3);
areasum += Math.Max(0.001f, areas[i]);
}
// Find sub triangle weighted by area.
float thr = s * areasum;
float acc = 0.0f;
float u = 1.0f;
int tri = npts - 1;
for (int i = 2; i < npts; i++)
{
float dacc = areas[i];
if (thr >= acc && thr < (acc + dacc))
{
u = (thr - acc) / dacc;
tri = i;
break;
}
acc += dacc;
}
float v = (float)Math.Sqrt(t);
float a = 1 - v;
float b = (1 - u) * v;
float c = u * v;
int pa = 0;
int pb = (tri - 1) * 3;
int pc = tri * 3;
return new Vector3f()
{
x = a * pts[pa] + b * pts[pb] + c * pts[pc],
y = a * pts[pa + 1] + b * pts[pb + 1] + c * pts[pc + 1],
z = a * pts[pa + 2] + b * pts[pb + 2] + c * pts[pc + 2]
};
}
public static int NextPow2(int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
public static int Ilog2(int v)
{
int r;
int shift;
r = (v > 0xffff ? 1 : 0) << 4;
v >>= r;
shift = (v > 0xff ? 1 : 0) << 3;
v >>= shift;
r |= shift;
shift = (v > 0xf ? 1 : 0) << 2;
v >>= shift;
r |= shift;
shift = (v > 0x3 ? 1 : 0) << 1;
v >>= shift;
r |= shift;
r |= (v >> 1);
return r;
}
public static IntersectResult IntersectSegmentPoly2D(Vector3f p0, Vector3f p1, float[] verts, int nverts)
{
IntersectResult result = new IntersectResult();
float EPS = 0.000001f;
var dir = p1.Subtract(p0);
var p0v = p0;
for (int i = 0, j = nverts - 1; i < nverts; j = i++)
{
Vector3f vpj = Vector3f.Of(verts, j * 3);
Vector3f vpi = Vector3f.Of(verts, i * 3);
var edge = vpi.Subtract(vpj);
var diff = p0v.Subtract(vpj);
float n = Vector3f.Perp2D(edge, diff);
float d = Vector3f.Perp2D(dir, edge);
if (Math.Abs(d) < EPS)
{
// S is nearly parallel to this edge
if (n < 0)
{
return result;
}
else
{
continue;
}
}
float t = n / d;
if (d < 0)
{
// segment S is entering across this edge
if (t > result.tmin)
{
result.tmin = t;
result.segMin = j;
// S enters after leaving polygon
if (result.tmin > result.tmax)
{
return result;
}
}
}
else
{
// segment S is leaving across this edge
if (t < result.tmax)
{
result.tmax = t;
result.segMax = j;
// S leaves before entering polygon
if (result.tmax < result.tmin)
{
return result;
}
}
}
}
result.intersects = true;
return result;
}
public static int OppositeTile(int side)
{
return (side + 4) & 0x7;
}
public static bool IntersectSegSeg2D(Vector3f ap, Vector3f aq, Vector3f bp, Vector3f bq, out float s, out float t)
{
s = 0;
t = 0;
Vector3f u = aq.Subtract(ap);
Vector3f v = bq.Subtract(bp);
Vector3f w = ap.Subtract(bp);
float d = Vector3f.PerpXZ(u, v);
if (Math.Abs(d) < 1e-6f)
{
return false;
}
s = Vector3f.PerpXZ(v, w) / d;
t = Vector3f.PerpXZ(u, w) / d;
return true;
}
} }
} }

View File

@ -1161,7 +1161,7 @@ namespace DotRecast.Detour.Crowd
Vector3f[] s = ag.boundary.GetSegment(j); Vector3f[] s = ag.boundary.GetSegment(j);
Vector3f s3 = s[1]; Vector3f s3 = s[1];
//Array.Copy(s, 3, s3, 0, 3); //Array.Copy(s, 3, s3, 0, 3);
if (TriArea2D(ag.npos, s[0], s3) < 0.0f) if (DetourCommon.TriArea2D(ag.npos, s[0], s3) < 0.0f)
{ {
continue; continue;
} }

View File

@ -120,7 +120,7 @@ namespace DotRecast.Detour.Crowd
var s3 = Vector3f.Of(s[3], s[4], s[5]); var s3 = Vector3f.Of(s[3], s[4], s[5]);
// Skip too distant segments. // Skip too distant segments.
var distSqr = DistancePtSegSqr2D(pos, s0, s3, out var tseg); var distSqr = DetourCommon.DistancePtSegSqr2D(pos, s0, s3, out var tseg);
if (distSqr > Sqr(collisionQueryRange)) if (distSqr > Sqr(collisionQueryRange))
{ {
continue; continue;

View File

@ -131,7 +131,7 @@ namespace DotRecast.Detour.Crowd
cir.dp.Normalize(); cir.dp.Normalize();
dv = cir.dvel.Subtract(dvel); dv = cir.dvel.Subtract(dvel);
float a = TriArea2D(orig, cir.dp, dv); float a = DetourCommon.TriArea2D(orig, cir.dp, dv);
if (a < 0.01f) if (a < 0.01f)
{ {
cir.np.x = -cir.dp.z; cir.np.x = -cir.dp.z;
@ -150,7 +150,7 @@ namespace DotRecast.Detour.Crowd
// Precalc if the agent is really close to the segment. // Precalc if the agent is really close to the segment.
float r = 0.01f; float r = 0.01f;
var distSqr = DistancePtSegSqr2D(pos, seg.p, seg.q, out var t); var distSqr = DetourCommon.DistancePtSegSqr2D(pos, seg.p, seg.q, out var t);
seg.touch = distSqr < Sqr(r); seg.touch = distSqr < Sqr(r);
} }
} }

View File

@ -43,7 +43,7 @@ namespace DotRecast.Detour.Crowd
int iterCount = config.maxFindPathIterations; int iterCount = config.maxFindPathIterations;
while (iterCount > 0) while (iterCount > 0)
{ {
PathQuery? q = queue.First?.Value; PathQuery q = queue.First?.Value;
if (q == null) if (q == null)
{ {
break; break;

View File

@ -74,7 +74,7 @@ namespace DotRecast.Detour.TileCache
/// Encodes a tile id. /// Encodes a tile id.
private long EncodeTileId(int salt, int it) private long EncodeTileId(int salt, int it)
{ {
return ((long)salt << m_tileBits) | it; return ((long)salt << m_tileBits) | (long)it;
} }
/// Decodes a tile salt. /// Decodes a tile salt.
@ -94,7 +94,7 @@ namespace DotRecast.Detour.TileCache
/// Encodes an obstacle id. /// Encodes an obstacle id.
private long EncodeObstacleId(int salt, int it) private long EncodeObstacleId(int salt, int it)
{ {
return ((long)salt << 16) | it; return ((long)salt << 16) | (long)it;
} }
/// Decodes an obstacle salt. /// Decodes an obstacle salt.
@ -120,7 +120,7 @@ namespace DotRecast.Detour.TileCache
m_tcomp = tcomp; m_tcomp = tcomp;
m_tmproc = tmprocs; m_tmproc = tmprocs;
m_tileLutSize = NextPow2(m_params.maxTiles / 4); m_tileLutSize = DetourCommon.NextPow2(m_params.maxTiles / 4);
if (m_tileLutSize == 0) if (m_tileLutSize == 0)
{ {
m_tileLutSize = 1; m_tileLutSize = 1;
@ -136,7 +136,7 @@ namespace DotRecast.Detour.TileCache
m_nextFreeTile = m_tiles[i]; m_nextFreeTile = m_tiles[i];
} }
m_tileBits = Ilog2(NextPow2(m_params.maxTiles)); m_tileBits = DetourCommon.Ilog2(DetourCommon.NextPow2(m_params.maxTiles));
m_saltBits = Math.Min(31, 32 - m_tileBits); m_saltBits = Math.Min(31, 32 - m_tileBits);
if (m_saltBits < 10) if (m_saltBits < 10)
{ {
@ -458,7 +458,7 @@ namespace DotRecast.Detour.TileCache
Vector3f tbmin = new Vector3f(); Vector3f tbmin = new Vector3f();
Vector3f tbmax = new Vector3f(); Vector3f tbmax = new Vector3f();
CalcTightTileBounds(tile.header, ref tbmin, ref tbmax); CalcTightTileBounds(tile.header, ref tbmin, ref tbmax);
if (OverlapBounds(bmin, bmax, tbmin, tbmax)) if (DetourCommon.OverlapBounds(bmin, bmax, tbmin, tbmax))
{ {
results.Add(i); results.Add(i);
} }

View File

@ -63,8 +63,8 @@ namespace DotRecast.Detour
Vector3f B = b.Subtract(b1); Vector3f B = b.Subtract(b1);
float cross = B.x * A.z - A.x * B.z; // TriArea2D({0, 0}, A, B); float cross = B.x * A.z - A.x * B.z; // TriArea2D({0, 0}, A, B);
float aHB = TriArea2D(b1, b, a); float aHB = DetourCommon.TriArea2D(b1, b, a);
float bHA = TriArea2D(a1, a, b); float bHA = DetourCommon.TriArea2D(a1, a, b);
if (Math.Abs(cross) < EPSILON) if (Math.Abs(cross) < EPSILON)
{ {
cross = 0f; cross = 0f;
@ -235,7 +235,7 @@ namespace DotRecast.Detour
private static Intersection SegSegInt(Vector3f a, Vector3f b, Vector3f c, Vector3f d, ref Vector3f p, ref Vector3f q) private static Intersection SegSegInt(Vector3f a, Vector3f b, Vector3f c, Vector3f d, ref Vector3f p, ref Vector3f q)
{ {
if (IntersectSegSeg2D(a, b, c, d, out var s, out var t)) if (DetourCommon.IntersectSegSeg2D(a, b, c, d, out var s, out var t))
{ {
if (s >= 0.0f && s <= 1.0f && t >= 0.0f && t <= 1.0f) if (s >= 0.0f && s <= 1.0f && t >= 0.0f && t <= 1.0f)
{ {

View File

@ -3,10 +3,41 @@ using DotRecast.Core;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
public static class DtCommon public static class DetourCommon
{ {
private static readonly float EQUAL_THRESHOLD = RcMath.Sqr(1.0f / 16384.0f); private static readonly float EQUAL_THRESHOLD = RcMath.Sqr(1.0f / 16384.0f);
public static int NextPow2(int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
public static int Ilog2(int v)
{
int r;
int shift;
r = (v > 0xffff ? 1 : 0) << 4;
v >>= r;
shift = (v > 0xff ? 1 : 0) << 3;
v >>= shift;
r |= shift;
shift = (v > 0xf ? 1 : 0) << 2;
v >>= shift;
r |= shift;
shift = (v > 0x3 ? 1 : 0) << 1;
v >>= shift;
r |= shift;
r |= (v >> 1);
return r;
}
/// Performs a 'sloppy' colocation check of the specified points. /// Performs a 'sloppy' colocation check of the specified points.
/// @param[in] p0 A point. [(x, y, z)] /// @param[in] p0 A point. [(x, y, z)]
/// @param[in] p1 A point. [(x, y, z)] /// @param[in] p1 A point. [(x, y, z)]
@ -311,7 +342,7 @@ namespace DotRecast.Detour
public static IntersectResult IntersectSegmentPoly2D(Vector3f p0, Vector3f p1, float[] verts, int nverts) public static IntersectResult IntersectSegmentPoly2D(Vector3f p0, Vector3f p1, float[] verts, int nverts)
{ {
IntersectResult result = new IntersectResult(); IntersectResult result = new IntersectResult();
float EPS = 0.000001f; const float EPS = 0.000001f;
var dir = p1.Subtract(p0); var dir = p1.Subtract(p0);
var p0v = p0; var p0v = p0;

View File

@ -140,8 +140,8 @@ namespace DotRecast.Detour.Io
private long Convert32BitRef(int refs, NavMeshParams option) private long Convert32BitRef(int refs, NavMeshParams option)
{ {
int m_tileBits = Ilog2(NextPow2(option.maxTiles)); int m_tileBits = DetourCommon.Ilog2(DetourCommon.NextPow2(option.maxTiles));
int m_polyBits = Ilog2(NextPow2(option.maxPolys)); int m_polyBits = DetourCommon.Ilog2(DetourCommon.NextPow2(option.maxPolys));
// Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow. // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow.
int m_saltBits = Math.Min(31, 32 - m_tileBits - m_polyBits); int m_saltBits = Math.Min(31, 32 - m_tileBits - m_polyBits);
int saltMask = (1 << m_saltBits) - 1; int saltMask = (1 << m_saltBits) - 1;

View File

@ -728,7 +728,7 @@ namespace DotRecast.Detour
{ {
// Internal edge // Internal edge
int idx = (bestPoly.neis[j] - 1); int idx = (bestPoly.neis[j] - 1);
long refs = m_nav.GetPolyRefBase(bestTile) | idx; long refs = m_nav.GetPolyRefBase(bestTile) | (long)idx;
if (filter.PassFilter(refs, bestTile, bestTile.data.polys[idx])) if (filter.PassFilter(refs, bestTile, bestTile.data.polys[idx]))
{ {
continue; continue;
@ -738,7 +738,7 @@ namespace DotRecast.Detour
// Calc distance to the edge. // Calc distance to the edge.
int vj = bestPoly.verts[j] * 3; int vj = bestPoly.verts[j] * 3;
int vi = bestPoly.verts[i] * 3; int vi = bestPoly.verts[i] * 3;
var distSqr = DistancePtSegSqr2D(centerPos, bestTile.data.verts, vj, vi, out var tseg); var distSqr = DetourCommon.DistancePtSegSqr2D(centerPos, bestTile.data.verts, vj, vi, out var tseg);
// Edge is too far, skip. // Edge is too far, skip.
if (distSqr > radiusSqr) if (distSqr > radiusSqr)
{ {
@ -781,7 +781,7 @@ namespace DotRecast.Detour
// Calc distance to the edge. // Calc distance to the edge.
int va = bestPoly.verts[link.edge] * 3; int va = bestPoly.verts[link.edge] * 3;
int vb = bestPoly.verts[(link.edge + 1) % bestPoly.vertCount] * 3; int vb = bestPoly.verts[(link.edge + 1) % bestPoly.vertCount] * 3;
var distSqr = DistancePtSegSqr2D(centerPos, bestTile.data.verts, va, vb, out var tseg); var distSqr = DetourCommon.DistancePtSegSqr2D(centerPos, bestTile.data.verts, va, vb, out var tseg);
// If the circle is not touching the next polygon, skip it. // If the circle is not touching the next polygon, skip it.
if (distSqr > radiusSqr) if (distSqr > radiusSqr)
{ {

View File

@ -116,21 +116,17 @@ namespace DotRecast.Detour
return EncodePolyId(tile.salt, it, 0); return EncodePolyId(tile.salt, it, 0);
} }
/** /// @{
* Derives a standard polygon reference. /// @name Encoding and Decoding
* /// These functions are generally meant for internal use only.
* @note This function is generally meant for internal use only. /// Derives a standard polygon reference.
* @param salt /// @note This function is generally meant for internal use only.
* The tile's salt value. /// @param[in] salt The tile's salt value.
* @param it /// @param[in] it The index of the tile.
* The index of the tile. /// @param[in] ip The index of the polygon within the tile.
* @param ip
* The index of the polygon within the tile.
* @return encoded polygon reference
*/
public static long EncodePolyId(int salt, int it, int ip) public static long EncodePolyId(int salt, int it, int ip)
{ {
return (((long)salt) << (DT_POLY_BITS + DT_TILE_BITS)) | ((long)it << DT_POLY_BITS) | ip; return (((long)salt) << (DT_POLY_BITS + DT_TILE_BITS)) | ((long)it << DT_POLY_BITS) | (long)ip;
} }
/// Decodes a standard polygon reference. /// Decodes a standard polygon reference.
@ -299,7 +295,7 @@ namespace DotRecast.Detour
// Init tiles // Init tiles
m_maxTiles = option.maxTiles; m_maxTiles = option.maxTiles;
m_maxVertPerPoly = maxVertsPerPoly; m_maxVertPerPoly = maxVertsPerPoly;
m_tileLutMask = Math.Max(1, NextPow2(option.maxTiles)) - 1; m_tileLutMask = Math.Max(1, DetourCommon.NextPow2(option.maxTiles)) - 1;
m_tiles = new MeshTile[m_maxTiles]; m_tiles = new MeshTile[m_maxTiles];
for (int i = 0; i < m_maxTiles; i++) for (int i = 0; i < m_maxTiles; i++)
{ {
@ -356,12 +352,12 @@ namespace DotRecast.Detour
while (nodeIndex < end) while (nodeIndex < end)
{ {
BVNode node = tile.data.bvTree[nodeIndex]; BVNode node = tile.data.bvTree[nodeIndex];
bool overlap = OverlapQuantBounds(bmin, bmax, node.bmin, node.bmax); bool overlap = DetourCommon.OverlapQuantBounds(bmin, bmax, node.bmin, node.bmax);
bool isLeafNode = node.i >= 0; bool isLeafNode = node.i >= 0;
if (isLeafNode && overlap) if (isLeafNode && overlap)
{ {
polys.Add(@base | node.i); polys.Add(@base | (long)node.i);
} }
if (overlap || isLeafNode) if (overlap || isLeafNode)
@ -402,9 +398,9 @@ namespace DotRecast.Detour
bmax.Max(tile.data.verts, v); bmax.Max(tile.data.verts, v);
} }
if (OverlapBounds(qmin, qmax, bmin, bmax)) if (DetourCommon.OverlapBounds(qmin, qmax, bmin, bmax))
{ {
polys.Add(@base | i); polys.Add(@base | (long)i);
} }
} }
@ -539,9 +535,9 @@ namespace DotRecast.Detour
for (int j = 0; j < neis.Count; ++j) for (int j = 0; j < neis.Count; ++j)
{ {
ConnectExtLinks(tile, neis[j], i); ConnectExtLinks(tile, neis[j], i);
ConnectExtLinks(neis[j], tile, OppositeTile(i)); ConnectExtLinks(neis[j], tile, DetourCommon.OppositeTile(i));
ConnectExtOffMeshLinks(tile, neis[j], i); ConnectExtOffMeshLinks(tile, neis[j], i);
ConnectExtOffMeshLinks(neis[j], tile, OppositeTile(i)); ConnectExtOffMeshLinks(neis[j], tile, DetourCommon.OppositeTile(i));
} }
} }
@ -657,7 +653,7 @@ namespace DotRecast.Detour
int idx = AllocLink(tile); int idx = AllocLink(tile);
Link link = tile.links[idx]; Link link = tile.links[idx];
link.refs = @base | (poly.neis[j] - 1); link.refs = @base | (long)(poly.neis[j] - 1);
link.edge = j; link.edge = j;
link.side = 0xff; link.side = 0xff;
link.bmin = link.bmax = 0; link.bmin = link.bmax = 0;
@ -743,7 +739,7 @@ namespace DotRecast.Detour
// Create new links // Create new links
int va = poly.verts[j] * 3; int va = poly.verts[j] * 3;
int vb = poly.verts[(j + 1) % nv] * 3; int vb = poly.verts[(j + 1) % nv] * 3;
IList<Tuple<long, float, float>> connectedPolys = FindConnectingPolys(tile.data.verts, va, vb, target, OppositeTile(dir)); IList<Tuple<long, float, float>> connectedPolys = FindConnectingPolys(tile.data.verts, va, vb, target, DetourCommon.OppositeTile(dir));
foreach (Tuple<long, float, float> connectedPoly in connectedPolys) foreach (Tuple<long, float, float> connectedPoly in connectedPolys)
{ {
int idx = AllocLink(tile); int idx = AllocLink(tile);
@ -802,7 +798,7 @@ namespace DotRecast.Detour
// Connect off-mesh links. // Connect off-mesh links.
// We are interested on links which land from target tile to this tile. // We are interested on links which land from target tile to this tile.
int oppositeSide = (side == -1) ? 0xff : OppositeTile(side); int oppositeSide = (side == -1) ? 0xff : DetourCommon.OppositeTile(side);
for (int i = 0; i < target.data.header.offMeshConCount; ++i) for (int i = 0; i < target.data.header.offMeshConCount; ++i)
{ {
@ -871,7 +867,7 @@ namespace DotRecast.Detour
int landPolyIdx = DecodePolyIdPoly(refs); int landPolyIdx = DecodePolyIdPoly(refs);
Poly landPoly = tile.data.polys[landPolyIdx]; Poly landPoly = tile.data.polys[landPolyIdx];
link = tile.links[tidx]; link = tile.links[tidx];
link.refs = GetPolyRefBase(target) | (targetCon.poly); link.refs = GetPolyRefBase(target) | (long)targetCon.poly;
link.edge = 0xff; link.edge = 0xff;
link.side = (side == -1 ? 0xff : side); link.side = (side == -1 ? 0xff : side);
link.bmin = link.bmax = 0; link.bmin = link.bmax = 0;
@ -931,7 +927,7 @@ namespace DotRecast.Detour
} }
// Add return value. // Add return value.
long refs = @base | i; long refs = @base | (long)i;
float tmin = Math.Max(amin.x, bmin.x); float tmin = Math.Max(amin.x, bmin.x);
float tmax = Math.Min(amax.x, bmax.x); float tmax = Math.Min(amax.x, bmax.x);
result.Add(Tuple.Create(refs, tmin, tmax)); result.Add(Tuple.Create(refs, tmin, tmax));
@ -1099,7 +1095,7 @@ namespace DotRecast.Detour
int landPolyIdx = DecodePolyIdPoly(refs); int landPolyIdx = DecodePolyIdPoly(refs);
Poly landPoly = tile.data.polys[landPolyIdx]; Poly landPoly = tile.data.polys[landPolyIdx];
link = tile.links[tidx]; link = tile.links[tidx];
link.refs = @base | (con.poly); link.refs = @base | (long)con.poly;
link.edge = 0xff; link.edge = 0xff;
link.side = 0xff; link.side = 0xff;
link.bmin = link.bmax = 0; link.bmin = link.bmax = 0;
@ -1173,7 +1169,7 @@ namespace DotRecast.Detour
continue; continue;
} }
var d = DistancePtSegSqr2D(pos, v[j], v[k], out var t); var d = DetourCommon.DistancePtSegSqr2D(pos, v[j], v[k], out var t);
if (d < dmin) if (d < dmin)
{ {
dmin = d; dmin = d;
@ -1197,7 +1193,7 @@ namespace DotRecast.Detour
v[1].y = tile.data.verts[poly.verts[k] * 3 + 1]; v[1].y = tile.data.verts[poly.verts[k] * 3 + 1];
v[1].z = tile.data.verts[poly.verts[k] * 3 + 2]; v[1].z = tile.data.verts[poly.verts[k] * 3 + 2];
var d = DistancePtSegSqr2D(pos, v[0], v[1], out var t); var d = DetourCommon.DistancePtSegSqr2D(pos, v[0], v[1], out var t);
if (d < dmin) if (d < dmin)
{ {
dmin = d; dmin = d;
@ -1229,7 +1225,7 @@ namespace DotRecast.Detour
Array.Copy(tile.data.verts, poly.verts[i] * 3, verts, i * 3, 3); Array.Copy(tile.data.verts, poly.verts[i] * 3, verts, i * 3, 3);
} }
if (!PointInPolygon(pos, verts, nv)) if (!DetourCommon.PointInPolygon(pos, verts, nv))
{ {
return null; return null;
} }
@ -1266,7 +1262,7 @@ namespace DotRecast.Detour
} }
} }
float? h = ClosestHeightPointTriangle(pos, v[0], v[1], v[2]); float? h = DetourCommon.ClosestHeightPointTriangle(pos, v[0], v[1], v[2]);
if (null != h) if (null != h)
{ {
return h; return h;
@ -1288,7 +1284,7 @@ namespace DotRecast.Detour
v[k + 1].z = tile.data.verts[poly.verts[j + k] * 3 + 2]; v[k + 1].z = tile.data.verts[poly.verts[j + k] * 3 + 2];
} }
float? h = ClosestHeightPointTriangle(pos, v[0], v[1], v[2]); float? h = DetourCommon.ClosestHeightPointTriangle(pos, v[0], v[1], v[2]);
if (null != h) if (null != h)
{ {
return h; return h;
@ -1325,7 +1321,7 @@ namespace DotRecast.Detour
var v0 = new Vector3f { x = tile.data.verts[i], y = tile.data.verts[i + 1], z = tile.data.verts[i + 2] }; var v0 = new Vector3f { x = tile.data.verts[i], y = tile.data.verts[i + 1], z = tile.data.verts[i + 2] };
i = poly.verts[1] * 3; i = poly.verts[1] * 3;
var v1 = new Vector3f { x = tile.data.verts[i], y = tile.data.verts[i + 1], z = tile.data.verts[i + 2] }; var v1 = new Vector3f { x = tile.data.verts[i], y = tile.data.verts[i + 1], z = tile.data.verts[i + 2] };
var distSqr = DistancePtSegSqr2D(pos, v0, v1, out var t); var distSqr = DetourCommon.DistancePtSegSqr2D(pos, v0, v1, out var t);
return new ClosestPointOnPolyResult(false, Vector3f.Lerp(v0, v1, t)); return new ClosestPointOnPolyResult(false, Vector3f.Lerp(v0, v1, t));
} }

View File

@ -131,7 +131,7 @@ namespace DotRecast.Detour
} }
// Must pass filter // Must pass filter
long refs = @base | i; long refs = @base | (long)i;
if (!filter.PassFilter(refs, tile, p)) if (!filter.PassFilter(refs, tile, p))
{ {
continue; continue;
@ -144,7 +144,7 @@ namespace DotRecast.Detour
int va = p.verts[0] * 3; int va = p.verts[0] * 3;
int vb = p.verts[j - 1] * 3; int vb = p.verts[j - 1] * 3;
int vc = p.verts[j] * 3; int vc = p.verts[j] * 3;
polyArea += TriArea2D(tile.data.verts, va, vb, vc); polyArea += DetourCommon.TriArea2D(tile.data.verts, va, vb, vc);
} }
// Choose random polygon weighted by area, using reservoi sampling. // Choose random polygon weighted by area, using reservoi sampling.
@ -174,7 +174,7 @@ namespace DotRecast.Detour
float s = frand.Next(); float s = frand.Next();
float t = frand.Next(); float t = frand.Next();
var pt = RandomPointInConvexPoly(verts, poly.vertCount, areas, s, t); var pt = DetourCommon.RandomPointInConvexPoly(verts, poly.vertCount, areas, s, t);
ClosestPointOnPolyResult closest = ClosestPointOnPoly(polyRef, pt).result; ClosestPointOnPolyResult closest = ClosestPointOnPoly(polyRef, pt).result;
return Results.Success(new FindRandomPointResult(polyRef, closest.GetClosest())); return Results.Success(new FindRandomPointResult(polyRef, closest.GetClosest()));
} }
@ -291,7 +291,7 @@ namespace DotRecast.Detour
int va = 0; int va = 0;
int vb = (j - 1) * 3; int vb = (j - 1) * 3;
int vc = j * 3; int vc = j * 3;
polyArea += TriArea2D(constrainedVerts, va, vb, vc); polyArea += DetourCommon.TriArea2D(constrainedVerts, va, vb, vc);
} }
// Choose random polygon weighted by area, using reservoi sampling. // Choose random polygon weighted by area, using reservoi sampling.
@ -346,7 +346,7 @@ namespace DotRecast.Detour
var vb = portalpoints.result.right; var vb = portalpoints.result.right;
// If the circle is not touching the next polygon, skip it. // If the circle is not touching the next polygon, skip it.
var distSqr = DistancePtSegSqr2D(centerPos, va, vb, out var tesg); var distSqr = DetourCommon.DistancePtSegSqr2D(centerPos, va, vb, out var tesg);
if (distSqr > radiusSqr) if (distSqr > radiusSqr)
{ {
continue; continue;
@ -400,7 +400,7 @@ namespace DotRecast.Detour
float t = frand.Next(); float t = frand.Next();
float[] areas = new float[randomPolyVerts.Length / 3]; float[] areas = new float[randomPolyVerts.Length / 3];
Vector3f pt = RandomPointInConvexPoly(randomPolyVerts, randomPolyVerts.Length / 3, areas, s, t); Vector3f pt = DetourCommon.RandomPointInConvexPoly(randomPolyVerts, randomPolyVerts.Length / 3, areas, s, t);
ClosestPointOnPolyResult closest = ClosestPointOnPoly(randomPolyRef, pt).result; ClosestPointOnPolyResult closest = ClosestPointOnPoly(randomPolyRef, pt).result;
return Results.Success(new FindRandomPointResult(randomPolyRef, closest.GetClosest())); return Results.Success(new FindRandomPointResult(randomPolyRef, closest.GetClosest()));
} }
@ -478,7 +478,7 @@ namespace DotRecast.Detour
} }
Vector3f closest; Vector3f closest;
if (DistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) if (DetourCommon.DistancePtPolyEdgesSqr(pos, verts, nv, edged, edget))
{ {
closest = pos; closest = pos;
} }
@ -539,7 +539,7 @@ namespace DotRecast.Detour
var v0 = new Vector3f { x = tile.data.verts[i], y = tile.data.verts[i + 1], z = tile.data.verts[i + 2] }; var v0 = new Vector3f { x = tile.data.verts[i], y = tile.data.verts[i + 1], z = tile.data.verts[i + 2] };
i = poly.verts[1] * 3; i = poly.verts[1] * 3;
var v1 = new Vector3f { x = tile.data.verts[i], y = tile.data.verts[i + 1], z = tile.data.verts[i + 2] }; var v1 = new Vector3f { x = tile.data.verts[i], y = tile.data.verts[i + 1], z = tile.data.verts[i + 2] };
var distSqr = DistancePtSegSqr2D(pos, v0, v1, out var tseg); var distSqr = DetourCommon.DistancePtSegSqr2D(pos, v0, v1, out var tseg);
return Results.Success(v0.y + (v1.y - v0.y) * tseg); return Results.Success(v0.y + (v1.y - v0.y) * tseg);
} }
@ -605,12 +605,12 @@ namespace DotRecast.Detour
while (nodeIndex < end) while (nodeIndex < end)
{ {
BVNode node = tile.data.bvTree[nodeIndex]; BVNode node = tile.data.bvTree[nodeIndex];
bool overlap = OverlapQuantBounds(bmin, bmax, node.bmin, node.bmax); bool overlap = DetourCommon.OverlapQuantBounds(bmin, bmax, node.bmin, node.bmax);
bool isLeafNode = node.i >= 0; bool isLeafNode = node.i >= 0;
if (isLeafNode && overlap) if (isLeafNode && overlap)
{ {
long refs = @base | node.i; long refs = @base | (long)node.i;
if (filter.PassFilter(refs, tile, tile.data.polys[node.i])) if (filter.PassFilter(refs, tile, tile.data.polys[node.i]))
{ {
query.Process(tile, tile.data.polys[node.i], refs); query.Process(tile, tile.data.polys[node.i], refs);
@ -642,7 +642,7 @@ namespace DotRecast.Detour
continue; continue;
} }
long refs = @base | i; long refs = @base | (long)i;
if (!filter.PassFilter(refs, tile, p)) if (!filter.PassFilter(refs, tile, p))
{ {
continue; continue;
@ -659,7 +659,7 @@ namespace DotRecast.Detour
bmax.Max(tile.data.verts, v); bmax.Max(tile.data.verts, v);
} }
if (OverlapBounds(qmin, qmax, bmin, bmax)) if (DetourCommon.OverlapBounds(qmin, qmax, bmin, bmax))
{ {
query.Process(tile, p, refs); query.Process(tile, p, refs);
} }
@ -712,7 +712,7 @@ namespace DotRecast.Detour
Vector3f bmax = center.Add(halfExtents); Vector3f bmax = center.Add(halfExtents);
m_nav.CalcTileLoc(bmin, out var minx, out var miny); m_nav.CalcTileLoc(bmin, out var minx, out var miny);
m_nav.CalcTileLoc(bmax, out var maxx, out var maxy); m_nav.CalcTileLoc(bmax, out var maxx, out var maxy);
List<MeshTile> tiles = new List<MeshTile>(); List<MeshTile> tiles = new List<MeshTile>();
for (int y = miny; y <= maxy; ++y) for (int y = miny; y <= maxy; ++y)
{ {
@ -1424,7 +1424,7 @@ namespace DotRecast.Detour
protected Status AppendVertex(Vector3f pos, int flags, long refs, List<StraightPathItem> straightPath, protected Status AppendVertex(Vector3f pos, int flags, long refs, List<StraightPathItem> straightPath,
int maxStraightPath) int maxStraightPath)
{ {
if (straightPath.Count > 0 && VEqual(straightPath[straightPath.Count - 1].pos, pos)) if (straightPath.Count > 0 && DetourCommon.VEqual(straightPath[straightPath.Count - 1].pos, pos))
{ {
// The vertices are equal, update flags and poly. // The vertices are equal, update flags and poly.
straightPath[straightPath.Count - 1].flags = flags; straightPath[straightPath.Count - 1].flags = flags;
@ -1496,7 +1496,7 @@ namespace DotRecast.Detour
} }
// Append intersection // Append intersection
if (IntersectSegSeg2D(startPos, endPos, left, right, out var _, out var t)) if (DetourCommon.IntersectSegSeg2D(startPos, endPos, left, right, out var _, out var t))
{ {
var pt = Vector3f.Lerp(left, right, t); var pt = Vector3f.Lerp(left, right, t);
stat = AppendVertex(pt, 0, path[i + 1], straightPath, maxStraightPath); stat = AppendVertex(pt, 0, path[i + 1], straightPath, maxStraightPath);
@ -1620,7 +1620,7 @@ namespace DotRecast.Detour
// If starting really close the portal, advance. // If starting really close the portal, advance.
if (i == 0) if (i == 0)
{ {
var distSqr = DistancePtSegSqr2D(portalApex, left, right, out var t); var distSqr = DetourCommon.DistancePtSegSqr2D(portalApex, left, right, out var t);
if (distSqr < Sqr(0.001f)) if (distSqr < Sqr(0.001f))
{ {
continue; continue;
@ -1636,9 +1636,9 @@ namespace DotRecast.Detour
} }
// Right vertex. // Right vertex.
if (TriArea2D(portalApex, portalRight, right) <= 0.0f) if (DetourCommon.TriArea2D(portalApex, portalRight, right) <= 0.0f)
{ {
if (VEqual(portalApex, portalRight) || TriArea2D(portalApex, portalLeft, right) > 0.0f) if (DetourCommon.VEqual(portalApex, portalRight) || DetourCommon.TriArea2D(portalApex, portalLeft, right) > 0.0f)
{ {
portalRight = right; portalRight = right;
rightPolyRef = (i + 1 < path.Count) ? path[i + 1] : 0; rightPolyRef = (i + 1 < path.Count) ? path[i + 1] : 0;
@ -1693,9 +1693,9 @@ namespace DotRecast.Detour
} }
// Left vertex. // Left vertex.
if (TriArea2D(portalApex, portalLeft, left) >= 0.0f) if (DetourCommon.TriArea2D(portalApex, portalLeft, left) >= 0.0f)
{ {
if (VEqual(portalApex, portalLeft) || TriArea2D(portalApex, portalRight, left) < 0.0f) if (DetourCommon.VEqual(portalApex, portalLeft) || DetourCommon.TriArea2D(portalApex, portalRight, left) < 0.0f)
{ {
portalLeft = left; portalLeft = left;
leftPolyRef = (i + 1 < path.Count) ? path[i + 1] : 0; leftPolyRef = (i + 1 < path.Count) ? path[i + 1] : 0;
@ -1845,7 +1845,7 @@ namespace DotRecast.Detour
} }
// If target is inside the poly, stop search. // If target is inside the poly, stop search.
if (PointInPolygon(endPos, verts, nverts)) if (DetourCommon.PointInPolygon(endPos, verts, nverts))
{ {
bestNode = curNode; bestNode = curNode;
bestPos = endPos; bestPos = endPos;
@ -1887,7 +1887,7 @@ namespace DotRecast.Detour
else if (curPoly.neis[j] != 0) else if (curPoly.neis[j] != 0)
{ {
int idx = curPoly.neis[j] - 1; int idx = curPoly.neis[j] - 1;
long refs = m_nav.GetPolyRefBase(curTile) | idx; long refs = m_nav.GetPolyRefBase(curTile) | (long)idx;
if (filter.PassFilter(refs, curTile, curTile.data.polys[idx])) if (filter.PassFilter(refs, curTile, curTile.data.polys[idx]))
{ {
// Internal edge, encode id. // Internal edge, encode id.
@ -1900,7 +1900,7 @@ namespace DotRecast.Detour
// Wall edge, calc distance. // Wall edge, calc distance.
int vj = j * 3; int vj = j * 3;
int vi = i * 3; int vi = i * 3;
var distSqr = DistancePtSegSqr2D(endPos, verts, vj, vi, out var tseg); var distSqr = DetourCommon.DistancePtSegSqr2D(endPos, verts, vj, vi, out var tseg);
if (distSqr < bestDist) if (distSqr < bestDist)
{ {
// Update nearest distance. // Update nearest distance.
@ -1924,7 +1924,7 @@ namespace DotRecast.Detour
// TODO: Maybe should use GetPortalPoints(), but this one is way faster. // TODO: Maybe should use GetPortalPoints(), but this one is way faster.
int vj = j * 3; int vj = j * 3;
int vi = i * 3; int vi = i * 3;
var distSqr = DistancePtSegSqr2D(searchPos, verts, vj, vi, out var _); var distSqr = DetourCommon.DistancePtSegSqr2D(searchPos, verts, vj, vi, out var _);
if (distSqr > searchRadSqr) if (distSqr > searchRadSqr)
{ {
continue; continue;
@ -2118,7 +2118,7 @@ namespace DotRecast.Detour
Vector3f left = ppoints.result.left; Vector3f left = ppoints.result.left;
Vector3f right = ppoints.result.right; Vector3f right = ppoints.result.right;
float t = 0.5f; float t = 0.5f;
if (IntersectSegSeg2D(fromPos, toPos, left, right, out var _, out var t2)) if (DetourCommon.IntersectSegSeg2D(fromPos, toPos, left, right, out var _, out var t2))
{ {
t = Clamp(t2, 0.1f, 0.9f); t = Clamp(t2, 0.1f, 0.9f);
} }
@ -2230,7 +2230,7 @@ namespace DotRecast.Detour
nv++; nv++;
} }
IntersectResult iresult = IntersectSegmentPoly2D(startPos, endPos, verts, nv); IntersectResult iresult = DetourCommon.IntersectSegmentPoly2D(startPos, endPos, verts, nv);
if (!iresult.intersects) if (!iresult.intersects)
{ {
// Could not hit the polygon, keep the old t and report hit. // Could not hit the polygon, keep the old t and report hit.
@ -2543,7 +2543,7 @@ namespace DotRecast.Detour
var vb = pp.result.right; var vb = pp.result.right;
// If the circle is not touching the next polygon, skip it. // If the circle is not touching the next polygon, skip it.
var distSqr = DistancePtSegSqr2D(centerPos, va, vb, out var _); var distSqr = DetourCommon.DistancePtSegSqr2D(centerPos, va, vb, out var _);
if (distSqr > radiusSqr) if (distSqr > radiusSqr)
{ {
continue; continue;
@ -2730,7 +2730,7 @@ namespace DotRecast.Detour
var vb = pp.result.right; var vb = pp.result.right;
// If the poly is not touching the edge to the next polygon, skip the connection it. // If the poly is not touching the edge to the next polygon, skip the connection it.
IntersectResult ir = IntersectSegmentPoly2D(va, vb, verts, nverts); IntersectResult ir = DetourCommon.IntersectSegmentPoly2D(va, vb, verts, nverts);
if (!ir.intersects) if (!ir.intersects)
{ {
continue; continue;
@ -2906,7 +2906,7 @@ namespace DotRecast.Detour
var vb = pp.result.right; var vb = pp.result.right;
// If the circle is not touching the next polygon, skip it. // If the circle is not touching the next polygon, skip it.
var distSqr = DistancePtSegSqr2D(centerPos, va, vb, out var _); var distSqr = DetourCommon.DistancePtSegSqr2D(centerPos, va, vb, out var _);
if (distSqr > radiusSqr) if (distSqr > radiusSqr)
{ {
continue; continue;
@ -2959,7 +2959,7 @@ namespace DotRecast.Detour
Array.Copy(pastTile.data.verts, pastPoly.verts[k] * 3, pb, k * 3, 3); Array.Copy(pastTile.data.verts, pastPoly.verts[k] * 3, pb, k * 3, 3);
} }
if (OverlapPolyPoly2D(pa, npa, pb, npb)) if (DetourCommon.OverlapPolyPoly2D(pa, npa, pb, npb))
{ {
overlap = true; overlap = true;
break; break;
@ -3071,7 +3071,7 @@ namespace DotRecast.Detour
if (poly.neis[j] != 0) if (poly.neis[j] != 0)
{ {
int idx = (poly.neis[j] - 1); int idx = (poly.neis[j] - 1);
neiRef = m_nav.GetPolyRefBase(tile) | idx; neiRef = m_nav.GetPolyRefBase(tile) | (long)idx;
if (!filter.PassFilter(neiRef, tile, tile.data.polys[idx])) if (!filter.PassFilter(neiRef, tile, tile.data.polys[idx]))
{ {
neiRef = 0; neiRef = 0;
@ -3239,7 +3239,7 @@ namespace DotRecast.Detour
{ {
// Internal edge // Internal edge
int idx = (bestPoly.neis[j] - 1); int idx = (bestPoly.neis[j] - 1);
long refs = m_nav.GetPolyRefBase(bestTile) | idx; long refs = m_nav.GetPolyRefBase(bestTile) | (long)idx;
if (filter.PassFilter(refs, bestTile, bestTile.data.polys[idx])) if (filter.PassFilter(refs, bestTile, bestTile.data.polys[idx]))
{ {
continue; continue;
@ -3249,7 +3249,7 @@ namespace DotRecast.Detour
// Calc distance to the edge. // Calc distance to the edge.
int vj = bestPoly.verts[j] * 3; int vj = bestPoly.verts[j] * 3;
int vi = bestPoly.verts[i] * 3; int vi = bestPoly.verts[i] * 3;
var distSqr = DistancePtSegSqr2D(centerPos, bestTile.data.verts, vj, vi, out var tseg); var distSqr = DetourCommon.DistancePtSegSqr2D(centerPos, bestTile.data.verts, vj, vi, out var tseg);
// Edge is too far, skip. // Edge is too far, skip.
if (distSqr > radiusSqr) if (distSqr > radiusSqr)
@ -3293,7 +3293,7 @@ namespace DotRecast.Detour
// Calc distance to the edge. // Calc distance to the edge.
int va = bestPoly.verts[link.edge] * 3; int va = bestPoly.verts[link.edge] * 3;
int vb = bestPoly.verts[(link.edge + 1) % bestPoly.vertCount] * 3; int vb = bestPoly.verts[(link.edge + 1) % bestPoly.vertCount] * 3;
var distSqr = DistancePtSegSqr2D(centerPos, bestTile.data.verts, va, vb, out var tseg); var distSqr = DetourCommon.DistancePtSegSqr2D(centerPos, bestTile.data.verts, va, vb, out var tseg);
// If the circle is not touching the next polygon, skip it. // If the circle is not touching the next polygon, skip it.
if (distSqr > radiusSqr) if (distSqr > radiusSqr)
{ {

View File

@ -34,7 +34,7 @@ namespace DotRecast.Detour
float[] qCircle = Circle(center, radius); float[] qCircle = Circle(center, radius);
float[] intersection = ConvexConvexIntersection.Intersect(verts, qCircle); float[] intersection = ConvexConvexIntersection.Intersect(verts, qCircle);
if (intersection == null && PointInPolygon(center, verts, verts.Length / 3)) if (intersection == null && DetourCommon.PointInPolygon(center, verts, verts.Length / 3))
{ {
// circle inside polygon // circle inside polygon
return qCircle; return qCircle;

View File

@ -100,7 +100,7 @@ public class TileNavMeshBuilder : AbstractNavMeshBuilder
Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh); Recast.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(Ilog2(NextPow2(tw * th)), 14); int tileBits = Math.Min(DetourCommon.Ilog2(DetourCommon.NextPow2(tw * th)), 14);
return tileBits; return tileBits;
} }

View File

@ -394,7 +394,7 @@ public class DebugDraw
void AppendArrowHead(Vector3f p, Vector3f q, float s, int col) void AppendArrowHead(Vector3f p, Vector3f q, float s, int col)
{ {
float eps = 0.001f; const float eps = 0.001f;
if (VdistSqr(p, q) < eps * eps) if (VdistSqr(p, q) < eps * eps)
{ {
return; return;

View File

@ -291,8 +291,7 @@ public class NavMeshRenderer
debugDraw.Begin(DebugDrawPrimitives.POINTS, 3.0f); debugDraw.Begin(DebugDrawPrimitives.POINTS, 3.0f);
foreach (ConvexVolume vol in geom.ConvexVolumes()) foreach (ConvexVolume vol in geom.ConvexVolumes())
{ {
int col = DebugDraw int col = DebugDraw.DuDarkenCol(DebugDraw.DuTransCol(DebugDraw.AreaToCol(vol.areaMod.GetMaskedValue()), 220));
.DuDarkenCol(DebugDraw.DuTransCol(DebugDraw.AreaToCol(vol.areaMod.GetMaskedValue()), 220));
for (int j = 0; j < vol.verts.Length; j += 3) for (int j = 0; j < vol.verts.Length; j += 3)
{ {
debugDraw.Vertex(vol.verts[j + 0], vol.verts[j + 1] + 0.1f, vol.verts[j + 2], col); debugDraw.Vertex(vol.verts[j + 0], vol.verts[j + 1] + 0.1f, vol.verts[j + 2], col);

View File

@ -132,7 +132,7 @@ public class RecastDebugDraw : DebugDraw
} }
int col; int col;
if (query != null && query.IsInClosedList(@base | i)) if (query != null && query.IsInClosedList(@base | (long)i))
{ {
col = DuRGBA(255, 196, 0, 64); col = DuRGBA(255, 196, 0, 64);
} }
@ -179,7 +179,7 @@ public class RecastDebugDraw : DebugDraw
} }
int col, col2; int col, col2;
if (query != null && query.IsInClosedList(@base | i)) if (query != null && query.IsInClosedList(@base | (long)i))
{ {
col = DuRGBA(255, 196, 0, 220); col = DuRGBA(255, 196, 0, 220);
} }
@ -1269,7 +1269,7 @@ public class RecastDebugDraw : DebugDraw
continue; continue;
} }
DebugDrawNavMeshPoly(mesh, @base | j, col); DebugDrawNavMeshPoly(mesh, @base | (long)j, col);
} }
} }
} }

View File

@ -77,8 +77,8 @@ public class DemoInputGeomProvider : IInputGeomProvider
Vector3f.Copy(ref bmax, vertices, 0); Vector3f.Copy(ref bmax, vertices, 0);
for (int i = 1; i < vertices.Length / 3; i++) for (int i = 1; i < vertices.Length / 3; i++)
{ {
bmin.Min(vertices, i * 3); bmin.Min(vertices, i * 3);
bmax.Max(vertices, i * 3); bmax.Max(vertices, i * 3);
} }
_mesh = new TriMesh(vertices, faces); _mesh = new TriMesh(vertices, faces);
@ -152,15 +152,13 @@ public class DemoInputGeomProvider : IInputGeomProvider
public float? RaycastMesh(Vector3f src, Vector3f dst) public float? RaycastMesh(Vector3f src, Vector3f dst)
{ {
// Prune hit ray. // Prune hit ray.
float[] btminmax = Intersections.IntersectSegmentAABB(src, dst, bmin, bmax); if (!Intersections.IsectSegAABB(src, dst, bmin, bmax, out var btmin, out var btmax))
if (null == btminmax)
{ {
return null; return null;
} }
float btmin = btminmax[0]; float[] p = new float[2];
float btmax = btminmax[1]; float[] q = new float[2];
float[] p = new float[2], q = new float[2];
p[0] = src.x + (dst.x - src.x) * btmin; p[0] = src.x + (dst.x - src.x) * btmin;
p[1] = src.z + (dst.z - src.z) * btmin; p[1] = src.z + (dst.z - src.z) * btmin;
q[0] = src.x + (dst.x - src.x) * btmax; q[0] = src.x + (dst.x - src.x) * btmax;
@ -185,12 +183,12 @@ public class DemoInputGeomProvider : IInputGeomProvider
vertices[tris[j] * 3 + 2] vertices[tris[j] * 3 + 2]
); );
Vector3f v2 = Vector3f.Of( Vector3f v2 = Vector3f.Of(
vertices[tris[j + 1] * 3], vertices[tris[j + 1] * 3],
vertices[tris[j + 1] * 3 + 1], vertices[tris[j + 1] * 3 + 1],
vertices[tris[j + 1] * 3 + 2] vertices[tris[j + 1] * 3 + 2]
); );
Vector3f v3 = Vector3f.Of( Vector3f v3 = Vector3f.Of(
vertices[tris[j + 2] * 3], vertices[tris[j + 2] * 3],
vertices[tris[j + 2] * 3 + 1], vertices[tris[j + 2] * 3 + 1],
vertices[tris[j + 2] * 3 + 2] vertices[tris[j + 2] * 3 + 2]
); );
@ -225,4 +223,4 @@ public class DemoInputGeomProvider : IInputGeomProvider
{ {
_convexVolumes.Clear(); _convexVolumes.Clear();
} }
} }

View File

@ -236,10 +236,8 @@ public class CrowdTool : Tool
Vector3f bmin = new Vector3f(); Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f(); Vector3f bmax = new Vector3f();
GetAgentBounds(ag, ref bmin, ref bmax); GetAgentBounds(ag, ref bmin, ref bmax);
float[] isect = Intersections.IntersectSegmentAABB(s, p, bmin, bmax); if (Intersections.IsectSegAABB(s, p, bmin, bmax, out var tmin, out var tmax))
if (null != isect)
{ {
float tmin = isect[0];
if (tmin > 0 && tmin < tsel) if (tmin > 0 && tmin < tsel)
{ {
isel = ag; isel = ag;
@ -486,7 +484,7 @@ public class CrowdTool : Tool
Vector3f[] s = ag.boundary.GetSegment(j); Vector3f[] s = ag.boundary.GetSegment(j);
Vector3f s0 = s[0]; Vector3f s0 = s[0];
Vector3f s3 = s[1]; Vector3f s3 = s[1];
if (TriArea2D(pos, s0, s3) < 0.0f) if (DetourCommon.TriArea2D(pos, s0, s3) < 0.0f)
col = DuDarkenCol(col); col = DuDarkenCol(col);
dd.AppendArrow(s[0].x, s[0].y + 0.2f, s[0].z, s[1].x, s[1].z + 0.2f, s[1].z, 0.0f, 0.3f, col); dd.AppendArrow(s[0].x, s[0].y + 0.2f, s[0].z, s[1].x, s[1].z + 0.2f, s[1].z, 0.0f, 0.3f, col);

View File

@ -850,7 +850,7 @@ public class TestNavmeshTool : Tool
var v0 = Vector3f.Of(s[0], s[1], s[2]); var v0 = Vector3f.Of(s[0], s[1], s[2]);
var s3 = Vector3f.Of(s[3], s[4], s[5]); var s3 = Vector3f.Of(s[3], s[4], s[5]);
// Skip too distant segments. // Skip too distant segments.
var distSqr = DistancePtSegSqr2D(m_spos, v0, s3, out var tseg); var distSqr = DetourCommon.DistancePtSegSqr2D(m_spos, v0, s3, out var tseg);
if (distSqr > RcMath.Sqr(m_neighbourhoodRadius)) if (distSqr > RcMath.Sqr(m_neighbourhoodRadius))
{ {
continue; continue;
@ -871,7 +871,7 @@ public class TestNavmeshTool : Tool
else else
{ {
int col = DuRGBA(192, 32, 16, 192); int col = DuRGBA(192, 32, 16, 192);
if (TriArea2D(m_spos, s.vmin, s3) < 0.0f) if (DetourCommon.TriArea2D(m_spos, s.vmin, s3) < 0.0f)
{ {
col = DuRGBA(96, 32, 16, 192); col = DuRGBA(96, 32, 16, 192);
} }

View File

@ -156,7 +156,7 @@ namespace DotRecast.Recast
private static bool CircumCircle(float[] verts, int p1, int p2, int p3, ref Vector3f c, RcAtomicFloat r) private static bool CircumCircle(float[] verts, int p1, int p2, int p3, ref Vector3f c, RcAtomicFloat r)
{ {
float EPS = 1e-6f; const float EPS = 1e-6f;
// Calculate the circle relative to p1, to avoid some precision issues. // Calculate the circle relative to p1, to avoid some precision issues.
Vector3f v1 = new Vector3f(); Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f(); Vector3f v2 = new Vector3f();
@ -204,7 +204,7 @@ namespace DotRecast.Recast
float v = (dot00 * dot12 - dot01 * dot02) * invDenom; float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
// If point lies inside the triangle, return interpolated y-coord. // If point lies inside the triangle, return interpolated y-coord.
float EPS = 1e-4f; const float EPS = 1e-4f;
if (u >= -EPS && v >= -EPS && (u + v) <= 1 + EPS) if (u >= -EPS && v >= -EPS && (u + v) <= 1 + EPS)
{ {
float y = verts[a + 1] + v0.y * u + v1.y * v; float y = verts[a + 1] + v0.y * u + v1.y * v;
@ -512,7 +512,7 @@ namespace DotRecast.Recast
static int CompleteFacet(Telemetry ctx, float[] pts, int npts, List<int> edges, int maxEdges, int nfaces, int e) static int CompleteFacet(Telemetry ctx, float[] pts, int npts, List<int> edges, int maxEdges, int nfaces, int e)
{ {
float EPS = 1e-5f; const float EPS = 1e-5f;
int edge = e * 4; int edge = e * 4;