diff --git a/src/DotRecast.Core/Numerics/RcVec3f.cs b/src/DotRecast.Core/Numerics/RcVec3f.cs index 4ab3446..86bc87e 100644 --- a/src/DotRecast.Core/Numerics/RcVec3f.cs +++ b/src/DotRecast.Core/Numerics/RcVec3f.cs @@ -125,15 +125,12 @@ namespace DotRecast.Core.Numerics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly RcVec3f Subtract(RcVec3f right) + public static RcVec3f Subtract(RcVec3f left, RcVec3f right) { - return new RcVec3f( - X - right.X, - Y - right.Y, - Z - right.Z - ); + return left - right; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly RcVec3f Add(RcVec3f v2) { @@ -286,7 +283,11 @@ namespace DotRecast.Core.Numerics [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RcVec3f operator -(RcVec3f left, RcVec3f right) { - return left.Subtract(right); + return new RcVec3f( + left.X - right.X, + left.Y - right.Y, + left.Z - right.Z + ); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/DotRecast.Core/Numerics/RcVecExtensions.cs b/src/DotRecast.Core/Numerics/RcVecExtensions.cs index 22e1483..008cd7f 100644 --- a/src/DotRecast.Core/Numerics/RcVecExtensions.cs +++ b/src/DotRecast.Core/Numerics/RcVecExtensions.cs @@ -16,5 +16,17 @@ namespace DotRecast.Core.Numerics default: throw new IndexOutOfRangeException("vector2f index out of range"); } } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Get(this RcVec3f v, int i) + { + switch (i) + { + case 0: return v.X; + case 1: return v.Y; + case 2: return v.Z; + default: throw new IndexOutOfRangeException("vector3f index out of range"); + } + } } } \ No newline at end of file diff --git a/src/DotRecast.Core/RcIntersections.cs b/src/DotRecast.Core/RcIntersections.cs index 4ec130b..736b20f 100644 --- a/src/DotRecast.Core/RcIntersections.cs +++ b/src/DotRecast.Core/RcIntersections.cs @@ -29,9 +29,9 @@ namespace DotRecast.Core { t = 0; float v, w; - RcVec3f ab = b.Subtract(a); - RcVec3f ac = c.Subtract(a); - RcVec3f qp = sp.Subtract(sq); + RcVec3f ab = RcVec3f.Subtract(b, a); + RcVec3f ac = RcVec3f.Subtract(c, a); + RcVec3f qp = RcVec3f.Subtract(sp, sq); // Compute triangle normal. Can be precalculated or cached if // intersecting multiple segments against the same triangle @@ -48,7 +48,7 @@ namespace DotRecast.Core // Compute intersection t value of pq with plane of triangle. A ray // intersects iff 0 <= t. Segment intersects iff 0 <= t <= 1. Delay // dividing by d until intersection has been found to pierce triangle - RcVec3f ap = sp.Subtract(a); + RcVec3f ap = RcVec3f.Subtract(sp, a); t = RcVec3f.Dot(ap, norm); if (t < 0.0f) { @@ -93,18 +93,18 @@ namespace DotRecast.Core for (int i = 0; i < 3; i++) { - if (Math.Abs(d[i]) < EPS) + if (Math.Abs(d.Get(i)) < EPS) { - if (sp[i] < amin[i] || sp[i] > amax[i]) + if (sp.Get(i) < amin.Get(i) || sp.Get(i) > amax.Get(i)) { return false; } } else { - float ood = 1.0f / d[i]; - float t1 = (amin[i] - sp[i]) * ood; - float t2 = (amax[i] - sp[i]) * ood; + float ood = 1.0f / d.Get(i); + float t1 = (amin.Get(i) - sp.Get(i)) * ood; + float t2 = (amax.Get(i) - sp.Get(i)) * ood; if (t1 > t2) { diff --git a/src/DotRecast.Detour.Crowd/DtCrowd.cs b/src/DotRecast.Detour.Crowd/DtCrowd.cs index 8a801f8..e5231bd 100644 --- a/src/DotRecast.Detour.Crowd/DtCrowd.cs +++ b/src/DotRecast.Detour.Crowd/DtCrowd.cs @@ -904,7 +904,7 @@ namespace DotRecast.Detour.Crowd } // Check for overlap. - RcVec3f diff = pos.Subtract(ag.npos); + RcVec3f diff = RcVec3f.Subtract(pos, ag.npos); if (Math.Abs(diff.Y) >= (height + ag.option.height) / 2.0f) { continue; @@ -1077,7 +1077,7 @@ namespace DotRecast.Detour.Crowd { DtCrowdAgent nei = ag.neis[j].agent; - RcVec3f diff = ag.npos.Subtract(nei.npos); + RcVec3f diff = RcVec3f.Subtract(ag.npos, nei.npos); diff.Y = 0; float distSqr = RcVec3f.LenSqr(diff); @@ -1224,7 +1224,7 @@ namespace DotRecast.Detour.Crowd { DtCrowdAgent nei = ag.neis[j].agent; long idx1 = nei.idx; - RcVec3f diff = ag.npos.Subtract(nei.npos); + RcVec3f diff = RcVec3f.Subtract(ag.npos, nei.npos); diff.Y = 0; float dist = RcVec3f.LenSqr(diff); diff --git a/src/DotRecast.Detour.Crowd/DtCrowdAgent.cs b/src/DotRecast.Detour.Crowd/DtCrowdAgent.cs index 46553c0..b46b02a 100644 --- a/src/DotRecast.Detour.Crowd/DtCrowdAgent.cs +++ b/src/DotRecast.Detour.Crowd/DtCrowdAgent.cs @@ -113,7 +113,7 @@ namespace DotRecast.Detour.Crowd { // Fake dynamic constraint. float maxDelta = option.maxAcceleration * dt; - RcVec3f dv = nvel.Subtract(vel); + RcVec3f dv = RcVec3f.Subtract(nvel, vel); float ds = dv.Length(); if (ds > maxDelta) dv = dv.Scale(maxDelta / ds); @@ -167,8 +167,8 @@ namespace DotRecast.Detour.Crowd var p0 = corners[ip0].pos; var p1 = corners[ip1].pos; - var dir0 = p0.Subtract(npos); - var dir1 = p1.Subtract(npos); + var dir0 = RcVec3f.Subtract(p0, npos); + var dir1 = RcVec3f.Subtract(p1, npos); dir0.Y = 0; dir1.Y = 0; @@ -191,7 +191,7 @@ namespace DotRecast.Detour.Crowd RcVec3f dir = new RcVec3f(); if (0 < corners.Count) { - dir = corners[0].pos.Subtract(npos); + dir = RcVec3f.Subtract(corners[0].pos, npos); dir.Y = 0; dir.Normalize(); } diff --git a/src/DotRecast.Detour.Crowd/DtObstacleAvoidanceQuery.cs b/src/DotRecast.Detour.Crowd/DtObstacleAvoidanceQuery.cs index ee3ceb3..e928fd4 100644 --- a/src/DotRecast.Detour.Crowd/DtObstacleAvoidanceQuery.cs +++ b/src/DotRecast.Detour.Crowd/DtObstacleAvoidanceQuery.cs @@ -126,9 +126,9 @@ namespace DotRecast.Detour.Crowd RcVec3f orig = new RcVec3f(); RcVec3f dv = new RcVec3f(); - cir.dp = pb.Subtract(pa); + cir.dp = RcVec3f.Subtract(pb, pa); cir.dp.Normalize(); - dv = cir.dvel.Subtract(dvel); + dv = RcVec3f.Subtract(cir.dvel, dvel); float a = DtUtils.TriArea2D(orig, cir.dp, dv); if (a < 0.01f) @@ -161,7 +161,7 @@ namespace DotRecast.Detour.Crowd tmin = 0; tmax = 0; - RcVec3f s = c1.Subtract(c0); + RcVec3f s = RcVec3f.Subtract(c1, c0); float r = r0 + r1; float c = s.Dot2D(s) - r * r; float a = v.Dot2D(v); @@ -185,8 +185,8 @@ namespace DotRecast.Detour.Crowd private bool IsectRaySeg(RcVec3f ap, RcVec3f u, RcVec3f bp, RcVec3f bq, ref float t) { - RcVec3f v = bq.Subtract(bp); - RcVec3f w = ap.Subtract(bp); + RcVec3f v = RcVec3f.Subtract(bq, bp); + RcVec3f w = RcVec3f.Subtract(ap, bp); float d = RcVec3f.Perp2D(u, v); if (Math.Abs(d) < 1e-6f) return false; @@ -238,8 +238,8 @@ namespace DotRecast.Detour.Crowd // RVO RcVec3f vab = vcand.Scale(2); - vab = vab.Subtract(vel); - vab = vab.Subtract(cir.vel); + vab = RcVec3f.Subtract(vab, vel); + vab = RcVec3f.Subtract(vab, cir.vel); // Side side += Math.Clamp(Math.Min(cir.dp.Dot2D(vab) * 0.5f + 0.5f, cir.np.Dot2D(vab) * 2), 0.0f, 1.0f); @@ -275,7 +275,7 @@ namespace DotRecast.Detour.Crowd if (seg.touch) { // Special case when the agent is very close to the segment. - RcVec3f sdir = seg.q.Subtract(seg.p); + RcVec3f sdir = RcVec3f.Subtract(seg.q, seg.p); RcVec3f snorm = new RcVec3f(); snorm.X = -sdir.Z; snorm.Z = sdir.X; diff --git a/src/DotRecast.Detour.Crowd/DtPathCorridor.cs b/src/DotRecast.Detour.Crowd/DtPathCorridor.cs index 2711b26..5b27d5d 100644 --- a/src/DotRecast.Detour.Crowd/DtPathCorridor.cs +++ b/src/DotRecast.Detour.Crowd/DtPathCorridor.cs @@ -192,7 +192,7 @@ namespace DotRecast.Detour.Crowd dist = Math.Min(dist + 0.01f, pathOptimizationRange); // Adjust ray length. - var delta = next.Subtract(m_pos); + var delta = RcVec3f.Subtract(next, m_pos); RcVec3f goal = RcVec3f.Mad(m_pos, delta, pathOptimizationRange / dist); var status = navquery.Raycast(m_path[0], m_pos, goal, filter, 0, 0, out var rayHit); diff --git a/src/DotRecast.Detour.Extras/Jumplink/EdgeSampler.cs b/src/DotRecast.Detour.Extras/Jumplink/EdgeSampler.cs index 9ab300a..f97ec55 100644 --- a/src/DotRecast.Detour.Extras/Jumplink/EdgeSampler.cs +++ b/src/DotRecast.Detour.Extras/Jumplink/EdgeSampler.cs @@ -16,7 +16,7 @@ namespace DotRecast.Detour.Extras.Jumplink public EdgeSampler(JumpEdge edge, Trajectory trajectory) { this.trajectory = trajectory; - ax = edge.sq.Subtract(edge.sp); + ax = RcVec3f.Subtract(edge.sq, edge.sp); ax.Normalize(); az.Set(ax.Z, 0, -ax.X); az.Normalize(); diff --git a/src/DotRecast.Detour/DtConvexConvexIntersections.cs b/src/DotRecast.Detour/DtConvexConvexIntersections.cs index 617fda9..3751750 100644 --- a/src/DotRecast.Detour/DtConvexConvexIntersections.cs +++ b/src/DotRecast.Detour/DtConvexConvexIntersections.cs @@ -58,8 +58,8 @@ namespace DotRecast.Detour a1.Set(p, 3 * ((ai + n - 1) % n)); // prev a b1.Set(q, 3 * ((bi + m - 1) % m)); // prev b - RcVec3f A = a.Subtract(a1); - RcVec3f B = b.Subtract(b1); + RcVec3f A = RcVec3f.Subtract(a, a1); + RcVec3f B = RcVec3f.Subtract(b, b1); float cross = B.X * A.Z - A.X * B.Z; // TriArea2D({0, 0}, A, B); float aHB = DtUtils.TriArea2D(b1, b, a); diff --git a/src/DotRecast.Detour/DtFindNearestPolyQuery.cs b/src/DotRecast.Detour/DtFindNearestPolyQuery.cs index 06e6c4e..6390bbb 100644 --- a/src/DotRecast.Detour/DtFindNearestPolyQuery.cs +++ b/src/DotRecast.Detour/DtFindNearestPolyQuery.cs @@ -28,7 +28,7 @@ namespace DotRecast.Detour // If a point is directly over a polygon and closer than // climb height, favor that instead of straight line nearest point. float d = 0; - RcVec3f diff = _center.Subtract(closestPtPoly); + RcVec3f diff = RcVec3f.Subtract(_center, closestPtPoly); if (posOverPoly) { d = Math.Abs(diff.Y) - tile.data.header.walkableClimb; diff --git a/src/DotRecast.Detour/DtNavMesh.cs b/src/DotRecast.Detour/DtNavMesh.cs index 4955447..b43e2f9 100644 --- a/src/DotRecast.Detour/DtNavMesh.cs +++ b/src/DotRecast.Detour/DtNavMesh.cs @@ -1352,7 +1352,7 @@ namespace DotRecast.Detour nearestPt = RcVec3f.Zero; bool overPoly = false; - RcVec3f bmin = center.Subtract(halfExtents); + RcVec3f bmin = RcVec3f.Subtract(center, halfExtents); RcVec3f bmax = center.Add(halfExtents); // Get nearby polygons from proximity grid. @@ -1369,7 +1369,7 @@ namespace DotRecast.Detour // If a point is directly over a polygon and closer than // climb height, favor that instead of straight line nearest point. - RcVec3f diff = center.Subtract(closestPtPoly); + RcVec3f diff = RcVec3f.Subtract(center, closestPtPoly); if (posOverPoly) { d = Math.Abs(diff.Y) - tile.data.header.walkableClimb; diff --git a/src/DotRecast.Detour/DtNavMeshQuery.cs b/src/DotRecast.Detour/DtNavMeshQuery.cs index 152a44e..71b0253 100644 --- a/src/DotRecast.Detour/DtNavMeshQuery.cs +++ b/src/DotRecast.Detour/DtNavMeshQuery.cs @@ -679,7 +679,7 @@ namespace DotRecast.Detour } // Find tiles the query touches. - RcVec3f bmin = center.Subtract(halfExtents); + RcVec3f bmin = RcVec3f.Subtract(center, halfExtents); RcVec3f bmax = center.Add(halfExtents); foreach (var t in QueryTiles(center, halfExtents)) { @@ -699,7 +699,7 @@ namespace DotRecast.Detour return RcImmutableArray.Empty; } - RcVec3f bmin = center.Subtract(halfExtents); + RcVec3f bmin = RcVec3f.Subtract(center, halfExtents); RcVec3f bmax = center.Add(halfExtents); m_nav.CalcTileLoc(bmin, out var minx, out var miny); m_nav.CalcTileLoc(bmax, out var maxx, out var maxy); @@ -2179,7 +2179,7 @@ namespace DotRecast.Detour RcVec3f lastPos = RcVec3f.Zero; curPos = startPos; - var dir = endPos.Subtract(startPos); + var dir = RcVec3f.Subtract(endPos, startPos); DtMeshTile prevTile, tile, nextTile; DtPoly prevPoly, poly, nextPoly; @@ -2343,8 +2343,8 @@ namespace DotRecast.Detour curPos = RcVec3f.Mad(startPos, dir, hit.t); var e1 = verts[segMax]; var e2 = verts[(segMax + 1) % nv]; - var eDir = e2.Subtract(e1); - var diff = curPos.Subtract(e1); + var eDir = RcVec3f.Subtract(e2, e1); + var diff = RcVec3f.Subtract(curPos, e1); float s = RcMath.Sqr(eDir.X) > RcMath.Sqr(eDir.Z) ? diff.X / eDir.X : diff.Z / eDir.Z; curPos.Y = e1.Y + eDir.Y * s; @@ -3301,7 +3301,7 @@ namespace DotRecast.Detour // Calc hit normal. if (hasBestV) { - var tangent = bestvi.Subtract(bestvj); + var tangent = RcVec3f.Subtract(bestvi, bestvj); hitNormal.X = tangent.Z; hitNormal.Y = 0; hitNormal.Z = -tangent.X; diff --git a/src/DotRecast.Detour/DtUtils.cs b/src/DotRecast.Detour/DtUtils.cs index ce88867..8580a84 100644 --- a/src/DotRecast.Detour/DtUtils.cs +++ b/src/DotRecast.Detour/DtUtils.cs @@ -215,9 +215,9 @@ namespace DotRecast.Detour const float EPS = 1e-6f; h = 0; - RcVec3f v0 = c.Subtract(a); - RcVec3f v1 = b.Subtract(a); - RcVec3f v2 = p.Subtract(a); + RcVec3f v0 = RcVec3f.Subtract(c, a); + RcVec3f v1 = RcVec3f.Subtract(b, a); + RcVec3f v2 = RcVec3f.Subtract(p, a); // Compute scaled barycentric coordinates float denom = v0.X * v1.Z - v0.Z * v1.X; @@ -353,15 +353,15 @@ namespace DotRecast.Detour segMin = -1; segMax = -1; - var dir = p1.Subtract(p0); + var dir = RcVec3f.Subtract(p1, p0); var p0v = p0; for (int i = 0, j = nverts - 1; i < nverts; j = i++) { RcVec3f vpj = verts[j]; RcVec3f vpi = verts[i]; - var edge = vpi.Subtract(vpj); - var diff = p0v.Subtract(vpj); + var edge = RcVec3f.Subtract(vpi, vpj); + var diff = RcVec3f.Subtract(p0v, vpj); float n = RcVec3f.Perp2D(edge, diff); float d = RcVec3f.Perp2D(dir, edge); if (Math.Abs(d) < EPS) @@ -422,9 +422,9 @@ namespace DotRecast.Detour s = 0; t = 0; - RcVec3f u = aq.Subtract(ap); - RcVec3f v = bq.Subtract(bp); - RcVec3f w = ap.Subtract(bp); + RcVec3f u = RcVec3f.Subtract(aq, ap); + RcVec3f v = RcVec3f.Subtract(bq, bp); + RcVec3f w = RcVec3f.Subtract(ap, bp); float d = RcVec3f.PerpXZ(u, v); if (Math.Abs(d) < 1e-6f) { diff --git a/src/DotRecast.Recast.Demo/Tools/TestNavmeshSampleTool.cs b/src/DotRecast.Recast.Demo/Tools/TestNavmeshSampleTool.cs index 9f9e43d..8e2b585 100644 --- a/src/DotRecast.Recast.Demo/Tools/TestNavmeshSampleTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/TestNavmeshSampleTool.cs @@ -507,7 +507,7 @@ public class TestNavmeshSampleTool : ISampleTool continue; } - RcVec3f delta = s3.Subtract(s.vmin); + RcVec3f delta = RcVec3f.Subtract(s3, s.vmin); RcVec3f p0 = RcVec3f.Mad(s.vmin, delta, 0.5f); RcVec3f norm = new RcVec3f(delta.Z, 0, -delta.X); norm.Normalize(); diff --git a/src/DotRecast.Recast.Toolset/Tools/RcCrowdTool.cs b/src/DotRecast.Recast.Toolset/Tools/RcCrowdTool.cs index 3e1d57a..eb9ef04 100644 --- a/src/DotRecast.Recast.Toolset/Tools/RcCrowdTool.cs +++ b/src/DotRecast.Recast.Toolset/Tools/RcCrowdTool.cs @@ -294,7 +294,7 @@ namespace DotRecast.Recast.Toolset.Tools private RcVec3f CalcVel(RcVec3f pos, RcVec3f tgt, float speed) { - RcVec3f vel = tgt.Subtract(pos); + RcVec3f vel = RcVec3f.Subtract(tgt, pos); vel.Y = 0.0f; vel.Normalize(); return vel.Scale(speed); diff --git a/src/DotRecast.Recast.Toolset/Tools/RcTestNavMeshTool.cs b/src/DotRecast.Recast.Toolset/Tools/RcTestNavMeshTool.cs index d7ca8f0..88e94a4 100644 --- a/src/DotRecast.Recast.Toolset/Tools/RcTestNavMeshTool.cs +++ b/src/DotRecast.Recast.Toolset/Tools/RcTestNavMeshTool.cs @@ -73,7 +73,7 @@ namespace DotRecast.Recast.Toolset.Tools : false; // Find movement delta. - RcVec3f delta = steerPos.Subtract(iterPos); + RcVec3f delta = RcVec3f.Subtract(steerPos, iterPos); float len = (float)Math.Sqrt(RcVec3f.Dot(delta, delta)); // If the steer target is end of path or off-mesh link, do not move past the location. if ((endOfPath || offMeshConnection) && len < STEP_SIZE) diff --git a/src/DotRecast.Recast/RcAreas.cs b/src/DotRecast.Recast/RcAreas.cs index 7157554..c2b0c86 100644 --- a/src/DotRecast.Recast/RcAreas.cs +++ b/src/DotRecast.Recast/RcAreas.cs @@ -760,12 +760,12 @@ namespace DotRecast.Recast RcVec3f vertC = new RcVec3f(verts.AsSpan(vertIndexC * 3)); // From A to B on the x/z plane - RcVec3f prevSegmentDir = vertB.Subtract(vertA); + RcVec3f prevSegmentDir = RcVec3f.Subtract(vertB, vertA); prevSegmentDir.Y = 0; // Squash onto x/z plane prevSegmentDir.SafeNormalize(); // From B to C on the x/z plane - RcVec3f currSegmentDir = vertC.Subtract(vertB); + RcVec3f currSegmentDir = RcVec3f.Subtract(vertC, vertB); currSegmentDir.Y = 0; // Squash onto x/z plane currSegmentDir.SafeNormalize(); diff --git a/test/DotRecast.Detour.Crowd.Test/AbstractCrowdTest.cs b/test/DotRecast.Detour.Crowd.Test/AbstractCrowdTest.cs index 44cbb7b..8fd4606 100644 --- a/test/DotRecast.Detour.Crowd.Test/AbstractCrowdTest.cs +++ b/test/DotRecast.Detour.Crowd.Test/AbstractCrowdTest.cs @@ -153,7 +153,7 @@ public class AbstractCrowdTest protected RcVec3f CalcVel(RcVec3f pos, RcVec3f tgt, float speed) { - RcVec3f vel = tgt.Subtract(pos); + RcVec3f vel = RcVec3f.Subtract(tgt, pos); vel.Y = 0.0f; vel.Normalize(); vel = vel.Scale(speed);