Skip to content

Commit 3f30ff4

Browse files
committed
Perform some additional cleanup of the System.Numerics.Vector and Matrix types
1 parent ba252ac commit 3f30ff4

File tree

7 files changed

+441
-775
lines changed

7 files changed

+441
-775
lines changed

src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.Impl.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ readonly get
7272
{
7373
ThrowHelper.ThrowArgumentOutOfRangeException();
7474
}
75-
76-
return Unsafe.Add(ref Unsafe.AsRef(in this.X), row)[column];
75+
return Unsafe.Add(ref Unsafe.AsRef(in X), row)[column];
7776
}
7877

7978
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -83,7 +82,7 @@ readonly get
8382
{
8483
ThrowHelper.ThrowArgumentOutOfRangeException();
8584
}
86-
Unsafe.Add(ref this.X, row)[column] = value;
85+
Unsafe.Add(ref X, row)[column] = value;
8786
}
8887
}
8988

@@ -514,7 +513,7 @@ public readonly float GetDeterminant()
514513
[MethodImpl(MethodImplOptions.AggressiveInlining)]
515514
public override readonly int GetHashCode() => HashCode.Combine(X, Y, Z);
516515

517-
bool IEquatable<Impl>.Equals(Impl other) => Equals(in other);
516+
readonly bool IEquatable<Impl>.Equals(Impl other) => Equals(in other);
518517
}
519518
}
520519
}

src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.Impl.cs

Lines changed: 270 additions & 385 deletions
Large diffs are not rendered by default.

src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs

Lines changed: 30 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ namespace System.Numerics
1414
[Intrinsic]
1515
public struct Plane : IEquatable<Plane>
1616
{
17-
private const float NormalizeEpsilon = 1.192092896e-07f; // smallest such that 1.0+NormalizeEpsilon != 1.0
18-
1917
/// <summary>The normal vector of the plane.</summary>
2018
public Vector3 Normal;
2119

@@ -74,49 +72,15 @@ public Plane(Vector4 value)
7472
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7573
public static Plane CreateFromVertices(Vector3 point1, Vector3 point2, Vector3 point3)
7674
{
77-
if (Vector128.IsHardwareAccelerated)
78-
{
79-
Vector3 a = point2 - point1;
80-
Vector3 b = point3 - point1;
81-
82-
// N = Cross(a, b)
83-
Vector3 n = Vector3.Cross(a, b);
84-
Vector3 normal = Vector3.Normalize(n);
85-
86-
// D = - Dot(N, point1)
87-
float d = -Vector3.Dot(normal, point1);
88-
89-
return Create(normal, d);
90-
}
91-
else
92-
{
93-
float ax = point2.X - point1.X;
94-
float ay = point2.Y - point1.Y;
95-
float az = point2.Z - point1.Z;
75+
// This implementation is based on the DirectX Math Library XMPlaneFromPoints method
76+
// https://github.com/microsoft/DirectXMath/blob/master/Inc/DirectXMathMisc.inl
9677

97-
float bx = point3.X - point1.X;
98-
float by = point3.Y - point1.Y;
99-
float bz = point3.Z - point1.Z;
78+
Vector3 normal = Vector3.Normalize(Vector3.Cross(point2 - point1, point3 - point1));
10079

101-
// N=Cross(a,b)
102-
float nx = ay * bz - az * by;
103-
float ny = az * bx - ax * bz;
104-
float nz = ax * by - ay * bx;
105-
106-
// Normalize(N)
107-
float ls = nx * nx + ny * ny + nz * nz;
108-
float invNorm = 1.0f / float.Sqrt(ls);
109-
110-
Vector3 normal = Vector3.Create(
111-
nx * invNorm,
112-
ny * invNorm,
113-
nz * invNorm);
114-
115-
return Create(
116-
normal,
117-
-(normal.X * point1.X + normal.Y * point1.Y + normal.Z * point1.Z)
118-
);
119-
}
80+
return Create(
81+
normal,
82+
-Vector3.Dot(normal, point1)
83+
);
12084
}
12185

12286
/// <summary>Calculates the dot product of a plane and a 4-dimensional vector.</summary>
@@ -131,29 +95,40 @@ public static Plane CreateFromVertices(Vector3 point1, Vector3 point2, Vector3 p
13195
/// <param name="plane">The plane.</param>
13296
/// <param name="value">The 3-dimensional vector.</param>
13397
/// <returns>The dot product.</returns>
134-
public static float DotCoordinate(Plane plane, Vector3 value) => Vector3.Dot(plane.Normal, value) + plane.D;
98+
public static float DotCoordinate(Plane plane, Vector3 value)
99+
{
100+
// This implementation is based on the DirectX Math Library XMPlaneDotCoord method
101+
// https://github.com/microsoft/DirectXMath/blob/master/Inc/DirectXMathMisc.inl
102+
103+
return Dot(plane, Vector4.Create(value, 1.0f));
104+
}
135105

136106
/// <summary>Returns the dot product of a specified three-dimensional vector and the <see cref="Normal" /> vector of this plane.</summary>
137107
/// <param name="plane">The plane.</param>
138108
/// <param name="value">The three-dimensional vector.</param>
139109
/// <returns>The dot product.</returns>
140-
public static float DotNormal(Plane plane, Vector3 value) => Vector3.Dot(plane.Normal, value);
110+
public static float DotNormal(Plane plane, Vector3 value)
111+
{
112+
// This implementation is based on the DirectX Math Library XMPlaneDotNormal method
113+
// https://github.com/microsoft/DirectXMath/blob/master/Inc/DirectXMathMisc.inl
114+
115+
return Vector3.Dot(plane.Normal, value);
116+
}
141117

142118
/// <summary>Creates a new <see cref="Plane" /> object whose normal vector is the source plane's normal vector normalized.</summary>
143119
/// <param name="value">The source plane.</param>
144120
/// <returns>The normalized plane.</returns>
145-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
146121
public static Plane Normalize(Plane value)
147122
{
148-
float normalLengthSquared = value.Normal.LengthSquared();
123+
// This implementation is based on the DirectX Math Library XMPlaneNormalize method
124+
// https://github.com/microsoft/DirectXMath/blob/master/Inc/DirectXMathMisc.inl
149125

150-
if (float.Abs(normalLengthSquared - 1.0f) < NormalizeEpsilon)
151-
{
152-
// It already normalized, so we don't need to farther process.
153-
return value;
154-
}
126+
Vector128<float> lengthSquared = Vector128.Create(value.Normal.LengthSquared());
155127

156-
return (value.AsVector128() / float.Sqrt(normalLengthSquared)).AsPlane();
128+
return Vector128.AndNot(
129+
(value.AsVector128() / Vector128.Sqrt(lengthSquared)),
130+
Vector128.Equals(lengthSquared, Vector128.Create(float.PositiveInfinity))
131+
).AsPlane();
157132
}
158133

159134
/// <summary>Transforms a normalized plane by a 4x4 matrix.</summary>
@@ -162,64 +137,15 @@ public static Plane Normalize(Plane value)
162137
/// <returns>The transformed plane.</returns>
163138
/// <remarks><paramref name="plane" /> must already be normalized so that its <see cref="Normal" /> vector is of unit length before this method is called.</remarks>
164139
[MethodImpl(MethodImplOptions.AggressiveInlining)]
165-
public static Plane Transform(Plane plane, Matrix4x4 matrix)
166-
{
167-
Matrix4x4.Invert(matrix, out Matrix4x4 m);
168-
169-
float x = plane.Normal.X, y = plane.Normal.Y, z = plane.Normal.Z, w = plane.D;
170-
171-
return Create(
172-
x * m.M11 + y * m.M12 + z * m.M13 + w * m.M14,
173-
x * m.M21 + y * m.M22 + z * m.M23 + w * m.M24,
174-
x * m.M31 + y * m.M32 + z * m.M33 + w * m.M34,
175-
x * m.M41 + y * m.M42 + z * m.M43 + w * m.M44
176-
);
177-
}
140+
public static Plane Transform(Plane plane, Matrix4x4 matrix) => Vector4.Transform(plane.AsVector4(), matrix).AsPlane();
178141

179142
/// <summary>Transforms a normalized plane by a Quaternion rotation.</summary>
180143
/// <param name="plane">The normalized plane to transform.</param>
181144
/// <param name="rotation">The Quaternion rotation to apply to the plane.</param>
182145
/// <returns>A new plane that results from applying the Quaternion rotation.</returns>
183146
/// <remarks><paramref name="plane" /> must already be normalized so that its <see cref="Normal" /> vector is of unit length before this method is called.</remarks>
184147
[MethodImpl(MethodImplOptions.AggressiveInlining)]
185-
public static Plane Transform(Plane plane, Quaternion rotation)
186-
{
187-
// Compute rotation matrix.
188-
float x2 = rotation.X + rotation.X;
189-
float y2 = rotation.Y + rotation.Y;
190-
float z2 = rotation.Z + rotation.Z;
191-
192-
float wx2 = rotation.W * x2;
193-
float wy2 = rotation.W * y2;
194-
float wz2 = rotation.W * z2;
195-
float xx2 = rotation.X * x2;
196-
float xy2 = rotation.X * y2;
197-
float xz2 = rotation.X * z2;
198-
float yy2 = rotation.Y * y2;
199-
float yz2 = rotation.Y * z2;
200-
float zz2 = rotation.Z * z2;
201-
202-
float m11 = 1.0f - yy2 - zz2;
203-
float m21 = xy2 - wz2;
204-
float m31 = xz2 + wy2;
205-
206-
float m12 = xy2 + wz2;
207-
float m22 = 1.0f - xx2 - zz2;
208-
float m32 = yz2 - wx2;
209-
210-
float m13 = xz2 - wy2;
211-
float m23 = yz2 + wx2;
212-
float m33 = 1.0f - xx2 - yy2;
213-
214-
float x = plane.Normal.X, y = plane.Normal.Y, z = plane.Normal.Z;
215-
216-
return Create(
217-
x * m11 + y * m21 + z * m31,
218-
x * m12 + y * m22 + z * m32,
219-
x * m13 + y * m23 + z * m33,
220-
plane.D
221-
);
222-
}
148+
public static Plane Transform(Plane plane, Quaternion rotation) => Vector4.Transform(plane.AsVector4(), rotation).AsPlane();
223149

224150
/// <summary>Returns a value that indicates whether two planes are equal.</summary>
225151
/// <param name="value1">The first plane to compare.</param>

0 commit comments

Comments
 (0)