Refactor engine to support double-precision vectors
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
#if USE_LARGE_WORLDS
|
||||
using Real = System.Double;
|
||||
#else
|
||||
using Real = System.Single;
|
||||
#endif
|
||||
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -185,6 +191,17 @@ namespace FlaxEngine
|
||||
Z = value.Z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Double3" /> struct.
|
||||
/// </summary>
|
||||
/// <param name="value">A vector containing the values with which to initialize the X, Y and Z components.</param>
|
||||
public Double3(Float3 value)
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
Z = value.Z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Double3" /> struct.
|
||||
/// </summary>
|
||||
@@ -1208,7 +1225,7 @@ namespace FlaxEngine
|
||||
double dot = Mathd.Clamp(Dot(from.Normalized, to.Normalized), -1.0, 1.0);
|
||||
if (Math.Abs(dot) > (1 - Mathd.Epsilon))
|
||||
return dot > 0.0 ? 0.0 : 180.0;
|
||||
return Mathd.Acos(dot) * Mathd.RadiansToDegrees;
|
||||
return Math.Acos(dot) * Mathd.RadiansToDegrees;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1295,10 +1312,7 @@ namespace FlaxEngine
|
||||
/// <param name="vector">The source vector.</param>
|
||||
/// <param name="normal">Normal of the surface.</param>
|
||||
/// <param name="result">When the method completes, contains the reflected vector.</param>
|
||||
/// <remarks>
|
||||
/// Reflect only gives the direction of a reflection off a surface, it does not determine
|
||||
/// whether the original vector was close enough to the surface to hit it.
|
||||
/// </remarks>
|
||||
/// <remarks>Reflect only gives the direction of a reflection off a surface, it does not determine whether the original vector was close enough to the surface to hit it.</remarks>
|
||||
public static void Reflect(ref Double3 vector, ref Double3 normal, out Double3 result)
|
||||
{
|
||||
double dot = vector.X * normal.X + vector.Y * normal.Y + vector.Z * normal.Z;
|
||||
@@ -1320,95 +1334,6 @@ namespace FlaxEngine
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Orthogonalizes a list of vectors.
|
||||
/// </summary>
|
||||
/// <param name="destination">The list of orthogonalized vectors.</param>
|
||||
/// <param name="source">The list of vectors to orthogonalize.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Orthogonalization is the process of making all vectors orthogonal to each other. This
|
||||
/// means that any given vector in the list will be orthogonal to any other given vector in the
|
||||
/// list.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Because this method uses the modified Gram-Schmidt process, the resulting vectors
|
||||
/// tend to be numerically unstable. The numeric stability decreases according to the vectors
|
||||
/// position in the list so that the first vector is the most stable and the last vector is the
|
||||
/// least stable.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="source" /> or <paramref name="destination" /> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination" /> is shorter in length than <paramref name="source" />.</exception>
|
||||
public static void Orthogonalize(Double3[] destination, params Double3[] source)
|
||||
{
|
||||
//Uses the modified Gram-Schmidt process.
|
||||
//q1 = m1
|
||||
//q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1
|
||||
//q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2
|
||||
//q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3
|
||||
//q5 = ...
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
if (destination.Length < source.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(destination), "The destination array must be of same length or larger length than the source array.");
|
||||
for (var i = 0; i < source.Length; ++i)
|
||||
{
|
||||
Double3 v = source[i];
|
||||
for (var r = 0; r < i; ++r)
|
||||
v -= Dot(destination[r], v) / Dot(destination[r], destination[r]) * destination[r];
|
||||
destination[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Orthonormalizes a list of vectors.
|
||||
/// </summary>
|
||||
/// <param name="destination">The list of orthonormalized vectors.</param>
|
||||
/// <param name="source">The list of vectors to orthonormalize.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Orthonormalization is the process of making all vectors orthogonal to each
|
||||
/// other and making all vectors of unit length. This means that any given vector will
|
||||
/// be orthogonal to any other given vector in the list.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Because this method uses the modified Gram-Schmidt process, the resulting vectors
|
||||
/// tend to be numerically unstable. The numeric stability decreases according to the vectors
|
||||
/// position in the list so that the first vector is the most stable and the last vector is the
|
||||
/// least stable.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="source" /> or <paramref name="destination" /> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination" /> is shorter in length than <paramref name="source" />.</exception>
|
||||
public static void Orthonormalize(Double3[] destination, params Double3[] source)
|
||||
{
|
||||
//Uses the modified Gram-Schmidt process.
|
||||
//Because we are making unit vectors, we can optimize the math for orthogonalization
|
||||
//and simplify the projection operation to remove the division.
|
||||
//q1 = m1 / |m1|
|
||||
//q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1|
|
||||
//q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2|
|
||||
//q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3|
|
||||
//q5 = ...
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
if (destination.Length < source.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(destination), "The destination array must be of same length or larger length than the source array.");
|
||||
for (var i = 0; i < source.Length; ++i)
|
||||
{
|
||||
Double3 v = source[i];
|
||||
for (var r = 0; r < i; ++r)
|
||||
v -= Dot(destination[r], v) * destination[r];
|
||||
v.Normalize();
|
||||
destination[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a 3D vector by the given <see cref="Quaternion" /> rotation.
|
||||
/// </summary>
|
||||
@@ -1446,51 +1371,6 @@ namespace FlaxEngine
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an array of vectors by the given <see cref="Quaternion" /> rotation.
|
||||
/// </summary>
|
||||
/// <param name="source">The array of vectors to transform.</param>
|
||||
/// <param name="rotation">The <see cref="Quaternion" /> rotation to apply.</param>
|
||||
/// <param name="destination">The array for which the transformed vectors are stored. This array may be the same array as <paramref name="source" />.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="source" /> or <paramref name="destination" /> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination" /> is shorter in length than <paramref name="source" />.</exception>
|
||||
public static void Transform(Double3[] source, ref Quaternion rotation, Double3[] destination)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
if (destination.Length < source.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(destination), "The destination array must be of same length or larger length than the source array.");
|
||||
double x = rotation.X + rotation.X;
|
||||
double y = rotation.Y + rotation.Y;
|
||||
double z = rotation.Z + rotation.Z;
|
||||
double wx = rotation.W * x;
|
||||
double wy = rotation.W * y;
|
||||
double wz = rotation.W * z;
|
||||
double xx = rotation.X * x;
|
||||
double xy = rotation.X * y;
|
||||
double xz = rotation.X * z;
|
||||
double yy = rotation.Y * y;
|
||||
double yz = rotation.Y * z;
|
||||
double zz = rotation.Z * z;
|
||||
double num1 = 1.0 - yy - zz;
|
||||
double num2 = xy - wz;
|
||||
double num3 = xz + wy;
|
||||
double num4 = xy + wz;
|
||||
double num5 = 1.0 - xx - zz;
|
||||
double num6 = yz - wx;
|
||||
double num7 = xz - wy;
|
||||
double num8 = yz + wx;
|
||||
double num9 = 1.0 - xx - yy;
|
||||
for (var i = 0; i < source.Length; i++)
|
||||
{
|
||||
destination[i] = new Double3(source[i].X * num1 + source[i].Y * num2 + source[i].Z * num3,
|
||||
source[i].X * num4 + source[i].Y * num5 + source[i].Z * num6,
|
||||
source[i].X * num7 + source[i].Y * num8 + source[i].Z * num9);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a 3D vector by the given <see cref="Matrix3x3"/>.
|
||||
/// </summary>
|
||||
@@ -1555,26 +1435,6 @@ namespace FlaxEngine
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an array of 3D vectors by the given <see cref="Matrix" />.
|
||||
/// </summary>
|
||||
/// <param name="source">The array of vectors to transform.</param>
|
||||
/// <param name="transform">The transformation <see cref="Matrix" />.</param>
|
||||
/// <param name="destination">The array for which the transformed vectors are stored.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="source" /> or <paramref name="destination" /> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination" /> is shorter in length than <paramref name="source" />.</exception>
|
||||
public static void Transform(Double3[] source, ref Matrix transform, Double4[] destination)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
if (destination.Length < source.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(destination), "The destination array must be of same length or larger length than the source array.");
|
||||
for (var i = 0; i < source.Length; ++i)
|
||||
Transform(ref source[i], ref transform, out destination[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a coordinate transformation using the given <see cref="Matrix" />.
|
||||
/// </summary>
|
||||
@@ -1619,35 +1479,6 @@ namespace FlaxEngine
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a coordinate transformation on an array of vectors using the given <see cref="Matrix" />.
|
||||
/// </summary>
|
||||
/// <param name="source">The array of coordinate vectors to transform.</param>
|
||||
/// <param name="transform">The transformation <see cref="Matrix" />.</param>
|
||||
/// <param name="destination">The array for which the transformed vectors are stored. This array may be the same array as <paramref name="source" />.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="source" /> or <paramref name="destination" /> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination" /> is shorter in length than
|
||||
/// <paramref name="source" />.
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// A coordinate transform performs the transformation with the assumption that the w component
|
||||
/// is one. The four dimensional vector obtained from the transformation operation has each
|
||||
/// component in the vector divided by the w component. This forces the w component to be one and
|
||||
/// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working
|
||||
/// with coordinates as the w component can safely be ignored.
|
||||
/// </remarks>
|
||||
public static void TransformCoordinate(Double3[] source, ref Matrix transform, Double3[] destination)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
if (destination.Length < source.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(destination), "The destination array must be of same length or larger length than the source array.");
|
||||
for (var i = 0; i < source.Length; i++)
|
||||
TransformCoordinate(ref source[i], ref transform, out destination[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a normal transformation using the given <see cref="Matrix" />.
|
||||
/// </summary>
|
||||
@@ -1687,33 +1518,6 @@ namespace FlaxEngine
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a normal transformation on an array of vectors using the given <see cref="Matrix" />.
|
||||
/// </summary>
|
||||
/// <param name="source">The array of normal vectors to transform.</param>
|
||||
/// <param name="transform">The transformation <see cref="Matrix" />.</param>
|
||||
/// <param name="destination">The array for which the transformed vectors are stored. This array may be the same array as <paramref name="source" />.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="source" /> or <paramref name="destination" /> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="destination" /> is shorter in length than <paramref name="source" />.</exception>
|
||||
/// <remarks>
|
||||
/// A normal transform performs the transformation with the assumption that the w component
|
||||
/// is zero. This causes the fourth row and fourth column of the matrix to be unused. The
|
||||
/// end result is a vector that is not translated, but all other transformation properties
|
||||
/// apply. This is often preferred for normal vectors as normals purely represent direction
|
||||
/// rather than location because normal vectors should not be translated.
|
||||
/// </remarks>
|
||||
public static void TransformNormal(Double3[] source, ref Matrix transform, Double3[] destination)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
if (destination.Length < source.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(destination), "The destination array must be of same length or larger length than the source array.");
|
||||
for (var i = 0; i < source.Length; ++i)
|
||||
TransformNormal(ref source[i], ref transform, out destination[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
@@ -1935,6 +1739,26 @@ namespace FlaxEngine
|
||||
return !Mathd.NearEqual(left.X, right.X) || !Mathd.NearEqual(left.Y, right.Y) || !Mathd.NearEqual(left.Z, right.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="Double3" /> to <see cref="Float3" />.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator Float3(Double3 value)
|
||||
{
|
||||
return new Float3((float)value.X, (float)value.Y, (float)value.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="Double3" /> to <see cref="Vector3" />.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator Vector3(Double3 value)
|
||||
{
|
||||
return new Vector3((Real)value.X, (Real)value.Y, (Real)value.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an explicit conversion from <see cref="Double3" /> to <see cref="Double2" />.
|
||||
/// </summary>
|
||||
@@ -2042,9 +1866,7 @@ namespace FlaxEngine
|
||||
/// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
|
||||
public override bool Equals(object value)
|
||||
{
|
||||
if (!(value is Double3 other))
|
||||
return false;
|
||||
return Mathd.NearEqual(other.X, X) && Mathd.NearEqual(other.Y, Y) && Mathd.NearEqual(other.Z, Z);
|
||||
return value is Double3 other && Mathd.NearEqual(other.X, X) && Mathd.NearEqual(other.Y, Y) && Mathd.NearEqual(other.Z, Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user