float[3] to Vector3f

This commit is contained in:
ikpil 2023-03-30 00:59:00 +09:00
parent 254ec50436
commit 535bbd38a4
54 changed files with 455 additions and 375 deletions

View File

@ -36,6 +36,15 @@ namespace DotRecast.Core
return dx * dx + dy * dy + dz * dz; return dx * dx + dy * dy + dz * dz;
} }
public static float vDistSqr(Vector3f v1, Vector3f v2, int i)
{
float dx = v2[i] - v1[0];
float dy = v2[i + 1] - v1[1];
float dz = v2[i + 2] - v1[2];
return dx * dx + dy * dy + dz * dz;
}
public static float[] vCross(float[] v1, float[] v2) public static float[] vCross(float[] v1, float[] v2)
{ {
Vector3f dest = new Vector3f(); Vector3f dest = new Vector3f();
@ -251,6 +260,13 @@ namespace DotRecast.Core
@out[2] = @in[2]; @out[2] = @in[2];
} }
public static void vCopy(float[] @out, Vector3f @in)
{
@out[0] = @in[0];
@out[1] = @in[1];
@out[2] = @in[2];
}
public static void vCopy(ref Vector3f @out, float[] @in) public static void vCopy(ref Vector3f @out, float[] @in)
{ {
@out.x = @in[0]; @out.x = @in[0];

View File

@ -17,6 +17,7 @@ freely, subject to the following restrictions:
*/ */
using System; using System;
using System.Numerics;
namespace DotRecast.Core namespace DotRecast.Core
{ {
@ -26,14 +27,16 @@ namespace DotRecast.Core
public float y; public float y;
public float z; public float z;
public static Vector3f Zero { get; } = new Vector3f(0, 0, 0);
public static Vector3f Of(float[] f) public static Vector3f Of(float[] f)
{ {
return new Vector3f() return new Vector3f(f[0], f[1], f[2]);
}
public static Vector3f Of(float x, float y, float z)
{ {
x = f[0], return new Vector3f(x, y, z);
y = f[1],
z = f[2],
};
} }
public Vector3f(float x, float y, float z) public Vector3f(float x, float y, float z)

View File

@ -321,7 +321,7 @@ namespace DotRecast.Detour.Crowd
/// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()] /// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()]
/// @param[in] vel The movement velocity. [(x, y, z)] /// @param[in] vel The movement velocity. [(x, y, z)]
/// @return True if the request was successfully submitted. /// @return True if the request was successfully submitted.
public bool requestMoveVelocity(CrowdAgent agent, float[] vel) public bool requestMoveVelocity(CrowdAgent agent, Vector3f vel)
{ {
// Initialize request. // Initialize request.
agent.targetRef = 0; agent.targetRef = 0;
@ -485,7 +485,7 @@ namespace DotRecast.Detour.Crowd
// ag.corridor.trimInvalidPath(agentRef, agentPos, m_navquery, // ag.corridor.trimInvalidPath(agentRef, agentPos, m_navquery,
// &m_filter); // &m_filter);
ag.boundary.reset(); ag.boundary.reset();
vCopy(ag.npos, agentPos); vCopy(ref ag.npos, agentPos);
replan = true; replan = true;
} }
@ -510,7 +510,7 @@ namespace DotRecast.Detour.Crowd
ag.targetRef = fnp.succeeded() ? fnp.result.getNearestRef() : 0L; ag.targetRef = fnp.succeeded() ? fnp.result.getNearestRef() : 0L;
if (fnp.succeeded()) if (fnp.succeeded())
{ {
vCopy(ag.targetPos, fnp.result.getNearestPos()); vCopy(ref ag.targetPos, fnp.result.getNearestPos());
} }
replan = true; replan = true;
@ -626,14 +626,14 @@ namespace DotRecast.Detour.Crowd
} }
else else
{ {
vCopy(reqPos, ag.targetPos); vCopy(ref reqPos, ag.targetPos);
} }
} }
else else
{ {
// Could not find path, start the request from current // Could not find path, start the request from current
// location. // location.
vCopy(reqPos, ag.npos); vCopy(ref reqPos, ag.npos);
reqPath = new List<long>(); reqPath = new List<long>();
reqPath.Add(path[0]); reqPath.Add(path[0]);
} }
@ -722,7 +722,7 @@ namespace DotRecast.Detour.Crowd
} }
// Apply results. // Apply results.
float[] targetPos = ag.targetPos; var targetPos = ag.targetPos;
bool valid = true; bool valid = true;
List<long> res = ag.targetPathQueryResult.path; List<long> res = ag.targetPathQueryResult.path;
@ -866,7 +866,7 @@ namespace DotRecast.Detour.Crowd
m_grid = new ProximityGrid(_config.maxAgentRadius * 3); m_grid = new ProximityGrid(_config.maxAgentRadius * 3);
foreach (CrowdAgent ag in agents) foreach (CrowdAgent ag in agents)
{ {
float[] p = ag.npos; Vector3f p = ag.npos;
float r = ag.option.radius; float r = ag.option.radius;
m_grid.addItem(ag, p[0] - r, p[2] - r, p[0] + r, p[2] + r); m_grid.addItem(ag, p[0] - r, p[2] - r, p[0] + r, p[2] + r);
} }
@ -901,7 +901,7 @@ namespace DotRecast.Detour.Crowd
_telemetry.stop("buildNeighbours"); _telemetry.stop("buildNeighbours");
} }
private List<CrowdNeighbour> getNeighbours(float[] pos, float height, float range, CrowdAgent skip, ProximityGrid grid) private List<CrowdNeighbour> getNeighbours(Vector3f pos, float height, float range, CrowdAgent skip, ProximityGrid grid)
{ {
List<CrowdNeighbour> result = new List<CrowdNeighbour>(); List<CrowdNeighbour> result = new List<CrowdNeighbour>();
HashSet<CrowdAgent> proxAgents = grid.queryItems(pos[0] - range, pos[2] - range, pos[0] + range, pos[2] + range); HashSet<CrowdAgent> proxAgents = grid.queryItems(pos[0] - range, pos[2] - range, pos[0] + range, pos[2] + range);
@ -914,7 +914,7 @@ namespace DotRecast.Detour.Crowd
} }
// Check for overlap. // Check for overlap.
float[] diff = vSub(pos, ag.npos); Vector3f diff = vSub(pos, ag.npos);
if (Math.Abs(diff[1]) >= (height + ag.option.height) / 2.0f) if (Math.Abs(diff[1]) >= (height + ag.option.height) / 2.0f)
{ {
continue; continue;
@ -958,15 +958,15 @@ namespace DotRecast.Detour.Crowd
// and short cut to there. // and short cut to there.
if ((ag.option.updateFlags & CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS) != 0 && ag.corners.Count > 0) if ((ag.option.updateFlags & CrowdAgentParams.DT_CROWD_OPTIMIZE_VIS) != 0 && ag.corners.Count > 0)
{ {
float[] target = ag.corners[Math.Min(1, ag.corners.Count - 1)].getPos(); Vector3f target = ag.corners[Math.Min(1, ag.corners.Count - 1)].getPos();
ag.corridor.optimizePathVisibility(target, ag.option.pathOptimizationRange, navQuery, ag.corridor.optimizePathVisibility(target, ag.option.pathOptimizationRange, navQuery,
m_filters[ag.option.queryFilterType]); m_filters[ag.option.queryFilterType]);
// Copy data for debug purposes. // Copy data for debug purposes.
if (debugAgent == ag) if (debugAgent == ag)
{ {
vCopy(debug.optStart, ag.corridor.getPos()); vCopy(ref debug.optStart, ag.corridor.getPos());
vCopy(debug.optEnd, target); vCopy(ref debug.optEnd, target);
} }
} }
else else
@ -974,8 +974,8 @@ namespace DotRecast.Detour.Crowd
// Copy data for debug purposes. // Copy data for debug purposes.
if (debugAgent == ag) if (debugAgent == ag)
{ {
vSet(debug.optStart, 0, 0, 0); vSet(ref debug.optStart, 0, 0, 0);
vSet(debug.optEnd, 0, 0, 0); vSet(ref debug.optEnd, 0, 0, 0);
} }
} }
} }
@ -1051,7 +1051,7 @@ namespace DotRecast.Detour.Crowd
if (ag.targetState == CrowdAgent.MoveRequestState.DT_CROWDAGENT_TARGET_VELOCITY) if (ag.targetState == CrowdAgent.MoveRequestState.DT_CROWDAGENT_TARGET_VELOCITY)
{ {
vCopy(dvel, ag.targetPos); vCopy(ref dvel, ag.targetPos);
ag.desiredSpeed = vLen(ag.targetPos); ag.desiredSpeed = vLen(ag.targetPos);
} }
else else
@ -1088,7 +1088,7 @@ namespace DotRecast.Detour.Crowd
{ {
CrowdAgent nei = ag.neis[j].agent; CrowdAgent nei = ag.neis[j].agent;
float[] diff = vSub(ag.npos, nei.npos); Vector3f diff = vSub(ag.npos, nei.npos);
diff[1] = 0; diff[1] = 0;
float distSqr = vLenSqr(diff); float distSqr = vLenSqr(diff);
@ -1124,7 +1124,7 @@ namespace DotRecast.Detour.Crowd
} }
// Set the desired velocity. // Set the desired velocity.
vCopy(ag.dvel, dvel); vCopy(ref ag.dvel, dvel);
} }
_telemetry.stop("calculateSteering"); _telemetry.stop("calculateSteering");
@ -1155,15 +1155,15 @@ namespace DotRecast.Detour.Crowd
// Append neighbour segments as obstacles. // Append neighbour segments as obstacles.
for (int j = 0; j < ag.boundary.getSegmentCount(); ++j) for (int j = 0; j < ag.boundary.getSegmentCount(); ++j)
{ {
float[] s = ag.boundary.getSegment(j); Vector3f[] s = ag.boundary.getSegment(j);
Vector3f s3 = new Vector3f(); Vector3f s3 = s[1];
Array.Copy(s, 3, s3, 0, 3); //Array.Copy(s, 3, s3, 0, 3);
if (triArea2D(ag.npos, s, s3) < 0.0f) if (triArea2D(ag.npos, s[0], s3) < 0.0f)
{ {
continue; continue;
} }
m_obstacleQuery.addSegment(s, s3); m_obstacleQuery.addSegment(s[0], s3);
} }
ObstacleAvoidanceDebugData vod = null; ObstacleAvoidanceDebugData vod = null;
@ -1180,14 +1180,14 @@ namespace DotRecast.Detour.Crowd
if (adaptive) if (adaptive)
{ {
Tuple<int, float[]> nsnvel = m_obstacleQuery.sampleVelocityAdaptive(ag.npos, ag.option.radius, var nsnvel = m_obstacleQuery.sampleVelocityAdaptive(ag.npos, ag.option.radius,
ag.desiredSpeed, ag.vel, ag.dvel, option, vod); ag.desiredSpeed, ag.vel, ag.dvel, option, vod);
ns = nsnvel.Item1; ns = nsnvel.Item1;
ag.nvel = nsnvel.Item2; ag.nvel = nsnvel.Item2;
} }
else else
{ {
Tuple<int, float[]> nsnvel = m_obstacleQuery.sampleVelocityGrid(ag.npos, ag.option.radius, var nsnvel = m_obstacleQuery.sampleVelocityGrid(ag.npos, ag.option.radius,
ag.desiredSpeed, ag.vel, ag.dvel, option, vod); ag.desiredSpeed, ag.vel, ag.dvel, option, vod);
ns = nsnvel.Item1; ns = nsnvel.Item1;
ag.nvel = nsnvel.Item2; ag.nvel = nsnvel.Item2;
@ -1198,7 +1198,7 @@ namespace DotRecast.Detour.Crowd
else else
{ {
// If not using velocity planning, new velocity is directly the desired velocity. // If not using velocity planning, new velocity is directly the desired velocity.
vCopy(ag.nvel, ag.dvel); vCopy(ref ag.nvel, ag.dvel);
} }
} }
@ -1234,7 +1234,7 @@ namespace DotRecast.Detour.Crowd
continue; continue;
} }
vSet(ag.disp, 0, 0, 0); vSet(ref ag.disp, 0, 0, 0);
float w = 0; float w = 0;
@ -1242,7 +1242,7 @@ namespace DotRecast.Detour.Crowd
{ {
CrowdAgent nei = ag.neis[j].agent; CrowdAgent nei = ag.neis[j].agent;
long idx1 = nei.idx; long idx1 = nei.idx;
float[] diff = vSub(ag.npos, nei.npos); Vector3f diff = vSub(ag.npos, nei.npos);
diff[1] = 0; diff[1] = 0;
float dist = vLenSqr(diff); float dist = vLenSqr(diff);
@ -1258,11 +1258,11 @@ namespace DotRecast.Detour.Crowd
// Agents on top of each other, try to choose diverging separation directions. // Agents on top of each other, try to choose diverging separation directions.
if (idx0 > idx1) if (idx0 > idx1)
{ {
vSet(diff, -ag.dvel[2], 0, ag.dvel[0]); vSet(ref diff, -ag.dvel[2], 0, ag.dvel[0]);
} }
else else
{ {
vSet(diff, ag.dvel[2], 0, -ag.dvel[0]); vSet(ref diff, ag.dvel[2], 0, -ag.dvel[0]);
} }
pen = 0.01f; pen = 0.01f;
@ -1311,7 +1311,7 @@ namespace DotRecast.Detour.Crowd
// Move along navmesh. // Move along navmesh.
ag.corridor.movePosition(ag.npos, navQuery, m_filters[ag.option.queryFilterType]); ag.corridor.movePosition(ag.npos, navQuery, m_filters[ag.option.queryFilterType]);
// Get valid constrained position back. // Get valid constrained position back.
vCopy(ag.npos, ag.corridor.getPos()); vCopy(ref ag.npos, ag.corridor.getPos());
// If not using path, truncate the corridor to just one poly. // If not using path, truncate the corridor to just one poly.
if (ag.targetState == CrowdAgent.MoveRequestState.DT_CROWDAGENT_TARGET_NONE if (ag.targetState == CrowdAgent.MoveRequestState.DT_CROWDAGENT_TARGET_NONE
@ -1361,8 +1361,8 @@ namespace DotRecast.Detour.Crowd
} }
// Update velocity. // Update velocity.
vSet(ag.vel, 0, 0, 0); vSet(ref ag.vel, 0, 0, 0);
vSet(ag.dvel, 0, 0, 0); vSet(ref ag.dvel, 0, 0, 0);
} }
_telemetry.stop("updateOffMeshConnections"); _telemetry.stop("updateOffMeshConnections");

View File

@ -33,7 +33,7 @@ namespace DotRecast.Detour.Crowd
private class Segment private class Segment
{ {
/** Segment start/end */ /** Segment start/end */
public float[] s = new float[6]; public Vector3f[] s = new Vector3f[2];
/** Distance for pruning. */ /** Distance for pruning. */
public float d; public float d;
@ -59,7 +59,13 @@ namespace DotRecast.Detour.Crowd
{ {
// Insert neighbour based on the distance. // Insert neighbour based on the distance.
Segment seg = new Segment(); Segment seg = new Segment();
Array.Copy(s, seg.s, 6); seg.s[0].x = s[0];
seg.s[0].y = s[1];
seg.s[0].z = s[2];
seg.s[1].x = s[3];
seg.s[1].y = s[4];
seg.s[1].z = s[5];
//Array.Copy(s, seg.s, 6);
seg.d = dist; seg.d = dist;
if (0 == m_segs.Count) if (0 == m_segs.Count)
{ {
@ -159,7 +165,7 @@ namespace DotRecast.Detour.Crowd
return m_center; return m_center;
} }
public float[] getSegment(int j) public Vector3f[] getSegment(int j)
{ {
return m_segs[j].s; return m_segs[j].s;
} }

View File

@ -169,6 +169,7 @@ namespace DotRecast.Detour.Crowd
{ {
if (m_nsegments >= m_maxSegments) if (m_nsegments >= m_maxSegments)
return; return;
ObstacleSegment seg = m_segments[m_nsegments++]; ObstacleSegment seg = m_segments[m_nsegments++];
vCopy(ref seg.p, p); vCopy(ref seg.p, p);
vCopy(ref seg.q, q); vCopy(ref seg.q, q);
@ -194,7 +195,7 @@ namespace DotRecast.Detour.Crowd
return m_segments[i]; return m_segments[i];
} }
private void prepare(Vector3f pos, float[] dvel) private void prepare(Vector3f pos, Vector3f dvel)
{ {
// Prepare obstacles // Prepare obstacles
for (int i = 0; i < m_ncircles; ++i) for (int i = 0; i < m_ncircles; ++i)
@ -235,10 +236,10 @@ namespace DotRecast.Detour.Crowd
} }
} }
SweepCircleCircleResult sweepCircleCircle(float[] c0, float r0, float[] v, float[] c1, float r1) SweepCircleCircleResult sweepCircleCircle(Vector3f c0, float r0, Vector3f v, Vector3f c1, float r1)
{ {
const float EPS = 0.0001f; const float EPS = 0.0001f;
float[] s = vSub(c1, c0); Vector3f s = vSub(c1, c0);
float r = r0 + r1; float r = r0 + r1;
float c = vDot2D(s, s) - r * r; float c = vDot2D(s, s) - r * r;
float a = vDot2D(v, v); float a = vDot2D(v, v);
@ -255,10 +256,10 @@ namespace DotRecast.Detour.Crowd
return new SweepCircleCircleResult(true, (b - rd) * a, (b + rd) * a); return new SweepCircleCircleResult(true, (b - rd) * a, (b + rd) * a);
} }
Tuple<bool, float> isectRaySeg(float[] ap, float[] u, float[] bp, float[] bq) Tuple<bool, float> isectRaySeg(Vector3f ap, Vector3f u, Vector3f bp, Vector3f bq)
{ {
float[] v = vSub(bq, bp); Vector3f v = vSub(bq, bp);
float[] w = vSub(ap, bp); Vector3f w = vSub(ap, bp);
float d = vPerp2D(u, v); float d = vPerp2D(u, v);
if (Math.Abs(d) < 1e-6f) if (Math.Abs(d) < 1e-6f)
return Tuple.Create(false, 0f); return Tuple.Create(false, 0f);
@ -282,7 +283,7 @@ namespace DotRecast.Detour.Crowd
* @param minPenalty * @param minPenalty
* threshold penalty for early out * threshold penalty for early out
*/ */
private float processSample(float[] vcand, float cs, float[] pos, float rad, float[] vel, float[] dvel, private float processSample(Vector3f vcand, float cs, Vector3f pos, float rad, Vector3f vel, Vector3f dvel,
float minPenalty, ObstacleAvoidanceDebugData debug) float minPenalty, ObstacleAvoidanceDebugData debug)
{ {
// penalty for straying away from the desired and current velocities // penalty for straying away from the desired and current velocities
@ -306,7 +307,7 @@ namespace DotRecast.Detour.Crowd
ObstacleCircle cir = m_circles[i]; ObstacleCircle cir = m_circles[i];
// RVO // RVO
float[] vab = vScale(vcand, 2); Vector3f vab = vScale(vcand, 2);
vab = vSub(vab, vel); vab = vSub(vab, vel);
vab = vSub(vab, cir.vel); vab = vSub(vab, cir.vel);
@ -346,7 +347,7 @@ namespace DotRecast.Detour.Crowd
if (seg.touch) if (seg.touch)
{ {
// Special case when the agent is very close to the segment. // Special case when the agent is very close to the segment.
float[] sdir = vSub(seg.q, seg.p); Vector3f sdir = vSub(seg.q, seg.p);
Vector3f snorm = new Vector3f(); Vector3f snorm = new Vector3f();
snorm[0] = -sdir[2]; snorm[0] = -sdir[2];
snorm[2] = sdir[0]; snorm[2] = sdir[0];
@ -391,7 +392,7 @@ namespace DotRecast.Detour.Crowd
return penalty; return penalty;
} }
public Tuple<int, float[]> sampleVelocityGrid(float[] pos, float rad, float vmax, float[] vel, float[] dvel, public Tuple<int, Vector3f> sampleVelocityGrid(Vector3f pos, float rad, float vmax, Vector3f vel, Vector3f dvel,
ObstacleAvoidanceParams option, ObstacleAvoidanceDebugData debug) ObstacleAvoidanceParams option, ObstacleAvoidanceDebugData debug)
{ {
prepare(pos, dvel); prepare(pos, dvel);
@ -401,7 +402,7 @@ namespace DotRecast.Detour.Crowd
m_invVmax = vmax > 0 ? 1.0f / vmax : float.MaxValue; m_invVmax = vmax > 0 ? 1.0f / vmax : float.MaxValue;
Vector3f nvel = new Vector3f(); Vector3f nvel = new Vector3f();
vSet(nvel, 0f, 0f, 0f); vSet(ref nvel, 0f, 0f, 0f);
if (debug != null) if (debug != null)
debug.reset(); debug.reset();
@ -419,7 +420,7 @@ namespace DotRecast.Detour.Crowd
for (int x = 0; x < m_params.gridSize; ++x) for (int x = 0; x < m_params.gridSize; ++x)
{ {
Vector3f vcand = new Vector3f(); Vector3f vcand = new Vector3f();
vSet(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[0]) + sqr(vcand[2]) > sqr(vmax + cs / 2)) if (sqr(vcand[0]) + sqr(vcand[2]) > sqr(vmax + cs / 2))
continue; continue;
@ -429,7 +430,7 @@ namespace DotRecast.Detour.Crowd
if (penalty < minPenalty) if (penalty < minPenalty)
{ {
minPenalty = penalty; minPenalty = penalty;
vCopy(nvel, vcand); vCopy(ref nvel, vcand);
} }
} }
} }
@ -449,7 +450,7 @@ namespace DotRecast.Detour.Crowd
} }
// vector normalization that ignores the y-component. // vector normalization that ignores the y-component.
float[] dtRotate2D(float[] v, float ang) Vector3f dtRotate2D(float[] v, float ang)
{ {
Vector3f dest = new Vector3f(); Vector3f dest = new Vector3f();
float c = (float)Math.Cos(ang); float c = (float)Math.Cos(ang);
@ -462,8 +463,8 @@ namespace DotRecast.Detour.Crowd
static readonly float DT_PI = 3.14159265f; static readonly float DT_PI = 3.14159265f;
public Tuple<int, float[]> sampleVelocityAdaptive(float[] pos, float rad, float vmax, float[] vel, public Tuple<int, Vector3f> sampleVelocityAdaptive(Vector3f pos, float rad, float vmax, Vector3f vel,
float[] dvel, ObstacleAvoidanceParams option, ObstacleAvoidanceDebugData debug) Vector3f dvel, ObstacleAvoidanceParams option, ObstacleAvoidanceDebugData debug)
{ {
prepare(pos, dvel); prepare(pos, dvel);
m_params = option; m_params = option;
@ -472,7 +473,7 @@ namespace DotRecast.Detour.Crowd
m_invVmax = vmax > 0 ? 1.0f / vmax : float.MaxValue; m_invVmax = vmax > 0 ? 1.0f / vmax : float.MaxValue;
Vector3f nvel = new Vector3f(); Vector3f nvel = new Vector3f();
vSet(nvel, 0f, 0f, 0f); vSet(ref nvel, 0f, 0f, 0f);
if (debug != null) if (debug != null)
debug.reset(); debug.reset();
@ -495,7 +496,7 @@ namespace DotRecast.Detour.Crowd
float[] ddir = new float[6]; float[] ddir = new float[6];
vCopy(ddir, dvel); vCopy(ddir, dvel);
dtNormalize2D(ddir); dtNormalize2D(ddir);
float[] rotated = dtRotate2D(ddir, da * 0.5f); // rotated by da/2 Vector3f rotated = dtRotate2D(ddir, da * 0.5f); // rotated by da/2
ddir[3] = rotated[0]; ddir[3] = rotated[0];
ddir[4] = rotated[1]; ddir[4] = rotated[1];
ddir[5] = rotated[2]; ddir[5] = rotated[2];
@ -539,18 +540,18 @@ namespace DotRecast.Detour.Crowd
// Start sampling. // Start sampling.
float cr = vmax * (1.0f - m_params.velBias); float cr = vmax * (1.0f - m_params.velBias);
Vector3f res = new Vector3f(); Vector3f res = new Vector3f();
vSet(res, dvel[0] * m_params.velBias, 0, dvel[2] * m_params.velBias); vSet(ref res, dvel[0] * m_params.velBias, 0, dvel[2] * m_params.velBias);
int ns = 0; int ns = 0;
for (int k = 0; k < depth; ++k) for (int k = 0; k < depth; ++k)
{ {
float minPenalty = float.MaxValue; float minPenalty = float.MaxValue;
Vector3f bvel = new Vector3f(); Vector3f bvel = new Vector3f();
vSet(bvel, 0, 0, 0); vSet(ref bvel, 0, 0, 0);
for (int i = 0; i < npat; ++i) for (int i = 0; i < npat; ++i)
{ {
Vector3f vcand = new Vector3f(); Vector3f vcand = new Vector3f();
vSet(vcand, res[0] + pat[i * 2 + 0] * cr, 0f, res[2] + pat[i * 2 + 1] * cr); vSet(ref vcand, res[0] + pat[i * 2 + 0] * cr, 0f, res[2] + pat[i * 2 + 1] * cr);
if (sqr(vcand[0]) + sqr(vcand[2]) > sqr(vmax + 0.001f)) if (sqr(vcand[0]) + sqr(vcand[2]) > sqr(vmax + 0.001f))
continue; continue;
@ -559,16 +560,16 @@ namespace DotRecast.Detour.Crowd
if (penalty < minPenalty) if (penalty < minPenalty)
{ {
minPenalty = penalty; minPenalty = penalty;
vCopy(bvel, vcand); vCopy(ref bvel, vcand);
} }
} }
vCopy(res, bvel); vCopy(ref res, bvel);
cr *= 0.5f; cr *= 0.5f;
} }
vCopy(nvel, res); vCopy(ref nvel, res);
return Tuple.Create(ns, nvel); return Tuple.Create(ns, nvel);
} }

View File

@ -460,11 +460,10 @@ namespace DotRecast.Detour.Crowd
* @param filter * @param filter
* The filter to apply to the operation. * The filter to apply to the operation.
*/ */
public bool moveTargetPosition(float[] npos, NavMeshQuery navquery, QueryFilter filter) public bool moveTargetPosition(Vector3f npos, NavMeshQuery navquery, QueryFilter filter)
{ {
// Move along navmesh and update new position. // Move along navmesh and update new position.
Result<MoveAlongSurfaceResult> masResult = navquery.moveAlongSurface(m_path[m_path.Count - 1], m_target, Result<MoveAlongSurfaceResult> masResult = navquery.moveAlongSurface(m_path[m_path.Count - 1], m_target, npos, filter);
npos, filter);
if (masResult.succeeded()) if (masResult.succeeded())
{ {
m_path = mergeCorridorEndMoved(m_path, masResult.result.getVisited()); m_path = mergeCorridorEndMoved(m_path, masResult.result.getVisited());
@ -474,7 +473,7 @@ namespace DotRecast.Detour.Crowd
* float h = m_target[1]; navquery->getPolyHeight(m_path[m_npath-1], * float h = m_target[1]; navquery->getPolyHeight(m_path[m_npath-1],
* result, &h); result[1] = h; * result, &h); result[1] = h;
*/ */
vCopy(m_target, masResult.result.getResultPos()); vCopy(ref m_target, masResult.result.getResultPos());
return true; return true;
} }
@ -528,7 +527,7 @@ namespace DotRecast.Detour.Crowd
if (n == 0) if (n == 0)
{ {
// The first polyref is bad, use current safe values. // The first polyref is bad, use current safe values.
vCopy(m_pos, safePos); vCopy(ref m_pos, safePos);
m_path.Clear(); m_path.Clear();
m_path.Add(safeRef); m_path.Add(safeRef);
} }
@ -539,10 +538,10 @@ namespace DotRecast.Detour.Crowd
} }
// Clamp target pos to last poly // Clamp target pos to last poly
Result<float[]> 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()) if (result.succeeded())
{ {
vCopy(m_target, result.result); vCopy(ref m_target, result.result);
} }
} }
@ -579,7 +578,7 @@ namespace DotRecast.Detour.Crowd
* *
* @return The current position within the corridor. * @return The current position within the corridor.
*/ */
public float[] getPos() public Vector3f getPos()
{ {
return m_pos; return m_pos;
} }
@ -589,7 +588,7 @@ namespace DotRecast.Detour.Crowd
* *
* @return The current target within the corridor. * @return The current target within the corridor.
*/ */
public float[] getTarget() public Vector3f getTarget()
{ {
return m_target; return m_target;
} }

View File

@ -19,6 +19,7 @@ freely, subject to the following restrictions:
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core;
namespace DotRecast.Detour.Crowd namespace DotRecast.Detour.Crowd
{ {
@ -76,7 +77,7 @@ namespace DotRecast.Detour.Crowd
} }
} }
public PathQueryResult request(long startRef, long endRef, float[] startPos, float[] endPos, QueryFilter filter) public PathQueryResult request(long startRef, long endRef, Vector3f startPos, Vector3f endPos, QueryFilter filter)
{ {
if (queue.Count >= config.pathQueueSize) if (queue.Count >= config.pathQueueSize)
{ {

View File

@ -80,7 +80,7 @@ namespace DotRecast.Detour.Crowd.Tracking
normalizeArray(m_tpen, m_nsamples); normalizeArray(m_tpen, m_nsamples);
} }
public void addSample(float[] 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) if (m_nsamples >= m_maxSamples)
return; return;

View File

@ -17,17 +17,18 @@ freely, subject to the following restrictions:
*/ */
using System; using System;
using DotRecast.Core;
using DotRecast.Recast; using DotRecast.Recast;
namespace DotRecast.Detour.Dynamic.Colliders namespace DotRecast.Detour.Dynamic.Colliders
{ {
public class CapsuleCollider : AbstractCollider public class CapsuleCollider : AbstractCollider
{ {
private readonly float[] start; private readonly Vector3f start;
private readonly float[] end; private readonly Vector3f end;
private readonly float radius; private readonly float radius;
public CapsuleCollider(float[] start, float[] end, float radius, int area, float flagMergeThreshold) : 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.start = start;
@ -41,7 +42,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
telemetry); telemetry);
} }
private static float[] bounds(float[] start, float[] end, float radius) private static float[] bounds(Vector3f start, Vector3f end, float radius)
{ {
return new float[] return new float[]
{ {

View File

@ -17,17 +17,18 @@ freely, subject to the following restrictions:
*/ */
using System; using System;
using DotRecast.Core;
using DotRecast.Recast; using DotRecast.Recast;
namespace DotRecast.Detour.Dynamic.Colliders namespace DotRecast.Detour.Dynamic.Colliders
{ {
public class CylinderCollider : AbstractCollider public class CylinderCollider : AbstractCollider
{ {
private readonly float[] start; private readonly Vector3f start;
private readonly float[] end; private readonly Vector3f end;
private readonly float radius; private readonly float radius;
public CylinderCollider(float[] start, float[] end, float radius, int area, float flagMergeThreshold) : 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.start = start;
@ -41,7 +42,7 @@ namespace DotRecast.Detour.Dynamic.Colliders
telemetry); telemetry);
} }
private static float[] bounds(float[] start, float[] end, float radius) private static float[] bounds(Vector3f start, Vector3f end, float radius)
{ {
return new float[] return new float[]
{ {

View File

@ -17,16 +17,17 @@ freely, subject to the following restrictions:
*/ */
using System; using System;
using DotRecast.Core;
using DotRecast.Recast; using DotRecast.Recast;
namespace DotRecast.Detour.Dynamic.Colliders namespace DotRecast.Detour.Dynamic.Colliders
{ {
public class SphereCollider : AbstractCollider public class SphereCollider : AbstractCollider
{ {
private readonly float[] center; private readonly Vector3f center;
private readonly float radius; private readonly float radius;
public SphereCollider(float[] center, float radius, int area, float flagMergeThreshold) : 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.center = center;
@ -39,11 +40,15 @@ namespace DotRecast.Detour.Dynamic.Colliders
telemetry); telemetry);
} }
private static float[] bounds(float[] center, float radius) private static float[] bounds(Vector3f center, float radius)
{ {
return new float[] return new float[]
{ {
center[0] - radius, center[1] - radius, center[2] - radius, center[0] + radius, center[1] + radius, center[0] - radius,
center[1] - radius,
center[2] - radius,
center[0] + radius,
center[1] + radius,
center[2] + radius center[2] + radius
}; };
} }

View File

@ -190,6 +190,12 @@ public class DebugDraw
getOpenGlDraw().vertex(pos, color); getOpenGlDraw().vertex(pos, color);
} }
public void vertex(Vector3f pos, int 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);
@ -254,12 +260,12 @@ public class DebugDraw
float dz = z1 - z0; float dz = z1 - z0;
float len = (float)Math.Sqrt(dx * dx + dy * dy + dz * dz); float len = (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
Vector3f prev = new Vector3f(); Vector3f prev = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, PAD, prev); evalArc(x0, y0, z0, dx, dy, dz, len * h, PAD, ref prev);
for (int i = 1; i <= NUM_ARC_PTS; ++i) for (int i = 1; i <= NUM_ARC_PTS; ++i)
{ {
float u = PAD + i * ARC_PTS_SCALE; float u = PAD + i * ARC_PTS_SCALE;
Vector3f pt = new Vector3f(); Vector3f pt = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, u, pt); evalArc(x0, y0, z0, dx, dy, dz, len * h, u, ref pt);
vertex(prev[0], prev[1], prev[2], col); vertex(prev[0], prev[1], prev[2], col);
vertex(pt[0], pt[1], pt[2], col); vertex(pt[0], pt[1], pt[2], col);
prev[0] = pt[0]; prev[0] = pt[0];
@ -270,22 +276,24 @@ public class DebugDraw
// End arrows // End arrows
if (as0 > 0.001f) if (as0 > 0.001f)
{ {
Vector3f p = new Vector3f(), q = new float[3]; Vector3f p = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, PAD, p); Vector3f q = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, PAD + 0.05f, q); 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); appendArrowHead(p, q, as0, col);
} }
if (as1 > 0.001f) if (as1 > 0.001f)
{ {
Vector3f p = new Vector3f(), q = new float[3]; Vector3f p = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, 1 - PAD, p); Vector3f q = new Vector3f();
evalArc(x0, y0, z0, dx, dy, dz, len * h, 1 - (PAD + 0.05f), q); 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); appendArrowHead(p, q, as1, col);
} }
} }
private void evalArc(float x0, float y0, float z0, float dx, float dy, float dz, float h, float u, float[] res) private void evalArc(float x0, float y0, float z0, float dx, float dy, float dz, float h, float u, ref Vector3f res)
{ {
res[0] = x0 + dx * u; res[0] = x0 + dx * u;
res[1] = y0 + dy * u + h * (1 - (u * 2 - 1) * (u * 2 - 1)); res[1] = y0 + dy * u + h * (1 - (u * 2 - 1) * (u * 2 - 1));
@ -376,15 +384,15 @@ public class DebugDraw
vertex(x1, y1, z1, col); vertex(x1, y1, z1, col);
// End arrows // End arrows
float[] p = new float[] { x0, y0, z0 }; Vector3f p = Vector3f.Of(x0, y0, z0);
float[] q = new float[] { x1, y1, z1 }; Vector3f q = Vector3f.Of(x1, y1, z1);
if (as0 > 0.001f) if (as0 > 0.001f)
appendArrowHead(p, q, as0, col); appendArrowHead(p, q, as0, col);
if (as1 > 0.001f) if (as1 > 0.001f)
appendArrowHead(q, p, as1, col); appendArrowHead(q, p, as1, col);
} }
void appendArrowHead(float[] p, float[] q, float s, int col) void appendArrowHead(Vector3f p, Vector3f q, float s, int col)
{ {
float eps = 0.001f; float eps = 0.001f;
if (vdistSqr(p, q) < eps * eps) if (vdistSqr(p, q) < eps * eps)
@ -392,12 +400,14 @@ public class DebugDraw
return; return;
} }
Vector3f ax = new Vector3f(), ay = { 0, 1, 0 }, az = new float[3]; Vector3f ax = new Vector3f();
vsub(az, q, p); Vector3f ay = Vector3f.Of(0, 1, 0);
vnormalize(az); Vector3f az = new Vector3f();
vcross(ax, ay, az); vsub(ref az, q, p);
vcross(ay, az, ax); vnormalize(ref az);
vnormalize(ay); vcross(ref ax, ay, az);
vcross(ref ay, az, ax);
vnormalize(ref ay);
vertex(p, col); vertex(p, col);
// vertex(p[0]+az[0]*s+ay[0]*s/2, p[1]+az[1]*s+ay[1]*s/2, p[2]+az[2]*s+ay[2]*s/2, col); // vertex(p[0]+az[0]*s+ay[0]*s/2, p[1]+az[1]*s+ay[1]*s/2, p[2]+az[2]*s+ay[2]*s/2, col);
@ -408,14 +418,14 @@ public class DebugDraw
vertex(p[0] + az[0] * s - ax[0] * s / 3, p[1] + az[1] * s - ax[1] * s / 3, p[2] + az[2] * s - ax[2] * s / 3, col); vertex(p[0] + az[0] * s - ax[0] * s / 3, p[1] + az[1] * s - ax[1] * s / 3, p[2] + az[2] * s - ax[2] * s / 3, col);
} }
public void vcross(float[] dest, float[] v1, float[] v2) public void vcross(ref Vector3f dest, Vector3f v1, Vector3f v2)
{ {
dest[0] = v1[1] * v2[2] - v1[2] * v2[1]; dest[0] = v1[1] * v2[2] - v1[2] * v2[1];
dest[1] = v1[2] * v2[0] - v1[0] * v2[2]; dest[1] = v1[2] * v2[0] - v1[0] * v2[2];
dest[2] = v1[0] * v2[1] - v1[1] * v2[0]; dest[2] = v1[0] * v2[1] - v1[1] * v2[0];
} }
public void vnormalize(float[] v) public void vnormalize(ref Vector3f v)
{ {
float d = (float)(1.0f / Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2])); float d = (float)(1.0f / Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
v[0] *= d; v[0] *= d;
@ -423,14 +433,14 @@ public class DebugDraw
v[2] *= d; v[2] *= d;
} }
public void vsub(float[] dest, float[] v1, float[] v2) public void vsub(ref Vector3f dest, Vector3f v1, Vector3f v2)
{ {
dest[0] = v1[0] - v2[0]; dest[0] = v1[0] - v2[0];
dest[1] = v1[1] - v2[1]; dest[1] = v1[1] - v2[1];
dest[2] = v1[2] - v2[2]; dest[2] = v1[2] - v2[2];
} }
public float vdistSqr(float[] v1, float[] v2) public float vdistSqr(Vector3f v1, Vector3f v2)
{ {
float x = v1[0] - v2[0]; float x = v1[0] - v2[0];
float y = v1[1] - v2[1]; float y = v1[1] - v2[1];
@ -578,7 +588,7 @@ public class DebugDraw
return _projectionMatrix; return _projectionMatrix;
} }
public float[] viewMatrix(float[] cameraPos, float[] cameraEulers) public float[] viewMatrix(Vector3f cameraPos, float[] cameraEulers)
{ {
float[] rx = GLU.build_4x4_rotation_matrix(cameraEulers[0], 1, 0, 0); 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[] ry = GLU.build_4x4_rotation_matrix(cameraEulers[1], 0, 1, 0);
@ -637,11 +647,6 @@ public class DebugDraw
return new float[] { px, py, pz, pw }; return new float[] { px, py, pz, pw };
} }
public bool frustumTest(float[] bmin, float[] bmax)
{
return frustumTest(new float[] { bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2] });
}
public bool frustumTest(float[] bounds) public bool frustumTest(float[] bounds)
{ {
foreach (float[] plane in frustumPlanes) foreach (float[] plane in frustumPlanes)
@ -693,4 +698,9 @@ public class DebugDraw
return true; return true;
} }
public bool frustumTest(Vector3f bmin, Vector3f bmax)
{
return frustumTest(new float[] { bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2] });
}
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using DotRecast.Core;
using Silk.NET.OpenGL; using Silk.NET.OpenGL;
namespace DotRecast.Recast.Demo.Draw; namespace DotRecast.Recast.Demo.Draw;
@ -324,6 +325,12 @@ public class ModernOpenGLDraw : OpenGLDraw
vertices.Add(new OpenGLVertex(pos, color)); vertices.Add(new OpenGLVertex(pos, color));
} }
public void vertex(Vector3f pos, int color)
{
vertices.Add(new OpenGLVertex(pos, color));
}
public void vertex(float[] pos, int color, float[] uv) public void vertex(float[] pos, int color, float[] uv)
{ {
vertices.Add(new OpenGLVertex(pos, uv, color)); vertices.Add(new OpenGLVertex(pos, uv, color));

View File

@ -1,3 +1,4 @@
using DotRecast.Core;
using Silk.NET.OpenGL; using Silk.NET.OpenGL;
namespace DotRecast.Recast.Demo.Draw; namespace DotRecast.Recast.Demo.Draw;
@ -15,6 +16,7 @@ public interface OpenGLDraw
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(float[] pos, int color);
void vertex(Vector3f pos, int color);
void vertex(float[] pos, int color, float[] uv); void vertex(float[] pos, int color, float[] uv);

View File

@ -25,6 +25,12 @@ public struct OpenGLVertex
{ {
} }
public OpenGLVertex(Vector3f pos, int color) :
this(pos[0], pos[1], pos[2], 0f, 0f, color)
{
}
public OpenGLVertex(float x, float y, float z, int color) : public OpenGLVertex(float x, float y, float z, int color) :
this(x, y, z, 0f, 0f, color) this(x, y, z, 0f, 0f, color)
{ {

View File

@ -20,6 +20,7 @@ freely, subject to the following restrictions:
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core;
using DotRecast.Detour; using DotRecast.Detour;
using DotRecast.Recast.Demo.Builder; using DotRecast.Recast.Demo.Builder;
using Silk.NET.OpenGL; using Silk.NET.OpenGL;
@ -529,7 +530,7 @@ public class RecastDebugDraw : DebugDraw
{ {
float alpha = 1f; float alpha = 1f;
float[] orig = cset.bmin; Vector3f orig = cset.bmin;
float cs = cset.cs; float cs = cset.cs;
float ch = cset.ch; float ch = cset.ch;
@ -540,7 +541,7 @@ public class RecastDebugDraw : DebugDraw
for (int i = 0; i < cset.conts.Count; ++i) for (int i = 0; i < cset.conts.Count; ++i)
{ {
Contour cont = cset.conts[i]; Contour cont = cset.conts[i];
float[] pos = getContourCenter(cont, orig, cs, ch); Vector3f pos = getContourCenter(cont, orig, cs, ch);
for (int j = 0; j < cont.nverts; ++j) for (int j = 0; j < cont.nverts; ++j)
{ {
int v = j * 4; int v = j * 4;
@ -552,7 +553,7 @@ public class RecastDebugDraw : DebugDraw
Contour cont2 = findContourFromSet(cset, (short)cont.verts[v + 3]); Contour cont2 = findContourFromSet(cset, (short)cont.verts[v + 3]);
if (cont2 != null) if (cont2 != null)
{ {
float[] pos2 = getContourCenter(cont2, orig, cs, ch); Vector3f pos2 = getContourCenter(cont2, orig, cs, ch);
appendArc(pos[0], pos[1], pos[2], pos2[0], pos2[1], pos2[2], 0.25f, 0.6f, 0.6f, color); appendArc(pos[0], pos[1], pos[2], pos2[0], pos2[1], pos2[2], 0.25f, 0.6f, 0.6f, color);
} }
} }
@ -568,14 +569,14 @@ public class RecastDebugDraw : DebugDraw
{ {
Contour cont = cset.conts[i]; Contour cont = cset.conts[i];
int col = duDarkenCol(duIntToCol(cont.reg, a)); int col = duDarkenCol(duIntToCol(cont.reg, a));
float[] pos = getContourCenter(cont, orig, cs, ch); Vector3f pos = getContourCenter(cont, orig, cs, ch);
vertex(pos, col); vertex(pos, col);
} }
end(); end();
} }
private float[] getContourCenter(Contour cont, float[] orig, float cs, float ch) private Vector3f getContourCenter(Contour cont, Vector3f orig, float cs, float ch)
{ {
Vector3f center = new Vector3f(); Vector3f center = new Vector3f();
center[0] = 0; center[0] = 0;
@ -619,7 +620,7 @@ public class RecastDebugDraw : DebugDraw
public void debugDrawRawContours(ContourSet cset, float alpha) public void debugDrawRawContours(ContourSet cset, float alpha)
{ {
float[] orig = cset.bmin; Vector3f orig = cset.bmin;
float cs = cset.cs; float cs = cset.cs;
float ch = cset.ch; float ch = cset.ch;
@ -695,7 +696,7 @@ public class RecastDebugDraw : DebugDraw
public void debugDrawContours(ContourSet cset) public void debugDrawContours(ContourSet cset)
{ {
float alpha = 1f; float alpha = 1f;
float[] orig = cset.bmin; Vector3f orig = cset.bmin;
float cs = cset.cs; float cs = cset.cs;
float ch = cset.ch; float ch = cset.ch;
@ -777,7 +778,7 @@ public class RecastDebugDraw : DebugDraw
return; return;
} }
float[] orig = hf.bmin; Vector3f orig = hf.bmin;
float cs = hf.cs; float cs = hf.cs;
float ch = hf.ch; float ch = hf.ch;
@ -809,7 +810,7 @@ public class RecastDebugDraw : DebugDraw
public void debugDrawHeightfieldWalkable(Heightfield hf) public void debugDrawHeightfieldWalkable(Heightfield hf)
{ {
float[] orig = hf.bmin; Vector3f orig = hf.bmin;
float cs = hf.cs; float cs = hf.cs;
float ch = hf.ch; float ch = hf.ch;
@ -942,7 +943,7 @@ public class RecastDebugDraw : DebugDraw
int nvp = mesh.nvp; int nvp = mesh.nvp;
float cs = mesh.cs; float cs = mesh.cs;
float ch = mesh.ch; float ch = mesh.ch;
float[] orig = mesh.bmin; Vector3f orig = mesh.bmin;
begin(DebugDrawPrimitives.TRIS); begin(DebugDrawPrimitives.TRIS);

View File

@ -22,6 +22,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using DotRecast.Core;
using DotRecast.Recast.Geom; using DotRecast.Recast.Geom;
namespace DotRecast.Recast.Demo.Geom; namespace DotRecast.Recast.Demo.Geom;
@ -31,8 +32,8 @@ public class DemoInputGeomProvider : InputGeomProvider
public readonly float[] vertices; public readonly float[] vertices;
public readonly int[] faces; public readonly int[] faces;
public readonly float[] normals; public readonly float[] normals;
private readonly float[] bmin; private readonly Vector3f bmin;
private readonly float[] bmax; private readonly Vector3f bmax;
private readonly List<ConvexVolume> _convexVolumes = new(); private readonly List<ConvexVolume> _convexVolumes = new();
private readonly List<DemoOffMeshConnection> offMeshConnections = new(); private readonly List<DemoOffMeshConnection> offMeshConnections = new();
private readonly ChunkyTriMesh chunkyTriMesh; private readonly ChunkyTriMesh chunkyTriMesh;
@ -100,7 +101,8 @@ public class DemoInputGeomProvider : InputGeomProvider
int v0 = faces[i] * 3; int v0 = faces[i] * 3;
int v1 = faces[i + 1] * 3; int v1 = faces[i + 1] * 3;
int v2 = faces[i + 2] * 3; int v2 = faces[i + 2] * 3;
Vector3f e0 = new Vector3f(), e1 = new float[3]; Vector3f e0 = new Vector3f();
Vector3f e1 = new Vector3f();
for (int j = 0; j < 3; ++j) for (int j = 0; j < 3; ++j)
{ {
e0[j] = vertices[v1 + j] - vertices[v0 + j]; e0[j] = vertices[v1 + j] - vertices[v0 + j];
@ -147,7 +149,7 @@ public class DemoInputGeomProvider : InputGeomProvider
offMeshConnections.RemoveAll(filter); // TODO : 확인 필요 offMeshConnections.RemoveAll(filter); // TODO : 확인 필요
} }
public float? raycastMesh(float[] src, float[] dst) public float? raycastMesh(float[] src, Vector3f dst)
{ {
// Prune hit ray. // Prune hit ray.
float[] btminmax = Intersections.intersectSegmentAABB(src, dst, bmin, bmax); float[] btminmax = Intersections.intersectSegmentAABB(src, dst, bmin, bmax);

View File

@ -78,7 +78,7 @@ public class Intersections
return t; return t;
} }
public static float[] intersectSegmentAABB(float[] sp, float[] sq, float[] amin, float[] amax) public static float[] intersectSegmentAABB(float[] sp, Vector3f sq, Vector3f amin, Vector3f amax)
{ {
float EPS = 1e-6f; float EPS = 1e-6f;

View File

@ -91,10 +91,10 @@ public class RecastDemo
private float scrollZoom; private float scrollZoom;
private readonly float[] origMousePos = new float[2]; private readonly float[] origMousePos = new float[2];
private readonly float[] origCameraEulers = new float[2]; private readonly float[] origCameraEulers = new float[2];
private readonly Vector3f origCameraPos = new Vector3f(); private Vector3f origCameraPos = new Vector3f();
private readonly float[] cameraEulers = { 45, -45 }; private readonly float[] cameraEulers = { 45, -45 };
private readonly float[] cameraPos = { 0, 0, 0 }; private Vector3f cameraPos = Vector3f.Of(0, 0, 0);
private readonly Vector3f rayStart = new Vector3f(); private readonly Vector3f rayStart = new Vector3f();
private readonly Vector3f rayEnd = new Vector3f(); private readonly Vector3f rayEnd = new Vector3f();

View File

@ -47,7 +47,7 @@ public class ConvexVolumeTool : Tool
sample = m_sample; sample = m_sample;
} }
public override void handleClick(float[] s, float[] p, bool shift) public override void handleClick(float[] s, Vector3f p, bool shift)
{ {
DemoInputGeomProvider geom = sample.getInputGeom(); DemoInputGeomProvider geom = sample.getInputGeom();
if (geom == null) if (geom == null)
@ -80,9 +80,7 @@ public class ConvexVolumeTool : Tool
// Create // Create
// If clicked on that last pt, create the shape. // If clicked on that last pt, create the shape.
if (pts.Count > 0 && RecastMath.vDistSqr(p, if (pts.Count > 0 && RecastMath.vDistSqr(p, Vector3f.Of(pts[pts.Count - 3], pts[pts.Count - 2], pts[pts.Count - 1]), 0) < 0.2f * 0.2f)
new float[] { pts[pts.Count - 3], pts[pts.Count - 2], pts[pts.Count - 1] },
0) < 0.2f * 0.2f)
{ {
if (hull.Count > 2) if (hull.Count > 2)
{ {

View File

@ -102,23 +102,23 @@ public class CrowdProfilingTool
} }
} }
float[] pos = null; Vector3f? pos = null;
switch (type) switch (type)
{ {
case AgentType.MOB: case AgentType.MOB:
pos = getMobPosition(navquery, filter, pos); pos = getMobPosition(navquery, filter);
break; break;
case AgentType.VILLAGER: case AgentType.VILLAGER:
pos = getVillagerPosition(navquery, filter, pos); pos = getVillagerPosition(navquery, filter);
break; break;
case AgentType.TRAVELLER: case AgentType.TRAVELLER:
pos = getVillagerPosition(navquery, filter, pos); pos = getVillagerPosition(navquery, filter);
break; break;
} }
if (pos != null) if (pos != null)
{ {
addAgent(pos, type); addAgent(pos.Value, type);
} }
} }
} }
@ -145,18 +145,18 @@ public class CrowdProfilingTool
} }
} }
private float[] getMobPosition(NavMeshQuery navquery, QueryFilter filter, float[] pos) private Vector3f? getMobPosition(NavMeshQuery navquery, QueryFilter filter)
{ {
Result<FindRandomPointResult> result = navquery.findRandomPoint(filter, rnd); Result<FindRandomPointResult> result = navquery.findRandomPoint(filter, rnd);
if (result.succeeded()) if (result.succeeded())
{ {
pos = result.result.getRandomPt(); return result.result.getRandomPt();
} }
return pos; return null;
} }
private float[] getVillagerPosition(NavMeshQuery navquery, QueryFilter filter, float[] pos) private Vector3f? getVillagerPosition(NavMeshQuery navquery, QueryFilter filter)
{ {
if (0 < zones.Count) if (0 < zones.Count)
{ {
@ -165,11 +165,11 @@ public class CrowdProfilingTool
zones[zone].getRandomPt(), zoneRadius, filter, rnd); zones[zone].getRandomPt(), zoneRadius, filter, rnd);
if (result.succeeded()) if (result.succeeded())
{ {
pos = result.result.getRandomPt(); return result.result.getRandomPt();
} }
} }
return pos; return null;
} }
private void createZones() private void createZones()
@ -403,7 +403,7 @@ public class CrowdProfilingTool
dd.depthMask(true); dd.depthMask(true);
} }
private CrowdAgent addAgent(float[] p, AgentType type) private CrowdAgent addAgent(Vector3f p, AgentType type)
{ {
CrowdAgentParams ap = agentParamsSupplier.Invoke(); CrowdAgentParams ap = agentParamsSupplier.Invoke();
ap.userData = new AgentData(type, p); ap.userData = new AgentData(type, p);
@ -422,10 +422,10 @@ public class CrowdProfilingTool
public readonly AgentType type; public readonly AgentType type;
public readonly Vector3f home = new Vector3f(); public readonly Vector3f home = new Vector3f();
public AgentData(AgentType type, float[] home) public AgentData(AgentType type, Vector3f home)
{ {
this.type = type; this.type = type;
RecastVectors.copy(this.home, home); RecastVectors.copy(ref this.home, home);
} }
} }

View File

@ -21,6 +21,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using DotRecast.Core;
using Silk.NET.Windowing; using Silk.NET.Windowing;
using DotRecast.Detour; using DotRecast.Detour;
using DotRecast.Detour.Crowd; using DotRecast.Detour.Crowd;
@ -79,7 +80,7 @@ public class CrowdTool : Tool
}; };
private readonly Dictionary<long, AgentTrail> m_trails = new(); private readonly Dictionary<long, AgentTrail> m_trails = new();
private float[] m_targetPos; private Vector3f m_targetPos;
private long m_targetRef; private long m_targetRef;
private CrowdToolMode m_mode = CrowdToolMode.CREATE; private CrowdToolMode m_mode = CrowdToolMode.CREATE;
private int m_modeIdx = CrowdToolMode.CREATE.Idx; private int m_modeIdx = CrowdToolMode.CREATE.Idx;
@ -146,7 +147,7 @@ public class CrowdTool : Tool
} }
} }
public override void handleClick(float[] s, float[] p, bool shift) public override void handleClick(float[] s, Vector3f p, bool shift)
{ {
if (m_mode == CrowdToolMode.PROFILING) if (m_mode == CrowdToolMode.PROFILING)
{ {
@ -192,7 +193,7 @@ public class CrowdTool : Tool
if (nav != null && navquery != null) if (nav != null && navquery != null)
{ {
QueryFilter filter = new DefaultQueryFilter(); QueryFilter filter = new DefaultQueryFilter();
float[] halfExtents = crowd.getQueryExtents(); Vector3f halfExtents = crowd.getQueryExtents();
Result<FindNearestPolyResult> result = navquery.findNearestPoly(p, halfExtents, filter); Result<FindNearestPolyResult> result = navquery.findNearestPoly(p, halfExtents, filter);
long refs = result.result.getNearestRef(); long refs = result.result.getNearestRef();
if (refs != 0) if (refs != 0)
@ -216,7 +217,7 @@ public class CrowdTool : Tool
} }
} }
private void addAgent(float[] p) private void addAgent(Vector3f p)
{ {
CrowdAgentParams ap = getAgentParams(); CrowdAgentParams ap = getAgentParams();
CrowdAgent ag = crowd.addAgent(p, ap); CrowdAgent ag = crowd.addAgent(p, ap);
@ -258,15 +259,16 @@ public class CrowdTool : Tool
return ap; return ap;
} }
private CrowdAgent hitTestAgents(float[] s, float[] p) private CrowdAgent hitTestAgents(float[] s, Vector3f p)
{ {
CrowdAgent isel = null; CrowdAgent isel = null;
float tsel = float.MaxValue; float tsel = float.MaxValue;
foreach (CrowdAgent ag in crowd.getActiveAgents()) foreach (CrowdAgent ag in crowd.getActiveAgents())
{ {
Vector3f bmin = new Vector3f(), bmax = new float[3]; Vector3f bmin = new Vector3f();
getAgentBounds(ag, bmin, bmax); Vector3f bmax = new Vector3f();
getAgentBounds(ag, ref bmin, ref bmax);
float[] isect = Intersections.intersectSegmentAABB(s, p, bmin, bmax); float[] isect = Intersections.intersectSegmentAABB(s, p, bmin, bmax);
if (null != isect) if (null != isect)
{ {
@ -282,9 +284,9 @@ public class CrowdTool : Tool
return isel; return isel;
} }
private void getAgentBounds(CrowdAgent ag, float[] bmin, float[] bmax) private void getAgentBounds(CrowdAgent ag, ref Vector3f bmin, ref Vector3f bmax)
{ {
float[] p = ag.npos; Vector3f p = ag.npos;
float r = ag.option.radius; float r = ag.option.radius;
float h = ag.option.height; float h = ag.option.height;
bmin[0] = p[0] - r; bmin[0] = p[0] - r;
@ -295,7 +297,7 @@ public class CrowdTool : Tool
bmax[2] = p[2] + r; bmax[2] = p[2] + r;
} }
private void setMoveTarget(float[] p, bool adjust) private void setMoveTarget(Vector3f p, bool adjust)
{ {
if (sample == null || crowd == null) if (sample == null || crowd == null)
return; return;
@ -303,14 +305,14 @@ public class CrowdTool : Tool
// Find nearest point on navmesh and set move request to that location. // Find nearest point on navmesh and set move request to that location.
NavMeshQuery navquery = sample.getNavMeshQuery(); NavMeshQuery navquery = sample.getNavMeshQuery();
QueryFilter filter = crowd.getFilter(0); QueryFilter filter = crowd.getFilter(0);
float[] halfExtents = crowd.getQueryExtents(); Vector3f halfExtents = crowd.getQueryExtents();
if (adjust) if (adjust)
{ {
// Request velocity // Request velocity
if (m_agentDebug.agent != null) if (m_agentDebug.agent != null)
{ {
float[] vel = calcVel(m_agentDebug.agent.npos, p, m_agentDebug.agent.option.maxSpeed); float[] vel = calcVel(ref m_agentDebug.agent.npos, p, m_agentDebug.agent.option.maxSpeed);
crowd.requestMoveVelocity(m_agentDebug.agent, vel); crowd.requestMoveVelocity(m_agentDebug.agent, vel);
} }
else else
@ -341,11 +343,11 @@ public class CrowdTool : Tool
} }
} }
private float[] calcVel(float[] pos, float[] tgt, float speed) private Vector3f calcVel(Vector3f pos, Vector3f tgt, float speed)
{ {
float[] vel = vSub(tgt, pos); Vector3f vel = vSub(tgt, pos);
vel[1] = 0.0f; vel[1] = 0.0f;
vNormalize(vel); vNormalize(ref vel);
return vScale(vel, speed); return vScale(vel, speed);
} }
@ -517,9 +519,9 @@ public class CrowdTool : Tool
for (int j = 0; j < ag.boundary.getSegmentCount(); ++j) for (int j = 0; j < ag.boundary.getSegmentCount(); ++j)
{ {
int col = duRGBA(192, 0, 128, 192); int col = duRGBA(192, 0, 128, 192);
float[] s = ag.boundary.getSegment(j); Vector3f[] s = ag.boundary.getSegment(j);
float[] s0 = new float[] { s[0], s[1], s[2] }; Vector3f s0 = s[0];
float[] s3 = new float[] { s[3], s[4], s[5] }; Vector3f s3 = s[1];
if (triArea2D(pos, s0, s3) < 0.0f) if (triArea2D(pos, s0, s3) < 0.0f)
col = duDarkenCol(col); col = duDarkenCol(col);
@ -562,7 +564,7 @@ public class CrowdTool : Tool
foreach (CrowdAgent ag in crowd.getActiveAgents()) foreach (CrowdAgent ag in crowd.getActiveAgents())
{ {
float radius = ag.option.radius; float radius = ag.option.radius;
float[] pos = ag.npos; Vector3f pos = ag.npos;
int col = duRGBA(0, 0, 0, 32); int col = duRGBA(0, 0, 0, 32);
if (m_agentDebug.agent == ag) if (m_agentDebug.agent == ag)
@ -575,7 +577,7 @@ public class CrowdTool : Tool
{ {
float height = ag.option.height; float height = ag.option.height;
float radius = ag.option.radius; float radius = ag.option.radius;
float[] pos = ag.npos; Vector3f pos = ag.npos;
int col = duRGBA(220, 220, 220, 128); int col = duRGBA(220, 220, 220, 128);
if (ag.targetState == CrowdAgent.MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING if (ag.targetState == CrowdAgent.MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING
@ -611,7 +613,7 @@ public class CrowdTool : Tool
dd.begin(QUADS); dd.begin(QUADS);
for (int j = 0; j < vod.getSampleCount(); ++j) for (int j = 0; j < vod.getSampleCount(); ++j)
{ {
float[] p = vod.getSampleVelocity(j); Vector3f p = vod.getSampleVelocity(j);
float sr = vod.getSampleSize(j); float sr = vod.getSampleSize(j);
float pen = vod.getSamplePenalty(j); float pen = vod.getSamplePenalty(j);
float pen2 = vod.getSamplePreferredSidePenalty(j); float pen2 = vod.getSamplePreferredSidePenalty(j);
@ -632,9 +634,9 @@ public class CrowdTool : Tool
{ {
float radius = ag.option.radius; float radius = ag.option.radius;
float height = ag.option.height; float height = ag.option.height;
float[] pos = ag.npos; Vector3f pos = ag.npos;
float[] vel = ag.vel; Vector3f vel = ag.vel;
float[] dvel = ag.dvel; Vector3f dvel = ag.dvel;
int col = duRGBA(220, 220, 220, 192); int col = duRGBA(220, 220, 220, 192);
if (ag.targetState == CrowdAgent.MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING if (ag.targetState == CrowdAgent.MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING

View File

@ -134,7 +134,7 @@ public class DynamicUpdateTool : Tool
this.sample = sample; this.sample = sample;
} }
public override void handleClick(float[] s, float[] p, bool shift) public override void handleClick(float[] s, Vector3f p, bool shift)
{ {
if (mode == DynamicUpdateToolMode.COLLIDERS) if (mode == DynamicUpdateToolMode.COLLIDERS)
{ {

View File

@ -45,7 +45,7 @@ public class JumpLinkBuilderTool : Tool
annotationBuilder = null; annotationBuilder = null;
} }
public override void handleClick(float[] s, float[] p, bool shift) public override void handleClick(float[] s, Vector3f p, bool shift)
{ {
} }

View File

@ -41,7 +41,7 @@ public class OffMeshConnectionTool : Tool
sample = m_sample; sample = m_sample;
} }
public override void handleClick(float[] s, float[] p, bool shift) public override void handleClick(float[] s, Vector3f p, bool shift)
{ {
DemoInputGeomProvider geom = sample.getInputGeom(); DemoInputGeomProvider geom = sample.getInputGeom();
if (geom == null) if (geom == null)

View File

@ -20,6 +20,7 @@ freely, subject to the following restrictions:
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core;
using DotRecast.Detour; using DotRecast.Detour;
namespace DotRecast.Recast.Demo.Tools; namespace DotRecast.Recast.Demo.Tools;
@ -29,7 +30,7 @@ public static class PathUtils
private const int MAX_STEER_POINTS = 3; private const int MAX_STEER_POINTS = 3;
public static SteerTarget getSteerTarget(NavMeshQuery navQuery, float[] startPos, float[] endPos, public static SteerTarget getSteerTarget(NavMeshQuery navQuery, Vector3f startPos, Vector3f endPos,
float minTargetDist, List<long> path) float minTargetDist, List<long> path)
{ {
// Find steer target. // Find steer target.
@ -75,7 +76,7 @@ public static class PathUtils
return target; return target;
} }
public static bool inRange(float[] v1, float[] v2, float r, float h) public static bool inRange(Vector3f v1, Vector3f v2, float r, float h)
{ {
float dx = v2[0] - v1[0]; float dx = v2[0] - v1[0];
float dy = v2[1] - v1[1]; float dy = v2[1] - v1[1];

View File

@ -18,19 +18,20 @@ freely, subject to the following restrictions:
*/ */
using System; using System;
using DotRecast.Core;
namespace DotRecast.Recast.Demo.Tools; namespace DotRecast.Recast.Demo.Tools;
public class PolyUtils public class PolyUtils
{ {
public static bool pointInPoly(float[] verts, float[] p) public static bool pointInPoly(float[] verts, Vector3f p)
{ {
int i, j; int i, j;
bool c = false; bool c = false;
for (i = 0, j = verts.Length / 3 - 1; i < verts.Length / 3; j = i++) for (i = 0, j = verts.Length / 3 - 1; i < verts.Length / 3; j = i++)
{ {
float[] vi = new float[] { verts[i * 3], verts[i * 3 + 1], verts[i * 3 + 2] }; Vector3f vi = Vector3f.Of(verts[i * 3], verts[i * 3 + 1], verts[i * 3 + 2]);
float[] vj = new float[] { verts[j * 3], verts[j * 3 + 1], verts[j * 3 + 2] }; Vector3f vj = Vector3f.Of(verts[j * 3], verts[j * 3 + 1], verts[j * 3 + 2]);
if (((vi[2] > p[2]) != (vj[2] > p[2])) if (((vi[2] > p[2]) != (vj[2] > p[2]))
&& (p[0] < (vj[0] - vi[0]) * (p[2] - vi[2]) / (vj[2] - vi[2]) + vi[0])) && (p[0] < (vj[0] - vi[0]) * (p[2] - vi[2]) / (vj[2] - vi[2]) + vi[0]))
{ {

View File

@ -22,10 +22,10 @@ public class TestNavmeshTool : Tool
private TestNavmeshToolMode m_toolMode => TestNavmeshToolMode.Values[m_toolModeIdx]; private TestNavmeshToolMode m_toolMode => TestNavmeshToolMode.Values[m_toolModeIdx];
private bool m_sposSet; private bool m_sposSet;
private bool m_eposSet; private bool m_eposSet;
private float[] m_spos; private Vector3f m_spos;
private float[] m_epos; private Vector3f m_epos;
private readonly DefaultQueryFilter m_filter; private readonly DefaultQueryFilter m_filter;
private readonly float[] m_polyPickExt = new float[] { 2, 4, 2 }; private readonly Vector3f m_polyPickExt = Vector3f.Of(2, 4, 2);
private long m_startRef; private long m_startRef;
private long m_endRef; private long m_endRef;
private float[] m_hitPos; private float[] m_hitPos;
@ -38,7 +38,7 @@ public class TestNavmeshTool : Tool
private List<long> m_parent; private List<long> m_parent;
private float m_neighbourhoodRadius; private float m_neighbourhoodRadius;
private readonly float[] m_queryPoly = new float[12]; private readonly float[] m_queryPoly = new float[12];
private List<float[]> m_smoothPath; private List<Vector3f> m_smoothPath;
private Status m_pathFindStatus = Status.FAILURE; private Status m_pathFindStatus = Status.FAILURE;
private bool enableRaycast = true; private bool enableRaycast = true;
private readonly List<float[]> randomPoints = new(); private readonly List<float[]> randomPoints = new();
@ -58,17 +58,17 @@ public class TestNavmeshTool : Tool
this.m_sample = m_sample; this.m_sample = m_sample;
} }
public override void handleClick(float[] s, float[] p, bool shift) public override void handleClick(float[] s, Vector3f p, bool shift)
{ {
if (shift) if (shift)
{ {
m_sposSet = true; m_sposSet = true;
m_spos = ArrayUtils.CopyOf(p, p.Length); m_spos = p;
} }
else else
{ {
m_eposSet = true; m_eposSet = true;
m_epos = ArrayUtils.CopyOf(p, p.Length); m_epos = p;
} }
recalc(); recalc();
@ -146,7 +146,8 @@ public class TestNavmeshTool : Tool
if (previousToolMode != m_toolMode || m_straightPathOptions != previousStraightPathOptions if (previousToolMode != m_toolMode || m_straightPathOptions != previousStraightPathOptions
|| previousIncludeFlags != includeFlags || previousExcludeFlags != excludeFlags || previousIncludeFlags != includeFlags || previousExcludeFlags != excludeFlags
|| previousEnableRaycast != enableRaycast || previousConstrainByCircle != constrainByCircle) { || previousEnableRaycast != enableRaycast || previousConstrainByCircle != constrainByCircle)
{
recalc(); recalc();
} }
} }
@ -193,9 +194,8 @@ public class TestNavmeshTool : Tool
{ {
List<long> polys = new(m_polys); List<long> polys = new(m_polys);
// Iterate over the path to find smooth path on the detail mesh surface. // Iterate over the path to find smooth path on the detail mesh surface.
float[] iterPos = m_navQuery.closestPointOnPoly(m_startRef, m_spos).result.getClosest(); Vector3f iterPos = m_navQuery.closestPointOnPoly(m_startRef, m_spos).result.getClosest();
float[] targetPos = m_navQuery.closestPointOnPoly(polys[polys.Count - 1], m_epos).result Vector3f targetPos = m_navQuery.closestPointOnPoly(polys[polys.Count - 1], m_epos).result.getClosest();
.getClosest();
float STEP_SIZE = 0.5f; float STEP_SIZE = 0.5f;
float SLOP = 0.01f; float SLOP = 0.01f;

View File

@ -18,6 +18,7 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using DotRecast.Recast.Demo.Draw; using DotRecast.Recast.Demo.Draw;
using Silk.NET.Windowing; using Silk.NET.Windowing;
@ -27,7 +28,7 @@ public abstract class Tool
{ {
public abstract void setSample(Sample m_sample); public abstract void setSample(Sample m_sample);
public abstract void handleClick(float[] s, float[] p, bool shift); public abstract void handleClick(float[] s, Vector3f p, bool shift);
public abstract void handleRender(NavMeshRenderer renderer); public abstract void handleRender(NavMeshRenderer renderer);

View File

@ -30,7 +30,7 @@ namespace DotRecast.Recast
private const float EPSILON = 0.00001f; private const float EPSILON = 0.00001f;
private static readonly int[] BOX_EDGES = new[] { 0, 1, 0, 2, 0, 4, 1, 3, 1, 5, 2, 3, 2, 6, 3, 7, 4, 5, 4, 6, 5, 7, 6, 7 }; private static readonly int[] BOX_EDGES = new[] { 0, 1, 0, 2, 0, 4, 1, 3, 1, 5, 2, 3, 2, 6, 3, 7, 4, 5, 4, 6, 5, 7, 6, 7 };
public static void rasterizeSphere(Heightfield hf, float[] 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 = float[] bounds =
@ -43,7 +43,7 @@ namespace DotRecast.Recast
ctx.stopTimer("RASTERIZE_SPHERE"); ctx.stopTimer("RASTERIZE_SPHERE");
} }
public static void rasterizeCapsule(Heightfield hf, float[] start, float[] 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) Telemetry ctx)
{ {
ctx.startTimer("RASTERIZE_CAPSULE"); ctx.startTimer("RASTERIZE_CAPSULE");
@ -53,13 +53,13 @@ namespace DotRecast.Recast
Math.Min(start[2], end[2]) - radius, Math.Max(start[0], end[0]) + radius, Math.Max(start[1], end[1]) + radius, Math.Min(start[2], end[2]) - radius, Math.Max(start[0], end[0]) + radius, Math.Max(start[1], end[1]) + radius,
Math.Max(start[2], end[2]) + radius Math.Max(start[2], end[2]) + radius
}; };
float[] axis = { end[0] - start[0], end[1] - start[1], end[2] - start[2] }; Vector3f axis = Vector3f.Of(end[0] - start[0], end[1] - start[1], end[2] - start[2]);
rasterizationFilledShape(hf, bounds, area, flagMergeThr, rasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => intersectCapsule(rectangle, start, end, axis, radius * radius)); rectangle => intersectCapsule(rectangle, start, end, axis, radius * radius));
ctx.stopTimer("RASTERIZE_CAPSULE"); ctx.stopTimer("RASTERIZE_CAPSULE");
} }
public static void rasterizeCylinder(Heightfield hf, float[] start, float[] 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) Telemetry ctx)
{ {
ctx.startTimer("RASTERIZE_CYLINDER"); ctx.startTimer("RASTERIZE_CYLINDER");
@ -69,7 +69,7 @@ namespace DotRecast.Recast
Math.Min(start[2], end[2]) - radius, Math.Max(start[0], end[0]) + radius, Math.Max(start[1], end[1]) + radius, Math.Min(start[2], end[2]) - radius, Math.Max(start[0], end[0]) + radius, Math.Max(start[1], end[1]) + radius,
Math.Max(start[2], end[2]) + radius Math.Max(start[2], end[2]) + radius
}; };
float[] axis = { end[0] - start[0], end[1] - start[1], end[2] - start[2] }; Vector3f axis = Vector3f.Of(end[0] - start[0], end[1] - start[1], end[2] - start[2]);
rasterizationFilledShape(hf, bounds, area, flagMergeThr, rasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => intersectCylinder(rectangle, start, end, axis, radius * radius)); rectangle => intersectCylinder(rectangle, start, end, axis, radius * radius));
ctx.stopTimer("RASTERIZE_CYLINDER"); ctx.stopTimer("RASTERIZE_CYLINDER");
@ -239,7 +239,7 @@ namespace DotRecast.Recast
} }
} }
private static float[] intersectSphere(float[] rectangle, float[] center, float radiusSqr) private static float[] intersectSphere(float[] rectangle, Vector3f center, float radiusSqr)
{ {
float x = Math.Max(rectangle[0], Math.Min(center[0], rectangle[2])); float x = Math.Max(rectangle[0], Math.Min(center[0], rectangle[2]));
float y = rectangle[4]; float y = rectangle[4];
@ -274,7 +274,7 @@ namespace DotRecast.Recast
return new float[] { y + tmin, y + tmax }; return new float[] { y + tmin, y + tmax };
} }
private static float[] intersectCapsule(float[] rectangle, float[] start, float[] end, float[] 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[0] * axis[0] + axis[2] * axis[2]; float axisLen2dSqr = axis[0] * axis[0] + axis[2] * axis[2];
@ -286,7 +286,7 @@ namespace DotRecast.Recast
return s; return s;
} }
private static float[] intersectCylinder(float[] rectangle, float[] start, float[] end, float[] axis, float radiusSqr) private static float[] intersectCylinder(float[] rectangle, Vector3f start, Vector3f end, Vector3f axis, float radiusSqr)
{ {
float[] s = mergeIntersections( float[] s = mergeIntersections(
rayCylinderIntersection(new float[] rayCylinderIntersection(new float[]
@ -315,7 +315,7 @@ namespace DotRecast.Recast
{ {
float x = rectangle[(i + 1) & 2]; float x = rectangle[(i + 1) & 2];
float z = rectangle[(i & 2) + 1]; float z = rectangle[(i & 2) + 1];
float[] a = { x, rectangle[4], z }; Vector3f a = Vector3f.Of(x, rectangle[4], z);
float dotAxisA = dot(axis, a); float dotAxisA = dot(axis, a);
float t = (ds - dotAxisA) / axis[1]; float t = (ds - dotAxisA) / axis[1];
rectangleOnStartPlane[i][0] = x; rectangleOnStartPlane[i][0] = x;
@ -337,7 +337,7 @@ namespace DotRecast.Recast
return s; return s;
} }
private static float[] cylinderCapIntersection(float[] 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; int j = (i + 1) % 4;
// Ray against sphere intersection // Ray against sphere intersection
@ -370,7 +370,7 @@ namespace DotRecast.Recast
return s; return s;
} }
private static float[] slabsCylinderIntersection(float[] rectangle, float[] start, float[] end, float[] axis, float radiusSqr, private static float[] slabsCylinderIntersection(float[] rectangle, Vector3f start, Vector3f end, Vector3f axis, float radiusSqr,
float[] s) float[] s)
{ {
if (Math.Min(start[0], end[0]) < rectangle[0]) if (Math.Min(start[0], end[0]) < rectangle[0])
@ -396,12 +396,12 @@ namespace DotRecast.Recast
return s; return s;
} }
private static float[] xSlabCylinderIntersection(float[] rectangle, float[] start, float[] 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 float[] xSlabRayIntersection(float[] rectangle, float[] start, float[] direction, float x) private static float[] xSlabRayIntersection(float[] rectangle, Vector3f start, Vector3f direction, float x)
{ {
// 2d intersection of plane and segment // 2d intersection of plane and segment
float t = (x - start[0]) / direction[0]; float t = (x - start[0]) / direction[0];
@ -409,12 +409,12 @@ namespace DotRecast.Recast
return new float[] { x, rectangle[4], z }; return new float[] { x, rectangle[4], z };
} }
private static float[] zSlabCylinderIntersection(float[] rectangle, float[] start, float[] 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 float[] zSlabRayIntersection(float[] rectangle, float[] start, float[] direction, float z) private static float[] zSlabRayIntersection(float[] rectangle, Vector3f start, Vector3f direction, float z)
{ {
// 2d intersection of plane and segment // 2d intersection of plane and segment
float t = (z - start[2]) / direction[2]; float t = (z - start[2]) / direction[2];
@ -423,10 +423,10 @@ namespace DotRecast.Recast
} }
// Based on Christer Ericsons's "Real-Time Collision Detection" // Based on Christer Ericsons's "Real-Time Collision Detection"
private static float[] rayCylinderIntersection(float[] point, float[] start, float[] axis, float radiusSqr) private static float[] rayCylinderIntersection(float[] point, Vector3f start, Vector3f axis, float radiusSqr)
{ {
float[] d = axis; Vector3f d = axis;
float[] m = { point[0] - start[0], point[1] - start[1], point[2] - start[2] }; Vector3f m = Vector3f.Of(point[0] - start[0], point[1] - start[1], point[2] - start[2]);
// float[] n = { 0, 1, 0 }; // float[] n = { 0, 1, 0 };
float md = dot(m, d); float md = dot(m, d);
// float nd = dot(n, d); // float nd = dot(n, d);

View File

@ -234,5 +234,11 @@ namespace DotRecast.Recast
{ {
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
} }
public static float dot(Vector3f v1, Vector3f v2)
{
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
} }
} }

View File

@ -20,6 +20,7 @@ freely, subject to the following restrictions:
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Crowd.Test; namespace DotRecast.Detour.Crowd.Test;
@ -36,22 +37,22 @@ public class AbstractCrowdTest
protected readonly long[] endRefs = { 281474976710721L, 281474976710767L, 281474976710758L, 281474976710731L, 281474976710772L }; protected readonly long[] endRefs = { 281474976710721L, 281474976710767L, 281474976710758L, 281474976710731L, 281474976710772L };
protected readonly float[][] startPoss = protected readonly Vector3f[] startPoss =
{ {
new[] { 22.60652f, 10.197294f, -45.918674f }, Vector3f.Of(22.60652f, 10.197294f, -45.918674f),
new[] { 22.331268f, 10.197294f, -1.0401875f }, Vector3f.Of(22.331268f, 10.197294f, -1.0401875f),
new[] { 18.694363f, 15.803535f, -73.090416f }, Vector3f.Of(18.694363f, 15.803535f, -73.090416f),
new[] { 0.7453353f, 10.197294f, -5.94005f }, Vector3f.Of(0.7453353f, 10.197294f, -5.94005f),
new[] { -20.651257f, 5.904126f, -13.712508f } Vector3f.Of(-20.651257f, 5.904126f, -13.712508f),
}; };
protected readonly float[][] endPoss = protected readonly Vector3f[] endPoss =
{ {
new[] { 6.4576626f, 10.197294f, -18.33406f }, Vector3f.Of(6.4576626f, 10.197294f, -18.33406f),
new[] { -5.8023443f, 0.19729415f, 3.008419f }, Vector3f.Of(-5.8023443f, 0.19729415f, 3.008419f),
new[] { 38.423977f, 10.197294f, -0.116066754f }, Vector3f.Of(38.423977f, 10.197294f, -0.116066754f),
new[] { 0.8635526f, 10.197294f, -10.31032f }, Vector3f.Of(0.8635526f, 10.197294f, -10.31032f),
new[] { 18.784092f, 10.197294f, 3.0543678f } Vector3f.Of(18.784092f, 10.197294f, 3.0543678f),
}; };
protected MeshData nmd; protected MeshData nmd;
@ -110,7 +111,7 @@ public class AbstractCrowdTest
return ap; return ap;
} }
protected void addAgentGrid(int size, float distance, int updateFlags, int obstacleAvoidanceType, float[] 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 i = 0; i < size; i++)
@ -126,15 +127,15 @@ public class AbstractCrowdTest
} }
} }
protected void setMoveTarget(float[] pos, bool adjust) protected void setMoveTarget(Vector3f pos, bool adjust)
{ {
float[] ext = crowd.getQueryExtents(); Vector3f ext = crowd.getQueryExtents();
QueryFilter filter = crowd.getFilter(0); QueryFilter filter = crowd.getFilter(0);
if (adjust) if (adjust)
{ {
foreach (CrowdAgent ag in crowd.getActiveAgents()) foreach (CrowdAgent ag in crowd.getActiveAgents())
{ {
float[] vel = calcVel(ag.npos, pos, ag.option.maxSpeed); Vector3f vel = calcVel(ag.npos, pos, ag.option.maxSpeed);
crowd.requestMoveVelocity(ag, vel); crowd.requestMoveVelocity(ag, vel);
} }
} }
@ -148,11 +149,11 @@ public class AbstractCrowdTest
} }
} }
protected float[] calcVel(float[] pos, float[] tgt, float speed) protected Vector3f calcVel(Vector3f pos, Vector3f tgt, float speed)
{ {
float[] vel = vSub(tgt, pos); Vector3f vel = vSub(tgt, pos);
vel[1] = 0.0f; vel[1] = 0.0f;
vNormalize(vel); vNormalize(ref vel);
vel = vScale(vel, speed); vel = vScale(vel, speed);
return vel; return vel;
} }

View File

@ -17,6 +17,7 @@ freely, subject to the following restrictions:
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
@ -30,22 +31,22 @@ public class PathCorridorTest
[SetUp] [SetUp]
public void setUp() public void setUp()
{ {
corridor.reset(0, new float[] { 10, 20, 30 }); corridor.reset(0, Vector3f.Of(10, 20, 30));
} }
[Test] [Test]
public void shouldKeepOriginalPathInFindCornersWhenNothingCanBePruned() public void shouldKeepOriginalPathInFindCornersWhenNothingCanBePruned()
{ {
List<StraightPathItem> straightPath = new(); List<StraightPathItem> straightPath = new();
straightPath.Add(new StraightPathItem(new float[] { 11, 20, 30.00001f }, 0, 0)); straightPath.Add(new StraightPathItem(Vector3f.Of(11, 20, 30.00001f), 0, 0));
straightPath.Add(new StraightPathItem(new float[] { 12, 20, 30.00002f }, 0, 0)); straightPath.Add(new StraightPathItem(Vector3f.Of(12, 20, 30.00002f), 0, 0));
straightPath.Add(new StraightPathItem(new float[] { 11f, 21, 32f }, 0, 0)); straightPath.Add(new StraightPathItem(Vector3f.Of(11f, 21, 32f), 0, 0));
straightPath.Add(new StraightPathItem(new float[] { 11f, 21, 32f }, 0, 0)); straightPath.Add(new StraightPathItem(Vector3f.Of(11f, 21, 32f), 0, 0));
Result<List<StraightPathItem>> result = Results.success(straightPath); Result<List<StraightPathItem>> result = Results.success(straightPath);
var mockQuery = new Mock<NavMeshQuery>(It.IsAny<NavMesh>()); var mockQuery = new Mock<NavMeshQuery>(It.IsAny<NavMesh>());
mockQuery.Setup(q => q.findStraightPath( mockQuery.Setup(q => q.findStraightPath(
It.IsAny<float[]>(), It.IsAny<Vector3f>(),
It.IsAny<float[]>(), It.IsAny<Vector3f>(),
It.IsAny<List<long>>(), It.IsAny<List<long>>(),
It.IsAny<int>(), It.IsAny<int>(),
It.IsAny<int>()) It.IsAny<int>())
@ -59,17 +60,17 @@ public class PathCorridorTest
public void shouldPrunePathInFindCorners() public void shouldPrunePathInFindCorners()
{ {
List<StraightPathItem> straightPath = new(); List<StraightPathItem> straightPath = new();
straightPath.Add(new StraightPathItem(new float[] { 10, 20, 30.00001f }, 0, 0)); // too close straightPath.Add(new StraightPathItem(Vector3f.Of(10, 20, 30.00001f), 0, 0)); // too close
straightPath.Add(new StraightPathItem(new float[] { 10, 20, 30.00002f }, 0, 0)); // too close straightPath.Add(new StraightPathItem(Vector3f.Of(10, 20, 30.00002f), 0, 0)); // too close
straightPath.Add(new StraightPathItem(new float[] { 11f, 21, 32f }, 0, 0)); straightPath.Add(new StraightPathItem(Vector3f.Of(11f, 21, 32f), 0, 0));
straightPath.Add(new StraightPathItem(new float[] { 12f, 22, 33f }, NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh straightPath.Add(new StraightPathItem(Vector3f.Of(12f, 22, 33f), NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
straightPath.Add(new StraightPathItem(new float[] { 11f, 21, 32f }, NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh straightPath.Add(new StraightPathItem(Vector3f.Of(11f, 21, 32f), NavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
Result<List<StraightPathItem>> result = Results.success(straightPath); Result<List<StraightPathItem>> result = Results.success(straightPath);
var mockQuery = new Mock<NavMeshQuery>(It.IsAny<NavMesh>()); var mockQuery = new Mock<NavMeshQuery>(It.IsAny<NavMesh>());
var s = mockQuery.Setup(q => q.findStraightPath( var s = mockQuery.Setup(q => q.findStraightPath(
It.IsAny<float[]>(), It.IsAny<Vector3f>(),
It.IsAny<float[]>(), It.IsAny<Vector3f>(),
It.IsAny<List<long>>(), It.IsAny<List<long>>(),
It.IsAny<int>(), It.IsAny<int>(),
It.IsAny<int>()) It.IsAny<int>())

View File

@ -10,10 +10,10 @@ namespace DotRecast.Detour.Dynamic.Test;
public class DynamicNavMeshTest public class DynamicNavMeshTest
{ {
private static readonly float[] START_POS = new float[] { 70.87453f, 0.0010070801f, 86.69021f }; private static readonly Vector3f START_POS = Vector3f.Of(70.87453f, 0.0010070801f, 86.69021f);
private static readonly float[] END_POS = new float[] { -50.22061f, 0.0010070801f, -70.761444f }; private static readonly Vector3f END_POS = Vector3f.Of(-50.22061f, 0.0010070801f, -70.761444f);
private static readonly float[] EXTENT = new float[] { 0.1f, 0.1f, 0.1f }; private static readonly Vector3f EXTENT = Vector3f.Of(0.1f, 0.1f, 0.1f);
private static readonly float[] SPHERE_POS = new float[] { 45.381645f, 0.0010070801f, 52.68981f }; private static readonly Vector3f SPHERE_POS = Vector3f.Of(45.381645f, 0.0010070801f, 52.68981f);
[Test] [Test]

View File

@ -47,8 +47,8 @@ public class VoxelFileReaderTest
Assert.That(f.tiles[0].cellHeight, Is.EqualTo(0.001f)); Assert.That(f.tiles[0].cellHeight, Is.EqualTo(0.001f));
Assert.That(f.tiles[0].width, Is.EqualTo(810)); Assert.That(f.tiles[0].width, Is.EqualTo(810));
Assert.That(f.tiles[0].depth, Is.EqualTo(810)); Assert.That(f.tiles[0].depth, Is.EqualTo(810));
Assert.That(f.tiles[0].boundsMin, Is.EqualTo(new float[] { -101.25f, 0f, -101.25f })); Assert.That(f.tiles[0].boundsMin, Is.EqualTo(Vector3f.Of(-101.25f, 0f, -101.25f)));
Assert.That(f.tiles[0].boundsMax, Is.EqualTo(new float[] { 101.25f, 5.0f, 101.25f })); Assert.That(f.tiles[0].boundsMax, Is.EqualTo(Vector3f.Of(101.25f, 5.0f, 101.25f)));
} }
[Test] [Test]
@ -74,7 +74,7 @@ public class VoxelFileReaderTest
Assert.That(f.tiles[0].cellHeight, Is.EqualTo(0.001f)); Assert.That(f.tiles[0].cellHeight, Is.EqualTo(0.001f));
Assert.That(f.tiles[0].width, Is.EqualTo(90)); Assert.That(f.tiles[0].width, Is.EqualTo(90));
Assert.That(f.tiles[0].depth, Is.EqualTo(90)); Assert.That(f.tiles[0].depth, Is.EqualTo(90));
Assert.That(f.tiles[0].boundsMin, Is.EqualTo(new float[] { -101.25f, 0f, -101.25f })); Assert.That(f.tiles[0].boundsMin, Is.EqualTo(Vector3f.Of(-101.25f, 0f, -101.25f)));
Assert.That(f.tiles[0].boundsMax, Is.EqualTo(new float[] { -78.75f, 5.0f, -78.75f })); Assert.That(f.tiles[0].boundsMax, Is.EqualTo(Vector3f.Of(-78.75f, 5.0f, -78.75f)));
} }
} }

View File

@ -49,8 +49,8 @@ public class VoxelFileReaderWriterTest
Assert.That(f.tiles[0].width, Is.EqualTo(810)); Assert.That(f.tiles[0].width, Is.EqualTo(810));
Assert.That(f.tiles[0].depth, Is.EqualTo(810)); Assert.That(f.tiles[0].depth, Is.EqualTo(810));
Assert.That(f.tiles[0].spanData.Length, Is.EqualTo(9021024)); Assert.That(f.tiles[0].spanData.Length, Is.EqualTo(9021024));
Assert.That(f.tiles[0].boundsMin, Is.EqualTo(new[] { -101.25f, 0f, -101.25f })); Assert.That(f.tiles[0].boundsMin, Is.EqualTo(Vector3f.Of(-101.25f, 0f, -101.25f)));
Assert.That(f.tiles[0].boundsMax, Is.EqualTo(new[] { 101.25f, 5.0f, 101.25f })); Assert.That(f.tiles[0].boundsMax, Is.EqualTo(Vector3f.Of(101.25f, 5.0f, 101.25f)));
} }
[TestCase(false)] [TestCase(false)]
@ -80,8 +80,8 @@ public class VoxelFileReaderWriterTest
Assert.That(f.tiles[0].spanData.Length, Is.EqualTo(104952)); Assert.That(f.tiles[0].spanData.Length, Is.EqualTo(104952));
Assert.That(f.tiles[5].spanData.Length, Is.EqualTo(109080)); Assert.That(f.tiles[5].spanData.Length, Is.EqualTo(109080));
Assert.That(f.tiles[18].spanData.Length, Is.EqualTo(113400)); Assert.That(f.tiles[18].spanData.Length, Is.EqualTo(113400));
Assert.That(f.tiles[0].boundsMin, Is.EqualTo(new[] { -101.25f, 0f, -101.25f })); Assert.That(f.tiles[0].boundsMin, Is.EqualTo(Vector3f.Of(-101.25f, 0f, -101.25f)));
Assert.That(f.tiles[0].boundsMax, Is.EqualTo(new[] { -78.75f, 5.0f, -78.75f })); 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)

View File

@ -32,7 +32,7 @@ public class VoxelQueryTest
{ {
private const int TILE_WIDTH = 100; private const int TILE_WIDTH = 100;
private const int TILE_DEPTH = 90; private const int TILE_DEPTH = 90;
private static readonly float[] ORIGIN = new float[] { 50, 10, 40 }; private static readonly Vector3f ORIGIN = Vector3f.Of(50, 10, 40);
[Test] [Test]

View File

@ -32,8 +32,8 @@ public class UnityAStarPathfindingImporterTest
public void test_v4_0_6() public void test_v4_0_6()
{ {
NavMesh mesh = loadNavMesh("graph.zip"); NavMesh mesh = loadNavMesh("graph.zip");
float[] startPos = new float[] { 8.200293f, 2.155071f, -26.176147f }; Vector3f startPos = Vector3f.Of(8.200293f, 2.155071f, -26.176147f);
float[] endPos = new float[] { 11.971109f, 0.000000f, 8.663261f }; 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.status, Is.EqualTo(Status.SUCCSESS));
Assert.That(path.result.Count, Is.EqualTo(57)); Assert.That(path.result.Count, Is.EqualTo(57));
@ -44,8 +44,8 @@ public class UnityAStarPathfindingImporterTest
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");
float[] startPos = new float[] { 22.93f, -2.37f, -5.11f }; Vector3f startPos = Vector3f.Of(22.93f, -2.37f, -5.11f);
float[] endPos = new float[] { 16.81f, -2.37f, 25.52f }; Vector3f endPos = Vector3f.Of(16.81f, -2.37f, 25.52f);
Result<List<long>> path = findPath(mesh, startPos, endPos); Result<List<long>> path = findPath(mesh, startPos, endPos);
Assert.That(path.status.isSuccess(), Is.True); Assert.That(path.status.isSuccess(), Is.True);
Assert.That(path.result.Count, Is.EqualTo(15)); Assert.That(path.result.Count, Is.EqualTo(15));
@ -56,7 +56,7 @@ public class UnityAStarPathfindingImporterTest
public void testBoundsTree() public void testBoundsTree()
{ {
NavMesh mesh = loadNavMesh("test_boundstree.zip"); NavMesh mesh = loadNavMesh("test_boundstree.zip");
float[] position = { 387.52988f, 19.997f, 368.86282f }; Vector3f position = Vector3f.Of(387.52988f, 19.997f, 368.86282f);
int[] tilePos = mesh.calcTileLoc(position); int[] tilePos = mesh.calcTileLoc(position);
long tileRef = mesh.getTileRefAt(tilePos[0], tilePos[1], 0); long tileRef = mesh.getTileRefAt(tilePos[0], tilePos[1], 0);
@ -87,7 +87,7 @@ public class UnityAStarPathfindingImporterTest
return meshes[0]; return meshes[0];
} }
private Result<List<long>> findPath(NavMesh mesh, float[] startPos, float[] endPos) private Result<List<long>> findPath(NavMesh mesh, Vector3f startPos, Vector3f endPos)
{ {
// Perform a simple pathfinding // Perform a simple pathfinding
NavMeshQuery query = new NavMeshQuery(mesh); NavMeshQuery query = new NavMeshQuery(mesh);
@ -97,19 +97,19 @@ public class UnityAStarPathfindingImporterTest
return query.findPath(polys[0].getNearestRef(), polys[1].getNearestRef(), startPos, endPos, filter); return query.findPath(polys[0].getNearestRef(), polys[1].getNearestRef(), startPos, endPos, filter);
} }
private FindNearestPolyResult[] getNearestPolys(NavMesh mesh, params float[][] positions) private FindNearestPolyResult[] getNearestPolys(NavMesh mesh, params Vector3f[] positions)
{ {
NavMeshQuery query = new NavMeshQuery(mesh); NavMeshQuery query = new NavMeshQuery(mesh);
QueryFilter filter = new DefaultQueryFilter(); QueryFilter filter = new DefaultQueryFilter();
float[] extents = new float[] { 0.1f, 0.1f, 0.1f }; Vector3f extents = Vector3f.Of(0.1f, 0.1f, 0.1f);
FindNearestPolyResult[] results = new FindNearestPolyResult[positions.Length]; FindNearestPolyResult[] results = new FindNearestPolyResult[positions.Length];
for (int i = 0; i < results.Length; i++) for (int i = 0; i < results.Length; i++)
{ {
float[] position = positions[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.succeeded(), Is.True);
Assert.That(result.result.getNearestPos(), Is.Not.Null, "Nearest start position is null!"); Assert.That(result.result.getNearestPos(), Is.Not.EqualTo(Vector3f.Zero), "Nearest start position is null!");
results[i] = result.result; results[i] = result.result;
} }

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. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -32,22 +33,22 @@ public abstract class AbstractDetourTest
281474976710721L, 281474976710767L, 281474976710758L, 281474976710731L, 281474976710772L 281474976710721L, 281474976710767L, 281474976710758L, 281474976710731L, 281474976710772L
}; };
protected static readonly float[][] startPoss = protected static readonly Vector3f[] startPoss =
{ {
new[] { 22.60652f, 10.197294f, -45.918674f }, Vector3f.Of(22.60652f, 10.197294f, -45.918674f),
new[] { 22.331268f, 10.197294f, -1.0401875f }, Vector3f.Of(22.331268f, 10.197294f, -1.0401875f),
new[] { 18.694363f, 15.803535f, -73.090416f }, Vector3f.Of(18.694363f, 15.803535f, -73.090416f),
new[] { 0.7453353f, 10.197294f, -5.94005f }, Vector3f.Of(0.7453353f, 10.197294f, -5.94005f),
new[] { -20.651257f, 5.904126f, -13.712508f } Vector3f.Of(-20.651257f, 5.904126f, -13.712508f)
}; };
protected static readonly float[][] endPoss = protected static readonly Vector3f[] endPoss =
{ {
new[] { 6.4576626f, 10.197294f, -18.33406f }, Vector3f.Of(6.4576626f, 10.197294f, -18.33406f),
new[] { -5.8023443f, 0.19729415f, 3.008419f }, Vector3f.Of(-5.8023443f, 0.19729415f, 3.008419f),
new[] { 38.423977f, 10.197294f, -0.116066754f }, Vector3f.Of(38.423977f, 10.197294f, -0.116066754f),
new[] { 0.8635526f, 10.197294f, -10.31032f }, Vector3f.Of(0.8635526f, 10.197294f, -10.31032f),
new[] { 18.784092f, 10.197294f, 3.0543678f } Vector3f.Of(18.784092f, 10.197294f, 3.0543678f),
}; };
protected NavMeshQuery query; protected NavMeshQuery query;

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. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -48,7 +49,7 @@ public class FindDistanceToWallTest : AbstractDetourTest
QueryFilter filter = new DefaultQueryFilter(); QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++) for (int i = 0; i < startRefs.Length; i++)
{ {
float[] startPos = startPoss[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; 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));

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. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -54,7 +55,7 @@ public class FindLocalNeighbourhoodTest : AbstractDetourTest
QueryFilter filter = new DefaultQueryFilter(); QueryFilter filter = new DefaultQueryFilter();
for (int i = 0; i < startRefs.Length; i++) for (int i = 0; i < startRefs.Length; i++)
{ {
float[] startPos = startPoss[i]; Vector3f startPos = startPoss[i];
Result<FindLocalNeighbourhoodResult> poly = query.findLocalNeighbourhood(startRefs[i], startPos, 3.5f, Result<FindLocalNeighbourhoodResult> poly = query.findLocalNeighbourhood(startRefs[i], startPos, 3.5f,
filter); filter);
Assert.That(poly.result.getRefs().Count, Is.EqualTo(REFS[i].Length)); Assert.That(poly.result.getRefs().Count, Is.EqualTo(REFS[i].Length));

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. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -35,10 +36,10 @@ public class FindNearestPolyTest : AbstractDetourTest
public void testFindNearestPoly() public void testFindNearestPoly()
{ {
QueryFilter filter = new DefaultQueryFilter(); QueryFilter filter = new DefaultQueryFilter();
float[] extents = { 2, 4, 2 }; Vector3f extents = Vector3f.Of(2, 4, 2);
for (int i = 0; i < startRefs.Length; i++) for (int i = 0; i < startRefs.Length; i++)
{ {
float[] startPos = startPoss[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.succeeded(), Is.True);
Assert.That(poly.result.getNearestRef(), Is.EqualTo(POLY_REFS[i])); Assert.That(poly.result.getNearestRef(), Is.EqualTo(POLY_REFS[i]));
@ -56,7 +57,7 @@ public class FindNearestPolyTest : AbstractDetourTest
return false; return false;
} }
public float getCost(float[] pa, float[] 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) Poly curPoly, long nextRef, MeshTile nextTile, Poly nextPoly)
{ {
return 0; return 0;
@ -67,10 +68,10 @@ public class FindNearestPolyTest : AbstractDetourTest
public void shouldReturnStartPosWhenNoPolyIsValid() public void shouldReturnStartPosWhenNoPolyIsValid()
{ {
var filter = new EmptyQueryFilter(); var filter = new EmptyQueryFilter();
float[] extents = { 2, 4, 2 }; Vector3f extents = Vector3f.Of(2, 4, 2);
for (int i = 0; i < startRefs.Length; i++) for (int i = 0; i < startRefs.Length; i++)
{ {
float[] startPos = startPoss[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.succeeded(), Is.True);
Assert.That(poly.result.getNearestRef(), Is.EqualTo(0L)); Assert.That(poly.result.getNearestRef(), Is.EqualTo(0L));

View File

@ -17,6 +17,7 @@ freely, subject to the following restrictions:
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -69,59 +70,59 @@ public class FindPathTest : AbstractDetourTest
{ {
new[] new[]
{ {
new StraightPathItem(new float[] { 22.606520f, 10.197294f, -45.918674f }, 1, 281474976710696L), new StraightPathItem(Vector3f.Of(22.606520f, 10.197294f, -45.918674f), 1, 281474976710696L),
new StraightPathItem(new float[] { 3.484785f, 10.197294f, -34.241272f }, 0, 281474976710713L), new StraightPathItem(Vector3f.Of(3.484785f, 10.197294f, -34.241272f), 0, 281474976710713L),
new StraightPathItem(new float[] { 1.984785f, 10.197294f, -31.241272f }, 0, 281474976710712L), new StraightPathItem(Vector3f.Of(1.984785f, 10.197294f, -31.241272f), 0, 281474976710712L),
new StraightPathItem(new float[] { 1.984785f, 10.197294f, -29.741272f }, 0, 281474976710727L), new StraightPathItem(Vector3f.Of(1.984785f, 10.197294f, -29.741272f), 0, 281474976710727L),
new StraightPathItem(new float[] { 2.584784f, 10.197294f, -27.941273f }, 0, 281474976710730L), new StraightPathItem(Vector3f.Of(2.584784f, 10.197294f, -27.941273f), 0, 281474976710730L),
new StraightPathItem(new float[] { 6.457663f, 10.197294f, -18.334061f }, 2, 0L) new StraightPathItem(Vector3f.Of(6.457663f, 10.197294f, -18.334061f), 2, 0L)
}, },
new[] new[]
{ {
new StraightPathItem(new float[] { 22.331268f, 10.197294f, -1.040187f }, 1, 281474976710773L), new StraightPathItem(Vector3f.Of(22.331268f, 10.197294f, -1.040187f), 1, 281474976710773L),
new StraightPathItem(new float[] { 9.784786f, 10.197294f, -2.141273f }, 0, 281474976710755L), new StraightPathItem(Vector3f.Of(9.784786f, 10.197294f, -2.141273f), 0, 281474976710755L),
new StraightPathItem(new float[] { 7.984783f, 10.197294f, -2.441269f }, 0, 281474976710753L), new StraightPathItem(Vector3f.Of(7.984783f, 10.197294f, -2.441269f), 0, 281474976710753L),
new StraightPathItem(new float[] { 1.984785f, 10.197294f, -8.441269f }, 0, 281474976710752L), new StraightPathItem(Vector3f.Of(1.984785f, 10.197294f, -8.441269f), 0, 281474976710752L),
new StraightPathItem(new float[] { -4.315216f, 10.197294f, -15.341270f }, 0, 281474976710724L), new StraightPathItem(Vector3f.Of(-4.315216f, 10.197294f, -15.341270f), 0, 281474976710724L),
new StraightPathItem(new float[] { -8.215216f, 10.197294f, -17.441269f }, 0, 281474976710728L), new StraightPathItem(Vector3f.Of(-8.215216f, 10.197294f, -17.441269f), 0, 281474976710728L),
new StraightPathItem(new float[] { -10.015216f, 10.197294f, -17.741272f }, 0, 281474976710738L), new StraightPathItem(Vector3f.Of(-10.015216f, 10.197294f, -17.741272f), 0, 281474976710738L),
new StraightPathItem(new float[] { -11.815216f, 9.997294f, -17.441269f }, 0, 281474976710736L), new StraightPathItem(Vector3f.Of(-11.815216f, 9.997294f, -17.441269f), 0, 281474976710736L),
new StraightPathItem(new float[] { -17.815216f, 5.197294f, -11.441269f }, 0, 281474976710735L), new StraightPathItem(Vector3f.Of(-17.815216f, 5.197294f, -11.441269f), 0, 281474976710735L),
new StraightPathItem(new float[] { -17.815216f, 5.197294f, -8.441269f }, 0, 281474976710746L), new StraightPathItem(Vector3f.Of(-17.815216f, 5.197294f, -8.441269f), 0, 281474976710746L),
new StraightPathItem(new float[] { -11.815216f, 0.197294f, 3.008419f }, 2, 0L) new StraightPathItem(Vector3f.Of(-11.815216f, 0.197294f, 3.008419f), 2, 0L)
}, },
new[] new[]
{ {
new StraightPathItem(new float[] { 18.694363f, 15.803535f, -73.090416f }, 1, 281474976710680L), new StraightPathItem(Vector3f.Of(18.694363f, 15.803535f, -73.090416f), 1, 281474976710680L),
new StraightPathItem(new float[] { 17.584785f, 10.197294f, -49.841274f }, 0, 281474976710697L), new StraightPathItem(Vector3f.Of(17.584785f, 10.197294f, -49.841274f), 0, 281474976710697L),
new StraightPathItem(new float[] { 17.284786f, 10.197294f, -48.041275f }, 0, 281474976710695L), new StraightPathItem(Vector3f.Of(17.284786f, 10.197294f, -48.041275f), 0, 281474976710695L),
new StraightPathItem(new float[] { 16.084785f, 10.197294f, -45.341274f }, 0, 281474976710694L), new StraightPathItem(Vector3f.Of(16.084785f, 10.197294f, -45.341274f), 0, 281474976710694L),
new StraightPathItem(new float[] { 3.484785f, 10.197294f, -34.241272f }, 0, 281474976710713L), new StraightPathItem(Vector3f.Of(3.484785f, 10.197294f, -34.241272f), 0, 281474976710713L),
new StraightPathItem(new float[] { 1.984785f, 10.197294f, -31.241272f }, 0, 281474976710712L), new StraightPathItem(Vector3f.Of(1.984785f, 10.197294f, -31.241272f), 0, 281474976710712L),
new StraightPathItem(new float[] { 1.984785f, 10.197294f, -8.441269f }, 0, 281474976710753L), new StraightPathItem(Vector3f.Of(1.984785f, 10.197294f, -8.441269f), 0, 281474976710753L),
new StraightPathItem(new float[] { 7.984783f, 10.197294f, -2.441269f }, 0, 281474976710755L), new StraightPathItem(Vector3f.Of(7.984783f, 10.197294f, -2.441269f), 0, 281474976710755L),
new StraightPathItem(new float[] { 9.784786f, 10.197294f, -2.141273f }, 0, 281474976710768L), new StraightPathItem(Vector3f.Of(9.784786f, 10.197294f, -2.141273f), 0, 281474976710768L),
new StraightPathItem(new float[] { 38.423977f, 10.197294f, -0.116067f }, 2, 0L) new StraightPathItem(Vector3f.Of(38.423977f, 10.197294f, -0.116067f), 2, 0L)
}, },
new[] new[]
{ {
new StraightPathItem(new float[] { 0.745335f, 10.197294f, -5.940050f }, 1, 281474976710753L), new StraightPathItem(Vector3f.Of(0.745335f, 10.197294f, -5.940050f), 1, 281474976710753L),
new StraightPathItem(new float[] { 0.863553f, 10.197294f, -10.310320f }, 2, 0L) new StraightPathItem(Vector3f.Of(0.863553f, 10.197294f, -10.310320f), 2, 0L)
}, },
new[] new[]
{ {
new StraightPathItem(new float[] { -20.651257f, 5.904126f, -13.712508f }, 1, 281474976710733L), new StraightPathItem(Vector3f.Of(-20.651257f, 5.904126f, -13.712508f), 1, 281474976710733L),
new StraightPathItem(new float[] { -11.815216f, 9.997294f, -17.441269f }, 0, 281474976710738L), new StraightPathItem(Vector3f.Of(-11.815216f, 9.997294f, -17.441269f), 0, 281474976710738L),
new StraightPathItem(new float[] { -10.015216f, 10.197294f, -17.741272f }, 0, 281474976710728L), new StraightPathItem(Vector3f.Of(-10.015216f, 10.197294f, -17.741272f), 0, 281474976710728L),
new StraightPathItem(new float[] { -8.215216f, 10.197294f, -17.441269f }, 0, 281474976710724L), new StraightPathItem(Vector3f.Of(-8.215216f, 10.197294f, -17.441269f), 0, 281474976710724L),
new StraightPathItem(new float[] { -4.315216f, 10.197294f, -15.341270f }, 0, 281474976710729L), new StraightPathItem(Vector3f.Of(-4.315216f, 10.197294f, -15.341270f), 0, 281474976710729L),
new StraightPathItem(new float[] { 1.984785f, 10.197294f, -8.441269f }, 0, 281474976710753L), new StraightPathItem(Vector3f.Of(1.984785f, 10.197294f, -8.441269f), 0, 281474976710753L),
new StraightPathItem(new float[] { 7.984783f, 10.197294f, -2.441269f }, 0, 281474976710755L), new StraightPathItem(Vector3f.Of(7.984783f, 10.197294f, -2.441269f), 0, 281474976710755L),
new StraightPathItem(new float[] { 18.784092f, 10.197294f, 3.054368f }, 2, 0L) new StraightPathItem(Vector3f.Of(18.784092f, 10.197294f, 3.054368f), 2, 0L)
} }
}; };
@ -133,8 +134,8 @@ public class FindPathTest : AbstractDetourTest
{ {
long startRef = startRefs[i]; long startRef = startRefs[i];
long endRef = endRefs[i]; long endRef = endRefs[i];
float[] startPos = startPoss[i]; Vector3f startPos = startPoss[i];
float[] endPos = endPoss[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.status, Is.EqualTo(STATUSES[i]));
Assert.That(path.result.Count, Is.EqualTo(RESULTS[i].Length)); Assert.That(path.result.Count, Is.EqualTo(RESULTS[i].Length));
@ -153,8 +154,8 @@ public class FindPathTest : AbstractDetourTest
{ {
long startRef = startRefs[i]; long startRef = startRefs[i];
long endRef = endRefs[i]; long endRef = endRefs[i];
float[] startPos = startPoss[i]; var startPos = startPoss[i];
float[] endPos = endPoss[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; Status status = Status.IN_PROGRESS;
while (status == Status.IN_PROGRESS) while (status == Status.IN_PROGRESS)
@ -182,8 +183,8 @@ public class FindPathTest : AbstractDetourTest
// startRefs.Length; i++) { // startRefs.Length; i++) {
long startRef = startRefs[i]; long startRef = startRefs[i];
long endRef = endRefs[i]; long endRef = endRefs[i];
float[] startPos = startPoss[i]; var startPos = startPoss[i];
float[] endPos = endPoss[i]; var 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);
Result<List<StraightPathItem>> result = query.findStraightPath(startPos, endPos, path.result, Result<List<StraightPathItem>> result = query.findStraightPath(startPos, endPos, path.result,
int.MaxValue, 0); int.MaxValue, 0);

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. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -102,7 +103,7 @@ public class FindPolysAroundCircleTest : AbstractDetourTest
for (int i = 0; i < startRefs.Length; i++) for (int i = 0; i < startRefs.Length; i++)
{ {
long startRef = startRefs[i]; long startRef = startRefs[i];
float[] startPos = startPoss[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); Assert.That(result.succeeded(), Is.True);
FindPolysAroundResult polys = result.result; FindPolysAroundResult polys = result.result;

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. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -129,9 +130,8 @@ public class FindPolysAroundShapeTest : AbstractDetourTest
for (int i = 0; i < startRefs.Length; i++) for (int i = 0; i < startRefs.Length; i++)
{ {
long startRef = startRefs[i]; long startRef = startRefs[i];
float[] startPos = startPoss[i]; Vector3f startPos = startPoss[i];
Result<FindPolysAroundResult> polys = query.findPolysAroundShape(startRef, Result<FindPolysAroundResult> polys = query.findPolysAroundShape(startRef, getQueryPoly(startPos, endPoss[i]), filter);
getQueryPoly(startPos, endPoss[i]), filter);
Assert.That(polys.result.getRefs().Count, Is.EqualTo(REFS[i].Length)); Assert.That(polys.result.getRefs().Count, Is.EqualTo(REFS[i].Length));
for (int v = 0; v < REFS[i].Length; v++) for (int v = 0; v < REFS[i].Length; v++)
{ {
@ -151,7 +151,7 @@ public class FindPolysAroundShapeTest : AbstractDetourTest
} }
} }
private float[] getQueryPoly(float[] m_spos, float[] m_epos) private float[] getQueryPoly(Vector3f m_spos, Vector3f m_epos)
{ {
float nx = (m_epos[2] - m_spos[2]) * 0.25f; float nx = (m_epos[2] - m_spos[2]) * 0.25f;
float nz = -(m_epos[0] - m_spos[0]) * 0.25f; float nz = -(m_epos[0] - m_spos[0]) * 0.25f;

View File

@ -58,7 +58,7 @@ public class MeshSetReaderWriterTest
NavMeshSetHeader header = new NavMeshSetHeader(); NavMeshSetHeader header = new NavMeshSetHeader();
header.magic = NavMeshSetHeader.NAVMESHSET_MAGIC; header.magic = NavMeshSetHeader.NAVMESHSET_MAGIC;
header.version = NavMeshSetHeader.NAVMESHSET_VERSION; header.version = NavMeshSetHeader.NAVMESHSET_VERSION;
vCopy(header.option.orig, geom.getMeshBoundsMin()); vCopy(ref header.option.orig, geom.getMeshBoundsMin());
header.option.tileWidth = m_tileSize * m_cellSize; header.option.tileWidth = m_tileSize * m_cellSize;
header.option.tileHeight = m_tileSize * m_cellSize; header.option.tileHeight = m_tileSize * m_cellSize;
header.option.maxTiles = m_maxTiles; header.option.maxTiles = m_maxTiles;

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. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -69,8 +70,8 @@ public class MoveAlongSurfaceTest : AbstractDetourTest
for (int i = 0; i < startRefs.Length; i++) for (int i = 0; i < startRefs.Length; i++)
{ {
long startRef = startRefs[i]; long startRef = startRefs[i];
float[] startPos = startPoss[i]; Vector3f startPos = startPoss[i];
float[] endPos = endPoss[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); Assert.That(result.succeeded(), Is.True);
MoveAlongSurfaceResult path = result.result; MoveAlongSurfaceResult path = result.result;

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. 3. This notice may not be removed or altered from any source distribution.
*/ */
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -28,7 +29,7 @@ public class PolygonByCircleConstraintTest
public void shouldHandlePolygonFullyInsideCircle() public void shouldHandlePolygonFullyInsideCircle()
{ {
float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 }; float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 };
float[] center = { 1, 0, 1 }; 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)); Assert.That(constrained, Is.EqualTo(polygon));
@ -39,7 +40,7 @@ public class PolygonByCircleConstraintTest
{ {
int expectedSize = 21; int expectedSize = 21;
float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 }; float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 };
float[] center = { 2, 0, 0 }; 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.Length, Is.EqualTo(expectedSize));
@ -51,7 +52,7 @@ public class PolygonByCircleConstraintTest
{ {
int expectedSize = 12 * 3; int expectedSize = 12 * 3;
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 }; float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
float[] center = { -1, 0, -1 }; 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)); Assert.That(constrained.Length, Is.EqualTo(expectedSize));
@ -69,7 +70,7 @@ public class PolygonByCircleConstraintTest
{ {
int expectedSize = 9 * 3; int expectedSize = 9 * 3;
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 }; float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
float[] center = { -2, 0, -1 }; 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.Length, Is.EqualTo(expectedSize));
@ -81,7 +82,7 @@ public class PolygonByCircleConstraintTest
{ {
int expectedSize = 7 * 3; int expectedSize = 7 * 3;
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 }; float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
float[] center = { 4, 0, 0 }; 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.Length, Is.EqualTo(expectedSize));

View File

@ -59,7 +59,7 @@ public class TestTiledNavMeshBuilder
{ {
// Create empty nav mesh // Create empty nav mesh
NavMeshParams navMeshParams = new NavMeshParams(); NavMeshParams navMeshParams = new NavMeshParams();
copy(navMeshParams.orig, m_geom.getMeshBoundsMin()); copy(ref navMeshParams.orig, m_geom.getMeshBoundsMin());
navMeshParams.tileWidth = m_tileSize * m_cellSize; navMeshParams.tileWidth = m_tileSize * m_cellSize;
navMeshParams.tileHeight = m_tileSize * m_cellSize; navMeshParams.tileHeight = m_tileSize * m_cellSize;
navMeshParams.maxTiles = 128; navMeshParams.maxTiles = 128;

View File

@ -17,6 +17,7 @@ freely, subject to the following restrictions:
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
@ -40,8 +41,8 @@ public class TiledFindPathTest
protected static readonly long[] START_REFS = { 281475015507969L }; protected static readonly long[] START_REFS = { 281475015507969L };
protected static readonly long[] END_REFS = { 281474985099266L }; protected static readonly long[] END_REFS = { 281474985099266L };
protected static readonly float[][] START_POS = { new[] { 39.447338f, 9.998177f, -0.784811f } }; protected static readonly Vector3f[] START_POS = { Vector3f.Of(39.447338f, 9.998177f, -0.784811f) };
protected static readonly float[][] END_POS = { new[] { 19.292645f, 11.611748f, -57.750366f } }; protected static readonly Vector3f[] END_POS = { Vector3f.Of(19.292645f, 11.611748f, -57.750366f) };
protected NavMeshQuery query; protected NavMeshQuery query;
protected NavMesh navmesh; protected NavMesh navmesh;
@ -66,8 +67,8 @@ public class TiledFindPathTest
{ {
long startRef = START_REFS[i]; long startRef = START_REFS[i];
long endRef = END_REFS[i]; long endRef = END_REFS[i];
float[] startPos = START_POS[i]; Vector3f startPos = START_POS[i];
float[] endPos = END_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.status, Is.EqualTo(STATUSES[i]));
Assert.That(path.result.Count, Is.EqualTo(RESULTS[i].Length)); Assert.That(path.result.Count, Is.EqualTo(RESULTS[i].Length));

View File

@ -54,7 +54,7 @@ public class AbstractTileCacheTest
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.ch = m_cellHeight;
option.cs = m_cellSize; option.cs = m_cellSize;
vCopy(option.orig, geom.getMeshBoundsMin()); vCopy(ref option.orig, geom.getMeshBoundsMin());
option.height = m_tileSize; option.height = m_tileSize;
option.width = m_tileSize; option.width = m_tileSize;
option.walkableHeight = m_agentHeight; option.walkableHeight = m_agentHeight;
@ -64,7 +64,7 @@ public class AbstractTileCacheTest
option.maxTiles = twh[0] * twh[1] * EXPECTED_LAYERS_PER_TILE; option.maxTiles = twh[0] * twh[1] * EXPECTED_LAYERS_PER_TILE;
option.maxObstacles = 128; option.maxObstacles = 128;
NavMeshParams navMeshParams = new NavMeshParams(); NavMeshParams navMeshParams = new NavMeshParams();
copy(navMeshParams.orig, geom.getMeshBoundsMin()); copy(ref navMeshParams.orig, geom.getMeshBoundsMin());
navMeshParams.tileWidth = m_tileSize * m_cellSize; navMeshParams.tileWidth = m_tileSize * m_cellSize;
navMeshParams.tileHeight = m_tileSize * m_cellSize; navMeshParams.tileHeight = m_tileSize * m_cellSize;
navMeshParams.maxTiles = 256; navMeshParams.maxTiles = 256;

View File

@ -98,8 +98,8 @@ public class TestTileLayerBuilder : AbstractTileLayersBuilder
header.tx = tx; header.tx = tx;
header.ty = ty; header.ty = ty;
header.tlayer = i; header.tlayer = i;
vCopy(header.bmin, layer.bmin); vCopy(ref header.bmin, layer.bmin);
vCopy(header.bmax, layer.bmax); vCopy(ref header.bmax, layer.bmax);
// Tile info. // Tile info.
header.width = layer.width; header.width = layer.width;

View File

@ -28,8 +28,8 @@ namespace DotRecast.Detour.TileCache.Test;
public class TileCacheFindPathTest : AbstractTileCacheTest public class TileCacheFindPathTest : AbstractTileCacheTest
{ {
private readonly float[] start = { 39.44734f, 9.998177f, -0.784811f }; private readonly Vector3f start = Vector3f.Of(39.44734f, 9.998177f, -0.784811f);
private readonly float[] end = { 19.292645f, 11.611748f, -57.750366f }; private readonly Vector3f end = Vector3f.Of(19.292645f, 11.611748f, -57.750366f);
private readonly NavMesh navmesh; private readonly NavMesh navmesh;
private readonly NavMeshQuery query; private readonly NavMeshQuery query;
@ -46,18 +46,17 @@ public class TileCacheFindPathTest : AbstractTileCacheTest
public void testFindPath() public void testFindPath()
{ {
QueryFilter filter = new DefaultQueryFilter(); QueryFilter filter = new DefaultQueryFilter();
float[] extents = new float[] { 2f, 4f, 2f }; Vector3f extents = Vector3f.Of(2f, 4f, 2f);
Result<FindNearestPolyResult> findPolyStart = query.findNearestPoly(start, extents, filter); Result<FindNearestPolyResult> findPolyStart = query.findNearestPoly(start, extents, filter);
Result<FindNearestPolyResult> findPolyEnd = query.findNearestPoly(end, extents, filter); Result<FindNearestPolyResult> findPolyEnd = query.findNearestPoly(end, extents, filter);
long startRef = findPolyStart.result.getNearestRef(); long startRef = findPolyStart.result.getNearestRef();
long endRef = findPolyEnd.result.getNearestRef(); long endRef = findPolyEnd.result.getNearestRef();
float[] startPos = findPolyStart.result.getNearestPos(); Vector3f startPos = findPolyStart.result.getNearestPos();
float[] endPos = findPolyEnd.result.getNearestPos(); Vector3f endPos = findPolyEnd.result.getNearestPos();
Result<List<long>> path = query.findPath(startRef, endRef, startPos, endPos, filter); Result<List<long>> path = query.findPath(startRef, endRef, startPos, endPos, filter);
int maxStraightPath = 256; int maxStraightPath = 256;
int options = 0; int options = 0;
Result<List<StraightPathItem>> pathStr = query.findStraightPath(startPos, endPos, path.result, maxStraightPath, Result<List<StraightPathItem>> pathStr = query.findStraightPath(startPos, endPos, path.result, maxStraightPath, options);
options);
Assert.That(pathStr.result.Count, Is.EqualTo(8)); Assert.That(pathStr.result.Count, Is.EqualTo(8));
} }
} }

View File

@ -30,8 +30,8 @@ public class TileCacheNavigationTest : AbstractTileCacheTest
{ {
protected readonly long[] startRefs = { 281475006070787L }; protected readonly long[] startRefs = { 281475006070787L };
protected readonly long[] endRefs = { 281474986147841L }; protected readonly long[] endRefs = { 281474986147841L };
protected readonly float[][] startPoss = { new[] { 39.447338f, 9.998177f, -0.784811f } }; protected readonly Vector3f[] startPoss = { Vector3f.Of(39.447338f, 9.998177f, -0.784811f) };
protected readonly float[][] endPoss = { new[] { 19.292645f, 11.611748f, -57.750366f } }; protected readonly Vector3f[] endPoss = { Vector3f.Of(19.292645f, 11.611748f, -57.750366f) };
private readonly Status[] statuses = { Status.SUCCSESS }; private readonly Status[] statuses = { Status.SUCCSESS };
private readonly long[][] results = private readonly long[][] results =
@ -86,8 +86,8 @@ public class TileCacheNavigationTest : AbstractTileCacheTest
{ {
long startRef = startRefs[i]; long startRef = startRefs[i];
long endRef = endRefs[i]; long endRef = endRefs[i];
float[] startPos = startPoss[i]; Vector3f startPos = startPoss[i];
float[] endPos = endPoss[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.status, Is.EqualTo(statuses[i]));
Assert.That(path.result.Count, Is.EqualTo(results[i].Length)); Assert.That(path.result.Count, Is.EqualTo(results[i].Length));
@ -106,8 +106,8 @@ public class TileCacheNavigationTest : AbstractTileCacheTest
{ {
long startRef = startRefs[i]; long startRef = startRefs[i];
long endRef = endRefs[i]; long endRef = endRefs[i];
float[] startPos = startPoss[i]; Vector3f startPos = startPoss[i];
float[] endPos = endPoss[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); 0, 0);
Assert.That(path.status, Is.EqualTo(statuses[i])); Assert.That(path.status, Is.EqualTo(statuses[i]));