@@ -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