C# style function name

This commit is contained in:
ikpil 2023-05-05 08:44:48 +09:00
parent bef429e5dc
commit ded8f33ac1
229 changed files with 5832 additions and 5830 deletions

View File

@ -6,12 +6,12 @@ namespace DotRecast.Core
{
private volatile int _location;
public bool set(bool v)
public bool Set(bool v)
{
return 0 != Interlocked.Exchange(ref _location, v ? 1 : 0);
}
public bool get()
public bool Get()
{
return 0 != _location;
}

View File

@ -19,34 +19,34 @@ namespace DotRecast.Core
_position = 0;
}
public ByteOrder order()
public ByteOrder Order()
{
return _order;
}
public void order(ByteOrder order)
public void Order(ByteOrder order)
{
_order = order;
}
public int limit()
public int Limit()
{
return _bytes.Length - _position;
}
public int remaining()
public int Remaining()
{
int rem = limit();
int rem = Limit();
return rem > 0 ? rem : 0;
}
public void position(int pos)
public void Position(int pos)
{
_position = pos;
}
public int position()
public int Position()
{
return _position;
}
@ -59,13 +59,13 @@ namespace DotRecast.Core
return _bytes.AsSpan(nextPos, length);
}
public byte get()
public byte Get()
{
var span = ReadBytes(1);
return span[0];
}
public short getShort()
public short GetShort()
{
var span = ReadBytes(2);
if (_order == ByteOrder.BIG_ENDIAN)
@ -79,7 +79,7 @@ namespace DotRecast.Core
}
public int getInt()
public int GetInt()
{
var span = ReadBytes(4);
if (_order == ByteOrder.BIG_ENDIAN)
@ -92,7 +92,7 @@ namespace DotRecast.Core
}
}
public float getFloat()
public float GetFloat()
{
var span = ReadBytes(4);
if (_order == ByteOrder.BIG_ENDIAN && BitConverter.IsLittleEndian)
@ -107,7 +107,7 @@ namespace DotRecast.Core
return BitConverter.ToSingle(span);
}
public long getLong()
public long GetLong()
{
var span = ReadBytes(8);
if (_order == ByteOrder.BIG_ENDIAN)
@ -120,7 +120,7 @@ namespace DotRecast.Core
}
}
public void putFloat(float v)
public void PutFloat(float v)
{
// if (_order == ByteOrder.BIG_ENDIAN)
// {
@ -134,7 +134,7 @@ namespace DotRecast.Core
// ?
}
public void putInt(int v)
public void PutInt(int v)
{
// ?
}

View File

@ -5,7 +5,7 @@ namespace DotRecast.Core
{
public static class CollectionExtensions
{
public static void forEach<T>(this IEnumerable<T> collection, Action<T> action)
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach (var item in collection)
{

View File

@ -25,7 +25,7 @@ namespace DotRecast.Core
// Calculates convex hull on xz-plane of points on 'pts',
// stores the indices of the resulting hull in 'out' and
// returns number of points on hull.
public static List<int> convexhull(List<float> pts)
public static List<int> Convexhull(List<float> pts)
{
int npts = pts.Count / 3;
List<int> @out = new List<int>();
@ -35,7 +35,7 @@ namespace DotRecast.Core
{
Vector3f a = Vector3f.Of(pts[i * 3], pts[i * 3 + 1], pts[i * 3 + 2]);
Vector3f b = Vector3f.Of(pts[hull * 3], pts[hull * 3 + 1], pts[hull * 3 + 2]);
if (cmppt(a, b))
if (Cmppt(a, b))
{
hull = i;
}
@ -52,7 +52,7 @@ namespace DotRecast.Core
Vector3f a = Vector3f.Of(pts[hull * 3], pts[hull * 3 + 1], pts[hull * 3 + 2]);
Vector3f b = Vector3f.Of(pts[endpt * 3], pts[endpt * 3 + 1], pts[endpt * 3 + 2]);
Vector3f c = Vector3f.Of(pts[j * 3], pts[j * 3 + 1], pts[j * 3 + 2]);
if (hull == endpt || left(a, b, c))
if (hull == endpt || Left(a, b, c))
{
endpt = j;
}
@ -65,7 +65,7 @@ namespace DotRecast.Core
}
// Returns true if 'a' is more lower-left than 'b'.
private static bool cmppt(Vector3f a, Vector3f b)
private static bool Cmppt(Vector3f a, Vector3f b)
{
if (a.x < b.x)
{
@ -91,7 +91,7 @@ namespace DotRecast.Core
}
// Returns true if 'c' is left of line 'a'-'b'.
private static bool left(Vector3f a, Vector3f b, Vector3f c)
private static bool Left(Vector3f a, Vector3f b, Vector3f c)
{
float u1 = b.x - a.x;
float v1 = b.z - a.z;

View File

@ -16,7 +16,7 @@ namespace DotRecast.Core
r = new Random((int)seed); // TODO : 랜덤 시드 확인 필요
}
public float frand()
public float Frand()
{
return (float)r.NextDouble();
}

View File

@ -24,20 +24,20 @@ namespace DotRecast.Core
{
public static class Intersections
{
public static float? intersectSegmentTriangle(Vector3f sp, Vector3f sq, Vector3f a, Vector3f b, Vector3f c)
public static float? IntersectSegmentTriangle(Vector3f sp, Vector3f sq, Vector3f a, Vector3f b, Vector3f c)
{
float v, w;
Vector3f ab = vSub(b, a);
Vector3f ac = vSub(c, a);
Vector3f qp = vSub(sp, sq);
Vector3f ab = VSub(b, a);
Vector3f ac = VSub(c, a);
Vector3f qp = VSub(sp, sq);
// Compute triangle normal. Can be precalculated or cached if
// intersecting multiple segments against the same triangle
Vector3f norm = vCross(ab, ac);
Vector3f norm = VCross(ab, ac);
// Compute denominator d. If d <= 0, segment is parallel to or points
// away from triangle, so exit early
float d = vDot(qp, norm);
float d = VDot(qp, norm);
if (d <= 0.0f)
{
return null;
@ -46,8 +46,8 @@ namespace DotRecast.Core
// Compute intersection t value of pq with plane of triangle. A ray
// intersects iff 0 <= t. Segment intersects iff 0 <= t <= 1. Delay
// dividing by d until intersection has been found to pierce triangle
Vector3f ap = vSub(sp, a);
float t = vDot(ap, norm);
Vector3f ap = VSub(sp, a);
float t = VDot(ap, norm);
if (t < 0.0f)
{
return null;
@ -59,14 +59,14 @@ namespace DotRecast.Core
}
// Compute barycentric coordinate components and test if within bounds
Vector3f e = vCross(qp, ap);
v = vDot(ac, e);
Vector3f e = VCross(qp, ap);
v = VDot(ac, e);
if (v < 0.0f || v > d)
{
return null;
}
w = -vDot(ab, e);
w = -VDot(ab, e);
if (w < 0.0f || v + w > d)
{
return null;
@ -78,7 +78,7 @@ namespace DotRecast.Core
return t;
}
public static float[] intersectSegmentAABB(Vector3f sp, Vector3f sq, Vector3f amin, Vector3f amax)
public static float[] IntersectSegmentAABB(Vector3f sp, Vector3f sq, Vector3f amin, Vector3f amax)
{
float EPS = 1e-6f;

View File

@ -26,9 +26,9 @@ namespace DotRecast.Core
public static class RecastMath
{
public const float EPS = 1e-4f;
private static readonly float EQUAL_THRESHOLD = sqr(1.0f / 16384.0f);
private static readonly float EQUAL_THRESHOLD = Sqr(1.0f / 16384.0f);
public static float vDistSqr(Vector3f v1, float[] v2, int i)
public static float VDistSqr(Vector3f v1, float[] v2, int i)
{
float dx = v2[i] - v1.x;
float dy = v2[i + 1] - v1.y;
@ -36,7 +36,7 @@ namespace DotRecast.Core
return dx * dx + dy * dy + dz * dz;
}
public static float vDistSqr(Vector3f v1, Vector3f v2)
public static float VDistSqr(Vector3f v1, Vector3f v2)
{
float dx = v2.x - v1.x;
float dy = v2.y - v1.y;
@ -44,7 +44,7 @@ namespace DotRecast.Core
return dx * dx + dy * dy + dz * dz;
}
public static float vDistSqr(float[] v, int i, int j)
public static float VDistSqr(float[] v, int i, int j)
{
float dx = v[i] - v[j];
float dy = v[i + 1] - v[j + 1];
@ -52,7 +52,7 @@ namespace DotRecast.Core
return dx * dx + dy * dy + dz * dz;
}
public static Vector3f vCross(Vector3f v1, Vector3f v2)
public static Vector3f VCross(Vector3f v1, Vector3f v2)
{
Vector3f dest = new Vector3f();
dest.x = v1.y * v2.z - v1.z * v2.y;
@ -61,22 +61,22 @@ namespace DotRecast.Core
return dest;
}
public static float vDot(Vector3f v1, Vector3f v2)
public static float VDot(Vector3f v1, Vector3f v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
public static float sqr(float f)
public static float Sqr(float f)
{
return f * f;
}
public static float getPathLen(float[] path, int npath)
public static float GetPathLen(float[] path, int npath)
{
float totd = 0;
for (int i = 0; i < npath - 1; ++i)
{
totd += (float)Math.Sqrt(vDistSqr(path, i * 3, (i + 1) * 3));
totd += (float)Math.Sqrt(VDistSqr(path, i * 3, (i + 1) * 3));
}
return totd;
@ -84,22 +84,22 @@ namespace DotRecast.Core
public static float step(float threshold, float v)
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);
}
public static int clamp(int v, int min, int max)
public static int Clamp(int v, int min, int max)
{
return Math.Max(Math.Min(v, max), min);
}
public static float lerp(float f, float g, float u)
public static float Lerp(float f, float g, float u)
{
return u * g + (1f - u) * f;
}
@ -110,7 +110,7 @@ namespace DotRecast.Core
/// @param[in] v1 The base vector. [(x, y, z)]
/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)]
/// @param[in] s The amount to scale @p v2 by before adding to @p v1.
public static Vector3f vMad(Vector3f v1, Vector3f v2, float s)
public static Vector3f VMad(Vector3f v1, Vector3f v2, float s)
{
Vector3f dest = new Vector3f();
dest.x = v1.x + v2.x * s;
@ -119,7 +119,7 @@ namespace DotRecast.Core
return dest;
}
public static Vector3f vMad(float[] v1, Vector3f v2, float s)
public static Vector3f VMad(float[] v1, Vector3f v2, float s)
{
Vector3f dest = new Vector3f();
dest.x = v1[0] + v2.x * s;
@ -136,7 +136,7 @@ namespace DotRecast.Core
/// @param[in] v1 The starting vector.
/// @param[in] v2 The destination vector.
/// @param[in] t The interpolation factor. [Limits: 0 <= value <= 1.0]
public static Vector3f vLerp(float[] verts, int v1, int v2, float t)
public static Vector3f VLerp(float[] verts, int v1, int v2, float t)
{
Vector3f dest = new Vector3f();
dest.x = verts[v1 + 0] + (verts[v2 + 0] - verts[v1 + 0]) * t;
@ -145,7 +145,7 @@ namespace DotRecast.Core
return dest;
}
public static Vector3f vLerp(Vector3f v1, Vector3f v2, float t)
public static Vector3f VLerp(Vector3f v1, Vector3f v2, float t)
{
Vector3f dest = new Vector3f();
dest.x = v1.x + (v2.x - v1.x) * t;
@ -155,16 +155,16 @@ namespace DotRecast.Core
}
public static Vector3f vSub(VectorPtr v1, VectorPtr v2)
public static Vector3f VSub(VectorPtr v1, VectorPtr v2)
{
Vector3f dest = new Vector3f();
dest.x = v1.get(0) - v2.get(0);
dest.y = v1.get(1) - v2.get(1);
dest.z = v1.get(2) - v2.get(2);
dest.x = v1.Get(0) - v2.Get(0);
dest.y = v1.Get(1) - v2.Get(1);
dest.z = v1.Get(2) - v2.Get(2);
return dest;
}
public static Vector3f vSub(Vector3f v1, Vector3f v2)
public static Vector3f VSub(Vector3f v1, Vector3f v2)
{
Vector3f dest = new Vector3f();
dest.x = v1.x - v2.x;
@ -173,17 +173,17 @@ namespace DotRecast.Core
return dest;
}
public static Vector3f vSub(Vector3f v1, VectorPtr v2)
public static Vector3f VSub(Vector3f v1, VectorPtr v2)
{
Vector3f dest = new Vector3f();
dest.x = v1.x - v2.get(0);
dest.y = v1.y - v2.get(1);
dest.z = v1.z - v2.get(2);
dest.x = v1.x - v2.Get(0);
dest.y = v1.y - v2.Get(1);
dest.z = v1.z - v2.Get(2);
return dest;
}
public static Vector3f vSub(Vector3f v1, float[] v2)
public static Vector3f VSub(Vector3f v1, float[] v2)
{
Vector3f dest = new Vector3f();
dest.x = v1.x - v2[0];
@ -192,7 +192,7 @@ namespace DotRecast.Core
return dest;
}
public static Vector3f vAdd(Vector3f v1, Vector3f v2)
public static Vector3f VAdd(Vector3f v1, Vector3f v2)
{
Vector3f dest = new Vector3f();
dest.x = v1.x + v2.x;
@ -201,42 +201,42 @@ namespace DotRecast.Core
return dest;
}
public static void vSet(ref Vector3f @out, float a, float b, float c)
public static void VSet(ref Vector3f @out, float a, float b, float c)
{
@out.x = a;
@out.y = b;
@out.z = c;
}
public static void vCopy(float[] @out, Vector3f @in)
public static void VCopy(float[] @out, Vector3f @in)
{
@out[0] = @in.x;
@out[1] = @in.y;
@out[2] = @in.z;
}
public static void vCopy(ref Vector3f @out, float[] @in)
public static void VCopy(ref Vector3f @out, float[] @in)
{
@out.x = @in[0];
@out.y = @in[1];
@out.z = @in[2];
}
public static void vCopy(ref Vector3f @out, float[] @in, int i)
public static void VCopy(ref Vector3f @out, float[] @in, int i)
{
@out.x = @in[i];
@out.y = @in[i + 1];
@out.z = @in[i + 2];
}
public static void vMin(float[] @out, float[] @in, int i)
public static void VMin(float[] @out, float[] @in, int i)
{
@out[0] = Math.Min(@out[0], @in[i]);
@out[1] = Math.Min(@out[1], @in[i + 1]);
@out[2] = Math.Min(@out[2], @in[i + 2]);
}
public static void vMin(ref Vector3f @out, float[] @in, int i)
public static void VMin(ref Vector3f @out, float[] @in, int i)
{
@out.x = Math.Min(@out.x, @in[i]);
@out.y = Math.Min(@out.y, @in[i + 1]);
@ -244,14 +244,14 @@ namespace DotRecast.Core
}
public static void vMax(float[] @out, float[] @in, int i)
public static void VMax(float[] @out, float[] @in, int i)
{
@out[0] = Math.Max(@out[0], @in[i]);
@out[1] = Math.Max(@out[1], @in[i + 1]);
@out[2] = Math.Max(@out[2], @in[i + 2]);
}
public static void vMax(ref Vector3f @out, float[] @in, int i)
public static void VMax(ref Vector3f @out, float[] @in, int i)
{
@out.x = Math.Max(@out.x, @in[i]);
@out.y = Math.Max(@out.y, @in[i + 1]);
@ -263,7 +263,7 @@ namespace DotRecast.Core
/// @param[in] v1 A point. [(x, y, z)]
/// @param[in] v2 A point. [(x, y, z)]
/// @return The distance between the two points.
public static float vDist(float[] v1, float[] v2)
public static float VDist(float[] v1, float[] v2)
{
float dx = v2[0] - v1[0];
float dy = v2[1] - v1[1];
@ -271,7 +271,7 @@ namespace DotRecast.Core
return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
}
public static float vDist(Vector3f v1, float[] v2)
public static float VDist(Vector3f v1, float[] v2)
{
float dx = v2[0] - v1.x;
float dy = v2[1] - v1.y;
@ -279,7 +279,7 @@ namespace DotRecast.Core
return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
}
public static float vDist(Vector3f v1, Vector3f v2)
public static float VDist(Vector3f v1, Vector3f v2)
{
float dx = v2.x - v1.x;
float dy = v2.y - v1.y;
@ -293,7 +293,7 @@ namespace DotRecast.Core
/// @param[in] v1 A point. [(x, y, z)]
/// @param[in] v2 A point. [(x, y, z)]
/// @return The distance between the two points.
public static float vDistSqr(float[] v1, float[] v2)
public static float VDistSqr(float[] v1, float[] v2)
{
float dx = v2[0] - v1[0];
float dy = v2[1] - v1[1];
@ -306,29 +306,29 @@ namespace DotRecast.Core
/// Derives the square of the scalar length of the vector. (len * len)
/// @param[in] v The vector. [(x, y, z)]
/// @return The square of the scalar length of the vector.
public static float vLenSqr(float[] v)
public static float VLenSqr(float[] v)
{
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
}
public static float vLenSqr(Vector3f v)
public static float VLenSqr(Vector3f v)
{
return v.x * v.x + v.y * v.y + v.z * v.z;
}
public static float vLen(float[] v)
public static float VLen(float[] v)
{
return (float)Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
public static float vLen(Vector3f v)
public static float VLen(Vector3f v)
{
return (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
public static float vDist(float[] v1, float[] verts, int i)
public static float VDist(float[] v1, float[] verts, int i)
{
float dx = verts[i] - v1[0];
float dy = verts[i + 1] - v1[1];
@ -344,14 +344,14 @@ namespace DotRecast.Core
///
/// The vectors are projected onto the xz-plane, so the y-values are
/// ignored.
public static float vDist2D(float[] v1, float[] v2)
public static float VDist2D(float[] v1, float[] v2)
{
float dx = v2[0] - v1[0];
float dz = v2[2] - v1[2];
return (float)Math.Sqrt(dx * dx + dz * dz);
}
public static float vDist2D(Vector3f v1, Vector3f v2)
public static float VDist2D(Vector3f v1, Vector3f v2)
{
float dx = v2.x - v1.x;
float dz = v2.z - v1.z;
@ -359,14 +359,14 @@ namespace DotRecast.Core
}
public static float vDist2DSqr(float[] v1, float[] v2)
public static float VDist2DSqr(float[] v1, float[] v2)
{
float dx = v2[0] - v1[0];
float dz = v2[2] - v1[2];
return dx * dx + dz * dz;
}
public static float vDist2DSqr(Vector3f v1, Vector3f v2)
public static float VDist2DSqr(Vector3f v1, Vector3f v2)
{
float dx = v2.x - v1.x;
float dz = v2.z - v1.z;
@ -374,7 +374,7 @@ namespace DotRecast.Core
}
public static float vDist2DSqr(Vector3f p, float[] verts, int i)
public static float VDist2DSqr(Vector3f p, float[] verts, int i)
{
float dx = verts[i] - p.x;
float dz = verts[i + 2] - p.z;
@ -383,9 +383,9 @@ namespace DotRecast.Core
/// Normalizes the vector.
/// @param[in,out] v The vector to normalize. [(x, y, z)]
public static void vNormalize(float[] v)
public static void VNormalize(float[] v)
{
float d = (float)(1.0f / Math.Sqrt(sqr(v[0]) + sqr(v[1]) + sqr(v[2])));
float d = (float)(1.0f / Math.Sqrt(Sqr(v[0]) + Sqr(v[1]) + Sqr(v[2])));
if (d != 0)
{
v[0] *= d;
@ -394,9 +394,9 @@ namespace DotRecast.Core
}
}
public static void vNormalize(ref Vector3f v)
public static void VNormalize(ref Vector3f v)
{
float d = (float)(1.0f / Math.Sqrt(sqr(v.x) + sqr(v.y) + sqr(v.z)));
float d = (float)(1.0f / Math.Sqrt(Sqr(v.x) + Sqr(v.y) + Sqr(v.z)));
if (d != 0)
{
v.x *= d;
@ -413,26 +413,26 @@ namespace DotRecast.Core
///
/// Basically, this function will return true if the specified points are
/// close enough to eachother to be considered colocated.
public static bool vEqual(float[] p0, float[] p1)
public static bool VEqual(float[] p0, float[] p1)
{
return vEqual(p0, p1, EQUAL_THRESHOLD);
return VEqual(p0, p1, EQUAL_THRESHOLD);
}
public static bool vEqual(Vector3f p0, Vector3f p1)
public static bool VEqual(Vector3f p0, Vector3f p1)
{
return vEqual(p0, p1, EQUAL_THRESHOLD);
return VEqual(p0, p1, EQUAL_THRESHOLD);
}
public static bool vEqual(float[] p0, float[] p1, float thresholdSqr)
public static bool VEqual(float[] p0, float[] p1, float thresholdSqr)
{
float d = vDistSqr(p0, p1);
float d = VDistSqr(p0, p1);
return d < thresholdSqr;
}
public static bool vEqual(Vector3f p0, Vector3f p1, float thresholdSqr)
public static bool VEqual(Vector3f p0, Vector3f p1, float thresholdSqr)
{
float d = vDistSqr(p0, p1);
float d = VDistSqr(p0, p1);
return d < thresholdSqr;
}
@ -444,18 +444,18 @@ namespace DotRecast.Core
///
/// The vectors are projected onto the xz-plane, so the y-values are
/// ignored.
public static float vDot2D(float[] u, float[] v)
public static float VDot2D(float[] u, float[] v)
{
return u[0] * v[0] + u[2] * v[2];
}
public static float vDot2D(Vector3f u, Vector3f v)
public static float VDot2D(Vector3f u, Vector3f v)
{
return u.x * v.x + u.z * v.z;
}
public static float vDot2D(Vector3f u, float[] v, int vi)
public static float VDot2D(Vector3f u, float[] v, int vi)
{
return u.x * v[vi] + u.z * v[vi + 2];
}
@ -467,12 +467,12 @@ namespace DotRecast.Core
///
/// The vectors are projected onto the xz-plane, so the y-values are
/// ignored.
public static float vPerp2D(float[] u, float[] v)
public static float VPerp2D(float[] u, float[] v)
{
return u[2] * v[0] - u[0] * v[2];
}
public static float vPerp2D(Vector3f u, Vector3f v)
public static float VPerp2D(Vector3f u, Vector3f v)
{
return u.z * v.x - u.x * v.z;
}
@ -487,7 +487,7 @@ namespace DotRecast.Core
/// @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)
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];
@ -496,7 +496,7 @@ namespace DotRecast.Core
return acx * abz - abx * acz;
}
public static float triArea2D(float[] a, float[] b, float[] c)
public static float TriArea2D(float[] a, float[] b, float[] c)
{
float abx = b[0] - a[0];
float abz = b[2] - a[2];
@ -505,7 +505,7 @@ namespace DotRecast.Core
return acx * abz - abx * acz;
}
public static float triArea2D(Vector3f a, Vector3f b, Vector3f c)
public static float TriArea2D(Vector3f a, Vector3f b, Vector3f c)
{
float abx = b.x - a.x;
float abz = b.z - a.z;
@ -514,7 +514,7 @@ namespace DotRecast.Core
return acx * abz - abx * acz;
}
public static float triArea2D(Vector3f a, float[] b, Vector3f c)
public static float TriArea2D(Vector3f a, float[] b, Vector3f c)
{
float abx = b[0] - a.x;
float abz = b[2] - a.z;
@ -532,7 +532,7 @@ namespace DotRecast.Core
/// @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)
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;
@ -548,7 +548,7 @@ namespace DotRecast.Core
/// @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(float[] amin, float[] amax, float[] bmin, float[] bmax)
public static bool OverlapBounds(float[] amin, float[] amax, float[] bmin, float[] bmax)
{
bool overlap = true;
overlap = (amin[0]> bmax[0] || amax[0] < bmin[0]) ? false : overlap;
@ -557,7 +557,7 @@ namespace DotRecast.Core
return overlap;
}
public static bool overlapBounds(Vector3f amin, Vector3f amax, Vector3f bmin, Vector3f bmax)
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;
@ -566,7 +566,7 @@ namespace DotRecast.Core
return overlap;
}
public static Tuple<float, float> distancePtSegSqr2D(Vector3f pt, Vector3f p, Vector3f q)
public static Tuple<float, float> DistancePtSegSqr2D(Vector3f pt, Vector3f p, Vector3f q)
{
float pqx = q.x - p.x;
float pqz = q.z - p.z;
@ -593,11 +593,11 @@ namespace DotRecast.Core
return Tuple.Create(dx * dx + dz * dz, t);
}
public static float? closestHeightPointTriangle(Vector3f p, Vector3f a, Vector3f b, Vector3f c)
public static float? ClosestHeightPointTriangle(Vector3f p, Vector3f a, Vector3f b, Vector3f c)
{
Vector3f v0 = vSub(c, a);
Vector3f v1 = vSub(b, a);
Vector3f v2 = vSub(p, a);
Vector3f v0 = VSub(c, a);
Vector3f v1 = VSub(b, a);
Vector3f v2 = VSub(p, a);
// Compute scaled barycentric coordinates
float denom = v0.x * v1.z - v0.z * v1.x;
@ -629,7 +629,7 @@ namespace DotRecast.Core
/// @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)
public static bool PointInPolygon(Vector3f pt, float[] verts, int nverts)
{
// TODO: Replace pnpoly with triArea2D tests?
int i, j;
@ -648,7 +648,7 @@ namespace DotRecast.Core
return c;
}
public static bool distancePtPolyEdgesSqr(Vector3f pt, float[] verts, int nverts, float[] ed, float[] et)
public static bool DistancePtPolyEdgesSqr(Vector3f pt, float[] verts, int nverts, float[] ed, float[] et)
{
// TODO: Replace pnpoly with triArea2D tests?
int i, j;
@ -663,7 +663,7 @@ namespace DotRecast.Core
c = !c;
}
Tuple<float, float> edet = distancePtSegSqr2D(pt, verts, vj, vi);
Tuple<float, float> edet = DistancePtSegSqr2D(pt, verts, vj, vi);
ed[j] = edet.Item1;
et[j] = edet.Item2;
}
@ -671,13 +671,13 @@ namespace DotRecast.Core
return c;
}
public static float[] projectPoly(Vector3f axis, float[] poly, int npoly)
public static float[] ProjectPoly(Vector3f axis, float[] poly, int npoly)
{
float rmin, rmax;
rmin = rmax = vDot2D(axis, poly, 0);
rmin = rmax = VDot2D(axis, poly, 0);
for (int i = 1; i < npoly; ++i)
{
float d = vDot2D(axis, poly, i * 3);
float d = VDot2D(axis, poly, i * 3);
rmin = Math.Min(rmin, d);
rmax = Math.Max(rmax, d);
}
@ -685,7 +685,7 @@ namespace DotRecast.Core
return new float[] { rmin, rmax };
}
public static bool overlapRange(float amin, float amax, float bmin, float bmax, float eps)
public static bool OverlapRange(float amin, float amax, float bmin, float bmax, float eps)
{
return ((amin + eps) > bmax || (amax - eps) < bmin) ? false : true;
}
@ -695,7 +695,7 @@ namespace DotRecast.Core
/// @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)
public static bool OverlapPolyPoly2D(float[] polya, int npolya, float[] polyb, int npolyb)
{
for (int i = 0, j = npolya - 1; i < npolya; j = i++)
{
@ -704,9 +704,9 @@ namespace DotRecast.Core
Vector3f n = Vector3f.Of(polya[vb + 2] - polya[va + 2], 0, -(polya[vb + 0] - polya[va + 0]));
float[] aminmax = projectPoly(n, polya, npolya);
float[] bminmax = projectPoly(n, polyb, npolyb);
if (!overlapRange(aminmax[0], aminmax[1], bminmax[0], bminmax[1], eps))
float[] aminmax = ProjectPoly(n, polya, npolya);
float[] bminmax = ProjectPoly(n, polyb, npolyb);
if (!OverlapRange(aminmax[0], aminmax[1], bminmax[0], bminmax[1], eps))
{
// Found separating axis
return false;
@ -720,9 +720,9 @@ namespace DotRecast.Core
Vector3f n = Vector3f.Of(polyb[vb + 2] - polyb[va + 2], 0, -(polyb[vb + 0] - polyb[va + 0]));
float[] aminmax = projectPoly(n, polya, npolya);
float[] bminmax = projectPoly(n, polyb, npolyb);
if (!overlapRange(aminmax[0], aminmax[1], bminmax[0], bminmax[1], eps))
float[] aminmax = ProjectPoly(n, polya, npolya);
float[] bminmax = ProjectPoly(n, polyb, npolyb);
if (!OverlapRange(aminmax[0], aminmax[1], bminmax[0], bminmax[1], eps))
{
// Found separating axis
return false;
@ -734,13 +734,13 @@ namespace DotRecast.Core
// 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)
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);
areas[i] = TriArea2D(pts, 0, (i - 1) * 3, i * 3);
areasum += Math.Max(0.001f, areas[i]);
}
@ -779,7 +779,7 @@ namespace DotRecast.Core
};
}
public static int nextPow2(int v)
public static int NextPow2(int v)
{
v--;
v |= v >> 1;
@ -791,7 +791,7 @@ namespace DotRecast.Core
return v;
}
public static int ilog2(int v)
public static int Ilog2(int v)
{
int r;
int shift;
@ -819,20 +819,20 @@ namespace DotRecast.Core
public int segMax = -1;
}
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();
float EPS = 0.000001f;
var dir = vSub(p1, p0);
var dir = VSub(p1, p0);
var p0v = p0;
for (int i = 0, j = nverts - 1; i < nverts; j = i++)
{
VectorPtr vpj = new VectorPtr(verts, j * 3);
var edge = vSub(new VectorPtr(verts, i * 3), vpj);
var diff = vSub(p0v, vpj);
float n = vPerp2D(edge, diff);
float d = vPerp2D(dir, edge);
var edge = VSub(new VectorPtr(verts, i * 3), vpj);
var diff = VSub(p0v, vpj);
float n = VPerp2D(edge, diff);
float d = VPerp2D(dir, edge);
if (Math.Abs(d) < EPS)
{
// S is nearly parallel to this edge
@ -881,7 +881,7 @@ namespace DotRecast.Core
return result;
}
public static Tuple<float, float> distancePtSegSqr2D(Vector3f pt, SegmentVert verts, int p, int q)
public static Tuple<float, float> DistancePtSegSqr2D(Vector3f pt, SegmentVert verts, int p, int q)
{
float pqx = verts[q + 0] - verts[p + 0];
float pqz = verts[q + 2] - verts[p + 2];
@ -909,7 +909,7 @@ namespace DotRecast.Core
}
public static Tuple<float, float> distancePtSegSqr2D(Vector3f pt, float[] verts, int p, int q)
public static Tuple<float, float> DistancePtSegSqr2D(Vector3f pt, float[] verts, int p, int q)
{
float pqx = verts[q + 0] - verts[p + 0];
float pqz = verts[q + 2] - verts[p + 2];
@ -936,38 +936,38 @@ namespace DotRecast.Core
return Tuple.Create(dx * dx + dz * dz, t);
}
public static int oppositeTile(int side)
public static int OppositeTile(int side)
{
return (side + 4) & 0x7;
}
public static float vperpXZ(float[] a, float[] b)
public static float VperpXZ(float[] a, float[] b)
{
return a[0] * b[2] - a[2] * b[0];
}
public static float vperpXZ(Vector3f a, Vector3f b)
public static float VperpXZ(Vector3f a, Vector3f b)
{
return a.x * b.z - a.z * b.x;
}
public static Tuple<float, float>? intersectSegSeg2D(Vector3f ap, Vector3f aq, Vector3f bp, Vector3f bq)
public static Tuple<float, float>? IntersectSegSeg2D(Vector3f ap, Vector3f aq, Vector3f bp, Vector3f bq)
{
Vector3f u = vSub(aq, ap);
Vector3f v = vSub(bq, bp);
Vector3f w = vSub(ap, bp);
float d = vperpXZ(u, v);
Vector3f u = VSub(aq, ap);
Vector3f v = VSub(bq, bp);
Vector3f w = VSub(ap, bp);
float d = VperpXZ(u, v);
if (Math.Abs(d) < 1e-6f)
{
return null;
}
float s = vperpXZ(v, w) / d;
float t = vperpXZ(u, w) / d;
float s = VperpXZ(v, w) / d;
float t = VperpXZ(u, w) / d;
return Tuple.Create(s, t);
}
public static Vector3f vScale(Vector3f @in, float scale)
public static Vector3f VScale(Vector3f @in, float scale)
{
var @out = new Vector3f();
@out.x = @in.x * scale;
@ -981,24 +981,24 @@ namespace DotRecast.Core
/// @param[in] v A point. [(x, y, z)]
/// @return True if all of the point's components are finite, i.e. not NaN
/// or any of the infinities.
public static bool vIsFinite(float[] v)
public static bool VIsFinite(float[] v)
{
return float.IsFinite(v[0]) && float.IsFinite(v[1]) && float.IsFinite(v[2]);
}
public static bool vIsFinite(Vector3f v)
public static bool VIsFinite(Vector3f v)
{
return float.IsFinite(v.x) && float.IsFinite(v.y) && float.IsFinite(v.z);
}
/// Checks that the specified vector's 2D components are finite.
/// @param[in] v A point. [(x, y, z)]
public static bool vIsFinite2D(float[] v)
public static bool VIsFinite2D(float[] v)
{
return float.IsFinite(v[0]) && float.IsFinite(v[2]);
}
public static bool vIsFinite2D(Vector3f v)
public static bool VIsFinite2D(Vector3f v)
{
return float.IsFinite(v.x) && float.IsFinite(v.z);
}

View File

@ -40,7 +40,7 @@ namespace DotRecast.Core
this.index = index;
}
public float get(int offset)
public float Get(int offset)
{
return array[index + offset];
}

File diff suppressed because it is too large Load Diff

View File

@ -135,35 +135,35 @@ namespace DotRecast.Detour.Crowd
animation = new CrowdAgentAnimation();
}
public void integrate(float dt)
public void Integrate(float dt)
{
// Fake dynamic constraint.
float maxDelta = option.maxAcceleration * dt;
Vector3f dv = vSub(nvel, vel);
float ds = vLen(dv);
Vector3f dv = VSub(nvel, vel);
float ds = VLen(dv);
if (ds > maxDelta)
dv = vScale(dv, maxDelta / ds);
vel = vAdd(vel, dv);
dv = VScale(dv, maxDelta / ds);
vel = VAdd(vel, dv);
// Integrate
if (vLen(vel) > 0.0001f)
npos = vMad(npos, vel, dt);
if (VLen(vel) > 0.0001f)
npos = VMad(npos, vel, dt);
else
vel = Vector3f.Zero;
}
public bool overOffmeshConnection(float radius)
public bool OverOffmeshConnection(float radius)
{
if (0 == corners.Count)
return false;
bool offMeshConnection = ((corners[corners.Count - 1].getFlags()
bool offMeshConnection = ((corners[corners.Count - 1].GetFlags()
& NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
? true
: false;
if (offMeshConnection)
{
float distSq = vDist2DSqr(npos, corners[corners.Count - 1].getPos());
float distSq = VDist2DSqr(npos, corners[corners.Count - 1].GetPos());
if (distSq < radius * radius)
return true;
}
@ -171,62 +171,62 @@ namespace DotRecast.Detour.Crowd
return false;
}
public float getDistanceToGoal(float range)
public float GetDistanceToGoal(float range)
{
if (0 == corners.Count)
return range;
bool endOfPath = ((corners[corners.Count - 1].getFlags() & NavMeshQuery.DT_STRAIGHTPATH_END) != 0) ? true : false;
bool endOfPath = ((corners[corners.Count - 1].GetFlags() & NavMeshQuery.DT_STRAIGHTPATH_END) != 0) ? true : false;
if (endOfPath)
return Math.Min(vDist2D(npos, corners[corners.Count - 1].getPos()), range);
return Math.Min(VDist2D(npos, corners[corners.Count - 1].GetPos()), range);
return range;
}
public Vector3f calcSmoothSteerDirection()
public Vector3f CalcSmoothSteerDirection()
{
Vector3f dir = new Vector3f();
if (0 < corners.Count)
{
int ip0 = 0;
int ip1 = Math.Min(1, corners.Count - 1);
var p0 = corners[ip0].getPos();
var p1 = corners[ip1].getPos();
var p0 = corners[ip0].GetPos();
var p1 = corners[ip1].GetPos();
var dir0 = vSub(p0, npos);
var dir1 = vSub(p1, npos);
var dir0 = VSub(p0, npos);
var dir1 = VSub(p1, npos);
dir0.y = 0;
dir1.y = 0;
float len0 = vLen(dir0);
float len1 = vLen(dir1);
float len0 = VLen(dir0);
float len1 = VLen(dir1);
if (len1 > 0.001f)
dir1 = vScale(dir1, 1.0f / len1);
dir1 = VScale(dir1, 1.0f / len1);
dir.x = dir0.x - dir1.x * len0 * 0.5f;
dir.y = 0;
dir.z = dir0.z - dir1.z * len0 * 0.5f;
vNormalize(ref dir);
VNormalize(ref dir);
}
return dir;
}
public Vector3f calcStraightSteerDirection()
public Vector3f CalcStraightSteerDirection()
{
Vector3f dir = new Vector3f();
if (0 < corners.Count)
{
dir = vSub(corners[0].getPos(), npos);
dir = VSub(corners[0].GetPos(), npos);
dir.y = 0;
vNormalize(ref dir);
VNormalize(ref dir);
}
return dir;
}
public void setTarget(long refs, Vector3f pos)
public void SetTarget(long refs, Vector3f pos)
{
targetRef = refs;
targetPos = pos;

View File

@ -54,11 +54,11 @@ namespace DotRecast.Detour.Crowd
public const int DT_CROWD_SEPARATION = 4;
public const int DT_CROWD_OPTIMIZE_VIS = 8;
/// < Use #dtPathCorridor::optimizePathVisibility() to optimize
/// < Use #dtPathCorridor::OptimizePathVisibility() to optimize
/// the agent path.
public const int DT_CROWD_OPTIMIZE_TOPO = 16;
/// < Use dtPathCorridor::optimizePathTopology() to optimize
/// < Use dtPathCorridor::OptimizePathTopology() to optimize
/// the agent path.
/// Flags that impact steering behavior. (See: #UpdateFlags)
public int updateFlags;

View File

@ -32,44 +32,44 @@ namespace DotRecast.Detour.Crowd
private readonly Dictionary<string, long> _executionTimings = new Dictionary<string, long>();
private readonly Dictionary<string, List<long>> _executionTimingSamples = new Dictionary<string, List<long>>();
public float maxTimeToEnqueueRequest()
public float MaxTimeToEnqueueRequest()
{
return _maxTimeToEnqueueRequest;
}
public float maxTimeToFindPath()
public float MaxTimeToFindPath()
{
return _maxTimeToFindPath;
}
public Dictionary<string, long> executionTimings()
public Dictionary<string, long> ExecutionTimings()
{
return _executionTimings;
}
public void start()
public void Start()
{
_maxTimeToEnqueueRequest = 0;
_maxTimeToFindPath = 0;
_executionTimings.Clear();
}
public void recordMaxTimeToEnqueueRequest(float time)
public void RecordMaxTimeToEnqueueRequest(float time)
{
_maxTimeToEnqueueRequest = Math.Max(_maxTimeToEnqueueRequest, time);
}
public void recordMaxTimeToFindPath(float time)
public void RecordMaxTimeToFindPath(float time)
{
_maxTimeToFindPath = Math.Max(_maxTimeToFindPath, time);
}
public void start(string name)
public void Start(string name)
{
_executionTimings.Add(name, FrequencyWatch.Ticks);
}
public void stop(string name)
public void Stop(string name)
{
long duration = FrequencyWatch.Ticks - _executionTimings[name];
if (!_executionTimingSamples.TryGetValue(name, out var s))

View File

@ -49,14 +49,14 @@ namespace DotRecast.Detour.Crowd
m_center.x = m_center.y = m_center.z = float.MaxValue;
}
public void reset()
public void Reset()
{
m_center.x = m_center.y = m_center.z = float.MaxValue;
m_polys.Clear();
m_segs.Clear();
}
protected void addSegment(float dist, SegmentVert s)
protected void AddSegment(float dist, SegmentVert s)
{
// Insert neighbour based on the distance.
Segment seg = new Segment();
@ -98,47 +98,47 @@ namespace DotRecast.Detour.Crowd
}
}
public void update(long refs, Vector3f pos, float collisionQueryRange, NavMeshQuery navquery, QueryFilter filter)
public void Update(long refs, Vector3f pos, float collisionQueryRange, NavMeshQuery navquery, QueryFilter filter)
{
if (refs == 0)
{
reset();
Reset();
return;
}
m_center = pos;
// First query non-overlapping polygons.
Result<FindLocalNeighbourhoodResult> res = navquery.findLocalNeighbourhood(refs, pos, collisionQueryRange,
Result<FindLocalNeighbourhoodResult> res = navquery.FindLocalNeighbourhood(refs, pos, collisionQueryRange,
filter);
if (res.Succeeded())
{
m_polys = res.result.getRefs();
m_polys = res.result.GetRefs();
m_segs.Clear();
// Secondly, store all polygon edges.
for (int j = 0; j < m_polys.Count; ++j)
{
Result<GetPolyWallSegmentsResult> result = navquery.getPolyWallSegments(m_polys[j], false, filter);
Result<GetPolyWallSegmentsResult> result = navquery.GetPolyWallSegments(m_polys[j], false, filter);
if (result.Succeeded())
{
GetPolyWallSegmentsResult gpws = result.result;
for (int k = 0; k < gpws.countSegmentRefs(); ++k)
for (int k = 0; k < gpws.CountSegmentRefs(); ++k)
{
SegmentVert s = gpws.getSegmentVert(k);
SegmentVert s = gpws.GetSegmentVert(k);
// Skip too distant segments.
Tuple<float, float> distseg = distancePtSegSqr2D(pos, s, 0, 3);
if (distseg.Item1 > sqr(collisionQueryRange))
Tuple<float, float> distseg = DistancePtSegSqr2D(pos, s, 0, 3);
if (distseg.Item1 > Sqr(collisionQueryRange))
{
continue;
}
addSegment(distseg.Item1, s);
AddSegment(distseg.Item1, s);
}
}
}
}
}
public bool isValid(NavMeshQuery navquery, QueryFilter filter)
public bool IsValid(NavMeshQuery navquery, QueryFilter filter)
{
if (m_polys.Count == 0)
{
@ -148,7 +148,7 @@ namespace DotRecast.Detour.Crowd
// Check that all polygons still pass query filter.
foreach (long refs in m_polys)
{
if (!navquery.isValidPolyRef(refs, filter))
if (!navquery.IsValidPolyRef(refs, filter))
{
return false;
}
@ -157,17 +157,17 @@ namespace DotRecast.Detour.Crowd
return true;
}
public Vector3f getCenter()
public Vector3f GetCenter()
{
return m_center;
}
public Vector3f[] getSegment(int j)
public Vector3f[] GetSegment(int j)
{
return m_segs[j].s;
}
public int getSegmentCount()
public int GetSegmentCount()
{
return m_segs.Count;
}

View File

@ -98,13 +98,13 @@ namespace DotRecast.Detour.Crowd
}
}
public void reset()
public void Reset()
{
m_ncircles = 0;
m_nsegments = 0;
}
public void addCircle(Vector3f pos, float rad, Vector3f vel, Vector3f dvel)
public void AddCircle(Vector3f pos, float rad, Vector3f vel, Vector3f dvel)
{
if (m_ncircles >= m_maxCircles)
return;
@ -116,7 +116,7 @@ namespace DotRecast.Detour.Crowd
cir.dvel = dvel;
}
public void addSegment(Vector3f p, Vector3f q)
public void AddSegment(Vector3f p, Vector3f q)
{
if (m_nsegments >= m_maxSegments)
return;
@ -126,27 +126,27 @@ namespace DotRecast.Detour.Crowd
seg.q = q;
}
public int getObstacleCircleCount()
public int GetObstacleCircleCount()
{
return m_ncircles;
}
public ObstacleCircle getObstacleCircle(int i)
public ObstacleCircle GetObstacleCircle(int i)
{
return m_circles[i];
}
public int getObstacleSegmentCount()
public int GetObstacleSegmentCount()
{
return m_nsegments;
}
public ObstacleSegment getObstacleSegment(int i)
public ObstacleSegment GetObstacleSegment(int i)
{
return m_segments[i];
}
private void prepare(Vector3f pos, Vector3f dvel)
private void Prepare(Vector3f pos, Vector3f dvel)
{
// Prepare obstacles
for (int i = 0; i < m_ncircles; ++i)
@ -159,11 +159,11 @@ namespace DotRecast.Detour.Crowd
Vector3f orig = new Vector3f();
Vector3f dv = new Vector3f();
cir.dp = vSub(pb, pa);
vNormalize(ref cir.dp);
dv = vSub(cir.dvel, dvel);
cir.dp = VSub(pb, pa);
VNormalize(ref cir.dp);
dv = VSub(cir.dvel, dvel);
float a = triArea2D(orig, cir.dp, dv);
float a = TriArea2D(orig, cir.dp, dv);
if (a < 0.01f)
{
cir.np.x = -cir.dp.z;
@ -182,23 +182,23 @@ namespace DotRecast.Detour.Crowd
// Precalc if the agent is really close to the segment.
float r = 0.01f;
Tuple<float, float> dt = distancePtSegSqr2D(pos, seg.p, seg.q);
seg.touch = dt.Item1 < sqr(r);
Tuple<float, float> dt = DistancePtSegSqr2D(pos, seg.p, seg.q);
seg.touch = dt.Item1 < Sqr(r);
}
}
SweepCircleCircleResult sweepCircleCircle(Vector3f c0, float r0, Vector3f v, Vector3f c1, float r1)
SweepCircleCircleResult SweepCircleCircle(Vector3f c0, float r0, Vector3f v, Vector3f c1, float r1)
{
const float EPS = 0.0001f;
Vector3f s = vSub(c1, c0);
Vector3f s = VSub(c1, c0);
float r = r0 + r1;
float c = vDot2D(s, s) - r * r;
float a = vDot2D(v, v);
float c = VDot2D(s, s) - r * r;
float a = VDot2D(v, v);
if (a < EPS)
return new SweepCircleCircleResult(false, 0f, 0f); // not moving
// Overlap, calc time to exit.
float b = vDot2D(v, s);
float b = VDot2D(v, s);
float d = b * b - a * c;
if (d < 0.0f)
return new SweepCircleCircleResult(false, 0f, 0f); // no intersection.
@ -207,20 +207,20 @@ namespace DotRecast.Detour.Crowd
return new SweepCircleCircleResult(true, (b - rd) * a, (b + rd) * a);
}
IsectRaySegResult isectRaySeg(Vector3f ap, Vector3f u, Vector3f bp, Vector3f bq)
IsectRaySegResult IsectRaySeg(Vector3f ap, Vector3f u, Vector3f bp, Vector3f bq)
{
Vector3f v = vSub(bq, bp);
Vector3f w = vSub(ap, bp);
float d = vPerp2D(u, v);
Vector3f v = VSub(bq, bp);
Vector3f w = VSub(ap, bp);
float d = VPerp2D(u, v);
if (Math.Abs(d) < 1e-6f)
return new IsectRaySegResult(false, 0f);
d = 1.0f / d;
float t = vPerp2D(v, w) * d;
float t = VPerp2D(v, w) * d;
if (t < 0 || t > 1)
return new IsectRaySegResult(false, 0f);
float s = vPerp2D(u, w) * d;
float s = VPerp2D(u, w) * d;
if (s < 0 || s > 1)
return new IsectRaySegResult(false, 0f);
@ -237,12 +237,12 @@ namespace DotRecast.Detour.Crowd
* @param minPenalty
* threshold penalty for early out
*/
private float processSample(Vector3f vcand, float cs, Vector3f pos, float rad, Vector3f vel, Vector3f dvel,
private float ProcessSample(Vector3f vcand, float cs, Vector3f pos, float rad, Vector3f vel, Vector3f dvel,
float minPenalty, ObstacleAvoidanceDebugData debug)
{
// penalty for straying away from the desired and current velocities
float vpen = m_params.weightDesVel * (vDist2D(vcand, dvel) * m_invVmax);
float vcpen = m_params.weightCurVel * (vDist2D(vcand, vel) * m_invVmax);
float vpen = m_params.weightDesVel * (VDist2D(vcand, dvel) * m_invVmax);
float vcpen = m_params.weightCurVel * (VDist2D(vcand, vel) * m_invVmax);
// find the threshold hit time to bail out based on the early out penalty
// (see how the penalty is calculated below to understnad)
@ -261,15 +261,15 @@ namespace DotRecast.Detour.Crowd
ObstacleCircle cir = m_circles[i];
// RVO
Vector3f vab = vScale(vcand, 2);
vab = vSub(vab, vel);
vab = vSub(vab, cir.vel);
Vector3f vab = VScale(vcand, 2);
vab = VSub(vab, vel);
vab = VSub(vab, cir.vel);
// Side
side += clamp(Math.Min(vDot2D(cir.dp, vab) * 0.5f + 0.5f, vDot2D(cir.np, vab) * 2), 0.0f, 1.0f);
side += Clamp(Math.Min(VDot2D(cir.dp, vab) * 0.5f + 0.5f, VDot2D(cir.np, vab) * 2), 0.0f, 1.0f);
nside++;
SweepCircleCircleResult sres = sweepCircleCircle(pos, rad, vab, cir.p, cir.rad);
SweepCircleCircleResult sres = SweepCircleCircle(pos, rad, vab, cir.p, cir.rad);
if (!sres.intersection)
continue;
float htmin = sres.htmin, htmax = sres.htmax;
@ -301,19 +301,19 @@ namespace DotRecast.Detour.Crowd
if (seg.touch)
{
// Special case when the agent is very close to the segment.
Vector3f sdir = vSub(seg.q, seg.p);
Vector3f sdir = VSub(seg.q, seg.p);
Vector3f snorm = new Vector3f();
snorm.x = -sdir.z;
snorm.z = sdir.x;
// If the velocity is pointing towards the segment, no collision.
if (vDot2D(snorm, vcand) < 0.0f)
if (VDot2D(snorm, vcand) < 0.0f)
continue;
// Else immediate collision.
htmin = 0.0f;
}
else
{
var ires = isectRaySeg(pos, vcand, seg.p, seg.q);
var ires = IsectRaySeg(pos, vcand, seg.p, seg.q);
if (!ires.result)
continue;
@ -342,15 +342,15 @@ namespace DotRecast.Detour.Crowd
float penalty = vpen + vcpen + spen + tpen;
// Store different penalties for debug viewing
if (debug != null)
debug.addSample(vcand, cs, penalty, vpen, vcpen, spen, tpen);
debug.AddSample(vcand, cs, penalty, vpen, vcpen, spen, tpen);
return penalty;
}
public Tuple<int, Vector3f> sampleVelocityGrid(Vector3f pos, float rad, float vmax, Vector3f vel, Vector3f dvel,
public Tuple<int, Vector3f> SampleVelocityGrid(Vector3f pos, float rad, float vmax, Vector3f vel, Vector3f dvel,
ObstacleAvoidanceParams option, ObstacleAvoidanceDebugData debug)
{
prepare(pos, dvel);
Prepare(pos, dvel);
m_params = option;
m_invHorizTime = 1.0f / m_params.horizTime;
m_vmax = vmax;
@ -359,7 +359,7 @@ namespace DotRecast.Detour.Crowd
Vector3f nvel = Vector3f.Zero;
if (debug != null)
debug.reset();
debug.Reset();
float cvx = dvel.x * m_params.velBias;
float cvz = dvel.z * m_params.velBias;
@ -374,12 +374,12 @@ namespace DotRecast.Detour.Crowd
for (int x = 0; x < m_params.gridSize; ++x)
{
Vector3f vcand = new Vector3f();
vSet(ref vcand, cvx + x * cs - half, 0f, cvz + y * cs - half);
VSet(ref vcand, cvx + x * cs - half, 0f, cvz + y * cs - half);
if (sqr(vcand.x) + sqr(vcand.z) > sqr(vmax + cs / 2))
if (Sqr(vcand.x) + Sqr(vcand.z) > Sqr(vmax + cs / 2))
continue;
float penalty = processSample(vcand, cs, pos, rad, vel, dvel, minPenalty, debug);
float penalty = ProcessSample(vcand, cs, pos, rad, vel, dvel, minPenalty, debug);
ns++;
if (penalty < minPenalty)
{
@ -393,7 +393,7 @@ namespace DotRecast.Detour.Crowd
}
// vector normalization that ignores the y-component.
void dtNormalize2D(float[] v)
void DtNormalize2D(float[] v)
{
float d = (float)Math.Sqrt(v[0] * v[0] + v[2] * v[2]);
if (d == 0)
@ -404,7 +404,7 @@ namespace DotRecast.Detour.Crowd
}
// vector normalization that ignores the y-component.
Vector3f dtRotate2D(float[] v, float ang)
Vector3f DtRotate2D(float[] v, float ang)
{
Vector3f dest = new Vector3f();
float c = (float)Math.Cos(ang);
@ -417,10 +417,10 @@ namespace DotRecast.Detour.Crowd
static readonly float DT_PI = 3.14159265f;
public Tuple<int, Vector3f> sampleVelocityAdaptive(Vector3f pos, float rad, float vmax, Vector3f vel,
public Tuple<int, Vector3f> SampleVelocityAdaptive(Vector3f pos, float rad, float vmax, Vector3f vel,
Vector3f dvel, ObstacleAvoidanceParams option, ObstacleAvoidanceDebugData debug)
{
prepare(pos, dvel);
Prepare(pos, dvel);
m_params = option;
m_invHorizTime = 1.0f / m_params.horizTime;
m_vmax = vmax;
@ -429,7 +429,7 @@ namespace DotRecast.Detour.Crowd
Vector3f nvel = Vector3f.Zero;
if (debug != null)
debug.reset();
debug.Reset();
// Build sampling pattern aligned to desired velocity.
float[] pat = new float[(DT_MAX_PATTERN_DIVS * DT_MAX_PATTERN_RINGS + 1) * 2];
@ -439,17 +439,17 @@ namespace DotRecast.Detour.Crowd
int nrings = m_params.adaptiveRings;
int depth = m_params.adaptiveDepth;
int nd = clamp(ndivs, 1, DT_MAX_PATTERN_DIVS);
int nr = clamp(nrings, 1, DT_MAX_PATTERN_RINGS);
int nd = Clamp(ndivs, 1, DT_MAX_PATTERN_DIVS);
int nr = Clamp(nrings, 1, DT_MAX_PATTERN_RINGS);
float da = (1.0f / nd) * DT_PI * 2;
float ca = (float)Math.Cos(da);
float sa = (float)Math.Sin(da);
// desired direction
float[] ddir = new float[6];
vCopy(ddir, dvel);
dtNormalize2D(ddir);
Vector3f rotated = dtRotate2D(ddir, da * 0.5f); // rotated by da/2
VCopy(ddir, dvel);
DtNormalize2D(ddir);
Vector3f rotated = DtRotate2D(ddir, da * 0.5f); // rotated by da/2
ddir[3] = rotated.x;
ddir[4] = rotated.y;
ddir[5] = rotated.z;
@ -493,7 +493,7 @@ namespace DotRecast.Detour.Crowd
// Start sampling.
float cr = vmax * (1.0f - m_params.velBias);
Vector3f res = new Vector3f();
vSet(ref res, dvel.x * m_params.velBias, 0, dvel.z * m_params.velBias);
VSet(ref res, dvel.x * m_params.velBias, 0, dvel.z * m_params.velBias);
int ns = 0;
for (int k = 0; k < depth; ++k)
{
@ -504,11 +504,11 @@ namespace DotRecast.Detour.Crowd
for (int i = 0; i < npat; ++i)
{
Vector3f vcand = new Vector3f();
vSet(ref vcand, res.x + pat[i * 2 + 0] * cr, 0f, res.z + pat[i * 2 + 1] * cr);
if (sqr(vcand.x) + sqr(vcand.z) > sqr(vmax + 0.001f))
VSet(ref vcand, res.x + pat[i * 2 + 0] * cr, 0f, res.z + pat[i * 2 + 1] * cr);
if (Sqr(vcand.x) + Sqr(vcand.z) > Sqr(vmax + 0.001f))
continue;
float penalty = processSample(vcand, cr / 10, pos, rad, vel, dvel, minPenalty, debug);
float penalty = ProcessSample(vcand, cr / 10, pos, rad, vel, dvel, minPenalty, debug);
ns++;
if (penalty < minPenalty)
{

View File

@ -30,17 +30,17 @@ namespace DotRecast.Detour.Crowd
/**
* Represents a dynamic polygon corridor used to plan agent movement.
*
* The corridor is loaded with a path, usually obtained from a #NavMeshQuery::findPath() query. The corridor is then
* The corridor is loaded with a path, usually obtained from a #NavMeshQuery::FindPath() query. The corridor is then
* used to plan local movement, with the corridor automatically updating as needed to deal with inaccurate agent
* locomotion.
*
* Example of a common use case:
*
* -# Construct the corridor object and call -# Obtain a path from a #dtNavMeshQuery object. -# Use #reset() to set the
* agent's current position. (At the beginning of the path.) -# Use #setCorridor() to load the path and target. -# Use
* #findCorners() to plan movement. (This handles dynamic path straightening.) -# Use #movePosition() to feed agent
* -# Construct the corridor object and call -# Obtain a path from a #dtNavMeshQuery object. -# Use #Reset() to set the
* agent's current position. (At the beginning of the path.) -# Use #SetCorridor() to load the path and target. -# Use
* #FindCorners() to plan movement. (This handles dynamic path straightening.) -# Use #MovePosition() to feed agent
* movement back into the corridor. (The corridor will automatically adjust as needed.) -# If the target is moving, use
* #moveTargetPosition() to update the end of the corridor. (The corridor will automatically adjust as needed.) -#
* #MoveTargetPosition() to update the end of the corridor. (The corridor will automatically adjust as needed.) -#
* Repeat the previous 3 steps to continue to move the agent.
*
* The corridor position and target are always constrained to the navigation mesh.
@ -55,13 +55,13 @@ namespace DotRecast.Detour.Crowd
* Every time a move function is used there is a chance that the path will become non-optimial. Basically, the further
* the target is moved from its original location, and the further the position is moved outside the original corridor,
* the more likely the path will become non-optimal. This issue can be addressed by periodically running the
* #optimizePathTopology() and #optimizePathVisibility() methods.
* #OptimizePathTopology() and #OptimizePathVisibility() methods.
*
* All local mesh queries have distance limitations. (Review the #dtNavMeshQuery methods for details.) So the most
* accurate use case is to move the position and target in small increments. If a large increment is used, then the
* corridor may not be able to accurately find the new location. Because of this limiation, if a position is moved in a
* large increment, then compare the desired and resulting polygon references. If the two do not match, then path
* replanning may be needed. E.g. If you move the target, check #getLastPoly() to see if it is the expected polygon.
* replanning may be needed. E.g. If you move the target, check #GetLastPoly() to see if it is the expected polygon.
*
*/
public class PathCorridor
@ -70,7 +70,7 @@ namespace DotRecast.Detour.Crowd
private Vector3f m_target = new Vector3f();
private List<long> m_path;
protected List<long> mergeCorridorStartMoved(List<long> path, List<long> visited)
protected List<long> MergeCorridorStartMoved(List<long> path, List<long> visited)
{
int furthestPath = -1;
int furthestVisited = -1;
@ -115,7 +115,7 @@ namespace DotRecast.Detour.Crowd
return result;
}
protected List<long> mergeCorridorEndMoved(List<long> path, List<long> visited)
protected List<long> MergeCorridorEndMoved(List<long> path, List<long> visited)
{
int furthestPath = -1;
int furthestVisited = -1;
@ -152,7 +152,7 @@ namespace DotRecast.Detour.Crowd
return result;
}
protected List<long> mergeCorridorStartShortcut(List<long> path, List<long> visited)
protected List<long> MergeCorridorStartShortcut(List<long> path, List<long> visited)
{
int furthestPath = -1;
int furthestVisited = -1;
@ -207,7 +207,7 @@ namespace DotRecast.Detour.Crowd
* @param pos
* The new position in the corridor. [(x, y, z)]
*/
public void reset(long refs, Vector3f pos)
public void Reset(long refs, Vector3f pos)
{
m_path.Clear();
m_path.Add(refs);
@ -215,7 +215,7 @@ namespace DotRecast.Detour.Crowd
m_target = pos;
}
private static readonly float MIN_TARGET_DIST = sqr(0.01f);
private static readonly float MIN_TARGET_DIST = Sqr(0.01f);
/**
* Finds the corners in the corridor from the position toward the target. (The straightened path.)
@ -234,10 +234,10 @@ namespace DotRecast.Detour.Crowd
* @param[in] navquery The query object used to build the corridor.
* @return Corners
*/
public List<StraightPathItem> findCorners(int maxCorners, NavMeshQuery navquery, QueryFilter filter)
public List<StraightPathItem> FindCorners(int maxCorners, NavMeshQuery navquery, QueryFilter filter)
{
List<StraightPathItem> path = new List<StraightPathItem>();
Result<List<StraightPathItem>> result = navquery.findStraightPath(m_pos, m_target, m_path, maxCorners, 0);
Result<List<StraightPathItem>> result = navquery.FindStraightPath(m_pos, m_target, m_path, maxCorners, 0);
if (result.Succeeded())
{
path = result.result;
@ -245,8 +245,8 @@ namespace DotRecast.Detour.Crowd
int start = 0;
foreach (StraightPathItem spi in path)
{
if ((spi.getFlags() & NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0
|| vDist2DSqr(spi.getPos(), m_pos) > MIN_TARGET_DIST)
if ((spi.GetFlags() & NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0
|| VDist2DSqr(spi.GetPos(), m_pos) > MIN_TARGET_DIST)
{
break;
}
@ -259,7 +259,7 @@ namespace DotRecast.Detour.Crowd
for (int i = start; i < path.Count; i++)
{
StraightPathItem spi = path[i];
if ((spi.getFlags() & NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
if ((spi.GetFlags() & NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
{
end = i + 1;
break;
@ -299,10 +299,10 @@ namespace DotRecast.Detour.Crowd
* @param filter
* The filter to apply to the operation.
*/
public void optimizePathVisibility(Vector3f next, float pathOptimizationRange, NavMeshQuery navquery, QueryFilter filter)
public void OptimizePathVisibility(Vector3f next, float pathOptimizationRange, NavMeshQuery navquery, QueryFilter filter)
{
// Clamp the ray to max distance.
float dist = vDist2D(m_pos, next);
float dist = VDist2D(m_pos, next);
// If too close to the goal, do not try to optimize.
if (dist < 0.01f)
@ -315,15 +315,15 @@ namespace DotRecast.Detour.Crowd
dist = Math.Min(dist + 0.01f, pathOptimizationRange);
// Adjust ray length.
var delta = vSub(next, m_pos);
Vector3f goal = vMad(m_pos, delta, pathOptimizationRange / dist);
var delta = VSub(next, m_pos);
Vector3f goal = VMad(m_pos, delta, pathOptimizationRange / dist);
Result<RaycastHit> rc = navquery.raycast(m_path[0], m_pos, goal, filter, 0, 0);
Result<RaycastHit> rc = navquery.Raycast(m_path[0], m_pos, goal, filter, 0, 0);
if (rc.Succeeded())
{
if (rc.result.path.Count > 1 && rc.result.t > 0.99f)
{
m_path = mergeCorridorStartShortcut(m_path, rc.result.path);
m_path = MergeCorridorStartShortcut(m_path, rc.result.path);
}
}
}
@ -344,27 +344,27 @@ namespace DotRecast.Detour.Crowd
* The filter to apply to the operation.
*
*/
public bool optimizePathTopology(NavMeshQuery navquery, QueryFilter filter, int maxIterations)
public bool OptimizePathTopology(NavMeshQuery navquery, QueryFilter filter, int maxIterations)
{
if (m_path.Count < 3)
{
return false;
}
navquery.initSlicedFindPath(m_path[0], m_path[m_path.Count - 1], m_pos, m_target, filter, 0);
navquery.updateSlicedFindPath(maxIterations);
Result<List<long>> fpr = navquery.finalizeSlicedFindPathPartial(m_path);
navquery.InitSlicedFindPath(m_path[0], m_path[m_path.Count - 1], m_pos, m_target, filter, 0);
navquery.UpdateSlicedFindPath(maxIterations);
Result<List<long>> fpr = navquery.FinalizeSlicedFindPathPartial(m_path);
if (fpr.Succeeded() && fpr.result.Count > 0)
{
m_path = mergeCorridorStartShortcut(m_path, fpr.result);
m_path = MergeCorridorStartShortcut(m_path, fpr.result);
return true;
}
return false;
}
public bool moveOverOffmeshConnection(long offMeshConRef, long[] refs, ref Vector3f start, ref Vector3f end, NavMeshQuery navquery)
public bool MoveOverOffmeshConnection(long offMeshConRef, long[] refs, ref Vector3f start, ref Vector3f end, NavMeshQuery navquery)
{
// Advance the path up to and over the off-mesh connection.
long prevRef = 0, polyRef = m_path[0];
@ -387,8 +387,8 @@ namespace DotRecast.Detour.Crowd
refs[0] = prevRef;
refs[1] = polyRef;
NavMesh nav = navquery.getAttachedNavMesh();
var startEnd = nav.getOffMeshConnectionPolyEndPoints(refs[0], refs[1]);
NavMesh nav = navquery.GetAttachedNavMesh();
var startEnd = nav.GetOffMeshConnectionPolyEndPoints(refs[0], refs[1]);
if (startEnd.Succeeded())
{
m_pos = startEnd.result.Item2;
@ -423,16 +423,16 @@ namespace DotRecast.Detour.Crowd
* @param filter
* The filter to apply to the operation.
*/
public bool movePosition(Vector3f npos, NavMeshQuery navquery, QueryFilter filter)
public bool MovePosition(Vector3f npos, NavMeshQuery navquery, QueryFilter filter)
{
// Move along navmesh and update new position.
Result<MoveAlongSurfaceResult> masResult = navquery.moveAlongSurface(m_path[0], m_pos, npos, filter);
Result<MoveAlongSurfaceResult> masResult = navquery.MoveAlongSurface(m_path[0], m_pos, npos, filter);
if (masResult.Succeeded())
{
m_path = mergeCorridorStartMoved(m_path, masResult.result.getVisited());
m_path = MergeCorridorStartMoved(m_path, masResult.result.GetVisited());
// Adjust the position to stay on top of the navmesh.
m_pos = masResult.result.getResultPos();
Result<float> hr = navquery.getPolyHeight(m_path[0], masResult.result.getResultPos());
m_pos = masResult.result.GetResultPos();
Result<float> hr = navquery.GetPolyHeight(m_path[0], masResult.result.GetResultPos());
if (hr.Succeeded())
{
m_pos.y = hr.result;
@ -461,20 +461,20 @@ namespace DotRecast.Detour.Crowd
* @param filter
* The filter to apply to the operation.
*/
public bool moveTargetPosition(Vector3f npos, NavMeshQuery navquery, QueryFilter filter)
public bool MoveTargetPosition(Vector3f npos, NavMeshQuery navquery, QueryFilter filter)
{
// Move along navmesh and update new position.
Result<MoveAlongSurfaceResult> masResult = navquery.moveAlongSurface(m_path[m_path.Count - 1], m_target, npos, filter);
Result<MoveAlongSurfaceResult> masResult = navquery.MoveAlongSurface(m_path[m_path.Count - 1], m_target, npos, filter);
if (masResult.Succeeded())
{
m_path = mergeCorridorEndMoved(m_path, masResult.result.getVisited());
m_path = MergeCorridorEndMoved(m_path, masResult.result.GetVisited());
// TODO: should we do that?
// Adjust the position to stay on top of the navmesh.
/*
* float h = m_target.y; navquery->getPolyHeight(m_path[m_npath-1],
* float h = m_target.y; navquery->GetPolyHeight(m_path[m_npath-1],
* result, &h); result.y = h;
*/
m_target = masResult.result.getResultPos();
m_target = masResult.result.GetResultPos();
return true;
}
@ -485,19 +485,19 @@ namespace DotRecast.Detour.Crowd
* Loads a new path and target into the corridor. The current corridor position is expected to be within the first
* polygon in the path. The target is expected to be in the last polygon.
*
* @warning The size of the path must not exceed the size of corridor's path buffer set during #init().
* @warning The size of the path must not exceed the size of corridor's path buffer set during #Init().
* @param target
* The target location within the last polygon of the path. [(x, y, z)]
* @param path
* The path corridor.
*/
public void setCorridor(Vector3f target, List<long> path)
public void SetCorridor(Vector3f target, List<long> path)
{
m_target = target;
m_path = new List<long>(path);
}
public void fixPathStart(long safeRef, Vector3f safePos)
public void FixPathStart(long safeRef, Vector3f safePos)
{
m_pos = safePos;
if (m_path.Count < 3 && m_path.Count > 0)
@ -516,11 +516,11 @@ namespace DotRecast.Detour.Crowd
}
}
public void trimInvalidPath(long safeRef, float[] safePos, NavMeshQuery navquery, QueryFilter filter)
public void TrimInvalidPath(long safeRef, float[] safePos, NavMeshQuery navquery, QueryFilter filter)
{
// Keep valid path as far as possible.
int n = 0;
while (n < m_path.Count && navquery.isValidPolyRef(m_path[n], filter))
while (n < m_path.Count && navquery.IsValidPolyRef(m_path[n], filter))
{
n++;
}
@ -528,7 +528,7 @@ namespace DotRecast.Detour.Crowd
if (n == 0)
{
// The first polyref is bad, use current safe values.
vCopy(ref m_pos, safePos);
VCopy(ref m_pos, safePos);
m_path.Clear();
m_path.Add(safeRef);
}
@ -539,7 +539,7 @@ namespace DotRecast.Detour.Crowd
}
// Clamp target pos to last poly
var result = navquery.closestPointOnPolyBoundary(m_path[m_path.Count - 1], m_target);
var result = navquery.ClosestPointOnPolyBoundary(m_path[m_path.Count - 1], m_target);
if (result.Succeeded())
{
m_target = result.result;
@ -559,13 +559,13 @@ namespace DotRecast.Detour.Crowd
* The filter to apply to the operation.
* @return
*/
public bool isValid(int maxLookAhead, NavMeshQuery navquery, QueryFilter filter)
public bool IsValid(int maxLookAhead, NavMeshQuery navquery, QueryFilter filter)
{
// Check that all polygons still pass query filter.
int n = Math.Min(m_path.Count, maxLookAhead);
for (int i = 0; i < n; ++i)
{
if (!navquery.isValidPolyRef(m_path[i], filter))
if (!navquery.IsValidPolyRef(m_path[i], filter))
{
return false;
}
@ -579,7 +579,7 @@ namespace DotRecast.Detour.Crowd
*
* @return The current position within the corridor.
*/
public Vector3f getPos()
public Vector3f GetPos()
{
return m_pos;
}
@ -589,7 +589,7 @@ namespace DotRecast.Detour.Crowd
*
* @return The current target within the corridor.
*/
public Vector3f getTarget()
public Vector3f GetTarget()
{
return m_target;
}
@ -599,7 +599,7 @@ namespace DotRecast.Detour.Crowd
*
* @return The polygon reference id of the first polygon in the corridor. (Or zero if there is no path.)
*/
public long getFirstPoly()
public long GetFirstPoly()
{
return 0 == m_path.Count ? 0 : m_path[0];
}
@ -609,7 +609,7 @@ namespace DotRecast.Detour.Crowd
*
* @return The polygon reference id of the last polygon in the corridor. (Or zero if there is no path.)
*/
public long getLastPoly()
public long GetLastPoly()
{
return 0 == m_path.Count ? 0 : m_path[m_path.Count - 1];
}
@ -617,7 +617,7 @@ namespace DotRecast.Detour.Crowd
/**
* The corridor's path.
*/
public List<long> getPath()
public List<long> GetPath()
{
return m_path;
}
@ -627,7 +627,7 @@ namespace DotRecast.Detour.Crowd
*
* @return The number of polygons in the current corridor path.
*/
public int getPathCount()
public int GetPathCount()
{
return m_path.Count;
}

View File

@ -36,7 +36,7 @@ namespace DotRecast.Detour.Crowd
this.config = config;
}
public void update(NavMesh navMesh)
public void Update(NavMesh navMesh)
{
// Update path request until there is nothing to update or up to maxIters pathfinder iterations has been
// consumed.
@ -54,32 +54,32 @@ namespace DotRecast.Detour.Crowd
if (q.result.status == null)
{
q.navQuery = new NavMeshQuery(navMesh);
q.result.status = q.navQuery.initSlicedFindPath(q.startRef, q.endRef, q.startPos, q.endPos, q.filter, 0);
q.result.status = q.navQuery.InitSlicedFindPath(q.startRef, q.endRef, q.startPos, q.endPos, q.filter, 0);
}
// Handle query in progress.
if (q.result.status.isInProgress())
if (q.result.status.IsInProgress())
{
Result<int> res = q.navQuery.updateSlicedFindPath(iterCount);
Result<int> res = q.navQuery.UpdateSlicedFindPath(iterCount);
q.result.status = res.status;
iterCount -= res.result;
}
if (q.result.status.isSuccess())
if (q.result.status.IsSuccess())
{
Result<List<long>> path = q.navQuery.finalizeSlicedFindPath();
Result<List<long>> path = q.navQuery.FinalizeSlicedFindPath();
q.result.status = path.status;
q.result.path = path.result;
}
if (!(q.result.status.isFailed() || q.result.status.isSuccess()))
if (!(q.result.status.IsFailed() || q.result.status.IsSuccess()))
{
queue.AddFirst(q);
}
}
}
public PathQueryResult request(long startRef, long endRef, Vector3f startPos, Vector3f endPos, QueryFilter filter)
public PathQueryResult Request(long startRef, long endRef, Vector3f startPos, Vector3f endPos, QueryFilter filter)
{
if (queue.Count >= config.pathQueueSize)
{

View File

@ -49,12 +49,12 @@ namespace DotRecast.Detour.Crowd.Tracking
m_tpen = new float[m_maxSamples];
}
public void reset()
public void Reset()
{
m_nsamples = 0;
}
void normalizeArray(float[] arr, int n)
void NormalizeArray(float[] arr, int n)
{
// Normalize penaly range.
float minPen = float.MaxValue;
@ -68,19 +68,19 @@ namespace DotRecast.Detour.Crowd.Tracking
float penRange = maxPen - minPen;
float s = penRange > 0.001f ? (1.0f / penRange) : 1;
for (int i = 0; i < n; ++i)
arr[i] = clamp((arr[i] - minPen) * s, 0.0f, 1.0f);
arr[i] = Clamp((arr[i] - minPen) * s, 0.0f, 1.0f);
}
public void normalizeSamples()
public void NormalizeSamples()
{
normalizeArray(m_pen, m_nsamples);
normalizeArray(m_vpen, m_nsamples);
normalizeArray(m_vcpen, m_nsamples);
normalizeArray(m_spen, m_nsamples);
normalizeArray(m_tpen, m_nsamples);
NormalizeArray(m_pen, m_nsamples);
NormalizeArray(m_vpen, m_nsamples);
NormalizeArray(m_vcpen, m_nsamples);
NormalizeArray(m_spen, m_nsamples);
NormalizeArray(m_tpen, m_nsamples);
}
public void addSample(Vector3f vel, float ssize, float pen, float vpen, float vcpen, float spen, float tpen)
public void AddSample(Vector3f vel, float ssize, float pen, float vpen, float vcpen, float spen, float tpen)
{
if (m_nsamples >= m_maxSamples)
return;
@ -96,12 +96,12 @@ namespace DotRecast.Detour.Crowd.Tracking
m_nsamples++;
}
public int getSampleCount()
public int GetSampleCount()
{
return m_nsamples;
}
public Vector3f getSampleVelocity(int i)
public Vector3f GetSampleVelocity(int i)
{
Vector3f vel = new Vector3f();
vel.x = m_vel[i * 3];
@ -110,32 +110,32 @@ namespace DotRecast.Detour.Crowd.Tracking
return vel;
}
public float getSampleSize(int i)
public float GetSampleSize(int i)
{
return m_ssize[i];
}
public float getSamplePenalty(int i)
public float GetSamplePenalty(int i)
{
return m_pen[i];
}
public float getSampleDesiredVelocityPenalty(int i)
public float GetSampleDesiredVelocityPenalty(int i)
{
return m_vpen[i];
}
public float getSampleCurrentVelocityPenalty(int i)
public float GetSampleCurrentVelocityPenalty(int i)
{
return m_vcpen[i];
}
public float getSamplePreferredSidePenalty(int i)
public float GetSamplePreferredSidePenalty(int i)
{
return m_spen[i];
}
public float getSampleCollisionTimePenalty(int i)
public float GetSampleCollisionTimePenalty(int i)
{
return m_tpen[i];
}

View File

@ -34,14 +34,14 @@ namespace DotRecast.Detour.Dynamic
_affectedTiles = affectedTiles;
}
public ICollection<DynamicTile> affectedTiles()
public ICollection<DynamicTile> AffectedTiles()
{
return _affectedTiles;
}
public void process(DynamicTile tile)
public void Process(DynamicTile tile)
{
tile.addCollider(colliderId, collider);
tile.AddCollider(colliderId, collider);
}
}
}

View File

@ -33,11 +33,11 @@ namespace DotRecast.Detour.Dynamic.Colliders
this._bounds = bounds;
}
public float[] bounds()
public float[] Bounds()
{
return _bounds;
}
public abstract void rasterize(Heightfield hf, Telemetry telemetry);
public abstract void Rasterize(Heightfield hf, Telemetry telemetry);
}
}

View File

@ -28,13 +28,13 @@ namespace DotRecast.Detour.Dynamic.Colliders
private readonly Vector3f[] halfEdges;
public BoxCollider(Vector3f center, Vector3f[] halfEdges, int area, float flagMergeThreshold) :
base(area, flagMergeThreshold, bounds(center, halfEdges))
base(area, flagMergeThreshold, Bounds(center, halfEdges))
{
this.center = center;
this.halfEdges = halfEdges;
}
private static float[] bounds(Vector3f center, Vector3f[] halfEdges)
private static float[] Bounds(Vector3f center, Vector3f[] halfEdges)
{
float[] bounds = new float[]
{
@ -60,13 +60,13 @@ namespace DotRecast.Detour.Dynamic.Colliders
return bounds;
}
public override void rasterize(Heightfield hf, Telemetry telemetry)
public override void Rasterize(Heightfield hf, Telemetry telemetry)
{
RecastFilledVolumeRasterization.rasterizeBox(
RecastFilledVolumeRasterization.RasterizeBox(
hf, center, halfEdges, area, (int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
}
public static Vector3f[] getHalfEdges(Vector3f up, Vector3f forward, Vector3f extent)
public static Vector3f[] GetHalfEdges(Vector3f up, Vector3f forward, Vector3f extent)
{
Vector3f[] halfEdges =
{
@ -74,11 +74,11 @@ namespace DotRecast.Detour.Dynamic.Colliders
Vector3f.Of(up.x, up.y, up.z),
Vector3f.Zero
};
RecastVectors.normalize(ref halfEdges[1]);
RecastVectors.cross(ref halfEdges[0], up, forward);
RecastVectors.normalize(ref halfEdges[0]);
RecastVectors.cross(ref halfEdges[2], halfEdges[0], up);
RecastVectors.normalize(ref halfEdges[2]);
RecastVectors.Normalize(ref halfEdges[1]);
RecastVectors.Cross(ref halfEdges[0], up, forward);
RecastVectors.Normalize(ref halfEdges[0]);
RecastVectors.Cross(ref halfEdges[2], halfEdges[0], up);
RecastVectors.Normalize(ref halfEdges[2]);
halfEdges[0].x *= extent.x;
halfEdges[0].y *= extent.x;
halfEdges[0].z *= extent.x;

View File

@ -29,20 +29,20 @@ namespace DotRecast.Detour.Dynamic.Colliders
private readonly float radius;
public CapsuleCollider(Vector3f start, Vector3f end, float radius, int area, float flagMergeThreshold) :
base(area, flagMergeThreshold, bounds(start, end, radius))
base(area, flagMergeThreshold, Bounds(start, end, radius))
{
this.start = start;
this.end = end;
this.radius = radius;
}
public override void rasterize(Heightfield hf, Telemetry telemetry)
public override void Rasterize(Heightfield hf, Telemetry telemetry)
{
RecastFilledVolumeRasterization.rasterizeCapsule(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
RecastFilledVolumeRasterization.RasterizeCapsule(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
telemetry);
}
private static float[] bounds(Vector3f start, Vector3f end, float radius)
private static float[] Bounds(Vector3f start, Vector3f end, float radius)
{
return new float[]
{

View File

@ -22,7 +22,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
{
public interface Collider
{
float[] bounds();
void rasterize(Heightfield hf, Telemetry telemetry);
float[] Bounds();
void Rasterize(Heightfield hf, Telemetry telemetry);
}
}

View File

@ -31,21 +31,21 @@ namespace DotRecast.Detour.Dynamic.Colliders
public CompositeCollider(List<Collider> colliders)
{
this.colliders = colliders;
_bounds = bounds(colliders);
_bounds = Bounds(colliders);
}
public CompositeCollider(params Collider[] colliders)
{
this.colliders = colliders.ToList();
_bounds = bounds(this.colliders);
_bounds = Bounds(this.colliders);
}
public float[] bounds()
public float[] Bounds()
{
return _bounds;
}
private static float[] bounds(List<Collider> colliders)
private static float[] Bounds(List<Collider> colliders)
{
float[] bounds = new float[]
{
@ -54,7 +54,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
};
foreach (Collider collider in colliders)
{
float[] b = collider.bounds();
float[] b = collider.Bounds();
bounds[0] = Math.Min(bounds[0], b[0]);
bounds[1] = Math.Min(bounds[1], b[1]);
bounds[2] = Math.Min(bounds[2], b[2]);
@ -66,10 +66,10 @@ namespace DotRecast.Detour.Dynamic.Colliders
return bounds;
}
public void rasterize(Heightfield hf, Telemetry telemetry)
public void Rasterize(Heightfield hf, Telemetry telemetry)
{
foreach (var c in colliders)
c.rasterize(hf, telemetry);
c.Rasterize(hf, telemetry);
}
}
}

View File

@ -27,7 +27,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
private readonly int[] triangles;
public ConvexTrimeshCollider(float[] vertices, int[] triangles, int area, float flagMergeThreshold) :
base(area, flagMergeThreshold, TrimeshCollider.computeBounds(vertices))
base(area, flagMergeThreshold, TrimeshCollider.ComputeBounds(vertices))
{
this.vertices = vertices;
this.triangles = triangles;
@ -40,9 +40,9 @@ namespace DotRecast.Detour.Dynamic.Colliders
this.triangles = triangles;
}
public override void rasterize(Heightfield hf, Telemetry telemetry)
public override void Rasterize(Heightfield hf, Telemetry telemetry)
{
RecastFilledVolumeRasterization.rasterizeConvex(hf, vertices, triangles, area,
RecastFilledVolumeRasterization.RasterizeConvex(hf, vertices, triangles, area,
(int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
}
}

View File

@ -29,20 +29,20 @@ namespace DotRecast.Detour.Dynamic.Colliders
private readonly float radius;
public CylinderCollider(Vector3f start, Vector3f end, float radius, int area, float flagMergeThreshold) :
base(area, flagMergeThreshold, bounds(start, end, radius))
base(area, flagMergeThreshold, Bounds(start, end, radius))
{
this.start = start;
this.end = end;
this.radius = radius;
}
public override void rasterize(Heightfield hf, Telemetry telemetry)
public override void Rasterize(Heightfield hf, Telemetry telemetry)
{
RecastFilledVolumeRasterization.rasterizeCylinder(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
RecastFilledVolumeRasterization.RasterizeCylinder(hf, start, end, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
telemetry);
}
private static float[] bounds(Vector3f start, Vector3f end, float radius)
private static float[] Bounds(Vector3f start, Vector3f end, float radius)
{
return new float[]
{

View File

@ -28,19 +28,19 @@ namespace DotRecast.Detour.Dynamic.Colliders
private readonly float radius;
public SphereCollider(Vector3f center, float radius, int area, float flagMergeThreshold) :
base(area, flagMergeThreshold, bounds(center, radius))
base(area, flagMergeThreshold, Bounds(center, radius))
{
this.center = center;
this.radius = radius;
}
public override void rasterize(Heightfield hf, Telemetry telemetry)
public override void Rasterize(Heightfield hf, Telemetry telemetry)
{
RecastFilledVolumeRasterization.rasterizeSphere(hf, center, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
RecastFilledVolumeRasterization.RasterizeSphere(hf, center, radius, area, (int)Math.Floor(flagMergeThreshold / hf.ch),
telemetry);
}
private static float[] bounds(Vector3f center, float radius)
private static float[] Bounds(Vector3f center, float radius)
{
return new float[]
{

View File

@ -27,7 +27,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
private readonly int[] triangles;
public TrimeshCollider(float[] vertices, int[] triangles, int area, float flagMergeThreshold) :
base(area, flagMergeThreshold, computeBounds(vertices))
base(area, flagMergeThreshold, ComputeBounds(vertices))
{
this.vertices = vertices;
this.triangles = triangles;
@ -40,7 +40,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
this.triangles = triangles;
}
public static float[] computeBounds(float[] vertices)
public static float[] ComputeBounds(float[] vertices)
{
float[] bounds = new float[] { vertices[0], vertices[1], vertices[2], vertices[0], vertices[1], vertices[2] };
for (int i = 3; i < vertices.Length; i += 3)
@ -56,11 +56,11 @@ namespace DotRecast.Detour.Dynamic.Colliders
return bounds;
}
public override void rasterize(Heightfield hf, Telemetry telemetry)
public override void Rasterize(Heightfield hf, Telemetry telemetry)
{
for (int i = 0; i < triangles.Length; i += 3)
{
RecastRasterization.rasterizeTriangle(hf, vertices, triangles[i], triangles[i + 1], triangles[i + 2], area,
RecastRasterization.RasterizeTriangle(hf, vertices, triangles[i], triangles[i + 1], triangles[i + 2], area,
(int)Math.Floor(flagMergeThreshold / hf.ch), telemetry);
}
}

View File

@ -68,14 +68,14 @@ namespace DotRecast.Detour.Dynamic
navMeshParams.maxPolys = 0x8000;
foreach (var t in voxelFile.tiles)
{
_tiles.Add(lookupKey(t.tileX, t.tileZ), new DynamicTile(t));
_tiles.Add(LookupKey(t.tileX, t.tileZ), new DynamicTile(t));
}
;
telemetry = new Telemetry();
}
public NavMesh navMesh()
public NavMesh NavMesh()
{
return _navMesh;
}
@ -83,64 +83,64 @@ namespace DotRecast.Detour.Dynamic
/**
* Voxel queries require checkpoints to be enabled in {@link DynamicNavMeshConfig}
*/
public VoxelQuery voxelQuery()
public VoxelQuery VoxelQuery()
{
return new VoxelQuery(navMeshParams.orig, navMeshParams.tileWidth, navMeshParams.tileHeight, lookupHeightfield);
return new VoxelQuery(navMeshParams.orig, navMeshParams.tileWidth, navMeshParams.tileHeight, LookupHeightfield);
}
private Heightfield lookupHeightfield(int x, int z)
private Heightfield LookupHeightfield(int x, int z)
{
return getTileAt(x, z)?.checkpoint.heightfield;
return GetTileAt(x, z)?.checkpoint.heightfield;
}
public long addCollider(Collider collider)
public long AddCollider(Collider collider)
{
long cid = currentColliderId.IncrementAndGet();
updateQueue.Add(new AddColliderQueueItem(cid, collider, getTiles(collider.bounds())));
updateQueue.Add(new AddColliderQueueItem(cid, collider, GetTiles(collider.Bounds())));
return cid;
}
public void removeCollider(long colliderId)
public void RemoveCollider(long colliderId)
{
updateQueue.Add(new RemoveColliderQueueItem(colliderId, getTilesByCollider(colliderId)));
updateQueue.Add(new RemoveColliderQueueItem(colliderId, GetTilesByCollider(colliderId)));
}
/**
* Perform full build of the nav mesh
*/
public void build()
public void Build()
{
processQueue();
rebuild(_tiles.Values);
ProcessQueue();
Rebuild(_tiles.Values);
}
/**
* Perform incremental update of the nav mesh
*/
public bool update()
public bool Update()
{
return rebuild(processQueue());
return Rebuild(ProcessQueue());
}
private bool rebuild(ICollection<DynamicTile> stream)
private bool Rebuild(ICollection<DynamicTile> stream)
{
foreach (var dynamicTile in stream)
rebuild(dynamicTile);
return updateNavMesh();
Rebuild(dynamicTile);
return UpdateNavMesh();
}
private HashSet<DynamicTile> processQueue()
private HashSet<DynamicTile> ProcessQueue()
{
var items = consumeQueue();
var items = ConsumeQueue();
foreach (var item in items)
{
process(item);
Process(item);
}
return items.SelectMany(i => i.affectedTiles()).ToHashSet();
return items.SelectMany(i => i.AffectedTiles()).ToHashSet();
}
private List<UpdateQueueItem> consumeQueue()
private List<UpdateQueueItem> ConsumeQueue()
{
List<UpdateQueueItem> items = new List<UpdateQueueItem>();
while (updateQueue.TryTake(out var item))
@ -151,38 +151,38 @@ namespace DotRecast.Detour.Dynamic
return items;
}
private void process(UpdateQueueItem item)
private void Process(UpdateQueueItem item)
{
foreach (var tile in item.affectedTiles())
foreach (var tile in item.AffectedTiles())
{
item.process(tile);
item.Process(tile);
}
}
/**
* Perform full build concurrently using the given {@link ExecutorService}
*/
public Task<bool> build(TaskFactory executor)
public Task<bool> Build(TaskFactory executor)
{
processQueue();
return rebuild(_tiles.Values, executor);
ProcessQueue();
return Rebuild(_tiles.Values, executor);
}
/**
* Perform incremental update concurrently using the given {@link ExecutorService}
*/
public Task<bool> update(TaskFactory executor)
public Task<bool> Update(TaskFactory executor)
{
return rebuild(processQueue(), executor);
return Rebuild(ProcessQueue(), executor);
}
private Task<bool> rebuild(ICollection<DynamicTile> tiles, TaskFactory executor)
private Task<bool> Rebuild(ICollection<DynamicTile> tiles, TaskFactory executor)
{
var tasks = tiles.Select(tile => executor.StartNew(() => rebuild(tile))).ToArray();
return Task.WhenAll(tasks).ContinueWith(k => updateNavMesh());
var tasks = tiles.Select(tile => executor.StartNew(() => Rebuild(tile))).ToArray();
return Task.WhenAll(tasks).ContinueWith(k => UpdateNavMesh());
}
private ICollection<DynamicTile> getTiles(float[] bounds)
private ICollection<DynamicTile> GetTiles(float[] bounds)
{
if (bounds == null)
{
@ -198,7 +198,7 @@ namespace DotRecast.Detour.Dynamic
{
for (int x = minx; x <= maxx; ++x)
{
DynamicTile tile = getTileAt(x, z);
DynamicTile tile = GetTileAt(x, z);
if (tile != null)
{
tiles.Add(tile);
@ -209,25 +209,25 @@ namespace DotRecast.Detour.Dynamic
return tiles;
}
private List<DynamicTile> getTilesByCollider(long cid)
private List<DynamicTile> GetTilesByCollider(long cid)
{
return _tiles.Values.Where(t => t.containsCollider(cid)).ToList();
return _tiles.Values.Where(t => t.ContainsCollider(cid)).ToList();
}
private void rebuild(DynamicTile tile)
private void Rebuild(DynamicTile tile)
{
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
option.walkableHeight = config.walkableHeight;
dirty = dirty | tile.build(builder, config, telemetry);
dirty = dirty | tile.Build(builder, config, telemetry);
}
private bool updateNavMesh()
private bool UpdateNavMesh()
{
if (dirty)
{
NavMesh navMesh = new NavMesh(navMeshParams, MAX_VERTS_PER_POLY);
foreach (var t in _tiles.Values)
t.addTo(navMesh);
t.AddTo(navMesh);
this._navMesh = navMesh;
dirty = false;
@ -237,24 +237,24 @@ namespace DotRecast.Detour.Dynamic
return false;
}
private DynamicTile getTileAt(int x, int z)
private DynamicTile GetTileAt(int x, int z)
{
return _tiles.TryGetValue(lookupKey(x, z), out var tile)
return _tiles.TryGetValue(LookupKey(x, z), out var tile)
? tile
: null;
}
private long lookupKey(long x, long z)
private long LookupKey(long x, long z)
{
return (z << 32) | x;
}
public List<VoxelTile> voxelTiles()
public List<VoxelTile> VoxelTiles()
{
return _tiles.Values.Select(t => t.voxelTile).ToList();
}
public List<RecastBuilderResult> recastResults()
public List<RecastBuilderResult> RecastResults()
{
return _tiles.Values.Select(t => t.recastResult).ToList();
}

View File

@ -42,31 +42,31 @@ namespace DotRecast.Detour.Dynamic
this.voxelTile = voxelTile;
}
public bool build(RecastBuilder builder, DynamicNavMeshConfig config, Telemetry telemetry)
public bool Build(RecastBuilder builder, DynamicNavMeshConfig config, Telemetry telemetry)
{
if (dirty)
{
Heightfield heightfield = buildHeightfield(config, telemetry);
RecastBuilderResult r = buildRecast(builder, config, voxelTile, heightfield, telemetry);
NavMeshDataCreateParams option = navMeshCreateParams(voxelTile.tileX, voxelTile.tileZ, voxelTile.cellSize,
Heightfield heightfield = BuildHeightfield(config, telemetry);
RecastBuilderResult r = BuildRecast(builder, config, voxelTile, heightfield, telemetry);
NavMeshDataCreateParams option = NavMeshCreateParams(voxelTile.tileX, voxelTile.tileZ, voxelTile.cellSize,
voxelTile.cellHeight, config, r);
meshData = NavMeshBuilder.createNavMeshData(option);
meshData = NavMeshBuilder.CreateNavMeshData(option);
return true;
}
return false;
}
private Heightfield buildHeightfield(DynamicNavMeshConfig config, Telemetry telemetry)
private Heightfield BuildHeightfield(DynamicNavMeshConfig config, Telemetry telemetry)
{
ICollection<long> rasterizedColliders = checkpoint != null ? checkpoint.colliders : ImmutableHashSet<long>.Empty;
Heightfield heightfield = checkpoint != null ? checkpoint.heightfield : voxelTile.heightfield();
Heightfield heightfield = checkpoint != null ? checkpoint.heightfield : voxelTile.Heightfield();
foreach (var (cid, c) in colliders)
{
if (!rasterizedColliders.Contains(cid))
{
heightfield.bmax.y = Math.Max(heightfield.bmax.y, c.bounds()[4] + heightfield.ch * 2);
c.rasterize(heightfield, telemetry);
heightfield.bmax.y = Math.Max(heightfield.bmax.y, c.Bounds()[4] + heightfield.ch * 2);
c.Rasterize(heightfield, telemetry);
}
}
@ -78,7 +78,7 @@ namespace DotRecast.Detour.Dynamic
return heightfield;
}
private RecastBuilderResult buildRecast(RecastBuilder builder, DynamicNavMeshConfig config, VoxelTile vt,
private RecastBuilderResult BuildRecast(RecastBuilder builder, DynamicNavMeshConfig config, VoxelTile vt,
Heightfield heightfield, Telemetry telemetry)
{
RecastConfig rcConfig = new RecastConfig(config.useTiles, config.tileSizeX, config.tileSizeZ, vt.borderSize,
@ -87,7 +87,7 @@ namespace DotRecast.Detour.Dynamic
config.maxEdgeLen, config.maxSimplificationError,
Math.Min(DynamicNavMesh.MAX_VERTS_PER_POLY, config.vertsPerPoly), true, config.detailSampleDistance,
config.detailSampleMaxError, null);
RecastBuilderResult r = builder.build(vt.tileX, vt.tileZ, null, rcConfig, heightfield, telemetry);
RecastBuilderResult r = builder.Build(vt.tileX, vt.tileZ, null, rcConfig, heightfield, telemetry);
if (config.keepIntermediateResults)
{
recastResult = r;
@ -96,18 +96,18 @@ namespace DotRecast.Detour.Dynamic
return r;
}
public void addCollider(long cid, Collider collider)
public void AddCollider(long cid, Collider collider)
{
colliders[cid] = collider;
dirty = true;
}
public bool containsCollider(long cid)
public bool ContainsCollider(long cid)
{
return colliders.ContainsKey(cid);
}
public void removeCollider(long colliderId)
public void RemoveCollider(long colliderId)
{
if (colliders.TryRemove(colliderId, out var collider))
{
@ -116,11 +116,11 @@ namespace DotRecast.Detour.Dynamic
}
}
private NavMeshDataCreateParams navMeshCreateParams(int tilex, int tileZ, float cellSize, float cellHeight,
private NavMeshDataCreateParams NavMeshCreateParams(int tilex, int tileZ, float cellSize, float cellHeight,
DynamicNavMeshConfig config, RecastBuilderResult rcResult)
{
PolyMesh m_pmesh = rcResult.getMesh();
PolyMeshDetail m_dmesh = rcResult.getMeshDetail();
PolyMesh m_pmesh = rcResult.GetMesh();
PolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
for (int i = 0; i < m_pmesh.npolys; ++i)
{
@ -164,15 +164,15 @@ namespace DotRecast.Detour.Dynamic
return option;
}
public void addTo(NavMesh navMesh)
public void AddTo(NavMesh navMesh)
{
if (meshData != null)
{
id = navMesh.addTile(meshData, 0, 0);
id = navMesh.AddTile(meshData, 0, 0);
}
else
{
navMesh.removeTile(id);
navMesh.RemoveTile(id);
id = 0;
}
}

View File

@ -30,10 +30,10 @@ namespace DotRecast.Detour.Dynamic
public DynamicTileCheckpoint(Heightfield heightfield, ISet<long> colliders)
{
this.colliders = colliders;
this.heightfield = clone(heightfield);
this.heightfield = Clone(heightfield);
}
private Heightfield clone(Heightfield source)
private Heightfield Clone(Heightfield source)
{
Heightfield clone = new Heightfield(source.width, source.height, source.bmin, source.bmax, source.cs,
source.ch, source.borderSize);

View File

@ -22,39 +22,39 @@ namespace DotRecast.Detour.Dynamic.Io
{
public static class ByteUtils
{
public static int getInt(byte[] data, int position, ByteOrder order)
public static int GetInt(byte[] data, int position, ByteOrder order)
{
return order == ByteOrder.BIG_ENDIAN ? getIntBE(data, position) : getIntLE(data, position);
return order == ByteOrder.BIG_ENDIAN ? GetIntBE(data, position) : GetIntLE(data, position);
}
public static int getIntBE(byte[] data, int position)
public static int GetIntBE(byte[] data, int position)
{
return ((data[position] & 0xff) << 24) | ((data[position + 1] & 0xff) << 16) | ((data[position + 2] & 0xff) << 8)
| (data[position + 3] & 0xff);
}
public static int getIntLE(byte[] data, int position)
public static int GetIntLE(byte[] data, int position)
{
return ((data[position + 3] & 0xff) << 24) | ((data[position + 2] & 0xff) << 16) | ((data[position + 1] & 0xff) << 8)
| (data[position] & 0xff);
}
public static int getShort(byte[] data, int position, ByteOrder order)
public static int GetShort(byte[] data, int position, ByteOrder order)
{
return order == ByteOrder.BIG_ENDIAN ? getShortBE(data, position) : getShortLE(data, position);
return order == ByteOrder.BIG_ENDIAN ? GetShortBE(data, position) : GetShortLE(data, position);
}
public static int getShortBE(byte[] data, int position)
public static int GetShortBE(byte[] data, int position)
{
return ((data[position] & 0xff) << 8) | (data[position + 1] & 0xff);
}
public static int getShortLE(byte[] data, int position)
public static int GetShortLE(byte[] data, int position)
{
return ((data[position + 1] & 0xff) << 8) | (data[position] & 0xff);
}
public static int putInt(int value, byte[] data, int position, ByteOrder order)
public static int PutInt(int value, byte[] data, int position, ByteOrder order)
{
if (order == ByteOrder.BIG_ENDIAN)
{
@ -74,7 +74,7 @@ namespace DotRecast.Detour.Dynamic.Io
return position + 4;
}
public static int putShort(int value, byte[] data, int position, ByteOrder order)
public static int PutShort(int value, byte[] data, int position, ByteOrder order)
{
if (order == ByteOrder.BIG_ENDIAN)
{

View File

@ -24,17 +24,17 @@ namespace DotRecast.Detour.Dynamic.Io
{
public class LZ4VoxelTileCompressor
{
public byte[] decompress(byte[] data)
public byte[] Decompress(byte[] data)
{
int compressedSize = ByteUtils.getIntBE(data, 0);
int compressedSize = ByteUtils.GetIntBE(data, 0);
return LZ4Pickler.Unpickle(data.AsSpan(4, compressedSize));
}
public byte[] compress(byte[] data)
public byte[] Compress(byte[] data)
{
byte[] compressed = LZ4Pickler.Pickle(data, LZ4Level.L12_MAX);
byte[] result = new byte[4 + compressed.Length];
ByteUtils.putInt(compressed.Length, result, 0, ByteOrder.BIG_ENDIAN);
ByteUtils.PutInt(compressed.Length, result, 0, ByteOrder.BIG_ENDIAN);
Array.Copy(compressed, 0, result, 4, compressed.Length);
return result;
}

View File

@ -56,12 +56,12 @@ namespace DotRecast.Detour.Dynamic.Io
public float[] bounds = new float[6];
public readonly List<VoxelTile> tiles = new List<VoxelTile>();
public void addTile(VoxelTile tile)
public void AddTile(VoxelTile tile)
{
tiles.Add(tile);
}
public RecastConfig getConfig(VoxelTile tile, PartitionType partitionType, int maxPolyVerts, int regionMergeSize,
public RecastConfig GetConfig(VoxelTile tile, PartitionType partitionType, int maxPolyVerts, int regionMergeSize,
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
AreaModification walkbableAreaMod, bool buildMeshDetail, float detailSampleDist, float detailSampleMaxError)
{
@ -71,7 +71,7 @@ namespace DotRecast.Detour.Dynamic.Io
buildMeshDetail, detailSampleDist, detailSampleMaxError, walkbableAreaMod);
}
public static VoxelFile from(RecastConfig config, List<RecastBuilderResult> results)
public static VoxelFile From(RecastConfig config, List<RecastBuilderResult> results)
{
VoxelFile f = new VoxelFile();
f.version = 1;
@ -102,19 +102,19 @@ namespace DotRecast.Detour.Dynamic.Io
};
foreach (RecastBuilderResult r in results)
{
f.tiles.Add(new VoxelTile(r.tileX, r.tileZ, r.getSolidHeightfield()));
f.bounds[0] = Math.Min(f.bounds[0], r.getSolidHeightfield().bmin.x);
f.bounds[1] = Math.Min(f.bounds[1], r.getSolidHeightfield().bmin.y);
f.bounds[2] = Math.Min(f.bounds[2], r.getSolidHeightfield().bmin.z);
f.bounds[3] = Math.Max(f.bounds[3], r.getSolidHeightfield().bmax.x);
f.bounds[4] = Math.Max(f.bounds[4], r.getSolidHeightfield().bmax.y);
f.bounds[5] = Math.Max(f.bounds[5], r.getSolidHeightfield().bmax.z);
f.tiles.Add(new VoxelTile(r.tileX, r.tileZ, r.GetSolidHeightfield()));
f.bounds[0] = Math.Min(f.bounds[0], r.GetSolidHeightfield().bmin.x);
f.bounds[1] = Math.Min(f.bounds[1], r.GetSolidHeightfield().bmin.y);
f.bounds[2] = Math.Min(f.bounds[2], r.GetSolidHeightfield().bmin.z);
f.bounds[3] = Math.Max(f.bounds[3], r.GetSolidHeightfield().bmax.x);
f.bounds[4] = Math.Max(f.bounds[4], r.GetSolidHeightfield().bmax.y);
f.bounds[5] = Math.Max(f.bounds[5], r.GetSolidHeightfield().bmax.z);
}
return f;
}
public static VoxelFile from(DynamicNavMesh mesh)
public static VoxelFile From(DynamicNavMesh mesh)
{
VoxelFile f = new VoxelFile();
f.version = 1;
@ -144,9 +144,9 @@ namespace DotRecast.Detour.Dynamic.Io
float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity,
float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity
};
foreach (VoxelTile vt in mesh.voxelTiles())
foreach (VoxelTile vt in mesh.VoxelTiles())
{
Heightfield heightfield = vt.heightfield();
Heightfield heightfield = vt.Heightfield();
f.tiles.Add(new VoxelTile(vt.tileX, vt.tileZ, heightfield));
f.bounds[0] = Math.Min(f.bounds[0], vt.boundsMin.x);
f.bounds[1] = Math.Min(f.bounds[1], vt.boundsMin.y);

View File

@ -26,40 +26,40 @@ namespace DotRecast.Detour.Dynamic.Io
{
private readonly LZ4VoxelTileCompressor compressor = new LZ4VoxelTileCompressor();
public VoxelFile read(BinaryReader stream)
public VoxelFile Read(BinaryReader stream)
{
ByteBuffer buf = IOUtils.toByteBuffer(stream);
ByteBuffer buf = IOUtils.ToByteBuffer(stream);
VoxelFile file = new VoxelFile();
int magic = buf.getInt();
int magic = buf.GetInt();
if (magic != VoxelFile.MAGIC)
{
magic = IOUtils.swapEndianness(magic);
magic = IOUtils.SwapEndianness(magic);
if (magic != VoxelFile.MAGIC)
{
throw new IOException("Invalid magic");
}
buf.order(buf.order() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
buf.Order(buf.Order() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
}
file.version = buf.getInt();
file.version = buf.GetInt();
bool isExportedFromAstar = (file.version & VoxelFile.VERSION_EXPORTER_MASK) == 0;
bool compression = (file.version & VoxelFile.VERSION_COMPRESSION_MASK) == VoxelFile.VERSION_COMPRESSION_LZ4;
file.walkableRadius = buf.getFloat();
file.walkableHeight = buf.getFloat();
file.walkableClimb = buf.getFloat();
file.walkableSlopeAngle = buf.getFloat();
file.cellSize = buf.getFloat();
file.maxSimplificationError = buf.getFloat();
file.maxEdgeLen = buf.getFloat();
file.minRegionArea = (int)buf.getFloat();
file.walkableRadius = buf.GetFloat();
file.walkableHeight = buf.GetFloat();
file.walkableClimb = buf.GetFloat();
file.walkableSlopeAngle = buf.GetFloat();
file.cellSize = buf.GetFloat();
file.maxSimplificationError = buf.GetFloat();
file.maxEdgeLen = buf.GetFloat();
file.minRegionArea = (int)buf.GetFloat();
if (!isExportedFromAstar)
{
file.regionMergeArea = buf.getFloat();
file.vertsPerPoly = buf.getInt();
file.buildMeshDetail = buf.get() != 0;
file.detailSampleDistance = buf.getFloat();
file.detailSampleMaxError = buf.getFloat();
file.regionMergeArea = buf.GetFloat();
file.vertsPerPoly = buf.GetInt();
file.buildMeshDetail = buf.Get() != 0;
file.detailSampleDistance = buf.GetFloat();
file.detailSampleMaxError = buf.GetFloat();
}
else
{
@ -70,18 +70,18 @@ namespace DotRecast.Detour.Dynamic.Io
file.detailSampleMaxError = file.maxSimplificationError * 0.8f;
}
file.useTiles = buf.get() != 0;
file.tileSizeX = buf.getInt();
file.tileSizeZ = buf.getInt();
file.rotation.x = buf.getFloat();
file.rotation.y = buf.getFloat();
file.rotation.z = buf.getFloat();
file.bounds[0] = buf.getFloat();
file.bounds[1] = buf.getFloat();
file.bounds[2] = buf.getFloat();
file.bounds[3] = buf.getFloat();
file.bounds[4] = buf.getFloat();
file.bounds[5] = buf.getFloat();
file.useTiles = buf.Get() != 0;
file.tileSizeX = buf.GetInt();
file.tileSizeZ = buf.GetInt();
file.rotation.x = buf.GetFloat();
file.rotation.y = buf.GetFloat();
file.rotation.z = buf.GetFloat();
file.bounds[0] = buf.GetFloat();
file.bounds[1] = buf.GetFloat();
file.bounds[2] = buf.GetFloat();
file.bounds[3] = buf.GetFloat();
file.bounds[4] = buf.GetFloat();
file.bounds[5] = buf.GetFloat();
if (isExportedFromAstar)
{
// bounds are saved as center + size
@ -93,22 +93,22 @@ namespace DotRecast.Detour.Dynamic.Io
file.bounds[5] += file.bounds[2];
}
int tileCount = buf.getInt();
int tileCount = buf.GetInt();
for (int tile = 0; tile < tileCount; tile++)
{
int tileX = buf.getInt();
int tileZ = buf.getInt();
int width = buf.getInt();
int depth = buf.getInt();
int borderSize = buf.getInt();
int tileX = buf.GetInt();
int tileZ = buf.GetInt();
int width = buf.GetInt();
int depth = buf.GetInt();
int borderSize = buf.GetInt();
Vector3f boundsMin = new Vector3f();
boundsMin.x = buf.getFloat();
boundsMin.y = buf.getFloat();
boundsMin.z = buf.getFloat();
boundsMin.x = buf.GetFloat();
boundsMin.y = buf.GetFloat();
boundsMin.z = buf.GetFloat();
Vector3f boundsMax = new Vector3f();
boundsMax.x = buf.getFloat();
boundsMax.y = buf.getFloat();
boundsMax.z = buf.getFloat();
boundsMax.x = buf.GetFloat();
boundsMax.y = buf.GetFloat();
boundsMax.z = buf.GetFloat();
if (isExportedFromAstar)
{
// bounds are local
@ -120,20 +120,20 @@ namespace DotRecast.Detour.Dynamic.Io
boundsMax.z += file.bounds[2];
}
float cellSize = buf.getFloat();
float cellHeight = buf.getFloat();
int voxelSize = buf.getInt();
int position = buf.position();
float cellSize = buf.GetFloat();
float cellHeight = buf.GetFloat();
int voxelSize = buf.GetInt();
int position = buf.Position();
byte[] bytes = buf.ReadBytes(voxelSize).ToArray();
if (compression)
{
bytes = compressor.decompress(bytes);
bytes = compressor.Decompress(bytes);
}
ByteBuffer data = new ByteBuffer(bytes);
data.order(buf.order());
file.addTile(new VoxelTile(tileX, tileZ, width, depth, boundsMin, boundsMax, cellSize, cellHeight, borderSize, data));
buf.position(position + voxelSize);
data.Order(buf.Order());
file.AddTile(new VoxelTile(tileX, tileZ, width, depth, boundsMin, boundsMax, cellSize, cellHeight, borderSize, data));
buf.Position(position + voxelSize);
}
return file;

View File

@ -26,69 +26,69 @@ namespace DotRecast.Detour.Dynamic.Io
{
private readonly LZ4VoxelTileCompressor compressor = new LZ4VoxelTileCompressor();
public void write(BinaryWriter stream, VoxelFile f, bool compression)
public void Write(BinaryWriter stream, VoxelFile f, bool compression)
{
write(stream, f, VoxelFile.PREFERRED_BYTE_ORDER, compression);
Write(stream, f, VoxelFile.PREFERRED_BYTE_ORDER, compression);
}
public void write(BinaryWriter stream, VoxelFile f, ByteOrder byteOrder, bool compression)
public void Write(BinaryWriter stream, VoxelFile f, ByteOrder byteOrder, bool compression)
{
write(stream, VoxelFile.MAGIC, byteOrder);
write(stream, VoxelFile.VERSION_EXPORTER_RECAST4J | (compression ? VoxelFile.VERSION_COMPRESSION_LZ4 : 0), byteOrder);
write(stream, f.walkableRadius, byteOrder);
write(stream, f.walkableHeight, byteOrder);
write(stream, f.walkableClimb, byteOrder);
write(stream, f.walkableSlopeAngle, byteOrder);
write(stream, f.cellSize, byteOrder);
write(stream, f.maxSimplificationError, byteOrder);
write(stream, f.maxEdgeLen, byteOrder);
write(stream, f.minRegionArea, byteOrder);
write(stream, f.regionMergeArea, byteOrder);
write(stream, f.vertsPerPoly, byteOrder);
write(stream, f.buildMeshDetail);
write(stream, f.detailSampleDistance, byteOrder);
write(stream, f.detailSampleMaxError, byteOrder);
write(stream, f.useTiles);
write(stream, f.tileSizeX, byteOrder);
write(stream, f.tileSizeZ, byteOrder);
write(stream, f.rotation.x, byteOrder);
write(stream, f.rotation.y, byteOrder);
write(stream, f.rotation.z, byteOrder);
write(stream, f.bounds[0], byteOrder);
write(stream, f.bounds[1], byteOrder);
write(stream, f.bounds[2], byteOrder);
write(stream, f.bounds[3], byteOrder);
write(stream, f.bounds[4], byteOrder);
write(stream, f.bounds[5], byteOrder);
write(stream, f.tiles.Count, byteOrder);
Write(stream, VoxelFile.MAGIC, byteOrder);
Write(stream, VoxelFile.VERSION_EXPORTER_RECAST4J | (compression ? VoxelFile.VERSION_COMPRESSION_LZ4 : 0), byteOrder);
Write(stream, f.walkableRadius, byteOrder);
Write(stream, f.walkableHeight, byteOrder);
Write(stream, f.walkableClimb, byteOrder);
Write(stream, f.walkableSlopeAngle, byteOrder);
Write(stream, f.cellSize, byteOrder);
Write(stream, f.maxSimplificationError, byteOrder);
Write(stream, f.maxEdgeLen, byteOrder);
Write(stream, f.minRegionArea, byteOrder);
Write(stream, f.regionMergeArea, byteOrder);
Write(stream, f.vertsPerPoly, byteOrder);
Write(stream, f.buildMeshDetail);
Write(stream, f.detailSampleDistance, byteOrder);
Write(stream, f.detailSampleMaxError, byteOrder);
Write(stream, f.useTiles);
Write(stream, f.tileSizeX, byteOrder);
Write(stream, f.tileSizeZ, byteOrder);
Write(stream, f.rotation.x, byteOrder);
Write(stream, f.rotation.y, byteOrder);
Write(stream, f.rotation.z, byteOrder);
Write(stream, f.bounds[0], byteOrder);
Write(stream, f.bounds[1], byteOrder);
Write(stream, f.bounds[2], byteOrder);
Write(stream, f.bounds[3], byteOrder);
Write(stream, f.bounds[4], byteOrder);
Write(stream, f.bounds[5], byteOrder);
Write(stream, f.tiles.Count, byteOrder);
foreach (VoxelTile t in f.tiles)
{
writeTile(stream, t, byteOrder, compression);
WriteTile(stream, t, byteOrder, compression);
}
}
public void writeTile(BinaryWriter stream, VoxelTile tile, ByteOrder byteOrder, bool compression)
public void WriteTile(BinaryWriter stream, VoxelTile tile, ByteOrder byteOrder, bool compression)
{
write(stream, tile.tileX, byteOrder);
write(stream, tile.tileZ, byteOrder);
write(stream, tile.width, byteOrder);
write(stream, tile.depth, byteOrder);
write(stream, tile.borderSize, byteOrder);
write(stream, tile.boundsMin.x, byteOrder);
write(stream, tile.boundsMin.y, byteOrder);
write(stream, tile.boundsMin.z, byteOrder);
write(stream, tile.boundsMax.x, byteOrder);
write(stream, tile.boundsMax.y, byteOrder);
write(stream, tile.boundsMax.z, byteOrder);
write(stream, tile.cellSize, byteOrder);
write(stream, tile.cellHeight, byteOrder);
Write(stream, tile.tileX, byteOrder);
Write(stream, tile.tileZ, byteOrder);
Write(stream, tile.width, byteOrder);
Write(stream, tile.depth, byteOrder);
Write(stream, tile.borderSize, byteOrder);
Write(stream, tile.boundsMin.x, byteOrder);
Write(stream, tile.boundsMin.y, byteOrder);
Write(stream, tile.boundsMin.z, byteOrder);
Write(stream, tile.boundsMax.x, byteOrder);
Write(stream, tile.boundsMax.y, byteOrder);
Write(stream, tile.boundsMax.z, byteOrder);
Write(stream, tile.cellSize, byteOrder);
Write(stream, tile.cellHeight, byteOrder);
byte[] bytes = tile.spanData;
if (compression)
{
bytes = compressor.compress(bytes);
bytes = compressor.Compress(bytes);
}
write(stream, bytes.Length, byteOrder);
Write(stream, bytes.Length, byteOrder);
stream.Write(bytes);
}
}

View File

@ -48,7 +48,7 @@ namespace DotRecast.Detour.Dynamic.Io
this.cellSize = cellSize;
this.cellHeight = cellHeight;
this.borderSize = borderSize;
spanData = toByteArray(buffer, width, depth, VoxelFile.PREFERRED_BYTE_ORDER);
spanData = ToByteArray(buffer, width, depth, VoxelFile.PREFERRED_BYTE_ORDER);
}
public VoxelTile(int tileX, int tileZ, Heightfield heightfield)
@ -62,15 +62,15 @@ namespace DotRecast.Detour.Dynamic.Io
cellSize = heightfield.cs;
cellHeight = heightfield.ch;
borderSize = heightfield.borderSize;
spanData = serializeSpans(heightfield, VoxelFile.PREFERRED_BYTE_ORDER);
spanData = SerializeSpans(heightfield, VoxelFile.PREFERRED_BYTE_ORDER);
}
public Heightfield heightfield()
public Heightfield Heightfield()
{
return VoxelFile.PREFERRED_BYTE_ORDER == ByteOrder.BIG_ENDIAN ? heightfieldBE() : heightfieldLE();
return VoxelFile.PREFERRED_BYTE_ORDER == ByteOrder.BIG_ENDIAN ? HeightfieldBE() : HeightfieldLE();
}
private Heightfield heightfieldBE()
private Heightfield HeightfieldBE()
{
Heightfield hf = new Heightfield(width, depth, boundsMin, boundsMax, cellSize, cellHeight, borderSize);
int position = 0;
@ -79,16 +79,16 @@ namespace DotRecast.Detour.Dynamic.Io
for (int x = 0; x < width; x++)
{
Span prev = null;
int spanCount = ByteUtils.getShortBE(spanData, position);
int spanCount = ByteUtils.GetShortBE(spanData, position);
position += 2;
for (int s = 0; s < spanCount; s++)
{
Span span = new Span();
span.smin = ByteUtils.getIntBE(spanData, position);
span.smin = ByteUtils.GetIntBE(spanData, position);
position += 4;
span.smax = ByteUtils.getIntBE(spanData, position);
span.smax = ByteUtils.GetIntBE(spanData, position);
position += 4;
span.area = ByteUtils.getIntBE(spanData, position);
span.area = ByteUtils.GetIntBE(spanData, position);
position += 4;
if (prev == null)
{
@ -107,7 +107,7 @@ namespace DotRecast.Detour.Dynamic.Io
return hf;
}
private Heightfield heightfieldLE()
private Heightfield HeightfieldLE()
{
Heightfield hf = new Heightfield(width, depth, boundsMin, boundsMax, cellSize, cellHeight, borderSize);
int position = 0;
@ -116,16 +116,16 @@ namespace DotRecast.Detour.Dynamic.Io
for (int x = 0; x < width; x++)
{
Span prev = null;
int spanCount = ByteUtils.getShortLE(spanData, position);
int spanCount = ByteUtils.GetShortLE(spanData, position);
position += 2;
for (int s = 0; s < spanCount; s++)
{
Span span = new Span();
span.smin = ByteUtils.getIntLE(spanData, position);
span.smin = ByteUtils.GetIntLE(spanData, position);
position += 4;
span.smax = ByteUtils.getIntLE(spanData, position);
span.smax = ByteUtils.GetIntLE(spanData, position);
position += 4;
span.area = ByteUtils.getIntLE(spanData, position);
span.area = ByteUtils.GetIntLE(spanData, position);
position += 4;
if (prev == null)
{
@ -144,7 +144,7 @@ namespace DotRecast.Detour.Dynamic.Io
return hf;
}
private byte[] serializeSpans(Heightfield heightfield, ByteOrder order)
private byte[] SerializeSpans(Heightfield heightfield, ByteOrder order)
{
int[] counts = new int[heightfield.width * heightfield.height];
int totalCount = 0;
@ -168,13 +168,13 @@ namespace DotRecast.Detour.Dynamic.Io
{
for (int x = 0; x < heightfield.width; x++)
{
position = ByteUtils.putShort(counts[pz + x], data, position, order);
position = ByteUtils.PutShort(counts[pz + x], data, position, order);
Span span = heightfield.spans[pz + x];
while (span != null)
{
position = ByteUtils.putInt(span.smin, data, position, order);
position = ByteUtils.putInt(span.smax, data, position, order);
position = ByteUtils.putInt(span.area, data, position, order);
position = ByteUtils.PutInt(span.smin, data, position, order);
position = ByteUtils.PutInt(span.smax, data, position, order);
position = ByteUtils.PutInt(span.area, data, position, order);
span = span.next;
}
}
@ -183,30 +183,30 @@ namespace DotRecast.Detour.Dynamic.Io
return data;
}
private byte[] toByteArray(ByteBuffer buf, int width, int height, ByteOrder order)
private byte[] ToByteArray(ByteBuffer buf, int width, int height, ByteOrder order)
{
byte[] data;
if (buf.order() == order)
if (buf.Order() == order)
{
data = buf.ReadBytes(buf.limit()).ToArray();
data = buf.ReadBytes(buf.Limit()).ToArray();
}
else
{
data = new byte[buf.limit()];
data = new byte[buf.Limit()];
int l = width * height;
int position = 0;
for (int i = 0; i < l; i++)
{
int count = buf.getShort();
ByteUtils.putShort(count, data, position, order);
int count = buf.GetShort();
ByteUtils.PutShort(count, data, position, order);
position += 2;
for (int j = 0; j < count; j++)
{
ByteUtils.putInt(buf.getInt(), data, position, order);
ByteUtils.PutInt(buf.GetInt(), data, position, order);
position += 4;
ByteUtils.putInt(buf.getInt(), data, position, order);
ByteUtils.PutInt(buf.GetInt(), data, position, order);
position += 4;
ByteUtils.putInt(buf.getInt(), data, position, order);
ByteUtils.PutInt(buf.GetInt(), data, position, order);
position += 4;
}
}

View File

@ -31,14 +31,14 @@ namespace DotRecast.Detour.Dynamic
this._affectedTiles = affectedTiles;
}
public ICollection<DynamicTile> affectedTiles()
public ICollection<DynamicTile> AffectedTiles()
{
return _affectedTiles;
}
public void process(DynamicTile tile)
public void Process(DynamicTile tile)
{
tile.removeCollider(colliderId);
tile.RemoveCollider(colliderId);
}
}
}

View File

@ -22,8 +22,8 @@ namespace DotRecast.Detour.Dynamic
{
public interface UpdateQueueItem
{
ICollection<DynamicTile> affectedTiles();
ICollection<DynamicTile> AffectedTiles();
void process(DynamicTile tile);
void Process(DynamicTile tile);
}
}

View File

@ -47,12 +47,12 @@ namespace DotRecast.Detour.Dynamic
*
* @return Optional with hit parameter (t) or empty if no hit found
*/
public float? raycast(Vector3f start, Vector3f end)
public float? Raycast(Vector3f start, Vector3f end)
{
return traverseTiles(start, end);
return TraverseTiles(start, end);
}
private float? traverseTiles(Vector3f start, Vector3f end)
private float? TraverseTiles(Vector3f start, Vector3f end)
{
float relStartX = start.x - origin.x;
float relStartZ = start.z - origin.z;
@ -79,7 +79,7 @@ namespace DotRecast.Detour.Dynamic
float t = 0;
while (true)
{
float? hit = traversHeightfield(sx, sz, start, end, t, Math.Min(1, Math.Min(tMaxX, tMaxZ)));
float? hit = TraversHeightfield(sx, sz, start, end, t, Math.Min(1, Math.Min(tMaxX, tMaxZ)));
if (hit.HasValue)
{
return hit;
@ -107,7 +107,7 @@ namespace DotRecast.Detour.Dynamic
return null;
}
private float? traversHeightfield(int x, int z, Vector3f start, Vector3f end, float tMin, float tMax)
private float? TraversHeightfield(int x, int z, Vector3f start, Vector3f end, float tMin, float tMax)
{
Heightfield hf = heightfieldProvider.Invoke(x, z);
if (null != hf)

View File

@ -23,15 +23,15 @@ namespace DotRecast.Detour.Extras
{
public class BVTreeBuilder
{
public void build(MeshData data)
public void Build(MeshData data)
{
data.bvTree = new BVNode[data.header.polyCount * 2];
data.header.bvNodeCount = data.bvTree.Length == 0
? 0
: createBVTree(data, data.bvTree, data.header.bvQuantFactor);
: CreateBVTree(data, data.bvTree, data.header.bvQuantFactor);
}
private static int createBVTree(MeshData data, BVNode[] nodes, float quantFactor)
private static int CreateBVTree(MeshData data, BVNode[] nodes, float quantFactor)
{
NavMeshBuilder.BVItem[] items = new NavMeshBuilder.BVItem[data.header.polyCount];
for (int i = 0; i < data.header.polyCount; i++)
@ -41,23 +41,23 @@ namespace DotRecast.Detour.Extras
it.i = i;
Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f();
vCopy(ref bmin, data.verts, data.polys[i].verts[0] * 3);
vCopy(ref bmax, data.verts, data.polys[i].verts[0] * 3);
VCopy(ref bmin, data.verts, data.polys[i].verts[0] * 3);
VCopy(ref bmax, data.verts, data.polys[i].verts[0] * 3);
for (int j = 1; j < data.polys[i].vertCount; j++)
{
vMin(ref bmin, data.verts, data.polys[i].verts[j] * 3);
vMax(ref bmax, data.verts, data.polys[i].verts[j] * 3);
VMin(ref bmin, data.verts, data.polys[i].verts[j] * 3);
VMax(ref bmax, data.verts, data.polys[i].verts[j] * 3);
}
it.bmin[0] = clamp((int)((bmin.x - data.header.bmin.x) * quantFactor), 0, 0x7fffffff);
it.bmin[1] = clamp((int)((bmin.y - data.header.bmin.y) * quantFactor), 0, 0x7fffffff);
it.bmin[2] = clamp((int)((bmin.z - data.header.bmin.z) * quantFactor), 0, 0x7fffffff);
it.bmax[0] = clamp((int)((bmax.x - data.header.bmin.x) * quantFactor), 0, 0x7fffffff);
it.bmax[1] = clamp((int)((bmax.y - data.header.bmin.y) * quantFactor), 0, 0x7fffffff);
it.bmax[2] = clamp((int)((bmax.z - data.header.bmin.z) * quantFactor), 0, 0x7fffffff);
it.bmin[0] = Clamp((int)((bmin.x - data.header.bmin.x) * quantFactor), 0, 0x7fffffff);
it.bmin[1] = Clamp((int)((bmin.y - data.header.bmin.y) * quantFactor), 0, 0x7fffffff);
it.bmin[2] = Clamp((int)((bmin.z - data.header.bmin.z) * quantFactor), 0, 0x7fffffff);
it.bmax[0] = Clamp((int)((bmax.x - data.header.bmin.x) * quantFactor), 0, 0x7fffffff);
it.bmax[1] = Clamp((int)((bmax.y - data.header.bmin.y) * quantFactor), 0, 0x7fffffff);
it.bmax[2] = Clamp((int)((bmax.z - data.header.bmin.z) * quantFactor), 0, 0x7fffffff);
}
return NavMeshBuilder.subdivide(items, data.header.polyCount, 0, data.header.polyCount, 0, nodes);
return NavMeshBuilder.Subdivide(items, data.header.polyCount, 0, data.header.polyCount, 0, nodes);
}
}
}

View File

@ -7,22 +7,22 @@ namespace DotRecast.Detour.Extras.Jumplink
{
public abstract class AbstractGroundSampler : GroundSampler
{
protected void sampleGround(JumpLinkBuilderConfig acfg, EdgeSampler es,
protected void SampleGround(JumpLinkBuilderConfig acfg, EdgeSampler es,
Func<Vector3f, float, Tuple<bool, float>> heightFunc)
{
float cs = acfg.cellSize;
float dist = (float)Math.Sqrt(vDist2DSqr(es.start.p, es.start.q));
float dist = (float)Math.Sqrt(VDist2DSqr(es.start.p, es.start.q));
int ngsamples = Math.Max(2, (int)Math.Ceiling(dist / cs));
sampleGroundSegment(heightFunc, es.start, ngsamples);
SampleGroundSegment(heightFunc, es.start, ngsamples);
foreach (GroundSegment end in es.end)
{
sampleGroundSegment(heightFunc, end, ngsamples);
SampleGroundSegment(heightFunc, end, ngsamples);
}
}
public abstract void sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es);
public abstract void Sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es);
protected void sampleGroundSegment(Func<Vector3f, float, Tuple<bool, float>> heightFunc, GroundSegment seg, int nsamples)
protected void SampleGroundSegment(Func<Vector3f, float, Tuple<bool, float>> heightFunc, GroundSegment seg, int nsamples)
{
seg.gsamples = new GroundSample[nsamples];
@ -32,7 +32,7 @@ namespace DotRecast.Detour.Extras.Jumplink
GroundSample s = new GroundSample();
seg.gsamples[i] = s;
Vector3f pt = vLerp(seg.p, seg.q, u);
Vector3f pt = VLerp(seg.p, seg.q, u);
Tuple<bool, float> height = heightFunc.Invoke(pt, seg.height);
s.p.x = pt.x;
s.p.y = height.Item2;

View File

@ -5,13 +5,13 @@ namespace DotRecast.Detour.Extras.Jumplink
{
public class ClimbTrajectory : Trajectory
{
public override Vector3f apply(Vector3f start, Vector3f end, float u)
public override Vector3f Apply(Vector3f start, Vector3f end, float u)
{
return new Vector3f()
{
x = lerp(start.x, end.x, Math.Min(2f * u, 1f)),
y = lerp(start.y, end.y, Math.Max(0f, 2f * u - 1f)),
z = lerp(start.z, end.z, Math.Min(2f * u, 1f))
x = Lerp(start.x, end.x, Math.Min(2f * u, 1f)),
y = Lerp(start.y, end.y, Math.Max(0f, 2f * u - 1f)),
z = Lerp(start.z, end.z, Math.Min(2f * u, 1f))
};
}
}

View File

@ -8,7 +8,7 @@ namespace DotRecast.Detour.Extras.Jumplink
{
public class EdgeExtractor
{
public Edge[] extractEdges(PolyMesh mesh)
public Edge[] ExtractEdges(PolyMesh mesh)
{
List<Edge> edges = new List<Edge>();
if (mesh != null)

View File

@ -17,11 +17,11 @@ namespace DotRecast.Detour.Extras.Jumplink
public EdgeSampler(Edge edge, Trajectory trajectory)
{
this.trajectory = trajectory;
ax = vSub(edge.sq, edge.sp);
vNormalize(ref ax);
vSet(ref az, ax.z, 0, -ax.x);
vNormalize(ref az);
vSet(ref ay, 0, 1, 0);
ax = VSub(edge.sq, edge.sp);
VNormalize(ref ax);
VSet(ref az, ax.z, 0, -ax.x);
VNormalize(ref az);
VSet(ref ay, 0, 1, 0);
}
}
}

View File

@ -5,16 +5,16 @@ namespace DotRecast.Detour.Extras.Jumplink
{
class EdgeSamplerFactory
{
public EdgeSampler get(JumpLinkBuilderConfig acfg, JumpLinkType type, Edge edge)
public EdgeSampler Get(JumpLinkBuilderConfig acfg, JumpLinkType type, Edge edge)
{
EdgeSampler es = null;
switch (type.Bit)
{
case JumpLinkType.EDGE_JUMP_BIT:
es = initEdgeJumpSampler(acfg, edge);
es = InitEdgeJumpSampler(acfg, edge);
break;
case JumpLinkType.EDGE_CLIMB_DOWN_BIT:
es = initClimbDownSampler(acfg, edge);
es = InitClimbDownSampler(acfg, edge);
break;
case JumpLinkType.EDGE_JUMP_OVER_BIT:
default:
@ -25,14 +25,14 @@ namespace DotRecast.Detour.Extras.Jumplink
}
private EdgeSampler initEdgeJumpSampler(JumpLinkBuilderConfig acfg, Edge edge)
private EdgeSampler InitEdgeJumpSampler(JumpLinkBuilderConfig acfg, Edge edge)
{
EdgeSampler es = new EdgeSampler(edge, new JumpTrajectory(acfg.jumpHeight));
es.start.height = acfg.agentClimb * 2;
Vector3f offset = new Vector3f();
trans2d(ref offset, es.az, es.ay, new Vector2f { x = acfg.startDistance, y = -acfg.agentClimb, });
vadd(ref es.start.p, edge.sp, offset);
vadd(ref es.start.q, edge.sq, offset);
Trans2d(ref offset, es.az, es.ay, new Vector2f { x = acfg.startDistance, y = -acfg.agentClimb, });
Vadd(ref es.start.p, edge.sp, offset);
Vadd(ref es.start.q, edge.sq, offset);
float dx = acfg.endDistance - 2 * acfg.agentRadius;
float cs = acfg.cellSize;
@ -42,43 +42,43 @@ namespace DotRecast.Detour.Extras.Jumplink
{
float v = (float)j / (float)(nsamples - 1);
float ox = 2 * acfg.agentRadius + dx * v;
trans2d(ref offset, es.az, es.ay, new Vector2f { x = ox, y = acfg.minHeight });
Trans2d(ref offset, es.az, es.ay, new Vector2f { x = ox, y = acfg.minHeight });
GroundSegment end = new GroundSegment();
end.height = acfg.heightRange;
vadd(ref end.p, edge.sp, offset);
vadd(ref end.q, edge.sq, offset);
Vadd(ref end.p, edge.sp, offset);
Vadd(ref end.q, edge.sq, offset);
es.end.Add(end);
}
return es;
}
private EdgeSampler initClimbDownSampler(JumpLinkBuilderConfig acfg, Edge edge)
private EdgeSampler InitClimbDownSampler(JumpLinkBuilderConfig acfg, Edge edge)
{
EdgeSampler es = new EdgeSampler(edge, new ClimbTrajectory());
es.start.height = acfg.agentClimb * 2;
Vector3f offset = new Vector3f();
trans2d(ref offset, es.az, es.ay, new Vector2f() { x = acfg.startDistance, y = -acfg.agentClimb });
vadd(ref es.start.p, edge.sp, offset);
vadd(ref es.start.q, edge.sq, offset);
Trans2d(ref offset, es.az, es.ay, new Vector2f() { x = acfg.startDistance, y = -acfg.agentClimb });
Vadd(ref es.start.p, edge.sp, offset);
Vadd(ref es.start.q, edge.sq, offset);
trans2d(ref offset, es.az, es.ay, new Vector2f() { x = acfg.endDistance, y = acfg.minHeight });
Trans2d(ref offset, es.az, es.ay, new Vector2f() { x = acfg.endDistance, y = acfg.minHeight });
GroundSegment end = new GroundSegment();
end.height = acfg.heightRange;
vadd(ref end.p, edge.sp, offset);
vadd(ref end.q, edge.sq, offset);
Vadd(ref end.p, edge.sp, offset);
Vadd(ref end.q, edge.sq, offset);
es.end.Add(end);
return es;
}
private void vadd(float[] dest, float[] v1, float[] v2)
private void Vadd(float[] dest, float[] v1, float[] v2)
{
dest[0] = v1[0] + v2[0];
dest[1] = v1[1] + v2[1];
dest[2] = v1[2] + v2[2];
}
private void vadd(ref Vector3f dest, Vector3f v1, Vector3f v2)
private void Vadd(ref Vector3f dest, Vector3f v1, Vector3f v2)
{
dest.x = v1.x + v2.x;
dest.y = v1.y + v2.y;
@ -86,14 +86,14 @@ namespace DotRecast.Detour.Extras.Jumplink
}
private void trans2d(float[] dst, float[] ax, float[] ay, float[] pt)
private void Trans2d(float[] dst, float[] ax, float[] ay, float[] pt)
{
dst[0] = ax[0] * pt[0] + ay[0] * pt[1];
dst[1] = ax[1] * pt[0] + ay[1] * pt[1];
dst[2] = ax[2] * pt[0] + ay[2] * pt[1];
}
private void trans2d(ref Vector3f dst, Vector3f ax, Vector3f ay, Vector2f pt)
private void Trans2d(ref Vector3f dst, Vector3f ax, Vector3f ay, Vector2f pt)
{
dst.x = ax.x * pt.x + ay.x * pt.y;
dst.y = ax.y * pt.x + ay.y * pt.y;

View File

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

View File

@ -21,10 +21,10 @@ namespace DotRecast.Detour.Extras.Jumplink
public JumpLinkBuilder(IList<RecastBuilderResult> results)
{
this.results = results;
edges = results.Select(r => edgeExtractor.extractEdges(r.getMesh())).ToList();
edges = results.Select(r => edgeExtractor.ExtractEdges(r.GetMesh())).ToList();
}
public List<JumpLink> build(JumpLinkBuilderConfig acfg, JumpLinkType type)
public List<JumpLink> Build(JumpLinkBuilderConfig acfg, JumpLinkType type)
{
List<JumpLink> links = new List<JumpLink>();
for (int tile = 0; tile < results.Count; tile++)
@ -32,24 +32,24 @@ namespace DotRecast.Detour.Extras.Jumplink
Edge[] edges = this.edges[tile];
foreach (Edge edge in edges)
{
links.AddRange(processEdge(acfg, results[tile], type, edge));
links.AddRange(ProcessEdge(acfg, results[tile], type, edge));
}
}
return links;
}
private List<JumpLink> processEdge(JumpLinkBuilderConfig acfg, RecastBuilderResult result, JumpLinkType type, Edge edge)
private List<JumpLink> ProcessEdge(JumpLinkBuilderConfig acfg, RecastBuilderResult result, JumpLinkType type, Edge edge)
{
EdgeSampler es = edgeSamplerFactory.get(acfg, type, edge);
groundSampler.sample(acfg, result, es);
trajectorySampler.sample(acfg, result.getSolidHeightfield(), es);
JumpSegment[] jumpSegments = jumpSegmentBuilder.build(acfg, es);
return buildJumpLinks(acfg, es, jumpSegments);
EdgeSampler es = edgeSamplerFactory.Get(acfg, type, edge);
groundSampler.Sample(acfg, result, es);
trajectorySampler.Sample(acfg, result.GetSolidHeightfield(), es);
JumpSegment[] jumpSegments = jumpSegmentBuilder.Build(acfg, es);
return BuildJumpLinks(acfg, es, jumpSegments);
}
private List<JumpLink> buildJumpLinks(JumpLinkBuilderConfig acfg, EdgeSampler es, JumpSegment[] jumpSegments)
private List<JumpLink> BuildJumpLinks(JumpLinkBuilderConfig acfg, EdgeSampler es, JumpSegment[] jumpSegments)
{
List<JumpLink> links = new List<JumpLink>();
foreach (JumpSegment js in jumpSegments)
@ -59,7 +59,7 @@ namespace DotRecast.Detour.Extras.Jumplink
GroundSegment end = es.end[js.groundSegment];
Vector3f ep = end.gsamples[js.startSample].p;
Vector3f eq = end.gsamples[js.startSample + js.samples - 1].p;
float d = Math.Min(vDist2DSqr(sp, sq), vDist2DSqr(ep, eq));
float d = Math.Min(VDist2DSqr(sp, sq), VDist2DSqr(ep, eq));
if (d >= 4 * acfg.agentRadius * acfg.agentRadius)
{
JumpLink link = new JumpLink();
@ -72,12 +72,12 @@ namespace DotRecast.Detour.Extras.Jumplink
for (int j = 0; j < link.nspine; ++j)
{
float u = ((float)j) / (link.nspine - 1);
Vector3f p = es.trajectory.apply(sp, ep, u);
Vector3f p = es.trajectory.Apply(sp, ep, u);
link.spine0[j * 3] = p.x;
link.spine0[j * 3 + 1] = p.y;
link.spine0[j * 3 + 2] = p.z;
p = es.trajectory.apply(sq, eq, u);
p = es.trajectory.Apply(sq, eq, u);
link.spine1[j * 3] = p.x;
link.spine1[j * 3 + 1] = p.y;
link.spine1[j * 3 + 2] = p.z;
@ -88,7 +88,7 @@ namespace DotRecast.Detour.Extras.Jumplink
return links;
}
public List<Edge[]> getEdges()
public List<Edge[]> GetEdges()
{
return edges;
}

View File

@ -6,7 +6,7 @@ namespace DotRecast.Detour.Extras.Jumplink
{
class JumpSegmentBuilder
{
public JumpSegment[] build(JumpLinkBuilderConfig acfg, EdgeSampler es)
public JumpSegment[] Build(JumpLinkBuilderConfig acfg, EdgeSampler es)
{
int n = es.end[0].gsamples.Length;
int[][] sampleGrid = ArrayUtils.Of<int>(n, es.end.Count);
@ -35,7 +35,7 @@ namespace DotRecast.Detour.Extras.Jumplink
{
var queue = new Queue<int[]>();
queue.Enqueue(new int[] { i, j });
fill(es, sampleGrid, queue, acfg.agentClimb, region);
Fill(es, sampleGrid, queue, acfg.agentClimb, region);
region++;
}
}
@ -84,7 +84,7 @@ namespace DotRecast.Detour.Extras.Jumplink
return jumpSegments;
}
private void fill(EdgeSampler es, int[][] sampleGrid, Queue<int[]> queue, float agentClimb, int region)
private void Fill(EdgeSampler es, int[][] sampleGrid, Queue<int[]> queue, float agentClimb, int region)
{
while (queue.TryDequeue(out var ij))
{
@ -97,28 +97,28 @@ namespace DotRecast.Detour.Extras.Jumplink
float h = p.p.y;
if (i < sampleGrid.Length - 1)
{
addNeighbour(es, queue, agentClimb, h, i + 1, j);
AddNeighbour(es, queue, agentClimb, h, i + 1, j);
}
if (i > 0)
{
addNeighbour(es, queue, agentClimb, h, i - 1, j);
AddNeighbour(es, queue, agentClimb, h, i - 1, j);
}
if (j < sampleGrid[0].Length - 1)
{
addNeighbour(es, queue, agentClimb, h, i, j + 1);
AddNeighbour(es, queue, agentClimb, h, i, j + 1);
}
if (j > 0)
{
addNeighbour(es, queue, agentClimb, h, i, j - 1);
AddNeighbour(es, queue, agentClimb, h, i, j - 1);
}
}
}
}
private void addNeighbour(EdgeSampler es, Queue<int[]> queue, float agentClimb, float h, int i, int j)
private void AddNeighbour(EdgeSampler es, Queue<int[]> queue, float agentClimb, float h, int i, int j)
{
GroundSample q = es.end[j].gsamples[i];
if (q.validTrajectory && Math.Abs(q.p.y - h) < agentClimb)

View File

@ -12,17 +12,17 @@ namespace DotRecast.Detour.Extras.Jumplink
this.jumpHeight = jumpHeight;
}
public override Vector3f apply(Vector3f start, Vector3f end, float u)
public override Vector3f Apply(Vector3f start, Vector3f end, float u)
{
return new Vector3f
{
x = lerp(start.x, end.x, u),
y = interpolateHeight(start.y, end.y, u),
z = lerp(start.z, end.z, u)
x = Lerp(start.x, end.x, u),
y = InterpolateHeight(start.y, end.y, u),
z = Lerp(start.z, end.z, u)
};
}
private float interpolateHeight(float ys, float ye, float u)
private float InterpolateHeight(float ys, float ye, float u)
{
if (u == 0f)
{

View File

@ -11,48 +11,48 @@ namespace DotRecast.Detour.Extras.Jumplink
private class NoOpFilter : QueryFilter
{
public bool passFilter(long refs, MeshTile tile, Poly poly)
public bool PassFilter(long refs, MeshTile tile, Poly poly)
{
return true;
}
public float getCost(Vector3f pa, Vector3f pb, long prevRef, MeshTile prevTile, Poly prevPoly, long curRef,
public float GetCost(Vector3f pa, Vector3f pb, long prevRef, MeshTile prevTile, Poly prevPoly, long curRef,
MeshTile curTile, Poly curPoly, long nextRef, MeshTile nextTile, Poly nextPoly)
{
return 0;
}
}
public override void sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es)
public override void Sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es)
{
NavMeshQuery navMeshQuery = createNavMesh(result, acfg.agentRadius, acfg.agentHeight, acfg.agentClimb);
sampleGround(acfg, es, (pt, h) => getNavMeshHeight(navMeshQuery, pt, acfg.cellSize, h));
NavMeshQuery navMeshQuery = CreateNavMesh(result, acfg.agentRadius, acfg.agentHeight, acfg.agentClimb);
SampleGround(acfg, es, (pt, h) => GetNavMeshHeight(navMeshQuery, pt, acfg.cellSize, h));
}
private NavMeshQuery createNavMesh(RecastBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
private NavMeshQuery CreateNavMesh(RecastBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
{
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
option.verts = r.getMesh().verts;
option.vertCount = r.getMesh().nverts;
option.polys = r.getMesh().polys;
option.polyAreas = r.getMesh().areas;
option.polyFlags = r.getMesh().flags;
option.polyCount = r.getMesh().npolys;
option.nvp = r.getMesh().nvp;
option.detailMeshes = r.getMeshDetail().meshes;
option.detailVerts = r.getMeshDetail().verts;
option.detailVertsCount = r.getMeshDetail().nverts;
option.detailTris = r.getMeshDetail().tris;
option.detailTriCount = r.getMeshDetail().ntris;
option.verts = r.GetMesh().verts;
option.vertCount = r.GetMesh().nverts;
option.polys = r.GetMesh().polys;
option.polyAreas = r.GetMesh().areas;
option.polyFlags = r.GetMesh().flags;
option.polyCount = r.GetMesh().npolys;
option.nvp = r.GetMesh().nvp;
option.detailMeshes = r.GetMeshDetail().meshes;
option.detailVerts = r.GetMeshDetail().verts;
option.detailVertsCount = r.GetMeshDetail().nverts;
option.detailTris = r.GetMeshDetail().tris;
option.detailTriCount = r.GetMeshDetail().ntris;
option.walkableRadius = agentRadius;
option.walkableHeight = agentHeight;
option.walkableClimb = agentClimb;
option.bmin = r.getMesh().bmin;
option.bmax = r.getMesh().bmax;
option.cs = r.getMesh().cs;
option.ch = r.getMesh().ch;
option.bmin = r.GetMesh().bmin;
option.bmax = r.GetMesh().bmax;
option.cs = r.GetMesh().cs;
option.ch = r.GetMesh().ch;
option.buildBvTree = true;
return new NavMeshQuery(new NavMesh(NavMeshBuilder.createNavMeshData(option), option.nvp, 0));
return new NavMeshQuery(new NavMesh(NavMeshBuilder.CreateNavMeshData(option), option.nvp, 0));
}
public class PolyQueryInvoker : PolyQuery
@ -64,32 +64,32 @@ namespace DotRecast.Detour.Extras.Jumplink
_callback = callback;
}
public void process(MeshTile tile, Poly poly, long refs)
public void Process(MeshTile tile, Poly poly, long refs)
{
_callback?.Invoke(tile, poly, refs);
}
}
private Tuple<bool, float> getNavMeshHeight(NavMeshQuery navMeshQuery, Vector3f pt, float cs, float heightRange)
private Tuple<bool, float> GetNavMeshHeight(NavMeshQuery navMeshQuery, Vector3f pt, float cs, float heightRange)
{
Vector3f halfExtents = new Vector3f { x = cs, y = heightRange, z = cs };
float maxHeight = pt.y + heightRange;
AtomicBoolean found = new AtomicBoolean();
AtomicFloat minHeight = new AtomicFloat(pt.y);
navMeshQuery.queryPolygons(pt, halfExtents, filter, new PolyQueryInvoker((tile, poly, refs) =>
navMeshQuery.QueryPolygons(pt, halfExtents, filter, new PolyQueryInvoker((tile, poly, refs) =>
{
Result<float> h = navMeshQuery.getPolyHeight(refs, pt);
Result<float> h = navMeshQuery.GetPolyHeight(refs, pt);
if (h.Succeeded())
{
float y = h.result;
if (y > minHeight.Get() && y < maxHeight)
{
minHeight.Exchange(y);
found.set(true);
found.Set(true);
}
}
}));
if (found.get())
if (found.Get())
{
return Tuple.Create(true, minHeight.Get());
}

View File

@ -5,12 +5,12 @@ namespace DotRecast.Detour.Extras.Jumplink
{
public class Trajectory
{
public float lerp(float f, float g, float u)
public float Lerp(float f, float g, float u)
{
return u * g + (1f - u) * f;
}
public virtual Vector3f apply(Vector3f start, Vector3f end, float u)
public virtual Vector3f Apply(Vector3f start, Vector3f end, float u)
{
throw new NotImplementedException();
}

View File

@ -7,7 +7,7 @@ namespace DotRecast.Detour.Extras.Jumplink
{
class TrajectorySampler
{
public void sample(JumpLinkBuilderConfig acfg, Heightfield heightfield, EdgeSampler es)
public void Sample(JumpLinkBuilderConfig acfg, Heightfield heightfield, EdgeSampler es)
{
int nsamples = es.start.gsamples.Length;
for (int i = 0; i < nsamples; ++i)
@ -21,7 +21,7 @@ namespace DotRecast.Detour.Extras.Jumplink
continue;
}
if (!sampleTrajectory(acfg, heightfield, ssmp.p, esmp.p, es.trajectory))
if (!SampleTrajectory(acfg, heightfield, ssmp.p, esmp.p, es.trajectory))
{
continue;
}
@ -32,16 +32,16 @@ namespace DotRecast.Detour.Extras.Jumplink
}
}
private bool sampleTrajectory(JumpLinkBuilderConfig acfg, Heightfield solid, Vector3f pa, Vector3f pb, Trajectory tra)
private bool SampleTrajectory(JumpLinkBuilderConfig acfg, Heightfield solid, Vector3f pa, Vector3f pb, Trajectory tra)
{
float cs = Math.Min(acfg.cellSize, acfg.cellHeight);
float d = vDist2D(pa, pb) + Math.Abs(pa.y - pb.y);
float d = VDist2D(pa, pb) + Math.Abs(pa.y - pb.y);
int nsamples = Math.Max(2, (int)Math.Ceiling(d / cs));
for (int i = 0; i < nsamples; ++i)
{
float u = (float)i / (float)(nsamples - 1);
Vector3f p = tra.apply(pa, pb, u);
if (checkHeightfieldCollision(solid, p.x, p.y + acfg.groundTolerance, p.y + acfg.agentHeight, p.z))
Vector3f p = tra.Apply(pa, pb, u);
if (CheckHeightfieldCollision(solid, p.x, p.y + acfg.groundTolerance, p.y + acfg.agentHeight, p.z))
{
return false;
}
@ -50,7 +50,7 @@ namespace DotRecast.Detour.Extras.Jumplink
return true;
}
private bool checkHeightfieldCollision(Heightfield solid, float x, float ymin, float ymax, float z)
private bool CheckHeightfieldCollision(Heightfield solid, float x, float ymin, float ymax, float z)
{
int w = solid.width;
int h = solid.height;
@ -75,7 +75,7 @@ namespace DotRecast.Detour.Extras.Jumplink
{
float symin = orig.y + s.smin * ch;
float symax = orig.y + s.smax * ch;
if (overlapRange(ymin, ymax, symin, symax))
if (OverlapRange(ymin, ymax, symin, symax))
{
return true;
}
@ -86,7 +86,7 @@ namespace DotRecast.Detour.Extras.Jumplink
return false;
}
private bool overlapRange(float amin, float amax, float bmin, float bmax)
private bool OverlapRange(float amin, float amax, float bmin, float bmax)
{
return (amin > bmax || amax < bmin) ? false : true;
}

View File

@ -22,14 +22,14 @@ namespace DotRecast.Detour.Extras
{
public class ObjExporter
{
public void export(NavMesh mesh)
public void Export(NavMesh mesh)
{
string filename = Path.Combine(Directory.GetCurrentDirectory(), "Demo", "astar.obj");
using var fs = new FileStream(filename, FileMode.CreateNew);
using var fw = new StreamWriter(fs);
for (int i = 0; i < mesh.getTileCount(); i++)
for (int i = 0; i < mesh.GetTileCount(); i++)
{
MeshTile tile = mesh.getTile(i);
MeshTile tile = mesh.GetTile(i);
if (tile != null)
{
for (int v = 0; v < tile.data.header.vertCount; v++)
@ -41,9 +41,9 @@ namespace DotRecast.Detour.Extras
}
int vertexOffset = 1;
for (int i = 0; i < mesh.getTileCount(); i++)
for (int i = 0; i < mesh.GetTileCount(); i++)
{
MeshTile tile = mesh.getTile(i);
MeshTile tile = mesh.GetTile(i);
if (tile != null)
{
for (int p = 0; p < tile.data.header.polyCount; p++)
@ -67,8 +67,8 @@ namespace DotRecast.Detour.Extras
*
MeshSetReader reader = new MeshSetReader();
ObjExporter exporter = new ObjExporter();
exporter.export(mesh);
reader.read(new FileInputStream("/home/piotr/Downloads/graph/all_tiles_navmesh.bin"), 3);
exporter.Export(mesh);
reader.Read(new FileInputStream("/home/piotr/Downloads/graph/all_tiles_navmesh.bin"), 3);
*/

View File

@ -23,7 +23,7 @@ namespace DotRecast.Detour.Extras
/**
* Find edge shared by 2 polygons within the same tile
*/
public static int findEdge(Poly node, Poly neighbour, MeshData tile, MeshData neighbourTile)
public static int FindEdge(Poly node, Poly neighbour, MeshData tile, MeshData neighbourTile)
{
// Compare indices first assuming there are no duplicate vertices
for (int i = 0; i < node.vertCount; i++)
@ -47,10 +47,10 @@ namespace DotRecast.Detour.Extras
for (int k = 0; k < neighbour.vertCount; k++)
{
int l = (k + 1) % neighbour.vertCount;
if ((samePosition(tile.verts, node.verts[i], neighbourTile.verts, neighbour.verts[l])
&& samePosition(tile.verts, node.verts[j], neighbourTile.verts, neighbour.verts[k]))
|| (samePosition(tile.verts, node.verts[i], neighbourTile.verts, neighbour.verts[k])
&& samePosition(tile.verts, node.verts[j], neighbourTile.verts, neighbour.verts[l])))
if ((SamePosition(tile.verts, node.verts[i], neighbourTile.verts, neighbour.verts[l])
&& SamePosition(tile.verts, node.verts[j], neighbourTile.verts, neighbour.verts[k]))
|| (SamePosition(tile.verts, node.verts[i], neighbourTile.verts, neighbour.verts[k])
&& SamePosition(tile.verts, node.verts[j], neighbourTile.verts, neighbour.verts[l])))
{
return i;
}
@ -60,7 +60,7 @@ namespace DotRecast.Detour.Extras
return -1;
}
private static bool samePosition(float[] verts, int v, float[] verts2, int v2)
private static bool SamePosition(float[] verts, int v, float[] verts2, int v2)
{
for (int i = 0; i < 3; i++)
{
@ -76,7 +76,7 @@ namespace DotRecast.Detour.Extras
/**
* Find edge closest to the given coordinate
*/
public static int findEdge(Poly node, MeshData tile, float value, int comp)
public static int FindEdge(Poly node, MeshData tile, float value, int comp)
{
float error = float.MaxValue;
int edge = 0;

View File

@ -22,11 +22,11 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
private readonly BVTreeBuilder builder = new BVTreeBuilder();
public void build(GraphMeshData graphData)
public void Build(GraphMeshData graphData)
{
foreach (MeshData d in graphData.tiles)
{
builder.build(d);
builder.Build(d);
}
}
}

View File

@ -24,24 +24,24 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
class GraphConnectionReader : ZipBinaryReader
{
public List<int[]> read(ZipArchive file, string filename, Meta meta, int[] indexToNode)
public List<int[]> Read(ZipArchive file, string filename, Meta meta, int[] indexToNode)
{
List<int[]> connections = new List<int[]>();
ByteBuffer buffer = toByteBuffer(file, filename);
while (buffer.remaining() > 0)
ByteBuffer buffer = ToByteBuffer(file, filename);
while (buffer.Remaining() > 0)
{
int count = buffer.getInt();
int count = buffer.GetInt();
int[] nodeConnections = new int[count];
connections.Add(nodeConnections);
for (int i = 0; i < count; i++)
{
int nodeIndex = buffer.getInt();
int nodeIndex = buffer.GetInt();
nodeConnections[i] = indexToNode[nodeIndex];
// XXX: Is there anything we can do with the cost?
int cost = buffer.getInt();
if (meta.isVersionAtLeast(Meta.UPDATED_STRUCT_VERSION))
int cost = buffer.GetInt();
if (meta.IsVersionAtLeast(Meta.UPDATED_STRUCT_VERSION))
{
byte shapeEdge = buffer.get();
byte shapeEdge = buffer.Get();
}
}
}

View File

@ -31,7 +31,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
this.tiles = tiles;
}
public int countNodes()
public int CountNodes()
{
int polyCount = 0;
foreach (MeshData t in tiles)
@ -42,7 +42,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
return polyCount;
}
public Poly getNode(int node)
public Poly GetNode(int node)
{
int index = 0;
foreach (MeshData t in tiles)
@ -58,7 +58,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
return null;
}
public MeshData getTile(int node)
public MeshData GetTile(int node)
{
int index = 0;
foreach (MeshData t in tiles)

View File

@ -27,59 +27,59 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
public const float INT_PRECISION_FACTOR = 1000f;
public GraphMeshData read(ZipArchive file, string filename, GraphMeta meta, int maxVertPerPoly)
public GraphMeshData Read(ZipArchive file, string filename, GraphMeta meta, int maxVertPerPoly)
{
ByteBuffer buffer = toByteBuffer(file, filename);
int tileXCount = buffer.getInt();
ByteBuffer buffer = ToByteBuffer(file, filename);
int tileXCount = buffer.GetInt();
if (tileXCount < 0)
{
return null;
}
int tileZCount = buffer.getInt();
int tileZCount = buffer.GetInt();
MeshData[] tiles = new MeshData[tileXCount * tileZCount];
for (int z = 0; z < tileZCount; z++)
{
for (int x = 0; x < tileXCount; x++)
{
int tileIndex = x + z * tileXCount;
int tx = buffer.getInt();
int tz = buffer.getInt();
int tx = buffer.GetInt();
int tz = buffer.GetInt();
if (tx != x || tz != z)
{
throw new ArgumentException("Inconsistent tile positions");
}
tiles[tileIndex] = new MeshData();
int width = buffer.getInt();
int depth = buffer.getInt();
int width = buffer.GetInt();
int depth = buffer.GetInt();
int trisCount = buffer.getInt();
int trisCount = buffer.GetInt();
int[] tris = new int[trisCount];
for (int i = 0; i < tris.Length; i++)
{
tris[i] = buffer.getInt();
tris[i] = buffer.GetInt();
}
int vertsCount = buffer.getInt();
int vertsCount = buffer.GetInt();
float[] verts = new float[3 * vertsCount];
for (int i = 0; i < verts.Length; i++)
{
verts[i] = buffer.getInt() / INT_PRECISION_FACTOR;
verts[i] = buffer.GetInt() / INT_PRECISION_FACTOR;
}
int[] vertsInGraphSpace = new int[3 * buffer.getInt()];
int[] vertsInGraphSpace = new int[3 * buffer.GetInt()];
for (int i = 0; i < vertsInGraphSpace.Length; i++)
{
vertsInGraphSpace[i] = buffer.getInt();
vertsInGraphSpace[i] = buffer.GetInt();
}
int nodeCount = buffer.getInt();
int nodeCount = buffer.GetInt();
Poly[] nodes = new Poly[nodeCount];
PolyDetail[] detailNodes = new PolyDetail[nodeCount];
float[] detailVerts = new float[0];
int[] detailTris = new int[4 * nodeCount];
int vertMask = getVertMask(vertsCount);
int vertMask = GetVertMask(vertsCount);
float ymin = float.PositiveInfinity;
float ymax = float.NegativeInfinity;
for (int i = 0; i < nodes.Length; i++)
@ -87,11 +87,11 @@ namespace DotRecast.Detour.Extras.Unity.Astar
nodes[i] = new Poly(i, maxVertPerPoly);
nodes[i].vertCount = 3;
// XXX: What can we do with the penalty?
int penalty = buffer.getInt();
nodes[i].flags = buffer.getInt();
nodes[i].verts[0] = buffer.getInt() & vertMask;
nodes[i].verts[1] = buffer.getInt() & vertMask;
nodes[i].verts[2] = buffer.getInt() & vertMask;
int penalty = buffer.GetInt();
nodes[i].flags = buffer.GetInt();
nodes[i].verts[0] = buffer.GetInt() & vertMask;
nodes[i].verts[1] = buffer.GetInt() & vertMask;
nodes[i].verts[2] = buffer.GetInt() & vertMask;
ymin = Math.Min(ymin, verts[nodes[i].verts[0] * 3 + 1]);
ymin = Math.Min(ymin, verts[nodes[i].verts[1] * 3 + 1]);
ymin = Math.Min(ymin, verts[nodes[i].verts[2] * 3 + 1]);
@ -148,7 +148,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
return new GraphMeshData(tileXCount, tileZCount, tiles);
}
public static int highestOneBit(uint i)
public static int HighestOneBit(uint i)
{
i |= (i >> 1);
i |= (i >> 2);
@ -159,9 +159,9 @@ namespace DotRecast.Detour.Extras.Unity.Astar
}
// See NavmeshBase.cs: ASTAR_RECAST_LARGER_TILES
private int getVertMask(int vertsCount)
private int GetVertMask(int vertsCount)
{
int vertMask = highestOneBit((uint)vertsCount);
int vertMask = HighestOneBit((uint)vertsCount);
if (vertMask != vertsCount)
{
vertMask *= 2;

View File

@ -24,7 +24,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
public class GraphMetaReader
{
public GraphMeta read(ZipArchive file, string filename)
public GraphMeta Read(ZipArchive file, string filename)
{
ZipArchiveEntry entry = file.GetEntry(filename);
using StreamReader reader = new StreamReader(entry.Open());

View File

@ -24,32 +24,32 @@ namespace DotRecast.Detour.Extras.Unity.Astar
public class LinkBuilder
{
// Process connections and transform them into recast neighbour flags
public void build(int nodeOffset, GraphMeshData graphData, List<int[]> connections)
public void Build(int nodeOffset, GraphMeshData graphData, List<int[]> connections)
{
for (int n = 0; n < connections.Count; n++)
{
int[] nodeConnections = connections[n];
MeshData tile = graphData.getTile(n);
Poly node = graphData.getNode(n);
MeshData tile = graphData.GetTile(n);
Poly node = graphData.GetNode(n);
foreach (int connection in nodeConnections)
{
MeshData neighbourTile = graphData.getTile(connection - nodeOffset);
MeshData neighbourTile = graphData.GetTile(connection - nodeOffset);
if (neighbourTile != tile)
{
buildExternalLink(tile, node, neighbourTile);
BuildExternalLink(tile, node, neighbourTile);
}
else
{
Poly neighbour = graphData.getNode(connection - nodeOffset);
buildInternalLink(tile, node, neighbourTile, neighbour);
Poly neighbour = graphData.GetNode(connection - nodeOffset);
BuildInternalLink(tile, node, neighbourTile, neighbour);
}
}
}
}
private void buildInternalLink(MeshData tile, Poly node, MeshData neighbourTile, Poly neighbour)
private void BuildInternalLink(MeshData tile, Poly node, MeshData neighbourTile, Poly neighbour)
{
int edge = PolyUtils.findEdge(node, neighbour, tile, neighbourTile);
int edge = PolyUtils.FindEdge(node, neighbour, tile, neighbourTile);
if (edge >= 0)
{
node.neis[edge] = neighbour.index + 1;
@ -61,23 +61,23 @@ namespace DotRecast.Detour.Extras.Unity.Astar
}
// In case of external link to other tiles we must find the direction
private void buildExternalLink(MeshData tile, Poly node, MeshData neighbourTile)
private void BuildExternalLink(MeshData tile, Poly node, MeshData neighbourTile)
{
if (neighbourTile.header.bmin.x > tile.header.bmin.x)
{
node.neis[PolyUtils.findEdge(node, tile, neighbourTile.header.bmin.x, 0)] = NavMesh.DT_EXT_LINK;
node.neis[PolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.x, 0)] = NavMesh.DT_EXT_LINK;
}
else if (neighbourTile.header.bmin.x < tile.header.bmin.x)
{
node.neis[PolyUtils.findEdge(node, tile, tile.header.bmin.x, 0)] = NavMesh.DT_EXT_LINK | 4;
node.neis[PolyUtils.FindEdge(node, tile, tile.header.bmin.x, 0)] = NavMesh.DT_EXT_LINK | 4;
}
else if (neighbourTile.header.bmin.z > tile.header.bmin.z)
{
node.neis[PolyUtils.findEdge(node, tile, neighbourTile.header.bmin.z, 2)] = NavMesh.DT_EXT_LINK | 2;
node.neis[PolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.z, 2)] = NavMesh.DT_EXT_LINK | 2;
}
else
{
node.neis[PolyUtils.findEdge(node, tile, tile.header.bmin.z, 2)] = NavMesh.DT_EXT_LINK | 6;
node.neis[PolyUtils.FindEdge(node, tile, tile.header.bmin.z, 2)] = NavMesh.DT_EXT_LINK | 6;
}
}
}

View File

@ -32,15 +32,15 @@ namespace DotRecast.Detour.Extras.Unity.Astar
public string[] guids { get; set; }
public string[] typeNames { get; set; }
public bool isSupportedVersion()
public bool IsSupportedVersion()
{
return isVersionAtLeast(MIN_SUPPORTED_VERSION);
return IsVersionAtLeast(MIN_SUPPORTED_VERSION);
}
public bool isVersionAtLeast(string minVersion)
public bool IsVersionAtLeast(string minVersion)
{
int[] actual = parseVersion(version);
int[] minSupported = parseVersion(minVersion);
int[] actual = ParseVersion(version);
int[] minSupported = ParseVersion(minVersion);
for (int i = 0; i < Math.Min(actual.Length, minSupported.Length); i++)
{
if (actual[i] > minSupported[i])
@ -56,7 +56,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
return true;
}
private int[] parseVersion(string version)
private int[] ParseVersion(string version)
{
Match m = VERSION_PATTERN.Match(version);
if (m.Success)
@ -73,7 +73,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
throw new ArgumentException("Invalid version format: " + version);
}
public bool isSupportedType()
public bool IsSupportedType()
{
foreach (string t in typeNames)
{

View File

@ -27,7 +27,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
public class MetaReader
{
public Meta read(ZipArchive file, string filename)
public Meta Read(ZipArchive file, string filename)
{
ZipArchiveEntry entry = file.GetEntry(filename);
using StreamReader reader = new StreamReader(entry.Open());
@ -42,12 +42,12 @@ namespace DotRecast.Detour.Extras.Unity.Astar
json = regex.Replace(json, replacement);
var meta = JsonSerializer.Deserialize<Meta>(json);
if (!meta.isSupportedType())
if (!meta.IsSupportedType())
{
throw new ArgumentException("Unsupported graph type " + string.Join(", ", meta.typeNames));
}
if (!meta.isSupportedVersion())
if (!meta.IsSupportedVersion())
{
throw new ArgumentException("Unsupported version " + meta.version);
}

View File

@ -23,15 +23,15 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
class NodeIndexReader : ZipBinaryReader
{
public int[] read(ZipArchive file, string filename)
public int[] Read(ZipArchive file, string filename)
{
ByteBuffer buffer = toByteBuffer(file, filename);
int maxNodeIndex = buffer.getInt();
ByteBuffer buffer = ToByteBuffer(file, filename);
int maxNodeIndex = buffer.GetInt();
int[] int2Node = new int[maxNodeIndex + 1];
int node = 0;
while (buffer.remaining() > 0)
while (buffer.Remaining() > 0)
{
int index = buffer.getInt();
int index = buffer.GetInt();
int2Node[index] = node++;
}

View File

@ -23,27 +23,27 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
public class NodeLink2Reader : ZipBinaryReader
{
public NodeLink2[] read(ZipArchive file, string filename, int[] indexToNode)
public NodeLink2[] Read(ZipArchive file, string filename, int[] indexToNode)
{
ByteBuffer buffer = toByteBuffer(file, filename);
int linkCount = buffer.getInt();
ByteBuffer buffer = ToByteBuffer(file, filename);
int linkCount = buffer.GetInt();
NodeLink2[] links = new NodeLink2[linkCount];
for (int i = 0; i < linkCount; i++)
{
long linkID = buffer.getLong();
int startNode = indexToNode[buffer.getInt()];
int endNode = indexToNode[buffer.getInt()];
int connectedNode1 = buffer.getInt();
int connectedNode2 = buffer.getInt();
long linkID = buffer.GetLong();
int startNode = indexToNode[buffer.GetInt()];
int endNode = indexToNode[buffer.GetInt()];
int connectedNode1 = buffer.GetInt();
int connectedNode2 = buffer.GetInt();
Vector3f clamped1 = new Vector3f();
clamped1.x = buffer.getFloat();
clamped1.y = buffer.getFloat();
clamped1.z = buffer.getFloat();
clamped1.x = buffer.GetFloat();
clamped1.y = buffer.GetFloat();
clamped1.z = buffer.GetFloat();
Vector3f clamped2 = new Vector3f();
clamped2.x = buffer.getFloat();
clamped2.y = buffer.getFloat();
clamped2.z = buffer.getFloat();
bool postScanCalled = buffer.get() != 0;
clamped2.x = buffer.GetFloat();
clamped2.y = buffer.GetFloat();
clamped2.z = buffer.GetFloat();
bool postScanCalled = buffer.Get() != 0;
links[i] = new NodeLink2(linkID, startNode, endNode, clamped1, clamped2);
}

View File

@ -22,16 +22,16 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
public class OffMeshLinkCreator
{
public void build(GraphMeshData graphData, NodeLink2[] links, int nodeOffset)
public void Build(GraphMeshData graphData, NodeLink2[] links, int nodeOffset)
{
if (links.Length > 0)
{
foreach (NodeLink2 l in links)
{
MeshData startTile = graphData.getTile(l.startNode - nodeOffset);
Poly startNode = graphData.getNode(l.startNode - nodeOffset);
MeshData endTile = graphData.getTile(l.endNode - nodeOffset);
Poly endNode = graphData.getNode(l.endNode - nodeOffset);
MeshData startTile = graphData.GetTile(l.startNode - nodeOffset);
Poly startNode = graphData.GetNode(l.startNode - nodeOffset);
MeshData endTile = graphData.GetTile(l.endNode - nodeOffset);
Poly endNode = graphData.GetNode(l.endNode - nodeOffset);
if (startNode != null && endNode != null)
{
// FIXME: Optimise
@ -40,7 +40,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
startTile.polys[poly] = new Poly(poly, 2);
startTile.polys[poly].verts[0] = startTile.header.vertCount;
startTile.polys[poly].verts[1] = startTile.header.vertCount + 1;
startTile.polys[poly].setType(Poly.DT_POLYTYPE_OFFMESH_CONNECTION);
startTile.polys[poly].SetType(Poly.DT_POLYTYPE_OFFMESH_CONNECTION);
startTile.verts = ArrayUtils.CopyOf(startTile.verts, startTile.verts.Length + 6);
startTile.header.polyCount++;
startTile.header.vertCount += 2;
@ -54,7 +54,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
connection.rad = 0.1f;
connection.side = startTile == endTile
? 0xFF
: NavMeshBuilder.classifyOffMeshPoint(new VectorPtr(connection.pos, 3),
: NavMeshBuilder.ClassifyOffMeshPoint(new VectorPtr(connection.pos, 3),
startTile.header.bmin, startTile.header.bmax);
connection.userId = (int)l.linkID;
if (startTile.offMeshCons == null)

View File

@ -33,9 +33,9 @@ namespace DotRecast.Detour.Extras.Unity.Astar
private readonly LinkBuilder linkCreator = new LinkBuilder();
private readonly OffMeshLinkCreator offMeshLinkCreator = new OffMeshLinkCreator();
public NavMesh[] load(FileStream zipFile)
public NavMesh[] Load(FileStream zipFile)
{
GraphData graphData = reader.read(zipFile);
GraphData graphData = reader.Read(zipFile);
Meta meta = graphData.meta;
NodeLink2[] nodeLinks2 = graphData.nodeLinks2;
NavMesh[] meshes = new NavMesh[meta.graphs];
@ -45,7 +45,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
GraphMeta graphMeta = graphData.graphMeta[graphIndex];
GraphMeshData graphMeshData = graphData.graphMeshData[graphIndex];
List<int[]> connections = graphData.graphConnections[graphIndex];
int nodeCount = graphMeshData.countNodes();
int nodeCount = graphMeshData.CountNodes();
if (connections.Count != nodeCount)
{
throw new ArgumentException("Inconsistent number of nodes in data file: " + nodeCount
@ -53,11 +53,11 @@ namespace DotRecast.Detour.Extras.Unity.Astar
}
// Build BV tree
bvTreeCreator.build(graphMeshData);
bvTreeCreator.Build(graphMeshData);
// Create links between nodes (both internal and portals between tiles)
linkCreator.build(nodeOffset, graphMeshData, connections);
linkCreator.Build(nodeOffset, graphMeshData, connections);
// Finally, process all the off-mesh links that can be actually converted to detour data
offMeshLinkCreator.build(graphMeshData, nodeLinks2, nodeOffset);
offMeshLinkCreator.Build(graphMeshData, nodeLinks2, nodeOffset);
NavMeshParams option = new NavMeshParams();
option.maxTiles = graphMeshData.tiles.Length;
option.maxPolys = 32768;
@ -69,11 +69,11 @@ namespace DotRecast.Detour.Extras.Unity.Astar
NavMesh mesh = new NavMesh(option, 3);
foreach (MeshData t in graphMeshData.tiles)
{
mesh.addTile(t, 0, 0);
mesh.AddTile(t, 0, 0);
}
meshes[graphIndex] = mesh;
nodeOffset += graphMeshData.countNodes();
nodeOffset += graphMeshData.CountNodes();
}
return meshes;

View File

@ -38,27 +38,27 @@ namespace DotRecast.Detour.Extras.Unity.Astar
private readonly GraphConnectionReader graphConnectionReader = new GraphConnectionReader();
private readonly NodeLink2Reader nodeLink2Reader = new NodeLink2Reader();
public GraphData read(FileStream zipFile)
public GraphData Read(FileStream zipFile)
{
using ZipArchive file = new ZipArchive(zipFile);
// Read meta file and check version and graph type
Meta meta = metaReader.read(file, META_FILE_NAME);
Meta meta = metaReader.Read(file, META_FILE_NAME);
// Read index to node mapping
int[] indexToNode = nodeIndexReader.read(file, NODE_INDEX_FILE_NAME);
int[] indexToNode = nodeIndexReader.Read(file, NODE_INDEX_FILE_NAME);
// Read NodeLink2 data (off-mesh links)
NodeLink2[] nodeLinks2 = nodeLink2Reader.read(file, NODE_LINK_2_FILE_NAME, indexToNode);
NodeLink2[] nodeLinks2 = nodeLink2Reader.Read(file, NODE_LINK_2_FILE_NAME, indexToNode);
// Read graph by graph
List<GraphMeta> metaList = new List<GraphMeta>();
List<GraphMeshData> meshDataList = new List<GraphMeshData>();
List<List<int[]>> connectionsList = new List<List<int[]>>();
for (int graphIndex = 0; graphIndex < meta.graphs; graphIndex++)
{
GraphMeta graphMeta = graphMetaReader.read(file, string.Format(GRAPH_META_FILE_NAME_PATTERN, graphIndex));
GraphMeta graphMeta = graphMetaReader.Read(file, string.Format(GRAPH_META_FILE_NAME_PATTERN, graphIndex));
// First graph mesh data - vertices and polygons
GraphMeshData graphData = graphDataReader.read(file,
GraphMeshData graphData = graphDataReader.Read(file,
string.Format(GRAPH_DATA_FILE_NAME_PATTERN, graphIndex), graphMeta, MAX_VERTS_PER_POLY);
// Then graph connection data - links between nodes located in both the same tile and other tiles
List<int[]> connections = graphConnectionReader.read(file,
List<int[]> connections = graphConnectionReader.Read(file,
string.Format(GRAPH_CONNECTION_FILE_NAME_PATTERN, graphIndex), meta, indexToNode);
metaList.Add(graphMeta);
meshDataList.Add(graphData);

View File

@ -25,13 +25,13 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{
public abstract class ZipBinaryReader
{
protected ByteBuffer toByteBuffer(ZipArchive file, string filename)
protected ByteBuffer ToByteBuffer(ZipArchive file, string filename)
{
ZipArchiveEntry graphReferences = file.GetEntry(filename);
using var entryStream = graphReferences.Open();
using var bis = new BinaryReader(entryStream);
ByteBuffer buffer = IOUtils.toByteBuffer(bis);
buffer.order(ByteOrder.LITTLE_ENDIAN);
ByteBuffer buffer = IOUtils.ToByteBuffer(bis);
buffer.Order(ByteOrder.LITTLE_ENDIAN);
return buffer;
}
}

View File

@ -29,31 +29,31 @@ namespace DotRecast.Detour.TileCache
{
public abstract class AbstractTileLayersBuilder
{
protected List<byte[]> build(ByteOrder order, bool cCompatibility, int threads, int tw, int th)
protected List<byte[]> Build(ByteOrder order, bool cCompatibility, int threads, int tw, int th)
{
if (threads == 1)
{
return buildSingleThread(order, cCompatibility, tw, th);
return BuildSingleThread(order, cCompatibility, tw, th);
}
return buildMultiThread(order, cCompatibility, tw, th, threads);
return BuildMultiThread(order, cCompatibility, tw, th, threads);
}
private List<byte[]> buildSingleThread(ByteOrder order, bool cCompatibility, int tw, int th)
private List<byte[]> BuildSingleThread(ByteOrder order, bool cCompatibility, int tw, int th)
{
List<byte[]> layers = new List<byte[]>();
for (int y = 0; y < th; ++y)
{
for (int x = 0; x < tw; ++x)
{
layers.AddRange(build(x, y, order, cCompatibility));
layers.AddRange(Build(x, y, order, cCompatibility));
}
}
return layers;
}
private List<byte[]> buildMultiThread(ByteOrder order, bool cCompatibility, int tw, int th, int threads)
private List<byte[]> BuildMultiThread(ByteOrder order, bool cCompatibility, int tw, int th, int threads)
{
var tasks = new ConcurrentQueue<Task<Tuple<int, int, List<byte[]>>>>();
for (int y = 0; y < th; ++y)
@ -64,7 +64,7 @@ namespace DotRecast.Detour.TileCache
int ty = y;
var task = Task.Run(() =>
{
var partial = build(tx, ty, order, cCompatibility);
var partial = Build(tx, ty, order, cCompatibility);
return Tuple.Create(tx, ty, partial);
});
tasks.Enqueue(task);
@ -88,6 +88,6 @@ namespace DotRecast.Detour.TileCache
return layers;
}
protected abstract List<byte[]> build(int tx, int ty, ByteOrder order, bool cCompatibility);
protected abstract List<byte[]> Build(int tx, int ty, ByteOrder order, bool cCompatibility);
}
}

View File

@ -54,13 +54,13 @@ namespace DotRecast.Detour.TileCache.Io.Compress
static readonly int MAX_CHUNK_LENGTH = 0xFFFF;
/**
* Do not call {@link #compress(byte[], int, int, byte[], int, int)} for input buffers
* Do not call {@link #Compress(byte[], int, int, byte[], int, int)} for input buffers
* which length less than this value.
*/
static readonly int MIN_LENGTH_TO_COMPRESSION = 32;
/**
* In this case {@link #compress(byte[], int, int, byte[], int, int)} will choose level
* In this case {@link #Compress(byte[], int, int, byte[], int, int)} will choose level
* automatically depending on the length of the input buffer. If length less than
* {@link #MIN_RECOMENDED_LENGTH_FOR_LEVEL_2} {@link #LEVEL_1} will be choosen,
* otherwise {@link #LEVEL_2}.
@ -82,7 +82,7 @@ namespace DotRecast.Detour.TileCache.Io.Compress
* @param inputLength length of input buffer
* @return Maximum output buffer length
*/
public static int calculateOutputBufferLength(int inputLength)
public static int CalculateOutputBufferLength(int inputLength)
{
int tempOutputLength = (int)(inputLength * 1.06);
return Math.Max(tempOutputLength, 66);
@ -94,7 +94,7 @@ namespace DotRecast.Detour.TileCache.Io.Compress
*
* If the input is not compressible, the return value might be larger than length (input buffer size).
*/
public static int compress(byte[] input, int inOffset, int inLength,
public static int Compress(byte[] input, int inOffset, int inLength,
byte[] output, int outOffset, int proposedLevel)
{
int level;
@ -178,9 +178,9 @@ namespace DotRecast.Detour.TileCache.Io.Compress
/* check for a run */
if (level == LEVEL_2)
{
//if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
//If(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
if (input[inOffset + ip] == input[inOffset + ip - 1] &&
readU16(input, inOffset + ip - 1) == readU16(input, inOffset + ip + 1))
ReadU16(input, inOffset + ip - 1) == ReadU16(input, inOffset + ip + 1))
{
distance = 1;
ip += 3;
@ -197,7 +197,7 @@ namespace DotRecast.Detour.TileCache.Io.Compress
{
/* find potential match */
// HASH_FUNCTION(hval,ip);
hval = hashFunction(input, inOffset + ip);
hval = HashFunction(input, inOffset + ip);
// hslot = htab + hval;
hslot = hval;
// refs = htab[hval];
@ -258,7 +258,7 @@ namespace DotRecast.Detour.TileCache.Io.Compress
len += 2;
}
}
} // end if(!matchLabel)
} // end If(!matchLabel)
/*
* match:
@ -440,11 +440,11 @@ namespace DotRecast.Detour.TileCache.Io.Compress
/* update the hash at match boundary */
//HASH_FUNCTION(hval,ip);
hval = hashFunction(input, inOffset + ip);
hval = HashFunction(input, inOffset + ip);
htab[hval] = ip++;
//HASH_FUNCTION(hval,ip);
hval = hashFunction(input, inOffset + ip);
hval = HashFunction(input, inOffset + ip);
htab[hval] = ip++;
/* assuming literal copy */
@ -459,7 +459,7 @@ namespace DotRecast.Detour.TileCache.Io.Compress
output[outOffset + op++] = input[inOffset + anchor++];
ip = anchor;
copy++;
if(copy == MAX_COPY){
If(copy == MAX_COPY){
copy = 0;
output[outOffset + op++] = MAX_COPY-1;
}
@ -507,7 +507,7 @@ namespace DotRecast.Detour.TileCache.Io.Compress
* Decompression is memory safe and guaranteed not to write the output buffer
* more than what is specified in outLength.
*/
public static int decompress(byte[] input, int inOffset, int inLength,
public static int Decompress(byte[] input, int inOffset, int inLength,
byte[] output, int outOffset, int outLength)
{
//int level = ((*(const flzuint8*)input) >> 5) + 1;
@ -569,8 +569,8 @@ namespace DotRecast.Detour.TileCache.Io.Compress
refs -= code;
/* match from 16-bit distance */
// if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
// if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
// If(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
// If(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
if (code == 255 && ofs == 31 << 8)
{
ofs = (input[inOffset + ip++] & 0xFF) << 8;
@ -580,7 +580,7 @@ namespace DotRecast.Detour.TileCache.Io.Compress
}
}
// if the output index + length of block(?) + 3(?) is over the output limit?
// if the output index + length of Block(?) + 3(?) is over the output limit?
if (op + len + 3 > outLength)
{
return 0;
@ -665,22 +665,22 @@ namespace DotRecast.Detour.TileCache.Io.Compress
}
}
// while(FASTLZ_EXPECT_CONDITIONAL(loop));
// While(FASTLZ_EXPECT_CONDITIONAL(loop));
} while (loop != 0);
// return op - (flzuint8*)output;
return op;
}
private static int hashFunction(byte[] p, int offset)
private static int HashFunction(byte[] p, int offset)
{
int v = readU16(p, offset);
v ^= readU16(p, offset + 1) ^ v >> 16 - HASH_LOG;
int v = ReadU16(p, offset);
v ^= ReadU16(p, offset + 1) ^ v >> 16 - HASH_LOG;
v &= HASH_MASK;
return v;
}
private static int readU16(byte[] data, int offset)
private static int ReadU16(byte[] data, int offset)
{
if (offset + 1 >= data.Length)
{

View File

@ -24,17 +24,17 @@ namespace DotRecast.Detour.TileCache.Io.Compress
{
public class FastLzTileCacheCompressor : TileCacheCompressor
{
public byte[] decompress(byte[] buf, int offset, int len, int outputlen)
public byte[] Decompress(byte[] buf, int offset, int len, int outputlen)
{
byte[] output = new byte[outputlen];
FastLz.decompress(buf, offset, len, output, 0, outputlen);
FastLz.Decompress(buf, offset, len, output, 0, outputlen);
return output;
}
public byte[] compress(byte[] buf)
public byte[] Compress(byte[] buf)
{
byte[] output = new byte[FastLz.calculateOutputBufferLength(buf.Length)];
int len = FastLz.compress(buf, 0, buf.Length, output, 0, output.Length);
byte[] output = new byte[FastLz.CalculateOutputBufferLength(buf.Length)];
int len = FastLz.Compress(buf, 0, buf.Length, output, 0, output.Length);
return ArrayUtils.CopyOf(output, len);
}
}

View File

@ -24,12 +24,12 @@ namespace DotRecast.Detour.TileCache.Io.Compress
{
public class LZ4TileCacheCompressor : TileCacheCompressor
{
public byte[] decompress(byte[] buf, int offset, int len, int outputlen)
public byte[] Decompress(byte[] buf, int offset, int len, int outputlen)
{
return LZ4Pickler.Unpickle(buf, offset, len);
}
public byte[] compress(byte[] buf)
public byte[] Compress(byte[] buf)
{
return LZ4Pickler.Pickle(buf);
}

View File

@ -22,7 +22,7 @@ namespace DotRecast.Detour.TileCache.Io.Compress
{
public static class TileCacheCompressorFactory
{
public static TileCacheCompressor get(bool cCompatibility)
public static TileCacheCompressor Get(bool cCompatibility)
{
if (cCompatibility)
return new FastLzTileCacheCompressor();

View File

@ -25,39 +25,39 @@ namespace DotRecast.Detour.TileCache.Io
{
public class TileCacheLayerHeaderReader
{
public TileCacheLayerHeader read(ByteBuffer data, bool cCompatibility)
public TileCacheLayerHeader Read(ByteBuffer data, bool cCompatibility)
{
TileCacheLayerHeader header = new TileCacheLayerHeader();
header.magic = data.getInt();
header.version = data.getInt();
header.magic = data.GetInt();
header.version = data.GetInt();
if (header.magic != TileCacheLayerHeader.DT_TILECACHE_MAGIC)
throw new IOException("Invalid magic");
if (header.version != TileCacheLayerHeader.DT_TILECACHE_VERSION)
throw new IOException("Invalid version");
header.tx = data.getInt();
header.ty = data.getInt();
header.tlayer = data.getInt();
header.tx = data.GetInt();
header.ty = data.GetInt();
header.tlayer = data.GetInt();
header.bmin.x = data.getFloat();
header.bmin.y = data.getFloat();
header.bmin.z = data.getFloat();
header.bmax.x = data.getFloat();
header.bmax.y = data.getFloat();
header.bmax.z = data.getFloat();
header.bmin.x = data.GetFloat();
header.bmin.y = data.GetFloat();
header.bmin.z = data.GetFloat();
header.bmax.x = data.GetFloat();
header.bmax.y = data.GetFloat();
header.bmax.z = data.GetFloat();
header.hmin = data.getShort() & 0xFFFF;
header.hmax = data.getShort() & 0xFFFF;
header.width = data.get() & 0xFF;
header.height = data.get() & 0xFF;
header.minx = data.get() & 0xFF;
header.maxx = data.get() & 0xFF;
header.miny = data.get() & 0xFF;
header.maxy = data.get() & 0xFF;
header.hmin = data.GetShort() & 0xFFFF;
header.hmax = data.GetShort() & 0xFFFF;
header.width = data.Get() & 0xFF;
header.height = data.Get() & 0xFF;
header.minx = data.Get() & 0xFF;
header.maxx = data.Get() & 0xFF;
header.miny = data.Get() & 0xFF;
header.maxy = data.Get() & 0xFF;
if (cCompatibility)
{
data.getShort(); // C struct padding
data.GetShort(); // C struct padding
}
return header;

View File

@ -26,32 +26,32 @@ namespace DotRecast.Detour.TileCache.Io
{
public class TileCacheLayerHeaderWriter : DetourWriter
{
public void write(BinaryWriter stream, TileCacheLayerHeader header, ByteOrder order, bool cCompatibility)
public void Write(BinaryWriter stream, TileCacheLayerHeader header, ByteOrder order, bool cCompatibility)
{
write(stream, header.magic, order);
write(stream, header.version, order);
write(stream, header.tx, order);
write(stream, header.ty, order);
write(stream, header.tlayer, order);
Write(stream, header.magic, order);
Write(stream, header.version, order);
Write(stream, header.tx, order);
Write(stream, header.ty, order);
Write(stream, header.tlayer, order);
write(stream, header.bmin.x, order);
write(stream, header.bmin.y, order);
write(stream, header.bmin.z, order);
write(stream, header.bmax.x, order);
write(stream, header.bmax.y, order);
write(stream, header.bmax.z, order);
Write(stream, header.bmin.x, order);
Write(stream, header.bmin.y, order);
Write(stream, header.bmin.z, order);
Write(stream, header.bmax.x, order);
Write(stream, header.bmax.y, order);
Write(stream, header.bmax.z, order);
write(stream, (short)header.hmin, order);
write(stream, (short)header.hmax, order);
write(stream, (byte)header.width);
write(stream, (byte)header.height);
write(stream, (byte)header.minx);
write(stream, (byte)header.maxx);
write(stream, (byte)header.miny);
write(stream, (byte)header.maxy);
Write(stream, (short)header.hmin, order);
Write(stream, (short)header.hmax, order);
Write(stream, (byte)header.width);
Write(stream, (byte)header.height);
Write(stream, (byte)header.minx);
Write(stream, (byte)header.maxx);
Write(stream, (byte)header.miny);
Write(stream, (byte)header.maxy);
if (cCompatibility)
{
write(stream, (short)0, order); // C struct padding
Write(stream, (short)0, order); // C struct padding
}
}
}

View File

@ -29,28 +29,28 @@ namespace DotRecast.Detour.TileCache.Io
{
private readonly NavMeshParamReader paramReader = new NavMeshParamReader();
public TileCache read(BinaryReader @is, int maxVertPerPoly, TileCacheMeshProcess meshProcessor)
public TileCache Read(BinaryReader @is, int maxVertPerPoly, TileCacheMeshProcess meshProcessor)
{
ByteBuffer bb = IOUtils.toByteBuffer(@is);
return read(bb, maxVertPerPoly, meshProcessor);
ByteBuffer bb = IOUtils.ToByteBuffer(@is);
return Read(bb, maxVertPerPoly, meshProcessor);
}
public TileCache read(ByteBuffer bb, int maxVertPerPoly, TileCacheMeshProcess meshProcessor)
public TileCache Read(ByteBuffer bb, int maxVertPerPoly, TileCacheMeshProcess meshProcessor)
{
TileCacheSetHeader header = new TileCacheSetHeader();
header.magic = bb.getInt();
header.magic = bb.GetInt();
if (header.magic != TileCacheSetHeader.TILECACHESET_MAGIC)
{
header.magic = IOUtils.swapEndianness(header.magic);
header.magic = IOUtils.SwapEndianness(header.magic);
if (header.magic != TileCacheSetHeader.TILECACHESET_MAGIC)
{
throw new IOException("Invalid magic");
}
bb.order(bb.order() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
bb.Order(bb.Order() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
}
header.version = bb.getInt();
header.version = bb.GetInt();
if (header.version != TileCacheSetHeader.TILECACHESET_VERSION)
{
if (header.version != TileCacheSetHeader.TILECACHESET_VERSION_RECAST4J)
@ -60,52 +60,52 @@ namespace DotRecast.Detour.TileCache.Io
}
bool cCompatibility = header.version == TileCacheSetHeader.TILECACHESET_VERSION;
header.numTiles = bb.getInt();
header.meshParams = paramReader.read(bb);
header.cacheParams = readCacheParams(bb, cCompatibility);
header.numTiles = bb.GetInt();
header.meshParams = paramReader.Read(bb);
header.cacheParams = ReadCacheParams(bb, cCompatibility);
NavMesh mesh = new NavMesh(header.meshParams, maxVertPerPoly);
TileCacheCompressor compressor = TileCacheCompressorFactory.get(cCompatibility);
TileCache tc = new TileCache(header.cacheParams, new TileCacheStorageParams(bb.order(), cCompatibility), mesh,
TileCacheCompressor compressor = TileCacheCompressorFactory.Get(cCompatibility);
TileCache tc = new TileCache(header.cacheParams, new TileCacheStorageParams(bb.Order(), cCompatibility), mesh,
compressor, meshProcessor);
// Read tiles.
for (int i = 0; i < header.numTiles; ++i)
{
long tileRef = bb.getInt();
int dataSize = bb.getInt();
long tileRef = bb.GetInt();
int dataSize = bb.GetInt();
if (tileRef == 0 || dataSize == 0)
{
break;
}
byte[] data = bb.ReadBytes(dataSize).ToArray();
long tile = tc.addTile(data, 0);
long tile = tc.AddTile(data, 0);
if (tile != 0)
{
tc.buildNavMeshTile(tile);
tc.BuildNavMeshTile(tile);
}
}
return tc;
}
private TileCacheParams readCacheParams(ByteBuffer bb, bool cCompatibility)
private TileCacheParams ReadCacheParams(ByteBuffer bb, bool cCompatibility)
{
TileCacheParams option = new TileCacheParams();
option.orig.x = bb.getFloat();
option.orig.y = bb.getFloat();
option.orig.z = bb.getFloat();
option.orig.x = bb.GetFloat();
option.orig.y = bb.GetFloat();
option.orig.z = bb.GetFloat();
option.cs = bb.getFloat();
option.ch = bb.getFloat();
option.width = bb.getInt();
option.height = bb.getInt();
option.walkableHeight = bb.getFloat();
option.walkableRadius = bb.getFloat();
option.walkableClimb = bb.getFloat();
option.maxSimplificationError = bb.getFloat();
option.maxTiles = bb.getInt();
option.maxObstacles = bb.getInt();
option.cs = bb.GetFloat();
option.ch = bb.GetFloat();
option.width = bb.GetInt();
option.height = bb.GetInt();
option.walkableHeight = bb.GetFloat();
option.walkableRadius = bb.GetFloat();
option.walkableClimb = bb.GetFloat();
option.maxSimplificationError = bb.GetFloat();
option.maxTiles = bb.GetInt();
option.maxObstacles = bb.GetInt();
return option;
}
}

View File

@ -29,54 +29,54 @@ namespace DotRecast.Detour.TileCache.Io
private readonly NavMeshParamWriter paramWriter = new NavMeshParamWriter();
private readonly TileCacheBuilder builder = new TileCacheBuilder();
public void write(BinaryWriter stream, TileCache cache, ByteOrder order, bool cCompatibility)
public void Write(BinaryWriter stream, TileCache cache, ByteOrder order, bool cCompatibility)
{
write(stream, TileCacheSetHeader.TILECACHESET_MAGIC, order);
write(stream, cCompatibility
Write(stream, TileCacheSetHeader.TILECACHESET_MAGIC, order);
Write(stream, cCompatibility
? TileCacheSetHeader.TILECACHESET_VERSION
: TileCacheSetHeader.TILECACHESET_VERSION_RECAST4J, order);
int numTiles = 0;
for (int i = 0; i < cache.getTileCount(); ++i)
for (int i = 0; i < cache.GetTileCount(); ++i)
{
CompressedTile tile = cache.getTile(i);
CompressedTile tile = cache.GetTile(i);
if (tile == null || tile.data == null)
continue;
numTiles++;
}
write(stream, numTiles, order);
paramWriter.write(stream, cache.getNavMesh().getParams(), order);
writeCacheParams(stream, cache.getParams(), order);
for (int i = 0; i < cache.getTileCount(); i++)
Write(stream, numTiles, order);
paramWriter.Write(stream, cache.GetNavMesh().GetParams(), order);
WriteCacheParams(stream, cache.GetParams(), order);
for (int i = 0; i < cache.GetTileCount(); i++)
{
CompressedTile tile = cache.getTile(i);
CompressedTile tile = cache.GetTile(i);
if (tile == null || tile.data == null)
continue;
write(stream, (int)cache.getTileRef(tile), order);
Write(stream, (int)cache.GetTileRef(tile), order);
byte[] data = tile.data;
TileCacheLayer layer = cache.decompressTile(tile);
data = builder.compressTileCacheLayer(layer, order, cCompatibility);
write(stream, data.Length, order);
TileCacheLayer layer = cache.DecompressTile(tile);
data = builder.CompressTileCacheLayer(layer, order, cCompatibility);
Write(stream, data.Length, order);
stream.Write(data);
}
}
private void writeCacheParams(BinaryWriter stream, TileCacheParams option, ByteOrder order)
private void WriteCacheParams(BinaryWriter stream, TileCacheParams option, ByteOrder order)
{
write(stream, option.orig.x, order);
write(stream, option.orig.y, order);
write(stream, option.orig.z, order);
Write(stream, option.orig.x, order);
Write(stream, option.orig.y, order);
Write(stream, option.orig.z, order);
write(stream, option.cs, order);
write(stream, option.ch, order);
write(stream, option.width, order);
write(stream, option.height, order);
write(stream, option.walkableHeight, order);
write(stream, option.walkableRadius, order);
write(stream, option.walkableClimb, order);
write(stream, option.maxSimplificationError, order);
write(stream, option.maxTiles, order);
write(stream, option.maxObstacles, order);
Write(stream, option.cs, order);
Write(stream, option.ch, order);
Write(stream, option.width, order);
Write(stream, option.height, order);
Write(stream, option.walkableHeight, order);
Write(stream, option.walkableRadius, order);
Write(stream, option.walkableClimb, order);
Write(stream, option.maxSimplificationError, order);
Write(stream, option.maxTiles, order);
Write(stream, option.maxObstacles, order);
}
}
}

View File

@ -66,46 +66,46 @@ namespace DotRecast.Detour.TileCache
private readonly TileCacheBuilder builder = new TileCacheBuilder();
private readonly TileCacheLayerHeaderReader tileReader = new TileCacheLayerHeaderReader();
private bool contains(List<long> a, long v)
private bool Contains(List<long> a, long v)
{
return a.Contains(v);
}
/// Encodes a tile id.
private long encodeTileId(int salt, int it)
private long EncodeTileId(int salt, int it)
{
return ((long)salt << m_tileBits) | it;
}
/// Decodes a tile salt.
private int decodeTileIdSalt(long refs)
private int DecodeTileIdSalt(long refs)
{
long saltMask = (1L << m_saltBits) - 1;
return (int)((refs >> m_tileBits) & saltMask);
}
/// Decodes a tile id.
private int decodeTileIdTile(long refs)
private int DecodeTileIdTile(long refs)
{
long tileMask = (1L << m_tileBits) - 1;
return (int)(refs & tileMask);
}
/// Encodes an obstacle id.
private long encodeObstacleId(int salt, int it)
private long EncodeObstacleId(int salt, int it)
{
return ((long)salt << 16) | it;
}
/// Decodes an obstacle salt.
private int decodeObstacleIdSalt(long refs)
private int DecodeObstacleIdSalt(long refs)
{
long saltMask = ((long)1 << 16) - 1;
return (int)((refs >> 16) & saltMask);
}
/// Decodes an obstacle id.
private int decodeObstacleIdObstacle(long refs)
private int DecodeObstacleIdObstacle(long refs)
{
long tileMask = ((long)1 << 16) - 1;
return (int)(refs & tileMask);
@ -120,7 +120,7 @@ namespace DotRecast.Detour.TileCache
m_tcomp = tcomp;
m_tmproc = tmprocs;
m_tileLutSize = nextPow2(m_params.maxTiles / 4);
m_tileLutSize = NextPow2(m_params.maxTiles / 4);
if (m_tileLutSize == 0)
{
m_tileLutSize = 1;
@ -136,7 +136,7 @@ namespace DotRecast.Detour.TileCache
m_nextFreeTile = m_tiles[i];
}
m_tileBits = ilog2(nextPow2(m_params.maxTiles));
m_tileBits = Ilog2(NextPow2(m_params.maxTiles));
m_saltBits = Math.Min(31, 32 - m_tileBits);
if (m_saltBits < 10)
{
@ -144,15 +144,15 @@ namespace DotRecast.Detour.TileCache
}
}
public CompressedTile getTileByRef(long refs)
public CompressedTile GetTileByRef(long refs)
{
if (refs == 0)
{
return null;
}
int tileIndex = decodeTileIdTile(refs);
int tileSalt = decodeTileIdSalt(refs);
int tileIndex = DecodeTileIdTile(refs);
int tileSalt = DecodeTileIdSalt(refs);
if (tileIndex >= m_params.maxTiles)
{
return null;
@ -167,18 +167,18 @@ namespace DotRecast.Detour.TileCache
return tile;
}
public List<long> getTilesAt(int tx, int ty)
public List<long> GetTilesAt(int tx, int ty)
{
List<long> tiles = new List<long>();
// Find tile based on hash.
int h = NavMesh.computeTileHash(tx, ty, m_tileLutMask);
int h = NavMesh.ComputeTileHash(tx, ty, m_tileLutMask);
CompressedTile tile = m_posLookup[h];
while (tile != null)
{
if (tile.header != null && tile.header.tx == tx && tile.header.ty == ty)
{
tiles.Add(getTileRef(tile));
tiles.Add(GetTileRef(tile));
}
tile = tile.next;
@ -187,10 +187,10 @@ namespace DotRecast.Detour.TileCache
return tiles;
}
CompressedTile getTileAt(int tx, int ty, int tlayer)
CompressedTile GetTileAt(int tx, int ty, int tlayer)
{
// Find tile based on hash.
int h = NavMesh.computeTileHash(tx, ty, m_tileLutMask);
int h = NavMesh.ComputeTileHash(tx, ty, m_tileLutMask);
CompressedTile tile = m_posLookup[h];
while (tile != null)
{
@ -205,7 +205,7 @@ namespace DotRecast.Detour.TileCache
return null;
}
public long getTileRef(CompressedTile tile)
public long GetTileRef(CompressedTile tile)
{
if (tile == null)
{
@ -213,10 +213,10 @@ namespace DotRecast.Detour.TileCache
}
int it = tile.index;
return encodeTileId(tile.salt, it);
return EncodeTileId(tile.salt, it);
}
public long getObstacleRef(TileCacheObstacle ob)
public long GetObstacleRef(TileCacheObstacle ob)
{
if (ob == null)
{
@ -224,24 +224,24 @@ namespace DotRecast.Detour.TileCache
}
int idx = ob.index;
return encodeObstacleId(ob.salt, idx);
return EncodeObstacleId(ob.salt, idx);
}
public TileCacheObstacle getObstacleByRef(long refs)
public TileCacheObstacle GetObstacleByRef(long refs)
{
if (refs == 0)
{
return null;
}
int idx = decodeObstacleIdObstacle(refs);
int idx = DecodeObstacleIdObstacle(refs);
if (idx >= m_obstacles.Count)
{
return null;
}
TileCacheObstacle ob = m_obstacles[idx];
int salt = decodeObstacleIdSalt(refs);
int salt = DecodeObstacleIdSalt(refs);
if (ob.salt != salt)
{
return null;
@ -250,14 +250,14 @@ namespace DotRecast.Detour.TileCache
return ob;
}
public long addTile(byte[] data, int flags)
public long AddTile(byte[] data, int flags)
{
// Make sure the data is in right format.
ByteBuffer buf = new ByteBuffer(data);
buf.order(m_storageParams.byteOrder);
TileCacheLayerHeader header = tileReader.read(buf, m_storageParams.cCompatibility);
buf.Order(m_storageParams.byteOrder);
TileCacheLayerHeader header = tileReader.Read(buf, m_storageParams.cCompatibility);
// Make sure the location is free.
if (getTileAt(header.tx, header.ty, header.tlayer) != null)
if (GetTileAt(header.tx, header.ty, header.tlayer) != null)
{
return 0;
}
@ -278,33 +278,33 @@ namespace DotRecast.Detour.TileCache
}
// Insert tile into the position lut.
int h = NavMesh.computeTileHash(header.tx, header.ty, m_tileLutMask);
int h = NavMesh.ComputeTileHash(header.tx, header.ty, m_tileLutMask);
tile.next = m_posLookup[h];
m_posLookup[h] = tile;
// Init tile.
tile.header = header;
tile.data = data;
tile.compressed = align4(buf.position());
tile.compressed = Align4(buf.Position());
tile.flags = flags;
return getTileRef(tile);
return GetTileRef(tile);
}
private int align4(int i)
private int Align4(int i)
{
return (i + 3) & (~3);
}
public void removeTile(long refs)
public void RemoveTile(long refs)
{
if (refs == 0)
{
throw new Exception("Invalid tile ref");
}
int tileIndex = decodeTileIdTile(refs);
int tileSalt = decodeTileIdSalt(refs);
int tileIndex = DecodeTileIdTile(refs);
int tileSalt = DecodeTileIdSalt(refs);
if (tileIndex >= m_params.maxTiles)
{
throw new Exception("Invalid tile index");
@ -317,7 +317,7 @@ namespace DotRecast.Detour.TileCache
}
// Remove tile from hash lookup.
int h = NavMesh.computeTileHash(tile.header.tx, tile.header.ty, m_tileLutMask);
int h = NavMesh.ComputeTileHash(tile.header.tx, tile.header.ty, m_tileLutMask);
CompressedTile prev = null;
CompressedTile cur = m_posLookup[h];
while (cur != null)
@ -358,34 +358,34 @@ namespace DotRecast.Detour.TileCache
}
// Cylinder obstacle
public long addObstacle(Vector3f pos, float radius, float height)
public long AddObstacle(Vector3f pos, float radius, float height)
{
TileCacheObstacle ob = allocObstacle();
TileCacheObstacle ob = AllocObstacle();
ob.type = TileCacheObstacle.TileCacheObstacleType.CYLINDER;
ob.pos = pos;
ob.radius = radius;
ob.height = height;
return addObstacleRequest(ob).refs;
return AddObstacleRequest(ob).refs;
}
// Aabb obstacle
public long addBoxObstacle(Vector3f bmin, Vector3f bmax)
public long AddBoxObstacle(Vector3f bmin, Vector3f bmax)
{
TileCacheObstacle ob = allocObstacle();
TileCacheObstacle ob = AllocObstacle();
ob.type = TileCacheObstacle.TileCacheObstacleType.BOX;
ob.bmin = bmin;
ob.bmax = bmax;
return addObstacleRequest(ob).refs;
return AddObstacleRequest(ob).refs;
}
// Box obstacle: can be rotated in Y
public long addBoxObstacle(Vector3f center, Vector3f extents, float yRadians)
public long AddBoxObstacle(Vector3f center, Vector3f extents, float yRadians)
{
TileCacheObstacle ob = allocObstacle();
TileCacheObstacle ob = AllocObstacle();
ob.type = TileCacheObstacle.TileCacheObstacleType.ORIENTED_BOX;
ob.center = center;
ob.extents = extents;
@ -393,19 +393,19 @@ namespace DotRecast.Detour.TileCache
float sinhalf = (float)Math.Sin(-0.5f * yRadians);
ob.rotAux[0] = coshalf * sinhalf;
ob.rotAux[1] = coshalf * coshalf - 0.5f;
return addObstacleRequest(ob).refs;
return AddObstacleRequest(ob).refs;
}
private ObstacleRequest addObstacleRequest(TileCacheObstacle ob)
private ObstacleRequest AddObstacleRequest(TileCacheObstacle ob)
{
ObstacleRequest req = new ObstacleRequest();
req.action = ObstacleRequestAction.REQUEST_ADD;
req.refs = getObstacleRef(ob);
req.refs = GetObstacleRef(ob);
m_reqs.Add(req);
return req;
}
public void removeObstacle(long refs)
public void RemoveObstacle(long refs)
{
if (refs == 0)
{
@ -418,7 +418,7 @@ namespace DotRecast.Detour.TileCache
m_reqs.Add(req);
}
private TileCacheObstacle allocObstacle()
private TileCacheObstacle AllocObstacle()
{
TileCacheObstacle o = m_nextFreeObstacle;
if (o == null)
@ -438,7 +438,7 @@ namespace DotRecast.Detour.TileCache
return o;
}
List<long> queryTiles(Vector3f bmin, Vector3f bmax)
List<long> QueryTiles(Vector3f bmin, Vector3f bmax)
{
List<long> results = new List<long>();
float tw = m_params.width * m_params.cs;
@ -451,14 +451,14 @@ namespace DotRecast.Detour.TileCache
{
for (int tx = tx0; tx <= tx1; ++tx)
{
List<long> tiles = getTilesAt(tx, ty);
List<long> tiles = GetTilesAt(tx, ty);
foreach (long i in tiles)
{
CompressedTile tile = m_tiles[decodeTileIdTile(i)];
CompressedTile tile = m_tiles[DecodeTileIdTile(i)];
Vector3f tbmin = new Vector3f();
Vector3f tbmax = new Vector3f();
calcTightTileBounds(tile.header, ref tbmin, ref tbmax);
if (overlapBounds(bmin, bmax, tbmin, tbmax))
CalcTightTileBounds(tile.header, ref tbmin, ref tbmax);
if (OverlapBounds(bmin, bmax, tbmin, tbmax))
{
results.Add(i);
}
@ -476,21 +476,21 @@ namespace DotRecast.Detour.TileCache
* cache is up to date another (immediate) call to update will have no effect; otherwise another call will
* continue processing obstacle requests and tile rebuilds.
*/
public bool update()
public bool Update()
{
if (0 == m_update.Count)
{
// Process requests.
foreach (ObstacleRequest req in m_reqs)
{
int idx = decodeObstacleIdObstacle(req.refs);
int idx = DecodeObstacleIdObstacle(req.refs);
if (idx >= m_obstacles.Count)
{
continue;
}
TileCacheObstacle ob = m_obstacles[idx];
int salt = decodeObstacleIdSalt(req.refs);
int salt = DecodeObstacleIdSalt(req.refs);
if (ob.salt != salt)
{
continue;
@ -501,13 +501,13 @@ namespace DotRecast.Detour.TileCache
// Find touched tiles.
Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f();
getObstacleBounds(ob, ref bmin, ref bmax);
ob.touched = queryTiles(bmin, bmax);
GetObstacleBounds(ob, ref bmin, ref bmax);
ob.touched = QueryTiles(bmin, bmax);
// Add tiles to update list.
ob.pending.Clear();
foreach (long j in ob.touched)
{
if (!contains(m_update, j))
if (!Contains(m_update, j))
{
m_update.Add(j);
}
@ -523,7 +523,7 @@ namespace DotRecast.Detour.TileCache
ob.pending.Clear();
foreach (long j in ob.touched)
{
if (!contains(m_update, j))
if (!Contains(m_update, j))
{
m_update.Add(j);
}
@ -542,7 +542,7 @@ namespace DotRecast.Detour.TileCache
long refs = m_update[0];
m_update.RemoveAt(0);
// Build mesh
buildNavMeshTile(refs);
BuildNavMeshTile(refs);
// Update obstacle states.
for (int i = 0; i < m_obstacles.Count; ++i)
@ -583,16 +583,16 @@ namespace DotRecast.Detour.TileCache
return 0 == m_update.Count && 0 == m_reqs.Count;
}
public void buildNavMeshTile(long refs)
public void BuildNavMeshTile(long refs)
{
int idx = decodeTileIdTile(refs);
int idx = DecodeTileIdTile(refs);
if (idx > m_params.maxTiles)
{
throw new Exception("Invalid tile index");
}
CompressedTile tile = m_tiles[idx];
int salt = decodeTileIdSalt(refs);
int salt = DecodeTileIdSalt(refs);
if (tile.salt != salt)
{
throw new Exception("Invalid tile salt");
@ -601,7 +601,7 @@ namespace DotRecast.Detour.TileCache
int walkableClimbVx = (int)(m_params.walkableClimb / m_params.ch);
// Decompress tile layer data.
TileCacheLayer layer = decompressTile(tile);
TileCacheLayer layer = DecompressTile(tile);
// Rasterize obstacles.
for (int i = 0; i < m_obstacles.Count; ++i)
@ -612,32 +612,32 @@ namespace DotRecast.Detour.TileCache
continue;
}
if (contains(ob.touched, refs))
if (Contains(ob.touched, refs))
{
if (ob.type == TileCacheObstacle.TileCacheObstacleType.CYLINDER)
{
builder.markCylinderArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.pos, ob.radius, ob.height, 0);
builder.MarkCylinderArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.pos, ob.radius, ob.height, 0);
}
else if (ob.type == TileCacheObstacle.TileCacheObstacleType.BOX)
{
builder.markBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.bmin, ob.bmax, 0);
builder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.bmin, ob.bmax, 0);
}
else if (ob.type == TileCacheObstacle.TileCacheObstacleType.ORIENTED_BOX)
{
builder.markBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.center, ob.extents, ob.rotAux, 0);
builder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.center, ob.extents, ob.rotAux, 0);
}
}
}
// Build navmesh
builder.buildTileCacheRegions(layer, walkableClimbVx);
TileCacheContourSet lcset = builder.buildTileCacheContours(layer, walkableClimbVx,
builder.BuildTileCacheRegions(layer, walkableClimbVx);
TileCacheContourSet lcset = builder.BuildTileCacheContours(layer, walkableClimbVx,
m_params.maxSimplificationError);
TileCachePolyMesh polyMesh = builder.buildTileCachePolyMesh(lcset, m_navmesh.getMaxVertsPerPoly());
TileCachePolyMesh polyMesh = builder.BuildTileCachePolyMesh(lcset, m_navmesh.GetMaxVertsPerPoly());
// Early out if the mesh tile is empty.
if (polyMesh.npolys == 0)
{
m_navmesh.removeTile(m_navmesh.getTileRefAt(tile.header.tx, tile.header.ty, tile.header.tlayer));
m_navmesh.RemoveTile(m_navmesh.GetTileRefAt(tile.header.tx, tile.header.ty, tile.header.tlayer));
return;
}
@ -648,7 +648,7 @@ namespace DotRecast.Detour.TileCache
option.polyAreas = polyMesh.areas;
option.polyFlags = polyMesh.flags;
option.polyCount = polyMesh.npolys;
option.nvp = m_navmesh.getMaxVertsPerPoly();
option.nvp = m_navmesh.GetMaxVertsPerPoly();
option.walkableHeight = m_params.walkableHeight;
option.walkableRadius = m_params.walkableRadius;
option.walkableClimb = m_params.walkableClimb;
@ -662,27 +662,27 @@ namespace DotRecast.Detour.TileCache
option.bmax = tile.header.bmax;
if (m_tmproc != null)
{
m_tmproc.process(option);
m_tmproc.Process(option);
}
MeshData meshData = NavMeshBuilder.createNavMeshData(option);
MeshData meshData = NavMeshBuilder.CreateNavMeshData(option);
// Remove existing tile.
m_navmesh.removeTile(m_navmesh.getTileRefAt(tile.header.tx, tile.header.ty, tile.header.tlayer));
m_navmesh.RemoveTile(m_navmesh.GetTileRefAt(tile.header.tx, tile.header.ty, tile.header.tlayer));
// Add new tile, or leave the location empty. if (navData) { // Let the
if (meshData != null)
{
m_navmesh.addTile(meshData, 0, 0);
m_navmesh.AddTile(meshData, 0, 0);
}
}
public TileCacheLayer decompressTile(CompressedTile tile)
public TileCacheLayer DecompressTile(CompressedTile tile)
{
TileCacheLayer layer = builder.decompressTileCacheLayer(m_tcomp, tile.data, m_storageParams.byteOrder,
TileCacheLayer layer = builder.DecompressTileCacheLayer(m_tcomp, tile.data, m_storageParams.byteOrder,
m_storageParams.cCompatibility);
return layer;
}
void calcTightTileBounds(TileCacheLayerHeader header, ref Vector3f bmin, ref Vector3f bmax)
void CalcTightTileBounds(TileCacheLayerHeader header, ref Vector3f bmin, ref Vector3f bmax)
{
float cs = m_params.cs;
bmin.x = header.bmin.x + header.minx * cs;
@ -693,7 +693,7 @@ namespace DotRecast.Detour.TileCache
bmax.z = header.bmin.z + (header.maxy + 1) * cs;
}
void getObstacleBounds(TileCacheObstacle ob, ref Vector3f bmin, ref Vector3f bmax)
void GetObstacleBounds(TileCacheObstacle ob, ref Vector3f bmin, ref Vector3f bmax)
{
if (ob.type == TileCacheObstacle.TileCacheObstacleType.CYLINDER)
{
@ -721,27 +721,27 @@ namespace DotRecast.Detour.TileCache
}
}
public TileCacheParams getParams()
public TileCacheParams GetParams()
{
return m_params;
}
public TileCacheCompressor getCompressor()
public TileCacheCompressor GetCompressor()
{
return m_tcomp;
}
public int getTileCount()
public int GetTileCount()
{
return m_params.maxTiles;
}
public CompressedTile getTile(int i)
public CompressedTile GetTile(int i)
{
return m_tiles[i];
}
public NavMesh getNavMesh()
public NavMesh GetNavMesh()
{
return m_navmesh;
}

View File

@ -62,12 +62,12 @@ namespace DotRecast.Detour.TileCache
poly = new List<int>();
}
public int npoly()
public int Npoly()
{
return poly.Count;
}
public void clear()
public void Clear()
{
nverts = 0;
verts.Clear();
@ -83,7 +83,7 @@ namespace DotRecast.Detour.TileCache
private readonly TileCacheLayerHeaderReader reader = new TileCacheLayerHeaderReader();
public void buildTileCacheRegions(TileCacheLayer layer, int walkableClimb)
public void BuildTileCacheRegions(TileCacheLayer layer, int walkableClimb)
{
int w = layer.header.width;
int h = layer.header.height;
@ -107,7 +107,7 @@ namespace DotRecast.Detour.TileCache
Array.Fill(prevCount, 0, 0, regId);
}
// memset(prevCount,0,sizeof(char)*regId);
// Memset(prevCount,0,Sizeof(char)*regId);
int sweepId = 0;
for (int x = 0; x < w; ++x)
@ -120,7 +120,7 @@ namespace DotRecast.Detour.TileCache
// -x
int xidx = (x - 1) + y * w;
if (x > 0 && isConnected(layer, idx, xidx, walkableClimb))
if (x > 0 && IsConnected(layer, idx, xidx, walkableClimb))
{
if (layer.regs[xidx] != 0xff)
sid = layer.regs[xidx];
@ -135,7 +135,7 @@ namespace DotRecast.Detour.TileCache
// -y
int yidx = x + (y - 1) * w;
if (y > 0 && isConnected(layer, idx, yidx, walkableClimb))
if (y > 0 && IsConnected(layer, idx, yidx, walkableClimb))
{
int nr = layer.regs[yidx];
if (nr != 0xff)
@ -221,13 +221,13 @@ namespace DotRecast.Detour.TileCache
// Update neighbours
int ymi = x + (y - 1) * w;
if (y > 0 && isConnected(layer, idx, ymi, walkableClimb))
if (y > 0 && IsConnected(layer, idx, ymi, walkableClimb))
{
int rai = layer.regs[ymi];
if (rai != 0xff && rai != ri)
{
addUniqueLast(regs[ri].neis, rai);
addUniqueLast(regs[rai].neis, ri);
AddUniqueLast(regs[ri].neis, rai);
AddUniqueLast(regs[rai].neis, ri);
}
}
}
@ -251,7 +251,7 @@ namespace DotRecast.Detour.TileCache
continue;
if (regn.area > mergea)
{
if (canMerge(reg.regId, regn.regId, regs, nregs))
if (CanMerge(reg.regId, regn.regId, regs, nregs))
{
mergea = regn.area;
merge = nei;
@ -291,7 +291,7 @@ namespace DotRecast.Detour.TileCache
}
}
void addUniqueLast(List<int> a, int v)
void AddUniqueLast(List<int> a, int v)
{
int n = a.Count;
if (n > 0 && a[n - 1] == v)
@ -299,7 +299,7 @@ namespace DotRecast.Detour.TileCache
a.Add(v);
}
bool isConnected(TileCacheLayer layer, int ia, int ib, int walkableClimb)
bool IsConnected(TileCacheLayer layer, int ia, int ib, int walkableClimb)
{
if (layer.areas[ia] != layer.areas[ib])
return false;
@ -308,7 +308,7 @@ namespace DotRecast.Detour.TileCache
return true;
}
bool canMerge(int oldRegId, int newRegId, LayerMonotoneRegion[] regs, int nregs)
bool CanMerge(int oldRegId, int newRegId, LayerMonotoneRegion[] regs, int nregs)
{
int count = 0;
for (int i = 0; i < nregs; ++i)
@ -326,7 +326,7 @@ namespace DotRecast.Detour.TileCache
return count == 1;
}
private void appendVertex(TempContour cont, int x, int y, int z, int r)
private void AppendVertex(TempContour cont, int x, int y, int z, int r)
{
// Try to merge with existing segments.
if (cont.nverts > 1)
@ -360,7 +360,7 @@ namespace DotRecast.Detour.TileCache
cont.nverts++;
}
private int getNeighbourReg(TileCacheLayer layer, int ax, int ay, int dir)
private int GetNeighbourReg(TileCacheLayer layer, int ax, int ay, int dir)
{
int w = layer.header.width;
int ia = ax + ay * w;
@ -377,30 +377,30 @@ namespace DotRecast.Detour.TileCache
return 0xff;
}
int bx = ax + getDirOffsetX(dir);
int by = ay + getDirOffsetY(dir);
int bx = ax + GetDirOffsetX(dir);
int by = ay + GetDirOffsetY(dir);
int ib = bx + by * w;
return layer.regs[ib];
}
private int getDirOffsetX(int dir)
private int GetDirOffsetX(int dir)
{
int[] offset = new int[] { -1, 0, 1, 0, };
return offset[dir & 0x03];
}
private int getDirOffsetY(int dir)
private int GetDirOffsetY(int dir)
{
int[] offset = new int[] { 0, 1, 0, -1 };
return offset[dir & 0x03];
}
private void walkContour(TileCacheLayer layer, int x, int y, TempContour cont)
private void WalkContour(TileCacheLayer layer, int x, int y, TempContour cont)
{
int w = layer.header.width;
int h = layer.header.height;
cont.clear();
cont.Clear();
int startX = x;
int startY = y;
@ -409,7 +409,7 @@ namespace DotRecast.Detour.TileCache
for (int i = 0; i < 4; ++i)
{
int ndir = (i + 3) & 3;
int rn = getNeighbourReg(layer, x, y, ndir);
int rn = GetNeighbourReg(layer, x, y, ndir);
if (rn != layer.regs[x + y * w])
{
startDir = ndir;
@ -425,7 +425,7 @@ namespace DotRecast.Detour.TileCache
int iter = 0;
while (iter < maxIter)
{
int rn = getNeighbourReg(layer, x, y, dir);
int rn = GetNeighbourReg(layer, x, y, dir);
int nx = x;
int ny = y;
@ -451,14 +451,14 @@ namespace DotRecast.Detour.TileCache
}
// Try to merge with previous vertex.
appendVertex(cont, px, layer.heights[x + y * w], pz, rn);
AppendVertex(cont, px, layer.heights[x + y * w], pz, rn);
ndir = (dir + 1) & 0x3; // Rotate CW
}
else
{
// Move to next.
nx = x + getDirOffsetX(dir);
ny = y + getDirOffsetY(dir);
nx = x + GetDirOffsetX(dir);
ny = y + GetDirOffsetY(dir);
ndir = (dir + 3) & 0x3; // Rotate CCW
}
@ -480,7 +480,7 @@ namespace DotRecast.Detour.TileCache
cont.nverts--;
}
private float distancePtSeg(int x, int z, int px, int pz, int qx, int qz)
private float DistancePtSeg(int x, int z, int px, int pz, int qx, int qz)
{
float pqx = qx - px;
float pqz = qz - pz;
@ -501,7 +501,7 @@ namespace DotRecast.Detour.TileCache
return dx * dx + dz * dz;
}
private void simplifyContour(TempContour cont, float maxError)
private void SimplifyContour(TempContour cont, float maxError)
{
cont.poly.Clear();
@ -515,7 +515,7 @@ namespace DotRecast.Detour.TileCache
cont.poly.Add(i);
}
if (cont.npoly() < 2)
if (cont.Npoly() < 2)
{
// If there is no transitions at all,
// create some initial points for the simplification process.
@ -552,9 +552,9 @@ namespace DotRecast.Detour.TileCache
// Add points until all raw points are within
// error tolerance to the simplified shape.
for (int i = 0; i < cont.npoly();)
for (int i = 0; i < cont.Npoly();)
{
int ii = (i + 1) % cont.npoly();
int ii = (i + 1) % cont.Npoly();
int ai = cont.poly[i];
int ax = cont.verts[ai * 4];
@ -588,7 +588,7 @@ namespace DotRecast.Detour.TileCache
// Tessellate only outer edges or edges between areas.
while (ci != endi)
{
float d = distancePtSeg(cont.verts[ci * 4], cont.verts[ci * 4 + 2], ax, az, bx, bz);
float d = DistancePtSeg(cont.verts[ci * 4], cont.verts[ci * 4 + 2], ax, az, bx, bz);
if (d > maxd)
{
maxd = d;
@ -612,14 +612,14 @@ namespace DotRecast.Detour.TileCache
// Remap vertices
int start = 0;
for (int i = 1; i < cont.npoly(); ++i)
for (int i = 1; i < cont.Npoly(); ++i)
if (cont.poly[i] < cont.poly[start])
start = i;
cont.nverts = 0;
for (int i = 0; i < cont.npoly(); ++i)
for (int i = 0; i < cont.Npoly(); ++i)
{
int j = (start + i) % cont.npoly();
int j = (start + i) % cont.Npoly();
int src = cont.poly[j] * 4;
int dst = cont.nverts * 4;
cont.verts[dst] = cont.verts[src];
@ -630,7 +630,7 @@ namespace DotRecast.Detour.TileCache
}
}
static Tuple<int, bool> getCornerHeight(TileCacheLayer layer, int x, int y, int z, int walkableClimb)
static Tuple<int, bool> GetCornerHeight(TileCacheLayer layer, int x, int y, int z, int walkableClimb)
{
int w = layer.header.width;
int h = layer.header.height;
@ -680,7 +680,7 @@ namespace DotRecast.Detour.TileCache
}
// TODO: move this somewhere else, once the layer meshing is done.
public TileCacheContourSet buildTileCacheContours(TileCacheLayer layer, int walkableClimb, float maxError)
public TileCacheContourSet BuildTileCacheContours(TileCacheLayer layer, int walkableClimb, float maxError)
{
int w = layer.header.width;
int h = layer.header.height;
@ -714,9 +714,9 @@ namespace DotRecast.Detour.TileCache
cont.reg = ri;
cont.area = layer.areas[idx];
walkContour(layer, x, y, temp);
WalkContour(layer, x, y, temp);
simplifyContour(temp, maxError);
SimplifyContour(temp, maxError);
// Store contour.
cont.nverts = temp.nverts;
@ -734,7 +734,7 @@ namespace DotRecast.Detour.TileCache
// stored at segment
// vertex of a
// segment.
Tuple<int, bool> res = getCornerHeight(layer, temp.verts[v], temp.verts[v + 1],
Tuple<int, bool> res = GetCornerHeight(layer, temp.verts[v], temp.verts[v + 1],
temp.verts[v + 2], walkableClimb);
int lh = res.Item1;
bool shouldRemove = res.Item2;
@ -759,7 +759,7 @@ namespace DotRecast.Detour.TileCache
const uint VERTEX_BUCKET_COUNT2 = (1 << 8);
private int computeVertexHash2(int x, int y, int z)
private int ComputeVertexHash2(int x, int y, int z)
{
uint h1 = 0x8da6b343; // Large multiplicative constants;
uint h2 = 0xd8163841; // here arbitrarily chosen primes
@ -768,9 +768,9 @@ namespace DotRecast.Detour.TileCache
return (int)(n & (VERTEX_BUCKET_COUNT2 - 1));
}
private int addVertex(int x, int y, int z, int[] verts, int[] firstVert, int[] nextVert, int nv)
private int AddVertex(int x, int y, int z, int[] verts, int[] firstVert, int[] nextVert, int nv)
{
int bucket = computeVertexHash2(x, 0, z);
int bucket = ComputeVertexHash2(x, 0, z);
int i = firstVert[bucket];
while (i != DT_TILECACHE_NULL_IDX)
{
@ -791,7 +791,7 @@ namespace DotRecast.Detour.TileCache
return i;
}
private void buildMeshAdjacency(int[] polys, int npolys, int[] verts, int nverts, TileCacheContourSet lcset,
private void BuildMeshAdjacency(int[] polys, int npolys, int[] verts, int nverts, TileCacheContourSet lcset,
int maxVertsPerPoly)
{
// Based on code by Eric Lengyel from:
@ -932,7 +932,7 @@ namespace DotRecast.Detour.TileCache
ezmax = tmp;
}
if (overlapRangeExl(zmin, zmax, ezmin, ezmax))
if (OverlapRangeExl(zmin, zmax, ezmin, ezmax))
{
// Reuse the other polyedge to store dir.
e.polyEdge[1] = dir;
@ -972,7 +972,7 @@ namespace DotRecast.Detour.TileCache
exmax = tmp;
}
if (overlapRangeExl(xmin, xmax, exmin, exmax))
if (OverlapRangeExl(xmin, xmax, exmin, exmax))
{
// Reuse the other polyedge to store dir.
e.polyEdge[1] = dir;
@ -1002,22 +1002,22 @@ namespace DotRecast.Detour.TileCache
}
}
private bool overlapRangeExl(int amin, int amax, int bmin, int bmax)
private bool OverlapRangeExl(int amin, int amax, int bmin, int bmax)
{
return (amin >= bmax || amax <= bmin) ? false : true;
}
private int prev(int i, int n)
private int Prev(int i, int n)
{
return i - 1 >= 0 ? i - 1 : n - 1;
}
private int next(int i, int n)
private int Next(int i, int n)
{
return i + 1 < n ? i + 1 : 0;
}
private int area2(int[] verts, int a, int b, int c)
private int Area2(int[] verts, int a, int b, int c)
{
return (verts[b] - verts[a]) * (verts[c + 2] - verts[a + 2])
- (verts[c] - verts[a]) * (verts[b + 2] - verts[a + 2]);
@ -1025,39 +1025,39 @@ namespace DotRecast.Detour.TileCache
// Returns true iff c is strictly to the left of the directed
// line through a to b.
private bool left(int[] verts, int a, int b, int c)
private bool Left(int[] verts, int a, int b, int c)
{
return area2(verts, a, b, c) < 0;
return Area2(verts, a, b, c) < 0;
}
private bool leftOn(int[] verts, int a, int b, int c)
private bool LeftOn(int[] verts, int a, int b, int c)
{
return area2(verts, a, b, c) <= 0;
return Area2(verts, a, b, c) <= 0;
}
private bool collinear(int[] verts, int a, int b, int c)
private bool Collinear(int[] verts, int a, int b, int c)
{
return area2(verts, a, b, c) == 0;
return Area2(verts, a, b, c) == 0;
}
// Returns true iff ab properly intersects cd: they share
// a point interior to both segments. The properness of the
// intersection is ensured by using strict leftness.
private bool intersectProp(int[] verts, int a, int b, int c, int d)
private bool IntersectProp(int[] verts, int a, int b, int c, int d)
{
// Eliminate improper cases.
if (collinear(verts, a, b, c) || collinear(verts, a, b, d) || collinear(verts, c, d, a)
|| collinear(verts, c, d, b))
if (Collinear(verts, a, b, c) || Collinear(verts, a, b, d) || Collinear(verts, c, d, a)
|| Collinear(verts, c, d, b))
return false;
return (left(verts, a, b, c) ^ left(verts, a, b, d)) && (left(verts, c, d, a) ^ left(verts, c, d, b));
return (Left(verts, a, b, c) ^ Left(verts, a, b, d)) && (Left(verts, c, d, a) ^ Left(verts, c, d, b));
}
// Returns T iff (a,b,c) are collinear and point c lies
// on the closed segement ab.
private bool between(int[] verts, int a, int b, int c)
private bool Between(int[] verts, int a, int b, int c)
{
if (!collinear(verts, a, b, c))
if (!Collinear(verts, a, b, c))
return false;
// If ab not vertical, check betweenness on x; else on y.
if (verts[a] != verts[b])
@ -1069,25 +1069,25 @@ namespace DotRecast.Detour.TileCache
}
// Returns true iff segments ab and cd intersect, properly or improperly.
private bool intersect(int[] verts, int a, int b, int c, int d)
private bool Intersect(int[] verts, int a, int b, int c, int d)
{
if (intersectProp(verts, a, b, c, d))
if (IntersectProp(verts, a, b, c, d))
return true;
else if (between(verts, a, b, c) || between(verts, a, b, d) || between(verts, c, d, a)
|| between(verts, c, d, b))
else if (Between(verts, a, b, c) || Between(verts, a, b, d) || Between(verts, c, d, a)
|| Between(verts, c, d, b))
return true;
else
return false;
}
private bool vequal(int[] verts, int a, int b)
private bool Vequal(int[] verts, int a, int b)
{
return verts[a] == verts[b] && verts[a + 2] == verts[b + 2];
}
// Returns T iff (v_i, v_j) is a proper internal *or* external
// diagonal of P, *ignoring edges incident to v_i and v_j*.
private bool diagonalie(int i, int j, int n, int[] verts, int[] indices)
private bool Diagonalie(int i, int j, int n, int[] verts, int[] indices)
{
int d0 = (indices[i] & 0x7fff) * 4;
int d1 = (indices[j] & 0x7fff) * 4;
@ -1095,17 +1095,17 @@ namespace DotRecast.Detour.TileCache
// For each edge (k,k+1) of P
for (int k = 0; k < n; k++)
{
int k1 = next(k, n);
int k1 = Next(k, n);
// Skip edges incident to i or j
if (!((k == i) || (k1 == i) || (k == j) || (k1 == j)))
{
int p0 = (indices[k] & 0x7fff) * 4;
int p1 = (indices[k1] & 0x7fff) * 4;
if (vequal(verts, d0, p0) || vequal(verts, d1, p0) || vequal(verts, d0, p1) || vequal(verts, d1, p1))
if (Vequal(verts, d0, p0) || Vequal(verts, d1, p0) || Vequal(verts, d0, p1) || Vequal(verts, d1, p1))
continue;
if (intersect(verts, d0, d1, p0, p1))
if (Intersect(verts, d0, d1, p0, p1))
return false;
}
}
@ -1115,29 +1115,29 @@ namespace DotRecast.Detour.TileCache
// Returns true iff the diagonal (i,j) is strictly internal to the
// polygon P in the neighborhood of the i endpoint.
private bool inCone(int i, int j, int n, int[] verts, int[] indices)
private bool InCone(int i, int j, int n, int[] verts, int[] indices)
{
int pi = (indices[i] & 0x7fff) * 4;
int pj = (indices[j] & 0x7fff) * 4;
int pi1 = (indices[next(i, n)] & 0x7fff) * 4;
int pin1 = (indices[prev(i, n)] & 0x7fff) * 4;
int pi1 = (indices[Next(i, n)] & 0x7fff) * 4;
int pin1 = (indices[Prev(i, n)] & 0x7fff) * 4;
// If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
if (leftOn(verts, pin1, pi, pi1))
return left(verts, pi, pj, pin1) && left(verts, pj, pi, pi1);
if (LeftOn(verts, pin1, pi, pi1))
return Left(verts, pi, pj, pin1) && Left(verts, pj, pi, pi1);
// Assume (i-1,i,i+1) not collinear.
// else P[i] is reflex.
return !(leftOn(verts, pi, pj, pi1) && leftOn(verts, pj, pi, pin1));
return !(LeftOn(verts, pi, pj, pi1) && LeftOn(verts, pj, pi, pin1));
}
// Returns T iff (v_i, v_j) is a proper internal
// diagonal of P.
private bool diagonal(int i, int j, int n, int[] verts, int[] indices)
private bool Diagonal(int i, int j, int n, int[] verts, int[] indices)
{
return inCone(i, j, n, verts, indices) && diagonalie(i, j, n, verts, indices);
return InCone(i, j, n, verts, indices) && Diagonalie(i, j, n, verts, indices);
}
private int triangulate(int n, int[] verts, int[] indices, int[] tris)
private int Triangulate(int n, int[] verts, int[] indices, int[] tris)
{
int ntris = 0;
int dst = 0; // tris;
@ -1145,9 +1145,9 @@ namespace DotRecast.Detour.TileCache
// removed.
for (int i = 0; i < n; i++)
{
int i1 = next(i, n);
int i2 = next(i1, n);
if (diagonal(i, i2, n, verts, indices))
int i1 = Next(i, n);
int i2 = Next(i1, n);
if (Diagonal(i, i2, n, verts, indices))
indices[i1] |= 0x8000;
}
@ -1157,11 +1157,11 @@ namespace DotRecast.Detour.TileCache
int mini = -1;
for (int mi = 0; mi < n; mi++)
{
int mi1 = next(mi, n);
int mi1 = Next(mi, n);
if ((indices[mi1] & 0x8000) != 0)
{
int p0 = (indices[mi] & 0x7fff) * 4;
int p2 = (indices[next(mi1, n)] & 0x7fff) * 4;
int p2 = (indices[Next(mi1, n)] & 0x7fff) * 4;
int dx = verts[p2] - verts[p0];
int dz = verts[p2 + 2] - verts[p0 + 2];
@ -1178,15 +1178,15 @@ namespace DotRecast.Detour.TileCache
{
// Should not happen.
/*
* printf("mini == -1 ntris=%d n=%d\n", ntris, n); for (int i = 0; i < n; i++) { printf("%d ",
* indices[i] & 0x0fffffff); } printf("\n");
* Printf("mini == -1 ntris=%d n=%d\n", ntris, n); for (int i = 0; i < n; i++) { Printf("%d ",
* indices[i] & 0x0fffffff); } Printf("\n");
*/
return -ntris;
}
int i = mini;
int i1 = next(i, n);
int i2 = next(i1, n);
int i1 = Next(i, n);
int i2 = Next(i1, n);
tris[dst++] = indices[i] & 0x7fff;
tris[dst++] = indices[i1] & 0x7fff;
@ -1200,14 +1200,14 @@ namespace DotRecast.Detour.TileCache
if (i1 >= n)
i1 = 0;
i = prev(i1, n);
i = Prev(i1, n);
// Update diagonal flags.
if (diagonal(prev(i, n), i1, n, verts, indices))
if (Diagonal(Prev(i, n), i1, n, verts, indices))
indices[i] |= 0x8000;
else
indices[i] &= 0x7fff;
if (diagonal(i, next(i1, n), n, verts, indices))
if (Diagonal(i, Next(i1, n), n, verts, indices))
indices[i1] |= 0x8000;
else
indices[i1] &= 0x7fff;
@ -1222,7 +1222,7 @@ namespace DotRecast.Detour.TileCache
return ntris;
}
private int countPolyVerts(int[] polys, int p, int maxVertsPerPoly)
private int CountPolyVerts(int[] polys, int p, int maxVertsPerPoly)
{
for (int i = 0; i < maxVertsPerPoly; ++i)
if (polys[p + i] == DT_TILECACHE_NULL_IDX)
@ -1230,16 +1230,16 @@ namespace DotRecast.Detour.TileCache
return maxVertsPerPoly;
}
private bool uleft(int[] verts, int a, int b, int c)
private bool Uleft(int[] verts, int a, int b, int c)
{
return (verts[b] - verts[a]) * (verts[c + 2] - verts[a + 2])
- (verts[c] - verts[a]) * (verts[b + 2] - verts[a + 2]) < 0;
}
private int[] getPolyMergeValue(int[] polys, int pa, int pb, int[] verts, int maxVertsPerPoly)
private int[] GetPolyMergeValue(int[] polys, int pa, int pb, int[] verts, int maxVertsPerPoly)
{
int na = countPolyVerts(polys, pa, maxVertsPerPoly);
int nb = countPolyVerts(polys, pb, maxVertsPerPoly);
int na = CountPolyVerts(polys, pa, maxVertsPerPoly);
int nb = CountPolyVerts(polys, pb, maxVertsPerPoly);
// If the merged polygon would be too big, do not merge.
if (na + nb - 2 > maxVertsPerPoly)
@ -1290,13 +1290,13 @@ namespace DotRecast.Detour.TileCache
va = polys[pa + (ea + na - 1) % na];
vb = polys[pa + ea];
vc = polys[pb + (eb + 2) % nb];
if (!uleft(verts, va * 3, vb * 3, vc * 3))
if (!Uleft(verts, va * 3, vb * 3, vc * 3))
return new int[] { -1, ea, eb };
va = polys[pb + (eb + nb - 1) % nb];
vb = polys[pb + eb];
vc = polys[pa + (ea + 2) % na];
if (!uleft(verts, va * 3, vb * 3, vc * 3))
if (!Uleft(verts, va * 3, vb * 3, vc * 3))
return new int[] { -1, ea, eb };
va = polys[pa + ea];
@ -1308,12 +1308,12 @@ namespace DotRecast.Detour.TileCache
return new int[] { dx * dx + dy * dy, ea, eb };
}
private void mergePolys(int[] polys, int pa, int pb, int ea, int eb, int maxVertsPerPoly)
private void MergePolys(int[] polys, int pa, int pb, int ea, int eb, int maxVertsPerPoly)
{
int[] tmp = new int[maxVertsPerPoly * 2];
int na = countPolyVerts(polys, pa, maxVertsPerPoly);
int nb = countPolyVerts(polys, pb, maxVertsPerPoly);
int na = CountPolyVerts(polys, pa, maxVertsPerPoly);
int nb = CountPolyVerts(polys, pb, maxVertsPerPoly);
// Merge polygons.
Array.Fill(tmp, DT_TILECACHE_NULL_IDX);
@ -1327,19 +1327,19 @@ namespace DotRecast.Detour.TileCache
Array.Copy(tmp, 0, polys, pa, maxVertsPerPoly);
}
private int pushFront(int v, List<int> arr)
private int PushFront(int v, List<int> arr)
{
arr.Insert(0, v);
return arr.Count;
}
private int pushBack(int v, List<int> arr)
private int PushBack(int v, List<int> arr)
{
arr.Add(v);
return arr.Count;
}
private bool canRemoveVertex(TileCachePolyMesh mesh, int rem)
private bool CanRemoveVertex(TileCachePolyMesh mesh, int rem)
{
// Count number of polygons to remove.
int maxVertsPerPoly = mesh.nvp;
@ -1347,7 +1347,7 @@ namespace DotRecast.Detour.TileCache
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * mesh.nvp * 2;
int nv = countPolyVerts(mesh.polys, p, maxVertsPerPoly);
int nv = CountPolyVerts(mesh.polys, p, maxVertsPerPoly);
int numRemoved = 0;
int numVerts = 0;
for (int j = 0; j < nv; ++j)
@ -1380,7 +1380,7 @@ namespace DotRecast.Detour.TileCache
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * mesh.nvp * 2;
int nv = countPolyVerts(mesh.polys, p, maxVertsPerPoly);
int nv = CountPolyVerts(mesh.polys, p, maxVertsPerPoly);
// Collect edges which touches the removed vertex.
for (int j = 0, k = nv - 1; j < nv; k = j++)
@ -1437,7 +1437,7 @@ namespace DotRecast.Detour.TileCache
return true;
}
private void removeVertex(TileCachePolyMesh mesh, int rem, int maxTris)
private void RemoveVertex(TileCachePolyMesh mesh, int rem, int maxTris)
{
// Count number of polygons to remove.
int maxVertsPerPoly = mesh.nvp;
@ -1445,7 +1445,7 @@ namespace DotRecast.Detour.TileCache
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * maxVertsPerPoly * 2;
int nv = countPolyVerts(mesh.polys, p, maxVertsPerPoly);
int nv = CountPolyVerts(mesh.polys, p, maxVertsPerPoly);
for (int j = 0; j < nv; ++j)
{
if (mesh.polys[p + j] == rem)
@ -1462,7 +1462,7 @@ namespace DotRecast.Detour.TileCache
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * maxVertsPerPoly * 2;
int nv = countPolyVerts(mesh.polys, p, maxVertsPerPoly);
int nv = CountPolyVerts(mesh.polys, p, maxVertsPerPoly);
bool hasRem = false;
for (int j = 0; j < nv; ++j)
if (mesh.polys[p + j] == rem)
@ -1505,7 +1505,7 @@ namespace DotRecast.Detour.TileCache
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * maxVertsPerPoly * 2;
int nv = countPolyVerts(mesh.polys, p, maxVertsPerPoly);
int nv = CountPolyVerts(mesh.polys, p, maxVertsPerPoly);
for (int j = 0; j < nv; ++j)
if (mesh.polys[p + j] > rem)
mesh.polys[p + j]--;
@ -1524,8 +1524,8 @@ namespace DotRecast.Detour.TileCache
// Start with one vertex, keep appending connected
// segments to the start and end of the hole.
nhole = pushBack(edges[0], hole);
pushBack(edges[2], harea);
nhole = PushBack(edges[0], hole);
PushBack(edges[2], harea);
while (nedges != 0)
{
@ -1540,15 +1540,15 @@ namespace DotRecast.Detour.TileCache
if (hole[0] == eb)
{
// The segment matches the beginning of the hole boundary.
nhole = pushFront(ea, hole);
pushFront(a, harea);
nhole = PushFront(ea, hole);
PushFront(a, harea);
add = true;
}
else if (hole[nhole - 1] == ea)
{
// The segment matches the end of the hole boundary.
nhole = pushBack(eb, hole);
pushBack(a, harea);
nhole = PushBack(eb, hole);
PushBack(a, harea);
add = true;
}
@ -1584,7 +1584,7 @@ namespace DotRecast.Detour.TileCache
}
// Triangulate the hole.
int ntris = triangulate(nhole, tverts, tpoly, tris);
int ntris = Triangulate(nhole, tverts, tpoly, tris);
if (ntris < 0)
{
// TODO: issue warning!
@ -1628,7 +1628,7 @@ namespace DotRecast.Detour.TileCache
for (int k = j + 1; k < npolys; ++k)
{
int pk = k * maxVertsPerPoly;
int[] pm = getPolyMergeValue(polys, pj, pk, mesh.verts, maxVertsPerPoly);
int[] pm = GetPolyMergeValue(polys, pj, pk, mesh.verts, maxVertsPerPoly);
int v = pm[0];
int ea = pm[1];
int eb = pm[2];
@ -1648,7 +1648,7 @@ namespace DotRecast.Detour.TileCache
// Found best, merge.
int pa = bestPa * maxVertsPerPoly;
int pb = bestPb * maxVertsPerPoly;
mergePolys(polys, pa, pb, bestEa, bestEb, maxVertsPerPoly);
MergePolys(polys, pa, pb, bestEa, bestEb, maxVertsPerPoly);
Array.Copy(polys, (npolys - 1) * maxVertsPerPoly, polys, pb, maxVertsPerPoly);
pareas[bestPb] = pareas[npolys - 1];
npolys--;
@ -1679,7 +1679,7 @@ namespace DotRecast.Detour.TileCache
}
}
public TileCachePolyMesh buildTileCachePolyMesh(TileCacheContourSet lcset, int maxVertsPerPoly)
public TileCachePolyMesh BuildTileCachePolyMesh(TileCacheContourSet lcset, int maxVertsPerPoly)
{
int maxVertices = 0;
int maxTris = 0;
@ -1733,7 +1733,7 @@ namespace DotRecast.Detour.TileCache
for (int j = 0; j < cont.nverts; ++j)
indices[j] = j;
int ntris = triangulate(cont.nverts, cont.verts, indices, tris);
int ntris = Triangulate(cont.nverts, cont.verts, indices, tris);
if (ntris <= 0)
{
// TODO: issue warning!
@ -1744,7 +1744,7 @@ namespace DotRecast.Detour.TileCache
for (int j = 0; j < cont.nverts; ++j)
{
int v = j * 4;
indices[j] = addVertex(cont.verts[v], cont.verts[v + 1], cont.verts[v + 2], mesh.verts, firstVert,
indices[j] = AddVertex(cont.verts[v], cont.verts[v + 1], cont.verts[v + 2], mesh.verts, firstVert,
nextVert, mesh.nverts);
mesh.nverts = Math.Max(mesh.nverts, indices[j] + 1);
if ((cont.verts[v + 3] & 0x80) != 0)
@ -1787,7 +1787,7 @@ namespace DotRecast.Detour.TileCache
for (int k = j + 1; k < npolys; ++k)
{
int pk = k * maxVertsPerPoly;
int[] pm = getPolyMergeValue(polys, pj, pk, mesh.verts, maxVertsPerPoly);
int[] pm = GetPolyMergeValue(polys, pj, pk, mesh.verts, maxVertsPerPoly);
int v = pm[0];
int ea = pm[1];
int eb = pm[2];
@ -1807,7 +1807,7 @@ namespace DotRecast.Detour.TileCache
// Found best, merge.
int pa = bestPa * maxVertsPerPoly;
int pb = bestPb * maxVertsPerPoly;
mergePolys(polys, pa, pb, bestEa, bestEb, maxVertsPerPoly);
MergePolys(polys, pa, pb, bestEa, bestEb, maxVertsPerPoly);
Array.Copy(polys, (npolys - 1) * maxVertsPerPoly, polys, pb, maxVertsPerPoly);
npolys--;
}
@ -1838,12 +1838,12 @@ namespace DotRecast.Detour.TileCache
{
if (vflags[i] != 0)
{
if (!canRemoveVertex(mesh, i))
if (!CanRemoveVertex(mesh, i))
continue;
removeVertex(mesh, i, maxTris);
RemoveVertex(mesh, i, maxTris);
// Remove vertex
// Note: mesh.nverts is already decremented inside
// removeVertex()!
// RemoveVertex()!
for (int j = i; j < mesh.nverts; ++j)
vflags[j] = vflags[j + 1];
--i;
@ -1851,12 +1851,12 @@ namespace DotRecast.Detour.TileCache
}
// Calculate adjacency.
buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.verts, mesh.nverts, lcset, maxVertsPerPoly);
BuildMeshAdjacency(mesh.polys, mesh.npolys, mesh.verts, mesh.nverts, lcset, maxVertsPerPoly);
return mesh;
}
public void markCylinderArea(TileCacheLayer layer, Vector3f orig, float cs, float ch, Vector3f pos, float radius, float height, int areaId)
public void MarkCylinderArea(TileCacheLayer layer, Vector3f orig, float cs, float ch, Vector3f pos, float radius, float height, int areaId)
{
Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f();
@ -1866,7 +1866,7 @@ namespace DotRecast.Detour.TileCache
bmax.x = pos.x + radius;
bmax.y = pos.y + height;
bmax.z = pos.z + radius;
float r2 = sqr(radius / cs + 0.5f);
float r2 = Sqr(radius / cs + 0.5f);
int w = layer.header.width;
int h = layer.header.height;
@ -1917,7 +1917,7 @@ namespace DotRecast.Detour.TileCache
}
}
public void markBoxArea(TileCacheLayer layer, Vector3f orig, float cs, float ch, Vector3f bmin, Vector3f bmax, int areaId)
public void MarkBoxArea(TileCacheLayer layer, Vector3f orig, float cs, float ch, Vector3f bmin, Vector3f bmax, int areaId)
{
int w = layer.header.width;
int h = layer.header.height;
@ -1961,14 +1961,14 @@ namespace DotRecast.Detour.TileCache
}
}
public byte[] compressTileCacheLayer(TileCacheLayer layer, ByteOrder order, bool cCompatibility)
public byte[] CompressTileCacheLayer(TileCacheLayer layer, ByteOrder order, bool cCompatibility)
{
using var ms = new MemoryStream();
using var baos = new BinaryWriter(ms);
TileCacheLayerHeaderWriter hw = new TileCacheLayerHeaderWriter();
try
{
hw.write(baos, layer.header, order, cCompatibility);
hw.Write(baos, layer.header, order, cCompatibility);
int gridSize = layer.header.width * layer.header.height;
byte[] buffer = new byte[gridSize * 3];
for (int i = 0; i < gridSize; i++)
@ -1978,7 +1978,7 @@ namespace DotRecast.Detour.TileCache
buffer[gridSize * 2 + i] = (byte)layer.cons[i];
}
baos.Write(TileCacheCompressorFactory.get(cCompatibility).compress(buffer));
baos.Write(TileCacheCompressorFactory.Get(cCompatibility).Compress(buffer));
return ms.ToArray();
}
catch (IOException e)
@ -1987,7 +1987,7 @@ namespace DotRecast.Detour.TileCache
}
}
public byte[] compressTileCacheLayer(TileCacheLayerHeader header, int[] heights, int[] areas, int[] cons,
public byte[] CompressTileCacheLayer(TileCacheLayerHeader header, int[] heights, int[] areas, int[] cons,
ByteOrder order, bool cCompatibility)
{
using var ms = new MemoryStream();
@ -1995,7 +1995,7 @@ namespace DotRecast.Detour.TileCache
TileCacheLayerHeaderWriter hw = new TileCacheLayerHeaderWriter();
try
{
hw.write(baos, header, order, cCompatibility);
hw.Write(baos, header, order, cCompatibility);
int gridSize = header.width * header.height;
byte[] buffer = new byte[gridSize * 3];
for (int i = 0; i < gridSize; i++)
@ -2005,7 +2005,7 @@ namespace DotRecast.Detour.TileCache
buffer[gridSize * 2 + i] = (byte)cons[i];
}
baos.Write(TileCacheCompressorFactory.get(cCompatibility).compress(buffer));
baos.Write(TileCacheCompressorFactory.Get(cCompatibility).Compress(buffer));
return ms.ToArray();
}
catch (IOException e)
@ -2014,15 +2014,15 @@ namespace DotRecast.Detour.TileCache
}
}
public TileCacheLayer decompressTileCacheLayer(TileCacheCompressor comp, byte[] compressed, ByteOrder order,
public TileCacheLayer DecompressTileCacheLayer(TileCacheCompressor comp, byte[] compressed, ByteOrder order,
bool cCompatibility)
{
ByteBuffer buf = new ByteBuffer(compressed);
buf.order(order);
buf.Order(order);
TileCacheLayer layer = new TileCacheLayer();
try
{
layer.header = reader.read(buf, cCompatibility);
layer.header = reader.Read(buf, cCompatibility);
}
catch (IOException e)
{
@ -2030,7 +2030,7 @@ namespace DotRecast.Detour.TileCache
}
int gridSize = layer.header.width * layer.header.height;
byte[] grids = comp.decompress(compressed, buf.position(), compressed.Length - buf.position(), gridSize * 3);
byte[] grids = comp.Decompress(compressed, buf.Position(), compressed.Length - buf.Position(), gridSize * 3);
layer.heights = new short[gridSize];
layer.areas = new short[gridSize];
layer.cons = new short[gridSize];
@ -2045,7 +2045,7 @@ namespace DotRecast.Detour.TileCache
return layer;
}
public void markBoxArea(TileCacheLayer layer, Vector3f orig, float cs, float ch, Vector3f center, Vector3f extents,
public void MarkBoxArea(TileCacheLayer layer, Vector3f orig, float cs, float ch, Vector3f center, Vector3f extents,
float[] rotAux, int areaId)
{
int w = layer.header.width;

View File

@ -22,8 +22,8 @@ namespace DotRecast.Detour.TileCache
{
public interface TileCacheCompressor
{
byte[] decompress(byte[] buf, int offset, int len, int outputlen);
byte[] Decompress(byte[] buf, int offset, int len, int outputlen);
byte[] compress(byte[] buf);
byte[] Compress(byte[] buf);
}
}

View File

@ -22,6 +22,6 @@ namespace DotRecast.Detour.TileCache
{
public interface TileCacheMeshProcess
{
void process(NavMeshDataCreateParams option);
void Process(NavMeshDataCreateParams option);
}
}

View File

@ -40,7 +40,7 @@ namespace DotRecast.Detour.TileCache
public float radius, height;
public Vector3f center = new Vector3f();
public Vector3f extents = new Vector3f();
public readonly float[] rotAux = new float[2]; // { cos(0.5f*angle)*sin(-0.5f*angle); cos(0.5f*angle)*cos(0.5f*angle) - 0.5 }
public readonly float[] rotAux = new float[2]; // { Cos(0.5f*angle)*Sin(-0.5f*angle); Cos(0.5f*angle)*Cos(0.5f*angle) - 0.5 }
public List<long> touched = new List<long>();
public readonly List<long> pending = new List<long>();
public int salt;

View File

@ -44,7 +44,7 @@ namespace DotRecast.Detour
Overlap,
}
public static float[] intersect(float[] p, float[] q)
public static float[] Intersect(float[] p, float[] q)
{
int n = p.Length / 3;
int m = q.Length / 3;
@ -68,24 +68,24 @@ namespace DotRecast.Detour
do
{
vCopy(ref a, p, 3 * (ai % n));
vCopy(ref b, q, 3 * (bi % m));
vCopy(ref a1, p, 3 * ((ai + n - 1) % n)); // prev a
vCopy(ref b1, q, 3 * ((bi + m - 1) % m)); // prev b
VCopy(ref a, p, 3 * (ai % n));
VCopy(ref b, q, 3 * (bi % m));
VCopy(ref a1, p, 3 * ((ai + n - 1) % n)); // prev a
VCopy(ref b1, q, 3 * ((bi + m - 1) % m)); // prev b
Vector3f A = vSub(a, a1);
Vector3f B = vSub(b, b1);
Vector3f A = VSub(a, a1);
Vector3f B = VSub(b, b1);
float cross = B.x * A.z - A.x * B.z; // triArea2D({0, 0}, A, B);
float aHB = triArea2D(b1, b, a);
float bHA = triArea2D(a1, a, b);
float cross = B.x * A.z - A.x * B.z; // TriArea2D({0, 0}, A, B);
float aHB = TriArea2D(b1, b, a);
float bHA = TriArea2D(a1, a, b);
if (Math.Abs(cross) < EPSILON)
{
cross = 0f;
}
bool parallel = cross == 0f;
Intersection code = parallel ? parallelInt(a1, a, b1, b, ref ip, ref iq) : segSegInt(a1, a, b1, b, ref ip, ref iq);
Intersection code = parallel ? ParallelInt(a1, a, b1, b, ref ip, ref iq) : SegSegInt(a1, a, b1, b, ref ip, ref iq);
if (code == Intersection.Single)
{
@ -95,17 +95,17 @@ namespace DotRecast.Detour
aa = ba = 0;
}
ii = addVertex(inters, ii, ip);
f = inOut(f, aHB, bHA);
ii = AddVertex(inters, ii, ip);
f = InOut(f, aHB, bHA);
}
/*-----Advance rules-----*/
/* Special case: A & B overlap and oppositely oriented. */
if (code == Intersection.Overlap && vDot2D(A, B) < 0)
if (code == Intersection.Overlap && VDot2D(A, B) < 0)
{
ii = addVertex(inters, ii, ip);
ii = addVertex(inters, ii, iq);
ii = AddVertex(inters, ii, ip);
ii = AddVertex(inters, ii, iq);
break;
}
@ -136,7 +136,7 @@ namespace DotRecast.Detour
{
if (f == InFlag.Pin)
{
ii = addVertex(inters, ii, a);
ii = AddVertex(inters, ii, a);
}
aa++;
@ -146,7 +146,7 @@ namespace DotRecast.Detour
{
if (f == InFlag.Qin)
{
ii = addVertex(inters, ii, b);
ii = AddVertex(inters, ii, b);
}
ba++;
@ -159,7 +159,7 @@ namespace DotRecast.Detour
{
if (f == InFlag.Qin)
{
ii = addVertex(inters, ii, b);
ii = AddVertex(inters, ii, b);
}
ba++;
@ -169,7 +169,7 @@ namespace DotRecast.Detour
{
if (f == InFlag.Pin)
{
ii = addVertex(inters, ii, a);
ii = AddVertex(inters, ii, a);
}
aa++;
@ -190,7 +190,7 @@ namespace DotRecast.Detour
return copied;
}
private static int addVertex(float[] inters, int ii, float[] p)
private static int AddVertex(float[] inters, int ii, float[] p)
{
if (ii > 0)
{
@ -211,7 +211,7 @@ namespace DotRecast.Detour
return ii + 3;
}
private static int addVertex(float[] inters, int ii, Vector3f p)
private static int AddVertex(float[] inters, int ii, Vector3f p)
{
if (ii > 0)
{
@ -233,7 +233,7 @@ namespace DotRecast.Detour
}
private static InFlag inOut(InFlag inflag, float aHB, float bHA)
private static InFlag InOut(InFlag inflag, float aHB, float bHA)
{
if (aHB > 0)
{
@ -247,9 +247,9 @@ namespace DotRecast.Detour
return inflag;
}
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)
{
var isec = intersectSegSeg2D(a, b, c, d);
var isec = IntersectSegSeg2D(a, b, c, d);
if (null != isec)
{
float s = isec.Item1;
@ -266,44 +266,44 @@ namespace DotRecast.Detour
return Intersection.None;
}
private static Intersection parallelInt(Vector3f a, Vector3f b, Vector3f c, Vector3f d, ref Vector3f p, ref Vector3f q)
private static Intersection ParallelInt(Vector3f a, Vector3f b, Vector3f c, Vector3f d, ref Vector3f p, ref Vector3f q)
{
if (between(a, b, c) && between(a, b, d))
if (Between(a, b, c) && Between(a, b, d))
{
p = c;
q = d;
return Intersection.Overlap;
}
if (between(c, d, a) && between(c, d, b))
if (Between(c, d, a) && Between(c, d, b))
{
p = a;
q = b;
return Intersection.Overlap;
}
if (between(a, b, c) && between(c, d, b))
if (Between(a, b, c) && Between(c, d, b))
{
p = c;
q = b;
return Intersection.Overlap;
}
if (between(a, b, c) && between(c, d, a))
if (Between(a, b, c) && Between(c, d, a))
{
p = c;
q = a;
return Intersection.Overlap;
}
if (between(a, b, d) && between(c, d, b))
if (Between(a, b, d) && Between(c, d, b))
{
p = d;
q = b;
return Intersection.Overlap;
}
if (between(a, b, d) && between(c, d, a))
if (Between(a, b, d) && Between(c, d, a))
{
p = d;
q = a;
@ -313,7 +313,7 @@ namespace DotRecast.Detour
return Intersection.None;
}
private static bool between(Vector3f a, Vector3f b, Vector3f c)
private static bool Between(Vector3f a, Vector3f b, Vector3f c)
{
if (Math.Abs(a.x - b.x) > Math.Abs(a.z - b.z))
{

View File

@ -39,7 +39,7 @@ namespace DotRecast.Detour
*
* <b>Custom Implementations</b>
*
* Implement a custom query filter by overriding the virtual passFilter() and getCost() functions. If this is done, both
* Implement a custom query filter by overriding the virtual PassFilter() and GetCost() functions. If this is done, both
* functions should be as fast as possible. Use cached local copies of data rather than accessing your own objects where
* possible.
*
@ -81,33 +81,33 @@ namespace DotRecast.Detour
}
}
public bool passFilter(long refs, MeshTile tile, Poly poly)
public bool PassFilter(long refs, MeshTile tile, Poly poly)
{
return (poly.flags & m_includeFlags) != 0 && (poly.flags & m_excludeFlags) == 0;
}
public float getCost(Vector3f pa, Vector3f pb, long prevRef, MeshTile prevTile, Poly prevPoly, long curRef,
public float GetCost(Vector3f pa, Vector3f pb, long prevRef, MeshTile prevTile, Poly prevPoly, long curRef,
MeshTile curTile, Poly curPoly, long nextRef, MeshTile nextTile, Poly nextPoly)
{
return vDist(pa, pb) * m_areaCost[curPoly.getArea()];
return VDist(pa, pb) * m_areaCost[curPoly.GetArea()];
}
public int getIncludeFlags()
public int GetIncludeFlags()
{
return m_includeFlags;
}
public void setIncludeFlags(int flags)
public void SetIncludeFlags(int flags)
{
m_includeFlags = flags;
}
public int getExcludeFlags()
public int GetExcludeFlags()
{
return m_excludeFlags;
}
public void setExcludeFlags(int flags)
public void SetExcludeFlags(int flags)
{
m_excludeFlags = flags;
}

View File

@ -35,9 +35,9 @@ namespace DotRecast.Detour
this.scale = scale;
}
public float getCost(Vector3f neighbourPos, Vector3f endPos)
public float GetCost(Vector3f neighbourPos, Vector3f endPos)
{
return vDist(neighbourPos, endPos) * scale;
return VDist(neighbourPos, endPos) * scale;
}
}
}

View File

@ -22,9 +22,9 @@ namespace DotRecast.Detour
{
public class DetourBuilder
{
public MeshData build(NavMeshDataCreateParams option, int tileX, int tileY)
public MeshData Build(NavMeshDataCreateParams option, int tileX, int tileY)
{
MeshData data = NavMeshBuilder.createNavMeshData(option);
MeshData data = NavMeshBuilder.CreateNavMeshData(option);
if (data != null)
{
data.header.x = tileX;

View File

@ -23,17 +23,17 @@ namespace DotRecast.Detour
nearestPt = center;
}
public void process(MeshTile tile, Poly poly, long refs)
public void Process(MeshTile tile, Poly poly, long refs)
{
// Find nearest polygon amongst the nearby polygons.
Result<ClosestPointOnPolyResult> closest = query.closestPointOnPoly(refs, center);
bool posOverPoly = closest.result.isPosOverPoly();
var closestPtPoly = closest.result.getClosest();
Result<ClosestPointOnPolyResult> closest = query.ClosestPointOnPoly(refs, center);
bool posOverPoly = closest.result.IsPosOverPoly();
var closestPtPoly = closest.result.GetClosest();
// If a point is directly over a polygon and closer than
// climb height, favor that instead of straight line nearest point.
float d = 0;
Vector3f diff = vSub(center, closestPtPoly);
Vector3f diff = VSub(center, closestPtPoly);
if (posOverPoly)
{
d = Math.Abs(diff.y) - tile.data.header.walkableClimb;
@ -41,7 +41,7 @@ namespace DotRecast.Detour
}
else
{
d = vLenSqr(diff);
d = VLenSqr(diff);
}
if (d < nearestDistanceSqr)
@ -53,7 +53,7 @@ namespace DotRecast.Detour
}
}
public FindNearestPolyResult result()
public FindNearestPolyResult Result()
{
return new FindNearestPolyResult(nearestRef, nearestPt, overPoly);
}

View File

@ -24,14 +24,14 @@ namespace DotRecast.Detour.Io
{
public abstract class DetourWriter
{
protected void write(BinaryWriter stream, float value, ByteOrder order)
protected void Write(BinaryWriter stream, float value, ByteOrder order)
{
byte[] bytes = BitConverter.GetBytes(value);
int i = BitConverter.ToInt32(bytes, 0);
write(stream, i, order);
Write(stream, i, order);
}
protected void write(BinaryWriter stream, short value, ByteOrder order)
protected void Write(BinaryWriter stream, short value, ByteOrder order)
{
if (order == ByteOrder.BIG_ENDIAN)
{
@ -45,21 +45,21 @@ namespace DotRecast.Detour.Io
}
}
protected void write(BinaryWriter stream, long value, ByteOrder order)
protected void Write(BinaryWriter stream, long value, ByteOrder order)
{
if (order == ByteOrder.BIG_ENDIAN)
{
write(stream, (int)((ulong)value >> 32), order);
write(stream, (int)(value & 0xFFFFFFFF), order);
Write(stream, (int)((ulong)value >> 32), order);
Write(stream, (int)(value & 0xFFFFFFFF), order);
}
else
{
write(stream, (int)(value & 0xFFFFFFFF), order);
write(stream, (int)((ulong)value >> 32), order);
Write(stream, (int)(value & 0xFFFFFFFF), order);
Write(stream, (int)((ulong)value >> 32), order);
}
}
protected void write(BinaryWriter stream, int value, ByteOrder order)
protected void Write(BinaryWriter stream, int value, ByteOrder order)
{
if (order == ByteOrder.BIG_ENDIAN)
{
@ -77,17 +77,17 @@ namespace DotRecast.Detour.Io
}
}
protected void write(BinaryWriter stream, bool @bool)
protected void Write(BinaryWriter stream, bool @bool)
{
write(stream, (byte)(@bool ? 1 : 0));
Write(stream, (byte)(@bool ? 1 : 0));
}
protected void write(BinaryWriter stream, byte value)
protected void Write(BinaryWriter stream, byte value)
{
stream.Write(value);
}
protected void write(BinaryWriter stream, MemoryStream data)
protected void Write(BinaryWriter stream, MemoryStream data)
{
data.Position = 0;
byte[] buffer = new byte[data.Length];

View File

@ -24,9 +24,9 @@ namespace DotRecast.Detour.Io
{
public static class IOUtils
{
public static ByteBuffer toByteBuffer(BinaryReader @is, bool direct)
public static ByteBuffer ToByteBuffer(BinaryReader @is, bool direct)
{
byte[] data = toByteArray(@is);
byte[] data = ToByteArray(@is);
if (direct)
{
Array.Reverse(data);
@ -35,7 +35,7 @@ namespace DotRecast.Detour.Io
return new ByteBuffer(data);
}
public static byte[] toByteArray(BinaryReader inputStream)
public static byte[] ToByteArray(BinaryReader inputStream)
{
using var baos = new MemoryStream();
byte[] buffer = new byte[4096];
@ -49,13 +49,13 @@ namespace DotRecast.Detour.Io
}
public static ByteBuffer toByteBuffer(BinaryReader inputStream)
public static ByteBuffer ToByteBuffer(BinaryReader inputStream)
{
var bytes = toByteArray(inputStream);
var bytes = ToByteArray(inputStream);
return new ByteBuffer(bytes);
}
public static int swapEndianness(int i)
public static int SwapEndianness(int i)
{
var s = (((uint)i >> 24) & 0xFF) | (((uint)i >> 8) & 0xFF00) | (((uint)i << 8) & 0xFF0000) | ((i << 24) & 0xFF000000);
return (int)s;

View File

@ -25,46 +25,46 @@ namespace DotRecast.Detour.Io
{
public const int DT_POLY_DETAIL_SIZE = 10;
public MeshData read(BinaryReader stream, int maxVertPerPoly)
public MeshData Read(BinaryReader stream, int maxVertPerPoly)
{
ByteBuffer buf = IOUtils.toByteBuffer(stream);
return read(buf, maxVertPerPoly, false);
ByteBuffer buf = IOUtils.ToByteBuffer(stream);
return Read(buf, maxVertPerPoly, false);
}
public MeshData read(ByteBuffer buf, int maxVertPerPoly)
public MeshData Read(ByteBuffer buf, int maxVertPerPoly)
{
return read(buf, maxVertPerPoly, false);
return Read(buf, maxVertPerPoly, false);
}
public MeshData read32Bit(BinaryReader stream, int maxVertPerPoly)
public MeshData Read32Bit(BinaryReader stream, int maxVertPerPoly)
{
ByteBuffer buf = IOUtils.toByteBuffer(stream);
return read(buf, maxVertPerPoly, true);
ByteBuffer buf = IOUtils.ToByteBuffer(stream);
return Read(buf, maxVertPerPoly, true);
}
public MeshData read32Bit(ByteBuffer buf, int maxVertPerPoly)
public MeshData Read32Bit(ByteBuffer buf, int maxVertPerPoly)
{
return read(buf, maxVertPerPoly, true);
return Read(buf, maxVertPerPoly, true);
}
public MeshData read(ByteBuffer buf, int maxVertPerPoly, bool is32Bit)
public MeshData Read(ByteBuffer buf, int maxVertPerPoly, bool is32Bit)
{
MeshData data = new MeshData();
MeshHeader header = new MeshHeader();
data.header = header;
header.magic = buf.getInt();
header.magic = buf.GetInt();
if (header.magic != MeshHeader.DT_NAVMESH_MAGIC)
{
header.magic = IOUtils.swapEndianness(header.magic);
header.magic = IOUtils.SwapEndianness(header.magic);
if (header.magic != MeshHeader.DT_NAVMESH_MAGIC)
{
throw new IOException("Invalid magic");
}
buf.order(buf.order() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
buf.Order(buf.Order() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
}
header.version = buf.getInt();
header.version = buf.GetInt();
if (header.version != MeshHeader.DT_NAVMESH_VERSION)
{
if (header.version < MeshHeader.DT_NAVMESH_VERSION_RECAST4J_FIRST
@ -75,67 +75,67 @@ namespace DotRecast.Detour.Io
}
bool cCompatibility = header.version == MeshHeader.DT_NAVMESH_VERSION;
header.x = buf.getInt();
header.y = buf.getInt();
header.layer = buf.getInt();
header.userId = buf.getInt();
header.polyCount = buf.getInt();
header.vertCount = buf.getInt();
header.maxLinkCount = buf.getInt();
header.detailMeshCount = buf.getInt();
header.detailVertCount = buf.getInt();
header.detailTriCount = buf.getInt();
header.bvNodeCount = buf.getInt();
header.offMeshConCount = buf.getInt();
header.offMeshBase = buf.getInt();
header.walkableHeight = buf.getFloat();
header.walkableRadius = buf.getFloat();
header.walkableClimb = buf.getFloat();
header.x = buf.GetInt();
header.y = buf.GetInt();
header.layer = buf.GetInt();
header.userId = buf.GetInt();
header.polyCount = buf.GetInt();
header.vertCount = buf.GetInt();
header.maxLinkCount = buf.GetInt();
header.detailMeshCount = buf.GetInt();
header.detailVertCount = buf.GetInt();
header.detailTriCount = buf.GetInt();
header.bvNodeCount = buf.GetInt();
header.offMeshConCount = buf.GetInt();
header.offMeshBase = buf.GetInt();
header.walkableHeight = buf.GetFloat();
header.walkableRadius = buf.GetFloat();
header.walkableClimb = buf.GetFloat();
header.bmin.x = buf.getFloat();
header.bmin.y = buf.getFloat();
header.bmin.z = buf.getFloat();
header.bmin.x = buf.GetFloat();
header.bmin.y = buf.GetFloat();
header.bmin.z = buf.GetFloat();
header.bmax.x = buf.getFloat();
header.bmax.y = buf.getFloat();
header.bmax.z = buf.getFloat();
header.bmax.x = buf.GetFloat();
header.bmax.y = buf.GetFloat();
header.bmax.z = buf.GetFloat();
header.bvQuantFactor = buf.getFloat();
data.verts = readVerts(buf, header.vertCount);
data.polys = readPolys(buf, header, maxVertPerPoly);
header.bvQuantFactor = buf.GetFloat();
data.verts = ReadVerts(buf, header.vertCount);
data.polys = ReadPolys(buf, header, maxVertPerPoly);
if (cCompatibility)
{
buf.position(buf.position() + header.maxLinkCount * getSizeofLink(is32Bit));
buf.Position(buf.Position() + header.maxLinkCount * GetSizeofLink(is32Bit));
}
data.detailMeshes = readPolyDetails(buf, header, cCompatibility);
data.detailVerts = readVerts(buf, header.detailVertCount);
data.detailTris = readDTris(buf, header);
data.bvTree = readBVTree(buf, header);
data.offMeshCons = readOffMeshCons(buf, header);
data.detailMeshes = ReadPolyDetails(buf, header, cCompatibility);
data.detailVerts = ReadVerts(buf, header.detailVertCount);
data.detailTris = ReadDTris(buf, header);
data.bvTree = ReadBVTree(buf, header);
data.offMeshCons = ReadOffMeshCons(buf, header);
return data;
}
public const int LINK_SIZEOF = 16;
public const int LINK_SIZEOF32BIT = 12;
public static int getSizeofLink(bool is32Bit)
public static int GetSizeofLink(bool is32Bit)
{
return is32Bit ? LINK_SIZEOF32BIT : LINK_SIZEOF;
}
private float[] readVerts(ByteBuffer buf, int count)
private float[] ReadVerts(ByteBuffer buf, int count)
{
float[] verts = new float[count * 3];
for (int i = 0; i < verts.Length; i++)
{
verts[i] = buf.getFloat();
verts[i] = buf.GetFloat();
}
return verts;
}
private Poly[] readPolys(ByteBuffer buf, MeshHeader header, int maxVertPerPoly)
private Poly[] ReadPolys(ByteBuffer buf, MeshHeader header, int maxVertPerPoly)
{
Poly[] polys = new Poly[header.polyCount];
for (int i = 0; i < polys.Length; i++)
@ -143,58 +143,58 @@ namespace DotRecast.Detour.Io
polys[i] = new Poly(i, maxVertPerPoly);
if (header.version < MeshHeader.DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK)
{
buf.getInt(); // polys[i].firstLink
buf.GetInt(); // polys[i].firstLink
}
for (int j = 0; j < polys[i].verts.Length; j++)
{
polys[i].verts[j] = buf.getShort() & 0xFFFF;
polys[i].verts[j] = buf.GetShort() & 0xFFFF;
}
for (int j = 0; j < polys[i].neis.Length; j++)
{
polys[i].neis[j] = buf.getShort() & 0xFFFF;
polys[i].neis[j] = buf.GetShort() & 0xFFFF;
}
polys[i].flags = buf.getShort() & 0xFFFF;
polys[i].vertCount = buf.get() & 0xFF;
polys[i].areaAndtype = buf.get() & 0xFF;
polys[i].flags = buf.GetShort() & 0xFFFF;
polys[i].vertCount = buf.Get() & 0xFF;
polys[i].areaAndtype = buf.Get() & 0xFF;
}
return polys;
}
private PolyDetail[] readPolyDetails(ByteBuffer buf, MeshHeader header, bool cCompatibility)
private PolyDetail[] ReadPolyDetails(ByteBuffer buf, MeshHeader header, bool cCompatibility)
{
PolyDetail[] polys = new PolyDetail[header.detailMeshCount];
for (int i = 0; i < polys.Length; i++)
{
polys[i] = new PolyDetail();
polys[i].vertBase = buf.getInt();
polys[i].triBase = buf.getInt();
polys[i].vertCount = buf.get() & 0xFF;
polys[i].triCount = buf.get() & 0xFF;
polys[i].vertBase = buf.GetInt();
polys[i].triBase = buf.GetInt();
polys[i].vertCount = buf.Get() & 0xFF;
polys[i].triCount = buf.Get() & 0xFF;
if (cCompatibility)
{
buf.getShort(); // C struct padding
buf.GetShort(); // C struct padding
}
}
return polys;
}
private int[] readDTris(ByteBuffer buf, MeshHeader header)
private int[] ReadDTris(ByteBuffer buf, MeshHeader header)
{
int[] tris = new int[4 * header.detailTriCount];
for (int i = 0; i < tris.Length; i++)
{
tris[i] = buf.get() & 0xFF;
tris[i] = buf.Get() & 0xFF;
}
return tris;
}
private BVNode[] readBVTree(ByteBuffer buf, MeshHeader header)
private BVNode[] ReadBVTree(ByteBuffer buf, MeshHeader header)
{
BVNode[] nodes = new BVNode[header.bvNodeCount];
for (int i = 0; i < nodes.Length; i++)
@ -204,34 +204,34 @@ namespace DotRecast.Detour.Io
{
for (int j = 0; j < 3; j++)
{
nodes[i].bmin[j] = buf.getShort() & 0xFFFF;
nodes[i].bmin[j] = buf.GetShort() & 0xFFFF;
}
for (int j = 0; j < 3; j++)
{
nodes[i].bmax[j] = buf.getShort() & 0xFFFF;
nodes[i].bmax[j] = buf.GetShort() & 0xFFFF;
}
}
else
{
for (int j = 0; j < 3; j++)
{
nodes[i].bmin[j] = buf.getInt();
nodes[i].bmin[j] = buf.GetInt();
}
for (int j = 0; j < 3; j++)
{
nodes[i].bmax[j] = buf.getInt();
nodes[i].bmax[j] = buf.GetInt();
}
}
nodes[i].i = buf.getInt();
nodes[i].i = buf.GetInt();
}
return nodes;
}
private OffMeshConnection[] readOffMeshCons(ByteBuffer buf, MeshHeader header)
private OffMeshConnection[] ReadOffMeshCons(ByteBuffer buf, MeshHeader header)
{
OffMeshConnection[] cons = new OffMeshConnection[header.offMeshConCount];
for (int i = 0; i < cons.Length; i++)
@ -239,14 +239,14 @@ namespace DotRecast.Detour.Io
cons[i] = new OffMeshConnection();
for (int j = 0; j < 6; j++)
{
cons[i].pos[j] = buf.getFloat();
cons[i].pos[j] = buf.GetFloat();
}
cons[i].rad = buf.getFloat();
cons[i].poly = buf.getShort() & 0xFFFF;
cons[i].flags = buf.get() & 0xFF;
cons[i].side = buf.get() & 0xFF;
cons[i].userId = buf.getInt();
cons[i].rad = buf.GetFloat();
cons[i].poly = buf.GetShort() & 0xFFFF;
cons[i].flags = buf.Get() & 0xFF;
cons[i].side = buf.Get() & 0xFF;
cons[i].userId = buf.GetInt();
}
return cons;

View File

@ -23,106 +23,106 @@ namespace DotRecast.Detour.Io
{
public class MeshDataWriter : DetourWriter
{
public void write(BinaryWriter stream, MeshData data, ByteOrder order, bool cCompatibility)
public void Write(BinaryWriter stream, MeshData data, ByteOrder order, bool cCompatibility)
{
MeshHeader header = data.header;
write(stream, header.magic, order);
write(stream, cCompatibility ? MeshHeader.DT_NAVMESH_VERSION : MeshHeader.DT_NAVMESH_VERSION_RECAST4J_LAST, order);
write(stream, header.x, order);
write(stream, header.y, order);
write(stream, header.layer, order);
write(stream, header.userId, order);
write(stream, header.polyCount, order);
write(stream, header.vertCount, order);
write(stream, header.maxLinkCount, order);
write(stream, header.detailMeshCount, order);
write(stream, header.detailVertCount, order);
write(stream, header.detailTriCount, order);
write(stream, header.bvNodeCount, order);
write(stream, header.offMeshConCount, order);
write(stream, header.offMeshBase, order);
write(stream, header.walkableHeight, order);
write(stream, header.walkableRadius, order);
write(stream, header.walkableClimb, order);
write(stream, header.bmin.x, order);
write(stream, header.bmin.y, order);
write(stream, header.bmin.z, order);
write(stream, header.bmax.x, order);
write(stream, header.bmax.y, order);
write(stream, header.bmax.z, order);
write(stream, header.bvQuantFactor, order);
writeVerts(stream, data.verts, header.vertCount, order);
writePolys(stream, data, order, cCompatibility);
Write(stream, header.magic, order);
Write(stream, cCompatibility ? MeshHeader.DT_NAVMESH_VERSION : MeshHeader.DT_NAVMESH_VERSION_RECAST4J_LAST, order);
Write(stream, header.x, order);
Write(stream, header.y, order);
Write(stream, header.layer, order);
Write(stream, header.userId, order);
Write(stream, header.polyCount, order);
Write(stream, header.vertCount, order);
Write(stream, header.maxLinkCount, order);
Write(stream, header.detailMeshCount, order);
Write(stream, header.detailVertCount, order);
Write(stream, header.detailTriCount, order);
Write(stream, header.bvNodeCount, order);
Write(stream, header.offMeshConCount, order);
Write(stream, header.offMeshBase, order);
Write(stream, header.walkableHeight, order);
Write(stream, header.walkableRadius, order);
Write(stream, header.walkableClimb, order);
Write(stream, header.bmin.x, order);
Write(stream, header.bmin.y, order);
Write(stream, header.bmin.z, order);
Write(stream, header.bmax.x, order);
Write(stream, header.bmax.y, order);
Write(stream, header.bmax.z, order);
Write(stream, header.bvQuantFactor, order);
WriteVerts(stream, data.verts, header.vertCount, order);
WritePolys(stream, data, order, cCompatibility);
if (cCompatibility)
{
byte[] linkPlaceholder = new byte[header.maxLinkCount * MeshDataReader.getSizeofLink(false)];
byte[] linkPlaceholder = new byte[header.maxLinkCount * MeshDataReader.GetSizeofLink(false)];
stream.Write(linkPlaceholder);
}
writePolyDetails(stream, data, order, cCompatibility);
writeVerts(stream, data.detailVerts, header.detailVertCount, order);
writeDTris(stream, data);
writeBVTree(stream, data, order, cCompatibility);
writeOffMeshCons(stream, data, order);
WritePolyDetails(stream, data, order, cCompatibility);
WriteVerts(stream, data.detailVerts, header.detailVertCount, order);
WriteDTris(stream, data);
WriteBVTree(stream, data, order, cCompatibility);
WriteOffMeshCons(stream, data, order);
}
private void writeVerts(BinaryWriter stream, float[] verts, int count, ByteOrder order)
private void WriteVerts(BinaryWriter stream, float[] verts, int count, ByteOrder order)
{
for (int i = 0; i < count * 3; i++)
{
write(stream, verts[i], order);
Write(stream, verts[i], order);
}
}
private void writePolys(BinaryWriter stream, MeshData data, ByteOrder order, bool cCompatibility)
private void WritePolys(BinaryWriter stream, MeshData data, ByteOrder order, bool cCompatibility)
{
for (int i = 0; i < data.header.polyCount; i++)
{
if (cCompatibility)
{
write(stream, 0xFFFF, order);
Write(stream, 0xFFFF, order);
}
for (int j = 0; j < data.polys[i].verts.Length; j++)
{
write(stream, (short)data.polys[i].verts[j], order);
Write(stream, (short)data.polys[i].verts[j], order);
}
for (int j = 0; j < data.polys[i].neis.Length; j++)
{
write(stream, (short)data.polys[i].neis[j], order);
Write(stream, (short)data.polys[i].neis[j], order);
}
write(stream, (short)data.polys[i].flags, order);
write(stream, (byte)data.polys[i].vertCount);
write(stream, (byte)data.polys[i].areaAndtype);
Write(stream, (short)data.polys[i].flags, order);
Write(stream, (byte)data.polys[i].vertCount);
Write(stream, (byte)data.polys[i].areaAndtype);
}
}
private void writePolyDetails(BinaryWriter stream, MeshData data, ByteOrder order, bool cCompatibility)
private void WritePolyDetails(BinaryWriter stream, MeshData data, ByteOrder order, bool cCompatibility)
{
for (int i = 0; i < data.header.detailMeshCount; i++)
{
write(stream, data.detailMeshes[i].vertBase, order);
write(stream, data.detailMeshes[i].triBase, order);
write(stream, (byte)data.detailMeshes[i].vertCount);
write(stream, (byte)data.detailMeshes[i].triCount);
Write(stream, data.detailMeshes[i].vertBase, order);
Write(stream, data.detailMeshes[i].triBase, order);
Write(stream, (byte)data.detailMeshes[i].vertCount);
Write(stream, (byte)data.detailMeshes[i].triCount);
if (cCompatibility)
{
write(stream, (short)0, order);
Write(stream, (short)0, order);
}
}
}
private void writeDTris(BinaryWriter stream, MeshData data)
private void WriteDTris(BinaryWriter stream, MeshData data)
{
for (int i = 0; i < data.header.detailTriCount * 4; i++)
{
write(stream, (byte)data.detailTris[i]);
Write(stream, (byte)data.detailTris[i]);
}
}
private void writeBVTree(BinaryWriter stream, MeshData data, ByteOrder order, bool cCompatibility)
private void WriteBVTree(BinaryWriter stream, MeshData data, ByteOrder order, bool cCompatibility)
{
for (int i = 0; i < data.header.bvNodeCount; i++)
{
@ -130,45 +130,45 @@ namespace DotRecast.Detour.Io
{
for (int j = 0; j < 3; j++)
{
write(stream, (short)data.bvTree[i].bmin[j], order);
Write(stream, (short)data.bvTree[i].bmin[j], order);
}
for (int j = 0; j < 3; j++)
{
write(stream, (short)data.bvTree[i].bmax[j], order);
Write(stream, (short)data.bvTree[i].bmax[j], order);
}
}
else
{
for (int j = 0; j < 3; j++)
{
write(stream, data.bvTree[i].bmin[j], order);
Write(stream, data.bvTree[i].bmin[j], order);
}
for (int j = 0; j < 3; j++)
{
write(stream, data.bvTree[i].bmax[j], order);
Write(stream, data.bvTree[i].bmax[j], order);
}
}
write(stream, data.bvTree[i].i, order);
Write(stream, data.bvTree[i].i, order);
}
}
private void writeOffMeshCons(BinaryWriter stream, MeshData data, ByteOrder order)
private void WriteOffMeshCons(BinaryWriter stream, MeshData data, ByteOrder order)
{
for (int i = 0; i < data.header.offMeshConCount; i++)
{
for (int j = 0; j < 6; j++)
{
write(stream, data.offMeshCons[i].pos[j], order);
Write(stream, data.offMeshCons[i].pos[j], order);
}
write(stream, data.offMeshCons[i].rad, order);
write(stream, (short)data.offMeshCons[i].poly, order);
write(stream, (byte)data.offMeshCons[i].flags);
write(stream, (byte)data.offMeshCons[i].side);
write(stream, data.offMeshCons[i].userId, order);
Write(stream, data.offMeshCons[i].rad, order);
Write(stream, (short)data.offMeshCons[i].poly, order);
Write(stream, (byte)data.offMeshCons[i].flags);
Write(stream, (byte)data.offMeshCons[i].side);
Write(stream, data.offMeshCons[i].userId, order);
}
}
}

View File

@ -30,39 +30,39 @@ namespace DotRecast.Detour.Io
private readonly MeshDataReader meshReader = new MeshDataReader();
private readonly NavMeshParamReader paramReader = new NavMeshParamReader();
public NavMesh read(BinaryReader @is, int maxVertPerPoly)
public NavMesh Read(BinaryReader @is, int maxVertPerPoly)
{
return read(IOUtils.toByteBuffer(@is), maxVertPerPoly, false);
return Read(IOUtils.ToByteBuffer(@is), maxVertPerPoly, false);
}
public NavMesh read(ByteBuffer bb, int maxVertPerPoly)
public NavMesh Read(ByteBuffer bb, int maxVertPerPoly)
{
return read(bb, maxVertPerPoly, false);
return Read(bb, maxVertPerPoly, false);
}
public NavMesh read32Bit(BinaryReader @is, int maxVertPerPoly)
public NavMesh Read32Bit(BinaryReader @is, int maxVertPerPoly)
{
return read(IOUtils.toByteBuffer(@is), maxVertPerPoly, true);
return Read(IOUtils.ToByteBuffer(@is), maxVertPerPoly, true);
}
public NavMesh read32Bit(ByteBuffer bb, int maxVertPerPoly)
public NavMesh Read32Bit(ByteBuffer bb, int maxVertPerPoly)
{
return read(bb, maxVertPerPoly, true);
return Read(bb, maxVertPerPoly, true);
}
public NavMesh read(BinaryReader @is)
public NavMesh Read(BinaryReader @is)
{
return read(IOUtils.toByteBuffer(@is));
return Read(IOUtils.ToByteBuffer(@is));
}
public NavMesh read(ByteBuffer bb)
public NavMesh Read(ByteBuffer bb)
{
return read(bb, -1, false);
return Read(bb, -1, false);
}
NavMesh read(ByteBuffer bb, int maxVertPerPoly, bool is32Bit)
NavMesh Read(ByteBuffer bb, int maxVertPerPoly, bool is32Bit)
{
NavMeshSetHeader header = readHeader(bb, maxVertPerPoly);
NavMeshSetHeader header = ReadHeader(bb, maxVertPerPoly);
if (header.maxVertsPerPoly <= 0)
{
throw new IOException("Invalid number of verts per poly " + header.maxVertsPerPoly);
@ -70,44 +70,44 @@ namespace DotRecast.Detour.Io
bool cCompatibility = header.version == NavMeshSetHeader.NAVMESHSET_VERSION;
NavMesh mesh = new NavMesh(header.option, header.maxVertsPerPoly);
readTiles(bb, is32Bit, header, cCompatibility, mesh);
ReadTiles(bb, is32Bit, header, cCompatibility, mesh);
return mesh;
}
private NavMeshSetHeader readHeader(ByteBuffer bb, int maxVertsPerPoly)
private NavMeshSetHeader ReadHeader(ByteBuffer bb, int maxVertsPerPoly)
{
NavMeshSetHeader header = new NavMeshSetHeader();
header.magic = bb.getInt();
header.magic = bb.GetInt();
if (header.magic != NavMeshSetHeader.NAVMESHSET_MAGIC)
{
header.magic = IOUtils.swapEndianness(header.magic);
header.magic = IOUtils.SwapEndianness(header.magic);
if (header.magic != NavMeshSetHeader.NAVMESHSET_MAGIC)
{
throw new IOException("Invalid magic " + header.magic);
}
bb.order(bb.order() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
bb.Order(bb.Order() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
}
header.version = bb.getInt();
header.version = bb.GetInt();
if (header.version != NavMeshSetHeader.NAVMESHSET_VERSION && header.version != NavMeshSetHeader.NAVMESHSET_VERSION_RECAST4J_1
&& header.version != NavMeshSetHeader.NAVMESHSET_VERSION_RECAST4J)
{
throw new IOException("Invalid version " + header.version);
}
header.numTiles = bb.getInt();
header.option = paramReader.read(bb);
header.numTiles = bb.GetInt();
header.option = paramReader.Read(bb);
header.maxVertsPerPoly = maxVertsPerPoly;
if (header.version == NavMeshSetHeader.NAVMESHSET_VERSION_RECAST4J)
{
header.maxVertsPerPoly = bb.getInt();
header.maxVertsPerPoly = bb.GetInt();
}
return header;
}
private void readTiles(ByteBuffer bb, bool is32Bit, NavMeshSetHeader header, bool cCompatibility, NavMesh mesh)
private void ReadTiles(ByteBuffer bb, bool is32Bit, NavMeshSetHeader header, bool cCompatibility, NavMesh mesh)
{
// Read tiles.
for (int i = 0; i < header.numTiles; ++i)
@ -115,14 +115,14 @@ namespace DotRecast.Detour.Io
NavMeshTileHeader tileHeader = new NavMeshTileHeader();
if (is32Bit)
{
tileHeader.tileRef = convert32BitRef(bb.getInt(), header.option);
tileHeader.tileRef = Convert32BitRef(bb.GetInt(), header.option);
}
else
{
tileHeader.tileRef = bb.getLong();
tileHeader.tileRef = bb.GetLong();
}
tileHeader.dataSize = bb.getInt();
tileHeader.dataSize = bb.GetInt();
if (tileHeader.tileRef == 0 || tileHeader.dataSize == 0)
{
break;
@ -130,18 +130,18 @@ namespace DotRecast.Detour.Io
if (cCompatibility && !is32Bit)
{
bb.getInt(); // C struct padding
bb.GetInt(); // C struct padding
}
MeshData data = meshReader.read(bb, mesh.getMaxVertsPerPoly(), is32Bit);
mesh.addTile(data, i, tileHeader.tileRef);
MeshData data = meshReader.Read(bb, mesh.GetMaxVertsPerPoly(), is32Bit);
mesh.AddTile(data, i, tileHeader.tileRef);
}
}
private long convert32BitRef(int refs, NavMeshParams option)
private long Convert32BitRef(int refs, NavMeshParams option)
{
int m_tileBits = ilog2(nextPow2(option.maxTiles));
int m_polyBits = ilog2(nextPow2(option.maxPolys));
int m_tileBits = Ilog2(NextPow2(option.maxTiles));
int m_polyBits = Ilog2(NextPow2(option.maxPolys));
// 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 saltMask = (1 << m_saltBits) - 1;
@ -150,7 +150,7 @@ namespace DotRecast.Detour.Io
int salt = ((refs >> (m_polyBits + m_tileBits)) & saltMask);
int it = ((refs >> m_polyBits) & tileMask);
int ip = refs & polyMask;
return NavMesh.encodePolyId(salt, it, ip);
return NavMesh.EncodePolyId(salt, it, ip);
}
}
}

View File

@ -26,20 +26,20 @@ namespace DotRecast.Detour.Io
private readonly MeshDataWriter writer = new MeshDataWriter();
private readonly NavMeshParamWriter paramWriter = new NavMeshParamWriter();
public void write(BinaryWriter stream, NavMesh mesh, ByteOrder order, bool cCompatibility)
public void Write(BinaryWriter stream, NavMesh mesh, ByteOrder order, bool cCompatibility)
{
writeHeader(stream, mesh, order, cCompatibility);
writeTiles(stream, mesh, order, cCompatibility);
WriteHeader(stream, mesh, order, cCompatibility);
WriteTiles(stream, mesh, order, cCompatibility);
}
private void writeHeader(BinaryWriter stream, NavMesh mesh, ByteOrder order, bool cCompatibility)
private void WriteHeader(BinaryWriter stream, NavMesh mesh, ByteOrder order, bool cCompatibility)
{
write(stream, NavMeshSetHeader.NAVMESHSET_MAGIC, order);
write(stream, cCompatibility ? NavMeshSetHeader.NAVMESHSET_VERSION : NavMeshSetHeader.NAVMESHSET_VERSION_RECAST4J, order);
Write(stream, NavMeshSetHeader.NAVMESHSET_MAGIC, order);
Write(stream, cCompatibility ? NavMeshSetHeader.NAVMESHSET_VERSION : NavMeshSetHeader.NAVMESHSET_VERSION_RECAST4J, order);
int numTiles = 0;
for (int i = 0; i < mesh.getMaxTiles(); ++i)
for (int i = 0; i < mesh.GetMaxTiles(); ++i)
{
MeshTile tile = mesh.getTile(i);
MeshTile tile = mesh.GetTile(i);
if (tile == null || tile.data == null || tile.data.header == null)
{
continue;
@ -48,39 +48,39 @@ namespace DotRecast.Detour.Io
numTiles++;
}
write(stream, numTiles, order);
paramWriter.write(stream, mesh.getParams(), order);
Write(stream, numTiles, order);
paramWriter.Write(stream, mesh.GetParams(), order);
if (!cCompatibility)
{
write(stream, mesh.getMaxVertsPerPoly(), order);
Write(stream, mesh.GetMaxVertsPerPoly(), order);
}
}
private void writeTiles(BinaryWriter stream, NavMesh mesh, ByteOrder order, bool cCompatibility)
private void WriteTiles(BinaryWriter stream, NavMesh mesh, ByteOrder order, bool cCompatibility)
{
for (int i = 0; i < mesh.getMaxTiles(); ++i)
for (int i = 0; i < mesh.GetMaxTiles(); ++i)
{
MeshTile tile = mesh.getTile(i);
MeshTile tile = mesh.GetTile(i);
if (tile == null || tile.data == null || tile.data.header == null)
{
continue;
}
NavMeshTileHeader tileHeader = new NavMeshTileHeader();
tileHeader.tileRef = mesh.getTileRef(tile);
tileHeader.tileRef = mesh.GetTileRef(tile);
using MemoryStream bb = new MemoryStream();
using BinaryWriter baos = new BinaryWriter(bb);
writer.write(baos, tile.data, order, cCompatibility);
writer.Write(baos, tile.data, order, cCompatibility);
baos.Flush();
baos.Close();
byte[] ba = bb.ToArray();
tileHeader.dataSize = ba.Length;
write(stream, tileHeader.tileRef, order);
write(stream, tileHeader.dataSize, order);
Write(stream, tileHeader.tileRef, order);
Write(stream, tileHeader.dataSize, order);
if (cCompatibility)
{
write(stream, 0, order); // C struct padding
Write(stream, 0, order); // C struct padding
}
stream.Write(ba);

View File

@ -4,16 +4,16 @@ namespace DotRecast.Detour.Io
{
public class NavMeshParamReader
{
public NavMeshParams read(ByteBuffer bb)
public NavMeshParams Read(ByteBuffer bb)
{
NavMeshParams option = new NavMeshParams();
option.orig.x = bb.getFloat();
option.orig.y = bb.getFloat();
option.orig.z = bb.getFloat();
option.tileWidth = bb.getFloat();
option.tileHeight = bb.getFloat();
option.maxTiles = bb.getInt();
option.maxPolys = bb.getInt();
option.orig.x = bb.GetFloat();
option.orig.y = bb.GetFloat();
option.orig.z = bb.GetFloat();
option.tileWidth = bb.GetFloat();
option.tileHeight = bb.GetFloat();
option.maxTiles = bb.GetInt();
option.maxPolys = bb.GetInt();
return option;
}
}

View File

@ -5,15 +5,15 @@ namespace DotRecast.Detour.Io
{
public class NavMeshParamWriter : DetourWriter
{
public void write(BinaryWriter stream, NavMeshParams option, ByteOrder order)
public void Write(BinaryWriter stream, NavMeshParams option, ByteOrder order)
{
write(stream, option.orig.x, order);
write(stream, option.orig.y, order);
write(stream, option.orig.z, order);
write(stream, option.tileWidth, order);
write(stream, option.tileHeight, order);
write(stream, option.maxTiles, order);
write(stream, option.maxPolys, order);
Write(stream, option.orig.x, order);
Write(stream, option.orig.y, order);
Write(stream, option.orig.z, order);
Write(stream, option.tileWidth, order);
Write(stream, option.tileHeight, order);
Write(stream, option.maxTiles, order);
Write(stream, option.maxPolys, order);
}
}
}

View File

@ -34,16 +34,16 @@ namespace DotRecast.Detour
{
}
public override Result<List<long>> findPath(long startRef, long endRef, Vector3f startPos, Vector3f endPos, QueryFilter filter,
public override Result<List<long>> FindPath(long startRef, long endRef, Vector3f startPos, Vector3f endPos, QueryFilter filter,
int options, float raycastLimit)
{
return findPath(startRef, endRef, startPos, endPos, filter);
return FindPath(startRef, endRef, startPos, endPos, filter);
}
public override Result<List<long>> findPath(long startRef, long endRef, Vector3f startPos, Vector3f endPos, QueryFilter filter)
public override Result<List<long>> FindPath(long startRef, long endRef, Vector3f startPos, Vector3f endPos, QueryFilter filter)
{
// Validate input
if (!m_nav.isValidPolyRef(startRef) || !m_nav.isValidPolyRef(endRef) || !vIsFinite(startPos) || !vIsFinite(endPos) || null == filter)
if (!m_nav.IsValidPolyRef(startRef) || !m_nav.IsValidPolyRef(endRef) || !VIsFinite(startPos) || !VIsFinite(endPos) || null == filter)
{
return Results.InvalidParam<List<long>>();
}
@ -55,27 +55,27 @@ namespace DotRecast.Detour
return Results.Success(singlePath);
}
m_nodePool.clear();
m_openList.clear();
m_nodePool.Clear();
m_openList.Clear();
Node startNode = m_nodePool.getNode(startRef);
Node startNode = m_nodePool.GetNode(startRef);
startNode.pos = startPos;
startNode.pidx = 0;
startNode.cost = 0;
startNode.total = vDist(startPos, endPos) * H_SCALE;
startNode.total = VDist(startPos, endPos) * H_SCALE;
startNode.id = startRef;
startNode.flags = Node.DT_NODE_OPEN;
m_openList.push(startNode);
m_openList.Push(startNode);
Node lastBestNode = startNode;
float lastBestNodeCost = startNode.total;
Status status = Status.SUCCSESS;
while (!m_openList.isEmpty())
while (!m_openList.IsEmpty())
{
// Remove node from open list and put it in closed list.
Node bestNode = m_openList.pop();
Node bestNode = m_openList.Pop();
bestNode.flags &= ~Node.DT_NODE_OPEN;
bestNode.flags |= Node.DT_NODE_CLOSED;
@ -89,7 +89,7 @@ namespace DotRecast.Detour
// Get current poly and tile.
// The API input has been cheked already, skip checking internal data.
long bestRef = bestNode.id;
Tuple<MeshTile, Poly> tileAndPoly = m_nav.getTileAndPolyByRefUnsafe(bestRef);
Tuple<MeshTile, Poly> tileAndPoly = m_nav.GetTileAndPolyByRefUnsafe(bestRef);
MeshTile bestTile = tileAndPoly.Item1;
Poly bestPoly = tileAndPoly.Item2;
@ -99,12 +99,12 @@ namespace DotRecast.Detour
Poly parentPoly = null;
if (bestNode.pidx != 0)
{
parentRef = m_nodePool.getNodeAtIdx(bestNode.pidx).id;
parentRef = m_nodePool.GetNodeAtIdx(bestNode.pidx).id;
}
if (parentRef != 0)
{
tileAndPoly = m_nav.getTileAndPolyByRefUnsafe(parentRef);
tileAndPoly = m_nav.GetTileAndPolyByRefUnsafe(parentRef);
parentTile = tileAndPoly.Item1;
parentPoly = tileAndPoly.Item2;
}
@ -121,11 +121,11 @@ namespace DotRecast.Detour
// Get neighbour poly and tile.
// The API input has been cheked already, skip checking internal data.
tileAndPoly = m_nav.getTileAndPolyByRefUnsafe(neighbourRef);
tileAndPoly = m_nav.GetTileAndPolyByRefUnsafe(neighbourRef);
MeshTile neighbourTile = tileAndPoly.Item1;
Poly neighbourPoly = tileAndPoly.Item2;
if (!filter.passFilter(neighbourRef, neighbourTile, neighbourPoly))
if (!filter.PassFilter(neighbourRef, neighbourTile, neighbourPoly))
{
continue;
}
@ -138,12 +138,12 @@ namespace DotRecast.Detour
}
// get the node
Node neighbourNode = m_nodePool.getNode(neighbourRef, crossSide);
Node neighbourNode = m_nodePool.GetNode(neighbourRef, crossSide);
// If the node is visited the first time, calculate node position.
if (neighbourNode.flags == 0)
{
var midpod = getEdgeMidPoint(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly,
var midpod = GetEdgeMidPoint(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly,
neighbourTile);
if (!midpod.Failed())
{
@ -159,9 +159,9 @@ namespace DotRecast.Detour
if (neighbourRef == endRef)
{
// Cost
float curCost = filter.getCost(bestNode.pos, neighbourNode.pos, parentRef, parentTile, parentPoly,
float curCost = filter.GetCost(bestNode.pos, neighbourNode.pos, parentRef, parentTile, parentPoly,
bestRef, bestTile, bestPoly, neighbourRef, neighbourTile, neighbourPoly);
float endCost = filter.getCost(neighbourNode.pos, endPos, bestRef, bestTile, bestPoly, neighbourRef,
float endCost = filter.GetCost(neighbourNode.pos, endPos, bestRef, bestTile, bestPoly, neighbourRef,
neighbourTile, neighbourPoly, 0L, null, null);
cost = bestNode.cost + curCost + endCost;
@ -170,10 +170,10 @@ namespace DotRecast.Detour
else
{
// Cost
float curCost = filter.getCost(bestNode.pos, neighbourNode.pos, parentRef, parentTile, parentPoly,
float curCost = filter.GetCost(bestNode.pos, neighbourNode.pos, parentRef, parentTile, parentPoly,
bestRef, bestTile, bestPoly, neighbourRef, neighbourTile, neighbourPoly);
cost = bestNode.cost + curCost;
heuristic = vDist(neighbourNode.pos, endPos) * H_SCALE;
heuristic = VDist(neighbourNode.pos, endPos) * H_SCALE;
}
float total = cost + heuristic;
@ -191,7 +191,7 @@ namespace DotRecast.Detour
}
// Add or update the node.
neighbourNode.pidx = m_nodePool.getNodeIdx(bestNode);
neighbourNode.pidx = m_nodePool.GetNodeIdx(bestNode);
neighbourNode.id = neighbourRef;
neighbourNode.flags = (neighbourNode.flags & ~Node.DT_NODE_CLOSED);
neighbourNode.cost = cost;
@ -200,13 +200,13 @@ namespace DotRecast.Detour
if ((neighbourNode.flags & Node.DT_NODE_OPEN) != 0)
{
// Already in open, update node location.
m_openList.modify(neighbourNode);
m_openList.Modify(neighbourNode);
}
else
{
// Put the node in open list.
neighbourNode.flags |= Node.DT_NODE_OPEN;
m_openList.push(neighbourNode);
m_openList.Push(neighbourNode);
}
// Update nearest node to target so far.
@ -218,7 +218,7 @@ namespace DotRecast.Detour
}
}
List<long> path = getPathToNode(lastBestNode);
List<long> path = GetPathToNode(lastBestNode);
if (lastBestNode.id != endRef)
{
@ -235,27 +235,27 @@ namespace DotRecast.Detour
* The maximum number of iterations to perform.
* @return The status flags for the query.
*/
public override Result<int> updateSlicedFindPath(int maxIter)
public override Result<int> UpdateSlicedFindPath(int maxIter)
{
if (!m_query.status.isInProgress())
if (!m_query.status.IsInProgress())
{
return Results.Of(m_query.status, 0);
}
// Make sure the request is still valid.
if (!m_nav.isValidPolyRef(m_query.startRef) || !m_nav.isValidPolyRef(m_query.endRef))
if (!m_nav.IsValidPolyRef(m_query.startRef) || !m_nav.IsValidPolyRef(m_query.endRef))
{
m_query.status = Status.FAILURE;
return Results.Of(m_query.status, 0);
}
int iter = 0;
while (iter < maxIter && !m_openList.isEmpty())
while (iter < maxIter && !m_openList.IsEmpty())
{
iter++;
// Remove node from open list and put it in closed list.
Node bestNode = m_openList.pop();
Node bestNode = m_openList.Pop();
bestNode.flags &= ~Node.DT_NODE_OPEN;
bestNode.flags |= Node.DT_NODE_CLOSED;
@ -271,7 +271,7 @@ namespace DotRecast.Detour
// The API input has been cheked already, skip checking internal
// data.
long bestRef = bestNode.id;
Result<Tuple<MeshTile, Poly>> tileAndPoly = m_nav.getTileAndPolyByRef(bestRef);
Result<Tuple<MeshTile, Poly>> tileAndPoly = m_nav.GetTileAndPolyByRef(bestRef);
if (tileAndPoly.Failed())
{
m_query.status = Status.FAILURE;
@ -288,20 +288,20 @@ namespace DotRecast.Detour
Node parentNode = null;
if (bestNode.pidx != 0)
{
parentNode = m_nodePool.getNodeAtIdx(bestNode.pidx);
parentNode = m_nodePool.GetNodeAtIdx(bestNode.pidx);
parentRef = parentNode.id;
if (parentNode.pidx != 0)
{
grandpaRef = m_nodePool.getNodeAtIdx(parentNode.pidx).id;
grandpaRef = m_nodePool.GetNodeAtIdx(parentNode.pidx).id;
}
}
if (parentRef != 0)
{
bool invalidParent = false;
tileAndPoly = m_nav.getTileAndPolyByRef(parentRef);
tileAndPoly = m_nav.GetTileAndPolyByRef(parentRef);
invalidParent = tileAndPoly.Failed();
if (invalidParent || (grandpaRef != 0 && !m_nav.isValidPolyRef(grandpaRef)))
if (invalidParent || (grandpaRef != 0 && !m_nav.IsValidPolyRef(grandpaRef)))
{
// The polygon has disappeared during the sliced query,
// fail.
@ -317,7 +317,7 @@ namespace DotRecast.Detour
bool tryLOS = false;
if ((m_query.options & DT_FINDPATH_ANY_ANGLE) != 0)
{
if ((parentRef != 0) && (vDistSqr(parentNode.pos, bestNode.pos) < m_query.raycastLimitSqr))
if ((parentRef != 0) && (VDistSqr(parentNode.pos, bestNode.pos) < m_query.raycastLimitSqr))
{
tryLOS = true;
}
@ -337,17 +337,17 @@ namespace DotRecast.Detour
// Get neighbour poly and tile.
// The API input has been cheked already, skip checking internal
// data.
Tuple<MeshTile, Poly> tileAndPolyUns = m_nav.getTileAndPolyByRefUnsafe(neighbourRef);
Tuple<MeshTile, Poly> tileAndPolyUns = m_nav.GetTileAndPolyByRefUnsafe(neighbourRef);
MeshTile neighbourTile = tileAndPolyUns.Item1;
Poly neighbourPoly = tileAndPolyUns.Item2;
if (!m_query.filter.passFilter(neighbourRef, neighbourTile, neighbourPoly))
if (!m_query.filter.PassFilter(neighbourRef, neighbourTile, neighbourPoly))
{
continue;
}
// get the neighbor node
Node neighbourNode = m_nodePool.getNode(neighbourRef, 0);
Node neighbourNode = m_nodePool.GetNode(neighbourRef, 0);
// do not expand to nodes that were already visited from the
// same parent
@ -360,7 +360,7 @@ namespace DotRecast.Detour
// position.
if (neighbourNode.flags == 0)
{
var midpod = getEdgeMidPoint(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly,
var midpod = GetEdgeMidPoint(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly,
neighbourTile);
if (!midpod.Failed())
{
@ -376,7 +376,7 @@ namespace DotRecast.Detour
bool foundShortCut = false;
if (tryLOS)
{
Result<RaycastHit> rayHit = raycast(parentRef, parentNode.pos, neighbourNode.pos, m_query.filter,
Result<RaycastHit> rayHit = Raycast(parentRef, parentNode.pos, neighbourNode.pos, m_query.filter,
DT_RAYCAST_USE_COSTS, grandpaRef);
if (rayHit.Succeeded())
{
@ -394,7 +394,7 @@ namespace DotRecast.Detour
if (!foundShortCut)
{
// No shortcut found.
float curCost = m_query.filter.getCost(bestNode.pos, neighbourNode.pos, parentRef, parentTile,
float curCost = m_query.filter.GetCost(bestNode.pos, neighbourNode.pos, parentRef, parentTile,
parentPoly, bestRef, bestTile, bestPoly, neighbourRef, neighbourTile, neighbourPoly);
cost = bestNode.cost + curCost;
}
@ -402,7 +402,7 @@ namespace DotRecast.Detour
// Special case for last node.
if (neighbourRef == m_query.endRef)
{
float endCost = m_query.filter.getCost(neighbourNode.pos, m_query.endPos, bestRef, bestTile,
float endCost = m_query.filter.GetCost(neighbourNode.pos, m_query.endPos, bestRef, bestTile,
bestPoly, neighbourRef, neighbourTile, neighbourPoly, 0, null, null);
cost = cost + endCost;
@ -410,7 +410,7 @@ namespace DotRecast.Detour
}
else
{
heuristic = vDist(neighbourNode.pos, m_query.endPos) * H_SCALE;
heuristic = VDist(neighbourNode.pos, m_query.endPos) * H_SCALE;
}
float total = cost + heuristic;
@ -430,7 +430,7 @@ namespace DotRecast.Detour
}
// Add or update the node.
neighbourNode.pidx = foundShortCut ? bestNode.pidx : m_nodePool.getNodeIdx(bestNode);
neighbourNode.pidx = foundShortCut ? bestNode.pidx : m_nodePool.GetNodeIdx(bestNode);
neighbourNode.id = neighbourRef;
neighbourNode.flags = (neighbourNode.flags & ~(Node.DT_NODE_CLOSED | Node.DT_NODE_PARENT_DETACHED));
neighbourNode.cost = cost;
@ -443,13 +443,13 @@ namespace DotRecast.Detour
if ((neighbourNode.flags & Node.DT_NODE_OPEN) != 0)
{
// Already in open, update node location.
m_openList.modify(neighbourNode);
m_openList.Modify(neighbourNode);
}
else
{
// Put the node in open list.
neighbourNode.flags |= Node.DT_NODE_OPEN;
m_openList.push(neighbourNode);
m_openList.Push(neighbourNode);
}
// Update nearest node to target so far.
@ -462,7 +462,7 @@ namespace DotRecast.Detour
}
// Exhausted all nodes, but could not find path.
if (m_openList.isEmpty())
if (m_openList.IsEmpty())
{
m_query.status = Status.PARTIAL_RESULT;
}
@ -474,10 +474,10 @@ namespace DotRecast.Detour
/// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
/// [(polyRef) * @p pathCount]
/// @returns The status flags for the query.
public override Result<List<long>> finalizeSlicedFindPath()
public override Result<List<long>> FinalizeSlicedFindPath()
{
List<long> path = new List<long>(64);
if (m_query.status.isFailed())
if (m_query.status.IsFailed())
{
// Reset query.
m_query = new QueryData();
@ -502,8 +502,8 @@ namespace DotRecast.Detour
int prevRay = 0;
do
{
Node next = m_nodePool.getNodeAtIdx(node.pidx);
node.pidx = m_nodePool.getNodeIdx(prev);
Node next = m_nodePool.GetNodeAtIdx(node.pidx);
node.pidx = m_nodePool.GetNodeIdx(prev);
prev = node;
int nextRay = node.flags & Node.DT_NODE_PARENT_DETACHED; // keep track of whether parent is not adjacent
// (i.e. due to raycast shortcut)
@ -517,10 +517,10 @@ namespace DotRecast.Detour
node = prev;
do
{
Node next = m_nodePool.getNodeAtIdx(node.pidx);
Node next = m_nodePool.GetNodeAtIdx(node.pidx);
if ((node.flags & Node.DT_NODE_PARENT_DETACHED) != 0)
{
Result<RaycastHit> iresult = raycast(node.id, node.pos, next.pos, m_query.filter, 0, 0);
Result<RaycastHit> iresult = Raycast(node.id, node.pos, next.pos, m_query.filter, 0, 0);
if (iresult.Succeeded())
{
path.AddRange(iresult.result.path);
@ -555,7 +555,7 @@ namespace DotRecast.Detour
/// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
/// [(polyRef) * @p pathCount]
/// @returns The status flags for the query.
public override Result<List<long>> finalizeSlicedFindPathPartial(List<long> existing)
public override Result<List<long>> FinalizeSlicedFindPathPartial(List<long> existing)
{
List<long> path = new List<long>(64);
if (null == existing || existing.Count <= 0)
@ -563,7 +563,7 @@ namespace DotRecast.Detour
return Results.Failure(path);
}
if (m_query.status.isFailed())
if (m_query.status.IsFailed())
{
// Reset query.
m_query = new QueryData();
@ -582,7 +582,7 @@ namespace DotRecast.Detour
Node node = null;
for (int i = existing.Count - 1; i >= 0; --i)
{
node = m_nodePool.findNode(existing[i]);
node = m_nodePool.FindNode(existing[i]);
if (node != null)
{
break;
@ -599,8 +599,8 @@ namespace DotRecast.Detour
int prevRay = 0;
do
{
Node next = m_nodePool.getNodeAtIdx(node.pidx);
node.pidx = m_nodePool.getNodeIdx(prev);
Node next = m_nodePool.GetNodeAtIdx(node.pidx);
node.pidx = m_nodePool.GetNodeIdx(prev);
prev = node;
int nextRay = node.flags & Node.DT_NODE_PARENT_DETACHED; // keep track of whether parent is not adjacent
// (i.e. due to raycast shortcut)
@ -614,10 +614,10 @@ namespace DotRecast.Detour
node = prev;
do
{
Node next = m_nodePool.getNodeAtIdx(node.pidx);
Node next = m_nodePool.GetNodeAtIdx(node.pidx);
if ((node.flags & Node.DT_NODE_PARENT_DETACHED) != 0)
{
Result<RaycastHit> iresult = raycast(node.id, node.pos, next.pos, m_query.filter, 0, 0);
Result<RaycastHit> iresult = Raycast(node.id, node.pos, next.pos, m_query.filter, 0, 0);
if (iresult.Succeeded())
{
path.AddRange(iresult.result.path);
@ -645,41 +645,41 @@ namespace DotRecast.Detour
return Results.Of(status, path);
}
public override Result<FindDistanceToWallResult> findDistanceToWall(long startRef, Vector3f centerPos, float maxRadius, QueryFilter filter)
public override Result<FindDistanceToWallResult> FindDistanceToWall(long startRef, Vector3f centerPos, float maxRadius, QueryFilter filter)
{
// Validate input
if (!m_nav.isValidPolyRef(startRef) || !vIsFinite(centerPos) || maxRadius < 0
if (!m_nav.IsValidPolyRef(startRef) || !VIsFinite(centerPos) || maxRadius < 0
|| !float.IsFinite(maxRadius) || null == filter)
{
return Results.InvalidParam<FindDistanceToWallResult>();
}
m_nodePool.clear();
m_openList.clear();
m_nodePool.Clear();
m_openList.Clear();
Node startNode = m_nodePool.getNode(startRef);
Node startNode = m_nodePool.GetNode(startRef);
startNode.pos = centerPos;
startNode.pidx = 0;
startNode.cost = 0;
startNode.total = 0;
startNode.id = startRef;
startNode.flags = Node.DT_NODE_OPEN;
m_openList.push(startNode);
m_openList.Push(startNode);
float radiusSqr = sqr(maxRadius);
float radiusSqr = Sqr(maxRadius);
Vector3f hitPos = new Vector3f();
VectorPtr bestvj = null;
VectorPtr bestvi = null;
while (!m_openList.isEmpty())
while (!m_openList.IsEmpty())
{
Node bestNode = m_openList.pop();
Node bestNode = m_openList.Pop();
bestNode.flags &= ~Node.DT_NODE_OPEN;
bestNode.flags |= Node.DT_NODE_CLOSED;
// Get poly and tile.
// The API input has been cheked already, skip checking internal data.
long bestRef = bestNode.id;
Tuple<MeshTile, Poly> tileAndPoly = m_nav.getTileAndPolyByRefUnsafe(bestRef);
Tuple<MeshTile, Poly> tileAndPoly = m_nav.GetTileAndPolyByRefUnsafe(bestRef);
MeshTile bestTile = tileAndPoly.Item1;
Poly bestPoly = tileAndPoly.Item2;
@ -687,7 +687,7 @@ namespace DotRecast.Detour
long parentRef = 0;
if (bestNode.pidx != 0)
{
parentRef = m_nodePool.getNodeAtIdx(bestNode.pidx).id;
parentRef = m_nodePool.GetNodeAtIdx(bestNode.pidx).id;
}
// Hit test walls.
@ -705,10 +705,10 @@ namespace DotRecast.Detour
{
if (link.refs != 0)
{
Tuple<MeshTile, Poly> linkTileAndPoly = m_nav.getTileAndPolyByRefUnsafe(link.refs);
Tuple<MeshTile, Poly> linkTileAndPoly = m_nav.GetTileAndPolyByRefUnsafe(link.refs);
MeshTile neiTile = linkTileAndPoly.Item1;
Poly neiPoly = linkTileAndPoly.Item2;
if (filter.passFilter(link.refs, neiTile, neiPoly))
if (filter.PassFilter(link.refs, neiTile, neiPoly))
{
solid = false;
}
@ -727,8 +727,8 @@ namespace DotRecast.Detour
{
// Internal edge
int idx = (bestPoly.neis[j] - 1);
long refs = m_nav.getPolyRefBase(bestTile) | idx;
if (filter.passFilter(refs, bestTile, bestTile.data.polys[idx]))
long refs = m_nav.GetPolyRefBase(bestTile) | idx;
if (filter.PassFilter(refs, bestTile, bestTile.data.polys[idx]))
{
continue;
}
@ -737,7 +737,7 @@ namespace DotRecast.Detour
// Calc distance to the edge.
int vj = bestPoly.verts[j] * 3;
int vi = bestPoly.verts[i] * 3;
Tuple<float, float> distseg = distancePtSegSqr2D(centerPos, bestTile.data.verts, vj, vi);
Tuple<float, float> distseg = DistancePtSegSqr2D(centerPos, bestTile.data.verts, vj, vi);
float distSqr = distseg.Item1;
float tseg = distseg.Item2;
@ -770,12 +770,12 @@ namespace DotRecast.Detour
}
// Expand to neighbour.
Tuple<MeshTile, Poly> neighbourTileAndPoly = m_nav.getTileAndPolyByRefUnsafe(neighbourRef);
Tuple<MeshTile, Poly> neighbourTileAndPoly = m_nav.GetTileAndPolyByRefUnsafe(neighbourRef);
MeshTile neighbourTile = neighbourTileAndPoly.Item1;
Poly neighbourPoly = neighbourTileAndPoly.Item2;
// Skip off-mesh connections.
if (neighbourPoly.getType() == Poly.DT_POLYTYPE_OFFMESH_CONNECTION)
if (neighbourPoly.GetType() == Poly.DT_POLYTYPE_OFFMESH_CONNECTION)
{
continue;
}
@ -783,7 +783,7 @@ namespace DotRecast.Detour
// Calc distance to the edge.
int va = bestPoly.verts[link.edge] * 3;
int vb = bestPoly.verts[(link.edge + 1) % bestPoly.vertCount] * 3;
Tuple<float, float> distseg = distancePtSegSqr2D(centerPos, bestTile.data.verts, va, vb);
Tuple<float, float> distseg = DistancePtSegSqr2D(centerPos, bestTile.data.verts, va, vb);
float distSqr = distseg.Item1;
// If the circle is not touching the next polygon, skip it.
if (distSqr > radiusSqr)
@ -791,12 +791,12 @@ namespace DotRecast.Detour
continue;
}
if (!filter.passFilter(neighbourRef, neighbourTile, neighbourPoly))
if (!filter.PassFilter(neighbourRef, neighbourTile, neighbourPoly))
{
continue;
}
Node neighbourNode = m_nodePool.getNode(neighbourRef);
Node neighbourNode = m_nodePool.GetNode(neighbourRef);
if ((neighbourNode.flags & Node.DT_NODE_CLOSED) != 0)
{
@ -806,7 +806,7 @@ namespace DotRecast.Detour
// Cost
if (neighbourNode.flags == 0)
{
var midPoint = getEdgeMidPoint(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly,
var midPoint = GetEdgeMidPoint(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly,
neighbourTile);
if (midPoint.Succeeded())
{
@ -814,7 +814,7 @@ namespace DotRecast.Detour
}
}
float total = bestNode.total + vDist(bestNode.pos, neighbourNode.pos);
float total = bestNode.total + VDist(bestNode.pos, neighbourNode.pos);
// The node is already in open list and the new result is worse, skip.
if ((neighbourNode.flags & Node.DT_NODE_OPEN) != 0 && total >= neighbourNode.total)
@ -824,17 +824,17 @@ namespace DotRecast.Detour
neighbourNode.id = neighbourRef;
neighbourNode.flags = (neighbourNode.flags & ~Node.DT_NODE_CLOSED);
neighbourNode.pidx = m_nodePool.getNodeIdx(bestNode);
neighbourNode.pidx = m_nodePool.GetNodeIdx(bestNode);
neighbourNode.total = total;
if ((neighbourNode.flags & Node.DT_NODE_OPEN) != 0)
{
m_openList.modify(neighbourNode);
m_openList.Modify(neighbourNode);
}
else
{
neighbourNode.flags |= Node.DT_NODE_OPEN;
m_openList.push(neighbourNode);
m_openList.Push(neighbourNode);
}
}
}
@ -843,11 +843,11 @@ namespace DotRecast.Detour
Vector3f hitNormal = new Vector3f();
if (bestvi != null && bestvj != null)
{
var tangent = vSub(bestvi, bestvj);
var tangent = VSub(bestvi, bestvj);
hitNormal.x = tangent.z;
hitNormal.y = 0;
hitNormal.z = -tangent.x;
vNormalize(ref hitNormal);
VNormalize(ref hitNormal);
}
return Results.Success(new FindDistanceToWallResult((float)Math.Sqrt(radiusSqr), hitPos, hitNormal));

File diff suppressed because it is too large Load Diff

View File

@ -61,7 +61,7 @@ namespace DotRecast.Detour
}
}
private static int[][] calcExtends(BVItem[] items, int nitems, int imin, int imax)
private static int[][] CalcExtends(BVItem[] items, int nitems, int imin, int imax)
{
int[] bmin = new int[3];
int[] bmax = new int[3];
@ -94,7 +94,7 @@ namespace DotRecast.Detour
return new int[][] { bmin, bmax };
}
private static int longestAxis(int x, int y, int z)
private static int LongestAxis(int x, int y, int z)
{
int axis = 0;
int maxVal = x;
@ -113,7 +113,7 @@ namespace DotRecast.Detour
return axis;
}
public static int subdivide(BVItem[] items, int nitems, int imin, int imax, int curNode, BVNode[] nodes)
public static int Subdivide(BVItem[] items, int nitems, int imin, int imax, int curNode, BVNode[] nodes)
{
int inum = imax - imin;
int icur = curNode;
@ -137,11 +137,11 @@ namespace DotRecast.Detour
else
{
// Split
int[][] minmax = calcExtends(items, nitems, imin, imax);
int[][] minmax = CalcExtends(items, nitems, imin, imax);
node.bmin = minmax[0];
node.bmax = minmax[1];
int axis = longestAxis(node.bmax[0] - node.bmin[0], node.bmax[1] - node.bmin[1],
int axis = LongestAxis(node.bmax[0] - node.bmin[0], node.bmax[1] - node.bmin[1],
node.bmax[2] - node.bmin[2]);
if (axis == 0)
@ -163,9 +163,9 @@ namespace DotRecast.Detour
int isplit = imin + inum / 2;
// Left
curNode = subdivide(items, nitems, imin, isplit, curNode, nodes);
curNode = Subdivide(items, nitems, imin, isplit, curNode, nodes);
// Right
curNode = subdivide(items, nitems, isplit, imax, curNode, nodes);
curNode = Subdivide(items, nitems, isplit, imax, curNode, nodes);
int iescape = curNode - icur;
// Negative index means escape.
@ -175,7 +175,7 @@ namespace DotRecast.Detour
return curNode;
}
private static int createBVTree(NavMeshDataCreateParams option, BVNode[] nodes)
private static int CreateBVTree(NavMeshDataCreateParams option, BVNode[] nodes)
{
// Build tree
float quantFactor = 1 / option.cs;
@ -193,22 +193,22 @@ namespace DotRecast.Detour
Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f();
int dv = vb * 3;
vCopy(ref bmin, option.detailVerts, dv);
vCopy(ref bmax, option.detailVerts, dv);
VCopy(ref bmin, option.detailVerts, dv);
VCopy(ref bmax, option.detailVerts, dv);
for (int j = 1; j < ndv; j++)
{
vMin(ref bmin, option.detailVerts, dv + j * 3);
vMax(ref bmax, option.detailVerts, dv + j * 3);
VMin(ref bmin, option.detailVerts, dv + j * 3);
VMax(ref bmax, option.detailVerts, dv + j * 3);
}
// BV-tree uses cs for all dimensions
it.bmin[0] = clamp((int)((bmin.x - option.bmin.x) * quantFactor), 0, int.MaxValue);
it.bmin[1] = clamp((int)((bmin.y - option.bmin.y) * quantFactor), 0, int.MaxValue);
it.bmin[2] = clamp((int)((bmin.z - option.bmin.z) * quantFactor), 0, int.MaxValue);
it.bmin[0] = Clamp((int)((bmin.x - option.bmin.x) * quantFactor), 0, int.MaxValue);
it.bmin[1] = Clamp((int)((bmin.y - option.bmin.y) * quantFactor), 0, int.MaxValue);
it.bmin[2] = Clamp((int)((bmin.z - option.bmin.z) * quantFactor), 0, int.MaxValue);
it.bmax[0] = clamp((int)((bmax.x - option.bmin.x) * quantFactor), 0, int.MaxValue);
it.bmax[1] = clamp((int)((bmax.y - option.bmin.y) * quantFactor), 0, int.MaxValue);
it.bmax[2] = clamp((int)((bmax.z - option.bmin.z) * quantFactor), 0, int.MaxValue);
it.bmax[0] = Clamp((int)((bmax.x - option.bmin.x) * quantFactor), 0, int.MaxValue);
it.bmax[1] = Clamp((int)((bmax.y - option.bmin.y) * quantFactor), 0, int.MaxValue);
it.bmax[2] = Clamp((int)((bmax.z - option.bmin.z) * quantFactor), 0, int.MaxValue);
}
else
{
@ -246,7 +246,7 @@ namespace DotRecast.Detour
}
}
return subdivide(items, option.polyCount, 0, option.polyCount, 0, nodes);
return Subdivide(items, option.polyCount, 0, option.polyCount, 0, nodes);
}
const int XP = 1 << 0;
@ -254,13 +254,13 @@ namespace DotRecast.Detour
const int XM = 1 << 2;
const int ZM = 1 << 3;
public static int classifyOffMeshPoint(VectorPtr pt, Vector3f bmin, Vector3f bmax)
public static int ClassifyOffMeshPoint(VectorPtr pt, Vector3f bmin, Vector3f bmax)
{
int outcode = 0;
outcode |= (pt.get(0) >= bmax.x) ? XP : 0;
outcode |= (pt.get(2) >= bmax.z) ? ZP : 0;
outcode |= (pt.get(0) < bmin.x) ? XM : 0;
outcode |= (pt.get(2) < bmin.z) ? ZM : 0;
outcode |= (pt.Get(0) >= bmax.x) ? XP : 0;
outcode |= (pt.Get(2) >= bmax.z) ? ZP : 0;
outcode |= (pt.Get(0) < bmin.x) ? XM : 0;
outcode |= (pt.Get(2) < bmin.z) ? ZM : 0;
switch (outcode)
{
@ -293,7 +293,7 @@ namespace DotRecast.Detour
*
* @return created tile data
*/
public static MeshData createNavMeshData(NavMeshDataCreateParams option)
public static MeshData CreateNavMeshData(NavMeshDataCreateParams option)
{
if (option.vertCount >= 0xffff)
return null;
@ -353,14 +353,14 @@ namespace DotRecast.Detour
VectorPtr p0 = new VectorPtr(option.offMeshConVerts, (i * 2 + 0) * 3);
VectorPtr p1 = new VectorPtr(option.offMeshConVerts, (i * 2 + 1) * 3);
offMeshConClass[i * 2 + 0] = classifyOffMeshPoint(p0, bmin, bmax);
offMeshConClass[i * 2 + 1] = classifyOffMeshPoint(p1, bmin, bmax);
offMeshConClass[i * 2 + 0] = ClassifyOffMeshPoint(p0, bmin, bmax);
offMeshConClass[i * 2 + 1] = ClassifyOffMeshPoint(p1, bmin, bmax);
// Zero out off-mesh start positions which are not even
// potentially touching the mesh.
if (offMeshConClass[i * 2 + 0] == 0xff)
{
if (p0.get(1) < bmin.y || p0.get(1) > bmax.y)
if (p0.Get(1) < bmin.y || p0.Get(1) > bmax.y)
offMeshConClass[i * 2 + 0] = 0;
}
@ -517,8 +517,8 @@ namespace DotRecast.Detour
navPolys[i] = p;
p.vertCount = 0;
p.flags = option.polyFlags[i];
p.setArea(option.polyAreas[i]);
p.setType(Poly.DT_POLYTYPE_GROUND);
p.SetArea(option.polyAreas[i]);
p.SetType(Poly.DT_POLYTYPE_GROUND);
for (int j = 0; j < nvp; ++j)
{
if (option.polys[src + j] == MESH_NULL_IDX)
@ -564,8 +564,8 @@ namespace DotRecast.Detour
p.verts[0] = offMeshVertsBase + n * 2;
p.verts[1] = offMeshVertsBase + n * 2 + 1;
p.flags = option.offMeshConFlags[i];
p.setArea(option.offMeshConAreas[i]);
p.setType(Poly.DT_POLYTYPE_OFFMESH_CONNECTION);
p.SetArea(option.offMeshConAreas[i]);
p.SetType(Poly.DT_POLYTYPE_OFFMESH_CONNECTION);
n++;
}
}
@ -637,7 +637,7 @@ namespace DotRecast.Detour
if (option.buildBvTree)
{
// Do not set header.bvNodeCount set to make it work look exactly the same as in original Detour
header.bvNodeCount = createBVTree(option, navBvtree);
header.bvNodeCount = CreateBVTree(option, navBvtree);
}
// Store Off-Mesh connections.

File diff suppressed because it is too large Load Diff

View File

@ -26,14 +26,14 @@ namespace DotRecast.Detour
*/
public static class NavMeshRaycast
{
public static float? raycast(NavMesh mesh, Vector3f src, Vector3f dst)
public static float? Raycast(NavMesh mesh, Vector3f src, Vector3f dst)
{
for (int t = 0; t < mesh.getMaxTiles(); ++t)
for (int t = 0; t < mesh.GetMaxTiles(); ++t)
{
MeshTile tile = mesh.getTile(t);
MeshTile tile = mesh.GetTile(t);
if (tile != null && tile.data != null)
{
float? intersection = raycast(tile, src, dst);
float? intersection = Raycast(tile, src, dst);
if (null != intersection)
{
return intersection;
@ -44,12 +44,12 @@ namespace DotRecast.Detour
return null;
}
private static float? raycast(MeshTile tile, Vector3f sp, Vector3f sq)
private static float? Raycast(MeshTile tile, Vector3f sp, Vector3f sq)
{
for (int i = 0; i < tile.data.header.polyCount; ++i)
{
Poly p = tile.data.polys[i];
if (p.getType() == Poly.DT_POLYTYPE_OFFMESH_CONNECTION)
if (p.GetType() == Poly.DT_POLYTYPE_OFFMESH_CONNECTION)
{
continue;
}
@ -79,7 +79,7 @@ namespace DotRecast.Detour
}
}
float? intersection = Intersections.intersectSegmentTriangle(sp, sq, verts[0], verts[1], verts[2]);
float? intersection = Intersections.IntersectSegmentTriangle(sp, sq, verts[0], verts[1], verts[2]);
if (null != intersection)
{
return intersection;

View File

@ -24,13 +24,13 @@ namespace DotRecast.Detour
{
public static class NavMeshUtils
{
public static Vector3f[] getNavMeshBounds(NavMesh mesh)
public static Vector3f[] GetNavMeshBounds(NavMesh mesh)
{
Vector3f bmin = Vector3f.Of(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
Vector3f bmax = Vector3f.Of(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
for (int t = 0; t < mesh.getMaxTiles(); ++t)
for (int t = 0; t < mesh.GetMaxTiles(); ++t)
{
MeshTile tile = mesh.getTile(t);
MeshTile tile = mesh.GetTile(t);
if (tile != null && tile.data != null)
{
for (int i = 0; i < tile.data.verts.Length; i += 3)

View File

@ -31,13 +31,13 @@ namespace DotRecast.Detour
{
}
public void clear()
public void Clear()
{
m_nodes.Clear();
m_map.Clear();
}
public List<Node> findNodes(long id)
public List<Node> FindNodes(long id)
{
var hasNode = m_map.TryGetValue(id, out var nodes);
;
@ -49,7 +49,7 @@ namespace DotRecast.Detour
return nodes;
}
public Node findNode(long id)
public Node FindNode(long id)
{
var hasNode = m_map.TryGetValue(id, out var nodes);
;
@ -61,7 +61,7 @@ namespace DotRecast.Detour
return null;
}
public Node getNode(long id, int state)
public Node GetNode(long id, int state)
{
var hasNode = m_map.TryGetValue(id, out var nodes);
;
@ -76,10 +76,10 @@ namespace DotRecast.Detour
}
}
return create(id, state);
return Create(id, state);
}
protected Node create(long id, int state)
protected Node Create(long id, int state)
{
Node node = new Node(m_nodes.Count + 1);
node.id = id;
@ -97,22 +97,22 @@ namespace DotRecast.Detour
return node;
}
public int getNodeIdx(Node node)
public int GetNodeIdx(Node node)
{
return node != null ? node.index : 0;
}
public Node getNodeAtIdx(int idx)
public Node GetNodeAtIdx(int idx)
{
return idx != 0 ? m_nodes[idx - 1] : null;
}
public Node getNode(long refs)
public Node GetNode(long refs)
{
return getNode(refs, 0);
return GetNode(refs, 0);
}
public Dictionary<long, List<Node>> getNodeMap()
public Dictionary<long, List<Node>> GetNodeMap()
{
return m_map;
}

View File

@ -28,40 +28,40 @@ namespace DotRecast.Detour
{
private readonly SortedQueue<Node> m_heap = new SortedQueue<Node>((n1, n2) => n1.total.CompareTo(n2.total));
public int count()
public int Count()
{
return m_heap.Count();
}
public void clear()
public void Clear()
{
m_heap.Clear();
}
public Node top()
public Node Top()
{
return m_heap.Top();
}
public Node pop()
public Node Pop()
{
var node = top();
var node = Top();
m_heap.Remove(node);
return node;
}
public void push(Node node)
public void Push(Node node)
{
m_heap.Enqueue(node);
}
public void modify(Node node)
public void Modify(Node node)
{
m_heap.Remove(node);
push(node);
Push(node);
}
public bool isEmpty()
public bool IsEmpty()
{
return 0 == m_heap.Count();
}

View File

@ -30,11 +30,11 @@ namespace DotRecast.Detour
private const int MAX_STEER_POINTS = 3;
public static SteerTarget getSteerTarget(NavMeshQuery navQuery, Vector3f startPos, Vector3f endPos,
public static SteerTarget GetSteerTarget(NavMeshQuery navQuery, Vector3f startPos, Vector3f endPos,
float minTargetDist, List<long> path)
{
// Find steer target.
Result<List<StraightPathItem>> result = navQuery.findStraightPath(startPos, endPos, path, MAX_STEER_POINTS, 0);
Result<List<StraightPathItem>> result = navQuery.FindStraightPath(startPos, endPos, path, MAX_STEER_POINTS, 0);
if (result.Failed())
{
return null;
@ -44,9 +44,9 @@ namespace DotRecast.Detour
float[] steerPoints = new float[straightPath.Count * 3];
for (int i = 0; i < straightPath.Count; i++)
{
steerPoints[i * 3] = straightPath[i].getPos().x;
steerPoints[i * 3 + 1] = straightPath[i].getPos().y;
steerPoints[i * 3 + 2] = straightPath[i].getPos().z;
steerPoints[i * 3] = straightPath[i].GetPos().x;
steerPoints[i * 3 + 1] = straightPath[i].GetPos().y;
steerPoints[i * 3 + 2] = straightPath[i].GetPos().z;
}
// Find vertex far enough to steer to.
@ -54,8 +54,8 @@ namespace DotRecast.Detour
while (ns < straightPath.Count)
{
// Stop at Off-Mesh link or when point is further than slop away.
if (((straightPath[ns].getFlags() & NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|| !inRange(straightPath[ns].getPos(), startPos, minTargetDist, 1000.0f))
if (((straightPath[ns].GetFlags() & NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|| !InRange(straightPath[ns].GetPos(), startPos, minTargetDist, 1000.0f))
break;
ns++;
}
@ -65,18 +65,18 @@ namespace DotRecast.Detour
return null;
Vector3f steerPos = Vector3f.Of(
straightPath[ns].getPos().x,
straightPath[ns].GetPos().x,
startPos.y,
straightPath[ns].getPos().z
straightPath[ns].GetPos().z
);
int steerPosFlag = straightPath[ns].getFlags();
long steerPosRef = straightPath[ns].getRef();
int steerPosFlag = straightPath[ns].GetFlags();
long steerPosRef = straightPath[ns].GetRef();
SteerTarget target = new SteerTarget(steerPos, steerPosFlag, steerPosRef, steerPoints);
return target;
}
public static bool inRange(Vector3f v1, Vector3f v2, float r, float h)
public static bool InRange(Vector3f v1, Vector3f v2, float r, float h)
{
float dx = v2.x - v1.x;
float dy = v2.y - v1.y;
@ -84,7 +84,7 @@ namespace DotRecast.Detour
return (dx * dx + dz * dz) < r * r && Math.Abs(dy) < h;
}
public static List<long> fixupCorridor(List<long> path, List<long> visited)
public static List<long> FixupCorridor(List<long> path, List<long> visited)
{
int furthestPath = -1;
int furthestVisited = -1;
@ -143,7 +143,7 @@ namespace DotRecast.Detour
// +-S-+-T-+
// |:::| | <-- the step can end up in here, resulting U-turn path.
// +---+---+
public static List<long> fixupShortcuts(List<long> path, NavMeshQuery navQuery)
public static List<long> FixupShortcuts(List<long> path, NavMeshQuery navQuery)
{
if (path.Count < 3)
{
@ -153,7 +153,7 @@ namespace DotRecast.Detour
// Get connected polygons
List<long> neis = new List<long>();
Result<Tuple<MeshTile, Poly>> tileAndPoly = navQuery.getAttachedNavMesh().getTileAndPolyByRef(path[0]);
Result<Tuple<MeshTile, Poly>> tileAndPoly = navQuery.GetAttachedNavMesh().GetTileAndPolyByRef(path[0]);
if (tileAndPoly.Failed())
{
return path;

View File

@ -58,25 +58,25 @@ namespace DotRecast.Detour
}
/** Sets the user defined area id. [Limit: &lt; {@link org.recast4j.detour.NavMesh#DT_MAX_AREAS}] */
public void setArea(int a)
public void SetArea(int a)
{
areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f);
}
/** Sets the polygon type. (See: #dtPolyTypes.) */
public void setType(int t)
public void SetType(int t)
{
areaAndtype = (areaAndtype & 0x3f) | (t << 6);
}
/** Gets the user defined area id. */
public int getArea()
public int GetArea()
{
return areaAndtype & 0x3f;
}
/** Gets the polygon type. (See: #dtPolyTypes) */
public int getType()
public int GetType()
{
return areaAndtype >> 6;
}

View File

@ -2,6 +2,6 @@ namespace DotRecast.Detour
{
public interface PolyQuery
{
void process(MeshTile tile, Poly poly, long refs);
void Process(MeshTile tile, Poly poly, long refs);
}
}

View File

@ -25,21 +25,21 @@ namespace DotRecast.Detour
public interface PolygonByCircleConstraint
{
float[] aply(float[] polyVerts, Vector3f circleCenter, float radius);
float[] Aply(float[] polyVerts, Vector3f circleCenter, float radius);
public static PolygonByCircleConstraint noop()
public static PolygonByCircleConstraint Noop()
{
return new NoOpPolygonByCircleConstraint();
}
public static PolygonByCircleConstraint strict()
public static PolygonByCircleConstraint Strict()
{
return new StrictPolygonByCircleConstraint();
}
public class NoOpPolygonByCircleConstraint : PolygonByCircleConstraint
{
public float[] aply(float[] polyVerts, Vector3f circleCenter, float radius)
public float[] Aply(float[] polyVerts, Vector3f circleCenter, float radius)
{
return polyVerts;
}
@ -53,13 +53,13 @@ namespace DotRecast.Detour
private const int CIRCLE_SEGMENTS = 12;
private static float[] unitCircle;
public float[] aply(float[] verts, Vector3f center, float radius)
public float[] Aply(float[] verts, Vector3f center, float radius)
{
float radiusSqr = radius * radius;
int outsideVertex = -1;
for (int pv = 0; pv < verts.Length; pv += 3)
{
if (vDist2DSqr(center, verts, pv) > radiusSqr)
if (VDist2DSqr(center, verts, pv) > radiusSqr)
{
outsideVertex = pv;
break;
@ -72,9 +72,9 @@ namespace DotRecast.Detour
return verts;
}
float[] qCircle = circle(center, radius);
float[] intersection = ConvexConvexIntersection.intersect(verts, qCircle);
if (intersection == null && pointInPolygon(center, verts, verts.Length / 3))
float[] qCircle = Circle(center, radius);
float[] intersection = ConvexConvexIntersection.Intersect(verts, qCircle);
if (intersection == null && PointInPolygon(center, verts, verts.Length / 3))
{
// circle inside polygon
return qCircle;
@ -83,7 +83,7 @@ namespace DotRecast.Detour
return intersection;
}
private float[] circle(Vector3f center, float radius)
private float[] Circle(Vector3f center, float radius)
{
if (unitCircle == null)
{

View File

@ -24,9 +24,9 @@ namespace DotRecast.Detour
{
public interface QueryFilter
{
bool passFilter(long refs, MeshTile tile, Poly poly);
bool PassFilter(long refs, MeshTile tile, Poly poly);
float getCost(Vector3f pa, Vector3f pb, long prevRef, MeshTile prevTile, Poly prevPoly, long curRef, MeshTile curTile,
float GetCost(Vector3f pa, Vector3f pb, long prevRef, MeshTile prevTile, Poly prevPoly, long curRef, MeshTile curTile,
Poly curPoly, long nextRef, MeshTile nextTile, Poly nextPoly);
}
}

View File

@ -22,6 +22,6 @@ namespace DotRecast.Detour
{
public interface QueryHeuristic
{
float getCost(Vector3f neighbourPos, Vector3f endPos);
float GetCost(Vector3f neighbourPos, Vector3f endPos);
}
}

View File

@ -34,13 +34,13 @@ namespace DotRecast.Detour.QueryResults
}
/** Returns true if the position is over the polygon. */
public bool isPosOverPoly()
public bool IsPosOverPoly()
{
return posOverPoly;
}
/** Returns the closest point on the polygon. [(x, y, z)] */
public Vector3f getClosest()
public Vector3f GetClosest()
{
return closest;
}

View File

@ -36,17 +36,17 @@ namespace DotRecast.Detour.QueryResults
this.normal = normal;
}
public float getDistance()
public float GetDistance()
{
return distance;
}
public Vector3f getPosition()
public Vector3f GetPosition()
{
return position;
}
public Vector3f getNormal()
public Vector3f GetNormal()
{
return normal;
}

View File

@ -34,12 +34,12 @@ namespace DotRecast.Detour.QueryResults
this.parentRefs = parentRefs;
}
public List<long> getRefs()
public List<long> GetRefs()
{
return refs;
}
public List<long> getParentRefs()
public List<long> GetParentRefs()
{
return parentRefs;
}

View File

@ -36,18 +36,18 @@ namespace DotRecast.Detour.QueryResults
}
/** Returns the reference id of the nearest polygon. 0 if no polygon is found. */
public long getNearestRef()
public long GetNearestRef()
{
return nearestRef;
}
/** Returns the nearest point on the polygon. [opt] [(x, y, z)]. Unchanged if no polygon is found. */
public Vector3f getNearestPos()
public Vector3f GetNearestPos()
{
return nearestPos;
}
public bool isOverPoly()
public bool IsOverPoly()
{
return overPoly;
}

View File

@ -36,17 +36,17 @@ namespace DotRecast.Detour.QueryResults
this.costs = costs;
}
public List<long> getRefs()
public List<long> GetRefs()
{
return refs;
}
public List<long> getParentRefs()
public List<long> GetParentRefs()
{
return parentRefs;
}
public List<float> getCosts()
public List<float> GetCosts()
{
return costs;
}

View File

@ -35,13 +35,13 @@ namespace DotRecast.Detour.QueryResults
}
/// @param[out] randomRef The reference id of the random location.
public long getRandomRef()
public long GetRandomRef()
{
return randomRef;
}
/// @param[out] randomPt The random location.
public Vector3f getRandomPt()
public Vector3f GetRandomPt()
{
return randomPt;
}

View File

@ -34,23 +34,23 @@ namespace DotRecast.Detour.QueryResults
_segmentRefs = segmentRefs;
}
public int countSegmentVerts()
public int CountSegmentVerts()
{
return _segmentVerts.Count;
}
public int countSegmentRefs()
public int CountSegmentRefs()
{
return _segmentRefs.Count;
}
public SegmentVert getSegmentVert(int idx)
public SegmentVert GetSegmentVert(int idx)
{
return _segmentVerts[idx];
}
public long getSegmentRef(int idx)
public long GetSegmentRef(int idx)
{
return _segmentRefs[idx];
}

View File

@ -37,12 +37,12 @@ namespace DotRecast.Detour.QueryResults
this.visited = visited;
}
public Vector3f getResultPos()
public Vector3f GetResultPos()
{
return resultPos;
}
public List<long> getVisited()
public List<long> GetVisited()
{
return visited;
}

View File

@ -84,12 +84,12 @@ namespace DotRecast.Detour.QueryResults
public bool Failed()
{
return status.isFailed();
return status.IsFailed();
}
public bool Succeeded()
{
return status.isSuccess();
return status.IsSuccess();
}
}
}

View File

@ -38,22 +38,22 @@ namespace DotRecast.Detour
public static class StatusEx
{
public static bool isFailed(this Status @this)
public static bool IsFailed(this Status @this)
{
return @this == Status.FAILURE || @this == Status.FAILURE_INVALID_PARAM;
}
public static bool isInProgress(this Status @this)
public static bool IsInProgress(this Status @this)
{
return @this == Status.IN_PROGRESS;
}
public static bool isSuccess(this Status @this)
public static bool IsSuccess(this Status @this)
{
return @this == Status.SUCCSESS || @this == Status.PARTIAL_RESULT;
}
public static bool isPartial(this Status @this)
public static bool IsPartial(this Status @this)
{
return @this == Status.PARTIAL_RESULT;
}

View File

@ -38,17 +38,17 @@ namespace DotRecast.Detour
this.refs = refs;
}
public Vector3f getPos()
public Vector3f GetPos()
{
return pos;
}
public int getFlags()
public int GetFlags()
{
return flags;
}
public long getRef()
public long GetRef()
{
return refs;
}

View File

@ -5,12 +5,12 @@ namespace DotRecast.Recast.Demo.Builder;
public abstract class AbstractNavMeshBuilder
{
protected NavMeshDataCreateParams getNavMeshCreateParams(DemoInputGeomProvider m_geom, float m_cellSize,
protected NavMeshDataCreateParams GetNavMeshCreateParams(DemoInputGeomProvider m_geom, float m_cellSize,
float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb,
RecastBuilderResult rcResult)
{
PolyMesh m_pmesh = rcResult.getMesh();
PolyMeshDetail m_dmesh = rcResult.getMeshDetail();
PolyMesh m_pmesh = rcResult.GetMesh();
PolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
for (int i = 0; i < m_pmesh.npolys; ++i)
{
@ -42,7 +42,7 @@ public abstract class AbstractNavMeshBuilder
option.ch = m_cellHeight;
option.buildBvTree = true;
option.offMeshConCount = m_geom.getOffMeshConnections().Count;
option.offMeshConCount = m_geom.GetOffMeshConnections().Count;
option.offMeshConVerts = new float[option.offMeshConCount * 6];
option.offMeshConRad = new float[option.offMeshConCount];
option.offMeshConDir = new int[option.offMeshConCount];
@ -51,7 +51,7 @@ public abstract class AbstractNavMeshBuilder
option.offMeshConUserID = new int[option.offMeshConCount];
for (int i = 0; i < option.offMeshConCount; i++)
{
DemoOffMeshConnection offMeshCon = m_geom.getOffMeshConnections()[i];
DemoOffMeshConnection offMeshCon = m_geom.GetOffMeshConnections()[i];
for (int j = 0; j < 6; j++)
{
option.offMeshConVerts[6 * i + j] = offMeshCon.verts[j];
@ -66,27 +66,27 @@ public abstract class AbstractNavMeshBuilder
return option;
}
protected MeshData updateAreaAndFlags(MeshData meshData)
protected MeshData UpdateAreaAndFlags(MeshData meshData)
{
// Update poly flags from areas.
for (int i = 0; i < meshData.polys.Length; ++i)
{
if (meshData.polys[i].getArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WALKABLE)
if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WALKABLE)
{
meshData.polys[i].setArea(SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND);
meshData.polys[i].SetArea(SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND);
}
if (meshData.polys[i].getArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND
|| meshData.polys[i].getArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS
|| meshData.polys[i].getArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD)
if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND
|| meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS
|| meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD)
{
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_WALK;
}
else if (meshData.polys[i].getArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER)
else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER)
{
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM;
}
else if (meshData.polys[i].getArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_DOOR)
else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_DOOR)
{
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR;
}

View File

@ -26,28 +26,28 @@ namespace DotRecast.Recast.Demo.Builder;
public class SoloNavMeshBuilder : AbstractNavMeshBuilder
{
public Tuple<IList<RecastBuilderResult>, NavMesh> build(DemoInputGeomProvider m_geom, PartitionType m_partitionType,
public Tuple<IList<RecastBuilderResult>, NavMesh> Build(DemoInputGeomProvider m_geom, PartitionType m_partitionType,
float m_cellSize, float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb,
float m_agentMaxSlope, int m_regionMinSize, int m_regionMergeSize, float m_edgeMaxLen, float m_edgeMaxError,
int m_vertsPerPoly, float m_detailSampleDist, float m_detailSampleMaxError, bool filterLowHangingObstacles,
bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
{
RecastBuilderResult rcResult = buildRecastResult(m_geom, m_partitionType, m_cellSize, m_cellHeight, m_agentHeight,
RecastBuilderResult rcResult = BuildRecastResult(m_geom, m_partitionType, m_cellSize, m_cellHeight, m_agentHeight,
m_agentRadius, m_agentMaxClimb, m_agentMaxSlope, m_regionMinSize, m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError,
m_vertsPerPoly, m_detailSampleDist, m_detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans,
filterWalkableLowHeightSpans);
return Tuple.Create(ImmutableArray.Create(rcResult) as IList<RecastBuilderResult>,
buildNavMesh(
buildMeshData(m_geom, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, rcResult),
BuildNavMesh(
BuildMeshData(m_geom, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, rcResult),
m_vertsPerPoly));
}
private NavMesh buildNavMesh(MeshData meshData, int m_vertsPerPoly)
private NavMesh BuildNavMesh(MeshData meshData, int m_vertsPerPoly)
{
return new NavMesh(meshData, m_vertsPerPoly, 0);
}
private RecastBuilderResult buildRecastResult(DemoInputGeomProvider m_geom, PartitionType m_partitionType, float m_cellSize,
private RecastBuilderResult BuildRecastResult(DemoInputGeomProvider m_geom, PartitionType m_partitionType, float m_cellSize,
float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb, float m_agentMaxSlope,
int m_regionMinSize, int m_regionMergeSize, float m_edgeMaxLen, float m_edgeMaxError, int m_vertsPerPoly,
float m_detailSampleDist, float m_detailSampleMaxError, bool filterLowHangingObstacles, bool filterLedgeSpans,
@ -57,16 +57,16 @@ public class SoloNavMeshBuilder : AbstractNavMeshBuilder
filterLedgeSpans, filterWalkableLowHeightSpans, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_regionMinSize,
m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, m_detailSampleDist, m_detailSampleMaxError,
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, m_geom.getMeshBoundsMin(), m_geom.getMeshBoundsMax());
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, m_geom.GetMeshBoundsMin(), m_geom.GetMeshBoundsMax());
RecastBuilder rcBuilder = new RecastBuilder();
return rcBuilder.build(m_geom, bcfg);
return rcBuilder.Build(m_geom, bcfg);
}
private MeshData buildMeshData(DemoInputGeomProvider m_geom, float m_cellSize, float m_cellHeight, float m_agentHeight,
private MeshData BuildMeshData(DemoInputGeomProvider m_geom, float m_cellSize, float m_cellHeight, float m_agentHeight,
float m_agentRadius, float m_agentMaxClimb, RecastBuilderResult rcResult)
{
NavMeshDataCreateParams option = getNavMeshCreateParams(m_geom, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius,
NavMeshDataCreateParams option = GetNavMeshCreateParams(m_geom, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius,
m_agentMaxClimb, rcResult);
return updateAreaAndFlags(NavMeshBuilder.createNavMeshData(option));
return UpdateAreaAndFlags(NavMeshBuilder.CreateNavMeshData(option));
}
}

View File

@ -32,87 +32,87 @@ public class TileNavMeshBuilder : AbstractNavMeshBuilder
{
}
public Tuple<IList<RecastBuilderResult>, NavMesh> build(DemoInputGeomProvider m_geom, PartitionType m_partitionType,
public Tuple<IList<RecastBuilderResult>, NavMesh> Build(DemoInputGeomProvider m_geom, PartitionType m_partitionType,
float m_cellSize, float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb,
float m_agentMaxSlope, int m_regionMinSize, int m_regionMergeSize, float m_edgeMaxLen, float m_edgeMaxError,
int m_vertsPerPoly, float m_detailSampleDist, float m_detailSampleMaxError, bool filterLowHangingObstacles,
bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize)
{
List<RecastBuilderResult> rcResult = buildRecastResult(m_geom, m_partitionType, m_cellSize, m_cellHeight, m_agentHeight,
List<RecastBuilderResult> rcResult = BuildRecastResult(m_geom, m_partitionType, m_cellSize, m_cellHeight, m_agentHeight,
m_agentRadius, m_agentMaxClimb, m_agentMaxSlope, m_regionMinSize, m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError,
m_vertsPerPoly, m_detailSampleDist, m_detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans,
filterWalkableLowHeightSpans, tileSize);
return Tuple.Create((IList<RecastBuilderResult>)rcResult,
buildNavMesh(m_geom,
buildMeshData(m_geom, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, rcResult),
BuildNavMesh(m_geom,
BuildMeshData(m_geom, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, rcResult),
m_cellSize, tileSize, m_vertsPerPoly));
}
private List<RecastBuilderResult> buildRecastResult(DemoInputGeomProvider m_geom, PartitionType m_partitionType,
private List<RecastBuilderResult> BuildRecastResult(DemoInputGeomProvider m_geom, PartitionType m_partitionType,
float m_cellSize, float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb,
float m_agentMaxSlope, int m_regionMinSize, int m_regionMergeSize, float m_edgeMaxLen, float m_edgeMaxError,
int m_vertsPerPoly, float m_detailSampleDist, float m_detailSampleMaxError, bool filterLowHangingObstacles,
bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize)
{
RecastConfig cfg = new RecastConfig(true, tileSize, tileSize, RecastConfig.calcBorder(m_agentRadius, m_cellSize),
RecastConfig cfg = new RecastConfig(true, tileSize, tileSize, RecastConfig.CalcBorder(m_agentRadius, m_cellSize),
m_partitionType, m_cellSize, m_cellHeight, m_agentMaxSlope, filterLowHangingObstacles, filterLedgeSpans,
filterWalkableLowHeightSpans, m_agentHeight, m_agentRadius, m_agentMaxClimb,
m_regionMinSize * m_regionMinSize * m_cellSize * m_cellSize,
m_regionMergeSize * m_regionMergeSize * m_cellSize * m_cellSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly,
true, m_detailSampleDist, m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE);
RecastBuilder rcBuilder = new RecastBuilder();
return rcBuilder.buildTiles(m_geom, cfg, Task.Factory);
return rcBuilder.BuildTiles(m_geom, cfg, Task.Factory);
}
private NavMesh buildNavMesh(DemoInputGeomProvider geom, List<MeshData> meshData, float cellSize, int tileSize,
private NavMesh BuildNavMesh(DemoInputGeomProvider geom, List<MeshData> meshData, float cellSize, int tileSize,
int vertsPerPoly)
{
NavMeshParams navMeshParams = new NavMeshParams();
navMeshParams.orig.x = geom.getMeshBoundsMin().x;
navMeshParams.orig.y = geom.getMeshBoundsMin().y;
navMeshParams.orig.z = geom.getMeshBoundsMin().z;
navMeshParams.orig.x = geom.GetMeshBoundsMin().x;
navMeshParams.orig.y = geom.GetMeshBoundsMin().y;
navMeshParams.orig.z = geom.GetMeshBoundsMin().z;
navMeshParams.tileWidth = tileSize * cellSize;
navMeshParams.tileHeight = tileSize * cellSize;
// snprintf(text, 64, "Tiles %d x %d", tw, th);
// Snprintf(text, 64, "Tiles %d x %d", tw, th);
navMeshParams.maxTiles = getMaxTiles(geom, cellSize, tileSize);
navMeshParams.maxPolys = getMaxPolysPerTile(geom, cellSize, tileSize);
navMeshParams.maxTiles = GetMaxTiles(geom, cellSize, tileSize);
navMeshParams.maxPolys = GetMaxPolysPerTile(geom, cellSize, tileSize);
NavMesh navMesh = new NavMesh(navMeshParams, vertsPerPoly);
meshData.forEach(md => navMesh.addTile(md, 0, 0));
meshData.ForEach(md => navMesh.AddTile(md, 0, 0));
return navMesh;
}
public int getMaxTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
public int GetMaxTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
{
int tileBits = getTileBits(geom, cellSize, tileSize);
int tileBits = GetTileBits(geom, cellSize, tileSize);
return 1 << tileBits;
}
public int getMaxPolysPerTile(DemoInputGeomProvider geom, float cellSize, int tileSize)
public int GetMaxPolysPerTile(DemoInputGeomProvider geom, float cellSize, int tileSize)
{
int polyBits = 22 - getTileBits(geom, cellSize, tileSize);
int polyBits = 22 - GetTileBits(geom, cellSize, tileSize);
return 1 << polyBits;
}
private int getTileBits(DemoInputGeomProvider geom, float cellSize, int tileSize)
private int GetTileBits(DemoInputGeomProvider geom, float cellSize, int tileSize)
{
int[] wh = Recast.calcGridSize(geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), cellSize);
int[] wh = Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize);
int tw = (wh[0] + tileSize - 1) / tileSize;
int th = (wh[1] + tileSize - 1) / tileSize;
int tileBits = Math.Min(ilog2(nextPow2(tw * th)), 14);
int tileBits = Math.Min(Ilog2(NextPow2(tw * th)), 14);
return tileBits;
}
public int[] getTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
{
int[] wh = Recast.calcGridSize(geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), cellSize);
int[] wh = Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize);
int tw = (wh[0] + tileSize - 1) / tileSize;
int th = (wh[1] + tileSize - 1) / tileSize;
return new int[] { tw, th };
}
private List<MeshData> buildMeshData(DemoInputGeomProvider m_geom, float m_cellSize, float m_cellHeight, float m_agentHeight,
private List<MeshData> BuildMeshData(DemoInputGeomProvider m_geom, float m_cellSize, float m_cellHeight, float m_agentHeight,
float m_agentRadius, float m_agentMaxClimb, List<RecastBuilderResult> rcResult)
{
// Add tiles to nav mesh
@ -121,14 +121,14 @@ public class TileNavMeshBuilder : AbstractNavMeshBuilder
{
int x = result.tileX;
int z = result.tileZ;
NavMeshDataCreateParams option = getNavMeshCreateParams(m_geom, m_cellSize, m_cellHeight, m_agentHeight,
NavMeshDataCreateParams option = GetNavMeshCreateParams(m_geom, m_cellSize, m_cellHeight, m_agentHeight,
m_agentRadius, m_agentMaxClimb, result);
option.tileX = x;
option.tileZ = z;
MeshData md = NavMeshBuilder.createNavMeshData(option);
MeshData md = NavMeshBuilder.CreateNavMeshData(option);
if (md != null)
{
meshData.Add(updateAreaAndFlags(md));
meshData.Add(UpdateAreaAndFlags(md));
}
}

View File

@ -48,24 +48,24 @@ public class DebugDraw
}
public void begin(DebugDrawPrimitives prim)
public void Begin(DebugDrawPrimitives prim)
{
begin(prim, 1f);
Begin(prim, 1f);
}
public void debugDrawCylinderWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col,
public void DebugDrawCylinderWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col,
float lineWidth)
{
begin(DebugDrawPrimitives.LINES, lineWidth);
appendCylinderWire(minx, miny, minz, maxx, maxy, maxz, col);
end();
Begin(DebugDrawPrimitives.LINES, lineWidth);
AppendCylinderWire(minx, miny, minz, maxx, maxy, maxz, col);
End();
}
private const int CYLINDER_NUM_SEG = 16;
private readonly float[] cylinderDir = new float[CYLINDER_NUM_SEG * 2];
private bool cylinderInit = false;
private void initCylinder()
private void InitCylinder()
{
if (!cylinderInit)
{
@ -79,9 +79,9 @@ public class DebugDraw
}
}
void appendCylinderWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col)
void AppendCylinderWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col)
{
initCylinder();
InitCylinder();
float cx = (maxx + minx) / 2;
float cz = (maxz + minz) / 2;
@ -90,61 +90,61 @@ public class DebugDraw
for (int i = 0, j = CYLINDER_NUM_SEG - 1; i < CYLINDER_NUM_SEG; j = i++)
{
vertex(cx + cylinderDir[j * 2 + 0] * rx, miny, cz + cylinderDir[j * 2 + 1] * rz, col);
vertex(cx + cylinderDir[i * 2 + 0] * rx, miny, cz + cylinderDir[i * 2 + 1] * rz, col);
vertex(cx + cylinderDir[j * 2 + 0] * rx, maxy, cz + cylinderDir[j * 2 + 1] * rz, col);
vertex(cx + cylinderDir[i * 2 + 0] * rx, maxy, cz + cylinderDir[i * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[j * 2 + 0] * rx, miny, cz + cylinderDir[j * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[i * 2 + 0] * rx, miny, cz + cylinderDir[i * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[j * 2 + 0] * rx, maxy, cz + cylinderDir[j * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[i * 2 + 0] * rx, maxy, cz + cylinderDir[i * 2 + 1] * rz, col);
}
for (int i = 0; i < CYLINDER_NUM_SEG; i += CYLINDER_NUM_SEG / 4)
{
vertex(cx + cylinderDir[i * 2 + 0] * rx, miny, cz + cylinderDir[i * 2 + 1] * rz, col);
vertex(cx + cylinderDir[i * 2 + 0] * rx, maxy, cz + cylinderDir[i * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[i * 2 + 0] * rx, miny, cz + cylinderDir[i * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[i * 2 + 0] * rx, maxy, cz + cylinderDir[i * 2 + 1] * rz, col);
}
}
public void debugDrawBoxWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col,
public void DebugDrawBoxWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col,
float lineWidth)
{
begin(DebugDrawPrimitives.LINES, lineWidth);
appendBoxWire(minx, miny, minz, maxx, maxy, maxz, col);
end();
Begin(DebugDrawPrimitives.LINES, lineWidth);
AppendBoxWire(minx, miny, minz, maxx, maxy, maxz, col);
End();
}
public void appendBoxWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col)
public void AppendBoxWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col)
{
// Top
vertex(minx, miny, minz, col);
vertex(maxx, miny, minz, col);
vertex(maxx, miny, minz, col);
vertex(maxx, miny, maxz, col);
vertex(maxx, miny, maxz, col);
vertex(minx, miny, maxz, col);
vertex(minx, miny, maxz, col);
vertex(minx, miny, minz, col);
Vertex(minx, miny, minz, col);
Vertex(maxx, miny, minz, col);
Vertex(maxx, miny, minz, col);
Vertex(maxx, miny, maxz, col);
Vertex(maxx, miny, maxz, col);
Vertex(minx, miny, maxz, col);
Vertex(minx, miny, maxz, col);
Vertex(minx, miny, minz, col);
// bottom
vertex(minx, maxy, minz, col);
vertex(maxx, maxy, minz, col);
vertex(maxx, maxy, minz, col);
vertex(maxx, maxy, maxz, col);
vertex(maxx, maxy, maxz, col);
vertex(minx, maxy, maxz, col);
vertex(minx, maxy, maxz, col);
vertex(minx, maxy, minz, col);
Vertex(minx, maxy, minz, col);
Vertex(maxx, maxy, minz, col);
Vertex(maxx, maxy, minz, col);
Vertex(maxx, maxy, maxz, col);
Vertex(maxx, maxy, maxz, col);
Vertex(minx, maxy, maxz, col);
Vertex(minx, maxy, maxz, col);
Vertex(minx, maxy, minz, col);
// Sides
vertex(minx, miny, minz, col);
vertex(minx, maxy, minz, col);
vertex(maxx, miny, minz, col);
vertex(maxx, maxy, minz, col);
vertex(maxx, miny, maxz, col);
vertex(maxx, maxy, maxz, col);
vertex(minx, miny, maxz, col);
vertex(minx, maxy, maxz, col);
Vertex(minx, miny, minz, col);
Vertex(minx, maxy, minz, col);
Vertex(maxx, miny, minz, col);
Vertex(maxx, maxy, minz, col);
Vertex(maxx, miny, maxz, col);
Vertex(maxx, maxy, maxz, col);
Vertex(minx, miny, maxz, col);
Vertex(minx, maxy, maxz, col);
}
public void appendBox(float minx, float miny, float minz, float maxx, float maxy, float maxz, int[] fcol)
public void AppendBox(float minx, float miny, float minz, float maxx, float maxy, float maxz, int[] fcol)
{
float[][] verts =
{
@ -161,66 +161,66 @@ public class DebugDraw
int idx = 0;
for (int i = 0; i < 6; ++i)
{
vertex(verts[boxIndices[idx]], fcol[i]);
Vertex(verts[boxIndices[idx]], fcol[i]);
idx++;
vertex(verts[boxIndices[idx]], fcol[i]);
Vertex(verts[boxIndices[idx]], fcol[i]);
idx++;
vertex(verts[boxIndices[idx]], fcol[i]);
Vertex(verts[boxIndices[idx]], fcol[i]);
idx++;
vertex(verts[boxIndices[idx]], fcol[i]);
Vertex(verts[boxIndices[idx]], fcol[i]);
idx++;
}
}
public void debugDrawArc(float x0, float y0, float z0, float x1, float y1, float z1, float h, float as0, float as1, int col,
public void DebugDrawArc(float x0, float y0, float z0, float x1, float y1, float z1, float h, float as0, float as1, int col,
float lineWidth)
{
begin(DebugDrawPrimitives.LINES, lineWidth);
appendArc(x0, y0, z0, x1, y1, z1, h, as0, as1, col);
end();
Begin(DebugDrawPrimitives.LINES, lineWidth);
AppendArc(x0, y0, z0, x1, y1, z1, h, as0, as1, col);
End();
}
public void begin(DebugDrawPrimitives prim, float size)
public void Begin(DebugDrawPrimitives prim, float size)
{
getOpenGlDraw().begin(prim, size);
GetOpenGlDraw().Begin(prim, size);
}
public void vertex(float[] pos, int color)
public void Vertex(float[] pos, int color)
{
getOpenGlDraw().vertex(pos, color);
GetOpenGlDraw().Vertex(pos, color);
}
public void vertex(Vector3f pos, int color)
public void Vertex(Vector3f pos, int color)
{
getOpenGlDraw().vertex(pos, color);
GetOpenGlDraw().Vertex(pos, color);
}
public void vertex(float x, float y, float z, int color)
public void Vertex(float x, float y, float z, int color)
{
getOpenGlDraw().vertex(x, y, z, color);
GetOpenGlDraw().Vertex(x, y, z, color);
}
public void vertex(Vector3f pos, int color, Vector2f uv)
public void Vertex(Vector3f pos, int color, Vector2f uv)
{
getOpenGlDraw().vertex(pos, color, uv);
GetOpenGlDraw().Vertex(pos, color, uv);
}
public void vertex(float x, float y, float z, int color, float u, float v)
public void Vertex(float x, float y, float z, int color, float u, float v)
{
getOpenGlDraw().vertex(x, y, z, color, u, v);
GetOpenGlDraw().Vertex(x, y, z, color, u, v);
}
public void end()
public void End()
{
getOpenGlDraw().end();
GetOpenGlDraw().End();
}
public void debugDrawCircle(float x, float y, float z, float r, int col, float lineWidth)
public void DebugDrawCircle(float x, float y, float z, float r, int col, float lineWidth)
{
begin(DebugDrawPrimitives.LINES, lineWidth);
appendCircle(x, y, z, r, col);
end();
Begin(DebugDrawPrimitives.LINES, lineWidth);
AppendCircle(x, y, z, r, col);
End();
}
private bool circleInit = false;
@ -229,7 +229,7 @@ public class DebugDraw
private float[] _viewMatrix = new float[16];
private readonly float[] _projectionMatrix = new float[16];
public void appendCircle(float x, float y, float z, float r, int col)
public void AppendCircle(float x, float y, float z, float r, int col)
{
if (!circleInit)
{
@ -244,8 +244,8 @@ public class DebugDraw
for (int i = 0, j = CIRCLE_NUM_SEG - 1; i < CIRCLE_NUM_SEG; j = i++)
{
vertex(x + circeDir[j * 2 + 0] * r, y, z + circeDir[j * 2 + 1] * r, col);
vertex(x + circeDir[i * 2 + 0] * r, y, z + circeDir[i * 2 + 1] * r, col);
Vertex(x + circeDir[j * 2 + 0] * r, y, z + circeDir[j * 2 + 1] * r, col);
Vertex(x + circeDir[i * 2 + 0] * r, y, z + circeDir[i * 2 + 1] * r, col);
}
}
@ -253,21 +253,21 @@ public class DebugDraw
private static readonly float PAD = 0.05f;
private static readonly float ARC_PTS_SCALE = (1.0f - PAD * 2) / NUM_ARC_PTS;
public void appendArc(float x0, float y0, float z0, float x1, float y1, float z1, float h, float as0, float as1, int col)
public void AppendArc(float x0, float y0, float z0, float x1, float y1, float z1, float h, float as0, float as1, int col)
{
float dx = x1 - x0;
float dy = y1 - y0;
float dz = z1 - z0;
float len = (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
Vector3f prev = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, PAD, ref prev);
EvalArc(x0, y0, z0, dx, dy, dz, len * h, PAD, ref prev);
for (int i = 1; i <= NUM_ARC_PTS; ++i)
{
float u = PAD + i * ARC_PTS_SCALE;
Vector3f pt = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, u, ref pt);
vertex(prev.x, prev.y, prev.z, col);
vertex(pt.x, pt.y, pt.z, col);
EvalArc(x0, y0, z0, dx, dy, dz, len * h, u, ref pt);
Vertex(prev.x, prev.y, prev.z, col);
Vertex(pt.x, pt.y, pt.z, col);
prev.x = pt.x;
prev.y = pt.y;
prev.z = pt.z;
@ -278,64 +278,64 @@ public class DebugDraw
{
Vector3f p = new Vector3f();
Vector3f q = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, PAD, ref p);
evalArc(x0, y0, z0, dx, dy, dz, len * h, PAD + 0.05f, ref q);
appendArrowHead(p, q, as0, col);
EvalArc(x0, y0, z0, dx, dy, dz, len * h, PAD, ref p);
EvalArc(x0, y0, z0, dx, dy, dz, len * h, PAD + 0.05f, ref q);
AppendArrowHead(p, q, as0, col);
}
if (as1 > 0.001f)
{
Vector3f p = new Vector3f();
Vector3f q = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, 1 - PAD, ref p);
evalArc(x0, y0, z0, dx, dy, dz, len * h, 1 - (PAD + 0.05f), ref q);
appendArrowHead(p, q, as1, col);
EvalArc(x0, y0, z0, dx, dy, dz, len * h, 1 - PAD, ref p);
EvalArc(x0, y0, z0, dx, dy, dz, len * h, 1 - (PAD + 0.05f), ref q);
AppendArrowHead(p, q, as1, col);
}
}
private void evalArc(float x0, float y0, float z0, float dx, float dy, float dz, float h, float u, ref Vector3f res)
private void EvalArc(float x0, float y0, float z0, float dx, float dy, float dz, float h, float u, ref Vector3f res)
{
res.x = x0 + dx * u;
res.y = y0 + dy * u + h * (1 - (u * 2 - 1) * (u * 2 - 1));
res.z = z0 + dz * u;
}
public void debugDrawCross(float x, float y, float z, float size, int col, float lineWidth)
public void DebugDrawCross(float x, float y, float z, float size, int col, float lineWidth)
{
begin(DebugDrawPrimitives.LINES, lineWidth);
appendCross(x, y, z, size, col);
end();
Begin(DebugDrawPrimitives.LINES, lineWidth);
AppendCross(x, y, z, size, col);
End();
}
private void appendCross(float x, float y, float z, float s, int col)
private void AppendCross(float x, float y, float z, float s, int col)
{
vertex(x - s, y, z, col);
vertex(x + s, y, z, col);
vertex(x, y - s, z, col);
vertex(x, y + s, z, col);
vertex(x, y, z - s, col);
vertex(x, y, z + s, col);
Vertex(x - s, y, z, col);
Vertex(x + s, y, z, col);
Vertex(x, y - s, z, col);
Vertex(x, y + s, z, col);
Vertex(x, y, z - s, col);
Vertex(x, y, z + s, col);
}
public void debugDrawBox(float minx, float miny, float minz, float maxx, float maxy, float maxz, int[] fcol)
public void DebugDrawBox(float minx, float miny, float minz, float maxx, float maxy, float maxz, int[] fcol)
{
begin(DebugDrawPrimitives.QUADS);
appendBox(minx, miny, minz, maxx, maxy, maxz, fcol);
end();
Begin(DebugDrawPrimitives.QUADS);
AppendBox(minx, miny, minz, maxx, maxy, maxz, fcol);
End();
}
public void debugDrawCylinder(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col)
public void DebugDrawCylinder(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col)
{
begin(DebugDrawPrimitives.TRIS);
appendCylinder(minx, miny, minz, maxx, maxy, maxz, col);
end();
Begin(DebugDrawPrimitives.TRIS);
AppendCylinder(minx, miny, minz, maxx, maxy, maxz, col);
End();
}
public void appendCylinder(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col)
public void AppendCylinder(float minx, float miny, float minz, float maxx, float maxy, float maxz, int col)
{
initCylinder();
InitCylinder();
int col2 = duMultCol(col, 160);
int col2 = DuMultCol(col, 160);
float cx = (maxx + minx) / 2;
float cz = (maxz + minz) / 2;
@ -345,57 +345,57 @@ public class DebugDraw
for (int i = 2; i < CYLINDER_NUM_SEG; ++i)
{
int a = 0, b = i - 1, c = i;
vertex(cx + cylinderDir[a * 2 + 0] * rx, miny, cz + cylinderDir[a * 2 + 1] * rz, col2);
vertex(cx + cylinderDir[b * 2 + 0] * rx, miny, cz + cylinderDir[b * 2 + 1] * rz, col2);
vertex(cx + cylinderDir[c * 2 + 0] * rx, miny, cz + cylinderDir[c * 2 + 1] * rz, col2);
Vertex(cx + cylinderDir[a * 2 + 0] * rx, miny, cz + cylinderDir[a * 2 + 1] * rz, col2);
Vertex(cx + cylinderDir[b * 2 + 0] * rx, miny, cz + cylinderDir[b * 2 + 1] * rz, col2);
Vertex(cx + cylinderDir[c * 2 + 0] * rx, miny, cz + cylinderDir[c * 2 + 1] * rz, col2);
}
for (int i = 2; i < CYLINDER_NUM_SEG; ++i)
{
int a = 0, b = i, c = i - 1;
vertex(cx + cylinderDir[a * 2 + 0] * rx, maxy, cz + cylinderDir[a * 2 + 1] * rz, col);
vertex(cx + cylinderDir[b * 2 + 0] * rx, maxy, cz + cylinderDir[b * 2 + 1] * rz, col);
vertex(cx + cylinderDir[c * 2 + 0] * rx, maxy, cz + cylinderDir[c * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[a * 2 + 0] * rx, maxy, cz + cylinderDir[a * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[b * 2 + 0] * rx, maxy, cz + cylinderDir[b * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[c * 2 + 0] * rx, maxy, cz + cylinderDir[c * 2 + 1] * rz, col);
}
for (int i = 0, j = CYLINDER_NUM_SEG - 1; i < CYLINDER_NUM_SEG; j = i++)
{
vertex(cx + cylinderDir[i * 2 + 0] * rx, miny, cz + cylinderDir[i * 2 + 1] * rz, col2);
vertex(cx + cylinderDir[j * 2 + 0] * rx, miny, cz + cylinderDir[j * 2 + 1] * rz, col2);
vertex(cx + cylinderDir[j * 2 + 0] * rx, maxy, cz + cylinderDir[j * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[i * 2 + 0] * rx, miny, cz + cylinderDir[i * 2 + 1] * rz, col2);
Vertex(cx + cylinderDir[j * 2 + 0] * rx, miny, cz + cylinderDir[j * 2 + 1] * rz, col2);
Vertex(cx + cylinderDir[j * 2 + 0] * rx, maxy, cz + cylinderDir[j * 2 + 1] * rz, col);
vertex(cx + cylinderDir[i * 2 + 0] * rx, miny, cz + cylinderDir[i * 2 + 1] * rz, col2);
vertex(cx + cylinderDir[j * 2 + 0] * rx, maxy, cz + cylinderDir[j * 2 + 1] * rz, col);
vertex(cx + cylinderDir[i * 2 + 0] * rx, maxy, cz + cylinderDir[i * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[i * 2 + 0] * rx, miny, cz + cylinderDir[i * 2 + 1] * rz, col2);
Vertex(cx + cylinderDir[j * 2 + 0] * rx, maxy, cz + cylinderDir[j * 2 + 1] * rz, col);
Vertex(cx + cylinderDir[i * 2 + 0] * rx, maxy, cz + cylinderDir[i * 2 + 1] * rz, col);
}
}
public void debugDrawArrow(float x0, float y0, float z0, float x1, float y1, float z1, float as0, float as1, int col,
public void DebugDrawArrow(float x0, float y0, float z0, float x1, float y1, float z1, float as0, float as1, int col,
float lineWidth)
{
begin(DebugDrawPrimitives.LINES, lineWidth);
appendArrow(x0, y0, z0, x1, y1, z1, as0, as1, col);
end();
Begin(DebugDrawPrimitives.LINES, lineWidth);
AppendArrow(x0, y0, z0, x1, y1, z1, as0, as1, col);
End();
}
public void appendArrow(float x0, float y0, float z0, float x1, float y1, float z1, float as0, float as1, int col)
public void AppendArrow(float x0, float y0, float z0, float x1, float y1, float z1, float as0, float as1, int col)
{
vertex(x0, y0, z0, col);
vertex(x1, y1, z1, col);
Vertex(x0, y0, z0, col);
Vertex(x1, y1, z1, col);
// End arrows
Vector3f p = Vector3f.Of(x0, y0, z0);
Vector3f q = Vector3f.Of(x1, y1, z1);
if (as0 > 0.001f)
appendArrowHead(p, q, as0, col);
AppendArrowHead(p, q, as0, col);
if (as1 > 0.001f)
appendArrowHead(q, p, as1, col);
AppendArrowHead(q, p, as1, col);
}
void appendArrowHead(Vector3f p, Vector3f q, float s, int col)
void AppendArrowHead(Vector3f p, Vector3f q, float s, int col)
{
float eps = 0.001f;
if (vdistSqr(p, q) < eps * eps)
if (VdistSqr(p, q) < eps * eps)
{
return;
}
@ -403,29 +403,29 @@ public class DebugDraw
Vector3f ax = new Vector3f();
Vector3f ay = Vector3f.Of(0, 1, 0);
Vector3f az = new Vector3f();
vsub(ref az, q, p);
vnormalize(ref az);
vcross(ref ax, ay, az);
vcross(ref ay, az, ax);
vnormalize(ref ay);
Vsub(ref az, q, p);
Vnormalize(ref az);
Vcross(ref ax, ay, az);
Vcross(ref ay, az, ax);
Vnormalize(ref ay);
vertex(p, col);
// vertex(p.x+az.x*s+ay.x*s/2, p.y+az.y*s+ay.y*s/2, p.z+az.z*s+ay.z*s/2, col);
vertex(p.x + az.x * s + ax.x * s / 3, p.y + az.y * s + ax.y * s / 3, p.z + az.z * s + ax.z * s / 3, col);
Vertex(p, col);
// Vertex(p.x+az.x*s+ay.x*s/2, p.y+az.y*s+ay.y*s/2, p.z+az.z*s+ay.z*s/2, col);
Vertex(p.x + az.x * s + ax.x * s / 3, p.y + az.y * s + ax.y * s / 3, p.z + az.z * s + ax.z * s / 3, col);
vertex(p, col);
// vertex(p.x+az.x*s-ay.x*s/2, p.y+az.y*s-ay.y*s/2, p.z+az.z*s-ay.z*s/2, col);
vertex(p.x + az.x * s - ax.x * s / 3, p.y + az.y * s - ax.y * s / 3, p.z + az.z * s - ax.z * s / 3, col);
Vertex(p, col);
// Vertex(p.x+az.x*s-ay.x*s/2, p.y+az.y*s-ay.y*s/2, p.z+az.z*s-ay.z*s/2, col);
Vertex(p.x + az.x * s - ax.x * s / 3, p.y + az.y * s - ax.y * s / 3, p.z + az.z * s - ax.z * s / 3, col);
}
public void vcross(ref Vector3f dest, Vector3f v1, Vector3f v2)
public void Vcross(ref Vector3f dest, Vector3f v1, Vector3f v2)
{
dest.x = v1.y * v2.z - v1.z * v2.y;
dest.y = v1.z * v2.x - v1.x * v2.z;
dest.z = v1.x * v2.y - v1.y * v2.x;
}
public void vnormalize(ref Vector3f v)
public void Vnormalize(ref Vector3f v)
{
float d = (float)(1.0f / Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z));
v.x *= d;
@ -433,14 +433,14 @@ public class DebugDraw
v.z *= d;
}
public void vsub(ref Vector3f dest, Vector3f v1, Vector3f v2)
public void Vsub(ref Vector3f dest, Vector3f v1, Vector3f v2)
{
dest.x = v1.x - v2.x;
dest.y = v1.y - v2.y;
dest.z = v1.z - v2.z;
}
public float vdistSqr(Vector3f v1, Vector3f v2)
public float VdistSqr(Vector3f v1, Vector3f v2)
{
float x = v1.x - v2.x;
float y = v1.y - v2.y;
@ -448,49 +448,49 @@ public class DebugDraw
return x * x + y * y + z * z;
}
// public static int areaToCol(int area) {
// public static int AreaToCol(int area) {
// if (area == 0) {
// return duRGBA(0, 192, 255, 255);
// return DuRGBA(0, 192, 255, 255);
// } else {
// return duIntToCol(area, 255);
// return DuIntToCol(area, 255);
// }
// }
public static int areaToCol(int area)
public static int AreaToCol(int area)
{
switch (area)
{
// Ground (0) : light blue
case SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WALKABLE:
case SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND:
return duRGBA(0, 192, 255, 255);
return DuRGBA(0, 192, 255, 255);
// Water : blue
case SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER:
return duRGBA(0, 0, 255, 255);
return DuRGBA(0, 0, 255, 255);
// Road : brown
case SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD:
return duRGBA(50, 20, 12, 255);
return DuRGBA(50, 20, 12, 255);
// Door : cyan
case SampleAreaModifications.SAMPLE_POLYAREA_TYPE_DOOR:
return duRGBA(0, 255, 255, 255);
return DuRGBA(0, 255, 255, 255);
// Grass : green
case SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS:
return duRGBA(0, 255, 0, 255);
return DuRGBA(0, 255, 0, 255);
// Jump : yellow
case SampleAreaModifications.SAMPLE_POLYAREA_TYPE_JUMP:
return duRGBA(255, 255, 0, 255);
return DuRGBA(255, 255, 0, 255);
// Unexpected : red
default:
return duRGBA(255, 0, 0, 255);
return DuRGBA(255, 0, 0, 255);
}
}
public static int duRGBA(int r, int g, int b, int a)
public static int DuRGBA(int r, int g, int b, int a)
{
return (r) | (g << 8) | (b << 16) | (a << 24);
}
public static int duLerpCol(int ca, int cb, int u)
public static int DuLerpCol(int ca, int cb, int u)
{
int ra = ca & 0xff;
int ga = (ca >> 8) & 0xff;
@ -505,134 +505,134 @@ public class DebugDraw
int g = (ga * (255 - u) + gb * u) / 255;
int b = (ba * (255 - u) + bb * u) / 255;
int a = (aa * (255 - u) + ab * u) / 255;
return duRGBA(r, g, b, a);
return DuRGBA(r, g, b, a);
}
public static int bit(int a, int b)
public static int Bit(int a, int b)
{
return (a & (1 << b)) >>> b;
}
public static int duIntToCol(int i, int a)
public static int DuIntToCol(int i, int a)
{
int r = bit(i, 1) + bit(i, 3) * 2 + 1;
int g = bit(i, 2) + bit(i, 4) * 2 + 1;
int b = bit(i, 0) + bit(i, 5) * 2 + 1;
return duRGBA(r * 63, g * 63, b * 63, a);
int r = Bit(i, 1) + Bit(i, 3) * 2 + 1;
int g = Bit(i, 2) + Bit(i, 4) * 2 + 1;
int b = Bit(i, 0) + Bit(i, 5) * 2 + 1;
return DuRGBA(r * 63, g * 63, b * 63, a);
}
public static void duCalcBoxColors(int[] colors, int colTop, int colSide)
public static void DuCalcBoxColors(int[] colors, int colTop, int colSide)
{
colors[0] = duMultCol(colTop, 250);
colors[1] = duMultCol(colSide, 140);
colors[2] = duMultCol(colSide, 165);
colors[3] = duMultCol(colSide, 165);
colors[4] = duMultCol(colSide, 217);
colors[5] = duMultCol(colSide, 217);
colors[0] = DuMultCol(colTop, 250);
colors[1] = DuMultCol(colSide, 140);
colors[2] = DuMultCol(colSide, 165);
colors[3] = DuMultCol(colSide, 165);
colors[4] = DuMultCol(colSide, 217);
colors[5] = DuMultCol(colSide, 217);
}
public static int duMultCol(int col, int d)
public static int DuMultCol(int col, int d)
{
int r = col & 0xff;
int g = (col >> 8) & 0xff;
int b = (col >> 16) & 0xff;
int a = (col >> 24) & 0xff;
return duRGBA((r * d) >> 8, (g * d) >> 8, (b * d) >> 8, a);
return DuRGBA((r * d) >> 8, (g * d) >> 8, (b * d) >> 8, a);
}
public static int duTransCol(int c, int a)
public static int DuTransCol(int c, int a)
{
return (a << 24) | (c & 0x00ffffff);
}
public static int duDarkenCol(int col)
public static int DuDarkenCol(int col)
{
return (int)(((col >> 1) & 0x007f7f7f) | (col & 0xff000000));
}
public void fog(float start, float end)
public void Fog(float start, float end)
{
getOpenGlDraw().fog(start, end);
GetOpenGlDraw().Fog(start, end);
}
public void fog(bool state)
public void Fog(bool state)
{
getOpenGlDraw().fog(state);
GetOpenGlDraw().Fog(state);
}
public void depthMask(bool state)
public void DepthMask(bool state)
{
getOpenGlDraw().depthMask(state);
GetOpenGlDraw().DepthMask(state);
}
public void texture(bool state)
public void Texture(bool state)
{
getOpenGlDraw().texture(g_tex, state);
GetOpenGlDraw().Texture(g_tex, state);
}
public void init(float fogDistance)
public void Init(float fogDistance)
{
getOpenGlDraw().init();
GetOpenGlDraw().Init();
}
public void clear()
public void Clear()
{
getOpenGlDraw().clear();
GetOpenGlDraw().Clear();
}
public float[] projectionMatrix(float fovy, float aspect, float near, float far)
public float[] ProjectionMatrix(float fovy, float aspect, float near, float far)
{
GLU.glhPerspectivef2(_projectionMatrix, fovy, aspect, near, far);
getOpenGlDraw().projectionMatrix(_projectionMatrix);
updateFrustum();
GLU.GlhPerspectivef2(_projectionMatrix, fovy, aspect, near, far);
GetOpenGlDraw().ProjectionMatrix(_projectionMatrix);
UpdateFrustum();
return _projectionMatrix;
}
public float[] viewMatrix(Vector3f cameraPos, float[] cameraEulers)
public float[] ViewMatrix(Vector3f cameraPos, float[] cameraEulers)
{
float[] rx = GLU.build_4x4_rotation_matrix(cameraEulers[0], 1, 0, 0);
float[] ry = GLU.build_4x4_rotation_matrix(cameraEulers[1], 0, 1, 0);
float[] r = GLU.mul(rx, ry);
float[] rx = GLU.Build_4x4_rotation_matrix(cameraEulers[0], 1, 0, 0);
float[] ry = GLU.Build_4x4_rotation_matrix(cameraEulers[1], 0, 1, 0);
float[] r = GLU.Mul(rx, ry);
float[] t = new float[16];
t[0] = t[5] = t[10] = t[15] = 1;
t[12] = -cameraPos.x;
t[13] = -cameraPos.y;
t[14] = -cameraPos.z;
_viewMatrix = GLU.mul(r, t);
getOpenGlDraw().viewMatrix(_viewMatrix);
updateFrustum();
_viewMatrix = GLU.Mul(r, t);
GetOpenGlDraw().ViewMatrix(_viewMatrix);
UpdateFrustum();
return _viewMatrix;
}
private OpenGLDraw getOpenGlDraw()
private OpenGLDraw GetOpenGlDraw()
{
return openGlDraw;
}
private void updateFrustum()
private void UpdateFrustum()
{
float[] vpm = GLU.mul(_projectionMatrix, _viewMatrix);
float[] vpm = GLU.Mul(_projectionMatrix, _viewMatrix);
// left
frustumPlanes[0] = normalizePlane(vpm[0 + 3] + vpm[0 + 0], vpm[4 + 3] + vpm[4 + 0], vpm[8 + 3] + vpm[8 + 0],
frustumPlanes[0] = NormalizePlane(vpm[0 + 3] + vpm[0 + 0], vpm[4 + 3] + vpm[4 + 0], vpm[8 + 3] + vpm[8 + 0],
vpm[12 + 3] + vpm[12 + 0]);
// right
frustumPlanes[1] = normalizePlane(vpm[0 + 3] - vpm[0 + 0], vpm[4 + 3] - vpm[4 + 0], vpm[8 + 3] - vpm[8 + 0],
frustumPlanes[1] = NormalizePlane(vpm[0 + 3] - vpm[0 + 0], vpm[4 + 3] - vpm[4 + 0], vpm[8 + 3] - vpm[8 + 0],
vpm[12 + 3] - vpm[12 + 0]);
// top
frustumPlanes[2] = normalizePlane(vpm[0 + 3] - vpm[0 + 1], vpm[4 + 3] - vpm[4 + 1], vpm[8 + 3] - vpm[8 + 1],
frustumPlanes[2] = NormalizePlane(vpm[0 + 3] - vpm[0 + 1], vpm[4 + 3] - vpm[4 + 1], vpm[8 + 3] - vpm[8 + 1],
vpm[12 + 3] - vpm[12 + 1]);
// bottom
frustumPlanes[3] = normalizePlane(vpm[0 + 3] + vpm[0 + 1], vpm[4 + 3] + vpm[4 + 1], vpm[8 + 3] + vpm[8 + 1],
frustumPlanes[3] = NormalizePlane(vpm[0 + 3] + vpm[0 + 1], vpm[4 + 3] + vpm[4 + 1], vpm[8 + 3] + vpm[8 + 1],
vpm[12 + 3] + vpm[12 + 1]);
// near
frustumPlanes[4] = normalizePlane(vpm[0 + 3] + vpm[0 + 2], vpm[4 + 3] + vpm[4 + 2], vpm[8 + 3] + vpm[8 + 2],
frustumPlanes[4] = NormalizePlane(vpm[0 + 3] + vpm[0 + 2], vpm[4 + 3] + vpm[4 + 2], vpm[8 + 3] + vpm[8 + 2],
vpm[12 + 3] + vpm[12 + 2]);
// far
frustumPlanes[5] = normalizePlane(vpm[0 + 3] - vpm[0 + 2], vpm[4 + 3] - vpm[4 + 2], vpm[8 + 3] - vpm[8 + 2],
frustumPlanes[5] = NormalizePlane(vpm[0 + 3] - vpm[0 + 2], vpm[4 + 3] - vpm[4 + 2], vpm[8 + 3] - vpm[8 + 2],
vpm[12 + 3] - vpm[12 + 2]);
}
private float[] normalizePlane(float px, float py, float pz, float pw)
private float[] NormalizePlane(float px, float py, float pz, float pw)
{
float length = (float)Math.Sqrt(px * px + py * py + pz * pz);
if (length != 0)
@ -647,7 +647,7 @@ public class DebugDraw
return new float[] { px, py, pz, pw };
}
public bool frustumTest(float[] bounds)
public bool FrustumTest(float[] bounds)
{
foreach (float[] plane in frustumPlanes)
{
@ -699,8 +699,8 @@ public class DebugDraw
return true;
}
public bool frustumTest(Vector3f bmin, Vector3f bmax)
public bool FrustumTest(Vector3f bmin, Vector3f bmax)
{
return frustumTest(new float[] { bmin.x, bmin.y, bmin.z, bmax.x, bmax.y, bmax.z });
return FrustumTest(new float[] { bmin.x, bmin.y, bmin.z, bmax.x, bmax.y, bmax.z });
}
}

View File

@ -32,7 +32,7 @@ public class GLCheckerTexture
_gl = gl;
}
public void release()
public void Release()
{
if (m_texId != 0)
{
@ -40,13 +40,13 @@ public class GLCheckerTexture
}
}
public void bind()
public void Bind()
{
if (m_texId == 0)
{
// Create checker pattern.
int col0 = DebugDraw.duRGBA(215, 215, 215, 255);
int col1 = DebugDraw.duRGBA(255, 255, 255, 255);
int col0 = DebugDraw.DuRGBA(215, 215, 215, 255);
int col1 = DebugDraw.DuRGBA(255, 255, 255, 255);
uint TSIZE = 64;
int[] data = new int[TSIZE * TSIZE];

View File

@ -24,24 +24,24 @@ namespace DotRecast.Recast.Demo.Draw;
public class GLU
{
public static float[] gluPerspective(float fovy, float aspect, float near, float far)
public static float[] GluPerspective(float fovy, float aspect, float near, float far)
{
float[] projectionMatrix = new float[16];
glhPerspectivef2(projectionMatrix, fovy, aspect, near, far);
//glLoadMatrixf(projectionMatrix);
GlhPerspectivef2(projectionMatrix, fovy, aspect, near, far);
//GlLoadMatrixf(projectionMatrix);
return projectionMatrix;
}
public static void glhPerspectivef2(float[] matrix, float fovyInDegrees, float aspectRatio, float znear,
public static void GlhPerspectivef2(float[] matrix, float fovyInDegrees, float aspectRatio, float znear,
float zfar)
{
float ymax, xmax;
ymax = (float)(znear * Math.Tan(fovyInDegrees * Math.PI / 360.0));
xmax = ymax * aspectRatio;
glhFrustumf2(matrix, -xmax, xmax, -ymax, ymax, znear, zfar);
GlhFrustumf2(matrix, -xmax, xmax, -ymax, ymax, znear, zfar);
}
private static void glhFrustumf2(float[] matrix, float left, float right, float bottom, float top, float znear,
private static void GlhFrustumf2(float[] matrix, float left, float right, float bottom, float top, float znear,
float zfar)
{
float temp, temp2, temp3, temp4;
@ -67,7 +67,7 @@ public class GLU
matrix[15] = 0.0f;
}
public static int glhUnProjectf(float winx, float winy, float winz, float[] modelview, float[] projection, int[] viewport, ref Vector3f objectCoordinate)
public static int GlhUnProjectf(float winx, float winy, float winz, float[] modelview, float[] projection, int[] viewport, ref Vector3f objectCoordinate)
{
// Transformation matrices
float[] m = new float[16], A = new float[16];
@ -76,7 +76,7 @@ public class GLU
// and store in A[16]
MultiplyMatrices4by4OpenGL_FLOAT(A, projection, modelview);
// Now compute the inverse of matrix A
if (glhInvertMatrixf2(A, m) == 0)
if (GlhInvertMatrixf2(A, m) == 0)
return 0;
// Transformation of normalized coordinates between -1 and 1
@in[0] = (winx - viewport[0]) / viewport[2] * 2.0f - 1.0f;
@ -126,7 +126,7 @@ public class GLU
}
// This code comes directly from GLU except that it is for float
static int glhInvertMatrixf2(float[] m, float[] @out)
static int GlhInvertMatrixf2(float[] m, float[] @out)
{
float[][] wtmp = ArrayUtils.Of<float>(4, 8);
float m0, m1, m2, m3, s;
@ -370,7 +370,7 @@ public class GLU
m[(c) * 4 + (r)] = v;
}
public static float[] build_4x4_rotation_matrix(float a, float x, float y, float z)
public static float[] Build_4x4_rotation_matrix(float a, float x, float y, float z)
{
float[] matrix = new float[16];
a = (float)(a * Math.PI / 180.0); // convert to radians
@ -408,7 +408,7 @@ public class GLU
return matrix;
}
public static float[] mul(float[] left, float[] right)
public static float[] Mul(float[] left, float[] right)
{
float m00 = left[0] * right[0] + left[4] * right[1] + left[8] * right[2] + left[12] * right[3];
float m01 = left[1] * right[0] + left[5] * right[1] + left[9] * right[2] + left[13] * right[3];

View File

@ -35,7 +35,7 @@ public class ModernOpenGLDraw : OpenGLDraw
_gl = gl;
}
public unsafe void init()
public unsafe void Init()
{
string SHADER_VERSION = "#version 400\n";
string vertex_shader = SHADER_VERSION + "uniform mat4 ProjMtx;\n" //
@ -153,7 +153,7 @@ public class ModernOpenGLDraw : OpenGLDraw
_gl.BindBuffer(GLEnum.ElementArrayBuffer, 0);
}
public void clear()
public void Clear()
{
_gl.ClearColor(0.3f, 0.3f, 0.32f, 1.0f);
_gl.Clear((uint)GLEnum.ColorBufferBit | (uint)GLEnum.DepthBufferBit);
@ -164,7 +164,7 @@ public class ModernOpenGLDraw : OpenGLDraw
_gl.Enable(GLEnum.CullFace);
}
public void begin(DebugDrawPrimitives prim, float size)
public void Begin(DebugDrawPrimitives prim, float size)
{
currentPrim = prim;
vertices.Clear();
@ -172,7 +172,7 @@ public class ModernOpenGLDraw : OpenGLDraw
_gl.PointSize(size);
}
public unsafe void end()
public unsafe void End()
{
if (0 >= vertices.Count)
{
@ -189,8 +189,8 @@ public class ModernOpenGLDraw : OpenGLDraw
_gl.BindVertexArray(vao);
_gl.BindBuffer(GLEnum.ArrayBuffer, vbo);
_gl.BindBuffer(GLEnum.ElementArrayBuffer, ebo);
// glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_BUFFER, GL_STREAM_DRAW);
// glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_BUFFER, GL_STREAM_DRAW);
// GlBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_BUFFER, GL_STREAM_DRAW);
// GlBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_BUFFER, GL_STREAM_DRAW);
uint vboSize = (uint)vertices.Count * 24;
uint eboSize = currentPrim == DebugDrawPrimitives.QUADS ? (uint)vertices.Count * 6 : (uint)vertices.Count * 4;
@ -203,7 +203,7 @@ public class ModernOpenGLDraw : OpenGLDraw
byte* pVerts = (byte*)_gl.MapBuffer(GLEnum.ArrayBuffer, GLEnum.WriteOnly);
byte* pElems = (byte*)_gl.MapBuffer(GLEnum.ElementArrayBuffer, GLEnum.WriteOnly);
//vertices.forEach(v => v.store(verts));
//vertices.ForEach(v => v.Store(verts));
fixed (void* v = vertices.AsArray())
{
System.Buffer.MemoryCopy(v, pVerts, vboSize, vboSize);
@ -241,7 +241,7 @@ public class ModernOpenGLDraw : OpenGLDraw
}
if (_texture != null)
{
_texture.bind();
_texture.Bind();
_gl.Uniform1(uniformUseTexture, 1.0f);
}
else
@ -276,63 +276,63 @@ public class ModernOpenGLDraw : OpenGLDraw
_gl.PointSize(1.0f);
}
public void vertex(float x, float y, float z, int color)
public void Vertex(float x, float y, float z, int color)
{
vertices.Add(new OpenGLVertex(x, y, z, color));
}
public void vertex(float[] pos, int color)
public void Vertex(float[] pos, int color)
{
vertices.Add(new OpenGLVertex(pos, color));
}
public void vertex(Vector3f pos, int color)
public void Vertex(Vector3f pos, int color)
{
vertices.Add(new OpenGLVertex(pos, color));
}
public void vertex(Vector3f pos, int color, Vector2f uv)
public void Vertex(Vector3f pos, int color, Vector2f uv)
{
vertices.Add(new OpenGLVertex(pos, uv, color));
}
public void vertex(float x, float y, float z, int color, float u, float v)
public void Vertex(float x, float y, float z, int color, float u, float v)
{
vertices.Add(new OpenGLVertex(x, y, z, u, v, color));
}
public void depthMask(bool state)
public void DepthMask(bool state)
{
_gl.DepthMask(state);
}
public void texture(GLCheckerTexture g_tex, bool state)
public void Texture(GLCheckerTexture g_tex, bool state)
{
_texture = state ? g_tex : null;
if (_texture != null)
{
_texture.bind();
_texture.Bind();
}
}
public void projectionMatrix(float[] projectionMatrix)
public void ProjectionMatrix(float[] projectionMatrix)
{
this._projectionMatrix = projectionMatrix;
}
public void viewMatrix(float[] viewMatrix)
public void ViewMatrix(float[] viewMatrix)
{
this._viewMatrix = viewMatrix;
}
public void fog(float start, float end)
public void Fog(float start, float end)
{
fogStart = start;
fogEnd = end;
}
public void fog(bool state)
public void Fog(bool state)
{
fogEnabled = state;
}

View File

@ -39,45 +39,45 @@ public class NavMeshRenderer
this.debugDraw = debugDraw;
}
public RecastDebugDraw getDebugDraw()
public RecastDebugDraw GetDebugDraw()
{
return debugDraw;
}
public void render(Sample sample)
public void Render(Sample sample)
{
if (sample == null)
{
return;
}
NavMeshQuery navQuery = sample.getNavMeshQuery();
DemoInputGeomProvider geom = sample.getInputGeom();
IList<RecastBuilderResult> rcBuilderResults = sample.getRecastResults();
NavMesh navMesh = sample.getNavMesh();
RcSettingsView rcSettingsView = sample.getSettingsUI();
debugDraw.fog(true);
debugDraw.depthMask(true);
var drawMode = rcSettingsView.getDrawMode();
NavMeshQuery navQuery = sample.GetNavMeshQuery();
DemoInputGeomProvider geom = sample.GetInputGeom();
IList<RecastBuilderResult> rcBuilderResults = sample.GetRecastResults();
NavMesh navMesh = sample.GetNavMesh();
RcSettingsView rcSettingsView = sample.GetSettingsUI();
debugDraw.Fog(true);
debugDraw.DepthMask(true);
var drawMode = rcSettingsView.GetDrawMode();
float texScale = 1.0f / (rcSettingsView.getCellSize() * 10.0f);
float m_agentMaxSlope = rcSettingsView.getAgentMaxSlope();
float texScale = 1.0f / (rcSettingsView.GetCellSize() * 10.0f);
float m_agentMaxSlope = rcSettingsView.GetAgentMaxSlope();
if (drawMode != DrawMode.DRAWMODE_NAVMESH_TRANS)
{
// Draw mesh
if (geom != null)
{
debugDraw.debugDrawTriMeshSlope(geom.vertices, geom.faces, geom.normals, m_agentMaxSlope, texScale);
drawOffMeshConnections(geom, false);
debugDraw.DebugDrawTriMeshSlope(geom.vertices, geom.faces, geom.normals, m_agentMaxSlope, texScale);
DrawOffMeshConnections(geom, false);
}
}
debugDraw.fog(false);
debugDraw.depthMask(false);
debugDraw.Fog(false);
debugDraw.DepthMask(false);
if (geom != null)
{
drawGeomBounds(geom);
DrawGeomBounds(geom);
}
if (navMesh != null && navQuery != null
@ -88,221 +88,221 @@ public class NavMeshRenderer
{
if (drawMode != DrawMode.DRAWMODE_NAVMESH_INVIS)
{
debugDraw.debugDrawNavMeshWithClosedList(navMesh, navQuery, navMeshDrawFlags);
debugDraw.DebugDrawNavMeshWithClosedList(navMesh, navQuery, navMeshDrawFlags);
}
if (drawMode == DrawMode.DRAWMODE_NAVMESH_BVTREE)
{
debugDraw.debugDrawNavMeshBVTree(navMesh);
debugDraw.DebugDrawNavMeshBVTree(navMesh);
}
if (drawMode == DrawMode.DRAWMODE_NAVMESH_PORTALS)
{
debugDraw.debugDrawNavMeshPortals(navMesh);
debugDraw.DebugDrawNavMeshPortals(navMesh);
}
if (drawMode == DrawMode.DRAWMODE_NAVMESH_NODES)
{
debugDraw.debugDrawNavMeshNodes(navQuery);
debugDraw.debugDrawNavMeshPolysWithFlags(navMesh, SampleAreaModifications.SAMPLE_POLYFLAGS_DISABLED,
DebugDraw.duRGBA(0, 0, 0, 128));
debugDraw.DebugDrawNavMeshNodes(navQuery);
debugDraw.DebugDrawNavMeshPolysWithFlags(navMesh, SampleAreaModifications.SAMPLE_POLYFLAGS_DISABLED,
DebugDraw.DuRGBA(0, 0, 0, 128));
}
}
debugDraw.depthMask(true);
debugDraw.DepthMask(true);
foreach (RecastBuilderResult rcBuilderResult in rcBuilderResults)
{
if (rcBuilderResult.getCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT)
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT)
{
debugDraw.debugDrawCompactHeightfieldSolid(rcBuilderResult.getCompactHeightfield());
debugDraw.DebugDrawCompactHeightfieldSolid(rcBuilderResult.GetCompactHeightfield());
}
if (rcBuilderResult.getCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT_DISTANCE)
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT_DISTANCE)
{
debugDraw.debugDrawCompactHeightfieldDistance(rcBuilderResult.getCompactHeightfield());
debugDraw.DebugDrawCompactHeightfieldDistance(rcBuilderResult.GetCompactHeightfield());
}
if (rcBuilderResult.getCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT_REGIONS)
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT_REGIONS)
{
debugDraw.debugDrawCompactHeightfieldRegions(rcBuilderResult.getCompactHeightfield());
debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.GetCompactHeightfield());
}
if (rcBuilderResult.getSolidHeightfield() != null && drawMode == DrawMode.DRAWMODE_VOXELS)
if (rcBuilderResult.GetSolidHeightfield() != null && drawMode == DrawMode.DRAWMODE_VOXELS)
{
debugDraw.fog(true);
debugDraw.debugDrawHeightfieldSolid(rcBuilderResult.getSolidHeightfield());
debugDraw.fog(false);
debugDraw.Fog(true);
debugDraw.DebugDrawHeightfieldSolid(rcBuilderResult.GetSolidHeightfield());
debugDraw.Fog(false);
}
if (rcBuilderResult.getSolidHeightfield() != null && drawMode == DrawMode.DRAWMODE_VOXELS_WALKABLE)
if (rcBuilderResult.GetSolidHeightfield() != null && drawMode == DrawMode.DRAWMODE_VOXELS_WALKABLE)
{
debugDraw.fog(true);
debugDraw.debugDrawHeightfieldWalkable(rcBuilderResult.getSolidHeightfield());
debugDraw.fog(false);
debugDraw.Fog(true);
debugDraw.DebugDrawHeightfieldWalkable(rcBuilderResult.GetSolidHeightfield());
debugDraw.Fog(false);
}
if (rcBuilderResult.getContourSet() != null && drawMode == DrawMode.DRAWMODE_RAW_CONTOURS)
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_RAW_CONTOURS)
{
debugDraw.depthMask(false);
debugDraw.debugDrawRawContours(rcBuilderResult.getContourSet(), 1f);
debugDraw.depthMask(true);
debugDraw.DepthMask(false);
debugDraw.DebugDrawRawContours(rcBuilderResult.GetContourSet(), 1f);
debugDraw.DepthMask(true);
}
if (rcBuilderResult.getContourSet() != null && drawMode == DrawMode.DRAWMODE_BOTH_CONTOURS)
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_BOTH_CONTOURS)
{
debugDraw.depthMask(false);
debugDraw.debugDrawRawContours(rcBuilderResult.getContourSet(), 0.5f);
debugDraw.debugDrawContours(rcBuilderResult.getContourSet());
debugDraw.depthMask(true);
debugDraw.DepthMask(false);
debugDraw.DebugDrawRawContours(rcBuilderResult.GetContourSet(), 0.5f);
debugDraw.DebugDrawContours(rcBuilderResult.GetContourSet());
debugDraw.DepthMask(true);
}
if (rcBuilderResult.getContourSet() != null && drawMode == DrawMode.DRAWMODE_CONTOURS)
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_CONTOURS)
{
debugDraw.depthMask(false);
debugDraw.debugDrawContours(rcBuilderResult.getContourSet());
debugDraw.depthMask(true);
debugDraw.DepthMask(false);
debugDraw.DebugDrawContours(rcBuilderResult.GetContourSet());
debugDraw.DepthMask(true);
}
if (rcBuilderResult.getCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_REGION_CONNECTIONS)
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_REGION_CONNECTIONS)
{
debugDraw.debugDrawCompactHeightfieldRegions(rcBuilderResult.getCompactHeightfield());
debugDraw.depthMask(false);
if (rcBuilderResult.getContourSet() != null)
debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.GetCompactHeightfield());
debugDraw.DepthMask(false);
if (rcBuilderResult.GetContourSet() != null)
{
debugDraw.debugDrawRegionConnections(rcBuilderResult.getContourSet());
debugDraw.DebugDrawRegionConnections(rcBuilderResult.GetContourSet());
}
debugDraw.depthMask(true);
debugDraw.DepthMask(true);
}
if (rcBuilderResult.getMesh() != null && drawMode == DrawMode.DRAWMODE_POLYMESH)
if (rcBuilderResult.GetMesh() != null && drawMode == DrawMode.DRAWMODE_POLYMESH)
{
debugDraw.depthMask(false);
debugDraw.debugDrawPolyMesh(rcBuilderResult.getMesh());
debugDraw.depthMask(true);
debugDraw.DepthMask(false);
debugDraw.DebugDrawPolyMesh(rcBuilderResult.GetMesh());
debugDraw.DepthMask(true);
}
if (rcBuilderResult.getMeshDetail() != null && drawMode == DrawMode.DRAWMODE_POLYMESH_DETAIL)
if (rcBuilderResult.GetMeshDetail() != null && drawMode == DrawMode.DRAWMODE_POLYMESH_DETAIL)
{
debugDraw.depthMask(false);
debugDraw.debugDrawPolyMeshDetail(rcBuilderResult.getMeshDetail());
debugDraw.depthMask(true);
debugDraw.DepthMask(false);
debugDraw.DebugDrawPolyMeshDetail(rcBuilderResult.GetMeshDetail());
debugDraw.DepthMask(true);
}
}
if (geom != null)
{
drawConvexVolumes(geom);
DrawConvexVolumes(geom);
}
}
private void drawGeomBounds(DemoInputGeomProvider geom)
private void DrawGeomBounds(DemoInputGeomProvider geom)
{
// Draw bounds
Vector3f bmin = geom.getMeshBoundsMin();
Vector3f bmax = geom.getMeshBoundsMax();
debugDraw.debugDrawBoxWire(bmin.x, bmin.y, bmin.z, bmax.x, bmax.y, bmax.z,
DebugDraw.duRGBA(255, 255, 255, 128), 1.0f);
debugDraw.begin(DebugDrawPrimitives.POINTS, 5.0f);
debugDraw.vertex(bmin.x, bmin.y, bmin.z, DebugDraw.duRGBA(255, 255, 255, 128));
debugDraw.end();
Vector3f bmin = geom.GetMeshBoundsMin();
Vector3f bmax = geom.GetMeshBoundsMax();
debugDraw.DebugDrawBoxWire(bmin.x, bmin.y, bmin.z, bmax.x, bmax.y, bmax.z,
DebugDraw.DuRGBA(255, 255, 255, 128), 1.0f);
debugDraw.Begin(DebugDrawPrimitives.POINTS, 5.0f);
debugDraw.Vertex(bmin.x, bmin.y, bmin.z, DebugDraw.DuRGBA(255, 255, 255, 128));
debugDraw.End();
}
public void drawOffMeshConnections(DemoInputGeomProvider geom, bool hilight)
public void DrawOffMeshConnections(DemoInputGeomProvider geom, bool hilight)
{
int conColor = DebugDraw.duRGBA(192, 0, 128, 192);
int baseColor = DebugDraw.duRGBA(0, 0, 0, 64);
debugDraw.depthMask(false);
int conColor = DebugDraw.DuRGBA(192, 0, 128, 192);
int baseColor = DebugDraw.DuRGBA(0, 0, 0, 64);
debugDraw.DepthMask(false);
debugDraw.begin(DebugDrawPrimitives.LINES, 2.0f);
foreach (DemoOffMeshConnection con in geom.getOffMeshConnections())
debugDraw.Begin(DebugDrawPrimitives.LINES, 2.0f);
foreach (DemoOffMeshConnection con in geom.GetOffMeshConnections())
{
float[] v = con.verts;
debugDraw.vertex(v[0], v[1], v[2], baseColor);
debugDraw.vertex(v[0], v[1] + 0.2f, v[2], baseColor);
debugDraw.Vertex(v[0], v[1], v[2], baseColor);
debugDraw.Vertex(v[0], v[1] + 0.2f, v[2], baseColor);
debugDraw.vertex(v[3], v[4], v[5], baseColor);
debugDraw.vertex(v[3], v[4] + 0.2f, v[5], baseColor);
debugDraw.Vertex(v[3], v[4], v[5], baseColor);
debugDraw.Vertex(v[3], v[4] + 0.2f, v[5], baseColor);
debugDraw.appendCircle(v[0], v[1] + 0.1f, v[2], con.radius, baseColor);
debugDraw.appendCircle(v[3], v[4] + 0.1f, v[5], con.radius, baseColor);
debugDraw.AppendCircle(v[0], v[1] + 0.1f, v[2], con.radius, baseColor);
debugDraw.AppendCircle(v[3], v[4] + 0.1f, v[5], con.radius, baseColor);
if (hilight)
{
debugDraw.appendArc(v[0], v[1], v[2], v[3], v[4], v[5], 0.25f, con.bidir ? 0.6f : 0.0f, 0.6f, conColor);
debugDraw.AppendArc(v[0], v[1], v[2], v[3], v[4], v[5], 0.25f, con.bidir ? 0.6f : 0.0f, 0.6f, conColor);
}
}
debugDraw.end();
debugDraw.End();
debugDraw.depthMask(true);
debugDraw.DepthMask(true);
}
void drawConvexVolumes(DemoInputGeomProvider geom)
void DrawConvexVolumes(DemoInputGeomProvider geom)
{
debugDraw.depthMask(false);
debugDraw.DepthMask(false);
debugDraw.begin(DebugDrawPrimitives.TRIS);
debugDraw.Begin(DebugDrawPrimitives.TRIS);
foreach (ConvexVolume vol in geom.convexVolumes())
foreach (ConvexVolume vol in geom.ConvexVolumes())
{
int col = DebugDraw.duTransCol(DebugDraw.areaToCol(vol.areaMod.getMaskedValue()), 32);
int col = DebugDraw.DuTransCol(DebugDraw.AreaToCol(vol.areaMod.GetMaskedValue()), 32);
for (int j = 0, k = vol.verts.Length - 3; j < vol.verts.Length; k = j, j += 3)
{
var va = Vector3f.Of(vol.verts[k], vol.verts[k + 1], vol.verts[k + 2]);
var vb = Vector3f.Of(vol.verts[j], vol.verts[j + 1], vol.verts[j + 2]);
debugDraw.vertex(vol.verts[0], vol.hmax, vol.verts[2], col);
debugDraw.vertex(vb.x, vol.hmax, vb.z, col);
debugDraw.vertex(va.x, vol.hmax, va.z, col);
debugDraw.Vertex(vol.verts[0], vol.hmax, vol.verts[2], col);
debugDraw.Vertex(vb.x, vol.hmax, vb.z, col);
debugDraw.Vertex(va.x, vol.hmax, va.z, col);
debugDraw.vertex(va.x, vol.hmin, va.z, DebugDraw.duDarkenCol(col));
debugDraw.vertex(va.x, vol.hmax, va.z, col);
debugDraw.vertex(vb.x, vol.hmax, vb.z, col);
debugDraw.Vertex(va.x, vol.hmin, va.z, DebugDraw.DuDarkenCol(col));
debugDraw.Vertex(va.x, vol.hmax, va.z, col);
debugDraw.Vertex(vb.x, vol.hmax, vb.z, col);
debugDraw.vertex(va.x, vol.hmin, va.z, DebugDraw.duDarkenCol(col));
debugDraw.vertex(vb.x, vol.hmax, vb.z, col);
debugDraw.vertex(vb.x, vol.hmin, vb.z, DebugDraw.duDarkenCol(col));
debugDraw.Vertex(va.x, vol.hmin, va.z, DebugDraw.DuDarkenCol(col));
debugDraw.Vertex(vb.x, vol.hmax, vb.z, col);
debugDraw.Vertex(vb.x, vol.hmin, vb.z, DebugDraw.DuDarkenCol(col));
}
}
debugDraw.end();
debugDraw.End();
debugDraw.begin(DebugDrawPrimitives.LINES, 2.0f);
foreach (ConvexVolume vol in geom.convexVolumes())
debugDraw.Begin(DebugDrawPrimitives.LINES, 2.0f);
foreach (ConvexVolume vol in geom.ConvexVolumes())
{
int col = DebugDraw.duTransCol(DebugDraw.areaToCol(vol.areaMod.getMaskedValue()), 220);
int col = DebugDraw.DuTransCol(DebugDraw.AreaToCol(vol.areaMod.GetMaskedValue()), 220);
for (int j = 0, k = vol.verts.Length - 3; j < vol.verts.Length; k = j, j += 3)
{
var va = Vector3f.Of(vol.verts[k], vol.verts[k + 1], vol.verts[k + 2]);
var vb = Vector3f.Of(vol.verts[j], vol.verts[j + 1], vol.verts[j + 2]);
debugDraw.vertex(va.x, vol.hmin, va.z, DebugDraw.duDarkenCol(col));
debugDraw.vertex(vb.x, vol.hmin, vb.z, DebugDraw.duDarkenCol(col));
debugDraw.vertex(va.x, vol.hmax, va.z, col);
debugDraw.vertex(vb.x, vol.hmax, vb.z, col);
debugDraw.vertex(va.x, vol.hmin, va.z, DebugDraw.duDarkenCol(col));
debugDraw.vertex(va.x, vol.hmax, va.z, col);
debugDraw.Vertex(va.x, vol.hmin, va.z, DebugDraw.DuDarkenCol(col));
debugDraw.Vertex(vb.x, vol.hmin, vb.z, DebugDraw.DuDarkenCol(col));
debugDraw.Vertex(va.x, vol.hmax, va.z, col);
debugDraw.Vertex(vb.x, vol.hmax, vb.z, col);
debugDraw.Vertex(va.x, vol.hmin, va.z, DebugDraw.DuDarkenCol(col));
debugDraw.Vertex(va.x, vol.hmax, va.z, col);
}
}
debugDraw.end();
debugDraw.End();
debugDraw.begin(DebugDrawPrimitives.POINTS, 3.0f);
foreach (ConvexVolume vol in geom.convexVolumes())
debugDraw.Begin(DebugDrawPrimitives.POINTS, 3.0f);
foreach (ConvexVolume vol in geom.ConvexVolumes())
{
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)
{
debugDraw.vertex(vol.verts[j + 0], vol.verts[j + 1] + 0.1f, vol.verts[j + 2], col);
debugDraw.vertex(vol.verts[j + 0], vol.hmin, vol.verts[j + 2], col);
debugDraw.vertex(vol.verts[j + 0], vol.hmax, vol.verts[j + 2], col);
debugDraw.Vertex(vol.verts[j + 0], vol.verts[j + 1] + 0.1f, vol.verts[j + 2], col);
debugDraw.Vertex(vol.verts[j + 0], vol.hmin, vol.verts[j + 2], col);
debugDraw.Vertex(vol.verts[j + 0], vol.hmax, vol.verts[j + 2], col);
}
}
debugDraw.end();
debugDraw.End();
debugDraw.depthMask(true);
debugDraw.DepthMask(true);
}
}

View File

@ -5,32 +5,32 @@ namespace DotRecast.Recast.Demo.Draw;
public interface OpenGLDraw
{
void init();
void Init();
void clear();
void Clear();
void begin(DebugDrawPrimitives prim, float size);
void Begin(DebugDrawPrimitives prim, float size);
void end();
void End();
void vertex(float x, float y, float z, int color);
void Vertex(float x, float y, float z, int color);
void vertex(float[] pos, int color);
void vertex(Vector3f pos, int color);
void Vertex(float[] pos, int color);
void Vertex(Vector3f pos, int color);
void vertex(Vector3f pos, int color, Vector2f uv);
void Vertex(Vector3f pos, int color, Vector2f uv);
void vertex(float x, float y, float z, int color, float u, float v);
void Vertex(float x, float y, float z, int color, float u, float v);
void fog(bool state);
void Fog(bool state);
void depthMask(bool state);
void DepthMask(bool state);
void texture(GLCheckerTexture g_tex, bool state);
void Texture(GLCheckerTexture g_tex, bool state);
void projectionMatrix(float[] projectionMatrix);
void ProjectionMatrix(float[] projectionMatrix);
void viewMatrix(float[] viewMatrix);
void ViewMatrix(float[] viewMatrix);
void fog(float start, float end);
void Fog(float start, float end);
}

View File

@ -46,7 +46,7 @@ public struct OpenGLVertex
this.color = color;
}
public void store(BinaryWriter writer)
public void Store(BinaryWriter writer)
{
// writer.Write(BitConverter.GetBytes(x));
// writer.Write(BitConverter.GetBytes(y));

File diff suppressed because it is too large Load Diff

View File

@ -39,11 +39,11 @@ public class DemoInputGeomProvider : InputGeomProvider
private readonly TriMesh _mesh;
public DemoInputGeomProvider(List<float> vertexPositions, List<int> meshFaces) :
this(mapVertices(vertexPositions), mapFaces(meshFaces))
this(MapVertices(vertexPositions), MapFaces(meshFaces))
{
}
private static int[] mapFaces(List<int> meshFaces)
private static int[] MapFaces(List<int> meshFaces)
{
int[] faces = new int[meshFaces.Count];
for (int i = 0; i < faces.Length; i++)
@ -54,7 +54,7 @@ public class DemoInputGeomProvider : InputGeomProvider
return faces;
}
private static float[] mapVertices(List<float> vertexPositions)
private static float[] MapVertices(List<float> vertexPositions)
{
float[] vertices = new float[vertexPositions.Count];
for (int i = 0; i < vertices.Length; i++)
@ -70,31 +70,31 @@ public class DemoInputGeomProvider : InputGeomProvider
this.vertices = vertices;
this.faces = faces;
normals = new float[faces.Length];
calculateNormals();
CalculateNormals();
bmin = Vector3f.Zero;
bmax = Vector3f.Zero;
RecastVectors.copy(ref bmin, vertices, 0);
RecastVectors.copy(ref bmax, vertices, 0);
RecastVectors.Copy(ref bmin, vertices, 0);
RecastVectors.Copy(ref bmax, vertices, 0);
for (int i = 1; i < vertices.Length / 3; i++)
{
RecastVectors.min(ref bmin, vertices, i * 3);
RecastVectors.max(ref bmax, vertices, i * 3);
RecastVectors.Min(ref bmin, vertices, i * 3);
RecastVectors.Max(ref bmax, vertices, i * 3);
}
_mesh = new TriMesh(vertices, faces);
}
public Vector3f getMeshBoundsMin()
public Vector3f GetMeshBoundsMin()
{
return bmin;
}
public Vector3f getMeshBoundsMax()
public Vector3f GetMeshBoundsMax()
{
return bmax;
}
public void calculateNormals()
public void CalculateNormals()
{
for (int i = 0; i < faces.Length; i += 3)
{
@ -123,36 +123,36 @@ public class DemoInputGeomProvider : InputGeomProvider
}
}
public IList<ConvexVolume> convexVolumes()
public IList<ConvexVolume> ConvexVolumes()
{
return _convexVolumes;
}
public IEnumerable<TriMesh> meshes()
public IEnumerable<TriMesh> Meshes()
{
return ImmutableArray.Create(_mesh);
}
public List<DemoOffMeshConnection> getOffMeshConnections()
public List<DemoOffMeshConnection> GetOffMeshConnections()
{
return offMeshConnections;
}
public void addOffMeshConnection(Vector3f start, Vector3f end, float radius, bool bidir, int area, int flags)
public void AddOffMeshConnection(Vector3f start, Vector3f end, float radius, bool bidir, int area, int flags)
{
offMeshConnections.Add(new DemoOffMeshConnection(start, end, radius, bidir, area, flags));
}
public void removeOffMeshConnections(Predicate<DemoOffMeshConnection> filter)
public void RemoveOffMeshConnections(Predicate<DemoOffMeshConnection> filter)
{
//offMeshConnections.retainAll(offMeshConnections.stream().filter(c -> !filter.test(c)).collect(toList()));
//offMeshConnections.RetainAll(offMeshConnections.Stream().Filter(c -> !filter.Test(c)).Collect(ToList()));
offMeshConnections.RemoveAll(filter); // TODO : 확인 필요
}
public float? raycastMesh(Vector3f src, Vector3f dst)
public float? RaycastMesh(Vector3f src, Vector3f dst)
{
// Prune hit ray.
float[] btminmax = Intersections.intersectSegmentAABB(src, dst, bmin, bmax);
float[] btminmax = Intersections.IntersectSegmentAABB(src, dst, bmin, bmax);
if (null == btminmax)
{
return null;
@ -166,7 +166,7 @@ public class DemoInputGeomProvider : InputGeomProvider
q[0] = src.x + (dst.x - src.x) * btmax;
q[1] = src.z + (dst.z - src.z) * btmax;
List<ChunkyTriMeshNode> chunks = _mesh.chunkyTriMesh.getChunksOverlappingSegment(p, q);
List<ChunkyTriMeshNode> chunks = _mesh.chunkyTriMesh.GetChunksOverlappingSegment(p, q);
if (0 == chunks.Count)
{
return null;
@ -194,7 +194,7 @@ public class DemoInputGeomProvider : InputGeomProvider
vertices[tris[j + 2] * 3 + 1],
vertices[tris[j + 2] * 3 + 2]
);
float? t = Intersections.intersectSegmentTriangle(src, dst, v1, v2, v3);
float? t = Intersections.IntersectSegmentTriangle(src, dst, v1, v2, v3);
if (null != t)
{
if (t.Value < tmin)
@ -211,7 +211,7 @@ public class DemoInputGeomProvider : InputGeomProvider
}
public void addConvexVolume(float[] verts, float minh, float maxh, AreaModification areaMod)
public void AddConvexVolume(float[] verts, float minh, float maxh, AreaModification areaMod)
{
ConvexVolume volume = new ConvexVolume();
volume.verts = verts;
@ -221,7 +221,7 @@ public class DemoInputGeomProvider : InputGeomProvider
_convexVolumes.Add(volume);
}
public void clearConvexVolumes()
public void ClearConvexVolumes()
{
_convexVolumes.Clear();
}

View File

@ -143,7 +143,7 @@ public class RecastDemo
}
}
float[] modelviewMatrix = dd.viewMatrix(cameraPos, cameraEulers);
float[] modelviewMatrix = dd.ViewMatrix(cameraPos, cameraEulers);
cameraPos.x += scrollZoom * 2.0f * modelviewMatrix[2];
cameraPos.y += scrollZoom * 2.0f * modelviewMatrix[6];
cameraPos.z += scrollZoom * 2.0f * modelviewMatrix[10];
@ -168,7 +168,7 @@ public class RecastDemo
if (pan)
{
float[] modelviewMatrix = dd.viewMatrix(cameraPos, cameraEulers);
float[] modelviewMatrix = dd.ViewMatrix(cameraPos, cameraEulers);
cameraPos.x = origCameraPos.x;
cameraPos.y = origCameraPos.y;
cameraPos.z = origCameraPos.z;
@ -286,7 +286,7 @@ public class RecastDemo
// // -- move somewhere else:
// glfw.SetWindowPos(window, (mode->Width - width) / 2, (mode->Height - height) / 2);
// // glfwSetWindowMonitor(window.getWindow(), monitor, 0, 0, mode.width(), mode.height(), mode.refreshRate());
// // GlfwSetWindowMonitor(window.GetWindow(), monitor, 0, 0, mode.Width(), mode.Height(), mode.RefreshRate());
// glfw.ShowWindow(window);
// glfw.MakeContextCurrent(window);
//}
@ -296,35 +296,35 @@ public class RecastDemo
return window;
}
private DemoInputGeomProvider loadInputMesh(byte[] stream)
private DemoInputGeomProvider LoadInputMesh(byte[] stream)
{
DemoInputGeomProvider geom = DemoObjImporter.load(stream);
DemoInputGeomProvider geom = DemoObjImporter.Load(stream);
sample = new Sample(geom, ImmutableArray<RecastBuilderResult>.Empty, null, settingsUI, dd);
toolsUI.setEnabled(true);
toolsUI.SetEnabled(true);
return geom;
}
private void loadNavMesh(FileStream file, string filename)
private void LoadNavMesh(FileStream file, string filename)
{
NavMesh mesh = null;
if (filename.EndsWith(".zip") || filename.EndsWith(".bytes"))
{
UnityAStarPathfindingImporter importer = new UnityAStarPathfindingImporter();
mesh = importer.load(file)[0];
mesh = importer.Load(file)[0];
}
else if (filename.EndsWith(".bin") || filename.EndsWith(".navmesh"))
{
MeshSetReader reader = new MeshSetReader();
using (var fis = new BinaryReader(file))
{
mesh = reader.read(fis, 6);
mesh = reader.Read(fis, 6);
}
}
if (mesh != null)
{
//sample = new Sample(null, ImmutableArray<RecastBuilderResult>.Empty, mesh, settingsUI, dd);
toolsUI.setEnabled(true);
toolsUI.SetEnabled(true);
}
}
@ -363,7 +363,7 @@ public class RecastDemo
dd = new RecastDebugDraw(_gl);
renderer = new NavMeshRenderer(dd);
dd.init(camr);
dd.Init(camr);
_imgui = new ImGuiController(_gl, window, _input);
@ -391,7 +391,7 @@ public class RecastDemo
Logger.Debug(glslString);
DemoInputGeomProvider geom = loadInputMesh(Loader.ToBytes("nav_test.obj"));
DemoInputGeomProvider geom = LoadInputMesh(Loader.ToBytes("nav_test.obj"));
sample = new Sample(geom, ImmutableArray<RecastBuilderResult>.Empty, null, settingsUI, dd);
}
@ -409,31 +409,31 @@ public class RecastDemo
var tempMoveAccel = keyboard.IsKeyPressed(Key.ShiftLeft) || keyboard.IsKeyPressed(Key.ShiftRight) ? 1.0f : -1f;
modState = keyboard.IsKeyPressed(Key.ControlLeft) || keyboard.IsKeyPressed(Key.ShiftRight) ? 1 : 0;
_moveFront = clamp(_moveFront + tempMoveFront * dt * 4.0f, 0, 2.0f);
_moveLeft = clamp(_moveLeft + tempMoveLeft * dt * 4.0f, 0, 2.0f);
_moveBack = clamp(_moveBack + tempMoveBack * dt * 4.0f, 0, 2.0f);
_moveRight = clamp(_moveRight + tempMoveRight * dt * 4.0f, 0, 2.0f);
_moveUp = clamp(_moveUp + tempMoveUp * dt * 4.0f, 0, 2.0f);
_moveDown = clamp(_moveDown + tempMoveDown * dt * 4.0f, 0, 2.0f);
_moveAccel = clamp(_moveAccel + tempMoveAccel * dt * 4.0f, 0, 2.0f);
_moveFront = Clamp(_moveFront + tempMoveFront * dt * 4.0f, 0, 2.0f);
_moveLeft = Clamp(_moveLeft + tempMoveLeft * dt * 4.0f, 0, 2.0f);
_moveBack = Clamp(_moveBack + tempMoveBack * dt * 4.0f, 0, 2.0f);
_moveRight = Clamp(_moveRight + tempMoveRight * dt * 4.0f, 0, 2.0f);
_moveUp = Clamp(_moveUp + tempMoveUp * dt * 4.0f, 0, 2.0f);
_moveDown = Clamp(_moveDown + tempMoveDown * dt * 4.0f, 0, 2.0f);
_moveAccel = Clamp(_moveAccel + tempMoveAccel * dt * 4.0f, 0, 2.0f);
}
}
private void OnWindowUpdate(double dt)
{
/*
* try (MemoryStack stack = stackPush()) { int[] w = stack.mallocInt(1); int[] h =
* stack.mallocInt(1); glfwGetWindowSize(win, w, h); width = w.x; height = h.x; }
* try (MemoryStack stack = StackPush()) { int[] w = stack.MallocInt(1); int[] h =
* stack.MallocInt(1); GlfwGetWindowSize(win, w, h); width = w.x; height = h.x; }
*/
if (sample.getInputGeom() != null)
if (sample.GetInputGeom() != null)
{
Vector3f bmin = sample.getInputGeom().getMeshBoundsMin();
Vector3f bmax = sample.getInputGeom().getMeshBoundsMax();
int[] voxels = Recast.calcGridSize(bmin, bmax, settingsUI.getCellSize());
settingsUI.setVoxels(voxels);
settingsUI.setTiles(tileNavMeshBuilder.getTiles(sample.getInputGeom(), settingsUI.getCellSize(), settingsUI.getTileSize()));
settingsUI.setMaxTiles(tileNavMeshBuilder.getMaxTiles(sample.getInputGeom(), settingsUI.getCellSize(), settingsUI.getTileSize()));
settingsUI.setMaxPolys(tileNavMeshBuilder.getMaxPolysPerTile(sample.getInputGeom(), settingsUI.getCellSize(), settingsUI.getTileSize()));
Vector3f bmin = sample.GetInputGeom().GetMeshBoundsMin();
Vector3f bmax = sample.GetInputGeom().GetMeshBoundsMax();
int[] voxels = Recast.CalcGridSize(bmin, bmax, settingsUI.GetCellSize());
settingsUI.SetVoxels(voxels);
settingsUI.SetTiles(tileNavMeshBuilder.GetTiles(sample.GetInputGeom(), settingsUI.GetCellSize(), settingsUI.GetTileSize()));
settingsUI.SetMaxTiles(tileNavMeshBuilder.GetMaxTiles(sample.GetInputGeom(), settingsUI.GetCellSize(), settingsUI.GetTileSize()));
settingsUI.SetMaxPolys(tileNavMeshBuilder.GetMaxPolysPerTile(sample.GetInputGeom(), settingsUI.GetCellSize(), settingsUI.GetTileSize()));
}
UpdateKeyboard((float)dt);
@ -465,40 +465,40 @@ public class RecastDemo
// Update sample simulation.
float SIM_RATE = 20;
float DELTA_TIME = 1.0f / SIM_RATE;
timeAcc = clamp((float)(timeAcc + dt), -1.0f, 1.0f);
timeAcc = Clamp((float)(timeAcc + dt), -1.0f, 1.0f);
int simIter = 0;
while (timeAcc > DELTA_TIME)
{
timeAcc -= DELTA_TIME;
if (simIter < 5 && sample != null)
{
toolsUI.handleUpdate(DELTA_TIME);
toolsUI.HandleUpdate(DELTA_TIME);
}
simIter++;
}
if (settingsUI.isMeshInputTrigerred())
if (settingsUI.IsMeshInputTrigerred())
{
var bytes = Loader.ToBytes(settingsUI.GetMeshInputFilePath());
sample.update(loadInputMesh(bytes), null, null);
sample.Update(LoadInputMesh(bytes), null, null);
}
else if (settingsUI.isNavMeshInputTrigerred())
else if (settingsUI.IsNavMeshInputTrigerred())
{
// try (MemoryStack stack = stackPush()) {
// PointerBuffer aFilterPatterns = stack.mallocPointer(4);
// aFilterPatterns.put(stack.UTF8("*.bin"));
// aFilterPatterns.put(stack.UTF8("*.zip"));
// aFilterPatterns.put(stack.UTF8("*.bytes"));
// aFilterPatterns.put(stack.UTF8("*.navmesh"));
// aFilterPatterns.flip();
// string filename = TinyFileDialogs.tinyfd_openFileDialog("Open Nav Mesh File", "", aFilterPatterns,
// try (MemoryStack stack = StackPush()) {
// PointerBuffer aFilterPatterns = stack.MallocPointer(4);
// aFilterPatterns.Put(stack.UTF8("*.bin"));
// aFilterPatterns.Put(stack.UTF8("*.zip"));
// aFilterPatterns.Put(stack.UTF8("*.bytes"));
// aFilterPatterns.Put(stack.UTF8("*.navmesh"));
// aFilterPatterns.Flip();
// string filename = TinyFileDialogs.Tinyfd_openFileDialog("Open Nav Mesh File", "", aFilterPatterns,
// "Nav Mesh File", false);
// if (filename != null) {
// File file = new File(filename);
// if (file.exists()) {
// if (file.Exists()) {
// try {
// loadNavMesh(file, filename);
// LoadNavMesh(file, filename);
// geom = null;
// } catch (Exception e) {
// Console.WriteLine(e);
@ -507,56 +507,56 @@ public class RecastDemo
// }
// }
}
if (settingsUI.isBuildTriggered() && sample.getInputGeom() != null)
if (settingsUI.IsBuildTriggered() && sample.GetInputGeom() != null)
{
if (!building)
{
float m_cellSize = settingsUI.getCellSize();
float m_cellHeight = settingsUI.getCellHeight();
float m_agentHeight = settingsUI.getAgentHeight();
float m_agentRadius = settingsUI.getAgentRadius();
float m_agentMaxClimb = settingsUI.getAgentMaxClimb();
float m_agentMaxSlope = settingsUI.getAgentMaxSlope();
int m_regionMinSize = settingsUI.getMinRegionSize();
int m_regionMergeSize = settingsUI.getMergedRegionSize();
float m_edgeMaxLen = settingsUI.getEdgeMaxLen();
float m_edgeMaxError = settingsUI.getEdgeMaxError();
int m_vertsPerPoly = settingsUI.getVertsPerPoly();
float m_detailSampleDist = settingsUI.getDetailSampleDist();
float m_detailSampleMaxError = settingsUI.getDetailSampleMaxError();
int m_tileSize = settingsUI.getTileSize();
float m_cellSize = settingsUI.GetCellSize();
float m_cellHeight = settingsUI.GetCellHeight();
float m_agentHeight = settingsUI.GetAgentHeight();
float m_agentRadius = settingsUI.GetAgentRadius();
float m_agentMaxClimb = settingsUI.GetAgentMaxClimb();
float m_agentMaxSlope = settingsUI.GetAgentMaxSlope();
int m_regionMinSize = settingsUI.GetMinRegionSize();
int m_regionMergeSize = settingsUI.GetMergedRegionSize();
float m_edgeMaxLen = settingsUI.GetEdgeMaxLen();
float m_edgeMaxError = settingsUI.GetEdgeMaxError();
int m_vertsPerPoly = settingsUI.GetVertsPerPoly();
float m_detailSampleDist = settingsUI.GetDetailSampleDist();
float m_detailSampleMaxError = settingsUI.GetDetailSampleMaxError();
int m_tileSize = settingsUI.GetTileSize();
long t = FrequencyWatch.Ticks;
Logger.Information($"build");
Tuple<IList<RecastBuilderResult>, NavMesh> buildResult;
if (settingsUI.isTiled())
if (settingsUI.IsTiled())
{
buildResult = tileNavMeshBuilder.build(sample.getInputGeom(), settingsUI.getPartitioning(), m_cellSize,
buildResult = tileNavMeshBuilder.Build(sample.GetInputGeom(), settingsUI.GetPartitioning(), m_cellSize,
m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_agentMaxSlope, m_regionMinSize,
m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, m_detailSampleDist,
m_detailSampleMaxError, settingsUI.isFilterLowHangingObstacles(), settingsUI.isFilterLedgeSpans(),
settingsUI.isFilterWalkableLowHeightSpans(), m_tileSize);
m_detailSampleMaxError, settingsUI.IsFilterLowHangingObstacles(), settingsUI.IsFilterLedgeSpans(),
settingsUI.IsFilterWalkableLowHeightSpans(), m_tileSize);
}
else
{
buildResult = soloNavMeshBuilder.build(sample.getInputGeom(), settingsUI.getPartitioning(), m_cellSize,
buildResult = soloNavMeshBuilder.Build(sample.GetInputGeom(), settingsUI.GetPartitioning(), m_cellSize,
m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_agentMaxSlope, m_regionMinSize,
m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, m_detailSampleDist,
m_detailSampleMaxError, settingsUI.isFilterLowHangingObstacles(), settingsUI.isFilterLedgeSpans(),
settingsUI.isFilterWalkableLowHeightSpans());
m_detailSampleMaxError, settingsUI.IsFilterLowHangingObstacles(), settingsUI.IsFilterLedgeSpans(),
settingsUI.IsFilterWalkableLowHeightSpans());
}
sample.update(sample.getInputGeom(), buildResult.Item1, buildResult.Item2);
sample.setChanged(false);
settingsUI.setBuildTime((FrequencyWatch.Ticks - t) / TimeSpan.TicksPerMillisecond);
//settingsUI.setBuildTelemetry(buildResult.Item1.Select(x => x.getTelemetry()).ToList());
toolsUI.setSample(sample);
sample.Update(sample.GetInputGeom(), buildResult.Item1, buildResult.Item2);
sample.SetChanged(false);
settingsUI.SetBuildTime((FrequencyWatch.Ticks - t) / TimeSpan.TicksPerMillisecond);
//settingsUI.SetBuildTelemetry(buildResult.Item1.Select(x => x.GetTelemetry()).ToList());
toolsUI.SetSample(sample);
Logger.Information($"build times");
Logger.Information($"-----------------------------------------");
var telemetries = buildResult.Item1
.Select(x => x.getTelemetry())
.Select(x => x.GetTelemetry())
.SelectMany(x => x.ToList())
.GroupBy(x => x.Item1)
.ToImmutableSortedDictionary(x => x.Key, x => x.Sum(y => y.Item2));
@ -574,35 +574,35 @@ public class RecastDemo
if (!_mouseOverMenu)
{
GLU.glhUnProjectf(mousePos[0], viewport[3] - 1 - mousePos[1], 0.0f, modelviewMatrix, projectionMatrix, viewport, ref rayStart);
GLU.glhUnProjectf(mousePos[0], viewport[3] - 1 - mousePos[1], 1.0f, modelviewMatrix, projectionMatrix, viewport, ref rayEnd);
GLU.GlhUnProjectf(mousePos[0], viewport[3] - 1 - mousePos[1], 0.0f, modelviewMatrix, projectionMatrix, viewport, ref rayStart);
GLU.GlhUnProjectf(mousePos[0], viewport[3] - 1 - mousePos[1], 1.0f, modelviewMatrix, projectionMatrix, viewport, ref rayEnd);
// Hit test mesh.
DemoInputGeomProvider inputGeom = sample.getInputGeom();
DemoInputGeomProvider inputGeom = sample.GetInputGeom();
if (processHitTest && sample != null)
{
float? hit = null;
if (inputGeom != null)
{
hit = inputGeom.raycastMesh(rayStart, rayEnd);
hit = inputGeom.RaycastMesh(rayStart, rayEnd);
}
if (!hit.HasValue && sample.getNavMesh() != null)
if (!hit.HasValue && sample.GetNavMesh() != null)
{
hit = NavMeshRaycast.raycast(sample.getNavMesh(), rayStart, rayEnd);
hit = NavMeshRaycast.Raycast(sample.GetNavMesh(), rayStart, rayEnd);
}
if (!hit.HasValue && sample.getRecastResults() != null)
if (!hit.HasValue && sample.GetRecastResults() != null)
{
hit = PolyMeshRaycast.raycast(sample.getRecastResults(), rayStart, rayEnd);
hit = PolyMeshRaycast.Raycast(sample.GetRecastResults(), rayStart, rayEnd);
}
float[] rayDir = new float[] { rayEnd.x - rayStart.x, rayEnd.y - rayStart.y, rayEnd.z - rayStart.z };
Tool rayTool = toolsUI.getTool();
vNormalize(rayDir);
Tool rayTool = toolsUI.GetTool();
VNormalize(rayDir);
if (rayTool != null)
{
rayTool.handleClickRay(rayStart, rayDir, processHitTestShift);
rayTool.HandleClickRay(rayStart, rayDir, processHitTestShift);
}
if (hit.HasValue)
@ -624,7 +624,7 @@ public class RecastDemo
pos.z = rayStart.z + (rayEnd.z - rayStart.z) * hitTime;
if (rayTool != null)
{
rayTool.handleClick(rayStart, pos, processHitTestShift);
rayTool.HandleClick(rayStart, pos, processHitTestShift);
}
}
}
@ -641,26 +641,26 @@ public class RecastDemo
processHitTest = false;
}
if (sample.isChanged())
if (sample.IsChanged())
{
Vector3f? bminN = null;
Vector3f? bmaxN = null;
if (sample.getInputGeom() != null)
if (sample.GetInputGeom() != null)
{
bminN = sample.getInputGeom().getMeshBoundsMin();
bmaxN = sample.getInputGeom().getMeshBoundsMax();
bminN = sample.GetInputGeom().GetMeshBoundsMin();
bmaxN = sample.GetInputGeom().GetMeshBoundsMax();
}
else if (sample.getNavMesh() != null)
else if (sample.GetNavMesh() != null)
{
Vector3f[] bounds = NavMeshUtils.getNavMeshBounds(sample.getNavMesh());
Vector3f[] bounds = NavMeshUtils.GetNavMeshBounds(sample.GetNavMesh());
bminN = bounds[0];
bmaxN = bounds[1];
}
else if (0 < sample.getRecastResults().Count)
else if (0 < sample.GetRecastResults().Count)
{
foreach (RecastBuilderResult result in sample.getRecastResults())
foreach (RecastBuilderResult result in sample.GetRecastResults())
{
if (result.getSolidHeightfield() != null)
if (result.GetSolidHeightfield() != null)
{
if (bminN == null)
{
@ -669,15 +669,15 @@ public class RecastDemo
}
bminN = Vector3f.Of(
Math.Min(bminN.Value.x, result.getSolidHeightfield().bmin.x),
Math.Min(bminN.Value.y, result.getSolidHeightfield().bmin.y),
Math.Min(bminN.Value.z, result.getSolidHeightfield().bmin.z)
Math.Min(bminN.Value.x, result.GetSolidHeightfield().bmin.x),
Math.Min(bminN.Value.y, result.GetSolidHeightfield().bmin.y),
Math.Min(bminN.Value.z, result.GetSolidHeightfield().bmin.z)
);
bmaxN = Vector3f.Of(
Math.Max(bmaxN.Value.x, result.getSolidHeightfield().bmax.x),
Math.Max(bmaxN.Value.y, result.getSolidHeightfield().bmax.y),
Math.Max(bmaxN.Value.z, result.getSolidHeightfield().bmax.z)
Math.Max(bmaxN.Value.x, result.GetSolidHeightfield().bmax.x),
Math.Max(bmaxN.Value.y, result.GetSolidHeightfield().bmax.y),
Math.Max(bmaxN.Value.z, result.GetSolidHeightfield().bmax.z)
);
}
}
@ -689,7 +689,7 @@ public class RecastDemo
Vector3f bmax = bmaxN.Value;
camr = (float)(Math.Sqrt(
sqr(bmax.x - bmin.x) + sqr(bmax.y - bmin.y) + sqr(bmax.z - bmin.z))
Sqr(bmax.x - bmin.x) + Sqr(bmax.y - bmin.y) + Sqr(bmax.z - bmin.z))
/ 2);
cameraPos.x = (bmax.x + bmin.x) / 2 + camr;
cameraPos.y = (bmax.y + bmin.y) / 2 + camr;
@ -699,8 +699,8 @@ public class RecastDemo
cameraEulers[1] = -45;
}
sample.setChanged(false);
toolsUI.setSample(sample);
sample.SetChanged(false);
toolsUI.SetSample(sample);
}
@ -717,19 +717,19 @@ public class RecastDemo
private void OnWindowRender(double dt)
{
// Clear the screen
dd.clear();
projectionMatrix = dd.projectionMatrix(50f, (float)width / (float)height, 1.0f, camr);
modelviewMatrix = dd.viewMatrix(cameraPos, cameraEulers);
dd.Clear();
projectionMatrix = dd.ProjectionMatrix(50f, (float)width / (float)height, 1.0f, camr);
modelviewMatrix = dd.ViewMatrix(cameraPos, cameraEulers);
dd.fog(camr * 0.1f, camr * 1.25f);
renderer.render(sample);
Tool tool = toolsUI.getTool();
dd.Fog(camr * 0.1f, camr * 1.25f);
renderer.Render(sample);
Tool tool = toolsUI.GetTool();
if (tool != null)
{
tool.handleRender(renderer);
tool.HandleRender(renderer);
}
dd.fog(false);
dd.Fog(false);
_canvas.Draw(dt);
_mouseOverMenu = _canvas.IsMouseOverUI();

View File

@ -43,56 +43,56 @@ public class Sample
this.recastResults = recastResults;
this.navMesh = navMesh;
_settingsView = settingsView;
setQuery(navMesh);
SetQuery(navMesh);
changed = true;
}
private void setQuery(NavMesh navMesh)
private void SetQuery(NavMesh navMesh)
{
navMeshQuery = navMesh != null ? new NavMeshQuery(navMesh) : null;
}
public DemoInputGeomProvider getInputGeom()
public DemoInputGeomProvider GetInputGeom()
{
return inputGeom;
}
public IList<RecastBuilderResult> getRecastResults()
public IList<RecastBuilderResult> GetRecastResults()
{
return recastResults;
}
public NavMesh getNavMesh()
public NavMesh GetNavMesh()
{
return navMesh;
}
public RcSettingsView getSettingsUI()
public RcSettingsView GetSettingsUI()
{
return _settingsView;
}
public NavMeshQuery getNavMeshQuery()
public NavMeshQuery GetNavMeshQuery()
{
return navMeshQuery;
}
public bool isChanged()
public bool IsChanged()
{
return changed;
}
public void setChanged(bool changed)
public void SetChanged(bool changed)
{
this.changed = changed;
}
public void update(DemoInputGeomProvider geom, IList<RecastBuilderResult> recastResults, NavMesh navMesh)
public void Update(DemoInputGeomProvider geom, IList<RecastBuilderResult> recastResults, NavMesh navMesh)
{
inputGeom = geom;
this.recastResults = recastResults;
this.navMesh = navMesh;
setQuery(navMesh);
SetQuery(navMesh);
changed = true;
}
}

View File

@ -16,7 +16,7 @@ public class ConsoleTextWriterHook : TextWriter
public override void Write(char[] buffer, int index, int count)
{
var s = new string(new Span<char>(buffer, index, count));
var s = new String(new Span<char>(buffer, index, count));
_event?.Invoke(s);
}
}

View File

@ -42,14 +42,14 @@ public class ConvexVolumeTool : Tool
private readonly List<float> pts = new();
private readonly List<int> hull = new();
public override void setSample(Sample m_sample)
public override void SetSample(Sample m_sample)
{
sample = m_sample;
}
public override void handleClick(Vector3f s, Vector3f p, bool shift)
public override void HandleClick(Vector3f s, Vector3f p, bool shift)
{
DemoInputGeomProvider geom = sample.getInputGeom();
DemoInputGeomProvider geom = sample.GetInputGeom();
if (geom == null)
{
return;
@ -59,10 +59,10 @@ public class ConvexVolumeTool : Tool
{
// Delete
int nearestIndex = -1;
IList<ConvexVolume> vols = geom.convexVolumes();
IList<ConvexVolume> vols = geom.ConvexVolumes();
for (int i = 0; i < vols.Count; ++i)
{
if (PolyUtils.pointInPoly(vols[i].verts, p) && p.y >= vols[i].hmin
if (PolyUtils.PointInPoly(vols[i].verts, p) && p.y >= vols[i].hmin
&& p.y <= vols[i].hmax)
{
nearestIndex = i;
@ -72,7 +72,7 @@ public class ConvexVolumeTool : Tool
// If end point close enough, delete it.
if (nearestIndex != -1)
{
geom.convexVolumes().RemoveAt(nearestIndex);
geom.ConvexVolumes().RemoveAt(nearestIndex);
}
}
else
@ -80,7 +80,7 @@ public class ConvexVolumeTool : Tool
// Create
// If clicked on that last pt, create the shape.
if (pts.Count > 0 && RecastMath.vDistSqr(p, Vector3f.Of(pts[pts.Count - 3], pts[pts.Count - 2], pts[pts.Count - 1])) < 0.2f * 0.2f)
if (pts.Count > 0 && RecastMath.VDistSqr(p, Vector3f.Of(pts[pts.Count - 3], pts[pts.Count - 2], pts[pts.Count - 1])) < 0.2f * 0.2f)
{
if (hull.Count > 2)
{
@ -105,15 +105,15 @@ public class ConvexVolumeTool : Tool
if (polyOffset > 0.01f)
{
float[] offset = new float[verts.Length * 2];
int noffset = PolyUtils.offsetPoly(verts, hull.Count, polyOffset, offset, offset.Length);
int noffset = PolyUtils.OffsetPoly(verts, hull.Count, polyOffset, offset, offset.Length);
if (noffset > 0)
{
geom.addConvexVolume(ArrayUtils.CopyOf(offset, 0, noffset * 3), minh, maxh, areaType);
geom.AddConvexVolume(ArrayUtils.CopyOf(offset, 0, noffset * 3), minh, maxh, areaType);
}
}
else
{
geom.addConvexVolume(verts, minh, maxh, areaType);
geom.AddConvexVolume(verts, minh, maxh, areaType);
}
}
@ -130,7 +130,7 @@ public class ConvexVolumeTool : Tool
if (pts.Count > 3)
{
hull.Clear();
hull.AddRange(ConvexUtils.convexhull(pts));
hull.AddRange(ConvexUtils.Convexhull(pts));
}
else
{
@ -140,9 +140,9 @@ public class ConvexVolumeTool : Tool
}
}
public override void handleRender(NavMeshRenderer renderer)
public override void HandleRender(NavMeshRenderer renderer)
{
RecastDebugDraw dd = renderer.getDebugDraw();
RecastDebugDraw dd = renderer.GetDebugDraw();
// Find height extent of the shape.
float minh = float.MaxValue, maxh = 0;
for (int i = 0; i < pts.Count; i += 3)
@ -153,37 +153,37 @@ public class ConvexVolumeTool : Tool
minh -= boxDescent;
maxh = minh + boxHeight;
dd.begin(POINTS, 4.0f);
dd.Begin(POINTS, 4.0f);
for (int i = 0; i < pts.Count; i += 3)
{
int col = duRGBA(255, 255, 255, 255);
int col = DuRGBA(255, 255, 255, 255);
if (i == pts.Count - 3)
{
col = duRGBA(240, 32, 16, 255);
col = DuRGBA(240, 32, 16, 255);
}
dd.vertex(pts[i + 0], pts[i + 1] + 0.1f, pts[i + 2], col);
dd.Vertex(pts[i + 0], pts[i + 1] + 0.1f, pts[i + 2], col);
}
dd.end();
dd.End();
dd.begin(LINES, 2.0f);
dd.Begin(LINES, 2.0f);
for (int i = 0, j = hull.Count - 1; i < hull.Count; j = i++)
{
int vi = hull[j] * 3;
int vj = hull[i] * 3;
dd.vertex(pts[vj + 0], minh, pts[vj + 2], duRGBA(255, 255, 255, 64));
dd.vertex(pts[vi + 0], minh, pts[vi + 2], duRGBA(255, 255, 255, 64));
dd.vertex(pts[vj + 0], maxh, pts[vj + 2], duRGBA(255, 255, 255, 64));
dd.vertex(pts[vi + 0], maxh, pts[vi + 2], duRGBA(255, 255, 255, 64));
dd.vertex(pts[vj + 0], minh, pts[vj + 2], duRGBA(255, 255, 255, 64));
dd.vertex(pts[vj + 0], maxh, pts[vj + 2], duRGBA(255, 255, 255, 64));
dd.Vertex(pts[vj + 0], minh, pts[vj + 2], DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vi + 0], minh, pts[vi + 2], DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vj + 0], maxh, pts[vj + 2], DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vi + 0], maxh, pts[vi + 2], DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vj + 0], minh, pts[vj + 2], DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vj + 0], maxh, pts[vj + 2], DuRGBA(255, 255, 255, 64));
}
dd.end();
dd.End();
}
public override void layout()
public override void Layout()
{
ImGui.SliderFloat("Shape Height", ref boxHeight, 0.1f, 20f, "%.1f");
ImGui.SliderFloat("Shape Descent", ref boxDescent, 0.1f, 20f, "%.1f");
@ -217,20 +217,20 @@ public class ConvexVolumeTool : Tool
hull.Clear();
pts.Clear();
DemoInputGeomProvider geom = sample.getInputGeom();
DemoInputGeomProvider geom = sample.GetInputGeom();
if (geom != null)
{
geom.clearConvexVolumes();
geom.ClearConvexVolumes();
}
}
}
public override string getName()
public override string GetName()
{
return "Create Convex Volumes";
}
public override void handleUpdate(float dt)
public override void HandleUpdate(float dt)
{
// TODO Auto-generated method stub
}

View File

@ -57,7 +57,7 @@ public class CrowdProfilingTool
this.agentParamsSupplier = agentParamsSupplier;
}
public void layout()
public void Layout()
{
ImGui.Text("Simulation Options");
ImGui.Separator();
@ -80,18 +80,18 @@ public class CrowdProfilingTool
if (navMesh != null)
{
rnd = new FRand(randomSeed);
createCrowd();
createZones();
CreateCrowd();
CreateZones();
NavMeshQuery navquery = new NavMeshQuery(navMesh);
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < agents; i++)
{
float tr = rnd.frand();
float tr = rnd.Frand();
AgentType type = AgentType.MOB;
float mobsPcnt = percentMobs / 100f;
if (tr > mobsPcnt)
{
tr = rnd.frand();
tr = rnd.Frand();
float travellerPcnt = percentTravellers / 100f;
if (tr > travellerPcnt)
{
@ -107,19 +107,19 @@ public class CrowdProfilingTool
switch (type)
{
case AgentType.MOB:
pos = getMobPosition(navquery, filter);
pos = GetMobPosition(navquery, filter);
break;
case AgentType.VILLAGER:
pos = getVillagerPosition(navquery, filter);
pos = GetVillagerPosition(navquery, filter);
break;
case AgentType.TRAVELLER:
pos = getVillagerPosition(navquery, filter);
pos = GetVillagerPosition(navquery, filter);
break;
}
if (pos != null)
{
addAgent(pos.Value, type);
AddAgent(pos.Value, type);
}
}
}
@ -129,10 +129,10 @@ public class CrowdProfilingTool
ImGui.Separator();
if (crowd != null)
{
ImGui.Text($"Max time to enqueue request: {crowd.telemetry().maxTimeToEnqueueRequest()} s");
ImGui.Text($"Max time to find path: {crowd.telemetry().maxTimeToFindPath()} s");
List<Tuple<string, long>> timings = crowd.telemetry()
.executionTimings()
ImGui.Text($"Max time to enqueue request: {crowd.Telemetry().MaxTimeToEnqueueRequest()} s");
ImGui.Text($"Max time to find path: {crowd.Telemetry().MaxTimeToFindPath()} s");
List<Tuple<string, long>> timings = crowd.Telemetry()
.ExecutionTimings()
.Select(e => Tuple.Create(e.Key, e.Value))
.OrderBy(x => x.Item2)
.ToList();
@ -146,34 +146,34 @@ public class CrowdProfilingTool
}
}
private Vector3f? getMobPosition(NavMeshQuery navquery, QueryFilter filter)
private Vector3f? GetMobPosition(NavMeshQuery navquery, QueryFilter filter)
{
Result<FindRandomPointResult> result = navquery.findRandomPoint(filter, rnd);
Result<FindRandomPointResult> result = navquery.FindRandomPoint(filter, rnd);
if (result.Succeeded())
{
return result.result.getRandomPt();
return result.result.GetRandomPt();
}
return null;
}
private Vector3f? getVillagerPosition(NavMeshQuery navquery, QueryFilter filter)
private Vector3f? GetVillagerPosition(NavMeshQuery navquery, QueryFilter filter)
{
if (0 < zones.Count)
{
int zone = (int)(rnd.frand() * zones.Count);
Result<FindRandomPointResult> result = navquery.findRandomPointWithinCircle(zones[zone].getRandomRef(),
zones[zone].getRandomPt(), zoneRadius, filter, rnd);
int zone = (int)(rnd.Frand() * zones.Count);
Result<FindRandomPointResult> result = navquery.FindRandomPointWithinCircle(zones[zone].GetRandomRef(),
zones[zone].GetRandomPt(), zoneRadius, filter, rnd);
if (result.Succeeded())
{
return result.result.getRandomPt();
return result.result.GetRandomPt();
}
}
return null;
}
private void createZones()
private void CreateZones()
{
zones.Clear();
QueryFilter filter = new DefaultQueryFilter();
@ -183,13 +183,13 @@ public class CrowdProfilingTool
float zoneSeparation = zoneRadius * zoneRadius * 16;
for (int k = 0; k < 100; k++)
{
Result<FindRandomPointResult> result = navquery.findRandomPoint(filter, rnd);
Result<FindRandomPointResult> result = navquery.FindRandomPoint(filter, rnd);
if (result.Succeeded())
{
bool valid = true;
foreach (FindRandomPointResult zone in zones)
{
if (RecastMath.vDistSqr(zone.getRandomPt(), result.result.getRandomPt()) < zoneSeparation)
if (RecastMath.VDistSqr(zone.GetRandomPt(), result.result.GetRandomPt()) < zoneSeparation)
{
valid = false;
break;
@ -206,46 +206,46 @@ public class CrowdProfilingTool
}
}
private void createCrowd()
private void CreateCrowd()
{
crowd = new Crowd(config, navMesh, __ => new DefaultQueryFilter(SampleAreaModifications.SAMPLE_POLYFLAGS_ALL,
SampleAreaModifications.SAMPLE_POLYFLAGS_DISABLED, new float[] { 1f, 10f, 1f, 1f, 2f, 1.5f }));
ObstacleAvoidanceParams option = new ObstacleAvoidanceParams(crowd.getObstacleAvoidanceParams(0));
ObstacleAvoidanceParams option = new ObstacleAvoidanceParams(crowd.GetObstacleAvoidanceParams(0));
// Low (11)
option.velBias = 0.5f;
option.adaptiveDivs = 5;
option.adaptiveRings = 2;
option.adaptiveDepth = 1;
crowd.setObstacleAvoidanceParams(0, option);
crowd.SetObstacleAvoidanceParams(0, option);
// Medium (22)
option.velBias = 0.5f;
option.adaptiveDivs = 5;
option.adaptiveRings = 2;
option.adaptiveDepth = 2;
crowd.setObstacleAvoidanceParams(1, option);
crowd.SetObstacleAvoidanceParams(1, option);
// Good (45)
option.velBias = 0.5f;
option.adaptiveDivs = 7;
option.adaptiveRings = 2;
option.adaptiveDepth = 3;
crowd.setObstacleAvoidanceParams(2, option);
crowd.SetObstacleAvoidanceParams(2, option);
// High (66)
option.velBias = 0.5f;
option.adaptiveDivs = 7;
option.adaptiveRings = 3;
option.adaptiveDepth = 3;
crowd.setObstacleAvoidanceParams(3, option);
crowd.SetObstacleAvoidanceParams(3, option);
}
public void update(float dt)
public void Update(float dt)
{
long startTime = FrequencyWatch.Ticks;
if (crowd != null)
{
crowd.config().pathQueueSize = pathQueueSize;
crowd.config().maxFindPathIterations = maxIterations;
crowd.update(dt, null);
crowd.Config().pathQueueSize = pathQueueSize;
crowd.Config().maxFindPathIterations = maxIterations;
crowd.Update(dt, null);
}
long endTime = FrequencyWatch.Ticks;
@ -253,21 +253,21 @@ public class CrowdProfilingTool
{
NavMeshQuery navquery = new NavMeshQuery(navMesh);
QueryFilter filter = new DefaultQueryFilter();
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
if (needsNewTarget(ag))
if (NeedsNewTarget(ag))
{
AgentData agentData = (AgentData)ag.option.userData;
switch (agentData.type)
{
case AgentType.MOB:
moveMob(navquery, filter, ag, agentData);
MoveMob(navquery, filter, ag, agentData);
break;
case AgentType.VILLAGER:
moveVillager(navquery, filter, ag, agentData);
MoveVillager(navquery, filter, ag, agentData);
break;
case AgentType.TRAVELLER:
moveTraveller(navquery, filter, ag, agentData);
MoveTraveller(navquery, filter, ag, agentData);
break;
}
}
@ -277,43 +277,43 @@ public class CrowdProfilingTool
crowdUpdateTime = (endTime - startTime) / TimeSpan.TicksPerMillisecond;
}
private void moveMob(NavMeshQuery navquery, QueryFilter filter, CrowdAgent ag, AgentData agentData)
private void MoveMob(NavMeshQuery navquery, QueryFilter filter, CrowdAgent ag, AgentData agentData)
{
// Move somewhere
Result<FindNearestPolyResult> nearestPoly = navquery.findNearestPoly(ag.npos, crowd.getQueryExtents(), filter);
Result<FindNearestPolyResult> nearestPoly = navquery.FindNearestPoly(ag.npos, crowd.GetQueryExtents(), filter);
if (nearestPoly.Succeeded())
{
Result<FindRandomPointResult> result = navquery.findRandomPointAroundCircle(nearestPoly.result.getNearestRef(),
Result<FindRandomPointResult> result = navquery.FindRandomPointAroundCircle(nearestPoly.result.GetNearestRef(),
agentData.home, zoneRadius * 2f, filter, rnd);
if (result.Succeeded())
{
crowd.requestMoveTarget(ag, result.result.getRandomRef(), result.result.getRandomPt());
crowd.RequestMoveTarget(ag, result.result.GetRandomRef(), result.result.GetRandomPt());
}
}
}
private void moveVillager(NavMeshQuery navquery, QueryFilter filter, CrowdAgent ag, AgentData agentData)
private void MoveVillager(NavMeshQuery navquery, QueryFilter filter, CrowdAgent ag, AgentData agentData)
{
// Move somewhere close
Result<FindNearestPolyResult> nearestPoly = navquery.findNearestPoly(ag.npos, crowd.getQueryExtents(), filter);
Result<FindNearestPolyResult> nearestPoly = navquery.FindNearestPoly(ag.npos, crowd.GetQueryExtents(), filter);
if (nearestPoly.Succeeded())
{
Result<FindRandomPointResult> result = navquery.findRandomPointAroundCircle(nearestPoly.result.getNearestRef(),
Result<FindRandomPointResult> result = navquery.FindRandomPointAroundCircle(nearestPoly.result.GetNearestRef(),
agentData.home, zoneRadius * 0.2f, filter, rnd);
if (result.Succeeded())
{
crowd.requestMoveTarget(ag, result.result.getRandomRef(), result.result.getRandomPt());
crowd.RequestMoveTarget(ag, result.result.GetRandomRef(), result.result.GetRandomPt());
}
}
}
private void moveTraveller(NavMeshQuery navquery, QueryFilter filter, CrowdAgent ag, AgentData agentData)
private void MoveTraveller(NavMeshQuery navquery, QueryFilter filter, CrowdAgent ag, AgentData agentData)
{
// Move to another zone
List<FindRandomPointResult> potentialTargets = new();
foreach (FindRandomPointResult zone in zones)
{
if (RecastMath.vDistSqr(zone.getRandomPt(), ag.npos) > zoneRadius * zoneRadius)
if (RecastMath.VDistSqr(zone.GetRandomPt(), ag.npos) > zoneRadius * zoneRadius)
{
potentialTargets.Add(zone);
}
@ -322,11 +322,11 @@ public class CrowdProfilingTool
if (0 < potentialTargets.Count)
{
potentialTargets.Shuffle();
crowd.requestMoveTarget(ag, potentialTargets[0].getRandomRef(), potentialTargets[0].getRandomPt());
crowd.RequestMoveTarget(ag, potentialTargets[0].GetRandomRef(), potentialTargets[0].GetRandomPt());
}
}
private bool needsNewTarget(CrowdAgent ag)
private bool NeedsNewTarget(CrowdAgent ag)
{
if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_NONE
|| ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_FAILED)
@ -345,7 +345,7 @@ public class CrowdProfilingTool
return false;
}
public void setup(float maxAgentRadius, NavMesh nav)
public void Setup(float maxAgentRadius, NavMesh nav)
{
navMesh = nav;
if (nav != null)
@ -354,20 +354,20 @@ public class CrowdProfilingTool
}
}
public void handleRender(NavMeshRenderer renderer)
public void HandleRender(NavMeshRenderer renderer)
{
RecastDebugDraw dd = renderer.getDebugDraw();
dd.depthMask(false);
RecastDebugDraw dd = renderer.GetDebugDraw();
dd.DepthMask(false);
if (crowd != null)
{
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
float radius = ag.option.radius;
Vector3f pos = ag.npos;
dd.debugDrawCircle(pos.x, pos.y, pos.z, radius, duRGBA(0, 0, 0, 32), 2.0f);
dd.DebugDrawCircle(pos.x, pos.y, pos.z, radius, DuRGBA(0, 0, 0, 32), 2.0f);
}
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
AgentData agentData = (AgentData)ag.option.userData;
@ -375,40 +375,40 @@ public class CrowdProfilingTool
float radius = ag.option.radius;
Vector3f pos = ag.npos;
int col = duRGBA(220, 220, 220, 128);
int col = DuRGBA(220, 220, 220, 128);
if (agentData.type == AgentType.TRAVELLER)
{
col = duRGBA(100, 160, 100, 128);
col = DuRGBA(100, 160, 100, 128);
}
if (agentData.type == AgentType.VILLAGER)
{
col = duRGBA(120, 80, 160, 128);
col = DuRGBA(120, 80, 160, 128);
}
if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING
|| ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE)
col = duLerpCol(col, duRGBA(255, 255, 32, 128), 128);
col = DuLerpCol(col, DuRGBA(255, 255, 32, 128), 128);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_WAITING_FOR_PATH)
col = duLerpCol(col, duRGBA(255, 64, 32, 128), 128);
col = DuLerpCol(col, DuRGBA(255, 64, 32, 128), 128);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_FAILED)
col = duRGBA(255, 32, 16, 128);
col = DuRGBA(255, 32, 16, 128);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_VELOCITY)
col = duLerpCol(col, duRGBA(64, 255, 0, 128), 128);
col = DuLerpCol(col, DuRGBA(64, 255, 0, 128), 128);
dd.debugDrawCylinder(pos.x - radius, pos.y + radius * 0.1f, pos.z - radius, pos.x + radius, pos.y + height,
dd.DebugDrawCylinder(pos.x - radius, pos.y + radius * 0.1f, pos.z - radius, pos.x + radius, pos.y + height,
pos.z + radius, col);
}
}
dd.depthMask(true);
dd.DepthMask(true);
}
private CrowdAgent addAgent(Vector3f p, AgentType type)
private CrowdAgent AddAgent(Vector3f p, AgentType type)
{
CrowdAgentParams ap = agentParamsSupplier.Invoke();
ap.userData = new AgentData(type, p);
return crowd.addAgent(p, ap);
return crowd.AddAgent(p, ap);
}
public enum AgentType
@ -430,11 +430,11 @@ public class CrowdProfilingTool
}
}
public void updateAgentParams(int updateFlags, int obstacleAvoidanceType, float separationWeight)
public void UpdateAgentParams(int updateFlags, int obstacleAvoidanceType, float separationWeight)
{
if (crowd != null)
{
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
CrowdAgentParams option = new CrowdAgentParams();
option.radius = ag.option.radius;
@ -448,7 +448,7 @@ public class CrowdProfilingTool
option.updateFlags = updateFlags;
option.obstacleAvoidanceType = obstacleAvoidanceType;
option.separationWeight = separationWeight;
crowd.updateAgentParameters(ag, option);
crowd.UpdateAgentParameters(ag, option);
}
}
}

View File

@ -89,51 +89,51 @@ public class CrowdTool : Tool
public CrowdTool()
{
m_agentDebug.vod = new ObstacleAvoidanceDebugData(2048);
profilingTool = new CrowdProfilingTool(getAgentParams);
profilingTool = new CrowdProfilingTool(GetAgentParams);
}
public override void setSample(Sample psample)
public override void SetSample(Sample psample)
{
if (sample != psample)
{
sample = psample;
}
NavMesh nav = sample.getNavMesh();
NavMesh nav = sample.GetNavMesh();
if (nav != null && m_nav != nav)
{
m_nav = nav;
CrowdConfig config = new CrowdConfig(sample.getSettingsUI().getAgentRadius());
CrowdConfig config = new CrowdConfig(sample.GetSettingsUI().GetAgentRadius());
crowd = new Crowd(config, nav, __ => new DefaultQueryFilter(SampleAreaModifications.SAMPLE_POLYFLAGS_ALL,
SampleAreaModifications.SAMPLE_POLYFLAGS_DISABLED, new float[] { 1f, 10f, 1f, 1f, 2f, 1.5f }));
// Setup local avoidance option to different qualities.
// Use mostly default settings, copy from dtCrowd.
ObstacleAvoidanceParams option = new ObstacleAvoidanceParams(crowd.getObstacleAvoidanceParams(0));
ObstacleAvoidanceParams option = new ObstacleAvoidanceParams(crowd.GetObstacleAvoidanceParams(0));
// Low (11)
option.velBias = 0.5f;
option.adaptiveDivs = 5;
option.adaptiveRings = 2;
option.adaptiveDepth = 1;
crowd.setObstacleAvoidanceParams(0, option);
crowd.SetObstacleAvoidanceParams(0, option);
// Medium (22)
option.velBias = 0.5f;
option.adaptiveDivs = 5;
option.adaptiveRings = 2;
option.adaptiveDepth = 2;
crowd.setObstacleAvoidanceParams(1, option);
crowd.SetObstacleAvoidanceParams(1, option);
// Good (45)
option.velBias = 0.5f;
option.adaptiveDivs = 7;
option.adaptiveRings = 2;
option.adaptiveDepth = 3;
crowd.setObstacleAvoidanceParams(2, option);
crowd.SetObstacleAvoidanceParams(2, option);
// High (66)
option.velBias = 0.5f;
@ -141,13 +141,13 @@ public class CrowdTool : Tool
option.adaptiveRings = 3;
option.adaptiveDepth = 3;
crowd.setObstacleAvoidanceParams(3, option);
crowd.SetObstacleAvoidanceParams(3, option);
profilingTool.setup(sample.getSettingsUI().getAgentRadius(), m_nav);
profilingTool.Setup(sample.GetSettingsUI().GetAgentRadius(), m_nav);
}
}
public override void handleClick(Vector3f s, Vector3f p, bool shift)
public override void HandleClick(Vector3f s, Vector3f p, bool shift)
{
if (m_mode == CrowdToolMode.PROFILING)
{
@ -164,67 +164,67 @@ public class CrowdTool : Tool
if (shift)
{
// Delete
CrowdAgent ahit = hitTestAgents(s, p);
CrowdAgent ahit = HitTestAgents(s, p);
if (ahit != null)
{
removeAgent(ahit);
RemoveAgent(ahit);
}
}
else
{
// Add
addAgent(p);
AddAgent(p);
}
}
else if (m_mode == CrowdToolMode.MOVE_TARGET)
{
setMoveTarget(p, shift);
SetMoveTarget(p, shift);
}
else if (m_mode == CrowdToolMode.SELECT)
{
// Highlight
CrowdAgent ahit = hitTestAgents(s, p);
hilightAgent(ahit);
CrowdAgent ahit = HitTestAgents(s, p);
HilightAgent(ahit);
}
else if (m_mode == CrowdToolMode.TOGGLE_POLYS)
{
NavMesh nav = sample.getNavMesh();
NavMeshQuery navquery = sample.getNavMeshQuery();
NavMesh nav = sample.GetNavMesh();
NavMeshQuery navquery = sample.GetNavMeshQuery();
if (nav != null && navquery != null)
{
QueryFilter filter = new DefaultQueryFilter();
Vector3f halfExtents = crowd.getQueryExtents();
Result<FindNearestPolyResult> result = navquery.findNearestPoly(p, halfExtents, filter);
long refs = result.result.getNearestRef();
Vector3f halfExtents = crowd.GetQueryExtents();
Result<FindNearestPolyResult> result = navquery.FindNearestPoly(p, halfExtents, filter);
long refs = result.result.GetNearestRef();
if (refs != 0)
{
Result<int> flags = nav.getPolyFlags(refs);
Result<int> flags = nav.GetPolyFlags(refs);
if (flags.Succeeded())
{
nav.setPolyFlags(refs, flags.result ^ SampleAreaModifications.SAMPLE_POLYFLAGS_DISABLED);
nav.SetPolyFlags(refs, flags.result ^ SampleAreaModifications.SAMPLE_POLYFLAGS_DISABLED);
}
}
}
}
}
private void removeAgent(CrowdAgent agent)
private void RemoveAgent(CrowdAgent agent)
{
crowd.removeAgent(agent);
crowd.RemoveAgent(agent);
if (agent == m_agentDebug.agent)
{
m_agentDebug.agent = null;
}
}
private void addAgent(Vector3f p)
private void AddAgent(Vector3f p)
{
CrowdAgentParams ap = getAgentParams();
CrowdAgent ag = crowd.addAgent(p, ap);
CrowdAgentParams ap = GetAgentParams();
CrowdAgent ag = crowd.AddAgent(p, ap);
if (ag != null)
{
if (m_targetRef != 0)
crowd.requestMoveTarget(ag, m_targetRef, m_targetPos);
crowd.RequestMoveTarget(ag, m_targetRef, m_targetPos);
// Init trail
if (!m_trails.TryGetValue(ag.idx, out var trail))
@ -244,32 +244,32 @@ public class CrowdTool : Tool
}
}
private CrowdAgentParams getAgentParams()
private CrowdAgentParams GetAgentParams()
{
CrowdAgentParams ap = new CrowdAgentParams();
ap.radius = sample.getSettingsUI().getAgentRadius();
ap.height = sample.getSettingsUI().getAgentHeight();
ap.radius = sample.GetSettingsUI().GetAgentRadius();
ap.height = sample.GetSettingsUI().GetAgentHeight();
ap.maxAcceleration = 8.0f;
ap.maxSpeed = 3.5f;
ap.collisionQueryRange = ap.radius * 12.0f;
ap.pathOptimizationRange = ap.radius * 30.0f;
ap.updateFlags = getUpdateFlags();
ap.updateFlags = GetUpdateFlags();
ap.obstacleAvoidanceType = toolParams.m_obstacleAvoidanceType;
ap.separationWeight = toolParams.m_separationWeight;
return ap;
}
private CrowdAgent hitTestAgents(Vector3f s, Vector3f p)
private CrowdAgent HitTestAgents(Vector3f s, Vector3f p)
{
CrowdAgent isel = null;
float tsel = float.MaxValue;
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f();
getAgentBounds(ag, ref bmin, ref bmax);
float[] isect = Intersections.intersectSegmentAABB(s, p, bmin, bmax);
GetAgentBounds(ag, ref bmin, ref bmax);
float[] isect = Intersections.IntersectSegmentAABB(s, p, bmin, bmax);
if (null != isect)
{
float tmin = isect[0];
@ -284,7 +284,7 @@ public class CrowdTool : Tool
return isel;
}
private void getAgentBounds(CrowdAgent ag, ref Vector3f bmin, ref Vector3f bmax)
private void GetAgentBounds(CrowdAgent ag, ref Vector3f bmin, ref Vector3f bmax)
{
Vector3f p = ag.npos;
float r = ag.option.radius;
@ -297,141 +297,141 @@ public class CrowdTool : Tool
bmax.z = p.z + r;
}
private void setMoveTarget(Vector3f p, bool adjust)
private void SetMoveTarget(Vector3f p, bool adjust)
{
if (sample == null || crowd == null)
return;
// Find nearest point on navmesh and set move request to that location.
NavMeshQuery navquery = sample.getNavMeshQuery();
QueryFilter filter = crowd.getFilter(0);
Vector3f halfExtents = crowd.getQueryExtents();
NavMeshQuery navquery = sample.GetNavMeshQuery();
QueryFilter filter = crowd.GetFilter(0);
Vector3f halfExtents = crowd.GetQueryExtents();
if (adjust)
{
// Request velocity
if (m_agentDebug.agent != null)
{
Vector3f vel = calcVel(m_agentDebug.agent.npos, p, m_agentDebug.agent.option.maxSpeed);
crowd.requestMoveVelocity(m_agentDebug.agent, vel);
Vector3f vel = CalcVel(m_agentDebug.agent.npos, p, m_agentDebug.agent.option.maxSpeed);
crowd.RequestMoveVelocity(m_agentDebug.agent, vel);
}
else
{
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Vector3f vel = calcVel(ag.npos, p, ag.option.maxSpeed);
crowd.requestMoveVelocity(ag, vel);
Vector3f vel = CalcVel(ag.npos, p, ag.option.maxSpeed);
crowd.RequestMoveVelocity(ag, vel);
}
}
}
else
{
Result<FindNearestPolyResult> result = navquery.findNearestPoly(p, halfExtents, filter);
m_targetRef = result.result.getNearestRef();
m_targetPos = result.result.getNearestPos();
Result<FindNearestPolyResult> result = navquery.FindNearestPoly(p, halfExtents, filter);
m_targetRef = result.result.GetNearestRef();
m_targetPos = result.result.GetNearestPos();
if (m_agentDebug.agent != null)
{
crowd.requestMoveTarget(m_agentDebug.agent, m_targetRef, m_targetPos);
crowd.RequestMoveTarget(m_agentDebug.agent, m_targetRef, m_targetPos);
}
else
{
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
crowd.requestMoveTarget(ag, m_targetRef, m_targetPos);
crowd.RequestMoveTarget(ag, m_targetRef, m_targetPos);
}
}
}
}
private Vector3f calcVel(Vector3f pos, Vector3f tgt, float speed)
private Vector3f CalcVel(Vector3f pos, Vector3f tgt, float speed)
{
Vector3f vel = vSub(tgt, pos);
Vector3f vel = VSub(tgt, pos);
vel.y = 0.0f;
vNormalize(ref vel);
return vScale(vel, speed);
VNormalize(ref vel);
return VScale(vel, speed);
}
public override void handleRender(NavMeshRenderer renderer)
public override void HandleRender(NavMeshRenderer renderer)
{
if (m_mode == CrowdToolMode.PROFILING)
{
profilingTool.handleRender(renderer);
profilingTool.HandleRender(renderer);
return;
}
RecastDebugDraw dd = renderer.getDebugDraw();
float rad = sample.getSettingsUI().getAgentRadius();
NavMesh nav = sample.getNavMesh();
RecastDebugDraw dd = renderer.GetDebugDraw();
float rad = sample.GetSettingsUI().GetAgentRadius();
NavMesh nav = sample.GetNavMesh();
if (nav == null || crowd == null)
return;
if (toolParams.m_showNodes && crowd.getPathQueue() != null)
if (toolParams.m_showNodes && crowd.GetPathQueue() != null)
{
// NavMeshQuery navquery = crowd.getPathQueue().getNavQuery();
// NavMeshQuery navquery = crowd.GetPathQueue().GetNavQuery();
// if (navquery != null) {
// dd.debugDrawNavMeshNodes(navquery);
// dd.DebugDrawNavMeshNodes(navquery);
// }
}
dd.depthMask(false);
dd.DepthMask(false);
// Draw paths
if (toolParams.m_showPath)
{
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
if (!toolParams.m_showDetailAll && ag != m_agentDebug.agent)
continue;
List<long> path = ag.corridor.getPath();
int npath = ag.corridor.getPathCount();
List<long> path = ag.corridor.GetPath();
int npath = ag.corridor.GetPathCount();
for (int j = 0; j < npath; ++j)
{
dd.debugDrawNavMeshPoly(nav, path[j], duRGBA(255, 255, 255, 24));
dd.DebugDrawNavMeshPoly(nav, path[j], DuRGBA(255, 255, 255, 24));
}
}
}
if (m_targetRef != 0)
dd.debugDrawCross(m_targetPos.x, m_targetPos.y + 0.1f, m_targetPos.z, rad, duRGBA(255, 255, 255, 192), 2.0f);
dd.DebugDrawCross(m_targetPos.x, m_targetPos.y + 0.1f, m_targetPos.z, rad, DuRGBA(255, 255, 255, 192), 2.0f);
// Occupancy grid.
if (toolParams.m_showGrid)
{
float gridy = -float.MaxValue;
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Vector3f pos = ag.corridor.getPos();
Vector3f pos = ag.corridor.GetPos();
gridy = Math.Max(gridy, pos.y);
}
gridy += 1.0f;
dd.begin(QUADS);
ProximityGrid grid = crowd.getGrid();
dd.Begin(QUADS);
ProximityGrid grid = crowd.GetGrid();
float cs = grid.GetCellSize();
foreach (var (combinedKey, count) in grid.GetItemCounts())
{
ProximityGrid.DecomposeKey(combinedKey, out var x, out var y);
if (count != 0)
{
int col = duRGBA(128, 0, 0, Math.Min(count * 40, 255));
dd.vertex(x * cs, gridy, y * cs, col);
dd.vertex(x * cs, gridy, y * cs + cs, col);
dd.vertex(x * cs + cs, gridy, y * cs + cs, col);
dd.vertex(x * cs + cs, gridy, y * cs, col);
int col = DuRGBA(128, 0, 0, Math.Min(count * 40, 255));
dd.Vertex(x * cs, gridy, y * cs, col);
dd.Vertex(x * cs, gridy, y * cs + cs, col);
dd.Vertex(x * cs + cs, gridy, y * cs + cs, col);
dd.Vertex(x * cs + cs, gridy, y * cs, col);
}
}
dd.end();
dd.End();
}
// Trail
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
AgentTrail trail = m_trails[ag.idx];
Vector3f pos = ag.npos;
dd.begin(LINES, 3.0f);
dd.Begin(LINES, 3.0f);
Vector3f prev = new Vector3f();
float preva = 1;
prev = pos;
@ -440,17 +440,17 @@ public class CrowdTool : Tool
int idx = (trail.htrail + AGENT_MAX_TRAIL - j) % AGENT_MAX_TRAIL;
int v = idx * 3;
float a = 1 - j / (float)AGENT_MAX_TRAIL;
dd.vertex(prev.x, prev.y + 0.1f, prev.z, duRGBA(0, 0, 0, (int)(128 * preva)));
dd.vertex(trail.trail[v], trail.trail[v + 1] + 0.1f, trail.trail[v + 2], duRGBA(0, 0, 0, (int)(128 * a)));
dd.Vertex(prev.x, prev.y + 0.1f, prev.z, DuRGBA(0, 0, 0, (int)(128 * preva)));
dd.Vertex(trail.trail[v], trail.trail[v + 1] + 0.1f, trail.trail[v + 2], DuRGBA(0, 0, 0, (int)(128 * a)));
preva = a;
vCopy(ref prev, trail.trail, v);
VCopy(ref prev, trail.trail, v);
}
dd.end();
dd.End();
}
// Corners & co
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
if (toolParams.m_showDetailAll == false && ag != m_agentDebug.agent)
continue;
@ -462,29 +462,29 @@ public class CrowdTool : Tool
{
if (0 < ag.corners.Count)
{
dd.begin(LINES, 2.0f);
dd.Begin(LINES, 2.0f);
for (int j = 0; j < ag.corners.Count; ++j)
{
Vector3f va = j == 0 ? pos : ag.corners[j - 1].getPos();
Vector3f vb = ag.corners[j].getPos();
dd.vertex(va.x, va.y + radius, va.z, duRGBA(128, 0, 0, 192));
dd.vertex(vb.x, vb.y + radius, vb.z, duRGBA(128, 0, 0, 192));
Vector3f va = j == 0 ? pos : ag.corners[j - 1].GetPos();
Vector3f vb = ag.corners[j].GetPos();
dd.Vertex(va.x, va.y + radius, va.z, DuRGBA(128, 0, 0, 192));
dd.Vertex(vb.x, vb.y + radius, vb.z, DuRGBA(128, 0, 0, 192));
}
if ((ag.corners[ag.corners.Count - 1].getFlags()
if ((ag.corners[ag.corners.Count - 1].GetFlags()
& NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
{
Vector3f v = ag.corners[ag.corners.Count - 1].getPos();
dd.vertex(v.x, v.y, v.z, duRGBA(192, 0, 0, 192));
dd.vertex(v.x, v.y + radius * 2, v.z, duRGBA(192, 0, 0, 192));
Vector3f v = ag.corners[ag.corners.Count - 1].GetPos();
dd.Vertex(v.x, v.y, v.z, DuRGBA(192, 0, 0, 192));
dd.Vertex(v.x, v.y + radius * 2, v.z, DuRGBA(192, 0, 0, 192));
}
dd.end();
dd.End();
if (toolParams.m_anticipateTurns)
{
/* float dvel[3], pos[3];
calcSmoothSteerDirection(ag.pos, ag.cornerVerts, ag.ncorners, dvel);
CalcSmoothSteerDirection(ag.pos, ag.cornerVerts, ag.ncorners, dvel);
pos.x = ag.pos.x + dvel.x;
pos.y = ag.pos.y + dvel.y;
pos.z = ag.pos.z + dvel.z;
@ -493,107 +493,107 @@ public class CrowdTool : Tool
float[] tgt = &ag.cornerVerts.x;
float y = ag.pos.y+off;
dd.begin(DU_DRAW_LINES, 2.0f);
dd.Begin(DU_DRAW_LINES, 2.0f);
dd.vertex(ag.pos.x,y,ag.pos.z, duRGBA(255,0,0,192));
dd.vertex(pos.x,y,pos.z, duRGBA(255,0,0,192));
dd.Vertex(ag.pos.x,y,ag.pos.z, DuRGBA(255,0,0,192));
dd.Vertex(pos.x,y,pos.z, DuRGBA(255,0,0,192));
dd.vertex(pos.x,y,pos.z, duRGBA(255,0,0,192));
dd.vertex(tgt.x,y,tgt.z, duRGBA(255,0,0,192));
dd.Vertex(pos.x,y,pos.z, DuRGBA(255,0,0,192));
dd.Vertex(tgt.x,y,tgt.z, DuRGBA(255,0,0,192));
dd.end();*/
dd.End();*/
}
}
}
if (toolParams.m_showCollisionSegments)
{
Vector3f center = ag.boundary.getCenter();
dd.debugDrawCross(center.x, center.y + radius, center.z, 0.2f, duRGBA(192, 0, 128, 255), 2.0f);
dd.debugDrawCircle(center.x, center.y + radius, center.z, ag.option.collisionQueryRange, duRGBA(192, 0, 128, 128), 2.0f);
Vector3f center = ag.boundary.GetCenter();
dd.DebugDrawCross(center.x, center.y + radius, center.z, 0.2f, DuRGBA(192, 0, 128, 255), 2.0f);
dd.DebugDrawCircle(center.x, center.y + radius, center.z, ag.option.collisionQueryRange, DuRGBA(192, 0, 128, 128), 2.0f);
dd.begin(LINES, 3.0f);
for (int j = 0; j < ag.boundary.getSegmentCount(); ++j)
dd.Begin(LINES, 3.0f);
for (int j = 0; j < ag.boundary.GetSegmentCount(); ++j)
{
int col = duRGBA(192, 0, 128, 192);
Vector3f[] s = ag.boundary.getSegment(j);
int col = DuRGBA(192, 0, 128, 192);
Vector3f[] s = ag.boundary.GetSegment(j);
Vector3f s0 = s[0];
Vector3f s3 = s[1];
if (triArea2D(pos, s0, s3) < 0.0f)
col = duDarkenCol(col);
if (TriArea2D(pos, s0, s3) < 0.0f)
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);
}
dd.end();
dd.End();
}
if (toolParams.m_showNeis)
{
dd.debugDrawCircle(pos.x, pos.y + radius, pos.z, ag.option.collisionQueryRange, duRGBA(0, 192, 128, 128),
dd.DebugDrawCircle(pos.x, pos.y + radius, pos.z, ag.option.collisionQueryRange, DuRGBA(0, 192, 128, 128),
2.0f);
dd.begin(LINES, 2.0f);
dd.Begin(LINES, 2.0f);
for (int j = 0; j < ag.neis.Count; ++j)
{
CrowdAgent nei = ag.neis[j].agent;
if (nei != null)
{
dd.vertex(pos.x, pos.y + radius, pos.z, duRGBA(0, 192, 128, 128));
dd.vertex(nei.npos.x, nei.npos.y + radius, nei.npos.z, duRGBA(0, 192, 128, 128));
dd.Vertex(pos.x, pos.y + radius, pos.z, DuRGBA(0, 192, 128, 128));
dd.Vertex(nei.npos.x, nei.npos.y + radius, nei.npos.z, DuRGBA(0, 192, 128, 128));
}
}
dd.end();
dd.End();
}
if (toolParams.m_showOpt)
{
dd.begin(LINES, 2.0f);
dd.vertex(m_agentDebug.optStart.x, m_agentDebug.optStart.y + 0.3f, m_agentDebug.optStart.z,
duRGBA(0, 128, 0, 192));
dd.vertex(m_agentDebug.optEnd.x, m_agentDebug.optEnd.y + 0.3f, m_agentDebug.optEnd.z, duRGBA(0, 128, 0, 192));
dd.end();
dd.Begin(LINES, 2.0f);
dd.Vertex(m_agentDebug.optStart.x, m_agentDebug.optStart.y + 0.3f, m_agentDebug.optStart.z,
DuRGBA(0, 128, 0, 192));
dd.Vertex(m_agentDebug.optEnd.x, m_agentDebug.optEnd.y + 0.3f, m_agentDebug.optEnd.z, DuRGBA(0, 128, 0, 192));
dd.End();
}
}
// Agent cylinders.
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
float radius = ag.option.radius;
Vector3f pos = ag.npos;
int col = duRGBA(0, 0, 0, 32);
int col = DuRGBA(0, 0, 0, 32);
if (m_agentDebug.agent == ag)
col = duRGBA(255, 0, 0, 128);
col = DuRGBA(255, 0, 0, 128);
dd.debugDrawCircle(pos.x, pos.y, pos.z, radius, col, 2.0f);
dd.DebugDrawCircle(pos.x, pos.y, pos.z, radius, col, 2.0f);
}
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
float height = ag.option.height;
float radius = ag.option.radius;
Vector3f pos = ag.npos;
int col = duRGBA(220, 220, 220, 128);
int col = DuRGBA(220, 220, 220, 128);
if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING
|| ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE)
col = duLerpCol(col, duRGBA(128, 0, 255, 128), 32);
col = DuLerpCol(col, DuRGBA(128, 0, 255, 128), 32);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_WAITING_FOR_PATH)
col = duLerpCol(col, duRGBA(128, 0, 255, 128), 128);
col = DuLerpCol(col, DuRGBA(128, 0, 255, 128), 128);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_FAILED)
col = duRGBA(255, 32, 16, 128);
col = DuRGBA(255, 32, 16, 128);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_VELOCITY)
col = duLerpCol(col, duRGBA(64, 255, 0, 128), 128);
col = DuLerpCol(col, DuRGBA(64, 255, 0, 128), 128);
dd.debugDrawCylinder(pos.x - radius, pos.y + radius * 0.1f, pos.z - radius, pos.x + radius, pos.y + height,
dd.DebugDrawCylinder(pos.x - radius, pos.y + radius * 0.1f, pos.z - radius, pos.x + radius, pos.y + height,
pos.z + radius, col);
}
if (toolParams.m_showVO)
{
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
if (toolParams.m_showDetailAll == false && ag != m_agentDebug.agent)
continue;
@ -605,29 +605,29 @@ public class CrowdTool : Tool
float dy = ag.npos.y + ag.option.height;
float dz = ag.npos.z;
dd.debugDrawCircle(dx, dy, dz, ag.option.maxSpeed, duRGBA(255, 255, 255, 64), 2.0f);
dd.DebugDrawCircle(dx, dy, dz, ag.option.maxSpeed, DuRGBA(255, 255, 255, 64), 2.0f);
dd.begin(QUADS);
for (int j = 0; j < vod.getSampleCount(); ++j)
dd.Begin(QUADS);
for (int j = 0; j < vod.GetSampleCount(); ++j)
{
Vector3f p = vod.getSampleVelocity(j);
float sr = vod.getSampleSize(j);
float pen = vod.getSamplePenalty(j);
float pen2 = vod.getSamplePreferredSidePenalty(j);
int col = duLerpCol(duRGBA(255, 255, 255, 220), duRGBA(128, 96, 0, 220), (int)(pen * 255));
col = duLerpCol(col, duRGBA(128, 0, 0, 220), (int)(pen2 * 128));
dd.vertex(dx + p.x - sr, dy, dz + p.z - sr, col);
dd.vertex(dx + p.x - sr, dy, dz + p.z + sr, col);
dd.vertex(dx + p.x + sr, dy, dz + p.z + sr, col);
dd.vertex(dx + p.x + sr, dy, dz + p.z - sr, col);
Vector3f p = vod.GetSampleVelocity(j);
float sr = vod.GetSampleSize(j);
float pen = vod.GetSamplePenalty(j);
float pen2 = vod.GetSamplePreferredSidePenalty(j);
int col = DuLerpCol(DuRGBA(255, 255, 255, 220), DuRGBA(128, 96, 0, 220), (int)(pen * 255));
col = DuLerpCol(col, DuRGBA(128, 0, 0, 220), (int)(pen2 * 128));
dd.Vertex(dx + p.x - sr, dy, dz + p.z - sr, col);
dd.Vertex(dx + p.x - sr, dy, dz + p.z + sr, col);
dd.Vertex(dx + p.x + sr, dy, dz + p.z + sr, col);
dd.Vertex(dx + p.x + sr, dy, dz + p.z - sr, col);
}
dd.end();
dd.End();
}
}
// Velocity stuff.
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
float radius = ag.option.radius;
float height = ag.option.height;
@ -635,54 +635,54 @@ public class CrowdTool : Tool
Vector3f vel = ag.vel;
Vector3f dvel = ag.dvel;
int col = duRGBA(220, 220, 220, 192);
int col = DuRGBA(220, 220, 220, 192);
if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING
|| ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE)
col = duLerpCol(col, duRGBA(128, 0, 255, 192), 48);
col = DuLerpCol(col, DuRGBA(128, 0, 255, 192), 48);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_WAITING_FOR_PATH)
col = duLerpCol(col, duRGBA(128, 0, 255, 192), 128);
col = DuLerpCol(col, DuRGBA(128, 0, 255, 192), 128);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_FAILED)
col = duRGBA(255, 32, 16, 192);
col = DuRGBA(255, 32, 16, 192);
else if (ag.targetState == MoveRequestState.DT_CROWDAGENT_TARGET_VELOCITY)
col = duLerpCol(col, duRGBA(64, 255, 0, 192), 128);
col = DuLerpCol(col, DuRGBA(64, 255, 0, 192), 128);
dd.debugDrawCircle(pos.x, pos.y + height, pos.z, radius, col, 2.0f);
dd.DebugDrawCircle(pos.x, pos.y + height, pos.z, radius, col, 2.0f);
dd.debugDrawArrow(pos.x, pos.y + height, pos.z, pos.x + dvel.x, pos.y + height + dvel.y, pos.z + dvel.z,
0.0f, 0.4f, duRGBA(0, 192, 255, 192), m_agentDebug.agent == ag ? 2.0f : 1.0f);
dd.DebugDrawArrow(pos.x, pos.y + height, pos.z, pos.x + dvel.x, pos.y + height + dvel.y, pos.z + dvel.z,
0.0f, 0.4f, DuRGBA(0, 192, 255, 192), m_agentDebug.agent == ag ? 2.0f : 1.0f);
dd.debugDrawArrow(pos.x, pos.y + height, pos.z, pos.x + vel.x, pos.y + height + vel.y, pos.z + vel.z, 0.0f,
0.4f, duRGBA(0, 0, 0, 160), 2.0f);
dd.DebugDrawArrow(pos.x, pos.y + height, pos.z, pos.x + vel.x, pos.y + height + vel.y, pos.z + vel.z, 0.0f,
0.4f, DuRGBA(0, 0, 0, 160), 2.0f);
}
dd.depthMask(true);
dd.DepthMask(true);
}
public override void handleUpdate(float dt)
public override void HandleUpdate(float dt)
{
updateTick(dt);
UpdateTick(dt);
}
private void updateTick(float dt)
private void UpdateTick(float dt)
{
if (m_mode == CrowdToolMode.PROFILING)
{
profilingTool.update(dt);
profilingTool.Update(dt);
return;
}
if (crowd == null)
return;
NavMesh nav = sample.getNavMesh();
NavMesh nav = sample.GetNavMesh();
if (nav == null)
return;
long startTime = FrequencyWatch.Ticks;
crowd.update(dt, m_agentDebug);
crowd.Update(dt, m_agentDebug);
long endTime = FrequencyWatch.Ticks;
// Update agent trails
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
AgentTrail trail = m_trails[ag.idx];
// Update agent movement trail.
@ -692,18 +692,18 @@ public class CrowdTool : Tool
trail.trail[trail.htrail * 3 + 2] = ag.npos.z;
}
m_agentDebug.vod.normalizeSamples();
m_agentDebug.vod.NormalizeSamples();
// m_crowdSampleCount.addSample((float) crowd.getVelocitySampleCount());
// m_crowdSampleCount.addSample((float) crowd.GetVelocitySampleCount());
crowdUpdateTime = (endTime - startTime) / TimeSpan.TicksPerMillisecond;
}
private void hilightAgent(CrowdAgent agent)
private void HilightAgent(CrowdAgent agent)
{
m_agentDebug.agent = agent;
}
public override void layout()
public override void Layout()
{
ImGui.Text($"Crowd Tool Mode");
ImGui.Separator();
@ -744,13 +744,13 @@ public class CrowdTool : Tool
|| m_obstacleAvoidanceType != toolParams.m_obstacleAvoidanceType
|| m_separationWeight != toolParams.m_separationWeight)
{
updateAgentParams();
UpdateAgentParams();
}
if (m_mode == CrowdToolMode.PROFILING)
{
profilingTool.layout();
profilingTool.Layout();
}
if (m_mode != CrowdToolMode.PROFILING)
@ -773,16 +773,16 @@ public class CrowdTool : Tool
}
}
private void updateAgentParams()
private void UpdateAgentParams()
{
if (crowd == null)
{
return;
}
int updateFlags = getUpdateFlags();
profilingTool.updateAgentParams(updateFlags, toolParams.m_obstacleAvoidanceType, toolParams.m_separationWeight);
foreach (CrowdAgent ag in crowd.getActiveAgents())
int updateFlags = GetUpdateFlags();
profilingTool.UpdateAgentParams(updateFlags, toolParams.m_obstacleAvoidanceType, toolParams.m_separationWeight);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
CrowdAgentParams option = new CrowdAgentParams();
option.radius = ag.option.radius;
@ -797,11 +797,11 @@ public class CrowdTool : Tool
option.updateFlags = updateFlags;
option.obstacleAvoidanceType = toolParams.m_obstacleAvoidanceType;
option.separationWeight = toolParams.m_separationWeight;
crowd.updateAgentParameters(ag, option);
crowd.UpdateAgentParameters(ag, option);
}
}
private int getUpdateFlags()
private int GetUpdateFlags()
{
int updateFlags = 0;
if (toolParams.m_anticipateTurns)
@ -832,7 +832,7 @@ public class CrowdTool : Tool
return updateFlags;
}
public override string getName()
public override string GetName()
{
return "Crowd";
}

View File

@ -6,9 +6,9 @@ namespace DotRecast.Recast.Demo.Tools;
public static class DemoObjImporter
{
public static DemoInputGeomProvider load(byte[] chunk)
public static DemoInputGeomProvider Load(byte[] chunk)
{
var context = ObjImporter.loadContext(chunk);
var context = ObjImporter.LoadContext(chunk);
return new DemoInputGeomProvider(context.vertexPositions, context.meshFaces);
}
}

View File

@ -16,6 +16,7 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
using System;
using System.Collections;
using System.Collections.Generic;
@ -125,17 +126,17 @@ public class DynamicUpdateTool : Tool
public DynamicUpdateTool()
{
executor = Task.Factory;
bridgeGeom = DemoObjImporter.load(Loader.ToBytes("bridge.obj"));
houseGeom = DemoObjImporter.load(Loader.ToBytes("house.obj"));
convexGeom = DemoObjImporter.load(Loader.ToBytes("convex.obj"));
bridgeGeom = DemoObjImporter.Load(Loader.ToBytes("bridge.obj"));
houseGeom = DemoObjImporter.Load(Loader.ToBytes("house.obj"));
convexGeom = DemoObjImporter.Load(Loader.ToBytes("convex.obj"));
}
public override void setSample(Sample sample)
public override void SetSample(Sample sample)
{
this.sample = sample;
}
public override void handleClick(Vector3f s, Vector3f p, bool shift)
public override void HandleClick(Vector3f s, Vector3f p, bool shift)
{
if (mode == DynamicUpdateToolMode.COLLIDERS)
{
@ -146,41 +147,41 @@ public class DynamicUpdateTool : Tool
{
if (colliderShape == ColliderShape.SPHERE)
{
colliderWithGizmo = sphereCollider(p);
colliderWithGizmo = SphereCollider(p);
}
else if (colliderShape == ColliderShape.CAPSULE)
{
colliderWithGizmo = capsuleCollider(p);
colliderWithGizmo = CapsuleCollider(p);
}
else if (colliderShape == ColliderShape.BOX)
{
colliderWithGizmo = boxCollider(p);
colliderWithGizmo = BoxCollider(p);
}
else if (colliderShape == ColliderShape.CYLINDER)
{
colliderWithGizmo = cylinderCollider(p);
colliderWithGizmo = CylinderCollider(p);
}
else if (colliderShape == ColliderShape.COMPOSITE)
{
colliderWithGizmo = compositeCollider(p);
colliderWithGizmo = CompositeCollider(p);
}
else if (colliderShape == ColliderShape.TRIMESH_BRIDGE)
{
colliderWithGizmo = trimeshBridge(p);
colliderWithGizmo = TrimeshBridge(p);
}
else if (colliderShape == ColliderShape.TRIMESH_HOUSE)
{
colliderWithGizmo = trimeshHouse(p);
colliderWithGizmo = TrimeshHouse(p);
}
else if (colliderShape == ColliderShape.CONVEX)
{
colliderWithGizmo = convexTrimesh(p);
colliderWithGizmo = ConvexTrimesh(p);
}
}
if (colliderWithGizmo != null)
{
long id = dynaMesh.addCollider(colliderWithGizmo.Item1);
long id = dynaMesh.AddCollider(colliderWithGizmo.Item1);
colliders.Add(id, colliderWithGizmo.Item1);
colliderGizmos.Add(id, colliderWithGizmo.Item2);
}
@ -205,7 +206,7 @@ public class DynamicUpdateTool : Tool
Vector3f sp = Vector3f.Of(spos.x, spos.y + 1.3f, spos.z);
Vector3f ep = Vector3f.Of(epos.x, epos.y + 1.3f, epos.z);
long t1 = FrequencyWatch.Ticks;
float? hitPos = dynaMesh.voxelQuery().raycast(sp, ep);
float? hitPos = dynaMesh.VoxelQuery().Raycast(sp, ep);
long t2 = FrequencyWatch.Ticks;
raycastTime = (t2 - t1) / TimeSpan.TicksPerMillisecond;
raycastHit = hitPos.HasValue;
@ -216,15 +217,15 @@ public class DynamicUpdateTool : Tool
}
}
private Tuple<Collider, ColliderGizmo> sphereCollider(Vector3f p)
private Tuple<Collider, ColliderGizmo> SphereCollider(Vector3f p)
{
float radius = 1 + (float)random.NextDouble() * 10;
return Tuple.Create<Collider, ColliderGizmo>(
new SphereCollider(p, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb),
GizmoFactory.sphere(p, radius));
GizmoFactory.Sphere(p, radius));
}
private Tuple<Collider, ColliderGizmo> capsuleCollider(Vector3f p)
private Tuple<Collider, ColliderGizmo> CapsuleCollider(Vector3f p)
{
float radius = 0.4f + (float)random.NextDouble() * 4f;
Vector3f a = Vector3f.Of(
@ -232,7 +233,7 @@ public class DynamicUpdateTool : Tool
0.01f + (float)random.NextDouble(),
(1f - 2 * (float)random.NextDouble())
);
vNormalize(ref a);
VNormalize(ref a);
float len = 1f + (float)random.NextDouble() * 20f;
a.x *= len;
a.y *= len;
@ -240,10 +241,10 @@ public class DynamicUpdateTool : Tool
Vector3f start = Vector3f.Of(p.x, p.y, p.z);
Vector3f end = Vector3f.Of(p.x + a.x, p.y + a.y, p.z + a.z);
return Tuple.Create<Collider, ColliderGizmo>(new CapsuleCollider(
start, end, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb), GizmoFactory.capsule(start, end, radius));
start, end, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb), GizmoFactory.Capsule(start, end, radius));
}
private Tuple<Collider, ColliderGizmo> boxCollider(Vector3f p)
private Tuple<Collider, ColliderGizmo> BoxCollider(Vector3f p)
{
Vector3f extent = Vector3f.Of(
0.5f + (float)random.NextDouble() * 6f,
@ -252,16 +253,16 @@ public class DynamicUpdateTool : Tool
);
Vector3f forward = Vector3f.Of((1f - 2 * (float)random.NextDouble()), 0, (1f - 2 * (float)random.NextDouble()));
Vector3f up = Vector3f.Of((1f - 2 * (float)random.NextDouble()), 0.01f + (float)random.NextDouble(), (1f - 2 * (float)random.NextDouble()));
Vector3f[] halfEdges = BoxCollider.getHalfEdges(up, forward, extent);
Vector3f[] halfEdges = Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(up, forward, extent);
return Tuple.Create<Collider, ColliderGizmo>(
new BoxCollider(p, halfEdges, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb), GizmoFactory.box(p, halfEdges));
new BoxCollider(p, halfEdges, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb), GizmoFactory.Box(p, halfEdges));
}
private Tuple<Collider, ColliderGizmo> cylinderCollider(Vector3f p)
private Tuple<Collider, ColliderGizmo> CylinderCollider(Vector3f p)
{
float radius = 0.7f + (float)random.NextDouble() * 4f;
float[] a = new float[] { (1f - 2 * (float)random.NextDouble()), 0.01f + (float)random.NextDouble(), (1f - 2 * (float)random.NextDouble()) };
vNormalize(a);
VNormalize(a);
float len = 2f + (float)random.NextDouble() * 20f;
a[0] *= len;
a[1] *= len;
@ -269,25 +270,25 @@ public class DynamicUpdateTool : Tool
Vector3f start = Vector3f.Of(p.x, p.y, p.z);
Vector3f end = Vector3f.Of(p.x + a[0], p.y + a[1], p.z + a[2]);
return Tuple.Create<Collider, ColliderGizmo>(new CylinderCollider(start, end, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER,
dynaMesh.config.walkableClimb), GizmoFactory.cylinder(start, end, radius));
dynaMesh.config.walkableClimb), GizmoFactory.Cylinder(start, end, radius));
}
private Tuple<Collider, ColliderGizmo> compositeCollider(Vector3f p)
private Tuple<Collider, ColliderGizmo> CompositeCollider(Vector3f p)
{
Vector3f baseExtent = Vector3f.Of(5, 3, 8);
Vector3f baseCenter = Vector3f.Of(p.x, p.y + 3, p.z);
Vector3f baseUp = Vector3f.Of(0, 1, 0);
Vector3f forward = Vector3f.Of((1f - 2 * (float)random.NextDouble()), 0, (1f - 2 * (float)random.NextDouble()));
vNormalize(ref forward);
Vector3f side = vCross(forward, baseUp);
BoxCollider @base = new BoxCollider(baseCenter, BoxCollider.getHalfEdges(baseUp, forward, baseExtent),
VNormalize(ref forward);
Vector3f side = VCross(forward, baseUp);
BoxCollider @base = new BoxCollider(baseCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(baseUp, forward, baseExtent),
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, dynaMesh.config.walkableClimb);
var roofUp = Vector3f.Zero;
Vector3f roofExtent = Vector3f.Of(4.5f, 4.5f, 8f);
float[] rx = GLU.build_4x4_rotation_matrix(45, forward.x, forward.y, forward.z);
roofUp = mulMatrixVector(ref roofUp, rx, baseUp);
float[] rx = GLU.Build_4x4_rotation_matrix(45, forward.x, forward.y, forward.z);
roofUp = MulMatrixVector(ref roofUp, rx, baseUp);
Vector3f roofCenter = Vector3f.Of(p.x, p.y + 6, p.z);
BoxCollider roof = new BoxCollider(roofCenter, BoxCollider.getHalfEdges(roofUp, forward, roofExtent),
BoxCollider roof = new BoxCollider(roofCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(roofUp, forward, roofExtent),
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, dynaMesh.config.walkableClimb);
Vector3f trunkStart = Vector3f.Of(
baseCenter.x - forward.x * 15 + side.x * 6,
@ -304,45 +305,45 @@ public class DynamicUpdateTool : Tool
SphereCollider crown = new SphereCollider(crownCenter, 4f, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS,
dynaMesh.config.walkableClimb);
CompositeCollider collider = new CompositeCollider(@base, roof, trunk, crown);
ColliderGizmo baseGizmo = GizmoFactory.box(baseCenter, BoxCollider.getHalfEdges(baseUp, forward, baseExtent));
ColliderGizmo roofGizmo = GizmoFactory.box(roofCenter, BoxCollider.getHalfEdges(roofUp, forward, roofExtent));
ColliderGizmo trunkGizmo = GizmoFactory.capsule(trunkStart, trunkEnd, 0.5f);
ColliderGizmo crownGizmo = GizmoFactory.sphere(crownCenter, 4f);
ColliderGizmo gizmo = GizmoFactory.composite(baseGizmo, roofGizmo, trunkGizmo, crownGizmo);
ColliderGizmo baseGizmo = GizmoFactory.Box(baseCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(baseUp, forward, baseExtent));
ColliderGizmo roofGizmo = GizmoFactory.Box(roofCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(roofUp, forward, roofExtent));
ColliderGizmo trunkGizmo = GizmoFactory.Capsule(trunkStart, trunkEnd, 0.5f);
ColliderGizmo crownGizmo = GizmoFactory.Sphere(crownCenter, 4f);
ColliderGizmo gizmo = GizmoFactory.Composite(baseGizmo, roofGizmo, trunkGizmo, crownGizmo);
return Tuple.Create<Collider, ColliderGizmo>(collider, gizmo);
}
private Tuple<Collider, ColliderGizmo> trimeshBridge(Vector3f p)
private Tuple<Collider, ColliderGizmo> TrimeshBridge(Vector3f p)
{
return trimeshCollider(p, bridgeGeom);
return TrimeshCollider(p, bridgeGeom);
}
private Tuple<Collider, ColliderGizmo> trimeshHouse(Vector3f p)
private Tuple<Collider, ColliderGizmo> TrimeshHouse(Vector3f p)
{
return trimeshCollider(p, houseGeom);
return TrimeshCollider(p, houseGeom);
}
private Tuple<Collider, ColliderGizmo> convexTrimesh(Vector3f p)
private Tuple<Collider, ColliderGizmo> ConvexTrimesh(Vector3f p)
{
float[] verts = transformVertices(p, convexGeom, 360);
float[] verts = TransformVertices(p, convexGeom, 360);
ConvexTrimeshCollider collider = new ConvexTrimeshCollider(verts, convexGeom.faces,
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, dynaMesh.config.walkableClimb * 10);
return Tuple.Create<Collider, ColliderGizmo>(collider, GizmoFactory.trimesh(verts, convexGeom.faces));
return Tuple.Create<Collider, ColliderGizmo>(collider, GizmoFactory.Trimesh(verts, convexGeom.faces));
}
private Tuple<Collider, ColliderGizmo> trimeshCollider(Vector3f p, DemoInputGeomProvider geom)
private Tuple<Collider, ColliderGizmo> TrimeshCollider(Vector3f p, DemoInputGeomProvider geom)
{
float[] verts = transformVertices(p, geom, 0);
float[] verts = TransformVertices(p, geom, 0);
TrimeshCollider collider = new TrimeshCollider(verts, geom.faces, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD,
dynaMesh.config.walkableClimb * 10);
return Tuple.Create<Collider, ColliderGizmo>(collider, GizmoFactory.trimesh(verts, geom.faces));
return Tuple.Create<Collider, ColliderGizmo>(collider, GizmoFactory.Trimesh(verts, geom.faces));
}
private float[] transformVertices(Vector3f p, DemoInputGeomProvider geom, float ax)
private float[] TransformVertices(Vector3f p, DemoInputGeomProvider geom, float ax)
{
float[] rx = GLU.build_4x4_rotation_matrix((float)random.NextDouble() * ax, 1, 0, 0);
float[] ry = GLU.build_4x4_rotation_matrix((float)random.NextDouble() * 360, 0, 1, 0);
float[] m = GLU.mul(rx, ry);
float[] rx = GLU.Build_4x4_rotation_matrix((float)random.NextDouble() * ax, 1, 0, 0);
float[] ry = GLU.Build_4x4_rotation_matrix((float)random.NextDouble() * 360, 0, 1, 0);
float[] m = GLU.Mul(rx, ry);
float[] verts = new float[geom.vertices.Length];
Vector3f v = new Vector3f();
Vector3f vr = new Vector3f();
@ -351,7 +352,7 @@ public class DynamicUpdateTool : Tool
v.x = geom.vertices[i];
v.y = geom.vertices[i + 1];
v.z = geom.vertices[i + 2];
mulMatrixVector(ref vr, m, v);
MulMatrixVector(ref vr, m, v);
vr.x += p.x;
vr.y += p.y - 0.1f;
vr.z += p.z;
@ -363,7 +364,7 @@ public class DynamicUpdateTool : Tool
return verts;
}
private float[] mulMatrixVector(float[] resultvector, float[] matrix, float[] pvector)
private float[] MulMatrixVector(float[] resultvector, float[] matrix, float[] pvector)
{
resultvector[0] = matrix[0] * pvector[0] + matrix[4] * pvector[1] + matrix[8] * pvector[2];
resultvector[1] = matrix[1] * pvector[0] + matrix[5] * pvector[1] + matrix[9] * pvector[2];
@ -371,7 +372,7 @@ public class DynamicUpdateTool : Tool
return resultvector;
}
private Vector3f mulMatrixVector(ref Vector3f resultvector, float[] matrix, Vector3f pvector)
private Vector3f MulMatrixVector(ref Vector3f resultvector, float[] matrix, Vector3f pvector)
{
resultvector.x = matrix[0] * pvector.x + matrix[4] * pvector.y + matrix[8] * pvector.z;
resultvector.y = matrix[1] * pvector.x + matrix[5] * pvector.y + matrix[9] * pvector.z;
@ -380,7 +381,7 @@ public class DynamicUpdateTool : Tool
}
public override void handleClickRay(Vector3f start, float[] dir, bool shift)
public override void HandleClickRay(Vector3f start, float[] dir, bool shift)
{
if (mode == DynamicUpdateToolMode.COLLIDERS)
{
@ -388,9 +389,9 @@ public class DynamicUpdateTool : Tool
{
foreach (var e in colliders)
{
if (hit(start, dir, e.Value.bounds()))
if (Hit(start, dir, e.Value.Bounds()))
{
dynaMesh.removeCollider(e.Key);
dynaMesh.RemoveCollider(e.Key);
colliders.Remove(e.Key);
colliderGizmos.Remove(e.Key);
break;
@ -400,7 +401,7 @@ public class DynamicUpdateTool : Tool
}
}
private bool hit(Vector3f point, float[] dir, float[] bounds)
private bool Hit(Vector3f point, float[] dir, float[] bounds)
{
float cx = 0.5f * (bounds[0] + bounds[3]);
float cy = 0.5f * (bounds[1] + bounds[4]);
@ -428,85 +429,85 @@ public class DynamicUpdateTool : Tool
return disc >= 0.0f;
}
public override void handleRender(NavMeshRenderer renderer)
public override void HandleRender(NavMeshRenderer renderer)
{
if (mode == DynamicUpdateToolMode.COLLIDERS)
{
if (showColliders)
{
colliderGizmos.Values.forEach(g => g.render(renderer.getDebugDraw()));
colliderGizmos.Values.ForEach(g => g.Render(renderer.GetDebugDraw()));
}
}
if (mode == DynamicUpdateToolMode.RAYCAST)
{
RecastDebugDraw dd = renderer.getDebugDraw();
int startCol = duRGBA(128, 25, 0, 192);
int endCol = duRGBA(51, 102, 0, 129);
RecastDebugDraw dd = renderer.GetDebugDraw();
int startCol = DuRGBA(128, 25, 0, 192);
int endCol = DuRGBA(51, 102, 0, 129);
if (sposSet)
{
drawAgent(dd, spos, startCol);
DrawAgent(dd, spos, startCol);
}
if (eposSet)
{
drawAgent(dd, epos, endCol);
DrawAgent(dd, epos, endCol);
}
dd.depthMask(false);
dd.DepthMask(false);
if (raycastHitPos != Vector3f.Zero)
{
int spathCol = raycastHit ? duRGBA(128, 32, 16, 220) : duRGBA(64, 128, 240, 220);
dd.begin(LINES, 2.0f);
dd.vertex(spos.x, spos.y + 1.3f, spos.z, spathCol);
dd.vertex(raycastHitPos.x, raycastHitPos.y, raycastHitPos.z, spathCol);
dd.end();
int spathCol = raycastHit ? DuRGBA(128, 32, 16, 220) : DuRGBA(64, 128, 240, 220);
dd.Begin(LINES, 2.0f);
dd.Vertex(spos.x, spos.y + 1.3f, spos.z, spathCol);
dd.Vertex(raycastHitPos.x, raycastHitPos.y, raycastHitPos.z, spathCol);
dd.End();
}
dd.depthMask(true);
dd.DepthMask(true);
}
}
private void drawAgent(RecastDebugDraw dd, Vector3f pos, int col)
private void DrawAgent(RecastDebugDraw dd, Vector3f pos, int col)
{
float r = sample.getSettingsUI().getAgentRadius();
float h = sample.getSettingsUI().getAgentHeight();
float c = sample.getSettingsUI().getAgentMaxClimb();
dd.depthMask(false);
float r = sample.GetSettingsUI().GetAgentRadius();
float h = sample.GetSettingsUI().GetAgentHeight();
float c = sample.GetSettingsUI().GetAgentMaxClimb();
dd.DepthMask(false);
// Agent dimensions.
dd.debugDrawCylinderWire(pos.x - r, pos.y + 0.02f, pos.z - r, pos.x + r, pos.y + h, pos.z + r, col, 2.0f);
dd.debugDrawCircle(pos.x, pos.y + c, pos.z, r, duRGBA(0, 0, 0, 64), 1.0f);
int colb = duRGBA(0, 0, 0, 196);
dd.begin(LINES);
dd.vertex(pos.x, pos.y - c, pos.z, colb);
dd.vertex(pos.x, pos.y + c, pos.z, colb);
dd.vertex(pos.x - r / 2, pos.y + 0.02f, pos.z, colb);
dd.vertex(pos.x + r / 2, pos.y + 0.02f, pos.z, colb);
dd.vertex(pos.x, pos.y + 0.02f, pos.z - r / 2, colb);
dd.vertex(pos.x, pos.y + 0.02f, pos.z + r / 2, colb);
dd.end();
dd.depthMask(true);
dd.DebugDrawCylinderWire(pos.x - r, pos.y + 0.02f, pos.z - r, pos.x + r, pos.y + h, pos.z + r, col, 2.0f);
dd.DebugDrawCircle(pos.x, pos.y + c, pos.z, r, DuRGBA(0, 0, 0, 64), 1.0f);
int colb = DuRGBA(0, 0, 0, 196);
dd.Begin(LINES);
dd.Vertex(pos.x, pos.y - c, pos.z, colb);
dd.Vertex(pos.x, pos.y + c, pos.z, colb);
dd.Vertex(pos.x - r / 2, pos.y + 0.02f, pos.z, colb);
dd.Vertex(pos.x + r / 2, pos.y + 0.02f, pos.z, colb);
dd.Vertex(pos.x, pos.y + 0.02f, pos.z - r / 2, colb);
dd.Vertex(pos.x, pos.y + 0.02f, pos.z + r / 2, colb);
dd.End();
dd.DepthMask(true);
}
public override void handleUpdate(float dt)
public override void HandleUpdate(float dt)
{
if (dynaMesh != null)
{
updateDynaMesh();
UpdateDynaMesh();
}
}
private void updateDynaMesh()
private void UpdateDynaMesh()
{
long t = FrequencyWatch.Ticks;
try
{
bool updated = dynaMesh.update(executor).Result;
bool updated = dynaMesh.Update(executor).Result;
if (updated)
{
buildTime = (FrequencyWatch.Ticks - t) / TimeSpan.TicksPerMillisecond;
sample.update(null, dynaMesh.recastResults(), dynaMesh.navMesh());
sample.setChanged(false);
sample.Update(null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
sample.SetChanged(false);
}
}
catch (Exception e)
@ -515,7 +516,7 @@ public class DynamicUpdateTool : Tool
}
}
public override void layout()
public override void Layout()
{
ImGui.Text($"Dynamic Update Tool Modes");
ImGui.Separator();
@ -548,7 +549,7 @@ public class DynamicUpdateTool : Tool
var picker = ImFilePicker.GetFilePicker(loadVoxelPopupStrId, Path.Combine(Environment.CurrentDirectory), ".voxels");
if (picker.Draw())
{
load(picker.SelectedFile);
Load(picker.SelectedFile);
ImFilePicker.RemoveFilePicker(loadVoxelPopupStrId);
}
@ -571,7 +572,7 @@ public class DynamicUpdateTool : Tool
if (picker.Draw())
{
if (string.IsNullOrEmpty(picker.SelectedFile))
save(picker.SelectedFile);
Save(picker.SelectedFile);
ImFilePicker.RemoveFilePicker(saveVoxelPopupStrId);
}
@ -597,7 +598,7 @@ public class DynamicUpdateTool : Tool
ImGui.Text("Partitioning");
ImGui.Separator();
PartitionType.Values.forEach(partition =>
PartitionType.Values.ForEach(partition =>
{
var label = partition.Name.Substring(0, 1).ToUpper()
+ partition.Name.Substring(1).ToLower();
@ -636,8 +637,8 @@ public class DynamicUpdateTool : Tool
{
if (dynaMesh != null)
{
buildDynaMesh();
sample.setChanged(false);
BuildDynaMesh();
sample.SetChanged(false);
}
}
}
@ -692,18 +693,18 @@ public class DynamicUpdateTool : Tool
}
private void load(string filename)
private void Load(string filename)
{
try
{
using var fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
using var br = new BinaryReader(fs);
VoxelFileReader reader = new VoxelFileReader();
VoxelFile voxelFile = reader.read(br);
VoxelFile voxelFile = reader.Read(br);
dynaMesh = new DynamicNavMesh(voxelFile);
dynaMesh.config.keepIntermediateResults = true;
updateUI();
buildDynaMesh();
UpdateUI();
BuildDynaMesh();
colliders.Clear();
}
@ -715,22 +716,22 @@ public class DynamicUpdateTool : Tool
}
private void save(string filename)
private void Save(string filename)
{
using var fs = new FileStream(filename, FileMode.CreateNew, FileAccess.Write);
using var bw = new BinaryWriter(fs);
VoxelFile voxelFile = VoxelFile.from(dynaMesh);
VoxelFile voxelFile = VoxelFile.From(dynaMesh);
VoxelFileWriter writer = new VoxelFileWriter();
writer.write(bw, voxelFile, compression);
writer.Write(bw, voxelFile, compression);
}
private void buildDynaMesh()
private void BuildDynaMesh()
{
configDynaMesh();
ConfigDynaMesh();
long t = FrequencyWatch.Ticks;
try
{
var _ = dynaMesh.build(executor).Result;
var _ = dynaMesh.Build(executor).Result;
}
catch (Exception e)
{
@ -738,10 +739,10 @@ public class DynamicUpdateTool : Tool
}
buildTime = (FrequencyWatch.Ticks - t) / TimeSpan.TicksPerMillisecond;
sample.update(null, dynaMesh.recastResults(), dynaMesh.navMesh());
sample.Update(null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
}
private void configDynaMesh()
private void ConfigDynaMesh()
{
dynaMesh.config.partitionType = partitioning;
dynaMesh.config.walkableHeight = walkableHeight;
@ -761,7 +762,7 @@ public class DynamicUpdateTool : Tool
dynaMesh.config.detailSampleMaxError = detailSampleMaxError;
}
private void updateUI()
private void UpdateUI()
{
cellSize = dynaMesh.config.cellSize;
partitioning = dynaMesh.config.partitionType;
@ -782,7 +783,7 @@ public class DynamicUpdateTool : Tool
filterWalkableLowHeightSpans = dynaMesh.config.filterWalkableLowHeightSpans;
}
public override string getName()
public override string GetName()
{
return "Dynamic Updates";
}

View File

@ -29,7 +29,7 @@ public class BoxGizmo : ColliderGizmo
private readonly Vector3f[] halfEdges;
public BoxGizmo(Vector3f center, Vector3f extent, Vector3f forward, Vector3f up) :
this(center, BoxCollider.getHalfEdges(up, forward, extent))
this(center, BoxCollider.GetHalfEdges(up, forward, extent))
{
}
@ -48,7 +48,7 @@ public class BoxGizmo : ColliderGizmo
}
}
public void render(RecastDebugDraw debugDraw)
public void Render(RecastDebugDraw debugDraw)
{
var trX = Vector3f.Of(halfEdges[0].x, halfEdges[1].x, halfEdges[2].x);
var trY = Vector3f.Of(halfEdges[0].y, halfEdges[1].y, halfEdges[2].y);
@ -56,31 +56,31 @@ public class BoxGizmo : ColliderGizmo
float[] vertices = new float[8 * 3];
for (int i = 0; i < 8; i++)
{
vertices[i * 3 + 0] = RecastVectors.dot(VERTS[i], trX) + center.x;
vertices[i * 3 + 1] = RecastVectors.dot(VERTS[i], trY) + center.y;
vertices[i * 3 + 2] = RecastVectors.dot(VERTS[i], trZ) + center.z;
vertices[i * 3 + 0] = RecastVectors.Dot(VERTS[i], trX) + center.x;
vertices[i * 3 + 1] = RecastVectors.Dot(VERTS[i], trY) + center.y;
vertices[i * 3 + 2] = RecastVectors.Dot(VERTS[i], trZ) + center.z;
}
debugDraw.begin(DebugDrawPrimitives.TRIS);
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < 12; i++)
{
int col = DebugDraw.duRGBA(200, 200, 50, 160);
int col = DebugDraw.DuRGBA(200, 200, 50, 160);
if (i == 4 || i == 5 || i == 8 || i == 9)
{
col = DebugDraw.duRGBA(160, 160, 40, 160);
col = DebugDraw.DuRGBA(160, 160, 40, 160);
}
else if (i > 4)
{
col = DebugDraw.duRGBA(120, 120, 30, 160);
col = DebugDraw.DuRGBA(120, 120, 30, 160);
}
for (int j = 0; j < 3; j++)
{
int v = TRIANLGES[i * 3 + j] * 3;
debugDraw.vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
debugDraw.Vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
}
}
debugDraw.end();
debugDraw.End();
}
}

View File

@ -23,17 +23,17 @@ public class CapsuleGizmo : ColliderGizmo
Vector3f axis = Vector3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
Vector3f[] normals = new Vector3f[3];
normals[1] = Vector3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
normalize(ref normals[1]);
normals[0] = getSideVector(axis);
Normalize(ref normals[1]);
normals[0] = GetSideVector(axis);
normals[2] = Vector3f.Zero;
cross(ref normals[2], normals[0], normals[1]);
normalize(ref normals[2]);
triangles = generateSphericalTriangles();
Cross(ref normals[2], normals[0], normals[1]);
Normalize(ref normals[2]);
triangles = GenerateSphericalTriangles();
var trX = Vector3f.Of(normals[0].x, normals[1].x, normals[2].x);
var trY = Vector3f.Of(normals[0].y, normals[1].y, normals[2].y);
var trZ = Vector3f.Of(normals[0].z, normals[1].z, normals[2].z);
float[] spVertices = generateSphericalVertices();
float halfLength = 0.5f * vLen(axis);
float[] spVertices = GenerateSphericalVertices();
float halfLength = 0.5f * VLen(axis);
vertices = new float[spVertices.Length];
gradient = new float[spVertices.Length / 3];
Vector3f v = new Vector3f();
@ -49,12 +49,12 @@ public class CapsuleGizmo : ColliderGizmo
v.x = vertices[i] - center[0];
v.y = vertices[i + 1] - center[1];
v.z = vertices[i + 2] - center[2];
normalize(ref v);
gradient[i / 3] = clamp(0.57735026f * (v.x + v.y + v.z), -1, 1);
Normalize(ref v);
gradient[i / 3] = Clamp(0.57735026f * (v.x + v.y + v.z), -1, 1);
}
}
private Vector3f getSideVector(Vector3f axis)
private Vector3f GetSideVector(Vector3f axis)
{
Vector3f side = Vector3f.Of(1, 0, 0);
if (axis.x > 0.8)
@ -63,27 +63,27 @@ public class CapsuleGizmo : ColliderGizmo
}
Vector3f forward = new Vector3f();
cross(ref forward, side, axis);
cross(ref side, axis, forward);
normalize(ref side);
Cross(ref forward, side, axis);
Cross(ref side, axis, forward);
Normalize(ref side);
return side;
}
public void render(RecastDebugDraw debugDraw)
public void Render(RecastDebugDraw debugDraw)
{
debugDraw.begin(DebugDrawPrimitives.TRIS);
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = triangles[i + j] * 3;
float c = gradient[triangles[i + j]];
int col = DebugDraw.duLerpCol(DebugDraw.duRGBA(32, 32, 0, 160), DebugDraw.duRGBA(220, 220, 0, 160),
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
debugDraw.vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
debugDraw.Vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
}
}
debugDraw.end();
debugDraw.End();
}
}

View File

@ -4,5 +4,5 @@ namespace DotRecast.Recast.Demo.Tools.Gizmos;
public interface ColliderGizmo
{
void render(RecastDebugDraw debugDraw);
void Render(RecastDebugDraw debugDraw);
}

View File

@ -1,4 +1,5 @@
using DotRecast.Core;
using System;
using DotRecast.Core;
using DotRecast.Recast.Demo.Draw;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
@ -12,8 +13,8 @@ public class CompositeGizmo : ColliderGizmo
this.gizmos = gizmos;
}
public void render(RecastDebugDraw debugDraw)
public void Render(RecastDebugDraw debugDraw)
{
gizmos.forEach(g => g.render(debugDraw));
gizmos.ForEach(g => g.Render(debugDraw));
}
}

View File

@ -23,17 +23,17 @@ public class CylinderGizmo : ColliderGizmo
Vector3f axis = Vector3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
Vector3f[] normals = new Vector3f[3];
normals[1] = Vector3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
normalize(ref normals[1]);
normals[0] = getSideVector(axis);
Normalize(ref normals[1]);
normals[0] = GetSideVector(axis);
normals[2] = Vector3f.Zero;
cross(ref normals[2], normals[0], normals[1]);
normalize(ref normals[2]);
triangles = generateCylindricalTriangles();
Cross(ref normals[2], normals[0], normals[1]);
Normalize(ref normals[2]);
triangles = GenerateCylindricalTriangles();
Vector3f trX = Vector3f.Of(normals[0].x, normals[1].x, normals[2].x);
Vector3f trY = Vector3f.Of(normals[0].y, normals[1].y, normals[2].y);
Vector3f trZ = Vector3f.Of(normals[0].z, normals[1].z, normals[2].z);
vertices = generateCylindricalVertices();
float halfLength = 0.5f * vLen(axis);
vertices = GenerateCylindricalVertices();
float halfLength = 0.5f * VLen(axis);
gradient = new float[vertices.Length / 3];
Vector3f v = new Vector3f();
for (int i = 0; i < vertices.Length; i += 3)
@ -54,13 +54,13 @@ public class CylinderGizmo : ColliderGizmo
v.x = vertices[i] - center.x;
v.y = vertices[i + 1] - center.y;
v.z = vertices[i + 2] - center.z;
normalize(ref v);
gradient[i / 3] = clamp(0.57735026f * (v.x + v.y + v.z), -1, 1);
Normalize(ref v);
gradient[i / 3] = Clamp(0.57735026f * (v.x + v.y + v.z), -1, 1);
}
}
}
private Vector3f getSideVector(Vector3f axis)
private Vector3f GetSideVector(Vector3f axis)
{
Vector3f side = Vector3f.Of(1, 0, 0);
if (axis.x > 0.8)
@ -69,27 +69,27 @@ public class CylinderGizmo : ColliderGizmo
}
Vector3f forward = new Vector3f();
cross(ref forward, side, axis);
cross(ref side, axis, forward);
normalize(ref side);
Cross(ref forward, side, axis);
Cross(ref side, axis, forward);
Normalize(ref side);
return side;
}
public void render(RecastDebugDraw debugDraw)
public void Render(RecastDebugDraw debugDraw)
{
debugDraw.begin(DebugDrawPrimitives.TRIS);
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = triangles[i + j] * 3;
float c = gradient[triangles[i + j]];
int col = DebugDraw.duLerpCol(DebugDraw.duRGBA(32, 32, 0, 160), DebugDraw.duRGBA(220, 220, 0, 160),
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
debugDraw.vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
debugDraw.Vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
}
}
debugDraw.end();
debugDraw.End();
}
}

View File

@ -4,32 +4,32 @@ namespace DotRecast.Recast.Demo.Tools.Gizmos;
public static class GizmoFactory
{
public static ColliderGizmo box(Vector3f center, Vector3f[] halfEdges)
public static ColliderGizmo Box(Vector3f center, Vector3f[] halfEdges)
{
return new BoxGizmo(center, halfEdges);
}
public static ColliderGizmo sphere(Vector3f center, float radius)
public static ColliderGizmo Sphere(Vector3f center, float radius)
{
return new SphereGizmo(center, radius);
}
public static ColliderGizmo capsule(Vector3f start, Vector3f end, float radius)
public static ColliderGizmo Capsule(Vector3f start, Vector3f end, float radius)
{
return new CapsuleGizmo(start, end, radius);
}
public static ColliderGizmo cylinder(Vector3f start, Vector3f end, float radius)
public static ColliderGizmo Cylinder(Vector3f start, Vector3f end, float radius)
{
return new CylinderGizmo(start, end, radius);
}
public static ColliderGizmo trimesh(float[] verts, int[] faces)
public static ColliderGizmo Trimesh(float[] verts, int[] faces)
{
return new TrimeshGizmo(verts, faces);
}
public static ColliderGizmo composite(params ColliderGizmo[] gizmos)
public static ColliderGizmo Composite(params ColliderGizmo[] gizmos)
{
return new CompositeGizmo(gizmos);
}

View File

@ -12,17 +12,17 @@ public class GizmoHelper
private static float[] sphericalVertices;
public static float[] generateSphericalVertices()
public static float[] GenerateSphericalVertices()
{
if (sphericalVertices == null)
{
sphericalVertices = generateSphericalVertices(SEGMENTS, RINGS);
sphericalVertices = GenerateSphericalVertices(SEGMENTS, RINGS);
}
return sphericalVertices;
}
private static float[] generateSphericalVertices(int segments, int rings)
private static float[] GenerateSphericalVertices(int segments, int rings)
{
float[] vertices = new float[6 + 3 * (segments + 1) * (rings + 1)];
// top
@ -33,7 +33,7 @@ public class GizmoHelper
for (int r = 0; r <= rings; r++)
{
double theta = Math.PI * (r + 1) / (rings + 2);
vi = generateRingVertices(segments, vertices, vi, theta);
vi = GenerateRingVertices(segments, vertices, vi, theta);
}
// bottom
@ -43,24 +43,24 @@ public class GizmoHelper
return vertices;
}
public static float[] generateCylindricalVertices()
public static float[] GenerateCylindricalVertices()
{
return generateCylindricalVertices(SEGMENTS);
return GenerateCylindricalVertices(SEGMENTS);
}
private static float[] generateCylindricalVertices(int segments)
private static float[] GenerateCylindricalVertices(int segments)
{
float[] vertices = new float[3 * (segments + 1) * 4];
int vi = 0;
for (int r = 0; r < 4; r++)
{
vi = generateRingVertices(segments, vertices, vi, Math.PI * 0.5);
vi = GenerateRingVertices(segments, vertices, vi, Math.PI * 0.5);
}
return vertices;
}
private static int generateRingVertices(int segments, float[] vertices, int vi, double theta)
private static int GenerateRingVertices(int segments, float[] vertices, int vi, double theta)
{
double cosTheta = Math.Cos(theta);
double sinTheta = Math.Sin(theta);
@ -77,21 +77,21 @@ public class GizmoHelper
return vi;
}
public static int[] generateSphericalTriangles()
public static int[] GenerateSphericalTriangles()
{
return generateSphericalTriangles(SEGMENTS, RINGS);
return GenerateSphericalTriangles(SEGMENTS, RINGS);
}
private static int[] generateSphericalTriangles(int segments, int rings)
private static int[] GenerateSphericalTriangles(int segments, int rings)
{
int[] triangles = new int[6 * (segments + rings * (segments + 1))];
int ti = generateSphereUpperCapTriangles(segments, triangles, 0);
ti = generateRingTriangles(segments, rings, triangles, 1, ti);
generateSphereLowerCapTriangles(segments, rings, triangles, ti);
int ti = GenerateSphereUpperCapTriangles(segments, triangles, 0);
ti = GenerateRingTriangles(segments, rings, triangles, 1, ti);
GenerateSphereLowerCapTriangles(segments, rings, triangles, ti);
return triangles;
}
public static int generateRingTriangles(int segments, int rings, int[] triangles, int vertexOffset, int ti)
public static int GenerateRingTriangles(int segments, int rings, int[] triangles, int vertexOffset, int ti)
{
for (int r = 0; r < rings; r++)
{
@ -113,7 +113,7 @@ public class GizmoHelper
return ti;
}
private static int generateSphereUpperCapTriangles(int segments, int[] triangles, int ti)
private static int GenerateSphereUpperCapTriangles(int segments, int[] triangles, int ti)
{
for (int p = 0; p < segments; p++)
{
@ -125,7 +125,7 @@ public class GizmoHelper
return ti;
}
private static void generateSphereLowerCapTriangles(int segments, int rings, int[] triangles, int ti)
private static void GenerateSphereLowerCapTriangles(int segments, int rings, int[] triangles, int ti)
{
int lastVertex = 1 + (segments + 1) * (rings + 1);
for (int p = 0; p < segments; p++)
@ -136,24 +136,24 @@ public class GizmoHelper
}
}
public static int[] generateCylindricalTriangles()
public static int[] GenerateCylindricalTriangles()
{
return generateCylindricalTriangles(SEGMENTS);
return GenerateCylindricalTriangles(SEGMENTS);
}
private static int[] generateCylindricalTriangles(int segments)
private static int[] GenerateCylindricalTriangles(int segments)
{
int circleTriangles = segments - 2;
int[] triangles = new int[6 * (circleTriangles + (segments + 1))];
int vi = 0;
int ti = generateCircleTriangles(segments, triangles, vi, 0, false);
ti = generateRingTriangles(segments, 1, triangles, segments + 1, ti);
int ti = GenerateCircleTriangles(segments, triangles, vi, 0, false);
ti = GenerateRingTriangles(segments, 1, triangles, segments + 1, ti);
int vertexCount = (segments + 1) * 4;
ti = generateCircleTriangles(segments, triangles, vertexCount - segments, ti, true);
ti = GenerateCircleTriangles(segments, triangles, vertexCount - segments, ti, true);
return triangles;
}
private static int generateCircleTriangles(int segments, int[] triangles, int vi, int ti, bool invert)
private static int GenerateCircleTriangles(int segments, int[] triangles, int vi, int ti, bool invert)
{
for (int p = 0; p < segments - 2; p++)
{
@ -174,7 +174,7 @@ public class GizmoHelper
return ti;
}
public static int getColorByNormal(float[] vertices, int v0, int v1, int v2)
public static int GetColorByNormal(float[] vertices, int v0, int v1, int v2)
{
Vector3f e0 = new Vector3f();
Vector3f e1 = new Vector3f();
@ -188,9 +188,9 @@ public class GizmoHelper
normal.x = e0.y * e1.z - e0.z * e1.y;
normal.y = e0.z * e1.x - e0.x * e1.z;
normal.z = e0.x * e1.y - e0.y * e1.x;
RecastVectors.normalize(ref normal);
float c = clamp(0.57735026f * (normal.x + normal.y + normal.z), -1, 1);
int col = DebugDraw.duLerpCol(DebugDraw.duRGBA(32, 32, 0, 160), DebugDraw.duRGBA(220, 220, 0, 160),
RecastVectors.Normalize(ref normal);
float c = Clamp(0.57735026f * (normal.x + normal.y + normal.z), -1, 1);
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
return col;
}

View File

@ -17,26 +17,26 @@ public class SphereGizmo : ColliderGizmo
{
this.center = center;
this.radius = radius;
vertices = generateSphericalVertices();
triangles = generateSphericalTriangles();
vertices = GenerateSphericalVertices();
triangles = GenerateSphericalTriangles();
}
public void render(RecastDebugDraw debugDraw)
public void Render(RecastDebugDraw debugDraw)
{
debugDraw.begin(DebugDrawPrimitives.TRIS);
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = triangles[i + j] * 3;
float c = clamp(0.57735026f * (vertices[v] + vertices[v + 1] + vertices[v + 2]), -1, 1);
int col = DebugDraw.duLerpCol(DebugDraw.duRGBA(32, 32, 0, 160), DebugDraw.duRGBA(220, 220, 0, 160),
float c = Clamp(0.57735026f * (vertices[v] + vertices[v + 1] + vertices[v + 2]), -1, 1);
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
debugDraw.vertex(radius * vertices[v] + center.x, radius * vertices[v + 1] + center.y,
debugDraw.Vertex(radius * vertices[v] + center.x, radius * vertices[v + 1] + center.y,
radius * vertices[v + 2] + center.z, col);
}
}
debugDraw.end();
debugDraw.End();
}
}

View File

@ -13,20 +13,20 @@ public class TrimeshGizmo : ColliderGizmo
this.triangles = triangles;
}
public void render(RecastDebugDraw debugDraw)
public void Render(RecastDebugDraw debugDraw)
{
debugDraw.begin(DebugDrawPrimitives.TRIS);
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < triangles.Length; i += 3)
{
int v0 = 3 * triangles[i];
int v1 = 3 * triangles[i + 1];
int v2 = 3 * triangles[i + 2];
int col = GizmoHelper.getColorByNormal(vertices, v0, v1, v2);
debugDraw.vertex(vertices[v0], vertices[v0 + 1], vertices[v0 + 2], col);
debugDraw.vertex(vertices[v1], vertices[v1 + 1], vertices[v1 + 2], col);
debugDraw.vertex(vertices[v2], vertices[v2 + 1], vertices[v2 + 2], col);
int col = GizmoHelper.GetColorByNormal(vertices, v0, v1, v2);
debugDraw.Vertex(vertices[v0], vertices[v0 + 1], vertices[v0 + 2], col);
debugDraw.Vertex(vertices[v1], vertices[v1 + 1], vertices[v1 + 2], col);
debugDraw.Vertex(vertices[v2], vertices[v2 + 1], vertices[v2 + 2], col);
}
debugDraw.end();
debugDraw.End();
}
}

View File

@ -39,124 +39,124 @@ public class JumpLinkBuilderTool : Tool
private readonly int selEdge = -1;
private readonly JumpLinkBuilderToolParams option = new JumpLinkBuilderToolParams();
public override void setSample(Sample sample)
public override void SetSample(Sample sample)
{
this.sample = sample;
annotationBuilder = null;
}
public override void handleClick(Vector3f s, Vector3f p, bool shift)
public override void HandleClick(Vector3f s, Vector3f p, bool shift)
{
}
public override void handleRender(NavMeshRenderer renderer)
public override void HandleRender(NavMeshRenderer renderer)
{
int col0 = duLerpCol(duRGBA(32, 255, 96, 255), duRGBA(255, 255, 255, 255), 200);
int col1 = duRGBA(32, 255, 96, 255);
RecastDebugDraw dd = renderer.getDebugDraw();
dd.depthMask(false);
int col0 = DuLerpCol(DuRGBA(32, 255, 96, 255), DuRGBA(255, 255, 255, 255), 200);
int col1 = DuRGBA(32, 255, 96, 255);
RecastDebugDraw dd = renderer.GetDebugDraw();
dd.DepthMask(false);
if ((option.flags & JumpLinkBuilderToolParams.DRAW_WALKABLE_BORDER) != 0)
{
if (annotationBuilder != null)
{
foreach (Edge[] edges in annotationBuilder.getEdges())
foreach (Edge[] edges in annotationBuilder.GetEdges())
{
dd.begin(LINES, 3.0f);
dd.Begin(LINES, 3.0f);
for (int i = 0; i < edges.Length; ++i)
{
int col = duRGBA(0, 96, 128, 255);
int col = DuRGBA(0, 96, 128, 255);
if (i == selEdge)
continue;
dd.vertex(edges[i].sp, col);
dd.vertex(edges[i].sq, col);
dd.Vertex(edges[i].sp, col);
dd.Vertex(edges[i].sq, col);
}
dd.end();
dd.End();
dd.begin(POINTS, 8.0f);
dd.Begin(POINTS, 8.0f);
for (int i = 0; i < edges.Length; ++i)
{
int col = duRGBA(0, 96, 128, 255);
int col = DuRGBA(0, 96, 128, 255);
if (i == selEdge)
continue;
dd.vertex(edges[i].sp, col);
dd.vertex(edges[i].sq, col);
dd.Vertex(edges[i].sp, col);
dd.Vertex(edges[i].sq, col);
}
dd.end();
dd.End();
if (selEdge >= 0 && selEdge < edges.Length)
{
int col = duRGBA(48, 16, 16, 255); // duRGBA(255,192,0,255);
dd.begin(LINES, 3.0f);
dd.vertex(edges[selEdge].sp, col);
dd.vertex(edges[selEdge].sq, col);
dd.end();
dd.begin(POINTS, 8.0f);
dd.vertex(edges[selEdge].sp, col);
dd.vertex(edges[selEdge].sq, col);
dd.end();
int col = DuRGBA(48, 16, 16, 255); // DuRGBA(255,192,0,255);
dd.Begin(LINES, 3.0f);
dd.Vertex(edges[selEdge].sp, col);
dd.Vertex(edges[selEdge].sq, col);
dd.End();
dd.Begin(POINTS, 8.0f);
dd.Vertex(edges[selEdge].sp, col);
dd.Vertex(edges[selEdge].sq, col);
dd.End();
}
dd.begin(POINTS, 4.0f);
dd.Begin(POINTS, 4.0f);
for (int i = 0; i < edges.Length; ++i)
{
int col = duRGBA(190, 190, 190, 255);
dd.vertex(edges[i].sp, col);
dd.vertex(edges[i].sq, col);
int col = DuRGBA(190, 190, 190, 255);
dd.Vertex(edges[i].sp, col);
dd.Vertex(edges[i].sq, col);
}
dd.end();
dd.End();
}
}
}
if ((option.flags & JumpLinkBuilderToolParams.DRAW_ANNOTATIONS) != 0)
{
dd.begin(QUADS);
dd.Begin(QUADS);
foreach (JumpLink link in links)
{
for (int j = 0; j < link.nspine - 1; ++j)
{
int u = (j * 255) / link.nspine;
int col = duTransCol(duLerpCol(col0, col1, u), 128);
dd.vertex(link.spine1[j * 3], link.spine1[j * 3 + 1], link.spine1[j * 3 + 2], col);
dd.vertex(link.spine1[(j + 1) * 3], link.spine1[(j + 1) * 3 + 1], link.spine1[(j + 1) * 3 + 2],
int col = DuTransCol(DuLerpCol(col0, col1, u), 128);
dd.Vertex(link.spine1[j * 3], link.spine1[j * 3 + 1], link.spine1[j * 3 + 2], col);
dd.Vertex(link.spine1[(j + 1) * 3], link.spine1[(j + 1) * 3 + 1], link.spine1[(j + 1) * 3 + 2],
col);
dd.vertex(link.spine0[(j + 1) * 3], link.spine0[(j + 1) * 3 + 1], link.spine0[(j + 1) * 3 + 2],
dd.Vertex(link.spine0[(j + 1) * 3], link.spine0[(j + 1) * 3 + 1], link.spine0[(j + 1) * 3 + 2],
col);
dd.vertex(link.spine0[j * 3], link.spine0[j * 3 + 1], link.spine0[j * 3 + 2], col);
dd.Vertex(link.spine0[j * 3], link.spine0[j * 3 + 1], link.spine0[j * 3 + 2], col);
}
}
dd.end();
dd.begin(LINES, 3.0f);
dd.End();
dd.Begin(LINES, 3.0f);
foreach (JumpLink link in links)
{
for (int j = 0; j < link.nspine - 1; ++j)
{
// int u = (j*255)/link.nspine;
int col = duTransCol(duDarkenCol(col1) /*duDarkenCol(duLerpCol(col0,col1,u))*/, 128);
int col = DuTransCol(DuDarkenCol(col1) /*DuDarkenCol(DuLerpCol(col0,col1,u))*/, 128);
dd.vertex(link.spine0[j * 3], link.spine0[j * 3 + 1], link.spine0[j * 3 + 2], col);
dd.vertex(link.spine0[(j + 1) * 3], link.spine0[(j + 1) * 3 + 1], link.spine0[(j + 1) * 3 + 2],
dd.Vertex(link.spine0[j * 3], link.spine0[j * 3 + 1], link.spine0[j * 3 + 2], col);
dd.Vertex(link.spine0[(j + 1) * 3], link.spine0[(j + 1) * 3 + 1], link.spine0[(j + 1) * 3 + 2],
col);
dd.vertex(link.spine1[j * 3], link.spine1[j * 3 + 1], link.spine1[j * 3 + 2], col);
dd.vertex(link.spine1[(j + 1) * 3], link.spine1[(j + 1) * 3 + 1], link.spine1[(j + 1) * 3 + 2],
dd.Vertex(link.spine1[j * 3], link.spine1[j * 3 + 1], link.spine1[j * 3 + 2], col);
dd.Vertex(link.spine1[(j + 1) * 3], link.spine1[(j + 1) * 3 + 1], link.spine1[(j + 1) * 3 + 2],
col);
}
dd.vertex(link.spine0[0], link.spine0[1], link.spine0[2], duDarkenCol(col1));
dd.vertex(link.spine1[0], link.spine1[1], link.spine1[2], duDarkenCol(col1));
dd.Vertex(link.spine0[0], link.spine0[1], link.spine0[2], DuDarkenCol(col1));
dd.Vertex(link.spine1[0], link.spine1[1], link.spine1[2], DuDarkenCol(col1));
dd.vertex(link.spine0[(link.nspine - 1) * 3], link.spine0[(link.nspine - 1) * 3 + 1],
link.spine0[(link.nspine - 1) * 3 + 2], duDarkenCol(col1));
dd.vertex(link.spine1[(link.nspine - 1) * 3], link.spine1[(link.nspine - 1) * 3 + 1],
link.spine1[(link.nspine - 1) * 3 + 2], duDarkenCol(col1));
dd.Vertex(link.spine0[(link.nspine - 1) * 3], link.spine0[(link.nspine - 1) * 3 + 1],
link.spine0[(link.nspine - 1) * 3 + 2], DuDarkenCol(col1));
dd.Vertex(link.spine1[(link.nspine - 1) * 3], link.spine1[(link.nspine - 1) * 3 + 1],
link.spine1[(link.nspine - 1) * 3 + 2], DuDarkenCol(col1));
}
dd.end();
dd.End();
}
if (annotationBuilder != null)
@ -167,97 +167,97 @@ public class JumpLinkBuilderTool : Tool
{
float r = link.start.height;
int col = duLerpCol(duRGBA(255, 192, 0, 255),
duRGBA(255, 255, 255, 255), 64);
int cola = duTransCol(col, 192);
int colb = duRGBA(255, 255, 255, 255);
int col = DuLerpCol(DuRGBA(255, 192, 0, 255),
DuRGBA(255, 255, 255, 255), 64);
int cola = DuTransCol(col, 192);
int colb = DuRGBA(255, 255, 255, 255);
// Start segment.
dd.begin(LINES, 3.0f);
dd.vertex(link.start.p, col);
dd.vertex(link.start.q, col);
dd.end();
dd.Begin(LINES, 3.0f);
dd.Vertex(link.start.p, col);
dd.Vertex(link.start.q, col);
dd.End();
dd.begin(LINES, 1.0f);
dd.vertex(link.start.p.x, link.start.p.y, link.start.p.z, colb);
dd.vertex(link.start.p.x, link.start.p.y + r, link.start.p.z, colb);
dd.vertex(link.start.p.x, link.start.p.y + r, link.start.p.z, colb);
dd.vertex(link.start.q.x, link.start.q.y + r, link.start.q.z, colb);
dd.vertex(link.start.q.x, link.start.q.y + r, link.start.q.z, colb);
dd.vertex(link.start.q.x, link.start.q.y, link.start.q.z, colb);
dd.vertex(link.start.q.x, link.start.q.y, link.start.q.z, colb);
dd.vertex(link.start.p.x, link.start.p.y, link.start.p.z, colb);
dd.end();
dd.Begin(LINES, 1.0f);
dd.Vertex(link.start.p.x, link.start.p.y, link.start.p.z, colb);
dd.Vertex(link.start.p.x, link.start.p.y + r, link.start.p.z, colb);
dd.Vertex(link.start.p.x, link.start.p.y + r, link.start.p.z, colb);
dd.Vertex(link.start.q.x, link.start.q.y + r, link.start.q.z, colb);
dd.Vertex(link.start.q.x, link.start.q.y + r, link.start.q.z, colb);
dd.Vertex(link.start.q.x, link.start.q.y, link.start.q.z, colb);
dd.Vertex(link.start.q.x, link.start.q.y, link.start.q.z, colb);
dd.Vertex(link.start.p.x, link.start.p.y, link.start.p.z, colb);
dd.End();
GroundSegment end = link.end;
r = end.height;
// End segment.
dd.begin(LINES, 3.0f);
dd.vertex(end.p, col);
dd.vertex(end.q, col);
dd.end();
dd.Begin(LINES, 3.0f);
dd.Vertex(end.p, col);
dd.Vertex(end.q, col);
dd.End();
dd.begin(LINES, 1.0f);
dd.vertex(end.p.x, end.p.y, end.p.z, colb);
dd.vertex(end.p.x, end.p.y + r, end.p.z, colb);
dd.vertex(end.p.x, end.p.y + r, end.p.z, colb);
dd.vertex(end.q.x, end.q.y + r, end.q.z, colb);
dd.vertex(end.q.x, end.q.y + r, end.q.z, colb);
dd.vertex(end.q.x, end.q.y, end.q.z, colb);
dd.vertex(end.q.x, end.q.y, end.q.z, colb);
dd.vertex(end.p.x, end.p.y, end.p.z, colb);
dd.end();
dd.Begin(LINES, 1.0f);
dd.Vertex(end.p.x, end.p.y, end.p.z, colb);
dd.Vertex(end.p.x, end.p.y + r, end.p.z, colb);
dd.Vertex(end.p.x, end.p.y + r, end.p.z, colb);
dd.Vertex(end.q.x, end.q.y + r, end.q.z, colb);
dd.Vertex(end.q.x, end.q.y + r, end.q.z, colb);
dd.Vertex(end.q.x, end.q.y, end.q.z, colb);
dd.Vertex(end.q.x, end.q.y, end.q.z, colb);
dd.Vertex(end.p.x, end.p.y, end.p.z, colb);
dd.End();
dd.begin(LINES, 4.0f);
drawTrajectory(dd, link, link.start.p, end.p, link.trajectory, cola);
drawTrajectory(dd, link, link.start.q, end.q, link.trajectory, cola);
dd.end();
dd.Begin(LINES, 4.0f);
DrawTrajectory(dd, link, link.start.p, end.p, link.trajectory, cola);
DrawTrajectory(dd, link, link.start.q, end.q, link.trajectory, cola);
dd.End();
dd.begin(LINES, 8.0f);
dd.vertex(link.start.p, duDarkenCol(col));
dd.vertex(link.start.q, duDarkenCol(col));
dd.vertex(end.p, duDarkenCol(col));
dd.vertex(end.q, duDarkenCol(col));
dd.end();
dd.Begin(LINES, 8.0f);
dd.Vertex(link.start.p, DuDarkenCol(col));
dd.Vertex(link.start.q, DuDarkenCol(col));
dd.Vertex(end.p, DuDarkenCol(col));
dd.Vertex(end.q, DuDarkenCol(col));
dd.End();
int colm = duRGBA(255, 255, 255, 255);
dd.begin(LINES, 3.0f);
dd.vertex(link.start.p, colm);
dd.vertex(link.start.q, colm);
dd.vertex(end.p, colm);
dd.vertex(end.q, colm);
dd.end();
int colm = DuRGBA(255, 255, 255, 255);
dd.Begin(LINES, 3.0f);
dd.Vertex(link.start.p, colm);
dd.Vertex(link.start.q, colm);
dd.Vertex(end.p, colm);
dd.Vertex(end.q, colm);
dd.End();
}
if ((option.flags & JumpLinkBuilderToolParams.DRAW_LAND_SAMPLES) != 0)
{
dd.begin(POINTS, 8.0f);
dd.Begin(POINTS, 8.0f);
for (int i = 0; i < link.start.gsamples.Length; ++i)
{
GroundSample s = link.start.gsamples[i];
float u = i / (float)(link.start.gsamples.Length - 1);
Vector3f spt = vLerp(link.start.p, link.start.q, u);
int col = duRGBA(48, 16, 16, 255); // duRGBA(255,(s->flags & 4)?255:0,0,255);
Vector3f spt = VLerp(link.start.p, link.start.q, u);
int col = DuRGBA(48, 16, 16, 255); // DuRGBA(255,(s->flags & 4)?255:0,0,255);
float off = 0.1f;
if (!s.validHeight)
{
off = 0;
col = duRGBA(220, 32, 32, 255);
col = DuRGBA(220, 32, 32, 255);
}
spt.y = s.p.y + off;
dd.vertex(spt, col);
dd.Vertex(spt, col);
}
dd.end();
dd.End();
dd.begin(POINTS, 4.0f);
dd.Begin(POINTS, 4.0f);
for (int i = 0; i < link.start.gsamples.Length; ++i)
{
GroundSample s = link.start.gsamples[i];
float u = i / (float)(link.start.gsamples.Length - 1);
Vector3f spt = vLerp(link.start.p, link.start.q, u);
int col = duRGBA(255, 255, 255, 255);
Vector3f spt = VLerp(link.start.p, link.start.q, u);
int col = DuRGBA(255, 255, 255, 255);
float off = 0;
if (s.validHeight)
{
@ -265,38 +265,38 @@ public class JumpLinkBuilderTool : Tool
}
spt.y = s.p.y + off;
dd.vertex(spt, col);
dd.Vertex(spt, col);
}
dd.end();
dd.End();
{
GroundSegment end = link.end;
dd.begin(POINTS, 8.0f);
dd.Begin(POINTS, 8.0f);
for (int i = 0; i < end.gsamples.Length; ++i)
{
GroundSample s = end.gsamples[i];
float u = i / (float)(end.gsamples.Length - 1);
Vector3f spt = vLerp(end.p, end.q, u);
int col = duRGBA(48, 16, 16, 255); // duRGBA(255,(s->flags & 4)?255:0,0,255);
Vector3f spt = VLerp(end.p, end.q, u);
int col = DuRGBA(48, 16, 16, 255); // DuRGBA(255,(s->flags & 4)?255:0,0,255);
float off = 0.1f;
if (!s.validHeight)
{
off = 0;
col = duRGBA(220, 32, 32, 255);
col = DuRGBA(220, 32, 32, 255);
}
spt.y = s.p.y + off;
dd.vertex(spt, col);
dd.Vertex(spt, col);
}
dd.end();
dd.begin(POINTS, 4.0f);
dd.End();
dd.Begin(POINTS, 4.0f);
for (int i = 0; i < end.gsamples.Length; ++i)
{
GroundSample s = end.gsamples[i];
float u = i / (float)(end.gsamples.Length - 1);
Vector3f spt = vLerp(end.p, end.q, u);
int col = duRGBA(255, 255, 255, 255);
Vector3f spt = VLerp(end.p, end.q, u);
int col = DuRGBA(255, 255, 255, 255);
float off = 0;
if (s.validHeight)
{
@ -304,29 +304,29 @@ public class JumpLinkBuilderTool : Tool
}
spt.y = s.p.y + off;
dd.vertex(spt, col);
dd.Vertex(spt, col);
}
dd.end();
dd.End();
}
}
}
}
dd.depthMask(true);
dd.DepthMask(true);
}
private void drawTrajectory(RecastDebugDraw dd, JumpLink link, Vector3f pa, Vector3f pb, Trajectory tra, int cola)
private void DrawTrajectory(RecastDebugDraw dd, JumpLink link, Vector3f pa, Vector3f pb, Trajectory tra, int cola)
{
}
public override void handleUpdate(float dt)
public override void HandleUpdate(float dt)
{
}
public override void layout()
public override void Layout()
{
if (0 >= sample.getRecastResults().Count)
if (0 >= sample.GetRecastResults().Count)
return;
ImGui.Text("Options");
@ -371,27 +371,27 @@ public class JumpLinkBuilderTool : Tool
{
if (annotationBuilder == null)
{
if (sample != null && 0 < sample.getRecastResults().Count)
if (sample != null && 0 < sample.GetRecastResults().Count)
{
annotationBuilder = new JumpLinkBuilder(sample.getRecastResults());
annotationBuilder = new JumpLinkBuilder(sample.GetRecastResults());
}
}
links.Clear();
if (annotationBuilder != null)
{
float cellSize = sample.getSettingsUI().getCellSize();
float agentHeight = sample.getSettingsUI().getAgentHeight();
float agentRadius = sample.getSettingsUI().getAgentRadius();
float agentClimb = sample.getSettingsUI().getAgentMaxClimb();
float cellHeight = sample.getSettingsUI().getCellHeight();
float cellSize = sample.GetSettingsUI().GetCellSize();
float agentHeight = sample.GetSettingsUI().GetAgentHeight();
float agentRadius = sample.GetSettingsUI().GetAgentRadius();
float agentClimb = sample.GetSettingsUI().GetAgentMaxClimb();
float cellHeight = sample.GetSettingsUI().GetCellHeight();
if ((option.buildTypes & JumpLinkType.EDGE_CLIMB_DOWN.Bit) != 0)
{
JumpLinkBuilderConfig config = new JumpLinkBuilderConfig(cellSize, cellHeight, agentRadius,
agentHeight, agentClimb, option.groundTolerance, -agentRadius * 0.2f,
cellSize + 2 * agentRadius + option.climbDownDistance,
-option.climbDownMaxHeight, -option.climbDownMinHeight, 0);
links.AddRange(annotationBuilder.build(config, JumpLinkType.EDGE_CLIMB_DOWN));
links.AddRange(annotationBuilder.Build(config, JumpLinkType.EDGE_CLIMB_DOWN));
}
if ((option.buildTypes & JumpLinkType.EDGE_JUMP.Bit) != 0)
@ -400,17 +400,17 @@ public class JumpLinkBuilderTool : Tool
agentHeight, agentClimb, option.groundTolerance, -agentRadius * 0.2f,
option.edgeJumpEndDistance, -option.edgeJumpDownMaxHeight,
option.edgeJumpUpMaxHeight, option.edgeJumpHeight);
links.AddRange(annotationBuilder.build(config, JumpLinkType.EDGE_JUMP));
links.AddRange(annotationBuilder.Build(config, JumpLinkType.EDGE_JUMP));
}
if (buildOffMeshConnections)
{
DemoInputGeomProvider geom = sample.getInputGeom();
DemoInputGeomProvider geom = sample.GetInputGeom();
if (geom != null)
{
int area = SampleAreaModifications.SAMPLE_POLYAREA_TYPE_JUMP_AUTO;
geom.removeOffMeshConnections(c => c.area == area);
links.forEach(l => addOffMeshLink(l, geom, agentRadius));
geom.RemoveOffMeshConnections(c => c.area == area);
links.ForEach(l => AddOffMeshLink(l, geom, agentRadius));
}
}
}
@ -427,7 +427,7 @@ public class JumpLinkBuilderTool : Tool
//option.flags = newFlags;
}
private void addOffMeshLink(JumpLink link, DemoInputGeomProvider geom, float agentRadius)
private void AddOffMeshLink(JumpLink link, DemoInputGeomProvider geom, float agentRadius)
{
int area = SampleAreaModifications.SAMPLE_POLYAREA_TYPE_JUMP_AUTO;
int flags = SampleAreaModifications.SAMPLE_POLYFLAGS_JUMP;
@ -436,15 +436,15 @@ public class JumpLinkBuilderTool : Tool
{
Vector3f p = link.startSamples[i].p;
Vector3f q = link.endSamples[i].p;
if (i == 0 || vDist2D(prev, p) > agentRadius)
if (i == 0 || VDist2D(prev, p) > agentRadius)
{
geom.addOffMeshConnection(p, q, agentRadius, false, area, flags);
geom.AddOffMeshConnection(p, q, agentRadius, false, area, flags);
prev = p;
}
}
}
public override string getName()
public override string GetName()
{
return "Annotation Builder";
}

View File

@ -36,14 +36,14 @@ public class OffMeshConnectionTool : Tool
private Vector3f hitPos;
private int bidir;
public override void setSample(Sample m_sample)
public override void SetSample(Sample m_sample)
{
sample = m_sample;
}
public override void handleClick(Vector3f s, Vector3f p, bool shift)
public override void HandleClick(Vector3f s, Vector3f p, bool shift)
{
DemoInputGeomProvider geom = sample.getInputGeom();
DemoInputGeomProvider geom = sample.GetInputGeom();
if (geom == null)
{
return;
@ -55,10 +55,10 @@ public class OffMeshConnectionTool : Tool
// Find nearest link end-point
float nearestDist = float.MaxValue;
DemoOffMeshConnection nearestConnection = null;
foreach (DemoOffMeshConnection offMeshCon in geom.getOffMeshConnections())
foreach (DemoOffMeshConnection offMeshCon in geom.GetOffMeshConnections())
{
float d = Math.Min(RecastMath.vDistSqr(p, offMeshCon.verts, 0), RecastMath.vDistSqr(p, offMeshCon.verts, 3));
if (d < nearestDist && Math.Sqrt(d) < sample.getSettingsUI().getAgentRadius())
float d = Math.Min(RecastMath.VDistSqr(p, offMeshCon.verts, 0), RecastMath.VDistSqr(p, offMeshCon.verts, 3));
if (d < nearestDist && Math.Sqrt(d) < sample.GetSettingsUI().GetAgentRadius())
{
nearestDist = d;
nearestConnection = offMeshCon;
@ -67,7 +67,7 @@ public class OffMeshConnectionTool : Tool
if (nearestConnection != null)
{
geom.getOffMeshConnections().Remove(nearestConnection);
geom.GetOffMeshConnections().Remove(nearestConnection);
}
}
else
@ -82,46 +82,46 @@ public class OffMeshConnectionTool : Tool
{
int area = SampleAreaModifications.SAMPLE_POLYAREA_TYPE_JUMP;
int flags = SampleAreaModifications.SAMPLE_POLYFLAGS_JUMP;
geom.addOffMeshConnection(hitPos, p, sample.getSettingsUI().getAgentRadius(), 0 == bidir, area, flags);
geom.AddOffMeshConnection(hitPos, p, sample.GetSettingsUI().GetAgentRadius(), 0 == bidir, area, flags);
hitPosSet = false;
}
}
}
public override void handleRender(NavMeshRenderer renderer)
public override void HandleRender(NavMeshRenderer renderer)
{
if (sample == null)
{
return;
}
RecastDebugDraw dd = renderer.getDebugDraw();
float s = sample.getSettingsUI().getAgentRadius();
RecastDebugDraw dd = renderer.GetDebugDraw();
float s = sample.GetSettingsUI().GetAgentRadius();
if (hitPosSet)
{
dd.debugDrawCross(hitPos.x, hitPos.y + 0.1f, hitPos.z, s, duRGBA(0, 0, 0, 128), 2.0f);
dd.DebugDrawCross(hitPos.x, hitPos.y + 0.1f, hitPos.z, s, DuRGBA(0, 0, 0, 128), 2.0f);
}
DemoInputGeomProvider geom = sample.getInputGeom();
DemoInputGeomProvider geom = sample.GetInputGeom();
if (geom != null)
{
renderer.drawOffMeshConnections(geom, true);
renderer.DrawOffMeshConnections(geom, true);
}
}
public override void layout()
public override void Layout()
{
ImGui.RadioButton("One Way", ref bidir, 0);
ImGui.RadioButton("Bidirectional", ref bidir, 1);
}
public override string getName()
public override string GetName()
{
return "Create Off-Mesh Links";
}
public override void handleUpdate(float dt)
public override void HandleUpdate(float dt)
{
// TODO Auto-generated method stub
}

File diff suppressed because it is too large Load Diff

View File

@ -26,19 +26,19 @@ namespace DotRecast.Recast.Demo.Tools;
public abstract class Tool
{
public abstract void setSample(Sample m_sample);
public abstract void SetSample(Sample m_sample);
public abstract void handleClick(Vector3f s, Vector3f p, bool shift);
public abstract void HandleClick(Vector3f s, Vector3f p, bool shift);
public abstract void handleRender(NavMeshRenderer renderer);
public abstract void HandleRender(NavMeshRenderer renderer);
public abstract void handleUpdate(float dt);
public abstract void HandleUpdate(float dt);
public abstract void layout();
public abstract void Layout();
public abstract string getName();
public abstract string GetName();
public virtual void handleClickRay(Vector3f start, float[] direction, bool shift)
public virtual void HandleClickRay(Vector3f start, float[] direction, bool shift)
{
// ...
}

View File

@ -22,5 +22,5 @@ namespace DotRecast.Recast.Demo.Tools;
public interface ToolUIModule
{
void layout(IWindow ctx);
void Layout(IWindow ctx);
}

View File

@ -59,9 +59,9 @@ public class RcSettingsView : IRcView
private bool tiled = false;
private int tileSize = 32;
// public readonly NkColor white = NkColor.create();
// public readonly NkColor background = NkColor.create();
// public readonly NkColor transparent = NkColor.create();
// public readonly NkColor white = NkColor.Create();
// public readonly NkColor background = NkColor.Create();
// public readonly NkColor transparent = NkColor.Create();
private bool buildTriggered;
private long buildTime;
private readonly int[] voxels = new int[2];
@ -154,7 +154,7 @@ public class RcSettingsView : IRcView
ImGui.Text("Partitioning");
ImGui.Separator();
PartitionType.Values.forEach(partition =>
PartitionType.Values.ForEach(partition =>
{
var label = partition.Name.Substring(0, 1).ToUpper()
+ partition.Name.Substring(1).ToLower();
@ -226,145 +226,145 @@ public class RcSettingsView : IRcView
ImGui.Text("Draw");
ImGui.Separator();
DrawMode.Values.forEach(dm => { ImGui.RadioButton(dm.Text, ref drawMode, dm.Idx); });
DrawMode.Values.ForEach(dm => { ImGui.RadioButton(dm.Text, ref drawMode, dm.Idx); });
ImGui.NewLine();
ImGui.End();
}
public float getCellSize()
public float GetCellSize()
{
return cellSize;
}
public float getCellHeight()
public float GetCellHeight()
{
return cellHeight;
}
public float getAgentHeight()
public float GetAgentHeight()
{
return agentHeight;
}
public float getAgentRadius()
public float GetAgentRadius()
{
return agentRadius;
}
public float getAgentMaxClimb()
public float GetAgentMaxClimb()
{
return agentMaxClimb;
}
public float getAgentMaxSlope()
public float GetAgentMaxSlope()
{
return agentMaxSlope;
}
public int getMinRegionSize()
public int GetMinRegionSize()
{
return minRegionSize;
}
public int getMergedRegionSize()
public int GetMergedRegionSize()
{
return mergedRegionSize;
}
public PartitionType getPartitioning()
public PartitionType GetPartitioning()
{
return partitioning;
}
public bool isBuildTriggered()
public bool IsBuildTriggered()
{
return buildTriggered;
}
public bool isFilterLowHangingObstacles()
public bool IsFilterLowHangingObstacles()
{
return filterLowHangingObstacles;
}
public bool isFilterLedgeSpans()
public bool IsFilterLedgeSpans()
{
return filterLedgeSpans;
}
public bool isFilterWalkableLowHeightSpans()
public bool IsFilterWalkableLowHeightSpans()
{
return filterWalkableLowHeightSpans;
}
public void setBuildTime(long buildTime)
public void SetBuildTime(long buildTime)
{
this.buildTime = buildTime;
}
public DrawMode getDrawMode()
public DrawMode GetDrawMode()
{
return DrawMode.Values[drawMode];
}
public float getEdgeMaxLen()
public float GetEdgeMaxLen()
{
return edgeMaxLen;
}
public float getEdgeMaxError()
public float GetEdgeMaxError()
{
return edgeMaxError;
}
public int getVertsPerPoly()
public int GetVertsPerPoly()
{
return vertsPerPoly;
}
public float getDetailSampleDist()
public float GetDetailSampleDist()
{
return detailSampleDist;
}
public float getDetailSampleMaxError()
public float GetDetailSampleMaxError()
{
return detailSampleMaxError;
}
public void setVoxels(int[] voxels)
public void SetVoxels(int[] voxels)
{
this.voxels[0] = voxels[0];
this.voxels[1] = voxels[1];
}
public bool isTiled()
public bool IsTiled()
{
return tiled;
}
public int getTileSize()
public int GetTileSize()
{
return tileSize;
}
public void setTiles(int[] tiles)
public void SetTiles(int[] tiles)
{
this.tiles[0] = tiles[0];
this.tiles[1] = tiles[1];
}
public void setMaxTiles(int maxTiles)
public void SetMaxTiles(int maxTiles)
{
this.maxTiles = maxTiles;
}
public void setMaxPolys(int maxPolys)
public void SetMaxPolys(int maxPolys)
{
this.maxPolys = maxPolys;
}
public bool isMeshInputTrigerred()
public bool IsMeshInputTrigerred()
{
return meshInputTrigerred;
}
@ -374,7 +374,7 @@ public class RcSettingsView : IRcView
return meshInputFilePath;
}
public bool isNavMeshInputTrigerred()
public bool IsNavMeshInputTrigerred()
{
return navMeshInputTrigerred;
}

View File

@ -47,54 +47,54 @@ public class RecastDemoCanvas
view.Bind(this);
}
// setupClipboard(window);
// glfwSetCharCallback(window, (w, codepoint) => nk_input_unicode(ctx, codepoint));
// SetupClipboard(window);
// GlfwSetCharCallback(window, (w, codepoint) => Nk_input_unicode(ctx, codepoint));
// glContext = new NuklearGL(this);
}
private void setupClipboard(long window)
private void SetupClipboard(long window)
{
// ctx.clip().copy((handle, text, len) => {
// ctx.Clip().copy((handle, text, len) => {
// if (len == 0) {
// return;
// }
//
// try (MemoryStack stack = stackPush()) {
// ByteBuffer str = stack.malloc(len + 1);
// memCopy(text, memAddress(str), len);
// str.put(len, (byte) 0);
// glfwSetClipboardString(window, str);
// try (MemoryStack stack = StackPush()) {
// ByteBuffer str = stack.Malloc(len + 1);
// MemCopy(text, MemAddress(str), len);
// str.Put(len, (byte) 0);
// GlfwSetClipboardString(window, str);
// }
// });
// ctx.clip().paste((handle, edit) => {
// long text = nglfwGetClipboardString(window);
// ctx.Clip().paste((handle, edit) => {
// long text = NglfwGetClipboardString(window);
// if (text != NULL) {
// nnk_textedit_paste(edit, text, nnk_strlen(text));
// Nnk_textedit_paste(edit, text, Nnk_strlen(text));
// }
// });
}
public void inputBegin()
public void InputBegin()
{
//nk_input_begin(ctx);
//Nk_input_begin(ctx);
}
public void inputEnd(IWindow win)
public void InputEnd(IWindow win)
{
// NkMouse mouse = ctx.input().mouse();
// if (mouse.grab()) {
// glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
// } else if (mouse.grabbed()) {
// float prevX = mouse.prev().x();
// float prevY = mouse.prev().y();
// glfwSetCursorPos(win, prevX, prevY);
// mouse.pos().x(prevX);
// mouse.pos().y(prevY);
// } else if (mouse.ungrab()) {
// glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
// NkMouse mouse = ctx.Input().Mouse();
// if (mouse.Grab()) {
// GlfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
// } else if (mouse.Grabbed()) {
// float prevX = mouse.Prev().x();
// float prevY = mouse.Prev().y();
// GlfwSetCursorPos(win, prevX, prevY);
// mouse.Pos().x(prevX);
// mouse.Pos().y(prevY);
// } else if (mouse.Ungrab()) {
// GlfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
// }
// nk_input_end(ctx);
// Nk_input_end(ctx);
}
public void Update(double dt)

View File

@ -17,17 +17,17 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
using System;
using System.Numerics;
using DotRecast.Core;
using DotRecast.Recast.Demo.Tools;
using DotRecast.Recast.Demo.UI;
using ImGuiNET;
namespace DotRecast.Recast.Demo.UI;
public class ToolsView : IRcView
{
//private readonly NkColor white = NkColor.create();
//private readonly NkColor white = NkColor.Create();
private int _currentToolIdx = 0;
private Tool currentTool;
private bool enabled;
@ -64,7 +64,7 @@ public class ToolsView : IRcView
for (int i = 0; i < tools.Length; ++i)
{
var tool = tools[i];
ImGui.RadioButton(tool.getName(), ref _currentToolIdx, i);
ImGui.RadioButton(tool.GetName(), ref _currentToolIdx, i);
}
ImGui.NewLine();
@ -76,30 +76,30 @@ public class ToolsView : IRcView
}
currentTool = tools[_currentToolIdx];
ImGui.Text(currentTool.getName());
ImGui.Text(currentTool.GetName());
ImGui.Separator();
currentTool.layout();
currentTool.Layout();
ImGui.End();
}
public void setEnabled(bool enabled)
public void SetEnabled(bool enabled)
{
this.enabled = enabled;
}
public Tool getTool()
public Tool GetTool()
{
return currentTool;
}
public void setSample(Sample sample)
public void SetSample(Sample sample)
{
tools.forEach(t => t.setSample(sample));
tools.ForEach(t => t.SetSample(sample));
}
public void handleUpdate(float dt)
public void HandleUpdate(float dt)
{
tools.forEach(t => t.handleUpdate(dt));
tools.ForEach(t => t.HandleUpdate(dt));
}
}

View File

@ -58,12 +58,12 @@ namespace DotRecast.Recast
Mask = other.Mask;
}
public int getMaskedValue()
public int GetMaskedValue()
{
return Value & Mask;
}
public int apply(int area)
public int Apply(int area)
{
return ((Value & Mask) | (area & ~Mask));
}

View File

@ -53,7 +53,7 @@ namespace DotRecast.Recast.Geom
int ntris;
int maxTrisPerChunk;
private void calcExtends(BoundsItem[] items, int imin, int imax, ref Vector2f bmin, ref Vector2f bmax)
private void CalcExtends(BoundsItem[] items, int imin, int imax, ref Vector2f bmin, ref Vector2f bmax)
{
bmin.x = items[imin].bmin.x;
bmin.y = items[imin].bmin.y;
@ -86,12 +86,12 @@ namespace DotRecast.Recast.Geom
}
}
private int longestAxis(float x, float y)
private int LongestAxis(float x, float y)
{
return y > x ? 1 : 0;
}
private void subdivide(BoundsItem[] items, int imin, int imax, int trisPerChunk, List<ChunkyTriMeshNode> nodes, int[] inTris)
private void Subdivide(BoundsItem[] items, int imin, int imax, int trisPerChunk, List<ChunkyTriMeshNode> nodes, int[] inTris)
{
int inum = imax - imin;
@ -101,7 +101,7 @@ namespace DotRecast.Recast.Geom
if (inum <= trisPerChunk)
{
// Leaf
calcExtends(items, imin, imax, ref node.bmin, ref node.bmax);
CalcExtends(items, imin, imax, ref node.bmin, ref node.bmax);
// Copy triangles.
node.i = nodes.Count;
@ -119,9 +119,9 @@ namespace DotRecast.Recast.Geom
else
{
// Split
calcExtends(items, imin, imax, ref node.bmin, ref node.bmax);
CalcExtends(items, imin, imax, ref node.bmin, ref node.bmax);
int axis = longestAxis(node.bmax.x - node.bmin.x, node.bmax.y - node.bmin.y);
int axis = LongestAxis(node.bmax.x - node.bmin.x, node.bmax.y - node.bmin.y);
if (axis == 0)
{
@ -137,9 +137,9 @@ namespace DotRecast.Recast.Geom
int isplit = imin + inum / 2;
// Left
subdivide(items, imin, isplit, trisPerChunk, nodes, inTris);
Subdivide(items, imin, isplit, trisPerChunk, nodes, inTris);
// Right
subdivide(items, isplit, imax, trisPerChunk, nodes, inTris);
Subdivide(items, isplit, imax, trisPerChunk, nodes, inTris);
// Negative index means escape.
node.i = -nodes.Count;
@ -189,7 +189,7 @@ namespace DotRecast.Recast.Geom
}
}
subdivide(items, 0, ntris, trisPerChunk, nodes, tris);
Subdivide(items, 0, ntris, trisPerChunk, nodes, tris);
// Calc max tris per node.
maxTrisPerChunk = 0;
@ -208,7 +208,7 @@ namespace DotRecast.Recast.Geom
}
}
private bool checkOverlapRect(float[] amin, float[] amax, Vector2f bmin, Vector2f bmax)
private bool CheckOverlapRect(float[] amin, float[] amax, Vector2f bmin, Vector2f bmax)
{
bool overlap = true;
overlap = (amin[0] > bmax.x || amax[0] < bmin.x) ? false : overlap;
@ -216,7 +216,7 @@ namespace DotRecast.Recast.Geom
return overlap;
}
public List<ChunkyTriMeshNode> getChunksOverlappingRect(float[] bmin, float[] bmax)
public List<ChunkyTriMeshNode> GetChunksOverlappingRect(float[] bmin, float[] bmax)
{
// Traverse tree
List<ChunkyTriMeshNode> ids = new List<ChunkyTriMeshNode>();
@ -224,7 +224,7 @@ namespace DotRecast.Recast.Geom
while (i < nodes.Count)
{
ChunkyTriMeshNode node = nodes[i];
bool overlap = checkOverlapRect(bmin, bmax, node.bmin, node.bmax);
bool overlap = CheckOverlapRect(bmin, bmax, node.bmin, node.bmax);
bool isLeafNode = node.i >= 0;
if (isLeafNode && overlap)
@ -245,7 +245,7 @@ namespace DotRecast.Recast.Geom
return ids;
}
public List<ChunkyTriMeshNode> getChunksOverlappingSegment(float[] p, float[] q)
public List<ChunkyTriMeshNode> GetChunksOverlappingSegment(float[] p, float[] q)
{
// Traverse tree
List<ChunkyTriMeshNode> ids = new List<ChunkyTriMeshNode>();
@ -253,7 +253,7 @@ namespace DotRecast.Recast.Geom
while (i < nodes.Count)
{
ChunkyTriMeshNode node = nodes[i];
bool overlap = checkOverlapSegment(p, q, node.bmin, node.bmax);
bool overlap = CheckOverlapSegment(p, q, node.bmin, node.bmax);
bool isLeafNode = node.i >= 0;
if (isLeafNode && overlap)
@ -274,7 +274,7 @@ namespace DotRecast.Recast.Geom
return ids;
}
private bool checkOverlapSegment(float[] p, float[] q, Vector2f bmin, Vector2f bmax)
private bool CheckOverlapSegment(float[] p, float[] q, Vector2f bmin, Vector2f bmax)
{
float EPSILON = 1e-6f;

View File

@ -22,6 +22,6 @@ namespace DotRecast.Recast.Geom
{
public interface ConvexVolumeProvider
{
IList<ConvexVolume> convexVolumes();
IList<ConvexVolume> ConvexVolumes();
}
}

View File

@ -25,10 +25,10 @@ namespace DotRecast.Recast.Geom
{
public interface InputGeomProvider : ConvexVolumeProvider
{
Vector3f getMeshBoundsMin();
Vector3f GetMeshBoundsMin();
Vector3f getMeshBoundsMax();
Vector3f GetMeshBoundsMax();
IEnumerable<TriMesh> meshes();
IEnumerable<TriMesh> Meshes();
}
}

View File

@ -36,11 +36,11 @@ namespace DotRecast.Recast.Geom
private readonly TriMesh _mesh;
public SimpleInputGeomProvider(List<float> vertexPositions, List<int> meshFaces)
: this(mapVertices(vertexPositions), mapFaces(meshFaces))
: this(MapVertices(vertexPositions), MapFaces(meshFaces))
{
}
private static int[] mapFaces(List<int> meshFaces)
private static int[] MapFaces(List<int> meshFaces)
{
int[] faces = new int[meshFaces.Count];
for (int i = 0; i < faces.Length; i++)
@ -51,7 +51,7 @@ namespace DotRecast.Recast.Geom
return faces;
}
private static float[] mapVertices(List<float> vertexPositions)
private static float[] MapVertices(List<float> vertexPositions)
{
float[] vertices = new float[vertexPositions.Count];
for (int i = 0; i < vertices.Length; i++)
@ -67,36 +67,36 @@ namespace DotRecast.Recast.Geom
this.vertices = vertices;
this.faces = faces;
normals = new float[faces.Length];
calculateNormals();
CalculateNormals();
bmin = Vector3f.Zero;
bmax = Vector3f.Zero;
RecastVectors.copy(ref bmin, vertices, 0);
RecastVectors.copy(ref bmax, vertices, 0);
RecastVectors.Copy(ref bmin, vertices, 0);
RecastVectors.Copy(ref bmax, vertices, 0);
for (int i = 1; i < vertices.Length / 3; i++)
{
RecastVectors.min(ref bmin, vertices, i * 3);
RecastVectors.max(ref bmax, vertices, i * 3);
RecastVectors.Min(ref bmin, vertices, i * 3);
RecastVectors.Max(ref bmax, vertices, i * 3);
}
_mesh = new TriMesh(vertices, faces);
}
public Vector3f getMeshBoundsMin()
public Vector3f GetMeshBoundsMin()
{
return bmin;
}
public Vector3f getMeshBoundsMax()
public Vector3f GetMeshBoundsMax()
{
return bmax;
}
public IList<ConvexVolume> convexVolumes()
public IList<ConvexVolume> ConvexVolumes()
{
return volumes;
}
public void addConvexVolume(float[] verts, float minh, float maxh, AreaModification areaMod)
public void AddConvexVolume(float[] verts, float minh, float maxh, AreaModification areaMod)
{
ConvexVolume vol = new ConvexVolume();
vol.hmin = minh;
@ -106,12 +106,12 @@ namespace DotRecast.Recast.Geom
volumes.Add(vol);
}
public IEnumerable<TriMesh> meshes()
public IEnumerable<TriMesh> Meshes()
{
return ImmutableArray.Create(_mesh);
}
public void calculateNormals()
public void CalculateNormals()
{
for (int i = 0; i < faces.Length; i += 3)
{

View File

@ -33,33 +33,33 @@ namespace DotRecast.Recast.Geom
{
bmin = Vector3f.Zero;
bmax = Vector3f.Zero;
RecastVectors.copy(ref bmin, vertices, 0);
RecastVectors.copy(ref bmax, vertices, 0);
RecastVectors.Copy(ref bmin, vertices, 0);
RecastVectors.Copy(ref bmax, vertices, 0);
for (int i = 1; i < vertices.Length / 3; i++)
{
RecastVectors.min(ref bmin, vertices, i * 3);
RecastVectors.max(ref bmax, vertices, i * 3);
RecastVectors.Min(ref bmin, vertices, i * 3);
RecastVectors.Max(ref bmax, vertices, i * 3);
}
_mesh = new TriMesh(vertices, faces);
}
public Vector3f getMeshBoundsMin()
public Vector3f GetMeshBoundsMin()
{
return bmin;
}
public Vector3f getMeshBoundsMax()
public Vector3f GetMeshBoundsMax()
{
return bmax;
}
public IEnumerable<TriMesh> meshes()
public IEnumerable<TriMesh> Meshes()
{
return ImmutableArray.Create(_mesh);
}
public IList<ConvexVolume> convexVolumes()
public IList<ConvexVolume> ConvexVolumes()
{
return ImmutableArray<ConvexVolume>.Empty;
}

View File

@ -35,19 +35,19 @@ namespace DotRecast.Recast.Geom
chunkyTriMesh = new ChunkyTriMesh(vertices, faces, faces.Length / 3, 32);
}
public int[] getTris()
public int[] GetTris()
{
return faces;
}
public float[] getVerts()
public float[] GetVerts()
{
return vertices;
}
public List<ChunkyTriMeshNode> getChunksOverlappingRect(float[] bmin, float[] bmax)
public List<ChunkyTriMeshNode> GetChunksOverlappingRect(float[] bmin, float[] bmax)
{
return chunkyTriMesh.getChunksOverlappingRect(bmin, bmax);
return chunkyTriMesh.GetChunksOverlappingRect(bmin, bmax);
}
}
}

View File

@ -31,13 +31,13 @@ namespace DotRecast.Recast
public List<int> meshFaces = new List<int>();
}
public static InputGeomProvider load(byte[] chunck)
public static InputGeomProvider Load(byte[] chunck)
{
var context = loadContext(chunck);
var context = LoadContext(chunck);
return new SimpleInputGeomProvider(context.vertexPositions, context.meshFaces);
}
public static ObjImporterContext loadContext(byte[] chunck)
public static ObjImporterContext LoadContext(byte[] chunck)
{
ObjImporterContext context = new ObjImporterContext();
try
@ -47,7 +47,7 @@ namespace DotRecast.Recast
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
readLine(line, context);
ReadLine(line, context);
}
}
catch (Exception e)
@ -59,23 +59,23 @@ namespace DotRecast.Recast
}
public static void readLine(string line, ObjImporterContext context)
public static void ReadLine(string line, ObjImporterContext context)
{
if (line.StartsWith("v"))
{
readVertex(line, context);
ReadVertex(line, context);
}
else if (line.StartsWith("f"))
{
readFace(line, context);
ReadFace(line, context);
}
}
private static void readVertex(string line, ObjImporterContext context)
private static void ReadVertex(string line, ObjImporterContext context)
{
if (line.StartsWith("v "))
{
float[] vert = readVector3f(line);
float[] vert = ReadVector3f(line);
foreach (float vp in vert)
{
context.vertexPositions.Add(vp);
@ -83,7 +83,7 @@ namespace DotRecast.Recast
}
}
private static float[] readVector3f(string line)
private static float[] ReadVector3f(string line)
{
string[] v = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (v.Length < 4)
@ -94,7 +94,7 @@ namespace DotRecast.Recast
return new float[] { float.Parse(v[1]), float.Parse(v[2]), float.Parse(v[3]) };
}
private static void readFace(string line, ObjImporterContext context)
private static void ReadFace(string line, ObjImporterContext context)
{
string[] v = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (v.Length < 4)
@ -104,21 +104,21 @@ namespace DotRecast.Recast
for (int j = 0; j < v.Length - 3; j++)
{
context.meshFaces.Add(readFaceVertex(v[1], context));
context.meshFaces.Add(ReadFaceVertex(v[1], context));
for (int i = 0; i < 2; i++)
{
context.meshFaces.Add(readFaceVertex(v[2 + j + i], context));
context.meshFaces.Add(ReadFaceVertex(v[2 + j + i], context));
}
}
}
private static int readFaceVertex(string face, ObjImporterContext context)
private static int ReadFaceVertex(string face, ObjImporterContext context)
{
string[] v = face.Split("/");
return getIndex(int.Parse(v[0]), context.vertexPositions.Count);
return GetIndex(int.Parse(v[0]), context.vertexPositions.Count);
}
private static int getIndex(int posi, int size)
private static int GetIndex(int posi, int size)
{
if (posi > 0)
{

View File

@ -24,13 +24,13 @@ namespace DotRecast.Recast
public static class PolyMeshRaycast
{
public static float? raycast(IList<RecastBuilderResult> results, Vector3f src, Vector3f dst)
public static float? Raycast(IList<RecastBuilderResult> results, Vector3f src, Vector3f dst)
{
foreach (RecastBuilderResult result in results)
{
if (result.getMeshDetail() != null)
if (result.GetMeshDetail() != null)
{
float? intersection = raycast(result.getMesh(), result.getMeshDetail(), src, dst);
float? intersection = Raycast(result.GetMesh(), result.GetMeshDetail(), src, dst);
if (null != intersection)
{
return intersection;
@ -41,7 +41,7 @@ namespace DotRecast.Recast
return null;
}
private static float? raycast(PolyMesh poly, PolyMeshDetail meshDetail, Vector3f sp, Vector3f sq)
private static float? Raycast(PolyMesh poly, PolyMeshDetail meshDetail, Vector3f sp, Vector3f sq)
{
if (meshDetail != null)
{
@ -63,7 +63,7 @@ namespace DotRecast.Recast
vs[k].z = meshDetail.verts[verts + meshDetail.tris[tris + j * 4 + k] * 3 + 2];
}
float? intersection = Intersections.intersectSegmentTriangle(sp, sq, vs[0], vs[1], vs[2]);
float? intersection = Intersections.IntersectSegmentTriangle(sp, sq, vs[0], vs[1], vs[2]);
if (null != intersection)
{
return intersection;

View File

@ -24,7 +24,7 @@ namespace DotRecast.Recast
{
public static class PolyUtils
{
public static bool pointInPoly(float[] verts, Vector3f p)
public static bool PointInPoly(float[] verts, Vector3f p)
{
int i, j;
bool c = false;
@ -42,7 +42,7 @@ namespace DotRecast.Recast
return c;
}
public static int offsetPoly(float[] verts, int nverts, float offset, float[] outVerts, int maxOutVerts)
public static int OffsetPoly(float[] verts, int nverts, float offset, float[] outVerts, int maxOutVerts)
{
float MITER_LIMIT = 1.20f;

View File

@ -27,7 +27,7 @@ namespace DotRecast.Recast
public class Recast
{
void calcBounds(float[] verts, int nv, float[] bmin, float[] bmax)
void CalcBounds(float[] verts, int nv, float[] bmin, float[] bmax)
{
for (int i = 0; i < 3; i++)
{
@ -46,25 +46,25 @@ namespace DotRecast.Recast
// Calculate bounding box.
}
public static int[] calcGridSize(float[] bmin, float[] bmax, float cs)
public static int[] CalcGridSize(float[] bmin, float[] bmax, float cs)
{
return new int[] { (int)((bmax[0] - bmin[0]) / cs + 0.5f), (int)((bmax[2] - bmin[2]) / cs + 0.5f) };
}
public static int[] calcGridSize(Vector3f bmin, float[] bmax, float cs)
public static int[] CalcGridSize(Vector3f bmin, float[] bmax, float cs)
{
return new int[] { (int)((bmax[0] - bmin.x) / cs + 0.5f), (int)((bmax[2] - bmin.z) / cs + 0.5f) };
}
public static int[] calcGridSize(Vector3f bmin, Vector3f bmax, float cs)
public static int[] CalcGridSize(Vector3f bmin, Vector3f bmax, float cs)
{
return new int[] { (int)((bmax.x - bmin.x) / cs + 0.5f), (int)((bmax.z - bmin.z) / cs + 0.5f) };
}
public static int[] calcTileCount(Vector3f bmin, Vector3f bmax, float cs, int tileSizeX, int tileSizeZ)
public static int[] CalcTileCount(Vector3f bmin, Vector3f bmax, float cs, int tileSizeX, int tileSizeZ)
{
int[] gwd = calcGridSize(bmin, bmax, cs);
int[] gwd = CalcGridSize(bmin, bmax, cs);
int gw = gwd[0];
int gd = gwd[1];
int tw = (gw + tileSizeX - 1) / tileSizeX;
@ -79,7 +79,7 @@ namespace DotRecast.Recast
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
public static int[] markWalkableTriangles(Telemetry ctx, float walkableSlopeAngle, float[] verts, int[] tris, int nt,
public static int[] MarkWalkableTriangles(Telemetry ctx, float walkableSlopeAngle, float[] verts, int[] tris, int nt,
AreaModification areaMod)
{
int[] areas = new int[nt];
@ -88,33 +88,33 @@ namespace DotRecast.Recast
for (int i = 0; i < nt; ++i)
{
int tri = i * 3;
calcTriNormal(verts, tris[tri], tris[tri + 1], tris[tri + 2], ref norm);
CalcTriNormal(verts, tris[tri], tris[tri + 1], tris[tri + 2], ref norm);
// Check if the face is walkable.
if (norm.y > walkableThr)
areas[i] = areaMod.apply(areas[i]);
areas[i] = areaMod.Apply(areas[i]);
}
return areas;
}
static void calcTriNormal(float[] verts, int v0, int v1, int v2, float[] norm)
static void CalcTriNormal(float[] verts, int v0, int v1, int v2, float[] norm)
{
Vector3f e0 = new Vector3f();
Vector3f e1 = new Vector3f();
RecastVectors.sub(ref e0, verts, v1 * 3, v0 * 3);
RecastVectors.sub(ref e1, verts, v2 * 3, v0 * 3);
RecastVectors.cross(norm, e0, e1);
RecastVectors.normalize(norm);
RecastVectors.Sub(ref e0, verts, v1 * 3, v0 * 3);
RecastVectors.Sub(ref e1, verts, v2 * 3, v0 * 3);
RecastVectors.Cross(norm, e0, e1);
RecastVectors.Normalize(norm);
}
static void calcTriNormal(float[] verts, int v0, int v1, int v2, ref Vector3f norm)
static void CalcTriNormal(float[] verts, int v0, int v1, int v2, ref Vector3f norm)
{
Vector3f e0 = new Vector3f();
Vector3f e1 = new Vector3f();
RecastVectors.sub(ref e0, verts, v1 * 3, v0 * 3);
RecastVectors.sub(ref e1, verts, v2 * 3, v0 * 3);
RecastVectors.cross(ref norm, e0, e1);
RecastVectors.normalize(ref norm);
RecastVectors.Sub(ref e0, verts, v1 * 3, v0 * 3);
RecastVectors.Sub(ref e1, verts, v2 * 3, v0 * 3);
RecastVectors.Cross(ref norm, e0, e1);
RecastVectors.Normalize(ref norm);
}
@ -126,7 +126,7 @@ namespace DotRecast.Recast
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
public static void clearUnwalkableTriangles(Telemetry ctx, float walkableSlopeAngle, float[] verts, int nv,
public static void ClearUnwalkableTriangles(Telemetry ctx, float walkableSlopeAngle, float[] verts, int nv,
int[] tris, int nt, int[] areas)
{
float walkableThr = (float)Math.Cos(walkableSlopeAngle / 180.0f * Math.PI);
@ -136,7 +136,7 @@ namespace DotRecast.Recast
for (int i = 0; i < nt; ++i)
{
int tri = i * 3;
calcTriNormal(verts, tris[tri], tris[tri + 1], tris[tri + 2], ref norm);
CalcTriNormal(verts, tris[tri], tris[tri + 1], tris[tri + 2], ref norm);
// Check if the face is walkable.
if (norm.y <= walkableThr)
areas[i] = RC_NULL_AREA;

View File

@ -35,11 +35,11 @@ namespace DotRecast.Recast
/// This method is usually called immediately after the heightfield has been built.
///
/// @see rcCompactHeightfield, rcBuildCompactHeightfield, rcConfig::walkableRadius
public static void erodeWalkableArea(Telemetry ctx, int radius, CompactHeightfield chf)
public static void ErodeWalkableArea(Telemetry ctx, int radius, CompactHeightfield chf)
{
int w = chf.width;
int h = chf.height;
ctx.startTimer("ERODE_AREA");
ctx.StartTimer("ERODE_AREA");
int[] dist = new int[chf.spanCount];
Array.Fill(dist, 255);
@ -206,7 +206,7 @@ namespace DotRecast.Recast
if (dist[i] < thr)
chf.areas[i] = RC_NULL_AREA;
ctx.stopTimer("ERODE_AREA");
ctx.StopTimer("ERODE_AREA");
}
/// @par
@ -215,12 +215,12 @@ namespace DotRecast.Recast
/// such as #rcMarkBoxArea, #rcMarkConvexPolyArea, and #rcMarkCylinderArea.
///
/// @see rcCompactHeightfield
public bool medianFilterWalkableArea(Telemetry ctx, CompactHeightfield chf)
public bool MedianFilterWalkableArea(Telemetry ctx, CompactHeightfield chf)
{
int w = chf.width;
int h = chf.height;
ctx.startTimer("MEDIAN_AREA");
ctx.StartTimer("MEDIAN_AREA");
int[] areas = new int[chf.spanCount];
@ -273,7 +273,7 @@ namespace DotRecast.Recast
chf.areas = areas;
ctx.stopTimer("MEDIAN_AREA");
ctx.StopTimer("MEDIAN_AREA");
return true;
}
@ -283,9 +283,9 @@ namespace DotRecast.Recast
/// The value of spacial parameters are in world units.
///
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
public void markBoxArea(Telemetry ctx, float[] bmin, float[] bmax, AreaModification areaMod, CompactHeightfield chf)
public void MarkBoxArea(Telemetry ctx, float[] bmin, float[] bmax, AreaModification areaMod, CompactHeightfield chf)
{
ctx.startTimer("MARK_BOX_AREA");
ctx.StartTimer("MARK_BOX_AREA");
int minx = (int)((bmin[0] - chf.bmin.x) / chf.cs);
int miny = (int)((bmin[1] - chf.bmin.y) / chf.ch);
@ -323,16 +323,16 @@ namespace DotRecast.Recast
if (s.y >= miny && s.y <= maxy)
{
if (chf.areas[i] != RC_NULL_AREA)
chf.areas[i] = areaMod.apply(chf.areas[i]);
chf.areas[i] = areaMod.Apply(chf.areas[i]);
}
}
}
}
ctx.stopTimer("MARK_BOX_AREA");
ctx.StopTimer("MARK_BOX_AREA");
}
static bool pointInPoly(float[] verts, Vector3f p)
static bool PointInPoly(float[] verts, Vector3f p)
{
bool c = false;
int i, j;
@ -357,19 +357,19 @@ namespace DotRecast.Recast
/// projected onto the xz-plane at @p hmin, then extruded to @p hmax.
///
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
public static void markConvexPolyArea(Telemetry ctx, float[] verts, float hmin, float hmax, AreaModification areaMod,
public static void MarkConvexPolyArea(Telemetry ctx, float[] verts, float hmin, float hmax, AreaModification areaMod,
CompactHeightfield chf)
{
ctx.startTimer("MARK_CONVEXPOLY_AREA");
ctx.StartTimer("MARK_CONVEXPOLY_AREA");
Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f();
RecastVectors.copy(ref bmin, verts, 0);
RecastVectors.copy(ref bmax, verts, 0);
RecastVectors.Copy(ref bmin, verts, 0);
RecastVectors.Copy(ref bmax, verts, 0);
for (int i = 3; i < verts.Length; i += 3)
{
RecastVectors.min(ref bmin, verts, i);
RecastVectors.max(ref bmax, verts, i);
RecastVectors.Min(ref bmin, verts, i);
RecastVectors.Max(ref bmax, verts, i);
}
bmin.y = hmin;
@ -418,19 +418,19 @@ namespace DotRecast.Recast
p.y = 0;
p.z = chf.bmin.z + (z + 0.5f) * chf.cs;
if (pointInPoly(verts, p))
if (PointInPoly(verts, p))
{
chf.areas[i] = areaMod.apply(chf.areas[i]);
chf.areas[i] = areaMod.Apply(chf.areas[i]);
}
}
}
}
}
ctx.stopTimer("MARK_CONVEXPOLY_AREA");
ctx.StopTimer("MARK_CONVEXPOLY_AREA");
}
int offsetPoly(float[] verts, int nverts, float offset, float[] outVerts, int maxOutVerts)
int OffsetPoly(float[] verts, int nverts, float offset, float[] outVerts, int maxOutVerts)
{
float MITER_LIMIT = 1.20f;
@ -513,10 +513,10 @@ namespace DotRecast.Recast
/// The value of spacial parameters are in world units.
///
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
public void markCylinderArea(Telemetry ctx, float[] pos, float r, float h, AreaModification areaMod,
public void MarkCylinderArea(Telemetry ctx, float[] pos, float r, float h, AreaModification areaMod,
CompactHeightfield chf)
{
ctx.startTimer("MARK_CYLINDER_AREA");
ctx.StartTimer("MARK_CYLINDER_AREA");
Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f();
@ -574,14 +574,14 @@ namespace DotRecast.Recast
if (dx * dx + dz * dz < r2)
{
chf.areas[i] = areaMod.apply(chf.areas[i]);
chf.areas[i] = areaMod.Apply(chf.areas[i]);
}
}
}
}
}
ctx.stopTimer("MARK_CYLINDER_AREA");
ctx.StopTimer("MARK_CYLINDER_AREA");
}
}
}

View File

@ -31,7 +31,7 @@ namespace DotRecast.Recast
{
public interface RecastBuilderProgressListener
{
void onProgress(int completed, int total);
void OnProgress(int completed, int total);
}
private readonly RecastBuilderProgressListener progressListener;
@ -46,48 +46,48 @@ namespace DotRecast.Recast
this.progressListener = progressListener;
}
public List<RecastBuilderResult> buildTiles(InputGeomProvider geom, RecastConfig cfg, TaskFactory taskFactory)
public List<RecastBuilderResult> BuildTiles(InputGeomProvider geom, RecastConfig cfg, TaskFactory taskFactory)
{
Vector3f bmin = geom.getMeshBoundsMin();
Vector3f bmax = geom.getMeshBoundsMax();
int[] twh = Recast.calcTileCount(bmin, bmax, cfg.cs, cfg.tileSizeX, cfg.tileSizeZ);
Vector3f bmin = geom.GetMeshBoundsMin();
Vector3f bmax = geom.GetMeshBoundsMax();
int[] twh = Recast.CalcTileCount(bmin, bmax, cfg.cs, cfg.tileSizeX, cfg.tileSizeZ);
int tw = twh[0];
int th = twh[1];
List<RecastBuilderResult> results = new List<RecastBuilderResult>();
if (null != taskFactory)
{
buildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, default);
BuildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, default);
}
else
{
buildSingleThreadAsync(geom, cfg, bmin, bmax, tw, th, results);
BuildSingleThreadAsync(geom, cfg, bmin, bmax, tw, th, results);
}
return results;
}
public Task buildTilesAsync(InputGeomProvider geom, RecastConfig cfg, int threads, List<RecastBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
public Task BuildTilesAsync(InputGeomProvider geom, RecastConfig cfg, int threads, List<RecastBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
{
Vector3f bmin = geom.getMeshBoundsMin();
Vector3f bmax = geom.getMeshBoundsMax();
int[] twh = Recast.calcTileCount(bmin, bmax, cfg.cs, cfg.tileSizeX, cfg.tileSizeZ);
Vector3f bmin = geom.GetMeshBoundsMin();
Vector3f bmax = geom.GetMeshBoundsMax();
int[] twh = Recast.CalcTileCount(bmin, bmax, cfg.cs, cfg.tileSizeX, cfg.tileSizeZ);
int tw = twh[0];
int th = twh[1];
Task task;
if (1 < threads)
{
task = buildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, cancellationToken);
task = BuildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, cancellationToken);
}
else
{
task = buildSingleThreadAsync(geom, cfg, bmin, bmax, tw, th, results);
task = BuildSingleThreadAsync(geom, cfg, bmin, bmax, tw, th, results);
}
return task;
}
private Task buildSingleThreadAsync(InputGeomProvider geom, RecastConfig cfg, Vector3f bmin, Vector3f bmax,
private Task BuildSingleThreadAsync(InputGeomProvider geom, RecastConfig cfg, Vector3f bmin, Vector3f bmax,
int tw, int th, List<RecastBuilderResult> results)
{
AtomicInteger counter = new AtomicInteger(0);
@ -95,14 +95,14 @@ namespace DotRecast.Recast
{
for (int x = 0; x < tw; ++x)
{
results.Add(buildTile(geom, cfg, bmin, bmax, x, y, counter, tw * th));
results.Add(BuildTile(geom, cfg, bmin, bmax, x, y, counter, tw * th));
}
}
return Task.CompletedTask;
}
private Task buildMultiThreadAsync(InputGeomProvider geom, RecastConfig cfg, Vector3f bmin, Vector3f bmax,
private Task BuildMultiThreadAsync(InputGeomProvider geom, RecastConfig cfg, Vector3f bmin, Vector3f bmax,
int tw, int th, List<RecastBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
{
AtomicInteger counter = new AtomicInteger(0);
@ -122,7 +122,7 @@ namespace DotRecast.Recast
try
{
RecastBuilderResult tile = buildTile(geom, cfg, bmin, bmax, tx, ty, counter, tw * th);
RecastBuilderResult tile = BuildTile(geom, cfg, bmin, bmax, tx, ty, counter, tw * th);
lock (results)
{
results.Add(tile);
@ -152,34 +152,34 @@ namespace DotRecast.Recast
return Task.WhenAll(tasks.ToArray());
}
private RecastBuilderResult buildTile(InputGeomProvider geom, RecastConfig cfg, Vector3f bmin, Vector3f bmax, int tx,
private RecastBuilderResult BuildTile(InputGeomProvider geom, RecastConfig cfg, Vector3f bmin, Vector3f bmax, int tx,
int ty, AtomicInteger counter, int total)
{
RecastBuilderResult result = build(geom, new RecastBuilderConfig(cfg, bmin, bmax, tx, ty));
RecastBuilderResult result = Build(geom, new RecastBuilderConfig(cfg, bmin, bmax, tx, ty));
if (progressListener != null)
{
progressListener.onProgress(counter.IncrementAndGet(), total);
progressListener.OnProgress(counter.IncrementAndGet(), total);
}
return result;
}
public RecastBuilderResult build(InputGeomProvider geom, RecastBuilderConfig builderCfg)
public RecastBuilderResult Build(InputGeomProvider geom, RecastBuilderConfig builderCfg)
{
RecastConfig cfg = builderCfg.cfg;
Telemetry ctx = new Telemetry();
//
// Step 1. Rasterize input polygon soup.
//
Heightfield solid = RecastVoxelization.buildSolidHeightfield(geom, builderCfg, ctx);
return build(builderCfg.tileX, builderCfg.tileZ, geom, cfg, solid, ctx);
Heightfield solid = RecastVoxelization.BuildSolidHeightfield(geom, builderCfg, ctx);
return Build(builderCfg.tileX, builderCfg.tileZ, geom, cfg, solid, ctx);
}
public RecastBuilderResult build(int tileX, int tileZ, ConvexVolumeProvider geom, RecastConfig cfg, Heightfield solid,
public RecastBuilderResult Build(int tileX, int tileZ, ConvexVolumeProvider geom, RecastConfig cfg, Heightfield solid,
Telemetry ctx)
{
filterHeightfield(solid, cfg, ctx);
CompactHeightfield chf = buildCompactHeightfield(geom, cfg, ctx, solid);
FilterHeightfield(solid, cfg, ctx);
CompactHeightfield chf = BuildCompactHeightfield(geom, cfg, ctx, solid);
// Partition the heightfield so that we can use simple algorithm later
// to triangulate the walkable areas.
@ -223,20 +223,20 @@ namespace DotRecast.Recast
{
// Prepare for region partitioning, by calculating distance field
// along the walkable surface.
RecastRegion.buildDistanceField(ctx, chf);
RecastRegion.BuildDistanceField(ctx, chf);
// Partition the walkable surface into simple regions without holes.
RecastRegion.buildRegions(ctx, chf, cfg.minRegionArea, cfg.mergeRegionArea);
RecastRegion.BuildRegions(ctx, chf, cfg.minRegionArea, cfg.mergeRegionArea);
}
else if (cfg.partitionType == PartitionType.MONOTONE)
{
// Partition the walkable surface into simple regions without holes.
// Monotone partitioning does not need distancefield.
RecastRegion.buildRegionsMonotone(ctx, chf, cfg.minRegionArea, cfg.mergeRegionArea);
RecastRegion.BuildRegionsMonotone(ctx, chf, cfg.minRegionArea, cfg.mergeRegionArea);
}
else
{
// Partition the walkable surface into simple regions without holes.
RecastRegion.buildLayerRegions(ctx, chf, cfg.minRegionArea);
RecastRegion.BuildLayerRegions(ctx, chf, cfg.minRegionArea);
}
//
@ -244,21 +244,21 @@ namespace DotRecast.Recast
//
// Create contours.
ContourSet cset = RecastContour.buildContours(ctx, chf, cfg.maxSimplificationError, cfg.maxEdgeLen,
ContourSet cset = RecastContour.BuildContours(ctx, chf, cfg.maxSimplificationError, cfg.maxEdgeLen,
RecastConstants.RC_CONTOUR_TESS_WALL_EDGES);
//
// Step 6. Build polygons mesh from contours.
//
PolyMesh pmesh = RecastMesh.buildPolyMesh(ctx, cset, cfg.maxVertsPerPoly);
PolyMesh pmesh = RecastMesh.BuildPolyMesh(ctx, cset, cfg.maxVertsPerPoly);
//
// Step 7. Create detail mesh which allows to access approximate height
// on each polygon.
//
PolyMeshDetail dmesh = cfg.buildMeshDetail
? RecastMeshDetail.buildPolyMeshDetail(ctx, pmesh, chf, cfg.detailSampleDist, cfg.detailSampleMaxError)
? RecastMeshDetail.BuildPolyMeshDetail(ctx, pmesh, chf, cfg.detailSampleDist, cfg.detailSampleMaxError)
: null;
return new RecastBuilderResult(tileX, tileZ, solid, chf, cset, pmesh, dmesh, ctx);
}
@ -266,59 +266,59 @@ namespace DotRecast.Recast
/*
* Step 2. Filter walkable surfaces.
*/
private void filterHeightfield(Heightfield solid, RecastConfig cfg, Telemetry ctx)
private void FilterHeightfield(Heightfield solid, RecastConfig cfg, Telemetry ctx)
{
// Once all geometry is rasterized, we do initial pass of filtering to
// remove unwanted overhangs caused by the conservative rasterization
// as well as filter spans where the character cannot possibly stand.
if (cfg.filterLowHangingObstacles)
{
RecastFilter.filterLowHangingWalkableObstacles(ctx, cfg.walkableClimb, solid);
RecastFilter.FilterLowHangingWalkableObstacles(ctx, cfg.walkableClimb, solid);
}
if (cfg.filterLedgeSpans)
{
RecastFilter.filterLedgeSpans(ctx, cfg.walkableHeight, cfg.walkableClimb, solid);
RecastFilter.FilterLedgeSpans(ctx, cfg.walkableHeight, cfg.walkableClimb, solid);
}
if (cfg.filterWalkableLowHeightSpans)
{
RecastFilter.filterWalkableLowHeightSpans(ctx, cfg.walkableHeight, solid);
RecastFilter.FilterWalkableLowHeightSpans(ctx, cfg.walkableHeight, solid);
}
}
/*
* Step 3. Partition walkable surface to simple regions.
*/
private CompactHeightfield buildCompactHeightfield(ConvexVolumeProvider volumeProvider, RecastConfig cfg, Telemetry ctx,
private CompactHeightfield BuildCompactHeightfield(ConvexVolumeProvider volumeProvider, RecastConfig cfg, Telemetry ctx,
Heightfield solid)
{
// Compact the heightfield so that it is faster to handle from now on.
// This will result more cache coherent data as well as the neighbours
// between walkable cells will be calculated.
CompactHeightfield chf = RecastCompact.buildCompactHeightfield(ctx, cfg.walkableHeight, cfg.walkableClimb, solid);
CompactHeightfield chf = RecastCompact.BuildCompactHeightfield(ctx, cfg.walkableHeight, cfg.walkableClimb, solid);
// Erode the walkable area by agent radius.
RecastArea.erodeWalkableArea(ctx, cfg.walkableRadius, chf);
RecastArea.ErodeWalkableArea(ctx, cfg.walkableRadius, chf);
// (Optional) Mark areas.
if (volumeProvider != null)
{
foreach (ConvexVolume vol in volumeProvider.convexVolumes())
foreach (ConvexVolume vol in volumeProvider.ConvexVolumes())
{
RecastArea.markConvexPolyArea(ctx, vol.verts, vol.hmin, vol.hmax, vol.areaMod, chf);
RecastArea.MarkConvexPolyArea(ctx, vol.verts, vol.hmin, vol.hmax, vol.areaMod, chf);
}
}
return chf;
}
public HeightfieldLayerSet buildLayers(InputGeomProvider geom, RecastBuilderConfig builderCfg)
public HeightfieldLayerSet BuildLayers(InputGeomProvider geom, RecastBuilderConfig builderCfg)
{
Telemetry ctx = new Telemetry();
Heightfield solid = RecastVoxelization.buildSolidHeightfield(geom, builderCfg, ctx);
filterHeightfield(solid, builderCfg.cfg, ctx);
CompactHeightfield chf = buildCompactHeightfield(geom, builderCfg.cfg, ctx, solid);
return RecastLayers.buildHeightfieldLayers(ctx, chf, builderCfg.cfg.walkableHeight);
Heightfield solid = RecastVoxelization.BuildSolidHeightfield(geom, builderCfg, ctx);
FilterHeightfield(solid, builderCfg.cfg, ctx);
CompactHeightfield chf = BuildCompactHeightfield(geom, builderCfg.cfg, ctx, solid);
return RecastLayers.BuildHeightfieldLayers(ctx, chf, builderCfg.cfg.walkableHeight);
}
}
}

View File

@ -94,7 +94,7 @@ namespace DotRecast.Recast
}
else
{
int[] wh = Recast.calcGridSize(this.bmin, this.bmax, cfg.cs);
int[] wh = Recast.CalcGridSize(this.bmin, this.bmax, cfg.cs);
width = wh[0];
height = wh[1];
}

View File

@ -23,32 +23,32 @@
telemetry = ctx;
}
public PolyMesh getMesh()
public PolyMesh GetMesh()
{
return pmesh;
}
public PolyMeshDetail getMeshDetail()
public PolyMeshDetail GetMeshDetail()
{
return dmesh;
}
public CompactHeightfield getCompactHeightfield()
public CompactHeightfield GetCompactHeightfield()
{
return chf;
}
public ContourSet getContourSet()
public ContourSet GetContourSet()
{
return cs;
}
public Heightfield getSolidHeightfield()
public Heightfield GetSolidHeightfield()
{
return solid;
}
public Telemetry getTelemetry()
public Telemetry GetTelemetry()
{
return telemetry;
}

View File

@ -59,7 +59,7 @@ namespace DotRecast.Recast
/// @param[in] x The x offset. [Limits: -1 <= value <= 1]
/// @param[in] y The y offset. [Limits: -1 <= value <= 1]
/// @return The direction that represents the offset.
public static int rcGetDirForOffset(int x, int y)
public static int RcGetDirForOffset(int x, int y)
{
int[] dirs = { 3, 0, -1, 2, 1 };
return dirs[((y + 1) << 1) + x];

View File

@ -38,15 +38,15 @@ namespace DotRecast.Recast
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocCompactHeightfield, rcHeightfield, rcCompactHeightfield, rcConfig
public static CompactHeightfield buildCompactHeightfield(Telemetry ctx, int walkableHeight, int walkableClimb,
public static CompactHeightfield BuildCompactHeightfield(Telemetry ctx, int walkableHeight, int walkableClimb,
Heightfield hf)
{
ctx.startTimer("BUILD_COMPACTHEIGHTFIELD");
ctx.StartTimer("BUILD_COMPACTHEIGHTFIELD");
CompactHeightfield chf = new CompactHeightfield();
int w = hf.width;
int h = hf.height;
int spanCount = getHeightFieldSpanCount(hf);
int spanCount = GetHeightFieldSpanCount(hf);
// Fill in header.
chf.width = w;
@ -93,8 +93,8 @@ namespace DotRecast.Recast
{
int bot = s.smax;
int top = s.next != null ? (int)s.next.smin : MAX_HEIGHT;
chf.spans[idx].y = clamp(bot, 0, MAX_HEIGHT);
chf.spans[idx].h = clamp(top - bot, 0, MAX_HEIGHT);
chf.spans[idx].y = Clamp(bot, 0, MAX_HEIGHT);
chf.spans[idx].h = Clamp(top - bot, 0, MAX_HEIGHT);
chf.areas[idx] = s.area;
idx++;
c.count++;
@ -161,11 +161,11 @@ namespace DotRecast.Recast
+ " (max: " + MAX_LAYERS + ")");
}
ctx.stopTimer("BUILD_COMPACTHEIGHTFIELD");
ctx.StopTimer("BUILD_COMPACTHEIGHTFIELD");
return chf;
}
private static int getHeightFieldSpanCount(Heightfield hf)
private static int GetHeightFieldSpanCount(Heightfield hf)
{
int w = hf.width;
int h = hf.height;

View File

@ -179,7 +179,7 @@ namespace DotRecast.Recast
this.buildMeshDetail = buildMeshDetail;
}
public static int calcBorder(float agentRadius, float cs)
public static int CalcBorder(float agentRadius, float cs)
{
return 3 + (int)Math.Ceiling(agentRadius / cs);
}

View File

@ -60,7 +60,7 @@ namespace DotRecast.Recast
}
}
private static CornerHeight getCornerHeight(int x, int y, int i, int dir, CompactHeightfield chf)
private static CornerHeight GetCornerHeight(int x, int y, int i, int dir, CompactHeightfield chf)
{
bool isBorderVertex = false;
CompactSpan s = chf.spans[i];
@ -138,7 +138,7 @@ namespace DotRecast.Recast
return new CornerHeight(ch, isBorderVertex);
}
private static void walkContour(int x, int y, int i, CompactHeightfield chf, int[] flags, List<int> points)
private static void WalkContour(int x, int y, int i, CompactHeightfield chf, int[] flags, List<int> points)
{
// Choose the first non-connected edge
int dir = 0;
@ -157,7 +157,7 @@ namespace DotRecast.Recast
{
// Choose the edge corner
bool isAreaBorder = false;
CornerHeight cornerHeight = getCornerHeight(x, y, i, dir, chf);
CornerHeight cornerHeight = GetCornerHeight(x, y, i, dir, chf);
bool isBorderVertex = cornerHeight.borderVertex;
int px = x;
int py = cornerHeight.height;
@ -231,7 +231,7 @@ namespace DotRecast.Recast
}
}
private static float distancePtSeg(int x, int z, int px, int pz, int qx, int qz)
private static float DistancePtSeg(int x, int z, int px, int pz, int qx, int qz)
{
float pqx = qx - px;
float pqz = qz - pz;
@ -252,7 +252,7 @@ namespace DotRecast.Recast
return dx * dx + dz * dz;
}
private static void simplifyContour(List<int> points, List<int> simplified, float maxError, int maxEdgeLen, int buildFlags)
private static void SimplifyContour(List<int> points, List<int> simplified, float maxError, int maxEdgeLen, int buildFlags)
{
// Add initial points.
bool hasConnections = false;
@ -377,7 +377,7 @@ namespace DotRecast.Recast
{
while (ci != endi)
{
float d = distancePtSeg(points[ci * 4 + 0], points[ci * 4 + 2], ax, az, bx, bz);
float d = DistancePtSeg(points[ci * 4 + 0], points[ci * 4 + 2], ax, az, bx, bz);
if (d > maxd)
{
maxd = d;
@ -480,7 +480,7 @@ namespace DotRecast.Recast
}
}
private static int calcAreaOfPolygon2D(int[] verts, int nverts)
private static int CalcAreaOfPolygon2D(int[] verts, int nverts)
{
int area = 0;
for (int i = 0, j = nverts - 1; i < nverts; j = i++)
@ -493,7 +493,7 @@ namespace DotRecast.Recast
return (area + 1) / 2;
}
private static bool intersectSegContour(int d0, int d1, int i, int n, int[] verts, int[] d0verts, int[] d1verts)
private static bool IntersectSegContour(int d0, int d1, int i, int n, int[] verts, int[] d0verts, int[] d1verts)
{
// For each edge (k,k+1) of P
int[] pverts = new int[4 * 4];
@ -507,7 +507,7 @@ namespace DotRecast.Recast
d1 = 4;
for (int k = 0; k < n; k++)
{
int k1 = RecastMesh.next(k, n);
int k1 = RecastMesh.Next(k, n);
// Skip edges incident to i.
if (i == k || i == k1)
continue;
@ -521,22 +521,22 @@ namespace DotRecast.Recast
p0 = 8;
p1 = 12;
if (RecastMesh.vequal(pverts, d0, p0) || RecastMesh.vequal(pverts, d1, p0)
|| RecastMesh.vequal(pverts, d0, p1) || RecastMesh.vequal(pverts, d1, p1))
if (RecastMesh.Vequal(pverts, d0, p0) || RecastMesh.Vequal(pverts, d1, p0)
|| RecastMesh.Vequal(pverts, d0, p1) || RecastMesh.Vequal(pverts, d1, p1))
continue;
if (RecastMesh.intersect(pverts, d0, d1, p0, p1))
if (RecastMesh.Intersect(pverts, d0, d1, p0, p1))
return true;
}
return false;
}
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 pi1 = RecastMesh.next(i, n) * 4;
int pin1 = RecastMesh.prev(i, n) * 4;
int pi1 = RecastMesh.Next(i, n) * 4;
int pin1 = RecastMesh.Prev(i, n) * 4;
int[] pverts = new int[4 * 4];
for (int g = 0; g < 4; g++)
{
@ -551,23 +551,23 @@ namespace DotRecast.Recast
pin1 = 8;
pj = 12;
// If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
if (RecastMesh.leftOn(pverts, pin1, pi, pi1))
return RecastMesh.left(pverts, pi, pj, pin1) && RecastMesh.left(pverts, pj, pi, pi1);
if (RecastMesh.LeftOn(pverts, pin1, pi, pi1))
return RecastMesh.Left(pverts, pi, pj, pin1) && RecastMesh.Left(pverts, pj, pi, pi1);
// Assume (i-1,i,i+1) not collinear.
// else P[i] is reflex.
return !(RecastMesh.leftOn(pverts, pi, pj, pi1) && RecastMesh.leftOn(pverts, pj, pi, pin1));
return !(RecastMesh.LeftOn(pverts, pi, pj, pi1) && RecastMesh.LeftOn(pverts, pj, pi, pin1));
}
private static void removeDegenerateSegments(List<int> simplified)
private static void RemoveDegenerateSegments(List<int> simplified)
{
// Remove adjacent vertices which are equal on xz-plane,
// or else the triangulator will get confused.
int npts = simplified.Count / 4;
for (int i = 0; i < npts; ++i)
{
int ni = RecastMesh.next(i, npts);
int ni = RecastMesh.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]
&& simplified[i * 4 + 2] == simplified[ni * 4 + 2])
{
@ -581,7 +581,7 @@ namespace DotRecast.Recast
}
}
private static void mergeContours(Contour ca, Contour cb, int ia, int ib)
private static void MergeContours(Contour ca, Contour cb, int ia, int ib)
{
int maxVerts = ca.nverts + cb.nverts + 2;
int[] verts = new int[maxVerts * 4];
@ -620,7 +620,7 @@ namespace DotRecast.Recast
}
// Finds the lowest leftmost vertex of a contour.
private static int[] findLeftMostVertex(Contour contour)
private static int[] FindLeftMostVertex(Contour contour)
{
int minx = contour.verts[0];
int minz = contour.verts[2];
@ -665,12 +665,12 @@ namespace DotRecast.Recast
}
}
private static void mergeRegionHoles(Telemetry ctx, ContourRegion region)
private static void MergeRegionHoles(Telemetry ctx, ContourRegion region)
{
// Sort holes from left to right.
for (int i = 0; i < region.nholes; i++)
{
int[] minleft = findLeftMostVertex(region.holes[i].contour);
int[] minleft = FindLeftMostVertex(region.holes[i].contour);
region.holes[i].minx = minleft[0];
region.holes[i].minz = minleft[1];
region.holes[i].leftmost = minleft[2];
@ -711,7 +711,7 @@ namespace DotRecast.Recast
int corner = bestVertex * 4;
for (int j = 0; j < outline.nverts; j++)
{
if (inCone(j, outline.nverts, outline.verts, corner, hole.verts))
if (InCone(j, outline.nverts, outline.verts, corner, hole.verts))
{
int dx = outline.verts[j * 4 + 0] - hole.verts[corner + 0];
int dz = outline.verts[j * 4 + 2] - hole.verts[corner + 2];
@ -729,10 +729,10 @@ namespace DotRecast.Recast
for (int j = 0; j < ndiags; j++)
{
int pt = diags[j].vert * 4;
bool intersect = intersectSegContour(pt, corner, diags[j].vert, outline.nverts, outline.verts,
bool intersect = IntersectSegContour(pt, corner, diags[j].vert, outline.nverts, outline.verts,
outline.verts, hole.verts);
for (int k = i; k < region.nholes && !intersect; k++)
intersect |= intersectSegContour(pt, corner, -1, region.holes[k].contour.nverts,
intersect |= IntersectSegContour(pt, corner, -1, region.holes[k].contour.nverts,
region.holes[k].contour.verts, outline.verts, hole.verts);
if (!intersect)
{
@ -750,11 +750,11 @@ namespace DotRecast.Recast
if (index == -1)
{
ctx.warn("mergeHoles: Failed to find merge points for");
ctx.Warn("mergeHoles: Failed to find merge points for");
continue;
}
mergeContours(region.outline, hole, index, bestVertex);
MergeContours(region.outline, hole, index, bestVertex);
}
}
@ -771,7 +771,7 @@ namespace DotRecast.Recast
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig
public static ContourSet buildContours(Telemetry ctx, CompactHeightfield chf, float maxError, int maxEdgeLen,
public static ContourSet BuildContours(Telemetry ctx, CompactHeightfield chf, float maxError, int maxEdgeLen,
int buildFlags)
{
int w = chf.width;
@ -779,7 +779,7 @@ namespace DotRecast.Recast
int borderSize = chf.borderSize;
ContourSet cset = new ContourSet();
ctx.startTimer("CONTOURS");
ctx.StartTimer("CONTOURS");
cset.bmin = chf.bmin;
cset.bmax = chf.bmax;
if (borderSize > 0)
@ -801,7 +801,7 @@ namespace DotRecast.Recast
int[] flags = new int[chf.spanCount];
ctx.startTimer("CONTOURS_TRACE");
ctx.StartTimer("CONTOURS_TRACE");
// Mark boundaries.
for (int y = 0; y < h; ++y)
@ -839,7 +839,7 @@ namespace DotRecast.Recast
}
}
ctx.stopTimer("CONTOURS_TRACE");
ctx.StopTimer("CONTOURS_TRACE");
List<int> verts = new List<int>(256);
List<int> simplified = new List<int>(64);
@ -865,14 +865,14 @@ namespace DotRecast.Recast
verts.Clear();
simplified.Clear();
ctx.startTimer("CONTOURS_WALK");
walkContour(x, y, i, chf, flags, verts);
ctx.stopTimer("CONTOURS_WALK");
ctx.StartTimer("CONTOURS_WALK");
WalkContour(x, y, i, chf, flags, verts);
ctx.StopTimer("CONTOURS_WALK");
ctx.startTimer("CONTOURS_SIMPLIFY");
simplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags);
removeDegenerateSegments(simplified);
ctx.stopTimer("CONTOURS_SIMPLIFY");
ctx.StartTimer("CONTOURS_SIMPLIFY");
SimplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags);
RemoveDegenerateSegments(simplified);
ctx.StopTimer("CONTOURS_SIMPLIFY");
// Store region->contour remap info.
// Create contour.
@ -932,7 +932,7 @@ namespace DotRecast.Recast
{
Contour cont = cset.conts[i];
// If the contour is wound backwards, it is a hole.
winding[i] = calcAreaOfPolygon2D(cont.verts, cont.nverts) < 0 ? -1 : 1;
winding[i] = CalcAreaOfPolygon2D(cont.verts, cont.nverts) < 0 ? -1 : 1;
if (winding[i] < 0)
nholes++;
}
@ -999,7 +999,7 @@ namespace DotRecast.Recast
if (reg.outline != null)
{
mergeRegionHoles(ctx, reg);
MergeRegionHoles(ctx, reg);
}
else
{
@ -1013,7 +1013,7 @@ namespace DotRecast.Recast
}
}
ctx.stopTimer("CONTOURS");
ctx.StopTimer("CONTOURS");
return cset;
}
}

View File

@ -24,28 +24,28 @@ using static DotRecast.Recast.RecastVectors;
namespace DotRecast.Recast
{
public class RecastFilledVolumeRasterization
public static class RecastFilledVolumeRasterization
{
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 };
public static void rasterizeSphere(Heightfield hf, Vector3f center, float radius, int area, int flagMergeThr, Telemetry ctx)
public static void RasterizeSphere(Heightfield hf, Vector3f center, float radius, int area, int flagMergeThr, Telemetry ctx)
{
ctx.startTimer("RASTERIZE_SPHERE");
ctx.StartTimer("RASTERIZE_SPHERE");
float[] bounds =
{
center.x - radius, center.y - radius, center.z - radius, center.x + radius, center.y + radius,
center.z + radius
};
rasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => intersectSphere(rectangle, center, radius * radius));
ctx.stopTimer("RASTERIZE_SPHERE");
RasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => IntersectSphere(rectangle, center, radius * radius));
ctx.StopTimer("RASTERIZE_SPHERE");
}
public static void rasterizeCapsule(Heightfield hf, Vector3f start, Vector3f end, float radius, int area, int flagMergeThr,
public static void RasterizeCapsule(Heightfield hf, Vector3f start, Vector3f end, float radius, int area, int flagMergeThr,
Telemetry ctx)
{
ctx.startTimer("RASTERIZE_CAPSULE");
ctx.StartTimer("RASTERIZE_CAPSULE");
float[] bounds =
{
Math.Min(start.x, end.x) - radius, Math.Min(start.y, end.y) - radius,
@ -53,15 +53,15 @@ namespace DotRecast.Recast
Math.Max(start.z, end.z) + radius
};
Vector3f axis = Vector3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
rasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => intersectCapsule(rectangle, start, end, axis, radius * radius));
ctx.stopTimer("RASTERIZE_CAPSULE");
RasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => IntersectCapsule(rectangle, start, end, axis, radius * radius));
ctx.StopTimer("RASTERIZE_CAPSULE");
}
public static void rasterizeCylinder(Heightfield hf, Vector3f start, Vector3f end, float radius, int area, int flagMergeThr,
public static void RasterizeCylinder(Heightfield hf, Vector3f start, Vector3f end, float radius, int area, int flagMergeThr,
Telemetry ctx)
{
ctx.startTimer("RASTERIZE_CYLINDER");
ctx.StartTimer("RASTERIZE_CYLINDER");
float[] bounds =
{
Math.Min(start.x, end.x) - radius, Math.Min(start.y, end.y) - radius,
@ -69,24 +69,24 @@ namespace DotRecast.Recast
Math.Max(start.z, end.z) + radius
};
Vector3f axis = Vector3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
rasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => intersectCylinder(rectangle, start, end, axis, radius * radius));
ctx.stopTimer("RASTERIZE_CYLINDER");
RasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => IntersectCylinder(rectangle, start, end, axis, radius * radius));
ctx.StopTimer("RASTERIZE_CYLINDER");
}
public static void rasterizeBox(Heightfield hf, Vector3f center, Vector3f[] halfEdges, int area, int flagMergeThr,
public static void RasterizeBox(Heightfield hf, Vector3f center, Vector3f[] halfEdges, int area, int flagMergeThr,
Telemetry ctx)
{
ctx.startTimer("RASTERIZE_BOX");
ctx.StartTimer("RASTERIZE_BOX");
Vector3f[] normals =
{
Vector3f.Of(halfEdges[0].x, halfEdges[0].y, halfEdges[0].z),
Vector3f.Of(halfEdges[1].x, halfEdges[1].y, halfEdges[1].z),
Vector3f.Of(halfEdges[2].x, halfEdges[2].y, halfEdges[2].z),
};
normalize(ref normals[0]);
normalize(ref normals[1]);
normalize(ref normals[2]);
Normalize(ref normals[0]);
Normalize(ref normals[1]);
Normalize(ref normals[2]);
float[] vertices = new float[8 * 3];
float[] bounds = new float[]
@ -122,14 +122,14 @@ namespace DotRecast.Recast
+ vertices[vi * 3 + 2] * planes[i][2];
}
rasterizationFilledShape(hf, bounds, area, flagMergeThr, rectangle => intersectBox(rectangle, vertices, planes));
ctx.stopTimer("RASTERIZE_BOX");
RasterizationFilledShape(hf, bounds, area, flagMergeThr, rectangle => IntersectBox(rectangle, vertices, planes));
ctx.StopTimer("RASTERIZE_BOX");
}
public static void rasterizeConvex(Heightfield hf, float[] vertices, int[] triangles, int area, int flagMergeThr,
public static void RasterizeConvex(Heightfield hf, float[] vertices, int[] triangles, int area, int flagMergeThr,
Telemetry ctx)
{
ctx.startTimer("RASTERIZE_CONVEX");
ctx.StartTimer("RASTERIZE_CONVEX");
float[] bounds = new float[] { vertices[0], vertices[1], vertices[2], vertices[0], vertices[1], vertices[2] };
for (int i = 0; i < vertices.Length; i += 3)
{
@ -153,9 +153,9 @@ namespace DotRecast.Recast
float[] ac = { vertices[c] - vertices[a], vertices[c + 1] - vertices[a + 1], vertices[c + 2] - vertices[a + 2] };
float[] bc = { vertices[c] - vertices[b], vertices[c + 1] - vertices[b + 1], vertices[c + 2] - vertices[b + 2] };
float[] ca = { vertices[a] - vertices[c], vertices[a + 1] - vertices[c + 1], vertices[a + 2] - vertices[c + 2] };
plane(planes, i, ab, ac, vertices, a);
plane(planes, i + 1, planes[i], bc, vertices, b);
plane(planes, i + 2, planes[i], ca, vertices, c);
Plane(planes, i, ab, ac, vertices, a);
Plane(planes, i + 1, planes[i], bc, vertices, b);
Plane(planes, i + 2, planes[i], ca, vertices, c);
float s = 1.0f / (vertices[a] * planes[i + 1][0] + vertices[a + 1] * planes[i + 1][1]
+ vertices[a + 2] * planes[i + 1][2] - planes[i + 1][3]);
@ -177,21 +177,21 @@ namespace DotRecast.Recast
triBounds[j][3] = Math.Max(Math.Max(vertices[a + 2], vertices[b + 2]), vertices[c + 2]);
}
rasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => intersectConvex(rectangle, triangles, vertices, planes, triBounds));
ctx.stopTimer("RASTERIZE_CONVEX");
RasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => IntersectConvex(rectangle, triangles, vertices, planes, triBounds));
ctx.StopTimer("RASTERIZE_CONVEX");
}
private static void plane(float[][] planes, int p, float[] v1, float[] v2, float[] vertices, int vert)
private static void Plane(float[][] planes, int p, float[] v1, float[] v2, float[] vertices, int vert)
{
RecastVectors.cross(planes[p], v1, v2);
RecastVectors.Cross(planes[p], v1, v2);
planes[p][3] = planes[p][0] * vertices[vert] + planes[p][1] * vertices[vert + 1] + planes[p][2] * vertices[vert + 2];
}
private static void rasterizationFilledShape(Heightfield hf, float[] bounds, int area, int flagMergeThr,
private static void RasterizationFilledShape(Heightfield hf, float[] bounds, int area, int flagMergeThr,
Func<float[], float[]> intersection)
{
if (!overlapBounds(hf.bmin, hf.bmax, bounds))
if (!OverlapBounds(hf.bmin, hf.bmax, bounds))
{
return;
}
@ -229,16 +229,16 @@ namespace DotRecast.Recast
int smax = (int)Math.Ceiling((h[1] - hf.bmin.y) * ich);
if (smin != smax)
{
int ismin = clamp(smin, 0, SPAN_MAX_HEIGHT);
int ismax = clamp(smax, ismin + 1, SPAN_MAX_HEIGHT);
RecastRasterization.addSpan(hf, x, z, ismin, ismax, area, flagMergeThr);
int ismin = Clamp(smin, 0, SPAN_MAX_HEIGHT);
int ismax = Clamp(smax, ismin + 1, SPAN_MAX_HEIGHT);
RecastRasterization.AddSpan(hf, x, z, ismin, ismax, area, flagMergeThr);
}
}
}
}
}
private static float[] intersectSphere(float[] rectangle, Vector3f center, float radiusSqr)
private static float[] IntersectSphere(float[] rectangle, Vector3f center, float radiusSqr)
{
float x = Math.Max(rectangle[0], Math.Min(center.x, rectangle[2]));
float y = rectangle[4];
@ -248,8 +248,8 @@ namespace DotRecast.Recast
float my = y - center.y;
float mz = z - center.z;
float b = my; // dot(m, d) d = (0, 1, 0)
float c = lenSqr(mx, my, mz) - radiusSqr;
float b = my; // Dot(m, d) d = (0, 1, 0)
float c = LenSqr(mx, my, mz) - radiusSqr;
if (c > 0.0f && b > 0.0f)
{
return null;
@ -273,47 +273,47 @@ namespace DotRecast.Recast
return new float[] { y + tmin, y + tmax };
}
private static float[] intersectCapsule(float[] rectangle, Vector3f start, Vector3f end, Vector3f axis, float radiusSqr)
private static float[] IntersectCapsule(float[] rectangle, Vector3f start, Vector3f end, Vector3f axis, float radiusSqr)
{
float[] s = mergeIntersections(intersectSphere(rectangle, start, radiusSqr), intersectSphere(rectangle, end, radiusSqr));
float[] s = MergeIntersections(IntersectSphere(rectangle, start, radiusSqr), IntersectSphere(rectangle, end, radiusSqr));
float axisLen2dSqr = axis.x * axis.x + axis.z * axis.z;
if (axisLen2dSqr > EPSILON)
{
s = slabsCylinderIntersection(rectangle, start, end, axis, radiusSqr, s);
s = SlabsCylinderIntersection(rectangle, start, end, axis, radiusSqr, s);
}
return s;
}
private static float[] intersectCylinder(float[] rectangle, Vector3f start, Vector3f end, Vector3f axis, float radiusSqr)
private static float[] IntersectCylinder(float[] rectangle, Vector3f start, Vector3f end, Vector3f axis, float radiusSqr)
{
float[] s = mergeIntersections(
rayCylinderIntersection(Vector3f.Of(
clamp(start.x, rectangle[0], rectangle[2]), rectangle[4],
clamp(start.z, rectangle[1], rectangle[3])
float[] s = MergeIntersections(
RayCylinderIntersection(Vector3f.Of(
Clamp(start.x, rectangle[0], rectangle[2]), rectangle[4],
Clamp(start.z, rectangle[1], rectangle[3])
), start, axis, radiusSqr),
rayCylinderIntersection(Vector3f.Of(
clamp(end.x, rectangle[0], rectangle[2]), rectangle[4],
clamp(end.z, rectangle[1], rectangle[3])
RayCylinderIntersection(Vector3f.Of(
Clamp(end.x, rectangle[0], rectangle[2]), rectangle[4],
Clamp(end.z, rectangle[1], rectangle[3])
), start, axis, radiusSqr));
float axisLen2dSqr = axis.x * axis.x + axis.z * axis.z;
if (axisLen2dSqr > EPSILON)
{
s = slabsCylinderIntersection(rectangle, start, end, axis, radiusSqr, s);
s = SlabsCylinderIntersection(rectangle, start, end, axis, radiusSqr, s);
}
if (axis.y * axis.y > EPSILON)
{
float[][] rectangleOnStartPlane = ArrayUtils.Of<float>(4, 3);
float[][] rectangleOnEndPlane = ArrayUtils.Of<float>(4, 3);
float ds = dot(axis, start);
float de = dot(axis, end);
float ds = Dot(axis, start);
float de = Dot(axis, end);
for (int i = 0; i < 4; i++)
{
float x = rectangle[(i + 1) & 2];
float z = rectangle[(i & 2) + 1];
Vector3f a = Vector3f.Of(x, rectangle[4], z);
float dotAxisA = dot(axis, a);
float dotAxisA = Dot(axis, a);
float t = (ds - dotAxisA) / axis.y;
rectangleOnStartPlane[i][0] = x;
rectangleOnStartPlane[i][1] = rectangle[4] + t;
@ -326,15 +326,15 @@ namespace DotRecast.Recast
for (int i = 0; i < 4; i++)
{
s = cylinderCapIntersection(start, radiusSqr, s, i, rectangleOnStartPlane);
s = cylinderCapIntersection(end, radiusSqr, s, i, rectangleOnEndPlane);
s = CylinderCapIntersection(start, radiusSqr, s, i, rectangleOnStartPlane);
s = CylinderCapIntersection(end, radiusSqr, s, i, rectangleOnEndPlane);
}
}
return s;
}
private static float[] cylinderCapIntersection(Vector3f start, float radiusSqr, float[] s, int i, float[][] rectangleOnPlane)
private static float[] CylinderCapIntersection(Vector3f start, float radiusSqr, float[] s, int i, float[][] rectangleOnPlane)
{
int j = (i + 1) % 4;
// Ray against sphere intersection
@ -348,9 +348,9 @@ namespace DotRecast.Recast
rectangleOnPlane[j][1] - rectangleOnPlane[i][1],
rectangleOnPlane[j][2] - rectangleOnPlane[i][2]
);
float dl = dot(d, d);
float b = dot(m, d) / dl;
float c = (dot(m, m) - radiusSqr) / dl;
float dl = Dot(d, d);
float b = Dot(m, d) / dl;
float c = (Dot(m, m) - radiusSqr) / dl;
float discr = b * b - c;
if (discr > EPSILON)
{
@ -364,83 +364,83 @@ namespace DotRecast.Recast
float y1 = rectangleOnPlane[i][1] + t1 * d.y;
float y2 = rectangleOnPlane[i][1] + t2 * d.y;
float[] y = { Math.Min(y1, y2), Math.Max(y1, y2) };
s = mergeIntersections(s, y);
s = MergeIntersections(s, y);
}
}
return s;
}
private static float[] slabsCylinderIntersection(float[] rectangle, Vector3f start, Vector3f end, Vector3f axis, float radiusSqr,
private static float[] SlabsCylinderIntersection(float[] rectangle, Vector3f start, Vector3f end, Vector3f axis, float radiusSqr,
float[] s)
{
if (Math.Min(start.x, end.x) < rectangle[0])
{
s = mergeIntersections(s, xSlabCylinderIntersection(rectangle, start, axis, radiusSqr, rectangle[0]));
s = MergeIntersections(s, XSlabCylinderIntersection(rectangle, start, axis, radiusSqr, rectangle[0]));
}
if (Math.Max(start.x, end.x) > rectangle[2])
{
s = mergeIntersections(s, xSlabCylinderIntersection(rectangle, start, axis, radiusSqr, rectangle[2]));
s = MergeIntersections(s, XSlabCylinderIntersection(rectangle, start, axis, radiusSqr, rectangle[2]));
}
if (Math.Min(start.z, end.z) < rectangle[1])
{
s = mergeIntersections(s, zSlabCylinderIntersection(rectangle, start, axis, radiusSqr, rectangle[1]));
s = MergeIntersections(s, ZSlabCylinderIntersection(rectangle, start, axis, radiusSqr, rectangle[1]));
}
if (Math.Max(start.z, end.z) > rectangle[3])
{
s = mergeIntersections(s, zSlabCylinderIntersection(rectangle, start, axis, radiusSqr, rectangle[3]));
s = MergeIntersections(s, ZSlabCylinderIntersection(rectangle, start, axis, radiusSqr, rectangle[3]));
}
return s;
}
private static float[] xSlabCylinderIntersection(float[] rectangle, Vector3f start, Vector3f axis, float radiusSqr, float x)
private static float[] XSlabCylinderIntersection(float[] rectangle, Vector3f start, Vector3f axis, float radiusSqr, float x)
{
return rayCylinderIntersection(xSlabRayIntersection(rectangle, start, axis, x), start, axis, radiusSqr);
return RayCylinderIntersection(XSlabRayIntersection(rectangle, start, axis, x), start, axis, radiusSqr);
}
private static Vector3f xSlabRayIntersection(float[] rectangle, Vector3f start, Vector3f direction, float x)
private static Vector3f XSlabRayIntersection(float[] rectangle, Vector3f start, Vector3f direction, float x)
{
// 2d intersection of plane and segment
float t = (x - start.x) / direction.x;
float z = clamp(start.z + t * direction.z, rectangle[1], rectangle[3]);
float z = Clamp(start.z + t * direction.z, rectangle[1], rectangle[3]);
return Vector3f.Of(x, rectangle[4], z);
}
private static float[] zSlabCylinderIntersection(float[] rectangle, Vector3f start, Vector3f axis, float radiusSqr, float z)
private static float[] ZSlabCylinderIntersection(float[] rectangle, Vector3f start, Vector3f axis, float radiusSqr, float z)
{
return rayCylinderIntersection(zSlabRayIntersection(rectangle, start, axis, z), start, axis, radiusSqr);
return RayCylinderIntersection(ZSlabRayIntersection(rectangle, start, axis, z), start, axis, radiusSqr);
}
private static Vector3f zSlabRayIntersection(float[] rectangle, Vector3f start, Vector3f direction, float z)
private static Vector3f ZSlabRayIntersection(float[] rectangle, Vector3f start, Vector3f direction, float z)
{
// 2d intersection of plane and segment
float t = (z - start.z) / direction.z;
float x = clamp(start.x + t * direction.x, rectangle[0], rectangle[2]);
float x = Clamp(start.x + t * direction.x, rectangle[0], rectangle[2]);
return Vector3f.Of(x, rectangle[4], z);
}
// Based on Christer Ericsons's "Real-Time Collision Detection"
private static float[] rayCylinderIntersection(Vector3f point, Vector3f start, Vector3f axis, float radiusSqr)
private static float[] RayCylinderIntersection(Vector3f point, Vector3f start, Vector3f axis, float radiusSqr)
{
Vector3f d = axis;
Vector3f m = Vector3f.Of(point.x - start.x, point.y - start.y, point.z - start.z);
// float[] n = { 0, 1, 0 };
float md = dot(m, d);
// float nd = dot(n, d);
float md = Dot(m, d);
// float nd = Dot(n, d);
float nd = axis.y;
float dd = dot(d, d);
float dd = Dot(d, d);
// float nn = dot(n, n);
// float nn = Dot(n, n);
float nn = 1;
// float mn = dot(m, n);
// float mn = Dot(m, n);
float mn = m.y;
// float a = dd * nn - nd * nd;
float a = dd - nd * nd;
float k = dot(m, m) - radiusSqr;
float k = Dot(m, m) - radiusSqr;
float c = dd * k - md * md;
if (Math.Abs(a) < EPSILON)
{
@ -508,7 +508,7 @@ namespace DotRecast.Recast
return new float[] { point.y + Math.Min(t1, t2), point.y + Math.Max(t1, t2) };
}
private static float[] intersectBox(float[] rectangle, float[] vertices, float[][] planes)
private static float[] IntersectBox(float[] rectangle, float[] vertices, float[][] planes)
{
float yMin = float.PositiveInfinity;
float yMax = float.NegativeInfinity;
@ -534,7 +534,7 @@ namespace DotRecast.Recast
{
if (Math.Abs(planes[j][1]) > EPSILON)
{
float dotNormalPoint = dot(planes[j], point);
float dotNormalPoint = Dot(planes[j], point);
float t = (planes[j][3] - dotNormalPoint) / planes[j][1];
float y = point.y + t;
bool valid = true;
@ -573,14 +573,14 @@ namespace DotRecast.Recast
float dz = vertices[vj + 2] - z;
if (Math.Abs(dx) > EPSILON)
{
float? iy = xSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[0]);
float? iy = XSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[0]);
if (iy != null)
{
yMin = Math.Min(yMin, iy.Value);
yMax = Math.Max(yMax, iy.Value);
}
iy = xSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[2]);
iy = XSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[2]);
if (iy != null)
{
yMin = Math.Min(yMin, iy.Value);
@ -590,14 +590,14 @@ namespace DotRecast.Recast
if (Math.Abs(dz) > EPSILON)
{
float? iy = zSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[1]);
float? iy = ZSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[1]);
if (iy != null)
{
yMin = Math.Min(yMin, iy.Value);
yMax = Math.Max(yMax, iy.Value);
}
iy = zSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[3]);
iy = ZSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[3]);
if (iy != null)
{
yMin = Math.Min(yMin, iy.Value);
@ -614,7 +614,7 @@ namespace DotRecast.Recast
return null;
}
private static float[] intersectConvex(float[] rectangle, int[] triangles, float[] verts, float[][] planes,
private static float[] IntersectConvex(float[] rectangle, int[] triangles, float[] verts, float[][] planes,
float[][] triBounds)
{
float imin = float.PositiveInfinity;
@ -652,14 +652,14 @@ namespace DotRecast.Recast
float dz = verts[vj + 2] - z;
if (Math.Abs(dx) > EPSILON)
{
float? iy = xSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[0]);
float? iy = XSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[0]);
if (iy != null)
{
imin = Math.Min(imin, iy.Value);
imax = Math.Max(imax, iy.Value);
}
iy = xSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[2]);
iy = XSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[2]);
if (iy != null)
{
imin = Math.Min(imin, iy.Value);
@ -669,14 +669,14 @@ namespace DotRecast.Recast
if (Math.Abs(dz) > EPSILON)
{
float? iy = zSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[1]);
float? iy = ZSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[1]);
if (iy != null)
{
imin = Math.Min(imin, iy.Value);
imax = Math.Max(imax, iy.Value);
}
iy = zSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[3]);
iy = ZSlabSegmentIntersection(rectangle, x, y, z, dx, dy, dz, rectangle[3]);
if (iy != null)
{
imin = Math.Min(imin, iy.Value);
@ -691,7 +691,7 @@ namespace DotRecast.Recast
{
point.x = ((i & 1) == 0) ? rectangle[0] : rectangle[2];
point.z = ((i & 2) == 0) ? rectangle[1] : rectangle[3];
float? y = rayTriangleIntersection(point, tri, planes);
float? y = RayTriangleIntersection(point, tri, planes);
if (y != null)
{
imin = Math.Min(imin, y.Value);
@ -708,7 +708,7 @@ namespace DotRecast.Recast
return null;
}
private static float? xSlabSegmentIntersection(float[] rectangle, float x, float y, float z, float dx, float dy, float dz,
private static float? XSlabSegmentIntersection(float[] rectangle, float x, float y, float z, float dx, float dy, float dz,
float slabX)
{
float x2 = x + dx;
@ -725,7 +725,7 @@ namespace DotRecast.Recast
return null;
}
private static float? zSlabSegmentIntersection(float[] rectangle, float x, float y, float z, float dx, float dy, float dz,
private static float? ZSlabSegmentIntersection(float[] rectangle, float x, float y, float z, float dx, float dy, float dz,
float slabZ)
{
float z2 = z + dz;
@ -742,17 +742,17 @@ namespace DotRecast.Recast
return null;
}
private static float? rayTriangleIntersection(Vector3f point, int plane, float[][] planes)
private static float? RayTriangleIntersection(Vector3f point, int plane, float[][] planes)
{
float t = (planes[plane][3] - dot(planes[plane], point)) / planes[plane][1];
float t = (planes[plane][3] - Dot(planes[plane], point)) / planes[plane][1];
float[] s = { point.x, point.y + t, point.z };
float u = dot(s, planes[plane + 1]) - planes[plane + 1][3];
float u = Dot(s, planes[plane + 1]) - planes[plane + 1][3];
if (u < 0.0f || u > 1.0f)
{
return null;
}
float v = dot(s, planes[plane + 2]) - planes[plane + 2][3];
float v = Dot(s, planes[plane + 2]) - planes[plane + 2][3];
if (v < 0.0f)
{
return null;
@ -767,7 +767,7 @@ namespace DotRecast.Recast
return s[1];
}
private static float[] mergeIntersections(float[] s1, float[] s2)
private static float[] MergeIntersections(float[] s1, float[] s2)
{
if (s1 == null)
{
@ -782,12 +782,12 @@ namespace DotRecast.Recast
return new float[] { Math.Min(s1[0], s2[0]), Math.Max(s1[1], s2[1]) };
}
private static float lenSqr(float dx, float dy, float dz)
private static float LenSqr(float dx, float dy, float dz)
{
return dx * dx + dy * dy + dz * dz;
}
private static bool overlapBounds(Vector3f amin, Vector3f amax, float[] bounds)
private static bool OverlapBounds(Vector3f amin, Vector3f amax, float[] bounds)
{
bool overlap = true;
overlap = (amin.x > bounds[3] || amax.x < bounds[0]) ? false : overlap;

View File

@ -31,15 +31,15 @@ namespace DotRecast.Recast
/// Allows the formation of walkable regions that will flow over low lying
/// objects such as curbs, and up structures such as stairways.
///
/// Two neighboring spans are walkable if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) < waklableClimb</tt>
/// Two neighboring spans are walkable if: <tt>RcAbs(currentSpan.smax - neighborSpan.smax) < waklableClimb</tt>
///
/// @warning Will override the effect of #rcFilterLedgeSpans. So if both filters are used, call
/// #rcFilterLedgeSpans after calling this filter.
///
/// @see rcHeightfield, rcConfig
public static void filterLowHangingWalkableObstacles(Telemetry ctx, int walkableClimb, Heightfield solid)
public static void FilterLowHangingWalkableObstacles(Telemetry ctx, int walkableClimb, Heightfield solid)
{
ctx.startTimer("FILTER_LOW_OBSTACLES");
ctx.StartTimer("FILTER_LOW_OBSTACLES");
int w = solid.width;
int h = solid.height;
@ -71,7 +71,7 @@ namespace DotRecast.Recast
}
}
ctx.stopTimer("FILTER_LOW_OBSTACLES");
ctx.StopTimer("FILTER_LOW_OBSTACLES");
}
/// @par
@ -81,12 +81,12 @@ namespace DotRecast.Recast
/// This method removes the impact of the overestimation of conservative voxelization
/// so the resulting mesh will not have regions hanging in the air over ledges.
///
/// A span is a ledge if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt>
/// A span is a ledge if: <tt>RcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt>
///
/// @see rcHeightfield, rcConfig
public static void filterLedgeSpans(Telemetry ctx, int walkableHeight, int walkableClimb, Heightfield solid)
public static void FilterLedgeSpans(Telemetry ctx, int walkableHeight, int walkableClimb, Heightfield solid)
{
ctx.startTimer("FILTER_LEDGE");
ctx.StartTimer("FILTER_LEDGE");
int w = solid.width;
int h = solid.height;
@ -168,7 +168,7 @@ namespace DotRecast.Recast
}
}
ctx.stopTimer("FILTER_LEDGE");
ctx.StopTimer("FILTER_LEDGE");
}
/// @par
@ -177,9 +177,9 @@ namespace DotRecast.Recast
/// maximum to the next higher span's minimum. (Same grid column.)
///
/// @see rcHeightfield, rcConfig
public static void filterWalkableLowHeightSpans(Telemetry ctx, int walkableHeight, Heightfield solid)
public static void FilterWalkableLowHeightSpans(Telemetry ctx, int walkableHeight, Heightfield solid)
{
ctx.startTimer("FILTER_WALKABLE");
ctx.StartTimer("FILTER_WALKABLE");
int w = solid.width;
int h = solid.height;
@ -200,7 +200,7 @@ namespace DotRecast.Recast
}
}
ctx.stopTimer("FILTER_WALKABLE");
ctx.StopTimer("FILTER_WALKABLE");
}
}
}

View File

@ -53,7 +53,7 @@ namespace DotRecast.Recast
}
};
private static void addUnique(List<int> a, int v)
private static void AddUnique(List<int> a, int v)
{
if (!a.Contains(v))
{
@ -61,19 +61,19 @@ namespace DotRecast.Recast
}
}
private static bool contains(List<int> a, int v)
private static bool Contains(List<int> a, int v)
{
return a.Contains(v);
}
private static bool overlapRange(int amin, int amax, int bmin, int bmax)
private static bool OverlapRange(int amin, int amax, int bmin, int bmax)
{
return (amin > bmax || amax < bmin) ? false : true;
}
public static HeightfieldLayerSet buildHeightfieldLayers(Telemetry ctx, CompactHeightfield chf, int walkableHeight)
public static HeightfieldLayerSet BuildHeightfieldLayers(Telemetry ctx, CompactHeightfield chf, int walkableHeight)
{
ctx.startTimer("RC_TIMER_BUILD_LAYERS");
ctx.StartTimer("RC_TIMER_BUILD_LAYERS");
int w = chf.width;
int h = chf.height;
int borderSize = chf.borderSize;
@ -234,7 +234,7 @@ namespace DotRecast.Recast
int ai = chf.cells[ax + ay * w].index + GetCon(s, dir);
int rai = srcReg[ai];
if (rai != 0xff && rai != ri)
addUnique(regs[ri].neis, rai);
AddUnique(regs[ri].neis, rai);
}
}
}
@ -248,8 +248,8 @@ namespace DotRecast.Recast
{
LayerRegion ri = regs[lregs[i]];
LayerRegion rj = regs[lregs[j]];
addUnique(ri.layers, lregs[j]);
addUnique(rj.layers, lregs[i]);
AddUnique(ri.layers, lregs[j]);
AddUnique(rj.layers, lregs[i]);
}
}
}
@ -288,7 +288,7 @@ namespace DotRecast.Recast
if (regn.layerId != 0xff)
continue;
// Skip if the neighbour is overlapping root region.
if (contains(root.layers, nei))
if (Contains(root.layers, nei))
continue;
// Skip if the height range would become too large.
int ymin = Math.Min(root.ymin, regn.ymin);
@ -303,7 +303,7 @@ namespace DotRecast.Recast
regn.layerId = layerId;
// Merge current layers to root.
foreach (int layer in regn.layers)
addUnique(root.layers, layer);
AddUnique(root.layers, layer);
root.ymin = Math.Min(root.ymin, regn.ymin);
root.ymax = Math.Max(root.ymax, regn.ymax);
}
@ -336,7 +336,7 @@ namespace DotRecast.Recast
continue;
// Skip if the regions are not close to each other.
if (!overlapRange(ri.ymin, ri.ymax + mergeHeight, rj.ymin, rj.ymax + mergeHeight))
if (!OverlapRange(ri.ymin, ri.ymax + mergeHeight, rj.ymin, rj.ymax + mergeHeight))
continue;
// Skip if the height range would become too large.
int ymin = Math.Min(ri.ymin, rj.ymin);
@ -355,7 +355,7 @@ namespace DotRecast.Recast
continue;
// Check if region 'k' is overlapping region 'ri'
// Index to 'regs' is the same as region id.
if (contains(ri.layers, k))
if (Contains(ri.layers, k))
{
overlap = true;
break;
@ -386,7 +386,7 @@ namespace DotRecast.Recast
rj.layerId = newId;
// Add overlaid layers from 'rj' to 'ri'.
foreach (int layer in rj.layers)
addUnique(ri.layers, layer);
AddUnique(ri.layers, layer);
// Update height bounds.
ri.ymin = Math.Min(ri.ymin, rj.ymin);
ri.ymax = Math.Max(ri.ymax, rj.ymax);
@ -417,12 +417,12 @@ namespace DotRecast.Recast
// No layers, return empty.
if (layerId == 0)
{
// ctx.stopTimer(RC_TIMER_BUILD_LAYERS);
// ctx.StopTimer(RC_TIMER_BUILD_LAYERS);
return null;
}
// Create layers.
// rcAssert(lset.layers == 0);
// RcAssert(lset.layers == 0);
int lw = w - borderSize * 2;
int lh = h - borderSize * 2;
@ -560,7 +560,7 @@ namespace DotRecast.Recast
layer.miny = layer.maxy = 0;
}
// ctx->stopTimer(RC_TIMER_BUILD_LAYERS);
// ctx->StopTimer(RC_TIMER_BUILD_LAYERS);
return lset;
}
}

View File

@ -36,7 +36,7 @@ namespace DotRecast.Recast
public int[] poly = new int[2];
}
private static void buildMeshAdjacency(int[] polys, int npolys, int nverts, int vertsPerPoly)
private static void BuildMeshAdjacency(int[] polys, int npolys, int nverts, int vertsPerPoly)
{
// Based on code by Eric Lengyel from:
// http://www.terathon.com/code/edges.php
@ -121,7 +121,7 @@ namespace DotRecast.Recast
}
}
private static int computeVertexHash(int x, int y, int z)
private static int ComputeVertexHash(int x, int y, int z)
{
uint h1 = 0x8da6b343; // Large multiplicative constants;
uint h2 = 0xd8163841; // here arbitrarily chosen primes
@ -131,9 +131,9 @@ namespace DotRecast.Recast
return (int)(n & (VERTEX_BUCKET_COUNT - 1));
}
private static int[] addVertex(int x, int y, int z, int[] verts, int[] firstVert, int[] nextVert, int nv)
private static int[] AddVertex(int x, int y, int z, int[] verts, int[] firstVert, int[] nextVert, int nv)
{
int bucket = computeVertexHash(x, 0, z);
int bucket = ComputeVertexHash(x, 0, z);
int i = firstVert[bucket];
while (i != -1)
@ -157,17 +157,17 @@ namespace DotRecast.Recast
return new int[] { i, nv };
}
public static int prev(int i, int n)
public static int Prev(int i, int n)
{
return i - 1 >= 0 ? i - 1 : n - 1;
}
public static int next(int i, int n)
public static int Next(int i, int n)
{
return i + 1 < n ? i + 1 : 0;
}
private static int area2(int[] verts, int a, int b, int c)
private static int Area2(int[] verts, int a, int b, int c)
{
return (verts[b + 0] - verts[a + 0]) * (verts[c + 2] - verts[a + 2])
- (verts[c + 0] - verts[a + 0]) * (verts[b + 2] - verts[a + 2]);
@ -175,39 +175,39 @@ namespace DotRecast.Recast
// Returns true iff c is strictly to the left of the directed
// line through a to b.
public static bool left(int[] verts, int a, int b, int c)
public static bool Left(int[] verts, int a, int b, int c)
{
return area2(verts, a, b, c) < 0;
return Area2(verts, a, b, c) < 0;
}
public static bool leftOn(int[] verts, int a, int b, int c)
public static bool LeftOn(int[] verts, int a, int b, int c)
{
return area2(verts, a, b, c) <= 0;
return Area2(verts, a, b, c) <= 0;
}
private static bool collinear(int[] verts, int a, int b, int c)
private static bool Collinear(int[] verts, int a, int b, int c)
{
return area2(verts, a, b, c) == 0;
return Area2(verts, a, b, c) == 0;
}
// Returns true iff ab properly intersects cd: they share
// a point interior to both segments. The properness of the
// intersection is ensured by using strict leftness.
private static bool intersectProp(int[] verts, int a, int b, int c, int d)
private static bool IntersectProp(int[] verts, int a, int b, int c, int d)
{
// Eliminate improper cases.
if (collinear(verts, a, b, c) || collinear(verts, a, b, d) || collinear(verts, c, d, a)
|| collinear(verts, c, d, b))
if (Collinear(verts, a, b, c) || Collinear(verts, a, b, d) || Collinear(verts, c, d, a)
|| Collinear(verts, c, d, b))
return false;
return (left(verts, a, b, c) ^ left(verts, a, b, d)) && (left(verts, c, d, a) ^ left(verts, c, d, b));
return (Left(verts, a, b, c) ^ Left(verts, a, b, d)) && (Left(verts, c, d, a) ^ Left(verts, c, d, b));
}
// Returns T iff (a,b,c) are collinear and point c lies
// on the closed segement ab.
private static bool between(int[] verts, int a, int b, int c)
private static bool Between(int[] verts, int a, int b, int c)
{
if (!collinear(verts, a, b, c))
if (!Collinear(verts, a, b, c))
return false;
// If ab not vertical, check betweenness on x; else on y.
if (verts[a + 0] != verts[b + 0])
@ -219,25 +219,25 @@ namespace DotRecast.Recast
}
// Returns true iff segments ab and cd intersect, properly or improperly.
public static bool intersect(int[] verts, int a, int b, int c, int d)
public static bool Intersect(int[] verts, int a, int b, int c, int d)
{
if (intersectProp(verts, a, b, c, d))
if (IntersectProp(verts, a, b, c, d))
return true;
else if (between(verts, a, b, c) || between(verts, a, b, d) || between(verts, c, d, a)
|| between(verts, c, d, b))
else if (Between(verts, a, b, c) || Between(verts, a, b, d) || Between(verts, c, d, a)
|| Between(verts, c, d, b))
return true;
else
return false;
}
public static bool vequal(int[] verts, int a, int b)
public static bool Vequal(int[] verts, int a, int b)
{
return verts[a + 0] == verts[b + 0] && verts[a + 2] == verts[b + 2];
}
// Returns T iff (v_i, v_j) is a proper internal *or* external
// diagonal of P, *ignoring edges incident to v_i and v_j*.
private static bool diagonalie(int i, int j, int n, int[] verts, int[] indices)
private static bool Diagonalie(int i, int j, int n, int[] verts, int[] indices)
{
int d0 = (indices[i] & 0x0fffffff) * 4;
int d1 = (indices[j] & 0x0fffffff) * 4;
@ -245,17 +245,17 @@ namespace DotRecast.Recast
// For each edge (k,k+1) of P
for (int k = 0; k < n; k++)
{
int k1 = next(k, n);
int k1 = Next(k, n);
// Skip edges incident to i or j
if (!((k == i) || (k1 == i) || (k == j) || (k1 == j)))
{
int p0 = (indices[k] & 0x0fffffff) * 4;
int p1 = (indices[k1] & 0x0fffffff) * 4;
if (vequal(verts, d0, p0) || vequal(verts, d1, p0) || vequal(verts, d0, p1) || vequal(verts, d1, p1))
if (Vequal(verts, d0, p0) || Vequal(verts, d1, p0) || Vequal(verts, d0, p1) || Vequal(verts, d1, p1))
continue;
if (intersect(verts, d0, d1, p0, p1))
if (Intersect(verts, d0, d1, p0, p1))
return false;
}
}
@ -265,31 +265,31 @@ namespace DotRecast.Recast
// Returns true iff the diagonal (i,j) is strictly internal to the
// polygon P in the neighborhood of the i endpoint.
private static bool inCone(int i, int j, int n, int[] verts, int[] indices)
private static bool InCone(int i, int j, int n, int[] verts, int[] indices)
{
int pi = (indices[i] & 0x0fffffff) * 4;
int pj = (indices[j] & 0x0fffffff) * 4;
int pi1 = (indices[next(i, n)] & 0x0fffffff) * 4;
int pin1 = (indices[prev(i, n)] & 0x0fffffff) * 4;
int pi1 = (indices[Next(i, n)] & 0x0fffffff) * 4;
int pin1 = (indices[Prev(i, n)] & 0x0fffffff) * 4;
// If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
if (leftOn(verts, pin1, pi, pi1))
if (LeftOn(verts, pin1, pi, pi1))
{
return left(verts, pi, pj, pin1) && left(verts, pj, pi, pi1);
return Left(verts, pi, pj, pin1) && Left(verts, pj, pi, pi1);
}
// Assume (i-1,i,i+1) not collinear.
// else P[i] is reflex.
return !(leftOn(verts, pi, pj, pi1) && leftOn(verts, pj, pi, pin1));
return !(LeftOn(verts, pi, pj, pi1) && LeftOn(verts, pj, pi, pin1));
}
// Returns T iff (v_i, v_j) is a proper internal
// diagonal of P.
private static bool diagonal(int i, int j, int n, int[] verts, int[] indices)
private static bool Diagonal(int i, int j, int n, int[] verts, int[] indices)
{
return inCone(i, j, n, verts, indices) && diagonalie(i, j, n, verts, indices);
return InCone(i, j, n, verts, indices) && Diagonalie(i, j, n, verts, indices);
}
private static bool diagonalieLoose(int i, int j, int n, int[] verts, int[] indices)
private static bool DiagonalieLoose(int i, int j, int n, int[] verts, int[] indices)
{
int d0 = (indices[i] & 0x0fffffff) * 4;
int d1 = (indices[j] & 0x0fffffff) * 4;
@ -297,17 +297,17 @@ namespace DotRecast.Recast
// For each edge (k,k+1) of P
for (int k = 0; k < n; k++)
{
int k1 = next(k, n);
int k1 = Next(k, n);
// Skip edges incident to i or j
if (!((k == i) || (k1 == i) || (k == j) || (k1 == j)))
{
int p0 = (indices[k] & 0x0fffffff) * 4;
int p1 = (indices[k1] & 0x0fffffff) * 4;
if (vequal(verts, d0, p0) || vequal(verts, d1, p0) || vequal(verts, d0, p1) || vequal(verts, d1, p1))
if (Vequal(verts, d0, p0) || Vequal(verts, d1, p0) || Vequal(verts, d0, p1) || Vequal(verts, d1, p1))
continue;
if (intersectProp(verts, d0, d1, p0, p1))
if (IntersectProp(verts, d0, d1, p0, p1))
return false;
}
}
@ -315,36 +315,36 @@ namespace DotRecast.Recast
return true;
}
private static bool inConeLoose(int i, int j, int n, int[] verts, int[] indices)
private static bool InConeLoose(int i, int j, int n, int[] verts, int[] indices)
{
int pi = (indices[i] & 0x0fffffff) * 4;
int pj = (indices[j] & 0x0fffffff) * 4;
int pi1 = (indices[next(i, n)] & 0x0fffffff) * 4;
int pin1 = (indices[prev(i, n)] & 0x0fffffff) * 4;
int pi1 = (indices[Next(i, n)] & 0x0fffffff) * 4;
int pin1 = (indices[Prev(i, n)] & 0x0fffffff) * 4;
// If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
if (leftOn(verts, pin1, pi, pi1))
return leftOn(verts, pi, pj, pin1) && leftOn(verts, pj, pi, pi1);
if (LeftOn(verts, pin1, pi, pi1))
return LeftOn(verts, pi, pj, pin1) && LeftOn(verts, pj, pi, pi1);
// Assume (i-1,i,i+1) not collinear.
// else P[i] is reflex.
return !(leftOn(verts, pi, pj, pi1) && leftOn(verts, pj, pi, pin1));
return !(LeftOn(verts, pi, pj, pi1) && LeftOn(verts, pj, pi, pin1));
}
private static bool diagonalLoose(int i, int j, int n, int[] verts, int[] indices)
private static bool DiagonalLoose(int i, int j, int n, int[] verts, int[] indices)
{
return inConeLoose(i, j, n, verts, indices) && diagonalieLoose(i, j, n, verts, indices);
return InConeLoose(i, j, n, verts, indices) && DiagonalieLoose(i, j, n, verts, indices);
}
private static int triangulate(int n, int[] verts, int[] indices, int[] tris)
private static int Triangulate(int n, int[] verts, int[] indices, int[] tris)
{
int ntris = 0;
// The last bit of the index is used to indicate if the vertex can be removed.
for (int i = 0; i < n; i++)
{
int i1 = next(i, n);
int i2 = next(i1, n);
if (diagonal(i, i2, n, verts, indices))
int i1 = Next(i, n);
int i2 = Next(i1, n);
if (Diagonal(i, i2, n, verts, indices))
{
indices[i1] |= int.MinValue; // TODO : 체크 필요
}
@ -356,11 +356,11 @@ namespace DotRecast.Recast
int mini = -1;
for (int minIdx = 0; minIdx < n; minIdx++)
{
int nextIdx1 = next(minIdx, n);
int nextIdx1 = Next(minIdx, n);
if ((indices[nextIdx1] & 0x80000000) != 0)
{
int p0 = (indices[minIdx] & 0x0fffffff) * 4;
int p2 = (indices[next(nextIdx1, n)] & 0x0fffffff) * 4;
int p2 = (indices[Next(nextIdx1, n)] & 0x0fffffff) * 4;
int dx = verts[p2 + 0] - verts[p0 + 0];
int dy = verts[p2 + 2] - verts[p0 + 2];
@ -388,12 +388,12 @@ namespace DotRecast.Recast
mini = -1;
for (int minIdx = 0; minIdx < n; minIdx++)
{
int nextIdx1 = next(minIdx, n);
int nextIdx2 = next(nextIdx1, n);
if (diagonalLoose(minIdx, nextIdx2, n, verts, indices))
int nextIdx1 = Next(minIdx, n);
int nextIdx2 = Next(nextIdx1, n);
if (DiagonalLoose(minIdx, nextIdx2, n, verts, indices))
{
int p0 = (indices[minIdx] & 0x0fffffff) * 4;
int p2 = (indices[next(nextIdx2, n)] & 0x0fffffff) * 4;
int p2 = (indices[Next(nextIdx2, n)] & 0x0fffffff) * 4;
int dx = verts[p2 + 0] - verts[p0 + 0];
int dy = verts[p2 + 2] - verts[p0 + 2];
int len = dx * dx + dy * dy;
@ -415,8 +415,8 @@ namespace DotRecast.Recast
}
int i = mini;
int i1 = next(i, n);
int i2 = next(i1, n);
int i1 = Next(i, n);
int i2 = Next(i1, n);
tris[ntris * 3] = indices[i] & 0x0fffffff;
tris[ntris * 3 + 1] = indices[i1] & 0x0fffffff;
@ -430,14 +430,14 @@ namespace DotRecast.Recast
if (i1 >= n)
i1 = 0;
i = prev(i1, n);
i = Prev(i1, n);
// Update diagonal flags.
if (diagonal(prev(i, n), i1, n, verts, indices))
if (Diagonal(Prev(i, n), i1, n, verts, indices))
indices[i] |= int.MinValue;
else
indices[i] &= 0x0fffffff;
if (diagonal(i, next(i1, n), n, verts, indices))
if (Diagonal(i, Next(i1, n), n, verts, indices))
indices[i1] |= int.MinValue;
else
indices[i1] &= 0x0fffffff;
@ -452,7 +452,7 @@ namespace DotRecast.Recast
return ntris;
}
private static int countPolyVerts(int[] p, int j, int nvp)
private static int CountPolyVerts(int[] p, int j, int nvp)
{
for (int i = 0; i < nvp; ++i)
if (p[i + j] == RC_MESH_NULL_IDX)
@ -460,18 +460,18 @@ namespace DotRecast.Recast
return nvp;
}
private static bool uleft(int[] verts, int a, int b, int c)
private static bool Uleft(int[] verts, int a, int b, int c)
{
return (verts[b + 0] - verts[a + 0]) * (verts[c + 2] - verts[a + 2])
- (verts[c + 0] - verts[a + 0]) * (verts[b + 2] - verts[a + 2]) < 0;
}
private static int[] getPolyMergeValue(int[] polys, int pa, int pb, int[] verts, int nvp)
private static int[] GetPolyMergeValue(int[] polys, int pa, int pb, int[] verts, int nvp)
{
int ea = -1;
int eb = -1;
int na = countPolyVerts(polys, pa, nvp);
int nb = countPolyVerts(polys, pb, nvp);
int na = CountPolyVerts(polys, pa, nvp);
int nb = CountPolyVerts(polys, pb, nvp);
// If the merged polygon would be too big, do not merge.
if (na + nb - 2 > nvp)
@ -520,13 +520,13 @@ namespace DotRecast.Recast
va = polys[pa + (ea + na - 1) % na];
vb = polys[pa + ea];
vc = polys[pb + (eb + 2) % nb];
if (!uleft(verts, va * 3, vb * 3, vc * 3))
if (!Uleft(verts, va * 3, vb * 3, vc * 3))
return new int[] { -1, ea, eb };
va = polys[pb + (eb + nb - 1) % nb];
vb = polys[pb + eb];
vc = polys[pa + (ea + 2) % na];
if (!uleft(verts, va * 3, vb * 3, vc * 3))
if (!Uleft(verts, va * 3, vb * 3, vc * 3))
return new int[] { -1, ea, eb };
va = polys[pa + ea];
@ -538,10 +538,10 @@ namespace DotRecast.Recast
return new int[] { dx * dx + dy * dy, ea, eb };
}
private static void mergePolyVerts(int[] polys, int pa, int pb, int ea, int eb, int tmp, int nvp)
private static void MergePolyVerts(int[] polys, int pa, int pb, int ea, int eb, int tmp, int nvp)
{
int na = countPolyVerts(polys, pa, nvp);
int nb = countPolyVerts(polys, pb, nvp);
int na = CountPolyVerts(polys, pa, nvp);
int nb = CountPolyVerts(polys, pb, nvp);
// Merge polygons.
Array.Fill(polys, RC_MESH_NULL_IDX, tmp, (tmp + nvp) - (tmp));
@ -563,7 +563,7 @@ namespace DotRecast.Recast
Array.Copy(polys, tmp, polys, pa, nvp);
}
private static int pushFront(int v, int[] arr, int an)
private static int PushFront(int v, int[] arr, int an)
{
an++;
for (int i = an - 1; i > 0; --i)
@ -572,14 +572,14 @@ namespace DotRecast.Recast
return an;
}
private static int pushBack(int v, int[] arr, int an)
private static int PushBack(int v, int[] arr, int an)
{
arr[an] = v;
an++;
return an;
}
private static bool canRemoveVertex(Telemetry ctx, PolyMesh mesh, int rem)
private static bool CanRemoveVertex(Telemetry ctx, PolyMesh mesh, int rem)
{
int nvp = mesh.nvp;
@ -589,7 +589,7 @@ namespace DotRecast.Recast
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * nvp * 2;
int nv = countPolyVerts(mesh.polys, p, nvp);
int nv = CountPolyVerts(mesh.polys, p, nvp);
int numRemoved = 0;
int numVerts = 0;
for (int j = 0; j < nv; ++j)
@ -624,7 +624,7 @@ namespace DotRecast.Recast
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * nvp * 2;
int nv = countPolyVerts(mesh.polys, p, nvp);
int nv = CountPolyVerts(mesh.polys, p, nvp);
// Collect edges which touches the removed vertex.
for (int j = 0, k = nv - 1; j < nv; k = j++)
@ -682,7 +682,7 @@ namespace DotRecast.Recast
return true;
}
private static void removeVertex(Telemetry ctx, PolyMesh mesh, int rem, int maxTris)
private static void RemoveVertex(Telemetry ctx, PolyMesh mesh, int rem, int maxTris)
{
int nvp = mesh.nvp;
@ -691,7 +691,7 @@ namespace DotRecast.Recast
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * nvp * 2;
int nv = countPolyVerts(mesh.polys, p, nvp);
int nv = CountPolyVerts(mesh.polys, p, nvp);
for (int j = 0; j < nv; ++j)
{
if (mesh.polys[p + j] == rem)
@ -714,7 +714,7 @@ namespace DotRecast.Recast
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * nvp * 2;
int nv = countPolyVerts(mesh.polys, p, nvp);
int nv = CountPolyVerts(mesh.polys, p, nvp);
bool hasRem = false;
for (int j = 0; j < nv; ++j)
if (mesh.polys[p + j] == rem)
@ -764,7 +764,7 @@ namespace DotRecast.Recast
for (int i = 0; i < mesh.npolys; ++i)
{
int p = i * nvp * 2;
int nv = countPolyVerts(mesh.polys, p, nvp);
int nv = CountPolyVerts(mesh.polys, p, nvp);
for (int j = 0; j < nv; ++j)
if (mesh.polys[p + j] > rem)
mesh.polys[p + j]--;
@ -783,9 +783,9 @@ namespace DotRecast.Recast
// Start with one vertex, keep appending connected
// segments to the start and end of the hole.
nhole = pushBack(edges[0], hole, nhole);
nhreg = pushBack(edges[2], hreg, nhreg);
nharea = pushBack(edges[3], harea, nharea);
nhole = PushBack(edges[0], hole, nhole);
nhreg = PushBack(edges[2], hreg, nhreg);
nharea = PushBack(edges[3], harea, nharea);
while (nedges != 0)
{
@ -801,17 +801,17 @@ namespace DotRecast.Recast
if (hole[0] == eb)
{
// The segment matches the beginning of the hole boundary.
nhole = pushFront(ea, hole, nhole);
nhreg = pushFront(r, hreg, nhreg);
nharea = pushFront(a, harea, nharea);
nhole = PushFront(ea, hole, nhole);
nhreg = PushFront(r, hreg, nhreg);
nharea = PushFront(a, harea, nharea);
add = true;
}
else if (hole[nhole - 1] == ea)
{
// The segment matches the end of the hole boundary.
nhole = pushBack(eb, hole, nhole);
nhreg = pushBack(r, hreg, nhreg);
nharea = pushBack(a, harea, nharea);
nhole = PushBack(eb, hole, nhole);
nhreg = PushBack(r, hreg, nhreg);
nharea = PushBack(a, harea, nharea);
add = true;
}
@ -850,11 +850,11 @@ namespace DotRecast.Recast
}
// Triangulate the hole.
int ntris = triangulate(nhole, tverts, thole, tris);
int ntris = Triangulate(nhole, tverts, thole, tris);
if (ntris < 0)
{
ntris = -ntris;
ctx.warn("removeVertex: triangulate() returned bad results.");
ctx.Warn("removeVertex: Triangulate() returned bad results.");
}
// Merge the hole triangles back to polygons.
@ -906,7 +906,7 @@ namespace DotRecast.Recast
for (int k = j + 1; k < npolys; ++k)
{
int pk = k * nvp;
int[] veaeb = getPolyMergeValue(polys, pj, pk, mesh.verts, nvp);
int[] veaeb = GetPolyMergeValue(polys, pj, pk, mesh.verts, nvp);
int v = veaeb[0];
int ea = veaeb[1];
int eb = veaeb[2];
@ -926,7 +926,7 @@ namespace DotRecast.Recast
// Found best, merge.
int pa = bestPa * nvp;
int pb = bestPb * nvp;
mergePolyVerts(polys, pa, pb, bestEa, bestEb, tmpPoly, nvp);
MergePolyVerts(polys, pa, pb, bestEa, bestEb, tmpPoly, nvp);
if (pregs[bestPa] != pregs[bestPb])
pregs[bestPa] = RC_MULTIPLE_REGS;
int last = (npolys - 1) * nvp;
@ -972,9 +972,9 @@ namespace DotRecast.Recast
/// limit must be retricted to <= #DT_VERTS_PER_POLYGON.
///
/// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig
public static PolyMesh buildPolyMesh(Telemetry ctx, ContourSet cset, int nvp)
public static PolyMesh BuildPolyMesh(Telemetry ctx, ContourSet cset, int nvp)
{
ctx.startTimer("POLYMESH");
ctx.StartTimer("POLYMESH");
PolyMesh mesh = new PolyMesh();
mesh.bmin = cset.bmin;
mesh.bmax = cset.bmax;
@ -1037,11 +1037,11 @@ namespace DotRecast.Recast
// Triangulate contour
for (int j = 0; j < cont.nverts; ++j)
indices[j] = j;
int ntris = triangulate(cont.nverts, cont.verts, indices, tris);
int ntris = Triangulate(cont.nverts, cont.verts, indices, tris);
if (ntris <= 0)
{
// Bad triangulation, should not happen.
ctx.warn("buildPolyMesh: Bad triangulation Contour " + i + ".");
ctx.Warn("buildPolyMesh: Bad triangulation Contour " + i + ".");
ntris = -ntris;
}
@ -1049,7 +1049,7 @@ namespace DotRecast.Recast
for (int j = 0; j < cont.nverts; ++j)
{
int v = j * 4;
int[] inv = addVertex(cont.verts[v + 0], cont.verts[v + 1], cont.verts[v + 2], mesh.verts, firstVert,
int[] inv = AddVertex(cont.verts[v + 0], cont.verts[v + 1], cont.verts[v + 2], mesh.verts, firstVert,
nextVert, mesh.nverts);
indices[j] = inv[0];
mesh.nverts = inv[1];
@ -1093,7 +1093,7 @@ namespace DotRecast.Recast
for (int k = j + 1; k < npolys; ++k)
{
int pk = k * nvp;
int[] veaeb = getPolyMergeValue(polys, pj, pk, mesh.verts, nvp);
int[] veaeb = GetPolyMergeValue(polys, pj, pk, mesh.verts, nvp);
int v = veaeb[0];
int ea = veaeb[1];
int eb = veaeb[2];
@ -1113,7 +1113,7 @@ namespace DotRecast.Recast
// Found best, merge.
int pa = bestPa * nvp;
int pb = bestPb * nvp;
mergePolyVerts(polys, pa, pb, bestEa, bestEb, tmpPoly, nvp);
MergePolyVerts(polys, pa, pb, bestEa, bestEb, tmpPoly, nvp);
int lastPoly = (npolys - 1) * nvp;
if (pb != lastPoly)
{
@ -1153,11 +1153,11 @@ namespace DotRecast.Recast
{
if (vflags[i] != 0)
{
if (!canRemoveVertex(ctx, mesh, i))
if (!CanRemoveVertex(ctx, mesh, i))
continue;
removeVertex(ctx, mesh, i, maxTris);
RemoveVertex(ctx, mesh, i, maxTris);
// Remove vertex
// Note: mesh.nverts is already decremented inside removeVertex()!
// Note: mesh.nverts is already decremented inside RemoveVertex()!
// Fixup vertex flags
for (int j = i; j < mesh.nverts; ++j)
vflags[j] = vflags[j + 1];
@ -1166,7 +1166,7 @@ namespace DotRecast.Recast
}
// Calculate adjacency.
buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, nvp);
BuildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, nvp);
// Find portal edges
if (mesh.borderSize > 0)
@ -1216,17 +1216,17 @@ namespace DotRecast.Recast
+ " (max " + MAX_MESH_VERTS_POLY + "). Data can be corrupted.");
}
ctx.stopTimer("POLYMESH");
ctx.StopTimer("POLYMESH");
return mesh;
}
/// @see rcAllocPolyMesh, rcPolyMesh
public static PolyMesh mergePolyMeshes(Telemetry ctx, PolyMesh[] meshes, int nmeshes)
public static PolyMesh MergePolyMeshes(Telemetry ctx, PolyMesh[] meshes, int nmeshes)
{
if (nmeshes == 0 || meshes == null)
return null;
ctx.startTimer("MERGE_POLYMESH");
ctx.StartTimer("MERGE_POLYMESH");
PolyMesh mesh = new PolyMesh();
mesh.nvp = meshes[0].nvp;
mesh.cs = meshes[0].cs;
@ -1239,8 +1239,8 @@ namespace DotRecast.Recast
int maxVertsPerMesh = 0;
for (int i = 0; i < nmeshes; ++i)
{
RecastVectors.min(ref mesh.bmin, meshes[i].bmin);
RecastVectors.max(ref mesh.bmax, meshes[i].bmax);
RecastVectors.Min(ref mesh.bmin, meshes[i].bmin);
RecastVectors.Max(ref mesh.bmax, meshes[i].bmax);
maxVertsPerMesh = Math.Max(maxVertsPerMesh, meshes[i].nverts);
maxVerts += meshes[i].nverts;
maxPolys += meshes[i].npolys;
@ -1280,7 +1280,7 @@ namespace DotRecast.Recast
for (int j = 0; j < pmesh.nverts; ++j)
{
int v = j * 3;
int[] inv = addVertex(pmesh.verts[v + 0] + ox, pmesh.verts[v + 1], pmesh.verts[v + 2] + oz, mesh.verts,
int[] inv = AddVertex(pmesh.verts[v + 0] + ox, pmesh.verts[v + 1], pmesh.verts[v + 2] + oz, mesh.verts,
firstVert, nextVert, mesh.nverts);
vremap[j] = inv[0];
@ -1335,7 +1335,7 @@ namespace DotRecast.Recast
}
// Calculate adjacency.
buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, mesh.nvp);
BuildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, mesh.nvp);
if (mesh.nverts > MAX_MESH_VERTS_POLY)
{
throw new Exception("rcBuildPolyMesh: The resulting mesh has too many vertices " + mesh.nverts
@ -1348,12 +1348,12 @@ namespace DotRecast.Recast
+ " (max " + MAX_MESH_VERTS_POLY + "). Data can be corrupted.");
}
ctx.stopTimer("MERGE_POLYMESH");
ctx.StopTimer("MERGE_POLYMESH");
return mesh;
}
public static PolyMesh copyPolyMesh(Telemetry ctx, PolyMesh src)
public static PolyMesh CopyPolyMesh(Telemetry ctx, PolyMesh src)
{
PolyMesh dst = new PolyMesh();

View File

@ -46,37 +46,37 @@ namespace DotRecast.Recast
public int[] data;
}
private static float vdot2(float[] a, float[] b)
private static float Vdot2(float[] a, float[] b)
{
return a[0] * b[0] + a[2] * b[2];
}
private static float vdot2(Vector3f a, Vector3f b)
private static float Vdot2(Vector3f a, Vector3f b)
{
return a.x * b.x + a.z * b.z;
}
private static float vdistSq2(float[] verts, int p, int q)
private 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)
private static float Vdist2(float[] verts, int p, int q)
{
return (float)Math.Sqrt(vdistSq2(verts, p, q));
return (float)Math.Sqrt(VdistSq2(verts, p, q));
}
private static float vdistSq2(float[] p, float[] q)
private static float VdistSq2(float[] p, float[] q)
{
float dx = q[0] - p[0];
float dy = q[2] - p[2];
return dx * dx + dy * dy;
}
private static float vdistSq2(float[] p, Vector3f q)
private static float VdistSq2(float[] p, Vector3f q)
{
float dx = q.x - p[0];
float dy = q.z - p[2];
@ -84,7 +84,7 @@ namespace DotRecast.Recast
}
private static float vdistSq2(Vector3f p, Vector3f q)
private static float VdistSq2(Vector3f p, Vector3f q)
{
float dx = q.x - p.x;
float dy = q.z - p.z;
@ -92,30 +92,30 @@ namespace DotRecast.Recast
}
private static float vdist2(float[] p, float[] q)
private static float Vdist2(float[] p, float[] q)
{
return (float)Math.Sqrt(vdistSq2(p, q));
return (float)Math.Sqrt(VdistSq2(p, q));
}
private static float vdist2(Vector3f p, Vector3f q)
private static float Vdist2(Vector3f p, Vector3f q)
{
return (float)Math.Sqrt(vdistSq2(p, q));
return (float)Math.Sqrt(VdistSq2(p, q));
}
private static float vdist2(float[] p, Vector3f q)
private static float Vdist2(float[] p, Vector3f q)
{
return (float)Math.Sqrt(vdistSq2(p, q));
return (float)Math.Sqrt(VdistSq2(p, q));
}
private static float vdistSq2(float[] p, float[] verts, int q)
private static float VdistSq2(float[] p, float[] verts, int q)
{
float dx = verts[q + 0] - p[0];
float dy = verts[q + 2] - p[2];
return dx * dx + dy * dy;
}
private static float vdistSq2(Vector3f p, float[] verts, int q)
private static float VdistSq2(Vector3f p, float[] verts, int q)
{
float dx = verts[q + 0] - p.x;
float dy = verts[q + 2] - p.z;
@ -123,18 +123,18 @@ namespace DotRecast.Recast
}
private static float vdist2(float[] p, float[] verts, int q)
private static float Vdist2(float[] p, float[] verts, int q)
{
return (float)Math.Sqrt(vdistSq2(p, verts, q));
return (float)Math.Sqrt(VdistSq2(p, verts, q));
}
private static float vdist2(Vector3f p, float[] verts, int q)
private static float Vdist2(Vector3f p, float[] verts, int q)
{
return (float)Math.Sqrt(vdistSq2(p, verts, q));
return (float)Math.Sqrt(VdistSq2(p, verts, q));
}
private static float vcross2(float[] verts, int p1, int p2, int p3)
private 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];
@ -143,7 +143,7 @@ namespace DotRecast.Recast
return u1 * v2 - v1 * u2;
}
private static float vcross2(float[] p1, float[] p2, float[] p3)
private static float Vcross2(float[] p1, float[] p2, float[] p3)
{
float u1 = p2[0] - p1[0];
float v1 = p2[2] - p1[2];
@ -152,7 +152,7 @@ namespace DotRecast.Recast
return u1 * v2 - v1 * u2;
}
private static float vcross2(Vector3f p1, Vector3f p2, Vector3f p3)
private static float Vcross2(Vector3f p1, Vector3f p2, Vector3f p3)
{
float u1 = p2.x - p1.x;
float v1 = p2.z - p1.z;
@ -162,49 +162,49 @@ namespace DotRecast.Recast
}
private static bool circumCircle(float[] verts, int p1, int p2, int p3, ref Vector3f c, AtomicFloat r)
private static bool CircumCircle(float[] verts, int p1, int p2, int p3, ref Vector3f c, AtomicFloat r)
{
float EPS = 1e-6f;
// Calculate the circle relative to p1, to avoid some precision issues.
Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f();
Vector3f v3 = new Vector3f();
RecastVectors.sub(ref v2, verts, p2, p1);
RecastVectors.sub(ref v3, verts, p3, p1);
RecastVectors.Sub(ref v2, verts, p2, p1);
RecastVectors.Sub(ref v3, verts, p3, p1);
float cp = vcross2(v1, v2, v3);
float cp = Vcross2(v1, v2, v3);
if (Math.Abs(cp) > EPS)
{
float v1Sq = vdot2(v1, v1);
float v2Sq = vdot2(v2, v2);
float v3Sq = vdot2(v3, v3);
float v1Sq = Vdot2(v1, v1);
float v2Sq = Vdot2(v2, v2);
float v3Sq = Vdot2(v3, v3);
c.x = (v1Sq * (v2.z - v3.z) + v2Sq * (v3.z - v1.z) + v3Sq * (v1.z - v2.z)) / (2 * cp);
c.y = 0;
c.z = (v1Sq * (v3.x - v2.x) + v2Sq * (v1.x - v3.x) + v3Sq * (v2.x - v1.x)) / (2 * cp);
r.Exchange(vdist2(c, v1));
RecastVectors.add(ref c, c, verts, p1);
r.Exchange(Vdist2(c, v1));
RecastVectors.Add(ref c, c, verts, p1);
return true;
}
RecastVectors.copy(ref c, verts, p1);
RecastVectors.Copy(ref c, verts, p1);
r.Exchange(0f);
return false;
}
private static float distPtTri(Vector3f p, float[] verts, int a, int b, int c)
private static float DistPtTri(Vector3f p, float[] verts, int a, int b, int c)
{
Vector3f v0 = new Vector3f();
Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f();
RecastVectors.sub(ref v0, verts, c, a);
RecastVectors.sub(ref v1, verts, b, a);
RecastVectors.sub(ref v2, p, verts, a);
RecastVectors.Sub(ref v0, verts, c, a);
RecastVectors.Sub(ref v1, verts, b, a);
RecastVectors.Sub(ref v2, p, verts, a);
float dot00 = vdot2(v0, v0);
float dot01 = vdot2(v0, v1);
float dot02 = vdot2(v0, v2);
float dot11 = vdot2(v1, v1);
float dot12 = vdot2(v1, v2);
float dot00 = Vdot2(v0, v0);
float dot01 = Vdot2(v0, v1);
float dot02 = Vdot2(v0, v2);
float dot11 = Vdot2(v1, v1);
float dot12 = Vdot2(v1, v2);
// Compute barycentric coordinates
float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
@ -222,7 +222,7 @@ namespace DotRecast.Recast
return float.MaxValue;
}
private static float distancePtSeg(float[] verts, int pt, int p, int q)
private 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];
@ -253,7 +253,7 @@ namespace DotRecast.Recast
return dx * dx + dy * dy + dz * dz;
}
private static float distancePtSeg2d(Vector3f verts, float[] poly, int p, int q)
private static float DistancePtSeg2d(Vector3f verts, float[] poly, int p, int q)
{
float pqx = poly[q + 0] - poly[p + 0];
float pqz = poly[q + 2] - poly[p + 2];
@ -281,7 +281,7 @@ namespace DotRecast.Recast
return dx * dx + dz * dz;
}
private static float distancePtSeg2d(float[] verts, int pt, float[] poly, int p, int q)
private 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];
@ -309,7 +309,7 @@ namespace DotRecast.Recast
return dx * dx + dz * dz;
}
private static float distToTriMesh(Vector3f p, float[] verts, int nverts, List<int> tris, int ntris)
private static float DistToTriMesh(Vector3f p, float[] verts, int nverts, List<int> tris, int ntris)
{
float dmin = float.MaxValue;
for (int i = 0; i < ntris; ++i)
@ -317,7 +317,7 @@ namespace DotRecast.Recast
int va = tris[i * 4 + 0] * 3;
int vb = tris[i * 4 + 1] * 3;
int vc = tris[i * 4 + 2] * 3;
float d = distPtTri(p, verts, va, vb, vc);
float d = DistPtTri(p, verts, va, vb, vc);
if (d < dmin)
{
dmin = d;
@ -332,7 +332,7 @@ namespace DotRecast.Recast
return dmin;
}
private static float distToPoly(int nvert, float[] verts, Vector3f p)
private static float DistToPoly(int nvert, float[] verts, Vector3f p)
{
float dmin = float.MaxValue;
int i, j;
@ -347,19 +347,19 @@ namespace DotRecast.Recast
c = !c;
}
dmin = Math.Min(dmin, distancePtSeg2d(p, verts, vj, vi));
dmin = Math.Min(dmin, DistancePtSeg2d(p, verts, vj, vi));
}
return c ? -dmin : dmin;
}
private static int getHeight(float fx, float fy, float fz, float cs, float ics, float ch, int radius,
private static int GetHeight(float fx, float fy, float fz, float cs, float ics, float ch, int radius,
HeightPatch hp)
{
int ix = (int)Math.Floor(fx * ics + 0.01f);
int iz = (int)Math.Floor(fz * ics + 0.01f);
ix = clamp(ix - hp.xmin, 0, hp.width - 1);
iz = clamp(iz - hp.ymin, 0, hp.height - 1);
ix = Clamp(ix - hp.xmin, 0, hp.width - 1);
iz = Clamp(iz - hp.ymin, 0, hp.height - 1);
int h = hp.data[ix + iz * hp.width];
if (h == RC_UNSET_HEIGHT)
{
@ -436,7 +436,7 @@ namespace DotRecast.Recast
return h;
}
private static int findEdge(List<int> edges, int s, int t)
private static int FindEdge(List<int> edges, int s, int t)
{
for (int i = 0; i < edges.Count / 4; i++)
{
@ -450,7 +450,7 @@ namespace DotRecast.Recast
return EV_UNDEF;
}
private static void addEdge(Telemetry ctx, List<int> edges, int maxEdges, int s, int t, int l, int r)
private static void AddEdge(Telemetry ctx, List<int> edges, int maxEdges, int s, int t, int l, int r)
{
if (edges.Count / 4 >= maxEdges)
{
@ -458,7 +458,7 @@ namespace DotRecast.Recast
}
// Add edge if not already in the triangulation.
int e = findEdge(edges, s, t);
int e = FindEdge(edges, s, t);
if (e == EV_UNDEF)
{
edges.Add(s);
@ -468,7 +468,7 @@ namespace DotRecast.Recast
}
}
private static void updateLeftFace(List<int> edges, int e, int s, int t, int f)
private 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)
{
@ -480,13 +480,13 @@ namespace DotRecast.Recast
}
}
private static bool overlapSegSeg2d(float[] verts, int a, int b, int c, int d)
private 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);
float a1 = Vcross2(verts, a, b, d);
float a2 = Vcross2(verts, a, b, c);
if (a1 * a2 < 0.0f)
{
float a3 = vcross2(verts, c, d, a);
float a3 = Vcross2(verts, c, d, a);
float a4 = a3 + a2 - a1;
if (a3 * a4 < 0.0f)
{
@ -497,7 +497,7 @@ namespace DotRecast.Recast
return false;
}
private static bool overlapEdges(float[] pts, List<int> edges, int s1, int t1)
private static bool OverlapEdges(float[] pts, List<int> edges, int s1, int t1)
{
for (int i = 0; i < edges.Count / 4; ++i)
{
@ -509,7 +509,7 @@ namespace DotRecast.Recast
continue;
}
if (overlapSegSeg2d(pts, s0 * 3, t0 * 3, s1 * 3, t1 * 3))
if (OverlapSegSeg2d(pts, s0 * 3, t0 * 3, s1 * 3, t1 * 3))
{
return true;
}
@ -518,7 +518,7 @@ namespace DotRecast.Recast
return false;
}
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;
@ -553,17 +553,17 @@ namespace DotRecast.Recast
continue;
}
if (vcross2(pts, s * 3, t * 3, u * 3) > EPS)
if (Vcross2(pts, s * 3, t * 3, u * 3) > EPS)
{
if (r.Get() < 0)
{
// The circle is not updated yet, do it now.
pt = u;
circumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
continue;
}
float d = vdist2(c, pts, u * 3);
float d = Vdist2(c, pts, u * 3);
float tol = 0.001f;
if (d > r.Get() * (1 + tol))
{
@ -574,25 +574,25 @@ namespace DotRecast.Recast
{
// Inside safe circumcircle, update circle.
pt = u;
circumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
}
else
{
// Inside epsilon circum circle, do extra tests to make sure the edge is valid.
// s-u and t-u cannot overlap with s-pt nor t-pt if they exists.
if (overlapEdges(pts, edges, s, u))
if (OverlapEdges(pts, edges, s, u))
{
continue;
}
if (overlapEdges(pts, edges, t, u))
if (OverlapEdges(pts, edges, t, u))
{
continue;
}
// Edge is valid.
pt = u;
circumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
}
}
}
@ -601,48 +601,48 @@ namespace DotRecast.Recast
if (pt < npts)
{
// Update face information of edge being completed.
updateLeftFace(edges, e * 4, s, t, nfaces);
UpdateLeftFace(edges, e * 4, s, t, nfaces);
// Add new edge or update face info of old edge.
e = findEdge(edges, pt, s);
e = FindEdge(edges, pt, s);
if (e == EV_UNDEF)
{
addEdge(ctx, edges, maxEdges, pt, s, nfaces, EV_UNDEF);
AddEdge(ctx, edges, maxEdges, pt, s, nfaces, EV_UNDEF);
}
else
{
updateLeftFace(edges, e * 4, pt, s, nfaces);
UpdateLeftFace(edges, e * 4, pt, s, nfaces);
}
// Add new edge or update face info of old edge.
e = findEdge(edges, t, pt);
e = FindEdge(edges, t, pt);
if (e == EV_UNDEF)
{
addEdge(ctx, edges, maxEdges, t, pt, nfaces, EV_UNDEF);
AddEdge(ctx, edges, maxEdges, t, pt, nfaces, EV_UNDEF);
}
else
{
updateLeftFace(edges, e * 4, t, pt, nfaces);
UpdateLeftFace(edges, e * 4, t, pt, nfaces);
}
nfaces++;
}
else
{
updateLeftFace(edges, e * 4, s, t, EV_HULL);
UpdateLeftFace(edges, e * 4, s, t, EV_HULL);
}
return nfaces;
}
private static void delaunayHull(Telemetry ctx, int npts, float[] pts, int nhull, int[] hull, List<int> tris)
private static void DelaunayHull(Telemetry ctx, int npts, float[] pts, int nhull, int[] hull, List<int> tris)
{
int nfaces = 0;
int maxEdges = npts * 10;
List<int> edges = new List<int>(64);
for (int i = 0, j = nhull - 1; i < nhull; j = i++)
{
addEdge(ctx, edges, maxEdges, hull[j], hull[i], EV_HULL, EV_UNDEF);
AddEdge(ctx, edges, maxEdges, hull[j], hull[i], EV_HULL, EV_UNDEF);
}
int currentEdge = 0;
@ -650,12 +650,12 @@ namespace DotRecast.Recast
{
if (edges[currentEdge * 4 + 2] == EV_UNDEF)
{
nfaces = completeFacet(ctx, pts, npts, edges, maxEdges, nfaces, currentEdge);
nfaces = CompleteFacet(ctx, pts, npts, edges, maxEdges, nfaces, currentEdge);
}
if (edges[currentEdge * 4 + 3] == EV_UNDEF)
{
nfaces = completeFacet(ctx, pts, npts, edges, maxEdges, nfaces, currentEdge);
nfaces = CompleteFacet(ctx, pts, npts, edges, maxEdges, nfaces, currentEdge);
}
currentEdge++;
@ -716,7 +716,7 @@ namespace DotRecast.Recast
if (tris[t + 0] == -1 || tris[t + 1] == -1 || tris[t + 2] == -1)
{
Console.Error.WriteLine("Dangling! " + tris[t] + " " + tris[t + 1] + " " + tris[t + 2]);
// ctx.log(RC_LOG_WARNING, "delaunayHull: Removing dangling face %d [%d,%d,%d].", i, t.x,t.y,t.z);
// ctx.Log(RC_LOG_WARNING, "delaunayHull: Removing dangling face %d [%d,%d,%d].", i, t.x,t.y,t.z);
tris[t + 0] = tris[tris.Count - 4];
tris[t + 1] = tris[tris.Count - 3];
tris[t + 2] = tris[tris.Count - 2];
@ -731,7 +731,7 @@ namespace DotRecast.Recast
}
// Calculate minimum extend of the polygon.
private static float polyMinExtent(float[] verts, int nverts)
private static float PolyMinExtent(float[] verts, int nverts)
{
float minDist = float.MaxValue;
for (int i = 0; i < nverts; i++)
@ -747,7 +747,7 @@ namespace DotRecast.Recast
continue;
}
float d = distancePtSeg2d(verts, j * 3, verts, p1, p2);
float d = DistancePtSeg2d(verts, j * 3, verts, p1, p2);
maxEdgeDist = Math.Max(maxEdgeDist, d);
}
@ -757,7 +757,7 @@ namespace DotRecast.Recast
return (float)Math.Sqrt(minDist);
}
private static void triangulateHull(int nverts, float[] verts, int nhull, int[] hull, int nin, List<int> tris)
private static void TriangulateHull(int nverts, float[] verts, int nhull, int[] hull, int nin, List<int> tris)
{
int start = 0, left = 1, right = nhull - 1;
@ -772,12 +772,12 @@ namespace DotRecast.Recast
}
// segments on edges
int pi = RecastMesh.prev(i, nhull);
int ni = RecastMesh.next(i, nhull);
int pi = RecastMesh.Prev(i, nhull);
int ni = RecastMesh.Next(i, nhull);
int pv = hull[pi] * 3;
int cv = hull[i] * 3;
int nv = hull[ni] * 3;
float d = vdist2(verts, pv, cv) + vdist2(verts, cv, nv) + vdist2(verts, nv, pv);
float d = Vdist2(verts, pv, cv) + Vdist2(verts, cv, nv) + Vdist2(verts, nv, pv);
if (d < dmin)
{
start = i;
@ -797,18 +797,18 @@ namespace DotRecast.Recast
// depending on which triangle has shorter perimeter.
// This heuristic was chose emprically, since it seems
// handle tesselated straight edges well.
while (RecastMesh.next(left, nhull) != right)
while (RecastMesh.Next(left, nhull) != right)
{
// Check to see if se should advance left or right.
int nleft = RecastMesh.next(left, nhull);
int nright = RecastMesh.prev(right, nhull);
int nleft = RecastMesh.Next(left, nhull);
int nright = RecastMesh.Prev(right, nhull);
int cvleft = hull[left] * 3;
int nvleft = hull[nleft] * 3;
int cvright = hull[right] * 3;
int nvright = hull[nright] * 3;
float dleft = vdist2(verts, cvleft, nvleft) + vdist2(verts, nvleft, cvright);
float dright = vdist2(verts, cvright, nvright) + vdist2(verts, cvleft, nvright);
float dleft = Vdist2(verts, cvleft, nvleft) + Vdist2(verts, nvleft, cvright);
float dright = Vdist2(verts, cvright, nvright) + Vdist2(verts, cvleft, nvright);
if (dleft < dright)
{
@ -829,17 +829,17 @@ namespace DotRecast.Recast
}
}
private static float getJitterX(int i)
private static float GetJitterX(int i)
{
return (((i * 0x8da6b343) & 0xffff) / 65535.0f * 2.0f) - 1.0f;
}
private static float getJitterY(int i)
private static float GetJitterY(int i)
{
return (((i * 0xd8163841) & 0xffff) / 65535.0f * 2.0f) - 1.0f;
}
static int buildPolyDetail(Telemetry ctx, float[] @in, int nin, float sampleDist, float sampleMaxError,
static int BuildPolyDetail(Telemetry ctx, float[] @in, int nin, float sampleDist, float sampleMaxError,
int heightSearchRadius, CompactHeightfield chf, HeightPatch hp, float[] verts, List<int> tris)
{
List<int> samples = new List<int>(512);
@ -853,7 +853,7 @@ namespace DotRecast.Recast
for (int i = 0; i < nin; ++i)
{
RecastVectors.copy(verts, i * 3, @in, i * 3);
RecastVectors.Copy(verts, i * 3, @in, i * 3);
}
tris.Clear();
@ -862,7 +862,7 @@ namespace DotRecast.Recast
float ics = 1.0f / cs;
// Calculate minimum extents of the polygon based on input data.
float minExtent = polyMinExtent(verts, nverts);
float minExtent = PolyMinExtent(verts, nverts);
// Tessellate outlines.
// This is done in separate pass in order to ensure
@ -920,7 +920,7 @@ namespace DotRecast.Recast
edge[pos + 0] = @in[vj + 0] + dx * u;
edge[pos + 1] = @in[vj + 1] + dy * u;
edge[pos + 2] = @in[vj + 2] + dz * u;
edge[pos + 1] = getHeight(edge[pos + 0], edge[pos + 1], edge[pos + 2], cs, ics, chf.ch,
edge[pos + 1] = GetHeight(edge[pos + 0], edge[pos + 1], edge[pos + 2], cs, ics, chf.ch,
heightSearchRadius, hp) * chf.ch;
}
@ -940,7 +940,7 @@ namespace DotRecast.Recast
int maxi = -1;
for (int m = a + 1; m < b; ++m)
{
float dev = distancePtSeg(edge, m * 3, va, vb);
float dev = DistancePtSeg(edge, m * 3, va, vb);
if (dev > maxd)
{
maxd = dev;
@ -972,7 +972,7 @@ namespace DotRecast.Recast
{
for (int k = nidx - 2; k > 0; --k)
{
RecastVectors.copy(verts, nverts * 3, edge, idx[k] * 3);
RecastVectors.Copy(verts, nverts * 3, edge, idx[k] * 3);
hull[nhull++] = nverts;
nverts++;
}
@ -981,7 +981,7 @@ namespace DotRecast.Recast
{
for (int k = 1; k < nidx - 1; ++k)
{
RecastVectors.copy(verts, nverts * 3, edge, idx[k] * 3);
RecastVectors.Copy(verts, nverts * 3, edge, idx[k] * 3);
hull[nhull++] = nverts;
nverts++;
}
@ -992,7 +992,7 @@ namespace DotRecast.Recast
// If the polygon minimum extent is small (sliver or small triangle), do not try to add internal points.
if (minExtent < sampleDist * 2)
{
triangulateHull(nverts, verts, nhull, hull, nin, tris);
TriangulateHull(nverts, verts, nhull, hull, nin, tris);
return nverts;
}
@ -1000,7 +1000,7 @@ namespace DotRecast.Recast
// We're using the triangulateHull instead of delaunayHull as it tends to
// create a bit better triangulation for long thin triangles when there
// are no internal points.
triangulateHull(nverts, verts, nhull, hull, nin, tris);
TriangulateHull(nverts, verts, nhull, hull, nin, tris);
if (tris.Count == 0)
{
@ -1013,12 +1013,12 @@ namespace DotRecast.Recast
// Create sample locations in a grid.
Vector3f bmin = new Vector3f();
Vector3f bmax = new Vector3f();
RecastVectors.copy(ref bmin, @in, 0);
RecastVectors.copy(ref bmax, @in, 0);
RecastVectors.Copy(ref bmin, @in, 0);
RecastVectors.Copy(ref bmax, @in, 0);
for (int i = 1; i < nin; ++i)
{
RecastVectors.min(ref bmin, @in, i * 3);
RecastVectors.max(ref bmax, @in, i * 3);
RecastVectors.Min(ref bmin, @in, i * 3);
RecastVectors.Max(ref bmax, @in, i * 3);
}
int x0 = (int)Math.Floor(bmin.x / sampleDist);
@ -1035,13 +1035,13 @@ namespace DotRecast.Recast
pt.y = (bmax.y + bmin.y) * 0.5f;
pt.z = z * sampleDist;
// Make sure the samples are not too close to the edges.
if (distToPoly(nin, @in, pt) > -sampleDist / 2)
if (DistToPoly(nin, @in, pt) > -sampleDist / 2)
{
continue;
}
samples.Add(x);
samples.Add(getHeight(pt.x, pt.y, pt.z, cs, ics, chf.ch, heightSearchRadius, hp));
samples.Add(GetHeight(pt.x, pt.y, pt.z, cs, ics, chf.ch, heightSearchRadius, hp));
samples.Add(z);
samples.Add(0); // Not added
}
@ -1073,10 +1073,10 @@ namespace DotRecast.Recast
Vector3f pt = new Vector3f();
// The sample location is jittered to get rid of some bad triangulations
// which are cause by symmetrical data from the grid structure.
pt.x = samples[s + 0] * sampleDist + getJitterX(i) * cs * 0.1f;
pt.x = samples[s + 0] * sampleDist + GetJitterX(i) * cs * 0.1f;
pt.y = samples[s + 1] * chf.ch;
pt.z = samples[s + 2] * sampleDist + getJitterY(i) * cs * 0.1f;
float d = distToTriMesh(pt, verts, nverts, tris, tris.Count / 4);
pt.z = samples[s + 2] * sampleDist + GetJitterY(i) * cs * 0.1f;
float d = DistToTriMesh(pt, verts, nverts, tris, tris.Count / 4);
if (d < 0)
{
continue; // did not hit the mesh.
@ -1099,12 +1099,12 @@ namespace DotRecast.Recast
// Mark sample as added.
samples[besti * 4 + 3] = 1;
// Add the new sample point.
RecastVectors.copy(verts, nverts * 3, bestpt, 0);
RecastVectors.Copy(verts, nverts * 3, bestpt, 0);
nverts++;
// Create new triangulation.
// TODO: Incremental add instead of full rebuild.
delaunayHull(ctx, nverts, verts, nhull, hull, tris);
DelaunayHull(ctx, nverts, verts, nhull, hull, tris);
}
}
@ -1121,7 +1121,7 @@ namespace DotRecast.Recast
return nverts;
}
static void seedArrayWithPolyCenter(Telemetry ctx, CompactHeightfield chf, int[] meshpoly, int poly, int npoly,
static void SeedArrayWithPolyCenter(Telemetry ctx, CompactHeightfield chf, int[] meshpoly, int poly, int npoly,
int[] verts, int bs, HeightPatch hp, List<int> array)
{
// Note: Reads to the compact heightfield are offset by border size (bs)
@ -1186,7 +1186,7 @@ namespace DotRecast.Recast
{
if (array.Count < 3)
{
ctx.warn("Walk towards polygon center failed to reach center");
ctx.Warn("Walk towards polygon center failed to reach center");
break;
}
@ -1211,11 +1211,11 @@ namespace DotRecast.Recast
int directDir;
if (cx == pcx)
{
directDir = rcGetDirForOffset(0, pcy > cy ? 1 : -1);
directDir = RcGetDirForOffset(0, pcy > cy ? 1 : -1);
}
else
{
directDir = rcGetDirForOffset(pcx > cx ? 1 : -1, 0);
directDir = RcGetDirForOffset(pcx > cx ? 1 : -1, 0);
}
// Push the direct dir last so we start with this on next iteration
@ -1272,14 +1272,14 @@ namespace DotRecast.Recast
const int RETRACT_SIZE = 256;
static void push3(List<int> queue, int v1, int v2, int v3)
static void Push3(List<int> queue, int v1, int v2, int v3)
{
queue.Add(v1);
queue.Add(v2);
queue.Add(v3);
}
static void getHeightData(Telemetry ctx, CompactHeightfield chf, int[] meshpolys, int poly, int npoly, int[] verts,
static void GetHeightData(Telemetry ctx, CompactHeightfield chf, int[] meshpolys, int poly, int npoly, int[] verts,
int bs, HeightPatch hp, int region)
{
// Note: Reads to the compact heightfield are offset by border size (bs)
@ -1333,7 +1333,7 @@ namespace DotRecast.Recast
if (border)
{
push3(queue, x, y, i);
Push3(queue, x, y, i);
}
break;
@ -1348,7 +1348,7 @@ namespace DotRecast.Recast
// then use the center as the seed point.
if (empty)
{
seedArrayWithPolyCenter(ctx, chf, meshpolys, poly, npoly, verts, bs, hp, queue);
SeedArrayWithPolyCenter(ctx, chf, meshpolys, poly, npoly, verts, bs, hp, queue);
}
int head = 0;
@ -1395,20 +1395,20 @@ namespace DotRecast.Recast
CompactSpan @as = chf.spans[ai];
hp.data[hx + hy * hp.width] = @as.y;
push3(queue, ax, ay, ai);
Push3(queue, ax, ay, ai);
}
}
}
static int getEdgeFlags(float[] verts, int va, int vb, float[] vpoly, int npoly)
static int GetEdgeFlags(float[] verts, int va, int vb, float[] vpoly, int npoly)
{
// The flag returned by this function matches getDetailTriEdgeFlags in Detour.
// Figure out if edge (va,vb) is part of the polygon boundary.
float thrSqr = 0.001f * 0.001f;
for (int i = 0, j = npoly - 1; i < npoly; j = i++)
{
if (distancePtSeg2d(verts, va, vpoly, j * 3, i * 3) < thrSqr
&& distancePtSeg2d(verts, vb, vpoly, j * 3, i * 3) < thrSqr)
if (DistancePtSeg2d(verts, va, vpoly, j * 3, i * 3) < thrSqr
&& DistancePtSeg2d(verts, vb, vpoly, j * 3, i * 3) < thrSqr)
{
return 1;
}
@ -1417,12 +1417,12 @@ namespace DotRecast.Recast
return 0;
}
static int getTriFlags(float[] verts, int va, int vb, int vc, float[] vpoly, int npoly)
static int GetTriFlags(float[] verts, int va, int vb, int vc, float[] vpoly, int npoly)
{
int flags = 0;
flags |= getEdgeFlags(verts, va, vb, vpoly, npoly) << 0;
flags |= getEdgeFlags(verts, vb, vc, vpoly, npoly) << 2;
flags |= getEdgeFlags(verts, vc, va, vpoly, npoly) << 4;
flags |= GetEdgeFlags(verts, va, vb, vpoly, npoly) << 0;
flags |= GetEdgeFlags(verts, vb, vc, vpoly, npoly) << 2;
flags |= GetEdgeFlags(verts, vc, va, vpoly, npoly) << 4;
return flags;
}
@ -1431,10 +1431,10 @@ namespace DotRecast.Recast
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocPolyMeshDetail, rcPolyMesh, rcCompactHeightfield, rcPolyMeshDetail, rcConfig
public static PolyMeshDetail buildPolyMeshDetail(Telemetry ctx, PolyMesh mesh, CompactHeightfield chf,
public static PolyMeshDetail BuildPolyMeshDetail(Telemetry ctx, PolyMesh mesh, CompactHeightfield chf,
float sampleDist, float sampleMaxError)
{
ctx.startTimer("POLYMESHDETAIL");
ctx.StartTimer("POLYMESHDETAIL");
if (mesh.nverts == 0 || mesh.npolys == 0)
{
return null;
@ -1533,10 +1533,10 @@ 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, hp, mesh.regs[i]);
// Build detail mesh.
int nverts = buildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, heightSearchRadius, chf, hp,
int nverts = BuildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, heightSearchRadius, chf, hp,
verts, tris);
// Move detail verts to world space.
@ -1612,22 +1612,22 @@ namespace DotRecast.Recast
dmesh.tris[dmesh.ntris * 4 + 0] = tris[t + 0];
dmesh.tris[dmesh.ntris * 4 + 1] = tris[t + 1];
dmesh.tris[dmesh.ntris * 4 + 2] = tris[t + 2];
dmesh.tris[dmesh.ntris * 4 + 3] = getTriFlags(verts, tris[t + 0] * 3, tris[t + 1] * 3,
dmesh.tris[dmesh.ntris * 4 + 3] = GetTriFlags(verts, tris[t + 0] * 3, tris[t + 1] * 3,
tris[t + 2] * 3, poly, npoly);
dmesh.ntris++;
}
}
ctx.stopTimer("POLYMESHDETAIL");
ctx.StopTimer("POLYMESHDETAIL");
return dmesh;
}
/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
PolyMeshDetail mergePolyMeshDetails(Telemetry ctx, PolyMeshDetail[] meshes, int nmeshes)
PolyMeshDetail MergePolyMeshDetails(Telemetry ctx, PolyMeshDetail[] meshes, int nmeshes)
{
PolyMeshDetail mesh = new PolyMeshDetail();
ctx.startTimer("MERGE_POLYMESHDETAIL");
ctx.StartTimer("MERGE_POLYMESHDETAIL");
int maxVerts = 0;
int maxTris = 0;
@ -1674,7 +1674,7 @@ namespace DotRecast.Recast
for (int k = 0; k < dm.nverts; ++k)
{
RecastVectors.copy(mesh.verts, mesh.nverts * 3, dm.verts, k * 3);
RecastVectors.Copy(mesh.verts, mesh.nverts * 3, dm.verts, k * 3);
mesh.nverts++;
}
@ -1688,7 +1688,7 @@ namespace DotRecast.Recast
}
}
ctx.stopTimer("MERGE_POLYMESHDETAIL");
ctx.StopTimer("MERGE_POLYMESHDETAIL");
return mesh;
}
}

View File

@ -41,7 +41,7 @@ namespace DotRecast.Recast
* Max axis extents of bounding box B
* @returns true if the two bounding boxes overlap. False otherwise
*/
private static bool overlapBounds(float[] amin, float[] amax, float[] bmin, float[] bmax)
private static bool OverlapBounds(float[] amin, float[] amax, float[] bmin, float[] bmax)
{
bool overlap = true;
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
@ -50,7 +50,7 @@ namespace DotRecast.Recast
return overlap;
}
private static bool overlapBounds(Vector3f amin, Vector3f amax, Vector3f bmin, Vector3f bmax)
private 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;
@ -81,7 +81,7 @@ namespace DotRecast.Recast
* The merge theshold. [Limit: >= 0] [Units: vx]
* @see Heightfield, Span.
*/
public static void addSpan(Heightfield heightfield, int x, int y, int spanMin, int spanMax, int areaId,
public static void AddSpan(Heightfield heightfield, int x, int y, int spanMin, int spanMax, int areaId,
int flagMergeThreshold)
{
int idx = x + y * heightfield.width;
@ -170,7 +170,7 @@ namespace DotRecast.Recast
* The separating axis
* @return The number of resulting polygon 1 and polygon 2 vertices
*/
private static int[] dividePoly(float[] inVerts, int inVertsOffset, int inVertsCount, int outVerts1, int outVerts2, float axisOffset,
private static int[] DividePoly(float[] inVerts, int inVertsOffset, int inVertsCount, int outVerts1, int outVerts2, float axisOffset,
int axis)
{
float[] d = new float[12];
@ -191,19 +191,19 @@ namespace DotRecast.Recast
+ (inVerts[inVertsOffset + i * 3 + 1] - inVerts[inVertsOffset + j * 3 + 1]) * s;
inVerts[outVerts1 + m * 3 + 2] = inVerts[inVertsOffset + j * 3 + 2]
+ (inVerts[inVertsOffset + i * 3 + 2] - inVerts[inVertsOffset + j * 3 + 2]) * s;
RecastVectors.copy(inVerts, outVerts2 + n * 3, inVerts, outVerts1 + m * 3);
RecastVectors.Copy(inVerts, outVerts2 + n * 3, inVerts, outVerts1 + m * 3);
m++;
n++;
// add the i'th point to the right polygon. Do NOT add points that are on the dividing line
// since these were already added above
if (d[i] > 0)
{
RecastVectors.copy(inVerts, outVerts1 + m * 3, inVerts, inVertsOffset + i * 3);
RecastVectors.Copy(inVerts, outVerts1 + m * 3, inVerts, inVertsOffset + i * 3);
m++;
}
else if (d[i] < 0)
{
RecastVectors.copy(inVerts, outVerts2 + n * 3, inVerts, inVertsOffset + i * 3);
RecastVectors.Copy(inVerts, outVerts2 + n * 3, inVerts, inVertsOffset + i * 3);
n++;
}
}
@ -212,13 +212,13 @@ namespace DotRecast.Recast
// add the i'th point to the right polygon. Addition is done even for points on the dividing line
if (d[i] >= 0)
{
RecastVectors.copy(inVerts, outVerts1 + m * 3, inVerts, inVertsOffset + i * 3);
RecastVectors.Copy(inVerts, outVerts1 + m * 3, inVerts, inVertsOffset + i * 3);
m++;
if (d[i] != 0)
continue;
}
RecastVectors.copy(inVerts, outVerts2 + n * 3, inVerts, inVertsOffset + i * 3);
RecastVectors.Copy(inVerts, outVerts2 + n * 3, inVerts, inVertsOffset + i * 3);
n++;
}
}
@ -255,7 +255,7 @@ namespace DotRecast.Recast
* @param flagMergeThreshold
* The threshold in which area flags will be merged
*/
private static void rasterizeTri(float[] verts, int v0, int v1, int v2, int area, Heightfield hf, Vector3f hfBBMin,
private static void RasterizeTri(float[] verts, int v0, int v1, int v2, int area, Heightfield hf, Vector3f hfBBMin,
Vector3f hfBBMax, float cellSize, float inverseCellSize, float inverseCellHeight, int flagMergeThreshold)
{
Vector3f tmin = new Vector3f();
@ -263,15 +263,15 @@ namespace DotRecast.Recast
float by = hfBBMax.y - hfBBMin.y;
// Calculate the bounding box of the triangle.
RecastVectors.copy(ref tmin, verts, v0 * 3);
RecastVectors.copy(ref tmax, verts, v0 * 3);
RecastVectors.min(ref tmin, verts, v1 * 3);
RecastVectors.min(ref tmin, verts, v2 * 3);
RecastVectors.max(ref tmax, verts, v1 * 3);
RecastVectors.max(ref tmax, verts, v2 * 3);
RecastVectors.Copy(ref tmin, verts, v0 * 3);
RecastVectors.Copy(ref tmax, verts, v0 * 3);
RecastVectors.Min(ref tmin, verts, v1 * 3);
RecastVectors.Min(ref tmin, verts, v2 * 3);
RecastVectors.Max(ref tmax, verts, v1 * 3);
RecastVectors.Max(ref tmax, verts, v2 * 3);
// If the triangle does not touch the bbox of the heightfield, skip the triagle.
if (!overlapBounds(hfBBMin, hfBBMax, tmin, tmax))
if (!OverlapBounds(hfBBMin, hfBBMax, tmin, tmax))
return;
// Calculate the footprint of the triangle on the grid's y-axis
@ -281,8 +281,8 @@ namespace DotRecast.Recast
int w = hf.width;
int h = hf.height;
// use -1 rather than 0 to cut the polygon properly at the start of the tile
z0 = clamp(z0, -1, h - 1);
z1 = clamp(z1, 0, h - 1);
z0 = Clamp(z0, -1, h - 1);
z1 = Clamp(z1, 0, h - 1);
// Clip the triangle into all grid cells it touches.
float[] buf = new float[7 * 3 * 4];
@ -291,16 +291,16 @@ namespace DotRecast.Recast
int p1 = inRow + 7 * 3;
int p2 = p1 + 7 * 3;
RecastVectors.copy(buf, 0, verts, v0 * 3);
RecastVectors.copy(buf, 3, verts, v1 * 3);
RecastVectors.copy(buf, 6, verts, v2 * 3);
RecastVectors.Copy(buf, 0, verts, v0 * 3);
RecastVectors.Copy(buf, 3, verts, v1 * 3);
RecastVectors.Copy(buf, 6, verts, v2 * 3);
int nvRow, nvIn = 3;
for (int z = z0; z <= z1; ++z)
{
// Clip polygon to row. Store the remaining polygon as well
float cellZ = hfBBMin.z + z * cellSize;
int[] nvrowin = dividePoly(buf, @in, nvIn, inRow, p1, cellZ + cellSize, 2);
int[] nvrowin = DividePoly(buf, @in, nvIn, inRow, p1, cellZ + cellSize, 2);
nvRow = nvrowin[0];
nvIn = nvrowin[1];
{
@ -332,15 +332,15 @@ namespace DotRecast.Recast
continue;
}
x0 = clamp(x0, -1, w - 1);
x1 = clamp(x1, 0, w - 1);
x0 = Clamp(x0, -1, w - 1);
x1 = Clamp(x1, 0, w - 1);
int nv, nv2 = nvRow;
for (int x = x0; x <= x1; ++x)
{
// Clip polygon to column. store the remaining polygon as well
float cx = hfBBMin.x + x * cellSize;
int[] nvnv2 = dividePoly(buf, inRow, nv2, p1, p2, cx + cellSize, 0);
int[] nvnv2 = DividePoly(buf, inRow, nv2, p1, p2, cx + cellSize, 0);
nv = nvnv2[0];
nv2 = nvnv2[1];
{
@ -378,10 +378,10 @@ namespace DotRecast.Recast
spanMax = by;
// Snap the span to the heightfield height grid.
int spanMinCellIndex = clamp((int)Math.Floor(spanMin * inverseCellHeight), 0, SPAN_MAX_HEIGHT);
int spanMaxCellIndex = clamp((int)Math.Ceiling(spanMax * inverseCellHeight), spanMinCellIndex + 1, SPAN_MAX_HEIGHT);
int spanMinCellIndex = Clamp((int)Math.Floor(spanMin * inverseCellHeight), 0, SPAN_MAX_HEIGHT);
int spanMaxCellIndex = Clamp((int)Math.Ceiling(spanMax * inverseCellHeight), spanMinCellIndex + 1, SPAN_MAX_HEIGHT);
addSpan(hf, x, z, spanMinCellIndex, spanMaxCellIndex, area, flagMergeThreshold);
AddSpan(hf, x, z, spanMinCellIndex, spanMaxCellIndex, area, flagMergeThreshold);
}
}
}
@ -407,17 +407,17 @@ namespace DotRecast.Recast
* The distance where the walkable flag is favored over the non-walkable flag. [Limit: >= 0] [Units: vx]
* @see Heightfield
*/
public static void rasterizeTriangle(Heightfield heightfield, float[] verts, int v0, int v1, int v2, int area,
public static void RasterizeTriangle(Heightfield heightfield, float[] verts, int v0, int v1, int v2, int area,
int flagMergeThreshold, Telemetry ctx)
{
ctx.startTimer("RASTERIZE_TRIANGLES");
ctx.StartTimer("RASTERIZE_TRIANGLES");
float inverseCellSize = 1.0f / heightfield.cs;
float inverseCellHeight = 1.0f / heightfield.ch;
rasterizeTri(verts, v0, v1, v2, area, heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize,
RasterizeTri(verts, v0, v1, v2, area, heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize,
inverseCellHeight, flagMergeThreshold);
ctx.stopTimer("RASTERIZE_TRIANGLES");
ctx.StopTimer("RASTERIZE_TRIANGLES");
}
/**
@ -438,10 +438,10 @@ namespace DotRecast.Recast
* The distance where the walkable flag is favored over the non-walkable flag. [Limit: >= 0] [Units: vx]
* @see Heightfield
*/
public static void rasterizeTriangles(Heightfield heightfield, float[] verts, int[] tris, int[] areaIds, int numTris,
public static void RasterizeTriangles(Heightfield heightfield, float[] verts, int[] tris, int[] areaIds, int numTris,
int flagMergeThreshold, Telemetry ctx)
{
ctx.startTimer("RASTERIZE_TRIANGLES");
ctx.StartTimer("RASTERIZE_TRIANGLES");
float inverseCellSize = 1.0f / heightfield.cs;
float inverseCellHeight = 1.0f / heightfield.ch;
@ -450,11 +450,11 @@ namespace DotRecast.Recast
int v0 = tris[triIndex * 3 + 0];
int v1 = tris[triIndex * 3 + 1];
int v2 = tris[triIndex * 3 + 2];
rasterizeTri(verts, v0, v1, v2, areaIds[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs,
RasterizeTri(verts, v0, v1, v2, areaIds[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs,
inverseCellSize, inverseCellHeight, flagMergeThreshold);
}
ctx.stopTimer("RASTERIZE_TRIANGLES");
ctx.StopTimer("RASTERIZE_TRIANGLES");
}
/**
@ -475,10 +475,10 @@ namespace DotRecast.Recast
* The distance where the walkable flag is favored over the non-walkable flag. [Limit: >= 0] [Units: vx]
* @see Heightfield
*/
public static void rasterizeTriangles(Heightfield heightfield, float[] verts, int[] areaIds, int numTris,
public static void RasterizeTriangles(Heightfield heightfield, float[] verts, int[] areaIds, int numTris,
int flagMergeThreshold, Telemetry ctx)
{
ctx.startTimer("RASTERIZE_TRIANGLES");
ctx.StartTimer("RASTERIZE_TRIANGLES");
float inverseCellSize = 1.0f / heightfield.cs;
float inverseCellHeight = 1.0f / heightfield.ch;
@ -487,11 +487,11 @@ namespace DotRecast.Recast
int v0 = (triIndex * 3 + 0);
int v1 = (triIndex * 3 + 1);
int v2 = (triIndex * 3 + 2);
rasterizeTri(verts, v0, v1, v2, areaIds[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs,
RasterizeTri(verts, v0, v1, v2, areaIds[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs,
inverseCellSize, inverseCellHeight, flagMergeThreshold);
}
ctx.stopTimer("RASTERIZE_TRIANGLES");
ctx.StopTimer("RASTERIZE_TRIANGLES");
}
}
}

View File

@ -38,7 +38,7 @@ namespace DotRecast.Recast
public int nei; // neighbour id
}
public static int calculateDistanceField(CompactHeightfield chf, int[] src)
public static int CalculateDistanceField(CompactHeightfield chf, int[] src)
{
int maxDist;
int w = chf.width;
@ -219,7 +219,7 @@ namespace DotRecast.Recast
return maxDist;
}
private static int[] boxBlur(CompactHeightfield chf, int thr, int[] src)
private static int[] BoxBlur(CompactHeightfield chf, int thr, int[] src)
{
int w = chf.width;
int h = chf.height;
@ -280,7 +280,7 @@ namespace DotRecast.Recast
return dst;
}
private static bool floodRegion(int x, int y, int i, int level, int r, CompactHeightfield chf, int[] srcReg,
private static bool FloodRegion(int x, int y, int i, int level, int r, CompactHeightfield chf, int[] srcReg,
int[] srcDist, List<int> stack)
{
int w = chf.width;
@ -398,7 +398,7 @@ namespace DotRecast.Recast
return count > 0;
}
private static int[] expandRegions(int maxIter, int level, CompactHeightfield chf, int[] srcReg, int[] srcDist,
private static int[] ExpandRegions(int maxIter, int level, CompactHeightfield chf, int[] srcReg, int[] srcDist,
List<int> stack, bool fillStack)
{
int w = chf.width;
@ -524,7 +524,7 @@ namespace DotRecast.Recast
return srcReg;
}
private static void sortCellsByLevel(int startLevel, CompactHeightfield chf, int[] srcReg, int nbStacks,
private static void SortCellsByLevel(int startLevel, CompactHeightfield chf, int[] srcReg, int nbStacks,
List<List<int>> stacks, int loglevelsPerStack) // the levels per stack (2 in our case) as a bit shift
{
int w = chf.width;
@ -569,7 +569,7 @@ namespace DotRecast.Recast
}
}
private static void appendStacks(List<int> srcStack, List<int> dstStack, int[] srcReg)
private static void AppendStacks(List<int> srcStack, List<int> dstStack, int[] srcReg)
{
for (int j = 0; j < srcStack.Count; j += 3)
{
@ -607,7 +607,7 @@ namespace DotRecast.Recast
}
}
private static void removeAdjacentNeighbours(Region reg)
private static void RemoveAdjacentNeighbours(Region reg)
{
// Remove adjacent duplicates.
for (int i = 0; i < reg.connections.Count && reg.connections.Count > 1;)
@ -624,7 +624,7 @@ namespace DotRecast.Recast
}
}
private static void replaceNeighbour(Region reg, int oldId, int newId)
private static void ReplaceNeighbour(Region reg, int oldId, int newId)
{
bool neiChanged = false;
for (int i = 0; i < reg.connections.Count; ++i)
@ -646,11 +646,11 @@ namespace DotRecast.Recast
if (neiChanged)
{
removeAdjacentNeighbours(reg);
RemoveAdjacentNeighbours(reg);
}
}
private static bool canMergeWithRegion(Region rega, Region regb)
private static bool CanMergeWithRegion(Region rega, Region regb)
{
if (rega.areaType != regb.areaType)
{
@ -682,7 +682,7 @@ namespace DotRecast.Recast
return true;
}
private static void addUniqueFloorRegion(Region reg, int n)
private static void AddUniqueFloorRegion(Region reg, int n)
{
if (!reg.floors.Contains(n))
{
@ -690,7 +690,7 @@ namespace DotRecast.Recast
}
}
private static bool mergeRegions(Region rega, Region regb)
private static bool MergeRegions(Region rega, Region regb)
{
int aid = rega.id;
int bid = regb.id;
@ -743,11 +743,11 @@ namespace DotRecast.Recast
rega.connections.Add(bcon[(insb + 1 + i) % ni]);
}
removeAdjacentNeighbours(rega);
RemoveAdjacentNeighbours(rega);
for (int j = 0; j < regb.floors.Count; ++j)
{
addUniqueFloorRegion(rega, regb.floors[j]);
AddUniqueFloorRegion(rega, regb.floors[j]);
}
rega.spanCount += regb.spanCount;
@ -757,14 +757,14 @@ namespace DotRecast.Recast
return true;
}
private static bool isRegionConnectedToBorder(Region reg)
private static bool IsRegionConnectedToBorder(Region reg)
{
// Region is connected to border if
// one of the neighbours is null id.
return reg.connections.Contains(0);
}
private static bool isSolidEdge(CompactHeightfield chf, int[] srcReg, int x, int y, int i, int dir)
private static bool IsSolidEdge(CompactHeightfield chf, int[] srcReg, int x, int y, int i, int dir)
{
CompactSpan s = chf.spans[i];
int r = 0;
@ -784,7 +784,7 @@ namespace DotRecast.Recast
return true;
}
private static void walkContour(int x, int y, int i, int dir, CompactHeightfield chf, int[] srcReg,
private static void WalkContour(int x, int y, int i, int dir, CompactHeightfield chf, int[] srcReg,
List<int> cont)
{
int startDir = dir;
@ -807,7 +807,7 @@ namespace DotRecast.Recast
{
CompactSpan s = chf.spans[i];
if (isSolidEdge(chf, srcReg, x, y, i, dir))
if (IsSolidEdge(chf, srcReg, x, y, i, dir))
{
// Choose the edge corner
int r = 0;
@ -874,7 +874,7 @@ namespace DotRecast.Recast
}
}
private static int mergeAndFilterRegions(Telemetry ctx, int minRegionArea, int mergeRegionSize, int maxRegionId,
private static int MergeAndFilterRegions(Telemetry ctx, int minRegionArea, int mergeRegionSize, int maxRegionId,
CompactHeightfield chf, int[] srcReg, List<int> overlaps)
{
int w = chf.width;
@ -925,7 +925,7 @@ namespace DotRecast.Recast
reg.overlap = true;
}
addUniqueFloorRegion(reg, floorId);
AddUniqueFloorRegion(reg, floorId);
}
// Have found contour
@ -940,7 +940,7 @@ namespace DotRecast.Recast
int ndir = -1;
for (int dir = 0; dir < 4; ++dir)
{
if (isSolidEdge(chf, srcReg, x, y, i, dir))
if (IsSolidEdge(chf, srcReg, x, y, i, dir))
{
ndir = dir;
break;
@ -951,7 +951,7 @@ namespace DotRecast.Recast
{
// The cell is at border.
// Walk around the contour to find all the neighbours.
walkContour(x, y, i, ndir, chf, srcReg, reg.connections);
WalkContour(x, y, i, ndir, chf, srcReg, reg.connections);
}
}
}
@ -1063,7 +1063,7 @@ namespace DotRecast.Recast
}
// Check to see if the region should be merged.
if (reg.spanCount > mergeRegionSize && isRegionConnectedToBorder(reg))
if (reg.spanCount > mergeRegionSize && IsRegionConnectedToBorder(reg))
{
continue;
}
@ -1086,7 +1086,7 @@ namespace DotRecast.Recast
continue;
}
if (mreg.spanCount < smallest && canMergeWithRegion(reg, mreg) && canMergeWithRegion(mreg, reg))
if (mreg.spanCount < smallest && CanMergeWithRegion(reg, mreg) && CanMergeWithRegion(mreg, reg))
{
smallest = mreg.spanCount;
mergeId = mreg.id;
@ -1100,7 +1100,7 @@ namespace DotRecast.Recast
Region target = regions[mergeId];
// Merge neighbours.
if (mergeRegions(target, reg))
if (MergeRegions(target, reg))
{
// Fixup regions pointing to current region.
for (int j = 0; j < nreg; ++j)
@ -1119,7 +1119,7 @@ namespace DotRecast.Recast
// Replace the current region with the new one if the
// current regions is neighbour.
replaceNeighbour(regions[j], oldId, mergeId);
ReplaceNeighbour(regions[j], oldId, mergeId);
}
mergeCount++;
@ -1188,7 +1188,7 @@ namespace DotRecast.Recast
return maxRegionId;
}
private static void addUniqueConnection(Region reg, int n)
private static void AddUniqueConnection(Region reg, int n)
{
if (!reg.connections.Contains(n))
{
@ -1196,7 +1196,7 @@ namespace DotRecast.Recast
}
}
private static int mergeAndFilterLayerRegions(Telemetry ctx, int minRegionArea, int maxRegionId,
private static int MergeAndFilterLayerRegions(Telemetry ctx, int minRegionArea, int maxRegionId,
CompactHeightfield chf, int[] srcReg, List<int> overlaps)
{
int w = chf.width;
@ -1250,7 +1250,7 @@ namespace DotRecast.Recast
int rai = srcReg[ai];
if (rai > 0 && rai < nreg && rai != ri)
{
addUniqueConnection(reg, rai);
AddUniqueConnection(reg, rai);
}
if ((rai & RC_BORDER_REG) != 0)
@ -1270,8 +1270,8 @@ namespace DotRecast.Recast
{
Region ri = regions[lregs[i]];
Region rj = regions[lregs[j]];
addUniqueFloorRegion(ri, lregs[j]);
addUniqueFloorRegion(rj, lregs[i]);
AddUniqueFloorRegion(ri, lregs[j]);
AddUniqueFloorRegion(rj, lregs[i]);
}
}
}
@ -1351,7 +1351,7 @@ namespace DotRecast.Recast
// Merge current layers to root.
for (int k = 0; k < regn.floors.Count; ++k)
{
addUniqueFloorRegion(root, regn.floors[k]);
AddUniqueFloorRegion(root, regn.floors[k]);
}
root.ymin = Math.Min(root.ymin, regn.ymin);
@ -1442,31 +1442,31 @@ namespace DotRecast.Recast
/// and rcCompactHeightfield::dist fields.
///
/// @see rcCompactHeightfield, rcBuildRegions, rcBuildRegionsMonotone
public static void buildDistanceField(Telemetry ctx, CompactHeightfield chf)
public static void BuildDistanceField(Telemetry ctx, CompactHeightfield chf)
{
ctx.startTimer("DISTANCEFIELD");
ctx.StartTimer("DISTANCEFIELD");
int[] src = new int[chf.spanCount];
ctx.startTimer("DISTANCEFIELD_DIST");
ctx.StartTimer("DISTANCEFIELD_DIST");
int maxDist = calculateDistanceField(chf, src);
int maxDist = CalculateDistanceField(chf, src);
chf.maxDistance = maxDist;
ctx.stopTimer("DISTANCEFIELD_DIST");
ctx.StopTimer("DISTANCEFIELD_DIST");
ctx.startTimer("DISTANCEFIELD_BLUR");
ctx.StartTimer("DISTANCEFIELD_BLUR");
// Blur
src = boxBlur(chf, 1, src);
src = BoxBlur(chf, 1, src);
// Store distance.
chf.dist = src;
ctx.stopTimer("DISTANCEFIELD_BLUR");
ctx.StopTimer("DISTANCEFIELD_BLUR");
ctx.stopTimer("DISTANCEFIELD");
ctx.StopTimer("DISTANCEFIELD");
}
private static void paintRectRegion(int minx, int maxx, int miny, int maxy, int regId, CompactHeightfield chf,
private static void PaintRectRegion(int minx, int maxx, int miny, int maxy, int regId, CompactHeightfield chf,
int[] srcReg)
{
int w = chf.width;
@ -1505,10 +1505,10 @@ namespace DotRecast.Recast
/// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions.
///
/// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig
public static void buildRegionsMonotone(Telemetry ctx, CompactHeightfield chf, int minRegionArea,
public static void BuildRegionsMonotone(Telemetry ctx, CompactHeightfield chf, int minRegionArea,
int mergeRegionArea)
{
ctx.startTimer("REGIONS");
ctx.StartTimer("REGIONS");
int w = chf.width;
int h = chf.height;
@ -1531,13 +1531,13 @@ namespace DotRecast.Recast
int bw = Math.Min(w, borderSize);
int bh = Math.Min(h, borderSize);
// Paint regions
paintRectRegion(0, bw, 0, h, id | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, bw, 0, h, id | RC_BORDER_REG, chf, srcReg);
id++;
paintRectRegion(w - bw, w, 0, h, id | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(w - bw, w, 0, h, id | RC_BORDER_REG, chf, srcReg);
id++;
paintRectRegion(0, w, 0, bh, id | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, w, 0, bh, id | RC_BORDER_REG, chf, srcReg);
id++;
paintRectRegion(0, w, h - bh, h, id | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, w, h - bh, h, id | RC_BORDER_REG, chf, srcReg);
id++;
}
@ -1650,15 +1650,15 @@ namespace DotRecast.Recast
}
}
ctx.startTimer("REGIONS_FILTER");
ctx.StartTimer("REGIONS_FILTER");
// Merge regions and filter out small regions.
List<int> overlaps = new List<int>();
chf.maxRegions = mergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, id, chf, srcReg, overlaps);
chf.maxRegions = MergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, id, chf, srcReg, overlaps);
// Monotone partitioning does not generate overlapping regions.
ctx.stopTimer("REGIONS_FILTER");
ctx.StopTimer("REGIONS_FILTER");
// Store the result out.
for (int i = 0; i < chf.spanCount; ++i)
@ -1666,7 +1666,7 @@ namespace DotRecast.Recast
chf.spans[i].reg = srcReg[i];
}
ctx.stopTimer("REGIONS");
ctx.StopTimer("REGIONS");
}
/// @par
@ -1688,16 +1688,16 @@ namespace DotRecast.Recast
/// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions.
///
/// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig
public static void buildRegions(Telemetry ctx, CompactHeightfield chf, int minRegionArea,
public static void BuildRegions(Telemetry ctx, CompactHeightfield chf, int minRegionArea,
int mergeRegionArea)
{
ctx.startTimer("REGIONS");
ctx.StartTimer("REGIONS");
int w = chf.width;
int h = chf.height;
int borderSize = chf.borderSize;
ctx.startTimer("REGIONS_WATERSHED");
ctx.StartTimer("REGIONS_WATERSHED");
int LOG_NB_STACKS = 3;
int NB_STACKS = 1 << LOG_NB_STACKS;
@ -1727,13 +1727,13 @@ namespace DotRecast.Recast
int bw = Math.Min(w, borderSize);
int bh = Math.Min(h, borderSize);
// Paint regions
paintRectRegion(0, bw, 0, h, regionId | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, bw, 0, h, regionId | RC_BORDER_REG, chf, srcReg);
regionId++;
paintRectRegion(w - bw, w, 0, h, regionId | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(w - bw, w, 0, h, regionId | RC_BORDER_REG, chf, srcReg);
regionId++;
paintRectRegion(0, w, 0, bh, regionId | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, w, 0, bh, regionId | RC_BORDER_REG, chf, srcReg);
regionId++;
paintRectRegion(0, w, h - bh, h, regionId | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, w, h - bh, h, regionId | RC_BORDER_REG, chf, srcReg);
regionId++;
}
@ -1745,27 +1745,27 @@ namespace DotRecast.Recast
level = level >= 2 ? level - 2 : 0;
sId = (sId + 1) & (NB_STACKS - 1);
// ctx->startTimer(RC_TIMER_DIVIDE_TO_LEVELS);
// ctx->StartTimer(RC_TIMER_DIVIDE_TO_LEVELS);
if (sId == 0)
{
sortCellsByLevel(level, chf, srcReg, NB_STACKS, lvlStacks, 1);
SortCellsByLevel(level, chf, srcReg, NB_STACKS, lvlStacks, 1);
}
else
{
appendStacks(lvlStacks[sId - 1], lvlStacks[sId], srcReg); // copy left overs from last level
AppendStacks(lvlStacks[sId - 1], lvlStacks[sId], srcReg); // copy left overs from last level
}
// ctx->stopTimer(RC_TIMER_DIVIDE_TO_LEVELS);
// ctx->StopTimer(RC_TIMER_DIVIDE_TO_LEVELS);
ctx.startTimer("REGIONS_EXPAND");
ctx.StartTimer("REGIONS_EXPAND");
// Expand current regions until no empty connected cells found.
expandRegions(expandIters, level, chf, srcReg, srcDist, lvlStacks[sId], false);
ExpandRegions(expandIters, level, chf, srcReg, srcDist, lvlStacks[sId], false);
ctx.stopTimer("REGIONS_EXPAND");
ctx.StopTimer("REGIONS_EXPAND");
ctx.startTimer("REGIONS_FLOOD");
ctx.StartTimer("REGIONS_FLOOD");
// Mark new regions with IDs.
for (int j = 0; j < lvlStacks[sId].Count; j += 3)
@ -1775,34 +1775,34 @@ namespace DotRecast.Recast
int i = lvlStacks[sId][j + 2];
if (i >= 0 && srcReg[i] == 0)
{
if (floodRegion(x, y, i, level, regionId, chf, srcReg, srcDist, stack))
if (FloodRegion(x, y, i, level, regionId, chf, srcReg, srcDist, stack))
{
regionId++;
}
}
}
ctx.stopTimer("REGIONS_FLOOD");
ctx.StopTimer("REGIONS_FLOOD");
}
// Expand current regions until no empty connected cells found.
expandRegions(expandIters * 8, 0, chf, srcReg, srcDist, stack, true);
ExpandRegions(expandIters * 8, 0, chf, srcReg, srcDist, stack, true);
ctx.stopTimer("REGIONS_WATERSHED");
ctx.StopTimer("REGIONS_WATERSHED");
ctx.startTimer("REGIONS_FILTER");
ctx.StartTimer("REGIONS_FILTER");
// Merge regions and filter out smalle regions.
List<int> overlaps = new List<int>();
chf.maxRegions = mergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, regionId, chf, srcReg, overlaps);
chf.maxRegions = MergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, regionId, chf, srcReg, overlaps);
// If overlapping regions were found during merging, split those regions.
if (overlaps.Count > 0)
{
ctx.warn("rcBuildRegions: " + overlaps.Count + " overlapping regions.");
ctx.Warn("rcBuildRegions: " + overlaps.Count + " overlapping regions.");
}
ctx.stopTimer("REGIONS_FILTER");
ctx.StopTimer("REGIONS_FILTER");
// Write the result out.
for (int i = 0; i < chf.spanCount; ++i)
@ -1810,12 +1810,12 @@ namespace DotRecast.Recast
chf.spans[i].reg = srcReg[i];
}
ctx.stopTimer("REGIONS");
ctx.StopTimer("REGIONS");
}
public static void buildLayerRegions(Telemetry ctx, CompactHeightfield chf, int minRegionArea)
public static void BuildLayerRegions(Telemetry ctx, CompactHeightfield chf, int minRegionArea)
{
ctx.startTimer("REGIONS");
ctx.StartTimer("REGIONS");
int w = chf.width;
int h = chf.height;
@ -1837,13 +1837,13 @@ namespace DotRecast.Recast
int bw = Math.Min(w, borderSize);
int bh = Math.Min(h, borderSize);
// Paint regions
paintRectRegion(0, bw, 0, h, id | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, bw, 0, h, id | RC_BORDER_REG, chf, srcReg);
id++;
paintRectRegion(w - bw, w, 0, h, id | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(w - bw, w, 0, h, id | RC_BORDER_REG, chf, srcReg);
id++;
paintRectRegion(0, w, 0, bh, id | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, w, 0, bh, id | RC_BORDER_REG, chf, srcReg);
id++;
paintRectRegion(0, w, h - bh, h, id | RC_BORDER_REG, chf, srcReg);
PaintRectRegion(0, w, h - bh, h, id | RC_BORDER_REG, chf, srcReg);
id++;
}
@ -1956,13 +1956,13 @@ namespace DotRecast.Recast
}
}
ctx.startTimer("REGIONS_FILTER");
ctx.StartTimer("REGIONS_FILTER");
// Merge monotone regions to layers and remove small regions.
List<int> overlaps = new List<int>();
chf.maxRegions = mergeAndFilterLayerRegions(ctx, minRegionArea, id, chf, srcReg, overlaps);
chf.maxRegions = MergeAndFilterLayerRegions(ctx, minRegionArea, id, chf, srcReg, overlaps);
ctx.stopTimer("REGIONS_FILTER");
ctx.StopTimer("REGIONS_FILTER");
// Store the result out.
for (int i = 0; i < chf.spanCount; ++i)
@ -1970,7 +1970,7 @@ namespace DotRecast.Recast
chf.spans[i].reg = srcReg[i];
}
ctx.stopTimer("REGIONS");
ctx.StopTimer("REGIONS");
}
}
}

View File

@ -25,61 +25,61 @@ namespace DotRecast.Recast
{
public static class RecastVectors
{
public static void min(ref Vector3f a, float[] b, int i)
public static void Min(ref Vector3f a, float[] b, int i)
{
a.x = Math.Min(a.x, b[i + 0]);
a.y = Math.Min(a.y, b[i + 1]);
a.z = Math.Min(a.z, b[i + 2]);
}
public static void min(ref Vector3f a, Vector3f b)
public static void Min(ref Vector3f a, Vector3f b)
{
a.x = Math.Min(a.x, b.x);
a.y = Math.Min(a.y, b.y);
a.z = Math.Min(a.z, b.z);
}
public static void max(ref Vector3f a, float[] b, int i)
public static void Max(ref Vector3f a, float[] b, int i)
{
a.x = Math.Max(a.x, b[i + 0]);
a.y = Math.Max(a.y, b[i + 1]);
a.z = Math.Max(a.z, b[i + 2]);
}
public static void max(ref Vector3f a, Vector3f b)
public static void Max(ref Vector3f a, Vector3f b)
{
a.x = Math.Max(a.x, b.x);
a.y = Math.Max(a.y, b.y);
a.z = Math.Max(a.z, b.z);
}
public static void copy(ref Vector3f @out, float[] @in, int i)
public static void Copy(ref Vector3f @out, float[] @in, int i)
{
copy(ref @out, 0, @in, i);
Copy(ref @out, 0, @in, i);
}
public static void copy(float[] @out, int n, float[] @in, int m)
public static void Copy(float[] @out, int n, float[] @in, int m)
{
@out[n] = @in[m];
@out[n + 1] = @in[m + 1];
@out[n + 2] = @in[m + 2];
}
public static void copy(float[] @out, int n, Vector3f @in, int m)
public static void Copy(float[] @out, int n, Vector3f @in, int m)
{
@out[n] = @in[m];
@out[n + 1] = @in[m + 1];
@out[n + 2] = @in[m + 2];
}
public static void copy(ref Vector3f @out, int n, float[] @in, int m)
public static void Copy(ref Vector3f @out, int n, float[] @in, int m)
{
@out[n] = @in[m];
@out[n + 1] = @in[m + 1];
@out[n + 2] = @in[m + 2];
}
public static void add(ref Vector3f e0, Vector3f a, float[] verts, int i)
public static void Add(ref Vector3f e0, Vector3f a, float[] verts, int i)
{
e0.x = a.x + verts[i];
e0.y = a.y + verts[i + 1];
@ -87,7 +87,7 @@ namespace DotRecast.Recast
}
public static void sub(ref Vector3f e0, float[] verts, int i, int j)
public static void Sub(ref Vector3f e0, float[] verts, int i, int j)
{
e0.x = verts[i] - verts[j];
e0.y = verts[i + 1] - verts[j + 1];
@ -95,7 +95,7 @@ namespace DotRecast.Recast
}
public static void sub(ref Vector3f e0, Vector3f i, float[] verts, int j)
public static void Sub(ref Vector3f e0, Vector3f i, float[] verts, int j)
{
e0.x = i.x - verts[j];
e0.y = i.y - verts[j + 1];
@ -103,21 +103,21 @@ namespace DotRecast.Recast
}
public static void cross(float[] dest, float[] v1, float[] v2)
public static void Cross(float[] dest, float[] v1, float[] v2)
{
dest[0] = v1[1] * v2[2] - v1[2] * v2[1];
dest[1] = v1[2] * v2[0] - v1[0] * v2[2];
dest[2] = v1[0] * v2[1] - v1[1] * v2[0];
}
public static void cross(float[] dest, Vector3f v1, Vector3f v2)
public static void Cross(float[] dest, Vector3f v1, Vector3f v2)
{
dest[0] = v1.y * v2.z - v1.z * v2.y;
dest[1] = v1.z * v2.x - v1.x * v2.z;
dest[2] = v1.x * v2.y - v1.y * v2.x;
}
public static void cross(ref Vector3f dest, Vector3f v1, Vector3f v2)
public static void Cross(ref Vector3f dest, Vector3f v1, Vector3f v2)
{
dest.x = v1.y * v2.z - v1.z * v2.y;
dest.y = v1.z * v2.x - v1.x * v2.z;
@ -125,7 +125,7 @@ namespace DotRecast.Recast
}
public static void normalize(float[] v)
public static void Normalize(float[] v)
{
float d = (float)(1.0f / Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
v[0] *= d;
@ -133,7 +133,7 @@ namespace DotRecast.Recast
v[2] *= d;
}
public static void normalize(ref Vector3f v)
public static void Normalize(ref Vector3f v)
{
float d = (float)(1.0f / Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z));
v.x *= d;
@ -141,17 +141,17 @@ namespace DotRecast.Recast
v.z *= d;
}
public static float dot(float[] v1, float[] v2)
public static float Dot(float[] v1, float[] v2)
{
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
public static float dot(float[] v1, Vector3f v2)
public static float Dot(float[] v1, Vector3f v2)
{
return v1[0] * v2.x + v1[1] * v2.y + v1[2] * v2.z;
}
public static float dot(Vector3f v1, Vector3f v2)
public static float Dot(Vector3f v1, Vector3f v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}

View File

@ -23,7 +23,7 @@ namespace DotRecast.Recast
{
public class RecastVoxelization
{
public static Heightfield buildSolidHeightfield(InputGeomProvider geomProvider, RecastBuilderConfig builderCfg,
public static Heightfield BuildSolidHeightfield(InputGeomProvider geomProvider, RecastBuilderConfig builderCfg,
Telemetry ctx)
{
RecastConfig cfg = builderCfg.cfg;
@ -41,9 +41,9 @@ namespace DotRecast.Recast
// If your input data is multiple meshes, you can transform them here,
// calculate
// the are type for each of the meshes and rasterize them.
foreach (TriMesh geom in geomProvider.meshes())
foreach (TriMesh geom in geomProvider.Meshes())
{
float[] verts = geom.getVerts();
float[] verts = geom.GetVerts();
if (cfg.useTiles)
{
float[] tbmin = new float[2];
@ -52,21 +52,21 @@ namespace DotRecast.Recast
tbmin[1] = builderCfg.bmin.z;
tbmax[0] = builderCfg.bmax.x;
tbmax[1] = builderCfg.bmax.z;
List<ChunkyTriMeshNode> nodes = geom.getChunksOverlappingRect(tbmin, tbmax);
List<ChunkyTriMeshNode> nodes = geom.GetChunksOverlappingRect(tbmin, tbmax);
foreach (ChunkyTriMeshNode node in nodes)
{
int[] tris = node.tris;
int ntris = tris.Length / 3;
int[] m_triareas = Recast.markWalkableTriangles(ctx, cfg.walkableSlopeAngle, verts, tris, ntris, cfg.walkableAreaMod);
RecastRasterization.rasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.walkableClimb, ctx);
int[] m_triareas = Recast.MarkWalkableTriangles(ctx, cfg.walkableSlopeAngle, verts, tris, ntris, cfg.walkableAreaMod);
RecastRasterization.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.walkableClimb, ctx);
}
}
else
{
int[] tris = geom.getTris();
int[] tris = geom.GetTris();
int ntris = tris.Length / 3;
int[] m_triareas = Recast.markWalkableTriangles(ctx, cfg.walkableSlopeAngle, verts, tris, ntris, cfg.walkableAreaMod);
RecastRasterization.rasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.walkableClimb, ctx);
int[] m_triareas = Recast.MarkWalkableTriangles(ctx, cfg.walkableSlopeAngle, verts, tris, ntris, cfg.walkableAreaMod);
RecastRasterization.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.walkableClimb, ctx);
}
}

View File

@ -31,19 +31,19 @@ namespace DotRecast.Recast
private readonly ThreadLocal<Dictionary<string, AtomicLong>> timerStart = new ThreadLocal<Dictionary<string, AtomicLong>>(() => new Dictionary<string, AtomicLong>());
private readonly ConcurrentDictionary<string, AtomicLong> timerAccum = new ConcurrentDictionary<string, AtomicLong>();
public void startTimer(string name)
public void StartTimer(string name)
{
timerStart.Value[name] = new AtomicLong(FrequencyWatch.Ticks);
}
public void stopTimer(string name)
public void StopTimer(string name)
{
timerAccum
.GetOrAdd(name, _ => new AtomicLong(0))
.AddAndGet(FrequencyWatch.Ticks - timerStart.Value?[name].Read() ?? 0);
}
public void warn(string @string)
public void Warn(string @string)
{
Console.WriteLine(@string);
}

View File

@ -64,9 +64,9 @@ public class AbstractCrowdTest
protected List<CrowdAgent> agents;
[SetUp]
public void setUp()
public void SetUp()
{
nmd = new RecastTestMeshBuilder().getMeshData();
nmd = new RecastTestMeshBuilder().GetMeshData();
navmesh = new NavMesh(nmd, 6, 0);
query = new NavMeshQuery(navmesh);
CrowdConfig config = new CrowdConfig(0.6f);
@ -76,29 +76,29 @@ public class AbstractCrowdTest
option.adaptiveDivs = 5;
option.adaptiveRings = 2;
option.adaptiveDepth = 1;
crowd.setObstacleAvoidanceParams(0, option);
crowd.SetObstacleAvoidanceParams(0, option);
option = new ObstacleAvoidanceParams();
option.velBias = 0.5f;
option.adaptiveDivs = 5;
option.adaptiveRings = 2;
option.adaptiveDepth = 2;
crowd.setObstacleAvoidanceParams(1, option);
crowd.SetObstacleAvoidanceParams(1, option);
option = new ObstacleAvoidanceParams();
option.velBias = 0.5f;
option.adaptiveDivs = 7;
option.adaptiveRings = 2;
option.adaptiveDepth = 3;
crowd.setObstacleAvoidanceParams(2, option);
crowd.SetObstacleAvoidanceParams(2, option);
option = new ObstacleAvoidanceParams();
option.velBias = 0.5f;
option.adaptiveDivs = 7;
option.adaptiveRings = 3;
option.adaptiveDepth = 3;
crowd.setObstacleAvoidanceParams(3, option);
crowd.SetObstacleAvoidanceParams(3, option);
agents = new();
}
protected CrowdAgentParams getAgentParams(int updateFlags, int obstacleAvoidanceType)
protected CrowdAgentParams GetAgentParams(int updateFlags, int obstacleAvoidanceType)
{
CrowdAgentParams ap = new CrowdAgentParams();
ap.radius = 0.6f;
@ -113,9 +113,9 @@ public class AbstractCrowdTest
return ap;
}
protected void addAgentGrid(int size, float distance, int updateFlags, int obstacleAvoidanceType, Vector3f startPos)
protected void AddAgentGrid(int size, float distance, int updateFlags, int obstacleAvoidanceType, Vector3f startPos)
{
CrowdAgentParams ap = getAgentParams(updateFlags, obstacleAvoidanceType);
CrowdAgentParams ap = GetAgentParams(updateFlags, obstacleAvoidanceType);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
@ -124,46 +124,46 @@ public class AbstractCrowdTest
pos.x = startPos.x + i * distance;
pos.y = startPos.y;
pos.z = startPos.z + j * distance;
agents.Add(crowd.addAgent(pos, ap));
agents.Add(crowd.AddAgent(pos, ap));
}
}
}
protected void setMoveTarget(Vector3f pos, bool adjust)
protected void SetMoveTarget(Vector3f pos, bool adjust)
{
Vector3f ext = crowd.getQueryExtents();
QueryFilter filter = crowd.getFilter(0);
Vector3f ext = crowd.GetQueryExtents();
QueryFilter filter = crowd.GetFilter(0);
if (adjust)
{
foreach (CrowdAgent ag in crowd.getActiveAgents())
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Vector3f vel = calcVel(ag.npos, pos, ag.option.maxSpeed);
crowd.requestMoveVelocity(ag, vel);
Vector3f vel = CalcVel(ag.npos, pos, ag.option.maxSpeed);
crowd.RequestMoveVelocity(ag, vel);
}
}
else
{
Result<FindNearestPolyResult> nearest = query.findNearestPoly(pos, ext, filter);
foreach (CrowdAgent ag in crowd.getActiveAgents())
Result<FindNearestPolyResult> nearest = query.FindNearestPoly(pos, ext, filter);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
crowd.requestMoveTarget(ag, nearest.result.getNearestRef(), nearest.result.getNearestPos());
crowd.RequestMoveTarget(ag, nearest.result.GetNearestRef(), nearest.result.GetNearestPos());
}
}
}
protected Vector3f calcVel(Vector3f pos, Vector3f tgt, float speed)
protected Vector3f CalcVel(Vector3f pos, Vector3f tgt, float speed)
{
Vector3f vel = vSub(tgt, pos);
Vector3f vel = VSub(tgt, pos);
vel.y = 0.0f;
vNormalize(ref vel);
vel = vScale(vel, speed);
VNormalize(ref vel);
vel = VScale(vel, speed);
return vel;
}
protected void dumpActiveAgents(int i)
protected void DumpActiveAgents(int i)
{
Console.WriteLine(crowd.getActiveAgents().Count);
foreach (CrowdAgent ag in crowd.getActiveAgents())
Console.WriteLine(crowd.GetActiveAgents().Count);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Console.WriteLine(ag.state + ", " + ag.targetState);
Console.WriteLine(ag.npos.x + ", " + ag.npos.y + ", " + ag.npos.z);

View File

@ -563,17 +563,17 @@ public class Crowd1Test : AbstractCrowdTest
};
[Test]
public void testAgent1Quality0TVTA()
public void TestAgent1Quality0TVTA()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE;
addAgentGrid(1, 0.4f, updateFlags, 0, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(1, 0.4f, updateFlags, 0, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q0TVTA.Length; i++)
{
crowd.update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.getActiveAgents())
crowd.Update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q0TVTA[i][0]).Within(0.001f));
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q0TVTA[i][1]).Within(0.001f));
@ -586,17 +586,17 @@ public class Crowd1Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality0TVT()
public void TestAgent1Quality0TVT()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO;
addAgentGrid(1, 0.4f, updateFlags, 0, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(1, 0.4f, updateFlags, 0, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q0TVT.Length; i++)
{
crowd.update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.getActiveAgents())
crowd.Update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q0TVT[i][0]).Within(0.001f));
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q0TVT[i][1]).Within(0.001f));
@ -609,16 +609,16 @@ public class Crowd1Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality0TV()
public void TestAgent1Quality0TV()
{
int updateFlags = CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS;
addAgentGrid(1, 0.4f, updateFlags, 0, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(1, 0.4f, updateFlags, 0, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q0TV.Length; i++)
{
crowd.update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.getActiveAgents())
crowd.Update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q0TV[i][0]).Within(0.001f));
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q0TV[i][1]).Within(0.001f));
@ -631,16 +631,16 @@ public class Crowd1Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality0T()
public void TestAgent1Quality0T()
{
int updateFlags = CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO;
addAgentGrid(1, 0.4f, updateFlags, 0, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(1, 0.4f, updateFlags, 0, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q0T.Length; i++)
{
crowd.update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.getActiveAgents())
crowd.Update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q0T[i][0]).Within(0.001));
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q0T[i][1]).Within(0.001));
@ -653,17 +653,17 @@ public class Crowd1Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality1TVTA()
public void TestAgent1Quality1TVTA()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE;
addAgentGrid(1, 0.4f, updateFlags, 1, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(1, 0.4f, updateFlags, 1, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q1TVTA.Length; i++)
{
crowd.update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.getActiveAgents())
crowd.Update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q1TVTA[i][0]).Within(0.001f));
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q1TVTA[i][1]).Within(0.001f));
@ -676,17 +676,17 @@ public class Crowd1Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality2TVTA()
public void TestAgent1Quality2TVTA()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE;
addAgentGrid(1, 0.4f, updateFlags, 2, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(1, 0.4f, updateFlags, 2, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q2TVTA.Length; i++)
{
crowd.update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.getActiveAgents())
crowd.Update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q2TVTA[i][0]).Within(0.001f));
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q2TVTA[i][1]).Within(0.001f));
@ -699,17 +699,17 @@ public class Crowd1Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality3TVTA()
public void TestAgent1Quality3TVTA()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE;
addAgentGrid(1, 0.4f, updateFlags, 3, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(1, 0.4f, updateFlags, 3, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q3TVTA.Length; i++)
{
crowd.update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.getActiveAgents())
crowd.Update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q3TVTA[i][0]).Within(0.001f));
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q3TVTA[i][1]).Within(0.001f));
@ -722,18 +722,18 @@ public class Crowd1Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality3TVTAS()
public void TestAgent1Quality3TVTAS()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE
| CrowdAgentParams.DT_CROWD_SEPARATION;
addAgentGrid(1, 0.4f, updateFlags, 3, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(1, 0.4f, updateFlags, 3, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q3TVTAS.Length; i++)
{
crowd.update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.getActiveAgents())
crowd.Update(1 / 5f, null);
foreach (CrowdAgent ag in crowd.GetActiveAgents())
{
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q3TVTAS[i][0]).Within(0.001f));
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q3TVTAS[i][1]).Within(0.001f));

View File

@ -306,16 +306,16 @@ public class Crowd4Test : AbstractCrowdTest
};
[Test]
public void testAgent1Quality2TVTA()
public void TestAgent1Quality2TVTA()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE;
addAgentGrid(2, 0.3f, updateFlags, 2, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(2, 0.3f, updateFlags, 2, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q2TVTA.Length; i++)
{
crowd.update(1 / 5f, null);
crowd.Update(1 / 5f, null);
CrowdAgent ag = agents[2];
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q2TVTA[i][0]).Within(0.001f), $"{i}");
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q2TVTA[i][1]).Within(0.001f), $"{i}");
@ -327,17 +327,17 @@ public class Crowd4Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality2TVTAS()
public void TestAgent1Quality2TVTAS()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE
| CrowdAgentParams.DT_CROWD_SEPARATION;
addAgentGrid(2, 0.3f, updateFlags, 2, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(2, 0.3f, updateFlags, 2, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q2TVTAS.Length; i++)
{
crowd.update(1 / 5f, null);
crowd.Update(1 / 5f, null);
CrowdAgent ag = agents[2];
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q2TVTAS[i][0]).Within(0.001f), $"{i}");
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q2TVTAS[i][1]).Within(0.001f), $"{i}");
@ -349,15 +349,15 @@ public class Crowd4Test : AbstractCrowdTest
}
[Test]
public void testAgent1Quality2T()
public void TestAgent1Quality2T()
{
int updateFlags = CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO;
addAgentGrid(2, 0.3f, updateFlags, 2, startPoss[0]);
setMoveTarget(endPoss[0], false);
AddAgentGrid(2, 0.3f, updateFlags, 2, startPoss[0]);
SetMoveTarget(endPoss[0], false);
for (int i = 0; i < EXPECTED_A1Q2T.Length; i++)
{
crowd.update(1 / 5f, null);
crowd.Update(1 / 5f, null);
CrowdAgent ag = agents[2];
Assert.That(ag.npos.x, Is.EqualTo(EXPECTED_A1Q2T[i][0]).Within(0.00001f), $"{i} - {ag.npos.x} {EXPECTED_A1Q2T[i][0]}");
Assert.That(ag.npos.y, Is.EqualTo(EXPECTED_A1Q2T[i][1]).Within(0.00001f), $"{i} - {ag.npos.y} {EXPECTED_A1Q2T[i][1]}");

View File

@ -97,19 +97,19 @@ public class Crowd4VelocityTest : AbstractCrowdTest
};
[Test]
public void testAgent1Quality3TVTA()
public void TestAgent1Quality3TVTA()
{
int updateFlags = CrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS
| CrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | CrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE;
addAgentGrid(2, 0.3f, updateFlags, 3, endPoss[0]);
setMoveTarget(endPoss[4], false);
AddAgentGrid(2, 0.3f, updateFlags, 3, endPoss[0]);
SetMoveTarget(endPoss[4], false);
for (int i = 0; i < EXPECTED_A1Q3TVTA.Length; i++)
{
crowd.update(1 / 5f, null);
crowd.Update(1 / 5f, null);
if (i == 20)
{
setMoveTarget(startPoss[2], true);
SetMoveTarget(startPoss[2], true);
}
CrowdAgent ag = agents[1];

View File

@ -31,13 +31,13 @@ public class PathCorridorTest
private readonly QueryFilter filter = new DefaultQueryFilter();
[SetUp]
public void setUp()
public void SetUp()
{
corridor.reset(0, Vector3f.Of(10, 20, 30));
corridor.Reset(0, Vector3f.Of(10, 20, 30));
}
[Test]
public void shouldKeepOriginalPathInFindCornersWhenNothingCanBePruned()
public void ShouldKeepOriginalPathInFindCornersWhenNothingCanBePruned()
{
List<StraightPathItem> straightPath = new();
straightPath.Add(new StraightPathItem(Vector3f.Of(11, 20, 30.00001f), 0, 0));
@ -46,20 +46,20 @@ public class PathCorridorTest
straightPath.Add(new StraightPathItem(Vector3f.Of(11f, 21, 32f), 0, 0));
Result<List<StraightPathItem>> result = Results.Success(straightPath);
var mockQuery = new Mock<NavMeshQuery>(It.IsAny<NavMesh>());
mockQuery.Setup(q => q.findStraightPath(
mockQuery.Setup(q => q.FindStraightPath(
It.IsAny<Vector3f>(),
It.IsAny<Vector3f>(),
It.IsAny<List<long>>(),
It.IsAny<int>(),
It.IsAny<int>())
).Returns(result);
List<StraightPathItem> path = corridor.findCorners(int.MaxValue, mockQuery.Object, filter);
List<StraightPathItem> path = corridor.FindCorners(int.MaxValue, mockQuery.Object, filter);
Assert.That(path.Count, Is.EqualTo(4));
Assert.That(path, Is.EqualTo(straightPath));
}
[Test]
public void shouldPrunePathInFindCorners()
public void ShouldPrunePathInFindCorners()
{
List<StraightPathItem> straightPath = new();
straightPath.Add(new StraightPathItem(Vector3f.Of(10, 20, 30.00001f), 0, 0)); // too close
@ -70,7 +70,7 @@ public class PathCorridorTest
Result<List<StraightPathItem>> result = Results.Success(straightPath);
var mockQuery = new Mock<NavMeshQuery>(It.IsAny<NavMesh>());
var s = mockQuery.Setup(q => q.findStraightPath(
var s = mockQuery.Setup(q => q.FindStraightPath(
It.IsAny<Vector3f>(),
It.IsAny<Vector3f>(),
It.IsAny<List<long>>(),
@ -78,7 +78,7 @@ public class PathCorridorTest
It.IsAny<int>())
).Returns(result);
List<StraightPathItem> path = corridor.findCorners(int.MaxValue, mockQuery.Object, filter);
List<StraightPathItem> path = corridor.FindCorners(int.MaxValue, mockQuery.Object, filter);
Assert.That(path.Count, Is.EqualTo(2));
Assert.That(path, Is.EqualTo(new List<StraightPathItem> { straightPath[2], straightPath[3] }));
}

View File

@ -39,7 +39,7 @@ public class RecastTestMeshBuilder
public const float m_detailSampleDist = 6.0f;
public const float m_detailSampleMaxError = 1.0f;
public RecastTestMeshBuilder() : this(ObjImporter.load(Loader.ToBytes("dungeon.obj")),
public RecastTestMeshBuilder() : this(ObjImporter.Load(Loader.ToBytes("dungeon.obj")),
PartitionType.WATERSHED, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_agentMaxSlope,
m_regionMinSize, m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, m_detailSampleDist,
m_detailSampleMaxError)
@ -54,16 +54,16 @@ public class RecastTestMeshBuilder
RecastConfig cfg = new RecastConfig(m_partitionType, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius,
m_agentMaxClimb, m_agentMaxSlope, m_regionMinSize, m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError,
m_vertsPerPoly, m_detailSampleDist, m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_GROUND);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, m_geom.getMeshBoundsMin(), m_geom.getMeshBoundsMax());
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, m_geom.GetMeshBoundsMin(), m_geom.GetMeshBoundsMax());
RecastBuilder rcBuilder = new RecastBuilder();
RecastBuilderResult rcResult = rcBuilder.build(m_geom, bcfg);
PolyMesh m_pmesh = rcResult.getMesh();
RecastBuilderResult rcResult = rcBuilder.Build(m_geom, bcfg);
PolyMesh m_pmesh = rcResult.GetMesh();
for (int i = 0; i < m_pmesh.npolys; ++i)
{
m_pmesh.flags[i] = 1;
}
PolyMeshDetail m_dmesh = rcResult.getMeshDetail();
PolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
option.verts = m_pmesh.verts;
option.vertCount = m_pmesh.nverts;
@ -104,10 +104,10 @@ public class RecastTestMeshBuilder
option.offMeshConUserID = new int[1];
option.offMeshConUserID[0] = 0x4567;
option.offMeshConCount = 1;
meshData = NavMeshBuilder.createNavMeshData(option);
meshData = NavMeshBuilder.CreateNavMeshData(option);
}
public MeshData getMeshData()
public MeshData GetMeshData()
{
return meshData;
}

View File

@ -19,7 +19,7 @@ public class DynamicNavMeshTest
[Test]
public void e2eTest()
public void E2eTest()
{
byte[] bytes = Loader.ToBytes("test_tiles.voxels");
using var ms = new MemoryStream(bytes);
@ -27,51 +27,51 @@ public class DynamicNavMeshTest
// load voxels from file
VoxelFileReader reader = new VoxelFileReader();
VoxelFile f = reader.read(bis);
VoxelFile f = reader.Read(bis);
// create dynamic navmesh
DynamicNavMesh mesh = new DynamicNavMesh(f);
// build navmesh asynchronously using multiple threads
Task<bool> future = mesh.build(Task.Factory);
Task<bool> future = mesh.Build(Task.Factory);
// wait for build to complete
bool _ = future.Result;
// create new query
NavMeshQuery query = new NavMeshQuery(mesh.navMesh());
NavMeshQuery query = new NavMeshQuery(mesh.NavMesh());
QueryFilter filter = new DefaultQueryFilter();
// find path
FindNearestPolyResult start = query.findNearestPoly(START_POS, EXTENT, filter).result;
FindNearestPolyResult end = query.findNearestPoly(END_POS, EXTENT, filter).result;
List<long> path = query.findPath(start.getNearestRef(), end.getNearestRef(), start.getNearestPos(),
end.getNearestPos(), filter, NavMeshQuery.DT_FINDPATH_ANY_ANGLE, float.MaxValue).result;
FindNearestPolyResult start = query.FindNearestPoly(START_POS, EXTENT, filter).result;
FindNearestPolyResult end = query.FindNearestPoly(END_POS, EXTENT, filter).result;
List<long> path = query.FindPath(start.GetNearestRef(), end.GetNearestRef(), start.GetNearestPos(),
end.GetNearestPos(), filter, NavMeshQuery.DT_FINDPATH_ANY_ANGLE, float.MaxValue).result;
// check path length without any obstacles
Assert.That(path.Count, Is.EqualTo(16));
// place obstacle
Collider colldier = new SphereCollider(SPHERE_POS, 20, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND, 0.1f);
long colliderId = mesh.addCollider(colldier);
long colliderId = mesh.AddCollider(colldier);
// update navmesh asynchronously
future = mesh.update(Task.Factory);
future = mesh.Update(Task.Factory);
// wait for update to complete
_ = future.Result;
// create new query
query = new NavMeshQuery(mesh.navMesh());
query = new NavMeshQuery(mesh.NavMesh());
// find path again
start = query.findNearestPoly(START_POS, EXTENT, filter).result;
end = query.findNearestPoly(END_POS, EXTENT, filter).result;
path = query.findPath(start.getNearestRef(), end.getNearestRef(), start.getNearestPos(), end.getNearestPos(), filter,
start = query.FindNearestPoly(START_POS, EXTENT, filter).result;
end = query.FindNearestPoly(END_POS, EXTENT, filter).result;
path = query.FindPath(start.GetNearestRef(), end.GetNearestRef(), start.GetNearestPos(), end.GetNearestPos(), filter,
NavMeshQuery.DT_FINDPATH_ANY_ANGLE, float.MaxValue).result;
// check path length with obstacles
Assert.That(path.Count, Is.EqualTo(19));
// remove obstacle
mesh.removeCollider(colliderId);
mesh.RemoveCollider(colliderId);
// update navmesh asynchronously
future = mesh.update(Task.Factory);
future = mesh.Update(Task.Factory);
// wait for update to complete
_ = future.Result;
// create new query
query = new NavMeshQuery(mesh.navMesh());
query = new NavMeshQuery(mesh.NavMesh());
// find path one more time
start = query.findNearestPoly(START_POS, EXTENT, filter).result;
end = query.findNearestPoly(END_POS, EXTENT, filter).result;
path = query.findPath(start.getNearestRef(), end.getNearestRef(), start.getNearestPos(), end.getNearestPos(), filter,
start = query.FindNearestPoly(START_POS, EXTENT, filter).result;
end = query.FindNearestPoly(END_POS, EXTENT, filter).result;
path = query.FindPath(start.GetNearestRef(), end.GetNearestRef(), start.GetNearestPos(), end.GetNearestPos(), filter,
NavMeshQuery.DT_FINDPATH_ANY_ANGLE, float.MaxValue).result;
// path length should be back to the initial value
Assert.That(path.Count, Is.EqualTo(16));

View File

@ -27,14 +27,14 @@ namespace DotRecast.Detour.Dynamic.Test.Io;
public class VoxelFileReaderTest
{
[Test]
public void shouldReadSingleTileFile()
public void ShouldReadSingleTileFile()
{
byte[] bytes = Loader.ToBytes("test.voxels");
using var ms = new MemoryStream(bytes);
using var bis = new BinaryReader(ms);
VoxelFileReader reader = new VoxelFileReader();
VoxelFile f = reader.read(bis);
VoxelFile f = reader.Read(bis);
Assert.That(f.useTiles, Is.False);
Assert.That(f.bounds, Is.EqualTo(new float[] { -100.0f, 0f, -100f, 100f, 5f, 100f }));
Assert.That(f.cellSize, Is.EqualTo(0.25f));
@ -53,14 +53,14 @@ public class VoxelFileReaderTest
}
[Test]
public void shouldReadMultiTileFile()
public void ShouldReadMultiTileFile()
{
byte[] bytes = Loader.ToBytes("test_tiles.voxels");
using var ms = new MemoryStream(bytes);
using var bis = new BinaryReader(ms);
VoxelFileReader reader = new VoxelFileReader();
VoxelFile f = reader.read(bis);
VoxelFile f = reader.Read(bis);
Assert.That(f.useTiles, Is.True);
Assert.That(f.bounds, Is.EqualTo(new float[] { -100.0f, 0f, -100f, 100f, 5f, 100f }));

View File

@ -28,13 +28,13 @@ public class VoxelFileReaderWriterTest
{
[TestCase(false)]
[TestCase(true)]
public void shouldReadSingleTileFile(bool compression)
public void ShouldReadSingleTileFile(bool compression)
{
byte[] bytes = Loader.ToBytes("test.voxels");
using var ms = new MemoryStream(bytes);
using var bis = new BinaryReader(ms);
VoxelFile f = readWriteRead(bis, compression);
VoxelFile f = ReadWriteRead(bis, compression);
Assert.That(f.useTiles, Is.False);
Assert.That(f.bounds, Is.EqualTo(new[] { -100.0f, 0f, -100f, 100f, 5f, 100f }));
Assert.That(f.cellSize, Is.EqualTo(0.25f));
@ -56,13 +56,13 @@ public class VoxelFileReaderWriterTest
[TestCase(false)]
[TestCase(true)]
public void shouldReadMultiTileFile(bool compression)
public void ShouldReadMultiTileFile(bool compression)
{
byte[] bytes = Loader.ToBytes("test_tiles.voxels");
using var ms = new MemoryStream(bytes);
using var bis = new BinaryReader(ms);
VoxelFile f = readWriteRead(bis, compression);
VoxelFile f = ReadWriteRead(bis, compression);
Assert.That(f.useTiles, Is.True);
Assert.That(f.bounds, Is.EqualTo(new[] { -100.0f, 0f, -100f, 100f, 5f, 100f }));
@ -85,18 +85,18 @@ public class VoxelFileReaderWriterTest
Assert.That(f.tiles[0].boundsMax, Is.EqualTo(Vector3f.Of(-78.75f, 5.0f, -78.75f)));
}
private VoxelFile readWriteRead(BinaryReader bis, bool compression)
private VoxelFile ReadWriteRead(BinaryReader bis, bool compression)
{
VoxelFileReader reader = new VoxelFileReader();
VoxelFile f = reader.read(bis);
VoxelFile f = reader.Read(bis);
using var msOut = new MemoryStream();
using var bwOut = new BinaryWriter(msOut);
VoxelFileWriter writer = new VoxelFileWriter();
writer.write(bwOut, f, compression);
writer.Write(bwOut, f, compression);
using var msIn = new MemoryStream(msOut.ToArray());
using var brIn = new BinaryReader(msIn);
return reader.read(brIn);
return reader.Read(brIn);
}
}

View File

@ -37,7 +37,7 @@ public class VoxelQueryTest
[Test]
public void shouldTraverseTiles()
public void ShouldTraverseTiles()
{
var hfProvider = new Mock<Func<int, int, Heightfield>>();
@ -59,7 +59,7 @@ public class VoxelQueryTest
Vector3f end = Vector3f.Of(320, 10, 57);
// When
query.raycast(start, end);
query.Raycast(start, end);
// Then
hfProvider.Verify(mock => mock.Invoke(It.IsAny<int>(), It.IsAny<int>()), Times.Exactly(6));
Assert.That(captorX, Is.EqualTo(new[] { 0, 1, 1, 1, 2, 2 }));
@ -67,29 +67,29 @@ public class VoxelQueryTest
}
[Test]
public void shouldHandleRaycastWithoutObstacles()
public void ShouldHandleRaycastWithoutObstacles()
{
DynamicNavMesh mesh = createDynaMesh();
VoxelQuery query = mesh.voxelQuery();
DynamicNavMesh mesh = CreateDynaMesh();
VoxelQuery query = mesh.VoxelQuery();
Vector3f start = Vector3f.Of(7.4f, 0.5f, -64.8f);
Vector3f end = Vector3f.Of(31.2f, 0.5f, -75.3f);
float? hit = query.raycast(start, end);
float? hit = query.Raycast(start, end);
Assert.That(hit, Is.Null);
}
[Test]
public void shouldHandleRaycastWithObstacles()
public void ShouldHandleRaycastWithObstacles()
{
DynamicNavMesh mesh = createDynaMesh();
VoxelQuery query = mesh.voxelQuery();
DynamicNavMesh mesh = CreateDynaMesh();
VoxelQuery query = mesh.VoxelQuery();
Vector3f start = Vector3f.Of(32.3f, 0.5f, 47.9f);
Vector3f end = Vector3f.Of(-31.2f, 0.5f, -29.8f);
float? hit = query.raycast(start, end);
float? hit = query.Raycast(start, end);
Assert.That(hit, Is.Not.Null);
Assert.That(hit.Value, Is.EqualTo(0.5263836f).Within(1e-7f));
}
private DynamicNavMesh createDynaMesh()
private DynamicNavMesh CreateDynaMesh()
{
var bytes = Loader.ToBytes("test_tiles.voxels");
using var ms = new MemoryStream(bytes);
@ -97,11 +97,11 @@ public class VoxelQueryTest
// load voxels from file
VoxelFileReader reader = new VoxelFileReader();
VoxelFile f = reader.read(bis);
VoxelFile f = reader.Read(bis);
// create dynamic navmesh
var mesh = new DynamicNavMesh(f);
// build navmesh asynchronously using multiple threads
Task<bool> future = mesh.build(Task.Factory);
Task<bool> future = mesh.Build(Task.Factory);
// wait for build to complete
var _ = future.Result;
return mesh;

View File

@ -31,53 +31,53 @@ namespace DotRecast.Detour.Extras.Test.Unity.Astar;
public class UnityAStarPathfindingImporterTest
{
[Test]
public void test_v4_0_6()
public void Test_v4_0_6()
{
NavMesh mesh = loadNavMesh("graph.zip");
NavMesh mesh = LoadNavMesh("graph.zip");
Vector3f startPos = Vector3f.Of(8.200293f, 2.155071f, -26.176147f);
Vector3f endPos = Vector3f.Of(11.971109f, 0.000000f, 8.663261f);
Result<List<long>> path = findPath(mesh, startPos, endPos);
Result<List<long>> path = FindPath(mesh, startPos, endPos);
Assert.That(path.status, Is.EqualTo(Status.SUCCSESS));
Assert.That(path.result.Count, Is.EqualTo(57));
saveMesh(mesh, "v4_0_6");
SaveMesh(mesh, "v4_0_6");
}
[Test]
public void test_v4_1_16()
public void Test_v4_1_16()
{
NavMesh mesh = loadNavMesh("graph_v4_1_16.zip");
NavMesh mesh = LoadNavMesh("graph_v4_1_16.zip");
Vector3f startPos = Vector3f.Of(22.93f, -2.37f, -5.11f);
Vector3f endPos = Vector3f.Of(16.81f, -2.37f, 25.52f);
Result<List<long>> path = findPath(mesh, startPos, endPos);
Assert.That(path.status.isSuccess(), Is.True);
Result<List<long>> path = FindPath(mesh, startPos, endPos);
Assert.That(path.status.IsSuccess(), Is.True);
Assert.That(path.result.Count, Is.EqualTo(15));
saveMesh(mesh, "v4_1_16");
SaveMesh(mesh, "v4_1_16");
}
[Test]
public void testBoundsTree()
public void TestBoundsTree()
{
NavMesh mesh = loadNavMesh("test_boundstree.zip");
NavMesh mesh = LoadNavMesh("test_boundstree.zip");
Vector3f position = Vector3f.Of(387.52988f, 19.997f, 368.86282f);
int[] tilePos = mesh.calcTileLoc(position);
long tileRef = mesh.getTileRefAt(tilePos[0], tilePos[1], 0);
MeshTile tile = mesh.getTileByRef(tileRef);
int[] tilePos = mesh.CalcTileLoc(position);
long tileRef = mesh.GetTileRefAt(tilePos[0], tilePos[1], 0);
MeshTile tile = mesh.GetTileByRef(tileRef);
MeshData data = tile.data;
BVNode[] bvNodes = data.bvTree;
data.bvTree = null; // set BV-Tree empty to get 'clear' search poly without BV
FindNearestPolyResult clearResult = getNearestPolys(mesh, position)[0]; // check poly to exists
FindNearestPolyResult clearResult = GetNearestPolys(mesh, position)[0]; // check poly to exists
// restore BV-Tree and try search again
// important aspect in that test: BV result must equals result without BV
// if poly not found or found other poly - tile bounds is wrong!
data.bvTree = bvNodes;
FindNearestPolyResult bvResult = getNearestPolys(mesh, position)[0];
FindNearestPolyResult bvResult = GetNearestPolys(mesh, position)[0];
Assert.That(bvResult.getNearestRef(), Is.EqualTo(clearResult.getNearestRef()));
Assert.That(bvResult.GetNearestRef(), Is.EqualTo(clearResult.GetNearestRef()));
}
private NavMesh loadNavMesh(string filename)
private NavMesh LoadNavMesh(string filename)
{
var filepath = Loader.ToRPath(filename);
using var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
@ -85,21 +85,21 @@ public class UnityAStarPathfindingImporterTest
// Import the graphs
UnityAStarPathfindingImporter importer = new UnityAStarPathfindingImporter();
NavMesh[] meshes = importer.load(fs);
NavMesh[] meshes = importer.Load(fs);
return meshes[0];
}
private Result<List<long>> findPath(NavMesh mesh, Vector3f startPos, Vector3f endPos)
private Result<List<long>> FindPath(NavMesh mesh, Vector3f startPos, Vector3f endPos)
{
// Perform a simple pathfinding
NavMeshQuery query = new NavMeshQuery(mesh);
QueryFilter filter = new DefaultQueryFilter();
FindNearestPolyResult[] polys = getNearestPolys(mesh, startPos, endPos);
return query.findPath(polys[0].getNearestRef(), polys[1].getNearestRef(), startPos, endPos, filter);
FindNearestPolyResult[] polys = GetNearestPolys(mesh, startPos, endPos);
return query.FindPath(polys[0].GetNearestRef(), polys[1].GetNearestRef(), startPos, endPos, filter);
}
private FindNearestPolyResult[] getNearestPolys(NavMesh mesh, params Vector3f[] positions)
private FindNearestPolyResult[] GetNearestPolys(NavMesh mesh, params Vector3f[] positions)
{
NavMeshQuery query = new NavMeshQuery(mesh);
QueryFilter filter = new DefaultQueryFilter();
@ -109,21 +109,21 @@ public class UnityAStarPathfindingImporterTest
for (int i = 0; i < results.Length; i++)
{
Vector3f position = positions[i];
Result<FindNearestPolyResult> result = query.findNearestPoly(position, extents, filter);
Result<FindNearestPolyResult> result = query.FindNearestPoly(position, extents, filter);
Assert.That(result.Succeeded(), Is.True);
Assert.That(result.result.getNearestPos(), Is.Not.EqualTo(Vector3f.Zero), "Nearest start position is null!");
Assert.That(result.result.GetNearestPos(), Is.Not.EqualTo(Vector3f.Zero), "Nearest start position is null!");
results[i] = result.result;
}
return results;
}
private void saveMesh(NavMesh mesh, string filePostfix)
private void SaveMesh(NavMesh mesh, string filePostfix)
{
// Set the flag to RecastDemo work properly
for (int i = 0; i < mesh.getTileCount(); i++)
for (int i = 0; i < mesh.GetTileCount(); i++)
{
foreach (Poly p in mesh.getTile(i).data.polys)
foreach (Poly p in mesh.GetTile(i).data.polys)
{
p.flags = 1;
}
@ -135,6 +135,6 @@ public class UnityAStarPathfindingImporterTest
string filepath = Path.Combine("test-output", filename);
using var fs = new FileStream(filename, FileMode.Create);
using var os = new BinaryWriter(fs);
writer.write(os, mesh, ByteOrder.LITTLE_ENDIAN, true);
writer.Write(os, mesh, ByteOrder.LITTLE_ENDIAN, true);
}
}

View File

@ -56,14 +56,14 @@ public abstract class AbstractDetourTest
protected NavMesh navmesh;
[SetUp]
public void setUp()
public void SetUp()
{
navmesh = createNavMesh();
navmesh = CreateNavMesh();
query = new NavMeshQuery(navmesh);
}
protected NavMesh createNavMesh()
protected NavMesh CreateNavMesh()
{
return new NavMesh(new RecastTestMeshBuilder().getMeshData(), 6, 0);
return new NavMesh(new RecastTestMeshBuilder().GetMeshData(), 6, 0);
}
}

View File

@ -24,21 +24,21 @@ namespace DotRecast.Detour.Test;
public class ConvexConvexIntersectionTest
{
[Test]
public void shouldHandleSamePolygonIntersection()
public void ShouldHandleSamePolygonIntersection()
{
float[] p = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
float[] q = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
float[] intersection = ConvexConvexIntersection.intersect(p, q);
float[] intersection = ConvexConvexIntersection.Intersect(p, q);
Assert.That(intersection.Length, Is.EqualTo(5 * 3));
Assert.That(intersection, Is.EqualTo(p));
}
[Test]
public void shouldHandleIntersection()
public void ShouldHandleIntersection()
{
float[] p = { -5, 0, -5, -5, 0, 4, 1, 0, 4, 1, 0, -5 };
float[] q = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
float[] intersection = ConvexConvexIntersection.intersect(p, q);
float[] intersection = ConvexConvexIntersection.Intersect(p, q);
Assert.That(intersection.Length, Is.EqualTo(5 * 3));
Assert.That(intersection, Is.EqualTo(new[] { 1, 0, 3, 1, 0, -3.4f, -2, 0, -4, -4, 0, 0, -3, 0, 3 }));
}

View File

@ -46,23 +46,23 @@ public class FindDistanceToWallTest : AbstractDetourTest
};
[Test]
public void testFindDistanceToWall()
public void TestFindDistanceToWall()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
{
Vector3f startPos = startPoss[i];
Result<FindDistanceToWallResult> result = query.findDistanceToWall(startRefs[i], startPos, 3.5f, filter);
Result<FindDistanceToWallResult> result = query.FindDistanceToWall(startRefs[i], startPos, 3.5f, filter);
FindDistanceToWallResult hit = result.result;
Assert.That(hit.getDistance(), Is.EqualTo(DISTANCES_TO_WALL[i]).Within(0.001f));
Assert.That(hit.GetDistance(), Is.EqualTo(DISTANCES_TO_WALL[i]).Within(0.001f));
Assert.That(hit.getPosition().x, Is.EqualTo(HIT_POSITION[i].x).Within(0.001f));
Assert.That(hit.getPosition().y, Is.EqualTo(HIT_POSITION[i].y).Within(0.001f));
Assert.That(hit.getPosition().z, Is.EqualTo(HIT_POSITION[i].z).Within(0.001f));
Assert.That(hit.GetPosition().x, Is.EqualTo(HIT_POSITION[i].x).Within(0.001f));
Assert.That(hit.GetPosition().y, Is.EqualTo(HIT_POSITION[i].y).Within(0.001f));
Assert.That(hit.GetPosition().z, Is.EqualTo(HIT_POSITION[i].z).Within(0.001f));
Assert.That(hit.getNormal().x, Is.EqualTo(HIT_NORMAL[i].x).Within(0.001f));
Assert.That(hit.getNormal().y, Is.EqualTo(HIT_NORMAL[i].y).Within(0.001f));
Assert.That(hit.getNormal().z, Is.EqualTo(HIT_NORMAL[i].z).Within(0.001f));
Assert.That(hit.GetNormal().x, Is.EqualTo(HIT_NORMAL[i].x).Within(0.001f));
Assert.That(hit.GetNormal().y, Is.EqualTo(HIT_NORMAL[i].y).Within(0.001f));
Assert.That(hit.GetNormal().z, Is.EqualTo(HIT_NORMAL[i].z).Within(0.001f));
}
}
}

View File

@ -52,17 +52,17 @@ public class FindLocalNeighbourhoodTest : AbstractDetourTest
};
[Test]
public void testFindNearestPoly()
public void TestFindNearestPoly()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
{
Vector3f startPos = startPoss[i];
Result<FindLocalNeighbourhoodResult> poly = query.findLocalNeighbourhood(startRefs[i], startPos, 3.5f, filter);
Assert.That(poly.result.getRefs().Count, Is.EqualTo(REFS[i].Length));
Result<FindLocalNeighbourhoodResult> poly = query.FindLocalNeighbourhood(startRefs[i], startPos, 3.5f, filter);
Assert.That(poly.result.GetRefs().Count, Is.EqualTo(REFS[i].Length));
for (int v = 0; v < REFS[i].Length; v++)
{
Assert.That(poly.result.getRefs()[v], Is.EqualTo(REFS[i][v]));
Assert.That(poly.result.GetRefs()[v], Is.EqualTo(REFS[i][v]));
}
}
}

View File

@ -35,31 +35,31 @@ public class FindNearestPolyTest : AbstractDetourTest
};
[Test]
public void testFindNearestPoly()
public void TestFindNearestPoly()
{
QueryFilter filter = new DefaultQueryFilter();
Vector3f extents = Vector3f.Of(2, 4, 2);
for (int i = 0; i < startRefs.Length; i++)
{
Vector3f startPos = startPoss[i];
Result<FindNearestPolyResult> poly = query.findNearestPoly(startPos, extents, filter);
Result<FindNearestPolyResult> poly = query.FindNearestPoly(startPos, extents, filter);
Assert.That(poly.Succeeded(), Is.True);
Assert.That(poly.result.getNearestRef(), Is.EqualTo(POLY_REFS[i]));
Assert.That(poly.result.GetNearestRef(), Is.EqualTo(POLY_REFS[i]));
for (int v = 0; v < POLY_POS[i].Length; v++)
{
Assert.That(poly.result.getNearestPos()[v], Is.EqualTo(POLY_POS[i][v]).Within(0.001f));
Assert.That(poly.result.GetNearestPos()[v], Is.EqualTo(POLY_POS[i][v]).Within(0.001f));
}
}
}
public class EmptyQueryFilter : QueryFilter
{
public bool passFilter(long refs, MeshTile tile, Poly poly)
public bool PassFilter(long refs, MeshTile tile, Poly poly)
{
return false;
}
public float getCost(Vector3f pa, Vector3f pb, long prevRef, MeshTile prevTile, Poly prevPoly, long curRef, MeshTile curTile,
public float GetCost(Vector3f pa, Vector3f pb, long prevRef, MeshTile prevTile, Poly prevPoly, long curRef, MeshTile curTile,
Poly curPoly, long nextRef, MeshTile nextTile, Poly nextPoly)
{
return 0;
@ -67,19 +67,19 @@ public class FindNearestPolyTest : AbstractDetourTest
}
[Test]
public void shouldReturnStartPosWhenNoPolyIsValid()
public void ShouldReturnStartPosWhenNoPolyIsValid()
{
var filter = new EmptyQueryFilter();
Vector3f extents = Vector3f.Of(2, 4, 2);
for (int i = 0; i < startRefs.Length; i++)
{
Vector3f startPos = startPoss[i];
Result<FindNearestPolyResult> poly = query.findNearestPoly(startPos, extents, filter);
Result<FindNearestPolyResult> poly = query.FindNearestPoly(startPos, extents, filter);
Assert.That(poly.Succeeded(), Is.True);
Assert.That(poly.result.getNearestRef(), Is.EqualTo(0L));
Assert.That(poly.result.GetNearestRef(), Is.EqualTo(0L));
for (int v = 0; v < POLY_POS[i].Length; v++)
{
Assert.That(poly.result.getNearestPos()[v], Is.EqualTo(startPos[v]).Within(0.001f));
Assert.That(poly.result.GetNearestPos()[v], Is.EqualTo(startPos[v]).Within(0.001f));
}
}
}

View File

@ -129,7 +129,7 @@ public class FindPathTest : AbstractDetourTest
};
[Test]
public void testFindPath()
public void TestFindPath()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
@ -138,7 +138,7 @@ public class FindPathTest : AbstractDetourTest
long endRef = endRefs[i];
Vector3f startPos = startPoss[i];
Vector3f endPos = endPoss[i];
Result<List<long>> path = query.findPath(startRef, endRef, startPos, endPos, filter);
Result<List<long>> path = query.FindPath(startRef, endRef, startPos, endPos, filter);
Assert.That(path.status, Is.EqualTo(STATUSES[i]));
Assert.That(path.result.Count, Is.EqualTo(RESULTS[i].Length));
for (int j = 0; j < RESULTS[i].Length; j++)
@ -149,7 +149,7 @@ public class FindPathTest : AbstractDetourTest
}
[Test]
public void testFindPathSliced()
public void TestFindPathSliced()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
@ -158,15 +158,15 @@ public class FindPathTest : AbstractDetourTest
long endRef = endRefs[i];
var startPos = startPoss[i];
var endPos = endPoss[i];
query.initSlicedFindPath(startRef, endRef, startPos, endPos, filter, NavMeshQuery.DT_FINDPATH_ANY_ANGLE);
query.InitSlicedFindPath(startRef, endRef, startPos, endPos, filter, NavMeshQuery.DT_FINDPATH_ANY_ANGLE);
Status status = Status.IN_PROGRESS;
while (status == Status.IN_PROGRESS)
{
Result<int> res = query.updateSlicedFindPath(10);
Result<int> res = query.UpdateSlicedFindPath(10);
status = res.status;
}
Result<List<long>> path = query.finalizeSlicedFindPath();
Result<List<long>> path = query.FinalizeSlicedFindPath();
Assert.That(path.status, Is.EqualTo(STATUSES[i]));
Assert.That(path.result.Count, Is.EqualTo(RESULTS[i].Length));
for (int j = 0; j < RESULTS[i].Length; j++)
@ -177,7 +177,7 @@ public class FindPathTest : AbstractDetourTest
}
[Test]
public void testFindPathStraight()
public void TestFindPathStraight()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < STRAIGHT_PATHS.Length; i++)
@ -187,8 +187,8 @@ public class FindPathTest : AbstractDetourTest
long endRef = endRefs[i];
var startPos = startPoss[i];
var endPos = endPoss[i];
Result<List<long>> path = query.findPath(startRef, endRef, startPos, endPos, filter);
Result<List<StraightPathItem>> result = query.findStraightPath(startPos, endPos, path.result,
Result<List<long>> path = query.FindPath(startRef, endRef, startPos, endPos, filter);
Result<List<StraightPathItem>> result = query.FindStraightPath(startPos, endPos, path.result,
int.MaxValue, 0);
List<StraightPathItem> straightPath = result.result;
Assert.That(straightPath.Count, Is.EqualTo(STRAIGHT_PATHS[i].Length));

View File

@ -99,26 +99,26 @@ public class FindPolysAroundCircleTest : AbstractDetourTest
};
[Test]
public void testFindPolysAroundCircle()
public void TestFindPolysAroundCircle()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
{
long startRef = startRefs[i];
Vector3f startPos = startPoss[i];
Result<FindPolysAroundResult> result = query.findPolysAroundCircle(startRef, startPos, 7.5f, filter);
Result<FindPolysAroundResult> result = query.FindPolysAroundCircle(startRef, startPos, 7.5f, filter);
Assert.That(result.Succeeded(), Is.True);
FindPolysAroundResult polys = result.result;
Assert.That(polys.getRefs().Count, Is.EqualTo(REFS[i].Length));
Assert.That(polys.GetRefs().Count, Is.EqualTo(REFS[i].Length));
for (int v = 0; v < REFS[i].Length; v++)
{
bool found = false;
for (int w = 0; w < REFS[i].Length; w++)
{
if (REFS[i][v] == polys.getRefs()[w])
if (REFS[i][v] == polys.GetRefs()[w])
{
Assert.That(polys.getParentRefs()[w], Is.EqualTo(PARENT_REFS[i][v]));
Assert.That(polys.getCosts()[w], Is.EqualTo(COSTS[i][v]).Within(0.01f));
Assert.That(polys.GetParentRefs()[w], Is.EqualTo(PARENT_REFS[i][v]));
Assert.That(polys.GetCosts()[w], Is.EqualTo(COSTS[i][v]).Within(0.01f));
found = true;
}
}

View File

@ -126,24 +126,24 @@ public class FindPolysAroundShapeTest : AbstractDetourTest
};
[Test]
public void testFindPolysAroundShape()
public void TestFindPolysAroundShape()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
{
long startRef = startRefs[i];
Vector3f startPos = startPoss[i];
Result<FindPolysAroundResult> polys = query.findPolysAroundShape(startRef, getQueryPoly(startPos, endPoss[i]), filter);
Assert.That(polys.result.getRefs().Count, Is.EqualTo(REFS[i].Length));
Result<FindPolysAroundResult> polys = query.FindPolysAroundShape(startRef, GetQueryPoly(startPos, endPoss[i]), filter);
Assert.That(polys.result.GetRefs().Count, Is.EqualTo(REFS[i].Length));
for (int v = 0; v < REFS[i].Length; v++)
{
bool found = false;
for (int w = 0; w < REFS[i].Length; w++)
{
if (REFS[i][v] == polys.result.getRefs()[w])
if (REFS[i][v] == polys.result.GetRefs()[w])
{
Assert.That(polys.result.getParentRefs()[w], Is.EqualTo(PARENT_REFS[i][v]));
Assert.That(polys.result.getCosts()[w], Is.EqualTo(COSTS[i][v]).Within(0.01f));
Assert.That(polys.result.GetParentRefs()[w], Is.EqualTo(PARENT_REFS[i][v]));
Assert.That(polys.result.GetCosts()[w], Is.EqualTo(COSTS[i][v]).Within(0.01f));
found = true;
}
}
@ -153,7 +153,7 @@ public class FindPolysAroundShapeTest : AbstractDetourTest
}
}
private float[] getQueryPoly(Vector3f m_spos, Vector3f m_epos)
private float[] GetQueryPoly(Vector3f m_spos, Vector3f m_epos)
{
float nx = (m_epos.z - m_spos.z) * 0.25f;
float nz = -(m_epos.x - m_spos.x) * 0.25f;

View File

@ -75,26 +75,26 @@ public class GetPolyWallSegmentsTest : AbstractDetourTest
};
[Test]
public void testFindDistanceToWall()
public void TestFindDistanceToWall()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
{
Result<GetPolyWallSegmentsResult> result = query.getPolyWallSegments(startRefs[i], true, filter);
Result<GetPolyWallSegmentsResult> result = query.GetPolyWallSegments(startRefs[i], true, filter);
GetPolyWallSegmentsResult segments = result.result;
Assert.That(segments.countSegmentVerts(), Is.EqualTo(VERTICES[i].Length / 6));
Assert.That(segments.countSegmentRefs(), Is.EqualTo(REFS[i].Length));
Assert.That(segments.CountSegmentVerts(), Is.EqualTo(VERTICES[i].Length / 6));
Assert.That(segments.CountSegmentRefs(), Is.EqualTo(REFS[i].Length));
for (int v = 0; v < VERTICES[i].Length / 6; v++)
{
for (int n = 0; n < 6; n++)
{
Assert.That(segments.getSegmentVert(v)[n], Is.EqualTo(VERTICES[i][v * 6 + n]).Within(0.001f));
Assert.That(segments.GetSegmentVert(v)[n], Is.EqualTo(VERTICES[i][v * 6 + n]).Within(0.001f));
}
}
for (int v = 0; v < REFS[i].Length; v++)
{
Assert.That(segments.getSegmentRef(v), Is.EqualTo(REFS[i][v]));
Assert.That(segments.GetSegmentRef(v), Is.EqualTo(REFS[i][v]));
}
}
}

View File

@ -30,48 +30,48 @@ public class MeshDataReaderWriterTest
private MeshData meshData;
[SetUp]
public void setUp()
public void SetUp()
{
RecastTestMeshBuilder rcBuilder = new RecastTestMeshBuilder();
meshData = rcBuilder.getMeshData();
meshData = rcBuilder.GetMeshData();
}
[Test]
public void testCCompatibility()
public void TestCCompatibility()
{
test(true, ByteOrder.BIG_ENDIAN);
Test(true, ByteOrder.BIG_ENDIAN);
}
[Test]
public void testCompact()
public void TestCompact()
{
test(false, ByteOrder.BIG_ENDIAN);
Test(false, ByteOrder.BIG_ENDIAN);
}
[Test]
public void testCCompatibilityLE()
public void TestCCompatibilityLE()
{
test(true, ByteOrder.LITTLE_ENDIAN);
Test(true, ByteOrder.LITTLE_ENDIAN);
}
[Test]
public void testCompactLE()
public void TestCompactLE()
{
test(false, ByteOrder.LITTLE_ENDIAN);
Test(false, ByteOrder.LITTLE_ENDIAN);
}
public void test(bool cCompatibility, ByteOrder order)
public void Test(bool cCompatibility, ByteOrder order)
{
using var ms = new MemoryStream();
using var bwos = new BinaryWriter(ms);
MeshDataWriter writer = new MeshDataWriter();
writer.write(bwos, meshData, order, cCompatibility);
writer.Write(bwos, meshData, order, cCompatibility);
ms.Seek(0, SeekOrigin.Begin);
using var bris = new BinaryReader(ms);
MeshDataReader reader = new MeshDataReader();
MeshData readData = reader.read(bris, VERTS_PER_POLYGON);
MeshData readData = reader.Read(bris, VERTS_PER_POLYGON);
Assert.That(readData.header.vertCount, Is.EqualTo(meshData.header.vertCount));
Assert.That(readData.header.polyCount, Is.EqualTo(meshData.header.polyCount));

View File

@ -30,86 +30,86 @@ public class MeshSetReaderTest
private readonly MeshSetReader reader = new MeshSetReader();
[Test]
public void testNavmesh()
public void TestNavmesh()
{
byte[] @is = Loader.ToBytes("all_tiles_navmesh.bin");
using var ms = new MemoryStream(@is);
using var bris = new BinaryReader(ms);
NavMesh mesh = reader.read(bris, 6);
Assert.That(mesh.getMaxTiles(), Is.EqualTo(128));
Assert.That(mesh.getParams().maxPolys, Is.EqualTo(0x8000));
Assert.That(mesh.getParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
List<MeshTile> tiles = mesh.getTilesAt(4, 7);
NavMesh mesh = reader.Read(bris, 6);
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
List<MeshTile> tiles = mesh.GetTilesAt(4, 7);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(7));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(22 * 3));
tiles = mesh.getTilesAt(1, 6);
tiles = mesh.GetTilesAt(1, 6);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(7));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(26 * 3));
tiles = mesh.getTilesAt(6, 2);
tiles = mesh.GetTilesAt(6, 2);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(1));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(4 * 3));
tiles = mesh.getTilesAt(7, 6);
tiles = mesh.GetTilesAt(7, 6);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(8));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(24 * 3));
}
[Test]
public void testDungeon()
public void TestDungeon()
{
byte[] @is = Loader.ToBytes("dungeon_all_tiles_navmesh.bin");
using var ms = new MemoryStream(@is);
using var bris = new BinaryReader(ms);
NavMesh mesh = reader.read(bris, 6);
Assert.That(mesh.getMaxTiles(), Is.EqualTo(128));
Assert.That(mesh.getParams().maxPolys, Is.EqualTo(0x8000));
Assert.That(mesh.getParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
List<MeshTile> tiles = mesh.getTilesAt(6, 9);
NavMesh mesh = reader.Read(bris, 6);
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
List<MeshTile> tiles = mesh.GetTilesAt(6, 9);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
tiles = mesh.getTilesAt(2, 9);
tiles = mesh.GetTilesAt(2, 9);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
tiles = mesh.getTilesAt(4, 3);
tiles = mesh.GetTilesAt(4, 3);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
tiles = mesh.getTilesAt(2, 8);
tiles = mesh.GetTilesAt(2, 8);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));
}
[Test]
public void testDungeon32Bit()
public void TestDungeon32Bit()
{
byte[] @is = Loader.ToBytes("dungeon_all_tiles_navmesh_32bit.bin");
using var ms = new MemoryStream(@is);
using var bris = new BinaryReader(ms);
NavMesh mesh = reader.read32Bit(bris, 6);
Assert.That(mesh.getMaxTiles(), Is.EqualTo(128));
Assert.That(mesh.getParams().maxPolys, Is.EqualTo(0x8000));
Assert.That(mesh.getParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
List<MeshTile> tiles = mesh.getTilesAt(6, 9);
NavMesh mesh = reader.Read32Bit(bris, 6);
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
List<MeshTile> tiles = mesh.GetTilesAt(6, 9);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
tiles = mesh.getTilesAt(2, 9);
tiles = mesh.GetTilesAt(2, 9);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
tiles = mesh.getTilesAt(4, 3);
tiles = mesh.GetTilesAt(4, 3);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
tiles = mesh.getTilesAt(2, 8);
tiles = mesh.GetTilesAt(2, 8);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));

View File

@ -52,14 +52,14 @@ public class MeshSetReaderWriterTest
private const int m_maxPolysPerTile = 0x8000;
[Test]
public void test()
public void Test()
{
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("dungeon.obj"));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("dungeon.obj"));
NavMeshSetHeader header = new NavMeshSetHeader();
header.magic = NavMeshSetHeader.NAVMESHSET_MAGIC;
header.version = NavMeshSetHeader.NAVMESHSET_VERSION;
header.option.orig = geom.getMeshBoundsMin();
header.option.orig = geom.GetMeshBoundsMin();
header.option.tileWidth = m_tileSize * m_cellSize;
header.option.tileHeight = m_tileSize * m_cellSize;
header.option.maxTiles = m_maxTiles;
@ -67,9 +67,9 @@ public class MeshSetReaderWriterTest
header.numTiles = 0;
NavMesh mesh = new NavMesh(header.option, 6);
Vector3f bmin = geom.getMeshBoundsMin();
Vector3f bmax = geom.getMeshBoundsMax();
int[] twh = DotRecast.Recast.Recast.calcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize);
Vector3f bmin = geom.GetMeshBoundsMin();
Vector3f bmax = geom.GetMeshBoundsMax();
int[] twh = DotRecast.Recast.Recast.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize);
int tw = twh[0];
int th = twh[1];
for (int y = 0; y < th; ++y)
@ -77,44 +77,44 @@ public class MeshSetReaderWriterTest
for (int x = 0; x < tw; ++x)
{
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize,
RecastConfig.calcBorder(m_agentRadius, m_cellSize), PartitionType.WATERSHED, m_cellSize, m_cellHeight,
RecastConfig.CalcBorder(m_agentRadius, m_cellSize), PartitionType.WATERSHED, m_cellSize, m_cellHeight,
m_agentMaxSlope, true, true, true, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_regionMinArea,
m_regionMergeArea, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, true, m_detailSampleDist,
m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_GROUND);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, bmin, bmax, x, y);
TestDetourBuilder db = new TestDetourBuilder();
MeshData data = db.build(geom, bcfg, m_agentHeight, m_agentRadius, m_agentMaxClimb, x, y, true);
MeshData data = db.Build(geom, bcfg, m_agentHeight, m_agentRadius, m_agentMaxClimb, x, y, true);
if (data != null)
{
mesh.removeTile(mesh.getTileRefAt(x, y, 0));
mesh.addTile(data, 0, 0);
mesh.RemoveTile(mesh.GetTileRefAt(x, y, 0));
mesh.AddTile(data, 0, 0);
}
}
}
using var ms = new MemoryStream();
using var os = new BinaryWriter(ms);
writer.write(os, mesh, ByteOrder.LITTLE_ENDIAN, true);
writer.Write(os, mesh, ByteOrder.LITTLE_ENDIAN, true);
ms.Seek(0, SeekOrigin.Begin);
using var @is = new BinaryReader(ms);
mesh = reader.read(@is, 6);
Assert.That(mesh.getMaxTiles(), Is.EqualTo(128));
Assert.That(mesh.getParams().maxPolys, Is.EqualTo(0x8000));
Assert.That(mesh.getParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
List<MeshTile> tiles = mesh.getTilesAt(6, 9);
mesh = reader.Read(@is, 6);
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
List<MeshTile> tiles = mesh.GetTilesAt(6, 9);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
tiles = mesh.getTilesAt(2, 9);
tiles = mesh.GetTilesAt(2, 9);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
tiles = mesh.getTilesAt(4, 3);
tiles = mesh.GetTilesAt(4, 3);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
tiles = mesh.getTilesAt(2, 8);
tiles = mesh.GetTilesAt(2, 8);
Assert.That(tiles.Count, Is.EqualTo(1));
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));

View File

@ -66,7 +66,7 @@ public class MoveAlongSurfaceTest : AbstractDetourTest
};
[Test]
public void testMoveAlongSurface()
public void TestMoveAlongSurface()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
@ -74,18 +74,18 @@ public class MoveAlongSurfaceTest : AbstractDetourTest
long startRef = startRefs[i];
Vector3f startPos = startPoss[i];
Vector3f endPos = endPoss[i];
Result<MoveAlongSurfaceResult> result = query.moveAlongSurface(startRef, startPos, endPos, filter);
Result<MoveAlongSurfaceResult> result = query.MoveAlongSurface(startRef, startPos, endPos, filter);
Assert.That(result.Succeeded(), Is.True);
MoveAlongSurfaceResult path = result.result;
for (int v = 0; v < 3; v++)
{
Assert.That(path.getResultPos()[v], Is.EqualTo(POSITION[i][v]).Within(0.01f));
Assert.That(path.GetResultPos()[v], Is.EqualTo(POSITION[i][v]).Within(0.01f));
}
Assert.That(path.getVisited().Count, Is.EqualTo(VISITED[i].Length));
Assert.That(path.GetVisited().Count, Is.EqualTo(VISITED[i].Length));
for (int j = 0; j < POSITION[i].Length; j++)
{
Assert.That(path.getVisited()[j], Is.EqualTo(VISITED[i][j]));
Assert.That(path.GetVisited()[j], Is.EqualTo(VISITED[i][j]));
}
}
}

View File

@ -26,13 +26,13 @@ public class NavMeshBuilderTest
private MeshData nmd;
[SetUp]
public void setUp()
public void SetUp()
{
nmd = new RecastTestMeshBuilder().getMeshData();
nmd = new RecastTestMeshBuilder().GetMeshData();
}
[Test]
public void testBVTree()
public void TestBVTree()
{
Assert.That(nmd.verts.Length / 3, Is.EqualTo(225));
Assert.That(nmd.polys.Length, Is.EqualTo(119));
@ -63,7 +63,7 @@ public class NavMeshBuilderTest
Assert.That(nmd.polys[118].verts[0], Is.EqualTo(223));
Assert.That(nmd.polys[118].verts[1], Is.EqualTo(224));
Assert.That(nmd.polys[118].flags, Is.EqualTo(12));
Assert.That(nmd.polys[118].getArea(), Is.EqualTo(2));
Assert.That(nmd.polys[118].getType(), Is.EqualTo(Poly.DT_POLYTYPE_OFFMESH_CONNECTION));
Assert.That(nmd.polys[118].GetArea(), Is.EqualTo(2));
Assert.That(nmd.polys[118].GetType(), Is.EqualTo(Poly.DT_POLYTYPE_OFFMESH_CONNECTION));
}
}

View File

@ -27,34 +27,34 @@ public class PolygonByCircleConstraintTest
private readonly PolygonByCircleConstraint constraint = new PolygonByCircleConstraint.StrictPolygonByCircleConstraint();
[Test]
public void shouldHandlePolygonFullyInsideCircle()
public void ShouldHandlePolygonFullyInsideCircle()
{
float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 };
Vector3f center = Vector3f.Of(1, 0, 1);
float[] constrained = constraint.aply(polygon, center, 6);
float[] constrained = constraint.Aply(polygon, center, 6);
Assert.That(constrained, Is.EqualTo(polygon));
}
[Test]
public void shouldHandleVerticalSegment()
public void ShouldHandleVerticalSegment()
{
int expectedSize = 21;
float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 };
Vector3f center = Vector3f.Of(2, 0, 0);
float[] constrained = constraint.aply(polygon, center, 3);
float[] constrained = constraint.Aply(polygon, center, 3);
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
Assert.That(constrained, Is.SupersetOf(new[] { 2f, 0f, 2f, 2f, 0f, -2f }));
}
[Test]
public void shouldHandleCircleFullyInsidePolygon()
public void ShouldHandleCircleFullyInsidePolygon()
{
int expectedSize = 12 * 3;
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
Vector3f center = Vector3f.Of(-1, 0, -1);
float[] constrained = constraint.aply(polygon, center, 2);
float[] constrained = constraint.Aply(polygon, center, 2);
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
@ -67,24 +67,24 @@ public class PolygonByCircleConstraintTest
}
[Test]
public void shouldHandleCircleInsidePolygon()
public void ShouldHandleCircleInsidePolygon()
{
int expectedSize = 9 * 3;
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
Vector3f center = Vector3f.Of(-2, 0, -1);
float[] constrained = constraint.aply(polygon, center, 3);
float[] constrained = constraint.Aply(polygon, center, 3);
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
Assert.That(constrained, Is.SupersetOf(new[] { -2f, 0f, -4f, -4f, 0f, 0f, -3.4641016f, 0.0f, 1.6076951f, -2.0f, 0.0f, 2.0f }));
}
[Test]
public void shouldHandleCircleOutsidePolygon()
public void ShouldHandleCircleOutsidePolygon()
{
int expectedSize = 7 * 3;
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
Vector3f center = Vector3f.Of(4, 0, 0);
float[] constrained = constraint.aply(polygon, center, 4);
float[] constrained = constraint.Aply(polygon, center, 4);
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
Assert.That(constrained, Is.SupersetOf(new[] { 1.5358982f, 0f, 3f, 2f, 0f, 3f, 3f, 0f, -3f }));

View File

@ -29,15 +29,15 @@ namespace DotRecast.Detour.Test;
public class RandomPointTest : AbstractDetourTest
{
[Test]
public void testRandom()
public void TestRandom()
{
FRand f = new FRand(1);
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < 1000; i++)
{
Result<FindRandomPointResult> point = query.findRandomPoint(filter, f);
Result<FindRandomPointResult> point = query.FindRandomPoint(filter, f);
Assert.That(point.Succeeded(), Is.True);
Tuple<MeshTile, Poly> tileAndPoly = navmesh.getTileAndPolyByRef(point.result.getRandomRef()).result;
Tuple<MeshTile, Poly> tileAndPoly = navmesh.GetTileAndPolyByRef(point.result.GetRandomRef()).result;
float[] bmin = new float[2];
float[] bmax = new float[2];
for (int j = 0; j < tileAndPoly.Item2.vertCount; j++)
@ -49,26 +49,26 @@ public class RandomPointTest : AbstractDetourTest
bmax[1] = j == 0 ? tileAndPoly.Item1.data.verts[v + 2] : Math.Max(bmax[1], tileAndPoly.Item1.data.verts[v + 2]);
}
Assert.That(point.result.getRandomPt().x >= bmin[0], Is.True);
Assert.That(point.result.getRandomPt().x <= bmax[0], Is.True);
Assert.That(point.result.getRandomPt().z >= bmin[1], Is.True);
Assert.That(point.result.getRandomPt().z <= bmax[1], Is.True);
Assert.That(point.result.GetRandomPt().x >= bmin[0], Is.True);
Assert.That(point.result.GetRandomPt().x <= bmax[0], Is.True);
Assert.That(point.result.GetRandomPt().z >= bmin[1], Is.True);
Assert.That(point.result.GetRandomPt().z <= bmax[1], Is.True);
}
}
[Test]
public void testRandomAroundCircle()
public void TestRandomAroundCircle()
{
FRand f = new FRand(1);
QueryFilter filter = new DefaultQueryFilter();
FindRandomPointResult point = query.findRandomPoint(filter, f).result;
FindRandomPointResult point = query.FindRandomPoint(filter, f).result;
for (int i = 0; i < 1000; i++)
{
Result<FindRandomPointResult> result = query.findRandomPointAroundCircle(point.getRandomRef(), point.getRandomPt(),
Result<FindRandomPointResult> result = query.FindRandomPointAroundCircle(point.GetRandomRef(), point.GetRandomPt(),
5f, filter, f);
Assert.That(result.Failed(), Is.False);
point = result.result;
Tuple<MeshTile, Poly> tileAndPoly = navmesh.getTileAndPolyByRef(point.getRandomRef()).result;
Tuple<MeshTile, Poly> tileAndPoly = navmesh.GetTileAndPolyByRef(point.GetRandomRef()).result;
float[] bmin = new float[2];
float[] bmax = new float[2];
for (int j = 0; j < tileAndPoly.Item2.vertCount; j++)
@ -80,59 +80,59 @@ public class RandomPointTest : AbstractDetourTest
bmax[1] = j == 0 ? tileAndPoly.Item1.data.verts[v + 2] : Math.Max(bmax[1], tileAndPoly.Item1.data.verts[v + 2]);
}
Assert.That(point.getRandomPt().x >= bmin[0], Is.True);
Assert.That(point.getRandomPt().x <= bmax[0], Is.True);
Assert.That(point.getRandomPt().z >= bmin[1], Is.True);
Assert.That(point.getRandomPt().z <= bmax[1], Is.True);
Assert.That(point.GetRandomPt().x >= bmin[0], Is.True);
Assert.That(point.GetRandomPt().x <= bmax[0], Is.True);
Assert.That(point.GetRandomPt().z >= bmin[1], Is.True);
Assert.That(point.GetRandomPt().z <= bmax[1], Is.True);
}
}
[Test]
public void testRandomWithinCircle()
public void TestRandomWithinCircle()
{
FRand f = new FRand(1);
QueryFilter filter = new DefaultQueryFilter();
FindRandomPointResult point = query.findRandomPoint(filter, f).result;
FindRandomPointResult point = query.FindRandomPoint(filter, f).result;
float radius = 5f;
for (int i = 0; i < 1000; i++)
{
Result<FindRandomPointResult> result = query.findRandomPointWithinCircle(point.getRandomRef(), point.getRandomPt(),
Result<FindRandomPointResult> result = query.FindRandomPointWithinCircle(point.GetRandomRef(), point.GetRandomPt(),
radius, filter, f);
Assert.That(result.Failed(), Is.False);
float distance = vDist2D(point.getRandomPt(), result.result.getRandomPt());
float distance = VDist2D(point.GetRandomPt(), result.result.GetRandomPt());
Assert.That(distance <= radius, Is.True);
point = result.result;
}
}
[Test]
public void testPerformance()
public void TestPerformance()
{
FRand f = new FRand(1);
QueryFilter filter = new DefaultQueryFilter();
FindRandomPointResult point = query.findRandomPoint(filter, f).result;
FindRandomPointResult point = query.FindRandomPoint(filter, f).result;
float radius = 5f;
// jvm warmup
for (int i = 0; i < 1000; i++)
{
query.findRandomPointAroundCircle(point.getRandomRef(), point.getRandomPt(), radius, filter, f);
query.FindRandomPointAroundCircle(point.GetRandomRef(), point.GetRandomPt(), radius, filter, f);
}
for (int i = 0; i < 1000; i++)
{
query.findRandomPointWithinCircle(point.getRandomRef(), point.getRandomPt(), radius, filter, f);
query.FindRandomPointWithinCircle(point.GetRandomRef(), point.GetRandomPt(), radius, filter, f);
}
long t1 = FrequencyWatch.Ticks;
for (int i = 0; i < 10000; i++)
{
query.findRandomPointAroundCircle(point.getRandomRef(), point.getRandomPt(), radius, filter, f);
query.FindRandomPointAroundCircle(point.GetRandomRef(), point.GetRandomPt(), radius, filter, f);
}
long t2 = FrequencyWatch.Ticks;
for (int i = 0; i < 10000; i++)
{
query.findRandomPointWithinCircle(point.getRandomRef(), point.getRandomPt(), radius, filter, f);
query.FindRandomPointWithinCircle(point.GetRandomRef(), point.GetRandomPt(), radius, filter, f);
}
long t3 = FrequencyWatch.Ticks;

View File

@ -40,7 +40,7 @@ public class RecastTestMeshBuilder
private const float m_detailSampleMaxError = 1.0f;
public RecastTestMeshBuilder() :
this(ObjImporter.load(Loader.ToBytes("dungeon.obj")),
this(ObjImporter.Load(Loader.ToBytes("dungeon.obj")),
PartitionType.WATERSHED, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_agentMaxSlope,
m_regionMinSize, m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, m_detailSampleDist,
m_detailSampleMaxError)
@ -55,16 +55,16 @@ public class RecastTestMeshBuilder
RecastConfig cfg = new RecastConfig(m_partitionType, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius,
m_agentMaxClimb, m_agentMaxSlope, m_regionMinSize, m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError,
m_vertsPerPoly, m_detailSampleDist, m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_GROUND);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, m_geom.getMeshBoundsMin(), m_geom.getMeshBoundsMax());
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, m_geom.GetMeshBoundsMin(), m_geom.GetMeshBoundsMax());
RecastBuilder rcBuilder = new RecastBuilder();
RecastBuilderResult rcResult = rcBuilder.build(m_geom, bcfg);
PolyMesh m_pmesh = rcResult.getMesh();
RecastBuilderResult rcResult = rcBuilder.Build(m_geom, bcfg);
PolyMesh m_pmesh = rcResult.GetMesh();
for (int i = 0; i < m_pmesh.npolys; ++i)
{
m_pmesh.flags[i] = 1;
}
PolyMeshDetail m_dmesh = rcResult.getMeshDetail();
PolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
option.verts = m_pmesh.verts;
option.vertCount = m_pmesh.nverts;
@ -105,10 +105,10 @@ public class RecastTestMeshBuilder
option.offMeshConUserID = new int[1];
option.offMeshConUserID[0] = 0x4567;
option.offMeshConCount = 1;
meshData = NavMeshBuilder.createNavMeshData(option);
meshData = NavMeshBuilder.CreateNavMeshData(option);
}
public MeshData getMeshData()
public MeshData GetMeshData()
{
return meshData;
}

View File

@ -23,12 +23,12 @@ namespace DotRecast.Detour.Test;
public class TestDetourBuilder : DetourBuilder
{
public MeshData build(InputGeomProvider geom, RecastBuilderConfig rcConfig, float agentHeight, float agentRadius,
public MeshData Build(InputGeomProvider geom, RecastBuilderConfig rcConfig, float agentHeight, float agentRadius,
float agentMaxClimb, int x, int y, bool applyRecastDemoFlags)
{
RecastBuilder rcBuilder = new RecastBuilder();
RecastBuilderResult rcResult = rcBuilder.build(geom, rcConfig);
PolyMesh pmesh = rcResult.getMesh();
RecastBuilderResult rcResult = rcBuilder.Build(geom, rcConfig);
PolyMesh pmesh = rcResult.GetMesh();
if (applyRecastDemoFlags)
{
@ -58,13 +58,13 @@ public class TestDetourBuilder : DetourBuilder
}
}
PolyMeshDetail dmesh = rcResult.getMeshDetail();
NavMeshDataCreateParams option = getNavMeshCreateParams(rcConfig.cfg, pmesh, dmesh, agentHeight, agentRadius,
PolyMeshDetail dmesh = rcResult.GetMeshDetail();
NavMeshDataCreateParams option = GetNavMeshCreateParams(rcConfig.cfg, pmesh, dmesh, agentHeight, agentRadius,
agentMaxClimb);
return build(option, x, y);
return Build(option, x, y);
}
public NavMeshDataCreateParams getNavMeshCreateParams(RecastConfig rcConfig, PolyMesh pmesh, PolyMeshDetail dmesh,
public NavMeshDataCreateParams GetNavMeshCreateParams(RecastConfig rcConfig, PolyMesh pmesh, PolyMeshDetail dmesh,
float agentHeight, float agentRadius, float agentMaxClimb)
{
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
@ -93,11 +93,11 @@ public class TestDetourBuilder : DetourBuilder
option.ch = rcConfig.ch;
option.buildBvTree = true;
/*
* option.offMeshConVerts = m_geom->getOffMeshConnectionVerts(); option.offMeshConRad =
* m_geom->getOffMeshConnectionRads(); option.offMeshConDir = m_geom->getOffMeshConnectionDirs();
* option.offMeshConAreas = m_geom->getOffMeshConnectionAreas(); option.offMeshConFlags =
* m_geom->getOffMeshConnectionFlags(); option.offMeshConUserID = m_geom->getOffMeshConnectionId();
* option.offMeshConCount = m_geom->getOffMeshConnectionCount();
* option.offMeshConVerts = m_geom->GetOffMeshConnectionVerts(); option.offMeshConRad =
* m_geom->GetOffMeshConnectionRads(); option.offMeshConDir = m_geom->GetOffMeshConnectionDirs();
* option.offMeshConAreas = m_geom->GetOffMeshConnectionAreas(); option.offMeshConFlags =
* m_geom->GetOffMeshConnectionFlags(); option.offMeshConUserID = m_geom->GetOffMeshConnectionId();
* option.offMeshConCount = m_geom->GetOffMeshConnectionCount();
*/
return option;
}

View File

@ -45,7 +45,7 @@ public class TestTiledNavMeshBuilder
private const int m_tileSize = 32;
public TestTiledNavMeshBuilder() :
this(ObjImporter.load(Loader.ToBytes("dungeon.obj")),
this(ObjImporter.Load(Loader.ToBytes("dungeon.obj")),
PartitionType.WATERSHED, m_cellSize, m_cellHeight, m_agentHeight, m_agentRadius, m_agentMaxClimb, m_agentMaxSlope,
m_regionMinSize, m_regionMergeSize, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, m_detailSampleDist,
m_detailSampleMaxError, m_tileSize)
@ -59,7 +59,7 @@ public class TestTiledNavMeshBuilder
{
// Create empty nav mesh
NavMeshParams navMeshParams = new NavMeshParams();
navMeshParams.orig = m_geom.getMeshBoundsMin();
navMeshParams.orig = m_geom.GetMeshBoundsMin();
navMeshParams.tileWidth = m_tileSize * m_cellSize;
navMeshParams.tileHeight = m_tileSize * m_cellSize;
navMeshParams.maxTiles = 128;
@ -67,18 +67,18 @@ public class TestTiledNavMeshBuilder
navMesh = new NavMesh(navMeshParams, 6);
// Build all tiles
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.calcBorder(m_agentRadius, m_cellSize),
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.CalcBorder(m_agentRadius, m_cellSize),
m_partitionType, m_cellSize, m_cellHeight, m_agentMaxSlope, true, true, true, m_agentHeight, m_agentRadius,
m_agentMaxClimb, m_regionMinArea, m_regionMergeArea, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, true,
m_detailSampleDist, m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_GROUND);
RecastBuilder rcBuilder = new RecastBuilder();
List<RecastBuilderResult> rcResult = rcBuilder.buildTiles(m_geom, cfg, null);
List<RecastBuilderResult> rcResult = rcBuilder.BuildTiles(m_geom, cfg, null);
// Add tiles to nav mesh
foreach (RecastBuilderResult result in rcResult)
{
PolyMesh pmesh = result.getMesh();
PolyMesh pmesh = result.GetMesh();
if (pmesh.npolys == 0)
{
continue;
@ -97,7 +97,7 @@ public class TestTiledNavMeshBuilder
option.polyFlags = pmesh.flags;
option.polyCount = pmesh.npolys;
option.nvp = pmesh.nvp;
PolyMeshDetail dmesh = result.getMeshDetail();
PolyMeshDetail dmesh = result.GetMeshDetail();
option.detailMeshes = dmesh.meshes;
option.detailVerts = dmesh.verts;
option.detailVertsCount = dmesh.nverts;
@ -113,11 +113,11 @@ public class TestTiledNavMeshBuilder
option.tileX = result.tileX;
option.tileZ = result.tileZ;
option.buildBvTree = true;
navMesh.addTile(NavMeshBuilder.createNavMeshData(option), 0, 0);
navMesh.AddTile(NavMeshBuilder.CreateNavMeshData(option), 0, 0);
}
}
public NavMesh getNavMesh()
public NavMesh GetNavMesh()
{
return navMesh;
}

View File

@ -50,19 +50,19 @@ public class TiledFindPathTest
protected NavMesh navmesh;
[SetUp]
public void setUp()
public void SetUp()
{
navmesh = createNavMesh();
navmesh = CreateNavMesh();
query = new NavMeshQuery(navmesh);
}
protected NavMesh createNavMesh()
protected NavMesh CreateNavMesh()
{
return new TestTiledNavMeshBuilder().getNavMesh();
return new TestTiledNavMeshBuilder().GetNavMesh();
}
[Test]
public void testFindPath()
public void TestFindPath()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < START_REFS.Length; i++)
@ -71,7 +71,7 @@ public class TiledFindPathTest
long endRef = END_REFS[i];
Vector3f startPos = START_POS[i];
Vector3f endPos = END_POS[i];
Result<List<long>> path = query.findPath(startRef, endRef, startPos, endPos, filter);
Result<List<long>> path = query.FindPath(startRef, endRef, startPos, endPos, filter);
Assert.That(path.status, Is.EqualTo(STATUSES[i]));
Assert.That(path.result.Count, Is.EqualTo(RESULTS[i].Length));
for (int j = 0; j < RESULTS[i].Length; j++)

View File

@ -41,7 +41,7 @@ public class AbstractTileCacheTest
protected class TestTileCacheMeshProcess : TileCacheMeshProcess
{
public void process(NavMeshDataCreateParams option)
public void Process(NavMeshDataCreateParams option)
{
for (int i = 0; i < option.polyCount; ++i)
{
@ -50,13 +50,13 @@ public class AbstractTileCacheTest
}
}
public TileCache getTileCache(InputGeomProvider geom, ByteOrder order, bool cCompatibility)
public TileCache GetTileCache(InputGeomProvider geom, ByteOrder order, bool cCompatibility)
{
TileCacheParams option = new TileCacheParams();
int[] twh = Recast.Recast.calcTileCount(geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize);
int[] twh = Recast.Recast.CalcTileCount(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize);
option.ch = m_cellHeight;
option.cs = m_cellSize;
option.orig = geom.getMeshBoundsMin();
option.orig = geom.GetMeshBoundsMin();
option.height = m_tileSize;
option.width = m_tileSize;
option.walkableHeight = m_agentHeight;
@ -66,14 +66,14 @@ public class AbstractTileCacheTest
option.maxTiles = twh[0] * twh[1] * EXPECTED_LAYERS_PER_TILE;
option.maxObstacles = 128;
NavMeshParams navMeshParams = new NavMeshParams();
navMeshParams.orig = geom.getMeshBoundsMin();
navMeshParams.orig = geom.GetMeshBoundsMin();
navMeshParams.tileWidth = m_tileSize * m_cellSize;
navMeshParams.tileHeight = m_tileSize * m_cellSize;
navMeshParams.maxTiles = 256;
navMeshParams.maxPolys = 16384;
NavMesh navMesh = new NavMesh(navMeshParams, 6);
TileCache tc = new TileCache(option, new TileCacheStorageParams(order, cCompatibility), navMesh,
TileCacheCompressorFactory.get(cCompatibility), new TestTileCacheMeshProcess());
TileCacheCompressorFactory.Get(cCompatibility), new TestTileCacheMeshProcess());
return tc;
}
}

View File

@ -32,28 +32,28 @@ public class TileCacheReaderTest
private readonly TileCacheReader reader = new TileCacheReader();
[Test]
public void testNavmesh()
public void TestNavmesh()
{
using var ms = new MemoryStream(Loader.ToBytes("all_tiles_tilecache.bin"));
using var @is = new BinaryReader(ms);
TileCache tc = reader.read(@is, 6, null);
Assert.That(tc.getNavMesh().getMaxTiles(), Is.EqualTo(256));
Assert.That(tc.getNavMesh().getParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.getNavMesh().getParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.getParams().cs, Is.EqualTo(0.3f).Within(0.0f));
Assert.That(tc.getParams().ch, Is.EqualTo(0.2f).Within(0.0f));
Assert.That(tc.getParams().walkableClimb, Is.EqualTo(0.9f).Within(0.0f));
Assert.That(tc.getParams().walkableHeight, Is.EqualTo(2f).Within(0.0f));
Assert.That(tc.getParams().walkableRadius, Is.EqualTo(0.6f).Within(0.0f));
Assert.That(tc.getParams().width, Is.EqualTo(48));
Assert.That(tc.getParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.getParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.getTileCount(), Is.EqualTo(168));
TileCache tc = reader.Read(@is, 6, null);
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
Assert.That(tc.GetNavMesh().GetParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.GetNavMesh().GetParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.GetParams().cs, Is.EqualTo(0.3f).Within(0.0f));
Assert.That(tc.GetParams().ch, Is.EqualTo(0.2f).Within(0.0f));
Assert.That(tc.GetParams().walkableClimb, Is.EqualTo(0.9f).Within(0.0f));
Assert.That(tc.GetParams().walkableHeight, Is.EqualTo(2f).Within(0.0f));
Assert.That(tc.GetParams().walkableRadius, Is.EqualTo(0.6f).Within(0.0f));
Assert.That(tc.GetParams().width, Is.EqualTo(48));
Assert.That(tc.GetParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.GetParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.GetTileCount(), Is.EqualTo(168));
// Tile0: Tris: 1, Verts: 4 Detail Meshed: 1 Detail Verts: 0 Detail Tris: 2
// Verts: -2.269517, 28.710686, 28.710686
MeshTile tile = tc.getNavMesh().getTile(0);
MeshTile tile = tc.GetNavMesh().GetTile(0);
MeshData data = tile.data;
MeshHeader header = data.header;
Assert.That(header.vertCount, Is.EqualTo(4));
@ -71,7 +71,7 @@ public class TileCacheReaderTest
Assert.That(data.verts[9], Is.EqualTo(28.710686f).Within(0.0001f));
// Tile8: Tris: 7, Verts: 10 Detail Meshed: 7 Detail Verts: 0 Detail Tris: 10
// Verts: 0.330483, 43.110687, 43.110687
tile = tc.getNavMesh().getTile(8);
tile = tc.GetNavMesh().GetTile(8);
data = tile.data;
header = data.header;
Console.WriteLine(data.header.x + " " + data.header.y + " " + data.header.layer);
@ -93,7 +93,7 @@ public class TileCacheReaderTest
Assert.That(data.verts[9], Is.EqualTo(43.110687f).Within(0.0001f));
// Tile16: Tris: 13, Verts: 33 Detail Meshed: 13 Detail Verts: 0 Detail Tris: 25
// Verts: 1.130483, 5.610685, 6.510685
tile = tc.getNavMesh().getTile(16);
tile = tc.GetNavMesh().GetTile(16);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(33));
@ -111,7 +111,7 @@ public class TileCacheReaderTest
Assert.That(data.verts[9], Is.EqualTo(6.510685f).Within(0.0001f));
// Tile29: Tris: 5, Verts: 15 Detail Meshed: 5 Detail Verts: 0 Detail Tris: 11
// Verts: 10.330483, 10.110685, 10.110685
tile = tc.getNavMesh().getTile(29);
tile = tc.GetNavMesh().GetTile(29);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(15));
@ -130,28 +130,28 @@ public class TileCacheReaderTest
}
[Test]
public void testDungeon()
public void TestDungeon()
{
using var ms = new MemoryStream(Loader.ToBytes("dungeon_all_tiles_tilecache.bin"));
using var @is = new BinaryReader(ms);
TileCache tc = reader.read(@is, 6, null);
Assert.That(tc.getNavMesh().getMaxTiles(), Is.EqualTo(256));
Assert.That(tc.getNavMesh().getParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.getNavMesh().getParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.getParams().cs, Is.EqualTo(0.3f).Within(0.0f));
Assert.That(tc.getParams().ch, Is.EqualTo(0.2f).Within(0.0f));
Assert.That(tc.getParams().walkableClimb, Is.EqualTo(0.9f).Within(0.0f));
Assert.That(tc.getParams().walkableHeight, Is.EqualTo(2f).Within(0.0f));
Assert.That(tc.getParams().walkableRadius, Is.EqualTo(0.6f).Within(0.0f));
Assert.That(tc.getParams().width, Is.EqualTo(48));
Assert.That(tc.getParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.getParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.getTileCount(), Is.EqualTo(168));
TileCache tc = reader.Read(@is, 6, null);
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
Assert.That(tc.GetNavMesh().GetParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.GetNavMesh().GetParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.GetParams().cs, Is.EqualTo(0.3f).Within(0.0f));
Assert.That(tc.GetParams().ch, Is.EqualTo(0.2f).Within(0.0f));
Assert.That(tc.GetParams().walkableClimb, Is.EqualTo(0.9f).Within(0.0f));
Assert.That(tc.GetParams().walkableHeight, Is.EqualTo(2f).Within(0.0f));
Assert.That(tc.GetParams().walkableRadius, Is.EqualTo(0.6f).Within(0.0f));
Assert.That(tc.GetParams().width, Is.EqualTo(48));
Assert.That(tc.GetParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.GetParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.GetTileCount(), Is.EqualTo(168));
// Tile0: Tris: 8, Verts: 18 Detail Meshed: 8 Detail Verts: 0 Detail Tris: 14
// Verts: 14.997294, 15.484785, 15.484785
MeshTile tile = tc.getNavMesh().getTile(0);
MeshTile tile = tc.GetNavMesh().GetTile(0);
MeshData data = tile.data;
MeshHeader header = data.header;
Assert.That(header.vertCount, Is.EqualTo(18));
@ -169,7 +169,7 @@ public class TileCacheReaderTest
Assert.That(data.verts[9], Is.EqualTo(15.484785f).Within(0.0001f));
// Tile8: Tris: 3, Verts: 8 Detail Meshed: 3 Detail Verts: 0 Detail Tris: 6
// Verts: 13.597294, 17.584785, 17.584785
tile = tc.getNavMesh().getTile(8);
tile = tc.GetNavMesh().GetTile(8);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(8));
@ -187,7 +187,7 @@ public class TileCacheReaderTest
Assert.That(data.verts[9], Is.EqualTo(17.584785f).Within(0.0001f));
// Tile16: Tris: 10, Verts: 20 Detail Meshed: 10 Detail Verts: 0 Detail Tris: 18
// Verts: 6.197294, -22.315216, -22.315216
tile = tc.getNavMesh().getTile(16);
tile = tc.GetNavMesh().GetTile(16);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(20));
@ -205,7 +205,7 @@ public class TileCacheReaderTest
Assert.That(data.verts[9], Is.EqualTo(-22.315216f).Within(0.0001f));
// Tile29: Tris: 1, Verts: 5 Detail Meshed: 1 Detail Verts: 0 Detail Tris: 3
// Verts: 10.197294, 48.484783, 48.484783
tile = tc.getNavMesh().getTile(29);
tile = tc.GetNavMesh().GetTile(29);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(5));

View File

@ -35,54 +35,54 @@ public class TileCacheReaderWriterTest : AbstractTileCacheTest
private readonly TileCacheWriter writer = new TileCacheWriter();
[Test]
public void testFastLz()
public void TestFastLz()
{
testDungeon(false);
testDungeon(true);
TestDungeon(false);
TestDungeon(true);
}
[Test]
public void testLZ4()
public void TestLZ4()
{
testDungeon(true);
testDungeon(false);
TestDungeon(true);
TestDungeon(false);
}
private void testDungeon(bool cCompatibility)
private void TestDungeon(bool cCompatibility)
{
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("dungeon.obj"));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("dungeon.obj"));
TestTileLayerBuilder layerBuilder = new TestTileLayerBuilder(geom);
List<byte[]> layers = layerBuilder.build(ByteOrder.LITTLE_ENDIAN, cCompatibility, 1);
TileCache tc = getTileCache(geom, ByteOrder.LITTLE_ENDIAN, cCompatibility);
List<byte[]> layers = layerBuilder.Build(ByteOrder.LITTLE_ENDIAN, cCompatibility, 1);
TileCache tc = GetTileCache(geom, ByteOrder.LITTLE_ENDIAN, cCompatibility);
foreach (byte[] layer in layers)
{
long refs = tc.addTile(layer, 0);
tc.buildNavMeshTile(refs);
long refs = tc.AddTile(layer, 0);
tc.BuildNavMeshTile(refs);
}
using var msout = new MemoryStream();
using var baos = new BinaryWriter(msout);
writer.write(baos, tc, ByteOrder.LITTLE_ENDIAN, cCompatibility);
writer.Write(baos, tc, ByteOrder.LITTLE_ENDIAN, cCompatibility);
using var msis = new MemoryStream(msout.ToArray());
using var bais = new BinaryReader(msis);
tc = reader.read(bais, 6, null);
Assert.That(tc.getNavMesh().getMaxTiles(), Is.EqualTo(256));
Assert.That(tc.getNavMesh().getParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.getNavMesh().getParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.getParams().cs, Is.EqualTo(0.3f).Within(0.0f));
Assert.That(tc.getParams().ch, Is.EqualTo(0.2f).Within(0.0f));
Assert.That(tc.getParams().walkableClimb, Is.EqualTo(0.9f).Within(0.0f));
Assert.That(tc.getParams().walkableHeight, Is.EqualTo(2f).Within(0.0f));
Assert.That(tc.getParams().walkableRadius, Is.EqualTo(0.6f).Within(0.0f));
Assert.That(tc.getParams().width, Is.EqualTo(48));
Assert.That(tc.getParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.getParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.getTileCount(), Is.EqualTo(168));
tc = reader.Read(bais, 6, null);
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
Assert.That(tc.GetNavMesh().GetParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.GetNavMesh().GetParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.GetParams().cs, Is.EqualTo(0.3f).Within(0.0f));
Assert.That(tc.GetParams().ch, Is.EqualTo(0.2f).Within(0.0f));
Assert.That(tc.GetParams().walkableClimb, Is.EqualTo(0.9f).Within(0.0f));
Assert.That(tc.GetParams().walkableHeight, Is.EqualTo(2f).Within(0.0f));
Assert.That(tc.GetParams().walkableRadius, Is.EqualTo(0.6f).Within(0.0f));
Assert.That(tc.GetParams().width, Is.EqualTo(48));
Assert.That(tc.GetParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.GetParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.GetTileCount(), Is.EqualTo(168));
// Tile0: Tris: 8, Verts: 18 Detail Meshed: 8 Detail Verts: 0 Detail Tris: 14
MeshTile tile = tc.getNavMesh().getTile(0);
MeshTile tile = tc.GetNavMesh().GetTile(0);
MeshData data = tile.data;
MeshHeader header = data.header;
Assert.That(header.vertCount, Is.EqualTo(18));
@ -96,7 +96,7 @@ public class TileCacheReaderWriterTest : AbstractTileCacheTest
Assert.That(data.detailVerts.Length, Is.EqualTo(0));
Assert.That(data.detailTris.Length, Is.EqualTo(4 * 14));
// Tile8: Tris: 3, Verts: 8 Detail Meshed: 3 Detail Verts: 0 Detail Tris: 6
tile = tc.getNavMesh().getTile(8);
tile = tc.GetNavMesh().GetTile(8);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(8));
@ -110,7 +110,7 @@ public class TileCacheReaderWriterTest : AbstractTileCacheTest
Assert.That(data.detailVerts.Length, Is.EqualTo(0));
Assert.That(data.detailTris.Length, Is.EqualTo(4 * 6));
// Tile16: Tris: 10, Verts: 20 Detail Meshed: 10 Detail Verts: 0 Detail Tris: 18
tile = tc.getNavMesh().getTile(16);
tile = tc.GetNavMesh().GetTile(16);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(20));
@ -124,7 +124,7 @@ public class TileCacheReaderWriterTest : AbstractTileCacheTest
Assert.That(data.detailVerts.Length, Is.EqualTo(0));
Assert.That(data.detailTris.Length, Is.EqualTo(4 * 18));
// Tile29: Tris: 1, Verts: 5 Detail Meshed: 1 Detail Verts: 0 Detail Tris: 3
tile = tc.getNavMesh().getTile(29);
tile = tc.GetNavMesh().GetTile(29);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(5));

View File

@ -30,71 +30,71 @@ namespace DotRecast.Detour.TileCache.Test;
public class TempObstaclesTest : AbstractTileCacheTest
{
[Test]
public void testDungeon()
public void TestDungeon()
{
bool cCompatibility = true;
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("dungeon.obj"));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("dungeon.obj"));
TestTileLayerBuilder layerBuilder = new TestTileLayerBuilder(geom);
List<byte[]> layers = layerBuilder.build(ByteOrder.LITTLE_ENDIAN, cCompatibility, 1);
TileCache tc = getTileCache(geom, ByteOrder.LITTLE_ENDIAN, cCompatibility);
List<byte[]> layers = layerBuilder.Build(ByteOrder.LITTLE_ENDIAN, cCompatibility, 1);
TileCache tc = GetTileCache(geom, ByteOrder.LITTLE_ENDIAN, cCompatibility);
foreach (byte[] data in layers)
{
long refs = tc.addTile(data, 0);
tc.buildNavMeshTile(refs);
long refs = tc.AddTile(data, 0);
tc.BuildNavMeshTile(refs);
}
List<MeshTile> tiles = tc.getNavMesh().getTilesAt(1, 4);
List<MeshTile> tiles = tc.GetNavMesh().GetTilesAt(1, 4);
MeshTile tile = tiles[0];
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
long o = tc.addObstacle(Vector3f.Of(-1.815208f, 9.998184f, -20.307983f), 1f, 2f);
bool upToDate = tc.update();
long o = tc.AddObstacle(Vector3f.Of(-1.815208f, 9.998184f, -20.307983f), 1f, 2f);
bool upToDate = tc.Update();
Assert.That(upToDate, Is.True);
tiles = tc.getNavMesh().getTilesAt(1, 4);
tiles = tc.GetNavMesh().GetTilesAt(1, 4);
tile = tiles[0];
Assert.That(tile.data.header.vertCount, Is.EqualTo(22));
Assert.That(tile.data.header.polyCount, Is.EqualTo(11));
tc.removeObstacle(o);
upToDate = tc.update();
tc.RemoveObstacle(o);
upToDate = tc.Update();
Assert.That(upToDate, Is.True);
tiles = tc.getNavMesh().getTilesAt(1, 4);
tiles = tc.GetNavMesh().GetTilesAt(1, 4);
tile = tiles[0];
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
}
[Test]
public void testDungeonBox()
public void TestDungeonBox()
{
bool cCompatibility = true;
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("dungeon.obj"));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("dungeon.obj"));
TestTileLayerBuilder layerBuilder = new TestTileLayerBuilder(geom);
List<byte[]> layers = layerBuilder.build(ByteOrder.LITTLE_ENDIAN, cCompatibility, 1);
TileCache tc = getTileCache(geom, ByteOrder.LITTLE_ENDIAN, cCompatibility);
List<byte[]> layers = layerBuilder.Build(ByteOrder.LITTLE_ENDIAN, cCompatibility, 1);
TileCache tc = GetTileCache(geom, ByteOrder.LITTLE_ENDIAN, cCompatibility);
foreach (byte[] data in layers)
{
long refs = tc.addTile(data, 0);
tc.buildNavMeshTile(refs);
long refs = tc.AddTile(data, 0);
tc.BuildNavMeshTile(refs);
}
List<MeshTile> tiles = tc.getNavMesh().getTilesAt(1, 4);
List<MeshTile> tiles = tc.GetNavMesh().GetTilesAt(1, 4);
MeshTile tile = tiles[0];
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
long o = tc.addBoxObstacle(
long o = tc.AddBoxObstacle(
Vector3f.Of(-2.315208f, 9.998184f, -20.807983f),
Vector3f.Of(-1.315208f, 11.998184f, -19.807983f)
);
bool upToDate = tc.update();
bool upToDate = tc.Update();
Assert.That(upToDate, Is.True);
tiles = tc.getNavMesh().getTilesAt(1, 4);
tiles = tc.GetNavMesh().GetTilesAt(1, 4);
tile = tiles[0];
Assert.That(tile.data.header.vertCount, Is.EqualTo(22));
Assert.That(tile.data.header.polyCount, Is.EqualTo(11));
tc.removeObstacle(o);
upToDate = tc.update();
tc.RemoveObstacle(o);
upToDate = tc.Update();
Assert.That(upToDate, Is.True);
tiles = tc.getNavMesh().getTilesAt(1, 4);
tiles = tc.GetNavMesh().GetTilesAt(1, 4);
tile = tiles[0];
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));

View File

@ -52,35 +52,35 @@ public class TestTileLayerBuilder : AbstractTileLayersBuilder
public TestTileLayerBuilder(InputGeomProvider geom)
{
this.geom = geom;
rcConfig = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.calcBorder(m_agentRadius, m_cellSize),
rcConfig = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.CalcBorder(m_agentRadius, m_cellSize),
PartitionType.WATERSHED, m_cellSize, m_cellHeight, m_agentMaxSlope, true, true, true, m_agentHeight,
m_agentRadius, m_agentMaxClimb, m_regionMinArea, m_regionMergeArea, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly,
true, m_detailSampleDist, m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_GROUND);
Vector3f bmin = geom.getMeshBoundsMin();
Vector3f bmax = geom.getMeshBoundsMax();
int[] twh = Recast.Recast.calcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize);
Vector3f bmin = geom.GetMeshBoundsMin();
Vector3f bmax = geom.GetMeshBoundsMax();
int[] twh = Recast.Recast.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize);
tw = twh[0];
th = twh[1];
}
public List<byte[]> build(ByteOrder order, bool cCompatibility, int threads)
public List<byte[]> Build(ByteOrder order, bool cCompatibility, int threads)
{
return build(order, cCompatibility, threads, tw, th);
return Build(order, cCompatibility, threads, tw, th);
}
public int getTw()
public int GetTw()
{
return tw;
}
public int getTh()
public int GetTh()
{
return th;
}
protected override List<byte[]> build(int tx, int ty, ByteOrder order, bool cCompatibility)
protected override List<byte[]> Build(int tx, int ty, ByteOrder order, bool cCompatibility)
{
HeightfieldLayerSet lset = getHeightfieldSet(tx, ty);
HeightfieldLayerSet lset = GetHeightfieldSet(tx, ty);
List<byte[]> result = new();
if (lset != null)
{
@ -110,20 +110,20 @@ public class TestTileLayerBuilder : AbstractTileLayersBuilder
header.maxy = layer.maxy;
header.hmin = layer.hmin;
header.hmax = layer.hmax;
result.Add(builder.compressTileCacheLayer(header, layer.heights, layer.areas, layer.cons, order, cCompatibility));
result.Add(builder.CompressTileCacheLayer(header, layer.heights, layer.areas, layer.cons, order, cCompatibility));
}
}
return result;
}
protected HeightfieldLayerSet getHeightfieldSet(int tx, int ty)
protected HeightfieldLayerSet GetHeightfieldSet(int tx, int ty)
{
RecastBuilder rcBuilder = new RecastBuilder();
Vector3f bmin = geom.getMeshBoundsMin();
Vector3f bmax = geom.getMeshBoundsMax();
Vector3f bmin = geom.GetMeshBoundsMin();
Vector3f bmax = geom.GetMeshBoundsMax();
RecastBuilderConfig cfg = new RecastBuilderConfig(rcConfig, bmin, bmax, tx, ty);
HeightfieldLayerSet lset = rcBuilder.buildLayers(geom, cfg);
HeightfieldLayerSet lset = rcBuilder.BuildLayers(geom, cfg);
return lset;
}
}

View File

@ -39,26 +39,26 @@ public class TileCacheFindPathTest : AbstractTileCacheTest
{
using var msis = new MemoryStream(Loader.ToBytes("dungeon_all_tiles_tilecache.bin"));
using var @is = new BinaryReader(msis);
TileCache tcC = new TileCacheReader().read(@is, 6, new TestTileCacheMeshProcess());
navmesh = tcC.getNavMesh();
TileCache tcC = new TileCacheReader().Read(@is, 6, new TestTileCacheMeshProcess());
navmesh = tcC.GetNavMesh();
query = new NavMeshQuery(navmesh);
}
[Test]
public void testFindPath()
public void TestFindPath()
{
QueryFilter filter = new DefaultQueryFilter();
Vector3f extents = Vector3f.Of(2f, 4f, 2f);
Result<FindNearestPolyResult> findPolyStart = query.findNearestPoly(start, extents, filter);
Result<FindNearestPolyResult> findPolyEnd = query.findNearestPoly(end, extents, filter);
long startRef = findPolyStart.result.getNearestRef();
long endRef = findPolyEnd.result.getNearestRef();
Vector3f startPos = findPolyStart.result.getNearestPos();
Vector3f endPos = findPolyEnd.result.getNearestPos();
Result<List<long>> path = query.findPath(startRef, endRef, startPos, endPos, filter);
Result<FindNearestPolyResult> findPolyStart = query.FindNearestPoly(start, extents, filter);
Result<FindNearestPolyResult> findPolyEnd = query.FindNearestPoly(end, extents, filter);
long startRef = findPolyStart.result.GetNearestRef();
long endRef = findPolyEnd.result.GetNearestRef();
Vector3f startPos = findPolyStart.result.GetNearestPos();
Vector3f endPos = findPolyEnd.result.GetNearestPos();
Result<List<long>> path = query.FindPath(startRef, endRef, startPos, endPos, filter);
int maxStraightPath = 256;
int options = 0;
Result<List<StraightPathItem>> pathStr = query.findStraightPath(startPos, endPos, path.result, maxStraightPath, options);
Result<List<StraightPathItem>> pathStr = query.FindStraightPath(startPos, endPos, path.result, maxStraightPath, options);
Assert.That(pathStr.result.Count, Is.EqualTo(8));
}
}

View File

@ -53,35 +53,35 @@ public class TileCacheNavigationTest : AbstractTileCacheTest
protected NavMeshQuery query;
[SetUp]
public void setUp()
public void SetUp()
{
bool cCompatibility = true;
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("dungeon.obj"));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("dungeon.obj"));
TestTileLayerBuilder layerBuilder = new TestTileLayerBuilder(geom);
List<byte[]> layers = layerBuilder.build(ByteOrder.LITTLE_ENDIAN, cCompatibility, 1);
TileCache tc = getTileCache(geom, ByteOrder.LITTLE_ENDIAN, cCompatibility);
List<byte[]> layers = layerBuilder.Build(ByteOrder.LITTLE_ENDIAN, cCompatibility, 1);
TileCache tc = GetTileCache(geom, ByteOrder.LITTLE_ENDIAN, cCompatibility);
foreach (byte[] data in layers)
{
tc.addTile(data, 0);
tc.AddTile(data, 0);
}
for (int y = 0; y < layerBuilder.getTh(); ++y)
for (int y = 0; y < layerBuilder.GetTh(); ++y)
{
for (int x = 0; x < layerBuilder.getTw(); ++x)
for (int x = 0; x < layerBuilder.GetTw(); ++x)
{
foreach (long refs in tc.getTilesAt(x, y))
foreach (long refs in tc.GetTilesAt(x, y))
{
tc.buildNavMeshTile(refs);
tc.BuildNavMeshTile(refs);
}
}
}
navmesh = tc.getNavMesh();
navmesh = tc.GetNavMesh();
query = new NavMeshQuery(navmesh);
}
[Test]
public void testFindPathWithDefaultHeuristic()
public void TestFindPathWithDefaultHeuristic()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
@ -90,7 +90,7 @@ public class TileCacheNavigationTest : AbstractTileCacheTest
long endRef = endRefs[i];
Vector3f startPos = startPoss[i];
Vector3f endPos = endPoss[i];
Result<List<long>> path = query.findPath(startRef, endRef, startPos, endPos, filter);
Result<List<long>> path = query.FindPath(startRef, endRef, startPos, endPos, filter);
Assert.That(path.status, Is.EqualTo(statuses[i]));
Assert.That(path.result.Count, Is.EqualTo(results[i].Length));
for (int j = 0; j < results[i].Length; j++)
@ -101,7 +101,7 @@ public class TileCacheNavigationTest : AbstractTileCacheTest
}
[Test]
public void testFindPathWithNoHeuristic()
public void TestFindPathWithNoHeuristic()
{
QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++)
@ -110,7 +110,7 @@ public class TileCacheNavigationTest : AbstractTileCacheTest
long endRef = endRefs[i];
Vector3f startPos = startPoss[i];
Vector3f endPos = endPoss[i];
Result<List<long>> path = query.findPath(startRef, endRef, startPos, endPos, filter, new DefaultQueryHeuristic(0.0f),
Result<List<long>> path = query.FindPath(startRef, endRef, startPos, endPos, filter, new DefaultQueryHeuristic(0.0f),
0, 0);
Assert.That(path.status, Is.EqualTo(statuses[i]));
Assert.That(path.result.Count, Is.EqualTo(results[i].Length));

View File

@ -32,68 +32,68 @@ namespace DotRecast.Detour.TileCache.Test;
public class TileCacheTest : AbstractTileCacheTest
{
[Test]
public void testFastLz()
public void TestFastLz()
{
testDungeon(ByteOrder.LITTLE_ENDIAN, false);
testDungeon(ByteOrder.LITTLE_ENDIAN, true);
testDungeon(ByteOrder.BIG_ENDIAN, false);
testDungeon(ByteOrder.BIG_ENDIAN, true);
test(ByteOrder.LITTLE_ENDIAN, false);
test(ByteOrder.LITTLE_ENDIAN, true);
test(ByteOrder.BIG_ENDIAN, false);
test(ByteOrder.BIG_ENDIAN, true);
TestDungeon(ByteOrder.LITTLE_ENDIAN, false);
TestDungeon(ByteOrder.LITTLE_ENDIAN, true);
TestDungeon(ByteOrder.BIG_ENDIAN, false);
TestDungeon(ByteOrder.BIG_ENDIAN, true);
Test(ByteOrder.LITTLE_ENDIAN, false);
Test(ByteOrder.LITTLE_ENDIAN, true);
Test(ByteOrder.BIG_ENDIAN, false);
Test(ByteOrder.BIG_ENDIAN, true);
}
[Test]
public void testLZ4()
public void TestLZ4()
{
testDungeon(ByteOrder.LITTLE_ENDIAN, false);
testDungeon(ByteOrder.LITTLE_ENDIAN, true);
testDungeon(ByteOrder.BIG_ENDIAN, false);
testDungeon(ByteOrder.BIG_ENDIAN, true);
test(ByteOrder.LITTLE_ENDIAN, false);
test(ByteOrder.LITTLE_ENDIAN, true);
test(ByteOrder.BIG_ENDIAN, false);
test(ByteOrder.BIG_ENDIAN, true);
TestDungeon(ByteOrder.LITTLE_ENDIAN, false);
TestDungeon(ByteOrder.LITTLE_ENDIAN, true);
TestDungeon(ByteOrder.BIG_ENDIAN, false);
TestDungeon(ByteOrder.BIG_ENDIAN, true);
Test(ByteOrder.LITTLE_ENDIAN, false);
Test(ByteOrder.LITTLE_ENDIAN, true);
Test(ByteOrder.BIG_ENDIAN, false);
Test(ByteOrder.BIG_ENDIAN, true);
}
private void testDungeon(ByteOrder order, bool cCompatibility)
private void TestDungeon(ByteOrder order, bool cCompatibility)
{
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("dungeon.obj"));
TileCache tc = getTileCache(geom, order, cCompatibility);
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("dungeon.obj"));
TileCache tc = GetTileCache(geom, order, cCompatibility);
TestTileLayerBuilder layerBuilder = new TestTileLayerBuilder(geom);
List<byte[]> layers = layerBuilder.build(order, cCompatibility, 1);
List<byte[]> layers = layerBuilder.Build(order, cCompatibility, 1);
int cacheLayerCount = 0;
int cacheCompressedSize = 0;
int cacheRawSize = 0;
foreach (byte[] layer in layers)
{
long refs = tc.addTile(layer, 0);
tc.buildNavMeshTile(refs);
long refs = tc.AddTile(layer, 0);
tc.BuildNavMeshTile(refs);
cacheLayerCount++;
cacheCompressedSize += layer.Length;
cacheRawSize += 4 * 48 * 48 + 56; // FIXME
}
Console.WriteLine("Compressor: " + tc.getCompressor().GetType().Name + " C Compatibility: " + cCompatibility
Console.WriteLine("Compressor: " + tc.GetCompressor().GetType().Name + " C Compatibility: " + cCompatibility
+ " Layers: " + cacheLayerCount + " Raw Size: " + cacheRawSize + " Compressed: " + cacheCompressedSize);
Assert.That(tc.getNavMesh().getMaxTiles(), Is.EqualTo(256));
Assert.That(tc.getNavMesh().getParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.getNavMesh().getParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.getParams().cs, Is.EqualTo(0.3f));
Assert.That(tc.getParams().ch, Is.EqualTo(0.2f));
Assert.That(tc.getParams().walkableClimb, Is.EqualTo(0.9f));
Assert.That(tc.getParams().walkableHeight, Is.EqualTo(2f));
Assert.That(tc.getParams().walkableRadius, Is.EqualTo(0.6f));
Assert.That(tc.getParams().width, Is.EqualTo(48));
Assert.That(tc.getParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.getParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.getTileCount(), Is.EqualTo(168));
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
Assert.That(tc.GetNavMesh().GetParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.GetNavMesh().GetParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.GetParams().cs, Is.EqualTo(0.3f));
Assert.That(tc.GetParams().ch, Is.EqualTo(0.2f));
Assert.That(tc.GetParams().walkableClimb, Is.EqualTo(0.9f));
Assert.That(tc.GetParams().walkableHeight, Is.EqualTo(2f));
Assert.That(tc.GetParams().walkableRadius, Is.EqualTo(0.6f));
Assert.That(tc.GetParams().width, Is.EqualTo(48));
Assert.That(tc.GetParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.GetParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.GetTileCount(), Is.EqualTo(168));
// Tile0: Tris: 8, Verts: 18 Detail Meshed: 8 Detail Verts: 0 Detail Tris: 14
MeshTile tile = tc.getNavMesh().getTile(0);
MeshTile tile = tc.GetNavMesh().GetTile(0);
MeshData data = tile.data;
MeshHeader header = data.header;
Assert.That(header.vertCount, Is.EqualTo(18));
@ -110,7 +110,7 @@ public class TileCacheTest : AbstractTileCacheTest
Assert.That(data.verts[6], Is.EqualTo(15.484785f).Within(0.0001f));
Assert.That(data.verts[9], Is.EqualTo(15.484785f).Within(0.0001f));
// Tile8: Tris: 3, Verts: 8 Detail Meshed: 3 Detail Verts: 0 Detail Tris: 6
tile = tc.getNavMesh().getTile(8);
tile = tc.GetNavMesh().GetTile(8);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(8));
@ -124,7 +124,7 @@ public class TileCacheTest : AbstractTileCacheTest
Assert.That(data.detailVerts.Length, Is.EqualTo(0));
Assert.That(data.detailTris.Length, Is.EqualTo(4 * 6));
// Tile16: Tris: 10, Verts: 20 Detail Meshed: 10 Detail Verts: 0 Detail Tris: 18
tile = tc.getNavMesh().getTile(16);
tile = tc.GetNavMesh().GetTile(16);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(20));
@ -138,7 +138,7 @@ public class TileCacheTest : AbstractTileCacheTest
Assert.That(data.detailVerts.Length, Is.EqualTo(0));
Assert.That(data.detailTris.Length, Is.EqualTo(4 * 18));
// Tile29: Tris: 1, Verts: 5 Detail Meshed: 1 Detail Verts: 0 Detail Tris: 3
tile = tc.getNavMesh().getTile(29);
tile = tc.GetNavMesh().GetTile(29);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(5));
@ -153,81 +153,81 @@ public class TileCacheTest : AbstractTileCacheTest
Assert.That(data.detailTris.Length, Is.EqualTo(4 * 3));
}
private void test(ByteOrder order, bool cCompatibility)
private void Test(ByteOrder order, bool cCompatibility)
{
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("nav_test.obj"));
TileCache tc = getTileCache(geom, order, cCompatibility);
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("nav_test.obj"));
TileCache tc = GetTileCache(geom, order, cCompatibility);
TestTileLayerBuilder layerBuilder = new TestTileLayerBuilder(geom);
List<byte[]> layers = layerBuilder.build(order, cCompatibility, 1);
List<byte[]> layers = layerBuilder.Build(order, cCompatibility, 1);
int cacheLayerCount = 0;
int cacheCompressedSize = 0;
int cacheRawSize = 0;
foreach (byte[] layer in layers)
{
long refs = tc.addTile(layer, 0);
tc.buildNavMeshTile(refs);
long refs = tc.AddTile(layer, 0);
tc.BuildNavMeshTile(refs);
cacheLayerCount++;
cacheCompressedSize += layer.Length;
cacheRawSize += 4 * 48 * 48 + 56;
}
Console.WriteLine("Compressor: " + tc.getCompressor().GetType().Name + " C Compatibility: " + cCompatibility
Console.WriteLine("Compressor: " + tc.GetCompressor().GetType().Name + " C Compatibility: " + cCompatibility
+ " Layers: " + cacheLayerCount + " Raw Size: " + cacheRawSize + " Compressed: " + cacheCompressedSize);
}
[Test]
public void testPerformance()
public void TestPerformance()
{
int threads = 4;
ByteOrder order = ByteOrder.LITTLE_ENDIAN;
bool cCompatibility = false;
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("dungeon.obj"));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("dungeon.obj"));
TestTileLayerBuilder layerBuilder = new TestTileLayerBuilder(geom);
for (int i = 0; i < 4; i++)
{
layerBuilder.build(order, cCompatibility, 1);
layerBuilder.build(order, cCompatibility, threads);
layerBuilder.Build(order, cCompatibility, 1);
layerBuilder.Build(order, cCompatibility, threads);
}
long t1 = FrequencyWatch.Ticks;
List<byte[]> layers = null;
for (int i = 0; i < 8; i++)
{
layers = layerBuilder.build(order, cCompatibility, 1);
layers = layerBuilder.Build(order, cCompatibility, 1);
}
long t2 = FrequencyWatch.Ticks;
for (int i = 0; i < 8; i++)
{
layers = layerBuilder.build(order, cCompatibility, threads);
layers = layerBuilder.Build(order, cCompatibility, threads);
}
long t3 = FrequencyWatch.Ticks;
Console.WriteLine(" Time ST : " + (t2 - t1) / TimeSpan.TicksPerMillisecond);
Console.WriteLine(" Time MT : " + (t3 - t2) / TimeSpan.TicksPerMillisecond);
TileCache tc = getTileCache(geom, order, cCompatibility);
TileCache tc = GetTileCache(geom, order, cCompatibility);
foreach (byte[] layer in layers)
{
long refs = tc.addTile(layer, 0);
tc.buildNavMeshTile(refs);
long refs = tc.AddTile(layer, 0);
tc.BuildNavMeshTile(refs);
}
Assert.That(tc.getNavMesh().getMaxTiles(), Is.EqualTo(256));
Assert.That(tc.getNavMesh().getParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.getNavMesh().getParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.getNavMesh().getMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.getParams().cs, Is.EqualTo(0.3f));
Assert.That(tc.getParams().ch, Is.EqualTo(0.2f));
Assert.That(tc.getParams().walkableClimb, Is.EqualTo(0.9f));
Assert.That(tc.getParams().walkableHeight, Is.EqualTo(2f));
Assert.That(tc.getParams().walkableRadius, Is.EqualTo(0.6f));
Assert.That(tc.getParams().width, Is.EqualTo(48));
Assert.That(tc.getParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.getParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.getTileCount(), Is.EqualTo(168));
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
Assert.That(tc.GetNavMesh().GetParams().maxPolys, Is.EqualTo(16384));
Assert.That(tc.GetNavMesh().GetParams().tileWidth, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetParams().tileHeight, Is.EqualTo(14.4f).Within(0.001f));
Assert.That(tc.GetNavMesh().GetMaxVertsPerPoly(), Is.EqualTo(6));
Assert.That(tc.GetParams().cs, Is.EqualTo(0.3f));
Assert.That(tc.GetParams().ch, Is.EqualTo(0.2f));
Assert.That(tc.GetParams().walkableClimb, Is.EqualTo(0.9f));
Assert.That(tc.GetParams().walkableHeight, Is.EqualTo(2f));
Assert.That(tc.GetParams().walkableRadius, Is.EqualTo(0.6f));
Assert.That(tc.GetParams().width, Is.EqualTo(48));
Assert.That(tc.GetParams().maxTiles, Is.EqualTo(6 * 7 * 4));
Assert.That(tc.GetParams().maxObstacles, Is.EqualTo(128));
Assert.That(tc.GetTileCount(), Is.EqualTo(168));
// Tile0: Tris: 8, Verts: 18 Detail Meshed: 8 Detail Verts: 0 Detail Tris: 14
MeshTile tile = tc.getNavMesh().getTile(0);
MeshTile tile = tc.GetNavMesh().GetTile(0);
MeshData data = tile.data;
MeshHeader header = data.header;
Assert.That(header.vertCount, Is.EqualTo(18));
@ -244,7 +244,7 @@ public class TileCacheTest : AbstractTileCacheTest
Assert.That(data.verts[6], Is.EqualTo(15.484785f).Within(0.0001f));
Assert.That(data.verts[9], Is.EqualTo(15.484785f).Within(0.0001f));
// Tile8: Tris: 3, Verts: 8 Detail Meshed: 3 Detail Verts: 0 Detail Tris: 6
tile = tc.getNavMesh().getTile(8);
tile = tc.GetNavMesh().GetTile(8);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(8));
@ -258,7 +258,7 @@ public class TileCacheTest : AbstractTileCacheTest
Assert.That(data.detailVerts.Length, Is.EqualTo(0));
Assert.That(data.detailTris.Length, Is.EqualTo(4 * 6));
// Tile16: Tris: 10, Verts: 20 Detail Meshed: 10 Detail Verts: 0 Detail Tris: 18
tile = tc.getNavMesh().getTile(16);
tile = tc.GetNavMesh().GetTile(16);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(20));
@ -272,7 +272,7 @@ public class TileCacheTest : AbstractTileCacheTest
Assert.That(data.detailVerts.Length, Is.EqualTo(0));
Assert.That(data.detailTris.Length, Is.EqualTo(4 * 18));
// Tile29: Tris: 1, Verts: 5 Detail Meshed: 1 Detail Verts: 0 Detail Tris: 3
tile = tc.getNavMesh().getTile(29);
tile = tc.GetNavMesh().GetTile(29);
data = tile.data;
header = data.header;
Assert.That(header.vertCount, Is.EqualTo(5));

View File

@ -48,15 +48,15 @@ public class RecastLayersTest
private const int m_tileSize = 48;
[Test]
public void testDungeon2()
public void TestDungeon2()
{
}
[Test]
public void testDungeon()
public void TestDungeon()
{
HeightfieldLayerSet lset = build("dungeon.obj", 3, 2);
HeightfieldLayerSet lset = Build("dungeon.obj", 3, 2);
Assert.That(lset.layers.Length, Is.EqualTo(1));
Assert.That(lset.layers[0].width, Is.EqualTo(48));
Assert.That(lset.layers[0].hmin, Is.EqualTo(51));
@ -72,9 +72,9 @@ public class RecastLayersTest
}
[Test]
public void test()
public void Test()
{
HeightfieldLayerSet lset = build("nav_test.obj", 3, 2);
HeightfieldLayerSet lset = Build("nav_test.obj", 3, 2);
Assert.That(lset.layers.Length, Is.EqualTo(3));
Assert.That(lset.layers[0].width, Is.EqualTo(48));
Assert.That(lset.layers[0].hmin, Is.EqualTo(13));
@ -114,9 +114,9 @@ public class RecastLayersTest
}
[Test]
public void test2()
public void Test2()
{
HeightfieldLayerSet lset = build("nav_test.obj", 2, 4);
HeightfieldLayerSet lset = Build("nav_test.obj", 2, 4);
Assert.That(lset.layers.Length, Is.EqualTo(2));
Assert.That(lset.layers[0].width, Is.EqualTo(48));
Assert.That(lset.layers[0].hmin, Is.EqualTo(13));
@ -143,16 +143,16 @@ public class RecastLayersTest
Assert.That(lset.layers[1].cons[1600], Is.EqualTo(0));
}
private HeightfieldLayerSet build(string filename, int x, int y)
private HeightfieldLayerSet Build(string filename, int x, int y)
{
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes(filename));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes(filename));
RecastBuilder builder = new RecastBuilder();
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.calcBorder(m_agentRadius, m_cellSize),
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.CalcBorder(m_agentRadius, m_cellSize),
m_partitionType, m_cellSize, m_cellHeight, m_agentMaxSlope, true, true, true, m_agentHeight, m_agentRadius,
m_agentMaxClimb, m_regionMinArea, m_regionMergeArea, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, true,
m_detailSampleDist, m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_GROUND);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), x, y);
HeightfieldLayerSet lset = builder.buildLayers(geom, bcfg);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), x, y);
HeightfieldLayerSet lset = builder.BuildLayers(geom, bcfg);
return lset;
}
}

View File

@ -46,60 +46,60 @@ public class RecastSoloMeshTest
private PartitionType m_partitionType = PartitionType.WATERSHED;
[Test]
public void testPerformance()
public void TestPerformance()
{
for (int i = 0; i < 10; i++)
{
testBuild("dungeon.obj", PartitionType.WATERSHED, 52, 16, 15, 223, 118, 118, 513, 291);
testBuild("dungeon.obj", PartitionType.MONOTONE, 0, 17, 16, 210, 100, 100, 453, 264);
testBuild("dungeon.obj", PartitionType.LAYERS, 0, 5, 5, 203, 97, 97, 446, 266);
TestBuild("dungeon.obj", PartitionType.WATERSHED, 52, 16, 15, 223, 118, 118, 513, 291);
TestBuild("dungeon.obj", PartitionType.MONOTONE, 0, 17, 16, 210, 100, 100, 453, 264);
TestBuild("dungeon.obj", PartitionType.LAYERS, 0, 5, 5, 203, 97, 97, 446, 266);
}
}
[Test]
public void testDungeonWatershed()
public void TestDungeonWatershed()
{
testBuild("dungeon.obj", PartitionType.WATERSHED, 52, 16, 15, 223, 118, 118, 513, 291);
TestBuild("dungeon.obj", PartitionType.WATERSHED, 52, 16, 15, 223, 118, 118, 513, 291);
}
[Test]
public void testDungeonMonotone()
public void TestDungeonMonotone()
{
testBuild("dungeon.obj", PartitionType.MONOTONE, 0, 17, 16, 210, 100, 100, 453, 264);
TestBuild("dungeon.obj", PartitionType.MONOTONE, 0, 17, 16, 210, 100, 100, 453, 264);
}
[Test]
public void testDungeonLayers()
public void TestDungeonLayers()
{
testBuild("dungeon.obj", PartitionType.LAYERS, 0, 5, 5, 203, 97, 97, 446, 266);
TestBuild("dungeon.obj", PartitionType.LAYERS, 0, 5, 5, 203, 97, 97, 446, 266);
}
[Test]
public void testWatershed()
public void TestWatershed()
{
testBuild("nav_test.obj", PartitionType.WATERSHED, 60, 48, 47, 349, 153, 153, 802, 558);
TestBuild("nav_test.obj", PartitionType.WATERSHED, 60, 48, 47, 349, 153, 153, 802, 558);
}
[Test]
public void testMonotone()
public void TestMonotone()
{
testBuild("nav_test.obj", PartitionType.MONOTONE, 0, 50, 49, 340, 185, 185, 871, 557);
TestBuild("nav_test.obj", PartitionType.MONOTONE, 0, 50, 49, 340, 185, 185, 871, 557);
}
[Test]
public void testLayers()
public void TestLayers()
{
testBuild("nav_test.obj", PartitionType.LAYERS, 0, 19, 32, 312, 150, 150, 764, 521);
TestBuild("nav_test.obj", PartitionType.LAYERS, 0, 19, 32, 312, 150, 150, 764, 521);
}
public void testBuild(string filename, PartitionType partitionType, int expDistance, int expRegions,
public void TestBuild(string filename, PartitionType partitionType, int expDistance, int expRegions,
int expContours, int expVerts, int expPolys, int expDetMeshes, int expDetVerts, int expDetTris)
{
m_partitionType = partitionType;
InputGeomProvider geomProvider = ObjImporter.load(Loader.ToBytes(filename));
InputGeomProvider geomProvider = ObjImporter.Load(Loader.ToBytes(filename));
long time = FrequencyWatch.Ticks;
Vector3f bmin = geomProvider.getMeshBoundsMin();
Vector3f bmax = geomProvider.getMeshBoundsMax();
Vector3f bmin = geomProvider.GetMeshBoundsMin();
Vector3f bmax = geomProvider.GetMeshBoundsMax();
Telemetry m_ctx = new Telemetry();
//
// Step 1. Initialize build config.
@ -117,10 +117,10 @@ public class RecastSoloMeshTest
// Allocate voxel heightfield where we rasterize our input data to.
Heightfield m_solid = new Heightfield(bcfg.width, bcfg.height, bcfg.bmin, bcfg.bmax, cfg.cs, cfg.ch, cfg.borderSize);
foreach (TriMesh geom in geomProvider.meshes())
foreach (TriMesh geom in geomProvider.Meshes())
{
float[] verts = geom.getVerts();
int[] tris = geom.getTris();
float[] verts = geom.GetVerts();
int[] tris = geom.GetTris();
int ntris = tris.Length / 3;
// Allocate array that can hold triangle area types.
@ -133,9 +133,9 @@ public class RecastSoloMeshTest
// If your input data is multiple meshes, you can transform them here,
// calculate
// the are type for each of the meshes and rasterize them.
int[] m_triareas = Recast.markWalkableTriangles(m_ctx, cfg.walkableSlopeAngle, verts, tris, ntris,
int[] m_triareas = Recast.MarkWalkableTriangles(m_ctx, cfg.walkableSlopeAngle, verts, tris, ntris,
cfg.walkableAreaMod);
RecastRasterization.rasterizeTriangles(m_solid, verts, tris, m_triareas, ntris, cfg.walkableClimb, m_ctx);
RecastRasterization.RasterizeTriangles(m_solid, verts, tris, m_triareas, ntris, cfg.walkableClimb, m_ctx);
//
// Step 3. Filter walkables surfaces.
//
@ -144,9 +144,9 @@ public class RecastSoloMeshTest
// Once all geometry is rasterized, we do initial pass of filtering to
// remove unwanted overhangs caused by the conservative rasterization
// as well as filter spans where the character cannot possibly stand.
RecastFilter.filterLowHangingWalkableObstacles(m_ctx, cfg.walkableClimb, m_solid);
RecastFilter.filterLedgeSpans(m_ctx, cfg.walkableHeight, cfg.walkableClimb, m_solid);
RecastFilter.filterWalkableLowHeightSpans(m_ctx, cfg.walkableHeight, m_solid);
RecastFilter.FilterLowHangingWalkableObstacles(m_ctx, cfg.walkableClimb, m_solid);
RecastFilter.FilterLedgeSpans(m_ctx, cfg.walkableHeight, cfg.walkableClimb, m_solid);
RecastFilter.FilterWalkableLowHeightSpans(m_ctx, cfg.walkableHeight, m_solid);
//
// Step 4. Partition walkable surface to simple regions.
@ -155,16 +155,16 @@ public class RecastSoloMeshTest
// Compact the heightfield so that it is faster to handle from now on.
// This will result more cache coherent data as well as the neighbours
// between walkable cells will be calculated.
CompactHeightfield m_chf = RecastCompact.buildCompactHeightfield(m_ctx, cfg.walkableHeight, cfg.walkableClimb,
CompactHeightfield m_chf = RecastCompact.BuildCompactHeightfield(m_ctx, cfg.walkableHeight, cfg.walkableClimb,
m_solid);
// Erode the walkable area by agent radius.
RecastArea.erodeWalkableArea(m_ctx, cfg.walkableRadius, m_chf);
RecastArea.ErodeWalkableArea(m_ctx, cfg.walkableRadius, m_chf);
// (Optional) Mark areas.
/*
* ConvexVolume vols = m_geom->getConvexVolumes(); for (int i = 0; i < m_geom->getConvexVolumeCount(); ++i)
* rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned
* ConvexVolume vols = m_geom->GetConvexVolumes(); for (int i = 0; i < m_geom->GetConvexVolumeCount(); ++i)
* RcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned
* char)vols[i].area, *m_chf);
*/
@ -211,20 +211,20 @@ public class RecastSoloMeshTest
{
// Prepare for region partitioning, by calculating distance field
// along the walkable surface.
RecastRegion.buildDistanceField(m_ctx, m_chf);
RecastRegion.BuildDistanceField(m_ctx, m_chf);
// Partition the walkable surface into simple regions without holes.
RecastRegion.buildRegions(m_ctx, m_chf, cfg.minRegionArea, cfg.mergeRegionArea);
RecastRegion.BuildRegions(m_ctx, m_chf, cfg.minRegionArea, cfg.mergeRegionArea);
}
else if (m_partitionType == PartitionType.MONOTONE)
{
// Partition the walkable surface into simple regions without holes.
// Monotone partitioning does not need distancefield.
RecastRegion.buildRegionsMonotone(m_ctx, m_chf, cfg.minRegionArea, cfg.mergeRegionArea);
RecastRegion.BuildRegionsMonotone(m_ctx, m_chf, cfg.minRegionArea, cfg.mergeRegionArea);
}
else
{
// Partition the walkable surface into simple regions without holes.
RecastRegion.buildLayerRegions(m_ctx, m_chf, cfg.minRegionArea);
RecastRegion.BuildLayerRegions(m_ctx, m_chf, cfg.minRegionArea);
}
Assert.That(m_chf.maxDistance, Is.EqualTo(expDistance), "maxDistance");
@ -234,7 +234,7 @@ public class RecastSoloMeshTest
//
// Create contours.
ContourSet m_cset = RecastContour.buildContours(m_ctx, m_chf, cfg.maxSimplificationError, cfg.maxEdgeLen,
ContourSet m_cset = RecastContour.BuildContours(m_ctx, m_chf, cfg.maxSimplificationError, cfg.maxEdgeLen,
RecastConstants.RC_CONTOUR_TESS_WALL_EDGES);
Assert.That(m_cset.conts.Count, Is.EqualTo(expContours), "Contours");
@ -243,7 +243,7 @@ public class RecastSoloMeshTest
//
// Build polygon navmesh from the contours.
PolyMesh m_pmesh = RecastMesh.buildPolyMesh(m_ctx, m_cset, cfg.maxVertsPerPoly);
PolyMesh m_pmesh = RecastMesh.BuildPolyMesh(m_ctx, m_cset, cfg.maxVertsPerPoly);
Assert.That(m_pmesh.nverts, Is.EqualTo(expVerts), "Mesh Verts");
Assert.That(m_pmesh.npolys, Is.EqualTo(expPolys), "Mesh Polys");
@ -252,7 +252,7 @@ public class RecastSoloMeshTest
// on each polygon.
//
PolyMeshDetail m_dmesh = RecastMeshDetail.buildPolyMeshDetail(m_ctx, m_pmesh, m_chf, cfg.detailSampleDist,
PolyMeshDetail m_dmesh = RecastMeshDetail.BuildPolyMeshDetail(m_ctx, m_pmesh, m_chf, cfg.detailSampleDist,
cfg.detailSampleMaxError);
Assert.That(m_dmesh.nmeshes, Is.EqualTo(expDetMeshes), "Mesh Detail Meshes");
Assert.That(m_dmesh.nverts, Is.EqualTo(expDetVerts), "Mesh Detail Verts");
@ -260,15 +260,15 @@ public class RecastSoloMeshTest
long time2 = FrequencyWatch.Ticks;
Console.WriteLine(filename + " : " + partitionType + " " + (time2 - time) / TimeSpan.TicksPerMillisecond + " ms");
Console.WriteLine(" " + (time3 - time) / TimeSpan.TicksPerMillisecond + " ms");
saveObj(filename.Substring(0, filename.LastIndexOf('.')) + "_" + partitionType + "_detail.obj", m_dmesh);
saveObj(filename.Substring(0, filename.LastIndexOf('.')) + "_" + partitionType + ".obj", m_pmesh);
SaveObj(filename.Substring(0, filename.LastIndexOf('.')) + "_" + partitionType + "_detail.obj", m_dmesh);
SaveObj(filename.Substring(0, filename.LastIndexOf('.')) + "_" + partitionType + ".obj", m_pmesh);
foreach (var (key, millis) in m_ctx.ToList())
{
Console.WriteLine($"{key} : {millis} ms");
}
}
private void saveObj(string filename, PolyMesh mesh)
private void SaveObj(string filename, PolyMesh mesh)
{
try
{
@ -308,7 +308,7 @@ public class RecastSoloMeshTest
}
}
private void saveObj(string filename, PolyMeshDetail dmesh)
private void SaveObj(string filename, PolyMeshDetail dmesh)
{
try
{

View File

@ -26,7 +26,7 @@ using static RecastConstants;
public class RecastTest
{
[Test]
public void testClearUnwalkableTriangles()
public void TestClearUnwalkableTriangles()
{
float walkableSlopeAngle = 45;
float[] verts = { 0, 0, 0, 1, 0, 0, 0, 0, -1 };
@ -38,18 +38,18 @@ public class RecastTest
Telemetry ctx = new Telemetry();
{
int[] areas = { 42 };
Recast.clearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
Recast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Sets area ID of unwalkable triangle to RC_NULL_AREA");
}
{
int[] areas = { 42 };
Recast.clearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
Recast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(42), "Does not modify walkable triangle aread ID's");
}
{
int[] areas = { 42 };
walkableSlopeAngle = 0;
Recast.clearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
Recast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Slopes equal to the max slope are considered unwalkable.");
}
}

View File

@ -53,70 +53,70 @@ public class RecastTileMeshTest
private const int m_tileSize = 32;
[Test]
public void testDungeon()
public void TestDungeon()
{
testBuild("dungeon.obj");
TestBuild("dungeon.obj");
}
public void testBuild(string filename)
public void TestBuild(string filename)
{
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes(filename));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes(filename));
RecastBuilder builder = new RecastBuilder();
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.calcBorder(m_agentRadius, m_cellSize),
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.CalcBorder(m_agentRadius, m_cellSize),
m_partitionType, m_cellSize, m_cellHeight, m_agentMaxSlope, true, true, true, m_agentHeight, m_agentRadius,
m_agentMaxClimb, m_regionMinArea, m_regionMergeArea, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, true,
m_detailSampleDist, m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_GROUND);
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), 7, 8);
RecastBuilderResult rcResult = builder.build(geom, bcfg);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(1));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(5));
bcfg = new RecastBuilderConfig(cfg, geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), 6, 9);
rcResult = builder.build(geom, bcfg);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(7));
bcfg = new RecastBuilderConfig(cfg, geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), 2, 9);
rcResult = builder.build(geom, bcfg);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(9));
bcfg = new RecastBuilderConfig(cfg, geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), 4, 3);
rcResult = builder.build(geom, bcfg);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(3));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(6));
bcfg = new RecastBuilderConfig(cfg, geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), 2, 8);
rcResult = builder.build(geom, bcfg);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(5));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(17));
bcfg = new RecastBuilderConfig(cfg, geom.getMeshBoundsMin(), geom.getMeshBoundsMax(), 0, 8);
rcResult = builder.build(geom, bcfg);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(6));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(15));
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 7, 8);
RecastBuilderResult rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 6, 9);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(7));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 9);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(9));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 4, 3);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(6));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 8);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(17));
bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 0, 8);
rcResult = builder.Build(geom, bcfg);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
}
[Test]
public void testPerformance()
public void TestPerformance()
{
InputGeomProvider geom = ObjImporter.load(Loader.ToBytes("dungeon.obj"));
InputGeomProvider geom = ObjImporter.Load(Loader.ToBytes("dungeon.obj"));
RecastBuilder builder = new RecastBuilder();
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.calcBorder(m_agentRadius, m_cellSize),
RecastConfig cfg = new RecastConfig(true, m_tileSize, m_tileSize, RecastConfig.CalcBorder(m_agentRadius, m_cellSize),
m_partitionType, m_cellSize, m_cellHeight, m_agentMaxSlope, true, true, true, m_agentHeight, m_agentRadius,
m_agentMaxClimb, m_regionMinArea, m_regionMergeArea, m_edgeMaxLen, m_edgeMaxError, m_vertsPerPoly, true,
m_detailSampleDist, m_detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_GROUND);
for (int i = 0; i < 4; i++)
{
build(geom, builder, cfg, 1, true);
build(geom, builder, cfg, 4, true);
Build(geom, builder, cfg, 1, true);
Build(geom, builder, cfg, 4, true);
}
long t1 = FrequencyWatch.Ticks;
for (int i = 0; i < 4; i++)
{
build(geom, builder, cfg, 1, false);
Build(geom, builder, cfg, 1, false);
}
long t2 = FrequencyWatch.Ticks;
for (int i = 0; i < 4; i++)
{
build(geom, builder, cfg, 4, false);
Build(geom, builder, cfg, 4, false);
}
long t3 = FrequencyWatch.Ticks;
@ -124,37 +124,37 @@ public class RecastTileMeshTest
Console.WriteLine(" Time MT : " + (t3 - t2) / TimeSpan.TicksPerMillisecond);
}
private void build(InputGeomProvider geom, RecastBuilder builder, RecastConfig cfg, int threads, bool validate)
private void Build(InputGeomProvider geom, RecastBuilder builder, RecastConfig cfg, int threads, bool validate)
{
CancellationTokenSource cts = new CancellationTokenSource();
List<RecastBuilderResult> 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)
{
RecastBuilderResult rcResult = getTile(tiles, 7, 8);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(1));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(5));
rcResult = getTile(tiles, 6, 9);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(7));
rcResult = getTile(tiles, 2, 9);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(9));
rcResult = getTile(tiles, 4, 3);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(3));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(6));
rcResult = getTile(tiles, 2, 8);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(5));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(17));
rcResult = getTile(tiles, 0, 8);
Assert.That(rcResult.getMesh().npolys, Is.EqualTo(6));
Assert.That(rcResult.getMesh().nverts, Is.EqualTo(15));
RecastBuilderResult rcResult = GetTile(tiles, 7, 8);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
rcResult = GetTile(tiles, 6, 9);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(7));
rcResult = GetTile(tiles, 2, 9);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(9));
rcResult = GetTile(tiles, 4, 3);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(6));
rcResult = GetTile(tiles, 2, 8);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(17));
rcResult = GetTile(tiles, 0, 8);
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
}
try
{
cts.Cancel();
//executor.awaitTermination(1000, TimeUnit.HOURS);
//executor.AwaitTermination(1000, TimeUnit.HOURS);
}
catch (Exception e)
{
@ -162,7 +162,7 @@ public class RecastTileMeshTest
}
}
private RecastBuilderResult getTile(List<RecastBuilderResult> tiles, int x, int z)
private RecastBuilderResult GetTile(List<RecastBuilderResult> tiles, int x, int z)
{
return tiles.FirstOrDefault(tile => tile.tileX == x && tile.tileZ == z);
}