mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Box Simd (#6193)
* Box Simd * Add 256 bit version of GetAABB * Add AABB bechmarks * No real diff between 128 & 256, so removing 256 | Method | Mean | Error | StdDev | Ratio | |----------- |----------:|----------:|----------:|------:| | GetAABB | 5.8107 ns | 0.0154 ns | 0.0137 ns | 1.00 | | GetAABB128 | 0.4927 ns | 0.0003 ns | 0.0002 ns | 0.08 | | GetAABB256 | 0.4332 ns | 0.0006 ns | 0.0006 ns | 0.07 | * Add Box2Rotated.Transform Benchmark * Results 20% faster and much smaller code. Also I don't think it inlined RotateVec * Add Matrix3x2Helper.TransformBox() benchmark new: | Method | Mean | Error | StdDev | Code Size | |---------- |---------:|----------:|----------:|----------:| | Transform | 2.463 ns | 0.0766 ns | 0.0679 ns | 216 B | old: | Method | Mean | Error | StdDev | Median | Code Size | |---------- |---------:|----------:|----------:|---------:|----------:| | Transform | 9.469 ns | 0.2140 ns | 0.5408 ns | 9.206 ns | 621 B | * Fix polygon constructor * SlimPolygonBenchmark * use new SimdHelper for other methods * Fix bugs * Use new methods * Simd SlimPolygon.ComputeAABB * Move simd transform to physics * Cleanup * Remove uneccesary Unsafe.SkipInit * These tests all work on master * Add Transform.MulSimd test * Add SlimPolygon constructor tests * Add ComputeAABB test --------- Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
@@ -3,7 +3,6 @@ using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
|
||||
|
||||
namespace Robust.Shared.Maths;
|
||||
|
||||
public static class Matrix3Helpers
|
||||
@@ -33,38 +32,52 @@ public static class Matrix3Helpers
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Box2 TransformBox(this Matrix3x2 refFromBox, Box2Rotated box)
|
||||
public static Box2 TransformBox(this Matrix3x2 refFromBox, in Box2Rotated box)
|
||||
{
|
||||
return (box.Transform * refFromBox).TransformBox(box.Box);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void TransformBox(
|
||||
this Matrix3x2 refFromBox,
|
||||
in Box2Rotated box,
|
||||
out Vector128<float> x,
|
||||
out Vector128<float> y)
|
||||
{
|
||||
(box.Transform * refFromBox).TransformBox(box.Box, out x, out y);
|
||||
}
|
||||
|
||||
public static Box2 TransformBox(this Matrix3x2 refFromBox, in Box2 box)
|
||||
{
|
||||
// Do transformation on all 4 corners of the box at once.
|
||||
// Then min/max the results to get the new AABB.
|
||||
TransformBox(refFromBox, box, out var x, out var y);
|
||||
var aabb = SimdHelpers.GetAABB(x, y);
|
||||
return Unsafe.As<Vector128<float>, Box2>(ref aabb);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies a transformation matrix to all of a box's corners and returns their coordinates in two simd vectors.
|
||||
/// </summary>
|
||||
/// <remarks>The corners are ordered clockwise, starting from what was the bottom left corner prior to the transformation.</remarks>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void TransformBox(
|
||||
this Matrix3x2 refFromBox,
|
||||
in Box2 box,
|
||||
out Vector128<float> x,
|
||||
out Vector128<float> y)
|
||||
{
|
||||
var boxVec = Unsafe.As<Box2, Vector128<float>>(ref Unsafe.AsRef(in box));
|
||||
|
||||
// Convert box into list of X and Y values for each of the 4 corners
|
||||
var allX = Vector128.Shuffle(boxVec, Vector128.Create(0, 0, 2, 2));
|
||||
var allY = Vector128.Shuffle(boxVec, Vector128.Create(1, 3, 3, 1));
|
||||
var boxX = Vector128.Shuffle(boxVec, Vector128.Create(0, 2, 2, 0));
|
||||
var boxY = Vector128.Shuffle(boxVec, Vector128.Create(1, 1, 3, 3));
|
||||
|
||||
// Transform coordinates
|
||||
var modX = allX * Vector128.Create(refFromBox.M11);
|
||||
var modY = allX * Vector128.Create(refFromBox.M12);
|
||||
modX += allY * Vector128.Create(refFromBox.M21);
|
||||
modY += allY * Vector128.Create(refFromBox.M22);
|
||||
modX += Vector128.Create(refFromBox.M31);
|
||||
modY += Vector128.Create(refFromBox.M32);
|
||||
|
||||
// Get bounding box by finding the min and max X and Y values.
|
||||
var l = SimdHelpers.MinHorizontal128(modX);
|
||||
var b = SimdHelpers.MinHorizontal128(modY);
|
||||
var r = SimdHelpers.MaxHorizontal128(modX);
|
||||
var t = SimdHelpers.MaxHorizontal128(modY);
|
||||
|
||||
var lbrt = SimdHelpers.MergeRows128(l, b, r, t);
|
||||
return Unsafe.As<Vector128<float>, Box2>(ref lbrt);
|
||||
x = Vector128.Create(refFromBox.M31)
|
||||
+ boxX * Vector128.Create(refFromBox.M11)
|
||||
+ boxY * Vector128.Create(refFromBox.M21);
|
||||
y = Vector128.Create(refFromBox.M32)
|
||||
+ boxX * Vector128.Create(refFromBox.M12)
|
||||
+ boxY * Vector128.Create(refFromBox.M22);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,6 +89,23 @@ public static class Matrix3Helpers
|
||||
return new Angle(Math.Atan2(t.M12, t.M11));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Matrix3x2 CreateTransform(float posX, float posY, double angle)
|
||||
{
|
||||
// returns a matrix that is equivalent to returning CreateRotation(angle) * CreateTranslation(posX, posY)
|
||||
var sin = (float) Math.Sin(angle);
|
||||
var cos = (float) Math.Cos(angle);
|
||||
return new Matrix3x2
|
||||
{
|
||||
M11 = cos,
|
||||
M21 = -sin,
|
||||
M31 = posX,
|
||||
M12 = sin,
|
||||
M22 = cos,
|
||||
M32 = posY,
|
||||
};
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Matrix3x2 CreateTransform(float posX, float posY, double angle, float scaleX = 1, float scaleY = 1)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user