From 7eba4e0c9d4a3c9b57ea8d20c5afefe1f52e7b6b Mon Sep 17 00:00:00 2001 From: ikpil Date: Wed, 25 Oct 2023 23:44:01 +0900 Subject: [PATCH] refactor: RcVec3f.Min/Max --- src/DotRecast.Core/Numerics/RcVec3f.cs | 38 ++++++------------- src/DotRecast.Core/Numerics/RcVecUtils.cs | 26 +++++++++++-- src/DotRecast.Detour.Extras/BVTreeBuilder.cs | 4 +- src/DotRecast.Detour/DtNavMesh.cs | 4 +- src/DotRecast.Detour/DtNavMeshBuilder.cs | 4 +- src/DotRecast.Detour/DtNavMeshQuery.cs | 4 +- .../Geom/DemoInputGeomProvider.cs | 4 +- .../Geom/SimpleInputGeomProvider.cs | 4 +- src/DotRecast.Recast/RcAreas.cs | 4 +- src/DotRecast.Recast/RcMeshDetails.cs | 4 +- src/DotRecast.Recast/RcMeshs.cs | 5 ++- src/DotRecast.Recast/RcRasterizations.cs | 8 ++-- test/DotRecast.Core.Test/Vector3Tests.cs | 20 +++++++++- 13 files changed, 76 insertions(+), 53 deletions(-) diff --git a/src/DotRecast.Core/Numerics/RcVec3f.cs b/src/DotRecast.Core/Numerics/RcVec3f.cs index e722d45..099f792 100644 --- a/src/DotRecast.Core/Numerics/RcVec3f.cs +++ b/src/DotRecast.Core/Numerics/RcVec3f.cs @@ -148,38 +148,24 @@ namespace DotRecast.Core.Numerics return HashCode.Combine(X, Y, Z); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Min(float[] @in, int i) + public static RcVec3f Min(RcVec3f value1, RcVec3f value2) { - X = Math.Min(X, @in[i]); - Y = Math.Min(Y, @in[i + 1]); - Z = Math.Min(Z, @in[i + 2]); + return new RcVec3f( + (value1.X < value2.X) ? value1.X : value2.X, + (value1.Y < value2.Y) ? value1.Y : value2.Y, + (value1.Z < value2.Z) ? value1.Z : value2.Z + ); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Min(RcVec3f b) + public static RcVec3f Max(RcVec3f value1, RcVec3f value2) { - X = Math.Min(X, b.X); - Y = Math.Min(Y, b.Y); - Z = Math.Min(Z, b.Z); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Max(RcVec3f b) - { - X = Math.Max(X, b.X); - Y = Math.Max(Y, b.Y); - Z = Math.Max(Z, b.Z); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Max(float[] @in, int i) - { - X = Math.Max(X, @in[i]); - Y = Math.Max(Y, @in[i + 1]); - Z = Math.Max(Z, @in[i + 2]); + return new RcVec3f( + (value1.X > value2.X) ? value1.X : value2.X, + (value1.Y > value2.Y) ? value1.Y : value2.Y, + (value1.Z > value2.Z) ? value1.Z : value2.Z + ); } public override string ToString() diff --git a/src/DotRecast.Core/Numerics/RcVecUtils.cs b/src/DotRecast.Core/Numerics/RcVecUtils.cs index 2f4b20e..7ebeb70 100644 --- a/src/DotRecast.Core/Numerics/RcVecUtils.cs +++ b/src/DotRecast.Core/Numerics/RcVecUtils.cs @@ -6,7 +6,7 @@ namespace DotRecast.Core.Numerics public static class RcVecUtils { public const float EPSILON = 1e-6f; - + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Get(this RcVec2f v, int i) { @@ -122,7 +122,7 @@ namespace DotRecast.Core.Numerics v1[1] * vector2.Y + v1[2] * vector2.Z; } - + /// Returns the distance between two points. /// @param[in] v1 A point. [(x, y, z)] /// @param[in] v2 A point. [(x, y, z)] @@ -135,7 +135,7 @@ namespace DotRecast.Core.Numerics float dz = v2[i + 2] - v1.Z; return dx * dx + dy * dy + dz * dz; } - + /// Normalizes the vector if the length is greater than zero. /// If the magnitude is zero, the vector is unchanged. /// @param[in,out] v The vector to normalize. [(x, y, z)] @@ -155,5 +155,25 @@ namespace DotRecast.Core.Numerics return v; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RcVec3f Min(RcVec3f v, float[] @in, int i) + { + return new RcVec3f( + (v.X < @in[i + 0]) ? v.X : @in[i + 0], + (v.Y < @in[i + 1]) ? v.Y : @in[i + 1], + (v.Z < @in[i + 2]) ? v.Z : @in[i + 2] + ); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RcVec3f Max(RcVec3f v, float[] @in, int i) + { + return new RcVec3f( + (v.X > @in[i + 0]) ? v.X : @in[i + 0], + (v.Y > @in[i + 1]) ? v.Y : @in[i + 1], + (v.Z > @in[i + 2]) ? v.Z : @in[i + 2] + ); + } } } \ No newline at end of file diff --git a/src/DotRecast.Detour.Extras/BVTreeBuilder.cs b/src/DotRecast.Detour.Extras/BVTreeBuilder.cs index 47b065c..9ca94fd 100644 --- a/src/DotRecast.Detour.Extras/BVTreeBuilder.cs +++ b/src/DotRecast.Detour.Extras/BVTreeBuilder.cs @@ -44,8 +44,8 @@ namespace DotRecast.Detour.Extras RcVec3f bmax = new RcVec3f(data.verts.AsSpan(data.polys[i].verts[0] * 3)); for (int j = 1; j < data.polys[i].vertCount; j++) { - bmin.Min(data.verts, data.polys[i].verts[j] * 3); - bmax.Max(data.verts, data.polys[i].verts[j] * 3); + bmin = RcVecUtils.Min(bmin, data.verts, data.polys[i].verts[j] * 3); + bmax = RcVecUtils.Max(bmax, data.verts, data.polys[i].verts[j] * 3); } it.bmin[0] = Math.Clamp((int)((bmin.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff); diff --git a/src/DotRecast.Detour/DtNavMesh.cs b/src/DotRecast.Detour/DtNavMesh.cs index f9a56ec..34c3d09 100644 --- a/src/DotRecast.Detour/DtNavMesh.cs +++ b/src/DotRecast.Detour/DtNavMesh.cs @@ -406,8 +406,8 @@ namespace DotRecast.Detour for (int j = 1; j < p.vertCount; ++j) { v = p.verts[j] * 3; - bmin.Min(tile.data.verts, v); - bmax.Max(tile.data.verts, v); + bmin = RcVecUtils.Min(bmin, tile.data.verts, v); + bmax = RcVecUtils.Max(bmax, tile.data.verts, v); } if (DtUtils.OverlapBounds(qmin, qmax, bmin, bmax)) diff --git a/src/DotRecast.Detour/DtNavMeshBuilder.cs b/src/DotRecast.Detour/DtNavMeshBuilder.cs index e53f243..9381b81 100644 --- a/src/DotRecast.Detour/DtNavMeshBuilder.cs +++ b/src/DotRecast.Detour/DtNavMeshBuilder.cs @@ -162,8 +162,8 @@ namespace DotRecast.Detour var bmax = new RcVec3f(option.detailVerts.AsSpan(dv)); for (int j = 1; j < ndv; j++) { - bmin.Min(option.detailVerts, dv + j * 3); - bmax.Max(option.detailVerts, dv + j * 3); + bmin = RcVecUtils.Min(bmin, option.detailVerts, dv + j * 3); + bmax = RcVecUtils.Max(bmax, option.detailVerts, dv + j * 3); } // BV-tree uses cs for all dimensions diff --git a/src/DotRecast.Detour/DtNavMeshQuery.cs b/src/DotRecast.Detour/DtNavMeshQuery.cs index c86d1c2..e72b4bb 100644 --- a/src/DotRecast.Detour/DtNavMeshQuery.cs +++ b/src/DotRecast.Detour/DtNavMeshQuery.cs @@ -646,8 +646,8 @@ namespace DotRecast.Detour for (int j = 1; j < p.vertCount; ++j) { v = p.verts[j] * 3; - bmin.Min(tile.data.verts, v); - bmax.Max(tile.data.verts, v); + bmin = RcVecUtils.Min(bmin, tile.data.verts, v); + bmax = RcVecUtils.Max(bmax, tile.data.verts, v); } if (DtUtils.OverlapBounds(qmin, qmax, bmin, bmax)) diff --git a/src/DotRecast.Recast.Toolset/Geom/DemoInputGeomProvider.cs b/src/DotRecast.Recast.Toolset/Geom/DemoInputGeomProvider.cs index 76ad3aa..6eb11c7 100644 --- a/src/DotRecast.Recast.Toolset/Geom/DemoInputGeomProvider.cs +++ b/src/DotRecast.Recast.Toolset/Geom/DemoInputGeomProvider.cs @@ -61,8 +61,8 @@ namespace DotRecast.Recast.Toolset.Geom bmax = new RcVec3f(vertices); for (int i = 1; i < vertices.Length / 3; i++) { - bmin.Min(vertices, i * 3); - bmax.Max(vertices, i * 3); + bmin = RcVecUtils.Min(bmin, vertices, i * 3); + bmax = RcVecUtils.Max(bmax, vertices, i * 3); } _mesh = new RcTriMesh(vertices, faces); diff --git a/src/DotRecast.Recast/Geom/SimpleInputGeomProvider.cs b/src/DotRecast.Recast/Geom/SimpleInputGeomProvider.cs index b252552..33f04c4 100644 --- a/src/DotRecast.Recast/Geom/SimpleInputGeomProvider.cs +++ b/src/DotRecast.Recast/Geom/SimpleInputGeomProvider.cs @@ -81,8 +81,8 @@ namespace DotRecast.Recast.Geom bmax = new RcVec3f(vertices); for (int i = 1; i < vertices.Length / 3; i++) { - bmin.Min(vertices, i * 3); - bmax.Max(vertices, i * 3); + bmin = RcVecUtils.Min(bmin, vertices, i * 3); + bmax = RcVecUtils.Max(bmax, vertices, i * 3); } _mesh = new RcTriMesh(vertices, faces); diff --git a/src/DotRecast.Recast/RcAreas.cs b/src/DotRecast.Recast/RcAreas.cs index 49ae660..c8cdc68 100644 --- a/src/DotRecast.Recast/RcAreas.cs +++ b/src/DotRecast.Recast/RcAreas.cs @@ -461,8 +461,8 @@ namespace DotRecast.Recast RcVec3f bmax = new RcVec3f(verts); for (int i = 3; i < verts.Length; i += 3) { - bmin.Min(verts, i); - bmax.Max(verts, i); + bmin = RcVecUtils.Min(bmin, verts, i); + bmax = RcVecUtils.Max(bmax, verts, i); } bmin.Y = minY; diff --git a/src/DotRecast.Recast/RcMeshDetails.cs b/src/DotRecast.Recast/RcMeshDetails.cs index 68e0e63..f772096 100644 --- a/src/DotRecast.Recast/RcMeshDetails.cs +++ b/src/DotRecast.Recast/RcMeshDetails.cs @@ -1004,8 +1004,8 @@ namespace DotRecast.Recast RcVec3f bmax = new RcVec3f(@in); for (int i = 1; i < nin; ++i) { - bmin.Min(@in, i * 3); - bmax.Max(@in, i * 3); + bmin = RcVecUtils.Min(bmin, @in, i * 3); + bmax = RcVecUtils.Max(bmax, @in, i * 3); } int x0 = (int)MathF.Floor(bmin.X / sampleDist); diff --git a/src/DotRecast.Recast/RcMeshs.cs b/src/DotRecast.Recast/RcMeshs.cs index 34dd342..a82537e 100644 --- a/src/DotRecast.Recast/RcMeshs.cs +++ b/src/DotRecast.Recast/RcMeshs.cs @@ -20,6 +20,7 @@ freely, subject to the following restrictions: using System; using DotRecast.Core; +using DotRecast.Core.Numerics; namespace DotRecast.Recast { @@ -1230,8 +1231,8 @@ namespace DotRecast.Recast int maxVertsPerMesh = 0; for (int i = 0; i < nmeshes; ++i) { - mesh.bmin.Min(meshes[i].bmin); - mesh.bmax.Max(meshes[i].bmax); + mesh.bmin = RcVec3f.Min(mesh.bmin, meshes[i].bmin); + mesh.bmax = RcVec3f.Max(mesh.bmax, meshes[i].bmax); maxVertsPerMesh = Math.Max(maxVertsPerMesh, meshes[i].nverts); maxVerts += meshes[i].nverts; maxPolys += meshes[i].npolys; diff --git a/src/DotRecast.Recast/RcRasterizations.cs b/src/DotRecast.Recast/RcRasterizations.cs index e9988d2..df5fb2f 100644 --- a/src/DotRecast.Recast/RcRasterizations.cs +++ b/src/DotRecast.Recast/RcRasterizations.cs @@ -239,10 +239,10 @@ namespace DotRecast.Recast // Calculate the bounding box of the triangle. RcVec3f tmin = new RcVec3f(verts.AsSpan(v0 * 3)); RcVec3f tmax = new RcVec3f(verts.AsSpan(v0 * 3)); - tmin.Min(verts, v1 * 3); - tmin.Min(verts, v2 * 3); - tmax.Max(verts, v1 * 3); - tmax.Max(verts, v2 * 3); + tmin = RcVecUtils.Min(tmin, verts, v1 * 3); + tmin = RcVecUtils.Min(tmin, verts, v2 * 3); + tmax = RcVecUtils.Max(tmax, verts, v1 * 3); + tmax = RcVecUtils.Max(tmax, verts, v2 * 3); // If the triangle does not touch the bbox of the heightfield, skip the triagle. if (!OverlapBounds(heightfieldBBMin, heightfieldBBMax, tmin, tmax)) diff --git a/test/DotRecast.Core.Test/Vector3Tests.cs b/test/DotRecast.Core.Test/Vector3Tests.cs index a2f0d85..0a18fe6 100644 --- a/test/DotRecast.Core.Test/Vector3Tests.cs +++ b/test/DotRecast.Core.Test/Vector3Tests.cs @@ -145,8 +145,24 @@ public class Vector3Tests [Repeat(100000)] public void TestVectorMinMax() { - // Min - // Max + var v1 = new Vector3(Random.Shared.NextSingle(), Random.Shared.NextSingle(), Random.Shared.NextSingle()); + var v2 = new Vector3(Random.Shared.NextSingle(), Random.Shared.NextSingle(), Random.Shared.NextSingle()); + var v3 = Vector3.Min(v1, v2); + var v4 = Vector3.Max(v1, v2); + + var v11 = new RcVec3f(v1.X, v1.Y, v1.Z); + var v22 = new RcVec3f(v2.X, v2.Y, v2.Z); + var v33 = RcVec3f.Min(v11, v22); + var v44 = RcVec3f.Max(v11, v22); + + Assert.That(v3.X, Is.EqualTo(v33.X)); + Assert.That(v3.Y, Is.EqualTo(v33.Y)); + Assert.That(v3.Z, Is.EqualTo(v33.Z)); + + Assert.That(v4.X, Is.EqualTo(v44.X)); + Assert.That(v4.Y, Is.EqualTo(v44.Y)); + Assert.That(v4.Z, Is.EqualTo(v44.Z)); + } [Test]