< Summary

Information
Class: FixedMathSharp.Vector3d
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Vectors/Vector3d.cs
Line coverage
98%
Covered lines: 506
Uncovered lines: 9
Coverable lines: 515
Total lines: 1650
Line coverage: 98.2%
Branch coverage
96%
Covered branches: 106
Total branches: 110
Branch coverage: 96.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)100%11100%
.ctor(...)100%11100%
get_RightHandNormal()100%11100%
get_LeftHandNormal()100%11100%
get_Normal()100%11100%
get_Magnitude()100%11100%
get_Direction()100%11100%
get_IsZero()100%11100%
get_SqrMagnitude()100%11100%
get_LongStateHash()100%11100%
get_StateHash()100%11100%
get_Item(...)100%44100%
set_Item(...)100%44100%
Set(...)100%11100%
AddInPlace(...)100%11100%
AddInPlace(...)100%11100%
AddInPlace(...)100%11100%
SubtractInPlace(...)100%11100%
SubtractInPlace(...)100%11100%
SubtractInPlace(...)100%11100%
ScaleInPlace(...)100%11100%
ScaleInPlace(...)100%11100%
Normalize()100%11100%
Normalize(...)100%44100%
IsNormalized()100%11100%
AllComponentsGreaterThanEpsilon()100%44100%
SnapSmallComponentsToZero(...)100%88100%
Distance(...)100%11100%
SqrDistance(...)100%11100%
Dot(...)100%11100%
CrossProduct(...)100%11100%
Cross(...)100%11100%
Lerp(...)100%11100%
UnclampedLerp(...)100%11100%
SpeedLerp(...)100%22100%
Slerp(...)100%11100%
GetNormalized(...)100%44100%
GetMagnitude(...)100%44100%
Abs(...)100%11100%
Sign(...)100%11100%
Clamp(...)100%11100%
ClampMagnitude(...)100%22100%
AreParallel(...)100%11100%
AreAlmostParallel(...)100%11100%
Midpoint(...)100%11100%
Distance(...)100%11100%
SqrDistance(...)100%11100%
ClosestPointsOnTwoLines(...)100%88100%
SolveClosestLineParameters(...)75%44100%
ClampSegmentParameter(...)50%4471.42%
ClosestPointOnLineSegment(...)100%22100%
Dot(...)100%11100%
Scale(...)100%11100%
Cross(...)100%11100%
CrossProduct(...)100%11100%
Project(...)100%22100%
ProjectOnPlane(...)100%22100%
ProjectOnPlane(...)50%2285.71%
Angle(...)100%22100%
Max(...)100%66100%
Min(...)100%66100%
Rotate(...)100%11100%
InverseRotate(...)100%11100%
op_Addition(...)100%11100%
op_Addition(...)100%11100%
op_Addition(...)100%11100%
op_Addition(...)100%11100%
op_Addition(...)100%11100%
op_Subtraction(...)100%11100%
op_Subtraction(...)100%210%
op_Subtraction(...)100%11100%
op_Subtraction(...)100%11100%
op_UnaryNegation(...)100%11100%
op_Multiply(...)100%11100%
op_Multiply(...)100%11100%
op_Multiply(...)100%210%
op_Multiply(...)100%11100%
op_Multiply(...)100%11100%
op_Multiply(...)100%11100%
op_Multiply(...)100%44100%
op_Multiply(...)100%11100%
op_Multiply(...)100%11100%
op_Division(...)100%22100%
op_Division(...)100%66100%
op_Division(...)100%22100%
op_Multiply(...)100%11100%
op_Multiply(...)100%11100%
op_Equality(...)100%11100%
op_Inequality(...)100%11100%
op_GreaterThan(...)100%44100%
op_LessThan(...)100%44100%
op_GreaterThanOrEqual(...)100%44100%
op_LessThanOrEqual(...)100%44100%
ToString()100%11100%
ToVector2d()100%11100%
ToVector4d(...)100%11100%
Deconstruct(...)100%11100%
Deconstruct(...)100%11100%
ToDegrees(...)100%11100%
ToRadians(...)100%11100%
Equals(...)100%22100%
Equals(...)100%44100%
Equals(...)100%11100%
GetHashCode()100%11100%
GetHashCode(...)100%11100%
CompareTo(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Vectors/Vector3d.cs

#LineLine coverage
 1using MemoryPack;
 2using System;
 3using System.Collections.Generic;
 4using System.Runtime.CompilerServices;
 5using System.Text.Json.Serialization;
 6
 7namespace FixedMathSharp;
 8
 9/// <summary>
 10/// Represents a 3D vector with fixed-point precision, supporting a wide range of vector operations such as rotation, sc
 11/// </summary>
 12/// <remarks>
 13/// The Vector3d struct is designed for high-precision applications in 3D space, including games, simulations, and physi
 14/// It offers essential operations like addition, subtraction, dot product, cross product, distance calculation, and nor
 15///
 16/// Use Cases:
 17/// - Modeling 3D positions, directions, and velocities with fixed-point precision.
 18/// - Performing vector transformations, including rotations using quaternions.
 19/// - Calculating distances, angles, projections, and interpolation between vectors.
 20/// - Essential for fixed-point math scenarios where floating-point precision isn't suitable.
 21/// </remarks>
 22[Serializable]
 23[MemoryPackable]
 24public partial struct Vector3d : IEquatable<Vector3d>, IComparable<Vector3d>, IEqualityComparer<Vector3d>
 25{
 26    #region Static Readonly Fields
 27
 28
 29    /// <summary>
 30    /// The upward direction vector (0, 1, 0).
 31    /// </summary>
 32    public static readonly Vector3d Up = new(0, 1, 0);
 33
 34    /// <summary>
 35    /// (1, 0, 0)
 36    /// </summary>
 37    public static readonly Vector3d Right = new(1, 0, 0);
 38
 39    /// <summary>
 40    /// (0, -1, 0)
 41    /// </summary>
 42    public static readonly Vector3d Down = new(0, -1, 0);
 43
 44    /// <summary>
 45    /// (-1, 0, 0)
 46    /// </summary>
 47    public static readonly Vector3d Left = new(-1, 0, 0);
 48
 49    /// <summary>
 50    /// The forward direction vector (0, 0, 1).
 51    /// </summary>
 52    public static readonly Vector3d Forward = new(0, 0, 1);
 53
 54    /// <summary>
 55    /// (0, 0, -1)
 56    /// </summary>
 57    public static readonly Vector3d Backward = new(0, 0, -1);
 58
 59    /// <summary>
 60    /// (1, 1, 1)
 61    /// </summary>
 62    public static readonly Vector3d One = new(1, 1, 1);
 63
 64    /// <summary>
 65    /// (-1, -1, -1)
 66    /// </summary>
 67    public static readonly Vector3d Negative = new(-1, -1, -1);
 68
 69    /// <summary>
 70    /// (0, 0, 0)
 71    /// </summary>
 72    public static readonly Vector3d Zero = new(0, 0, 0);
 73
 74
 75    #endregion
 76
 77    #region Fields
 78
 79    /// <summary>
 80    /// The X component of the vector.
 81    /// </summary>
 82    [JsonInclude]
 83    [MemoryPackOrder(0)]
 84    public Fixed64 x;
 85
 86    /// <summary>
 87    /// The Y component of the vector.
 88    /// </summary>
 89    [JsonInclude]
 90    [MemoryPackOrder(1)]
 91    public Fixed64 y;
 92
 93    /// <summary>
 94    /// The Z component of the vector.
 95    /// </summary>
 96    [JsonInclude]
 97    [MemoryPackOrder(2)]
 98    public Fixed64 z;
 99
 100    #endregion
 101
 102    #region Constructors
 103
 104    /// <summary>
 105    /// Initializes a new instance of the Vector3d structure using integer values for the X, Y, and Z components.
 106    /// </summary>
 107    /// <param name="xInt">The value of the X component as an integer.</param>
 108    /// <param name="yInt">The value of the Y component as an integer.</param>
 109    /// <param name="zInt">The value of the Z component as an integer.</param>
 2637110    public Vector3d(int xInt, int yInt, int zInt) : this((Fixed64)xInt, (Fixed64)yInt, (Fixed64)zInt) { }
 111
 112    /// <summary>
 113    /// Initializes a new instance of the Vector3d structure using the specified X, Y, and Z coordinates as
 114    /// double-precision floating-point values.
 115    /// </summary>
 116    /// <remarks>This constructor allows for convenient creation of a Vector3d from double values, which are
 117    /// internally converted to the Fixed64 representation used by the structure.</remarks>
 118    /// <param name="xDoub">The X coordinate of the vector, specified as a double-precision floating-point value.</param
 119    /// <param name="yDoub">The Y coordinate of the vector, specified as a double-precision floating-point value.</param
 120    /// <param name="zDoub">The Z coordinate of the vector, specified as a double-precision floating-point value.</param
 99121    public Vector3d(double xDoub, double yDoub, double zDoub) : this((Fixed64)xDoub, (Fixed64)yDoub, (Fixed64)zDoub) { }
 122
 123    /// <summary>
 124    /// Initializes a new instance of the Vector3d structure with the specified X, Y, and Z components.
 125    /// </summary>
 126    /// <param name="x">The value of the X component of the vector.</param>
 127    /// <param name="y">The value of the Y component of the vector.</param>
 128    /// <param name="z">The value of the Z component of the vector.</param>
 129    [JsonConstructor]
 130    public Vector3d(Fixed64 x, Fixed64 y, Fixed64 z)
 8695131    {
 8695132        this.x = x;
 8695133        this.y = y;
 8695134        this.z = z;
 8695135    }
 136
 137    #endregion
 138
 139    #region Properties
 140
 141    /// <summary>
 142    ///  Provides a rotated version of the current vector, where rotation is a 90 degrees rotation around the Y axis in 
 143    /// </summary>
 144    /// <remarks>
 145    /// These operations rotate the vector 90 degrees around the Y-axis.
 146    /// Note that the positive direction of rotation is defined by the right-hand rule:
 147    /// If your right hand's thumb points in the positive Y direction, then your fingers curl in the positive direction 
 148    /// </remarks>
 149    [JsonIgnore]
 150    [MemoryPackIgnore]
 151    public Vector3d RightHandNormal
 152    {
 153        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1154        get => new(z, y, -x);
 155    }
 156
 157    /// <summary>
 158    /// Provides a rotated version of the current vector, where rotation is a 90 degrees rotation around the Y axis in t
 159    /// </summary>
 160    [JsonIgnore]
 161    [MemoryPackIgnore]
 162    public Vector3d LeftHandNormal
 163    {
 164        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1165        get => new(-z, y, x);
 166    }
 167
 168    /// <inheritdoc cref="GetNormalized(Vector3d)"/>
 169    [JsonIgnore]
 170    [MemoryPackIgnore]
 171    public Vector3d Normal
 172    {
 173        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 12174        get => GetNormalized(this);
 175    }
 176
 177    /// <summary>
 178    /// Returns the actual length of this vector (RO).
 179    /// </summary>
 180    [JsonIgnore]
 181    [MemoryPackIgnore]
 182    public Fixed64 Magnitude
 183    {
 184        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 706185        get => GetMagnitude(this);
 186    }
 187
 188    /// <summary>
 189    /// Calculates the forward direction vector based on the yaw (x) and pitch (y) angles.
 190    /// </summary>
 191    /// <remarks>
 192    /// This is commonly used to determine the direction an object is facing in 3D space,
 193    /// where 'x' represents the yaw (horizontal rotation) and 'y' represents the pitch (vertical rotation).
 194    /// </remarks>
 195    [JsonIgnore]
 196    [MemoryPackIgnore]
 197    public Vector3d Direction
 198    {
 199        get
 1200        {
 1201            Fixed64 temp1 = FixedMath.Cos(x) * FixedMath.Sin(y);
 1202            Fixed64 temp2 = FixedMath.Sin(-x);
 1203            Fixed64 temp3 = FixedMath.Cos(x) * FixedMath.Cos(y);
 1204            return new Vector3d(temp1, temp2, temp3);
 1205        }
 206    }
 207
 208    /// <summary>
 209    /// Are all components of this vector equal to zero?
 210    /// </summary>
 211    /// <returns></returns>
 212    [JsonIgnore]
 213    [MemoryPackIgnore]
 214    public bool IsZero
 215    {
 216        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 5217        get => this.Equals(Zero);
 218    }
 219
 220    /// <summary>
 221    /// This vector's square magnitude.
 222    /// If you're doing distance checks, use SqrMagnitude and square the distance you're checking against
 223    /// If you need to know the actual distance, use MyMagnitude
 224    /// </summary>
 225    /// <returns>The magnitude.</returns>
 226    [JsonIgnore]
 227    [MemoryPackIgnore]
 228    public Fixed64 SqrMagnitude
 229    {
 230        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 413231        get => (x * x) + (y * y) + (z * z);
 232    }
 233
 234    /// <summary>
 235    /// Returns a long hash of the vector based on its x, y, and z values.
 236    /// </summary>
 237    [JsonIgnore]
 238    [MemoryPackIgnore]
 239    public long LongStateHash
 240    {
 241        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 30242        get => (x.m_rawValue * 31) + (y.m_rawValue * 7) + (z.m_rawValue * 11);
 243    }
 244
 245    /// <summary>
 246    /// Returns a hash of the vector based on its state.
 247    /// </summary>
 248    [JsonIgnore]
 249    [MemoryPackIgnore]
 250    public int StateHash
 251    {
 252        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 30253        get => (int)(LongStateHash % int.MaxValue);
 254    }
 255
 256    /// <summary>
 257    /// Gets or sets the component value at the specified index.
 258    /// </summary>
 259    /// <remarks>
 260    /// Use this indexer to access or modify the x, y, or z components of the vector by index.
 261    /// Index 0 corresponds to x, 1 to y, and 2 to z.
 262    /// </remarks>
 263    /// <param name="index">The zero-based index of the component to access. Valid values are 0 (x), 1 (y), or 2 (z).</p
 264    /// <returns>The value of the component at the specified index.</returns>
 265    /// <exception cref="IndexOutOfRangeException">Thrown if index is less than 0 or greater than 2.</exception>
 266    [JsonIgnore]
 267    [MemoryPackIgnore]
 268    public Fixed64 this[int index]
 269    {
 270        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 271        get
 11272        {
 11273            return index switch
 11274            {
 3275                0 => x,
 3276                1 => y,
 3277                2 => z,
 2278                _ => throw new IndexOutOfRangeException("Invalid Vector3d index!"),
 11279            };
 9280        }
 281        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 282        set
 26283        {
 26284            switch (index)
 285            {
 286                case 0:
 8287                    x = value;
 8288                    break;
 289                case 1:
 8290                    y = value;
 8291                    break;
 292                case 2:
 8293                    z = value;
 8294                    break;
 295                default:
 2296                    throw new IndexOutOfRangeException("Invalid Vector3d index!");
 297            }
 24298        }
 299    }
 300
 301    #endregion
 302
 303    #region Methods
 304
 305    /// <summary>
 306    /// Set x, y and z components of an existing Vector3.
 307    /// </summary>
 308    /// <param name="newX"></param>
 309    /// <param name="newY"></param>
 310    /// <param name="newZ"></param>
 311    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 312    public Vector3d Set(Fixed64 newX, Fixed64 newY, Fixed64 newZ)
 1313    {
 1314        x = newX;
 1315        y = newY;
 1316        z = newZ;
 1317        return this;
 1318    }
 319
 320    /// <summary>
 321    /// Adds the specified values to the components of the vector in place and returns the modified vector.
 322    /// </summary>
 323    /// <param name="amount">The amount to add to the components.</param>
 324    /// <returns>The modified vector after addition.</returns>
 325    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 326    public Vector3d AddInPlace(Fixed64 amount)
 1327    {
 1328        x += amount;
 1329        y += amount;
 1330        z += amount;
 1331        return this;
 1332    }
 333
 334    /// <summary>
 335    /// Adds the specified values to the components of the vector in place and returns the modified vector.
 336    /// </summary>
 337    /// <param name="xAmount">The amount to add to the x component.</param>
 338    /// <param name="yAmount">The amount to add to the y component.</param>
 339    /// <param name="zAmount">The amount to add to the z component.</param>
 340    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 341    public Vector3d AddInPlace(Fixed64 xAmount, Fixed64 yAmount, Fixed64 zAmount)
 2342    {
 2343        x += xAmount;
 2344        y += yAmount;
 2345        z += zAmount;
 2346        return this;
 2347    }
 348
 349    /// <summary>
 350    /// Adds the specified vector components to the corresponding components of the in place vector and returns the modi
 351    /// </summary>
 352    /// <param name="other">The other vector to add the components.</param>
 353    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 354    public Vector3d AddInPlace(Vector3d other)
 1355    {
 1356        AddInPlace(other.x, other.y, other.z);
 1357        return this;
 1358    }
 359
 360    /// <summary>
 361    /// Subtracts the specified value from all components of the vector in place and returns the modified vector.
 362    /// </summary>
 363    /// <param name="amount">The amount to subtract from each component.</param>
 364    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 365    public Vector3d SubtractInPlace(Fixed64 amount)
 1366    {
 1367        x -= amount;
 1368        y -= amount;
 1369        z -= amount;
 1370        return this;
 1371    }
 372
 373    /// <summary>
 374    /// Subtracts the specified values from the components of the vector in place and returns the modified vector.
 375    /// </summary>
 376    /// <param name="xAmount">The amount to subtract from the x component.</param>
 377    /// <param name="yAmount">The amount to subtract from the y component.</param>
 378    /// <param name="zAmount">The amount to subtract from the z component.</param>
 379    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 380    public Vector3d SubtractInPlace(Fixed64 xAmount, Fixed64 yAmount, Fixed64 zAmount)
 2381    {
 2382        x -= xAmount;
 2383        y -= yAmount;
 2384        z -= zAmount;
 2385        return this;
 2386    }
 387
 388    /// <summary>
 389    /// Subtracts the specified vector from the components of the vector in place and returns the modified vector.
 390    /// </summary>
 391    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 392    public Vector3d SubtractInPlace(Vector3d other)
 1393    {
 1394        SubtractInPlace(other.x, other.y, other.z);
 1395        return this;
 1396    }
 397
 398    /// <summary>
 399    /// Scales the components of the vector by the specified scalar factor in place and returns the modified vector.
 400    /// </summary>
 401    /// <param name="scaleFactor">The scalar factor to multiply each component by.</param>
 402    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 403    public Vector3d ScaleInPlace(Fixed64 scaleFactor)
 1404    {
 1405        x *= scaleFactor;
 1406        y *= scaleFactor;
 1407        z *= scaleFactor;
 1408        return this;
 1409    }
 410
 411    /// <summary>
 412    /// Scales each component of the vector by the corresponding component of the given vector in place and returns the 
 413    /// </summary>
 414    /// <param name="scale">The vector containing the scale factors for each component.</param>
 415    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 416    public Vector3d ScaleInPlace(Vector3d scale)
 1417    {
 1418        x *= scale.x;
 1419        y *= scale.y;
 1420        z *= scale.z;
 1421        return this;
 1422    }
 423
 424    /// <summary>
 425    /// Normalizes this vector in place, making its magnitude (length) equal to 1, and returns the modified vector.
 426    /// </summary>
 427    /// <remarks>
 428    /// If the vector is zero-length or already normalized, no operation is performed.
 429    /// This method modifies the current vector in place and supports method chaining.
 430    /// </remarks>
 431    /// <returns>The normalized vector.</returns>
 432    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 433    public Vector3d Normalize()
 343434    {
 343435        return this = GetNormalized(this);
 343436    }
 437
 438    /// <summary>
 439    /// Normalizes this vector in place and outputs its original magnitude.
 440    /// </summary>
 441    /// <remarks>
 442    /// If the vector is zero-length or already normalized, no operation is performed, but the original magnitude will s
 443    /// </remarks>
 444    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 445    public Vector3d Normalize(out Fixed64 mag)
 3446    {
 3447        mag = GetMagnitude(this);
 448
 449        // If magnitude is zero, return a zero vector to avoid divide-by-zero errors
 3450        if (mag == Fixed64.Zero)
 1451        {
 1452            x = Fixed64.Zero;
 1453            y = Fixed64.Zero;
 1454            z = Fixed64.Zero;
 1455            return this;
 456        }
 457
 458        // If already normalized, return as-is
 2459        if (mag == Fixed64.One)
 1460            return this;
 461
 1462        x /= mag;
 1463        y /= mag;
 1464        z /= mag;
 465
 1466        return this;
 3467    }
 468
 469    /// <summary>
 470    /// Checks if this vector has been normalized by checking if the magnitude is close to 1.
 471    /// </summary>
 472    public bool IsNormalized()
 48473    {
 48474        return FixedMath.Abs(Magnitude - Fixed64.One) <= Fixed64.Epsilon;
 48475    }
 476
 477    /// <summary>
 478    /// Checks whether all components are strictly greater than <see cref="Fixed64.Epsilon"/>.
 479    /// </summary>
 480    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 481    public bool AllComponentsGreaterThanEpsilon()
 2482    {
 2483        return x.Abs() > Fixed64.Epsilon && y.Abs() > Fixed64.Epsilon && z.Abs() > Fixed64.Epsilon;
 2484    }
 485
 486    /// <summary>
 487    /// Returns a new vector with components whose absolute values are less than the specified threshold set to zero.
 488    /// </summary>
 489    /// <remarks>
 490    /// This method is useful for eliminating insignificant floating-point errors by zeroing out very small vector compo
 491    /// The default threshold is suitable for most cases where near-zero values are considered noise.
 492    /// </remarks>
 493    /// <param name="threshold">
 494    /// The minimum absolute value a component must have to be retained.
 495    /// If null, a default epsilon value is used.
 496    /// </param>
 497    /// <returns>A new Vector3d instance with small components snapped to zero based on the specified threshold.</return
 498    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 499    public Vector3d SnapSmallComponentsToZero(Fixed64? threshold = null)
 3500    {
 3501        Fixed64 effectiveThreshold = threshold ?? Fixed64.Epsilon;
 3502        return new Vector3d(
 3503            x.Abs() < effectiveThreshold ? Fixed64.Zero : x,
 3504            y.Abs() < effectiveThreshold ? Fixed64.Zero : y,
 3505            z.Abs() < effectiveThreshold ? Fixed64.Zero : z
 3506        );
 3507    }
 508
 509    /// <summary>
 510    /// Computes the distance between this vector and another vector.
 511    /// </summary>
 512    /// <param name="otherX">The x component of the other vector.</param>
 513    /// <param name="otherY">The y component of the other vector.</param>
 514    /// <param name="otherZ">The z component of the other vector.</param>
 515    /// <returns>The distance between the two vectors.</returns>
 516    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 517    public Fixed64 Distance(Fixed64 otherX, Fixed64 otherY, Fixed64 otherZ)
 22518    {
 22519        Fixed64 temp1 = x - otherX;
 22520        temp1 *= temp1;
 22521        Fixed64 temp2 = y - otherY;
 22522        temp2 *= temp2;
 22523        Fixed64 temp3 = z - otherZ;
 22524        temp3 *= temp3;
 22525        return FixedMath.Sqrt(temp1 + temp2 + temp3);
 22526    }
 527
 528    /// <summary>
 529    /// Calculates the squared distance between two vectors, avoiding the need for a square root operation.
 530    /// </summary>
 531    /// <returns>The squared distance between the two vectors.</returns>
 532    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 533    public Fixed64 SqrDistance(Fixed64 otherX, Fixed64 otherY, Fixed64 otherZ)
 189534    {
 189535        Fixed64 temp1 = x - otherX;
 189536        temp1 *= temp1;
 189537        Fixed64 temp2 = y - otherY;
 189538        temp2 *= temp2;
 189539        Fixed64 temp3 = z - otherZ;
 189540        temp3 *= temp3;
 189541        return temp1 + temp2 + temp3;
 189542    }
 543
 544    /// <summary>
 545    /// Computes the dot product of this vector with another vector specified by its components.
 546    /// </summary>
 547    /// <param name="otherX">The x component of the other vector.</param>
 548    /// <param name="otherY">The y component of the other vector.</param>
 549    /// <param name="otherZ">The z component of the other vector.</param>
 550    /// <returns>The dot product of the two vectors.</returns>
 551    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 552    public Fixed64 Dot(Fixed64 otherX, Fixed64 otherY, Fixed64 otherZ)
 4611553    {
 4611554        return x * otherX + y * otherY + z * otherZ;
 4611555    }
 556
 557    /// <summary>
 558    /// Computes the cross product magnitude of this vector with another vector.
 559    /// </summary>
 560    /// <param name="otherX">The X component of the other vector.</param>
 561    /// <param name="otherY">The Y component of the other vector.</param>
 562    /// <param name="otherZ">The Z component of the other vector.</param>
 563    /// <returns>The cross product magnitude.</returns>
 564    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 565    public Fixed64 CrossProduct(Fixed64 otherX, Fixed64 otherY, Fixed64 otherZ)
 2566    {
 2567        return (y * otherZ - z * otherY) + (z * otherX - x * otherZ) + (x * otherY - y * otherX);
 2568    }
 569
 570    /// <summary>
 571    /// Returns the cross vector of this vector with another vector.
 572    /// </summary>
 573    /// <returns>A new vector representing the cross product.</returns>
 574    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 575    public Vector3d Cross(Fixed64 otherX, Fixed64 otherY, Fixed64 otherZ)
 1342576    {
 1342577        return new Vector3d(
 1342578            y * otherZ - z * otherY,
 1342579            z * otherX - x * otherZ,
 1342580            x * otherY - y * otherX);
 1342581    }
 582
 583    #endregion
 584
 585    #region Vector3d Operations
 586
 587    /// <summary>
 588    /// Linearly interpolates between two points.
 589    /// </summary>
 590    /// <param name="a">Start value, returned when t = 0.</param>
 591    /// <param name="b">End value, returned when t = 1.</param>
 592    /// <param name="mag">Value used to interpolate between a and b.</param>
 593    /// <returns> Interpolated value, equals to a + (b - a) * t.</returns>
 594    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 595    public static Vector3d Lerp(Vector3d a, Vector3d b, Fixed64 mag)
 3596    {
 3597        mag = FixedMath.Clamp01(mag);
 3598        return new Vector3d(a.x + (b.x - a.x) * mag, a.y + (b.y - a.y) * mag, a.z + (b.z - a.z) * mag);
 3599    }
 600
 601    /// <summary>
 602    /// Linearly interpolates between two vectors without clamping the interpolation factor between 0 and 1.
 603    /// </summary>
 604    /// <param name="a">The start vector.</param>
 605    /// <param name="b">The end vector.</param>
 606    /// <param name="t">The interpolation factor. Values outside the range [0, 1] will cause the interpolation to go bey
 607    /// <returns>The interpolated vector.</returns>
 608    /// <remarks>
 609    /// Unlike traditional Lerp, this function allows interpolation factors greater than 1 or less than 0,
 610    /// which means the resulting vector can extend beyond the endpoints.
 611    /// </remarks>
 612    public static Vector3d UnclampedLerp(Vector3d a, Vector3d b, Fixed64 t)
 2613    {
 2614        return (b - a) * t + a;
 2615    }
 616
 617    /// <summary>
 618    /// Moves from a to b at some speed dependent of a delta time with out passing b.
 619    /// </summary>
 620    /// <param name="a"></param>
 621    /// <param name="b"></param>
 622    /// <param name="speed"></param>
 623    /// <param name="dt"></param>
 624    /// <returns></returns>
 625    public static Vector3d SpeedLerp(Vector3d a, Vector3d b, Fixed64 speed, Fixed64 dt)
 3626    {
 3627        Vector3d v = b - a;
 3628        Fixed64 dv = speed * dt;
 3629        if (dv > v.Magnitude)
 1630            return b;
 631        else
 2632            return a + v.Normal * dv;
 3633    }
 634
 635    /// <summary>
 636    /// Spherically interpolates between two vectors, moving along the shortest arc on a unit sphere.
 637    /// </summary>
 638    /// <param name="start">The starting vector.</param>
 639    /// <param name="end">The ending vector.</param>
 640    /// <param name="percent">A value between 0 and 1 that represents the interpolation amount. 0 returns the start vect
 641    /// <returns>The interpolated vector between the two input vectors.</returns>
 642    /// <remarks>
 643    /// Slerp is used to interpolate between two unit vectors on a sphere, providing smooth rotation.
 644    /// It can be more computationally expensive than linear interpolation (Lerp) but results in smoother, arc-like moti
 645    /// </remarks>
 646    public static Vector3d Slerp(Vector3d start, Vector3d end, Fixed64 percent)
 4647    {
 648        // Dot product - the cosine of the angle between 2 vectors.
 4649        Fixed64 dot = Dot(start, end);
 650        // Clamp it to be in the range of Acos()
 651        // This may be unnecessary, but floating point
 652        // precision can be a fickle mistress.
 4653        dot = FixedMath.Clamp(dot, -Fixed64.One, Fixed64.One);
 654        // Acos(dot) returns the angle between start and end,
 655        // And multiplying that by percent returns the angle between
 656        // start and the final result.
 4657        Fixed64 theta = FixedMath.Acos(dot) * percent;
 4658        Vector3d RelativeVec = end - start * dot;
 4659        RelativeVec.Normalize();
 660        // Orthonormal basis
 661        // The final result.
 4662        return (start * FixedMath.Cos(theta)) + (RelativeVec * FixedMath.Sin(theta));
 4663    }
 664
 665    /// <summary>
 666    /// Normalizes the given vector, returning a unit vector with the same direction.
 667    /// </summary>
 668    /// <param name="value">The vector to normalize.</param>
 669    /// <returns>A normalized (unit) vector with the same direction.</returns>
 670    public static Vector3d GetNormalized(Vector3d value)
 355671    {
 355672        Fixed64 mag = GetMagnitude(value);
 673
 674        // If magnitude is zero, return a zero vector to avoid divide-by-zero errors
 355675        if (mag == Fixed64.Zero)
 1676            return new Vector3d(Fixed64.Zero, Fixed64.Zero, Fixed64.Zero);
 677
 678        // If already normalized, return as-is
 354679        if (FixedMath.Abs(mag - Fixed64.One) <= Fixed64.Epsilon)
 100680            return value;
 681
 682        // Normalize it exactly
 254683        return new Vector3d(
 254684            value.x / mag,
 254685            value.y / mag,
 254686            value.z / mag
 254687        );
 355688    }
 689
 690    /// <summary>
 691    /// Returns the magnitude (length) of this vector.
 692    /// </summary>
 693    /// <param name="vector">The vector whose magnitude is being calculated.</param>
 694    /// <returns>The magnitude of the vector.</returns>
 695    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 696    public static Fixed64 GetMagnitude(Vector3d vector)
 1065697    {
 1065698        Fixed64 mag = (vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z);
 699
 700        // Clamp tiny drift around 1 in either direction.
 1065701        if (FixedMath.Abs(mag - Fixed64.One) <= Fixed64.Epsilon)
 441702            return Fixed64.One;
 703
 624704        return mag != Fixed64.Zero ? FixedMath.Sqrt(mag) : Fixed64.Zero;
 1065705    }
 706
 707    /// <summary>
 708    /// Returns a new <see cref="Vector3d"/> where each component is the absolute value of the corresponding input compo
 709    /// </summary>
 710    /// <param name="value">The input vector.</param>
 711    /// <returns>A vector with absolute values for each component.</returns>
 712    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 713    public static Vector3d Abs(Vector3d value)
 76714    {
 76715        return new Vector3d(value.x.Abs(), value.y.Abs(), value.z.Abs());
 76716    }
 717
 718    /// <summary>
 719    /// Returns a new <see cref="Vector3d"/> where each component is the sign of the corresponding input component.
 720    /// </summary>
 721    /// <param name="value">The input vector.</param>
 722    /// <returns>A vector where each component is -1, 0, or 1 based on the sign of the input.</returns>
 723    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 724    public static Vector3d Sign(Vector3d value)
 1725    {
 1726        return new Vector3d(value.x.Sign(), value.y.Sign(), value.z.Sign());
 1727    }
 728
 729    /// <summary>
 730    /// Clamps each component of the given <see cref="Vector3d"/> within the specified min and max bounds.
 731    /// </summary>
 732    /// <param name="value">The vector to clamp.</param>
 733    /// <param name="min">The minimum bounds.</param>
 734    /// <param name="max">The maximum bounds.</param>
 735    /// <returns>A vector with each component clamped between min and max.</returns>
 736    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 737    public static Vector3d Clamp(Vector3d value, Vector3d min, Vector3d max)
 3738    {
 3739        return new Vector3d(
 3740            FixedMath.Clamp(value.x, min.x, max.x),
 3741            FixedMath.Clamp(value.y, min.y, max.y),
 3742            FixedMath.Clamp(value.z, min.z, max.z)
 3743        );
 3744    }
 745
 746    /// <summary>
 747    /// Clamps the given Vector3d within the specified magnitude.
 748    /// </summary>
 749    /// <param name="value"></param>
 750    /// <param name="maxMagnitude"></param>
 751    /// <returns></returns>
 752    public static Vector3d ClampMagnitude(Vector3d value, Fixed64 maxMagnitude)
 2753    {
 2754        if (value.SqrMagnitude > maxMagnitude * maxMagnitude)
 1755            return value.Normal * maxMagnitude; // Scale vector to max magnitude
 756
 1757        return value;
 2758    }
 759
 760    /// <summary>
 761    /// Determines if two vectors are exactly parallel by checking if their cross product is zero.
 762    /// </summary>
 763    /// <param name="v1">The first vector.</param>
 764    /// <param name="v2">The second vector.</param>
 765    /// <returns>True if the vectors are exactly parallel, false otherwise.</returns>
 766    public static bool AreParallel(Vector3d v1, Vector3d v2)
 2767    {
 2768        return Cross(v1, v2).SqrMagnitude == Fixed64.Zero;
 2769    }
 770
 771    /// <summary>
 772    /// Determines if two vectors are approximately parallel based on a cosine similarity threshold.
 773    /// </summary>
 774    /// <param name="v1">The first normalized vector.</param>
 775    /// <param name="v2">The second normalized vector.</param>
 776    /// <param name="cosThreshold">The cosine similarity threshold for near-parallel vectors.</param>
 777    /// <returns>True if the vectors are nearly parallel, false otherwise.</returns>
 778    public static bool AreAlmostParallel(Vector3d v1, Vector3d v2, Fixed64 cosThreshold)
 2779    {
 780        // Assuming v1 and v2 are already normalized
 2781        Fixed64 dot = Dot(v1, v2);
 782
 783        // Compare dot product directly to the cosine threshold
 2784        return dot >= cosThreshold;
 2785    }
 786
 787    /// <summary>
 788    /// Computes the midpoint between two vectors.
 789    /// </summary>
 790    /// <param name="v1">The first vector.</param>
 791    /// <param name="v2">The second vector.</param>
 792    /// <returns>The midpoint vector.</returns>
 793    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 794    public static Vector3d Midpoint(Vector3d v1, Vector3d v2)
 2795    {
 2796        return new Vector3d((v1.x + v2.x) * Fixed64.Half, (v1.y + v2.y) * Fixed64.Half, (v1.z + v2.z) * Fixed64.Half);
 2797    }
 798
 799    /// <inheritdoc cref="Distance(Fixed64, Fixed64, Fixed64)" />
 800    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 801    public static Fixed64 Distance(Vector3d start, Vector3d end)
 22802    {
 22803        return start.Distance(end.x, end.y, end.z);
 22804    }
 805
 806    /// <inheritdoc cref="SqrDistance(Fixed64, Fixed64, Fixed64)" />
 807    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 808    public static Fixed64 SqrDistance(Vector3d start, Vector3d end)
 189809    {
 189810        return start.SqrDistance(end.x, end.y, end.z);
 189811    }
 812
 813    /// <summary>
 814    /// Calculates the closest points on two line segments.
 815    /// </summary>
 816    /// <param name="line1Start">The starting point of the first line segment.</param>
 817    /// <param name="line1End">The ending point of the first line segment.</param>
 818    /// <param name="line2Start">The starting point of the second line segment.</param>
 819    /// <param name="line2End">The ending point of the second line segment.</param>
 820    /// <returns>
 821    /// A tuple containing two points representing the closest points on each line segment. The first item is the closes
 822    /// and the second item is the closest point on the second line.
 823    /// </returns>
 824    /// <remarks>
 825    /// This method considers the line segments, not the infinite lines they represent, ensuring that the returned point
 826    /// </remarks>
 827    public static (Vector3d, Vector3d) ClosestPointsOnTwoLines(Vector3d line1Start, Vector3d line1End, Vector3d line2Sta
 6828    {
 6829        Vector3d u = line1End - line1Start;
 6830        Vector3d v = line2End - line2Start;
 6831        Vector3d w = line1Start - line2Start;
 832
 6833        Fixed64 a = Dot(u, u);
 6834        Fixed64 b = Dot(u, v);
 6835        Fixed64 c = Dot(v, v);
 6836        Fixed64 d = Dot(u, w);
 6837        Fixed64 e = Dot(v, w);
 6838        Fixed64 D = a * c - b * b;
 839
 6840        (Fixed64 sc, Fixed64 tc) = SolveClosestLineParameters(a, b, c, d, e, D);
 841
 842        // recompute sc if it is outside [0,1]
 6843        if (sc < Fixed64.Zero)
 1844        {
 1845            sc = Fixed64.Zero;
 1846            tc = ClampSegmentParameter(e, c);
 1847        }
 5848        else if (sc > Fixed64.One)
 1849        {
 1850            sc = Fixed64.One;
 1851            tc = ClampSegmentParameter(e + b, c);
 1852        }
 853
 854        // recompute tc if it is outside [0,1]
 6855        if (tc < Fixed64.Zero)
 1856        {
 1857            tc = Fixed64.Zero;
 1858            sc = ClampSegmentParameter(-d, a);
 1859        }
 5860        else if (tc > Fixed64.One)
 1861        {
 1862            tc = Fixed64.One;
 1863            sc = ClampSegmentParameter(-d + b, a);
 1864        }
 865
 866        // get the difference of the two closest points
 6867        Vector3d pointOnLine1 = line1Start + sc * u;
 6868        Vector3d pointOnLine2 = line2Start + tc * v;
 869
 6870        return (pointOnLine1, pointOnLine2);
 6871    }
 872
 873    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 874    private static (Fixed64 sc, Fixed64 tc) SolveClosestLineParameters(
 875        Fixed64 a,
 876        Fixed64 b,
 877        Fixed64 c,
 878        Fixed64 d,
 879        Fixed64 e,
 880        Fixed64 determinant)
 6881    {
 6882        if (determinant.Abs() < Fixed64.Epsilon)
 1883            return (Fixed64.Zero, b > c ? d / b : e / c);
 884
 5885        return ((b * e - c * d) / determinant, (a * e - b * d) / determinant);
 6886    }
 887
 888    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 889    private static Fixed64 ClampSegmentParameter(Fixed64 numerator, Fixed64 denominator)
 4890    {
 4891        if (numerator < Fixed64.Zero)
 0892            return Fixed64.Zero;
 893
 4894        if (numerator > denominator)
 0895            return Fixed64.One;
 896
 4897        return numerator / denominator;
 4898    }
 899
 900    /// <summary>
 901    /// Calculates the closest point on a line segment defined by start and end points to a given point in space.
 902    /// </summary>
 903    /// <param name="point">The point to project onto the segment.</param>
 904    /// <param name="start">The start of the line segment.</param>
 905    /// <param name="end">The end of the line segment.</param>
 906    /// <returns>The closest point on the line segment to the given point.</returns>
 907    public static Vector3d ClosestPointOnLineSegment(Vector3d point, Vector3d start, Vector3d end)
 51908    {
 51909        Vector3d segment = end - start;
 51910        Fixed64 lengthSquared = segment.SqrMagnitude;
 911
 51912        if (lengthSquared == Fixed64.Zero)
 1913            return start;
 914
 50915        Fixed64 t = Dot(point - start, segment) / lengthSquared;
 50916        t = FixedMath.Clamp(t, Fixed64.Zero, Fixed64.One);
 917
 50918        return start + segment * t;
 51919    }
 920
 921    /// <summary>
 922    /// Dot Product of two vectors.
 923    /// </summary>
 924    /// <param name="lhs"></param>
 925    /// <param name="rhs"></param>
 926    /// <returns></returns>
 927    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 928    public static Fixed64 Dot(Vector3d lhs, Vector3d rhs)
 4611929    {
 4611930        return lhs.Dot(rhs.x, rhs.y, rhs.z);
 4611931    }
 932
 933    /// <summary>
 934    /// Multiplies two vectors component-wise.
 935    /// </summary>
 936    /// <param name="a"></param>
 937    /// <param name="b"></param>
 938    /// <returns></returns>
 939    public static Vector3d Scale(Vector3d a, Vector3d b)
 1940    {
 1941        return new Vector3d(a.x * b.x, a.y * b.y, a.z * b.z);
 1942    }
 943
 944    /// <summary>
 945    /// Cross Product of two vectors.
 946    /// </summary>
 947    /// <param name="lhs"></param>
 948    /// <param name="rhs"></param>
 949    /// <returns></returns>
 950    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 951    public static Vector3d Cross(Vector3d lhs, Vector3d rhs)
 1342952    {
 1342953        return lhs.Cross(rhs.x, rhs.y, rhs.z);
 1342954    }
 955
 956    /// <inheritdoc cref="CrossProduct(Fixed64, Fixed64, Fixed64)"/>
 957    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 958    public static Fixed64 CrossProduct(Vector3d lhs, Vector3d rhs)
 1959    {
 1960        return lhs.CrossProduct(rhs.x, rhs.y, rhs.z);
 1961    }
 962
 963    /// <summary>
 964    /// Projects a vector onto another vector.
 965    /// </summary>
 966    /// <param name="vector"></param>
 967    /// <param name="onNormal"></param>
 968    /// <returns></returns>
 969    public static Vector3d Project(Vector3d vector, Vector3d onNormal)
 3970    {
 3971        Fixed64 sqrMag = Dot(onNormal, onNormal);
 3972        if (sqrMag.Abs() < Fixed64.Epsilon)
 1973            return Zero;
 974        else
 2975        {
 2976            Fixed64 dot = Dot(vector, onNormal);
 2977            return new Vector3d(onNormal.x * dot / sqrMag,
 2978                onNormal.y * dot / sqrMag,
 2979                onNormal.z * dot / sqrMag);
 980        }
 3981    }
 982
 983    /// <summary>
 984    /// Projects a vector onto a plane defined by a normal orthogonal to the plane.
 985    /// </summary>
 986    /// <param name="vector"></param>
 987    /// <param name="planeNormal"></param>
 988    /// <returns></returns>
 989    public static Vector3d ProjectOnPlane(Vector3d vector, Vector3d planeNormal)
 2990    {
 2991        Fixed64 sqrMag = Dot(planeNormal, planeNormal);
 2992        if (sqrMag.Abs() < Fixed64.Epsilon)
 1993            return vector;
 994        else
 1995        {
 1996            Fixed64 dot = Dot(vector, planeNormal);
 1997            return new Vector3d(vector.x - planeNormal.x * dot / sqrMag,
 1998                vector.y - planeNormal.y * dot / sqrMag,
 1999                vector.z - planeNormal.z * dot / sqrMag);
 1000        }
 21001    }
 1002
 1003    /// <summary>
 1004    /// Projects a point onto a plane defined by a normal and a distance from the origin.
 1005    /// </summary>
 1006    /// <param name="point">The point to project.</param>
 1007    /// <param name="plane">The plane onto which the point is projected.</param>
 1008    /// <returns>The projected point.</returns>
 1009    public static Vector3d ProjectOnPlane(Vector3d point, FixedPlane plane)
 251010    {
 251011        Fixed64 normalLengthSquared = plane.Normal.SqrMagnitude;
 251012        if (normalLengthSquared == Fixed64.Zero)
 01013            return point;
 1014
 251015        Fixed64 distance = plane.DotCoordinate(point);
 251016        return point - plane.Normal * (distance / normalLengthSquared);
 251017    }
 1018
 1019    /// <summary>
 1020    /// Computes the angle in degrees between two vectors.
 1021    /// </summary>
 1022    /// <param name="from">The starting vector.</param>
 1023    /// <param name="to">The target vector.</param>
 1024    /// <returns>The angle in degrees between the two vectors.</returns>
 1025    /// <remarks>
 1026    /// This method calculates the angle by using the dot product between the vectors and normalizing the result.
 1027    /// The angle is always the smaller angle between the two vectors on a plane.
 1028    /// </remarks>
 1029    public static Fixed64 Angle(Vector3d from, Vector3d to)
 21030    {
 21031        Fixed64 denominator = FixedMath.Sqrt(from.SqrMagnitude * to.SqrMagnitude);
 1032
 21033        if (denominator.Abs() < Fixed64.Epsilon)
 11034            return Fixed64.Zero;
 1035
 11036        Fixed64 dot = FixedMath.Clamp(Dot(from, to) / denominator, -Fixed64.One, Fixed64.One);
 1037
 11038        return FixedMath.RadToDeg(FixedMath.Acos(dot));
 21039    }
 1040
 1041    /// <summary>
 1042    ///  Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors.
 1043    /// </summary>
 1044    /// <param name="value1">The first vector.</param>
 1045    /// <param name="value2">The second vector.</param>
 1046    /// <returns>The maximized vector.</returns>
 1047    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1048    public static Vector3d Max(Vector3d value1, Vector3d value2)
 3051049    {
 3051050        return new Vector3d((value1.x > value2.x) ? value1.x : value2.x, (value1.y > value2.y) ? value1.y : value2.y, (v
 3051051    }
 1052
 1053    /// <summary>
 1054    /// Returns a vector whose elements are the minimum of each of the pairs of elements in two specified vectors.
 1055    /// </summary>
 1056    /// <param name="value1">The first vector.</param>
 1057    /// <param name="value2">The second vector.</param>
 1058    /// <returns>The minimized vector.</returns>
 1059    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1060    public static Vector3d Min(Vector3d value1, Vector3d value2)
 3051061    {
 3051062        return new Vector3d((value1.x < value2.x) ? value1.x : value2.x, (value1.y < value2.y) ? value1.y : value2.y, (v
 3051063    }
 1064
 1065    /// <summary>
 1066    /// Rotates the vector around a given position using a specified quaternion rotation.
 1067    /// </summary>
 1068    /// <param name="source">The vector to rotate.</param>
 1069    /// <param name="position">The position around which the vector is rotated.</param>
 1070    /// <param name="rotation">The quaternion representing the rotation.</param>
 1071    /// <returns>The rotated vector.</returns>
 1072    public static Vector3d Rotate(Vector3d source, Vector3d position, FixedQuaternion rotation)
 11073    {
 11074        source -= position; // Translate the vector by the position
 11075        var normalizedRotation = rotation.Normal;
 11076        return (normalizedRotation * source) + position;
 11077    }
 1078
 1079    /// <summary>
 1080    /// Applies the inverse of a specified quaternion rotation to the vector around a given position.
 1081    /// </summary>
 1082    /// <param name="source">The vector to rotate.</param>
 1083    /// <param name="position">The position around which the vector is rotated.</param>
 1084    /// <param name="rotation">The quaternion representing the inverse rotation.</param>
 1085    /// <returns>The rotated vector.</returns>
 1086    public static Vector3d InverseRotate(Vector3d source, Vector3d position, FixedQuaternion rotation)
 11087    {
 11088        source -= position; // Translate the vector by the position
 11089        var normalizedRotation = rotation.Normal;
 1090        // Undo the rotation
 11091        source = normalizedRotation.Inverse() * source;
 1092        // Add the original position back
 11093        return source + position;
 11094    }
 1095
 1096    #endregion
 1097
 1098    #region Operators
 1099
 1100    /// <summary>
 1101    /// Adds two Vector3d instances component-wise.
 1102    /// </summary>
 1103    /// <param name="v1">The first vector to add.</param>
 1104    /// <param name="v2">The second vector to add.</param>
 1105    /// <returns>A new Vector3d whose components are the sum of the corresponding components of v1 and v2.</returns>
 1106    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1107    public static Vector3d operator +(Vector3d v1, Vector3d v2)
 8771108    {
 8771109        return new Vector3d(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
 8771110    }
 1111
 1112    /// <summary>
 1113    /// Adds a scalar value to each component of the specified vector and returns the resulting vector.
 1114    /// </summary>
 1115    /// <param name="v1">The vector to which the scalar value will be added.</param>
 1116    /// <param name="mag">The scalar value to add to each component of the vector.</param>
 1117    /// <returns>A new Vector3d whose components are the sum of the corresponding components of the input vector and the
 1118    /// value.</returns>
 1119    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1120    public static Vector3d operator +(Vector3d v1, Fixed64 mag)
 21121    {
 21122        return new Vector3d(v1.x + mag, v1.y + mag, v1.z + mag);
 21123    }
 1124
 1125    /// <inheritdoc cref="operator +(Vector3d, Fixed64)"/>
 1126    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1127    public static Vector3d operator +(Fixed64 mag, Vector3d v1)
 11128    {
 11129        return v1 + mag;
 11130    }
 1131
 1132    /// <summary>
 1133    /// Adds a Vector3d instance to a tuple representing x, y, and z components and returns the resulting vector.
 1134    /// </summary>
 1135    /// <param name="v1">The first vector to add.</param>
 1136    /// <param name="v2">A tuple containing the x, y, and z values to add to the vector.</param>
 1137    /// <returns>A new Vector3d that is the sum of the original vector and the specified tuple components.</returns>
 1138    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1139    public static Vector3d operator +(Vector3d v1, (int x, int y, int z) v2)
 21140    {
 21141        return new Vector3d(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
 21142    }
 1143
 1144    /// <summary>
 1145    /// Adds a 3-tuple of integers to a Vector3d instance, returning the resulting vector.
 1146    /// </summary>
 1147    /// <param name="v2">A tuple containing the X, Y, and Z components to add to the vector.</param>
 1148    /// <param name="v1">The Vector3d instance to which the tuple components are added.</param>
 1149    /// <returns>A new Vector3d representing the sum of the original vector and the specified tuple components.</returns
 1150    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1151    public static Vector3d operator +((int x, int y, int z) v2, Vector3d v1)
 11152    {
 11153        return v1 + v2;
 11154    }
 1155
 1156    /// <summary>
 1157    /// Subtracts the components of one Vector3d from another and returns the resulting vector.
 1158    /// </summary>
 1159    /// <param name="v1">The vector to subtract from.</param>
 1160    /// <param name="v2">The vector to subtract.</param>
 1161    /// <returns>A Vector3d whose components are the result of subtracting the corresponding components of v2 from v1.</
 1162    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1163    public static Vector3d operator -(Vector3d v1, Vector3d v2)
 6101164    {
 6101165        return new Vector3d(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
 6101166    }
 1167
 1168    /// <summary>
 1169    /// Subtracts the specified scalar value from each component of the given vector.
 1170    /// </summary>
 1171    /// <param name="v1">The vector from which to subtract the scalar value from each component.</param>
 1172    /// <param name="mag">The scalar value to subtract from each component of the vector.</param>
 1173    /// <returns>A new Vector3d whose components are the result of subtracting the scalar value from the corresponding c
 1174    /// of the input vector.</returns>
 1175    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1176    public static Vector3d operator -(Vector3d v1, Fixed64 mag)
 01177    {
 01178        return new Vector3d(v1.x - mag, v1.y - mag, v1.z - mag);
 01179    }
 1180
 1181    /// <summary>
 1182    /// Subtracts the specified tuple from the given vector and returns the resulting vector.
 1183    /// </summary>
 1184    /// <param name="v1">The vector from which to subtract the tuple values.</param>
 1185    /// <param name="v2">A tuple containing the x, y, and z values to subtract from the vector.</param>
 1186    /// <returns>A new Vector3d representing the result of subtracting the tuple values from the original vector.</retur
 1187    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1188    public static Vector3d operator -(Vector3d v1, (int x, int y, int z) v2)
 11189    {
 11190        return new Vector3d(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
 11191    }
 1192
 1193    /// <summary>
 1194    /// Subtracts the components of a specified Vector3d from the corresponding components of a 3-tuple of integers and
 1195    /// returns the resulting Vector3d.
 1196    /// </summary>
 1197    /// <remarks>This operator enables direct subtraction between a tuple of three integers and a Vector3d,
 1198    /// returning a new Vector3d instance.</remarks>
 1199    /// <param name="v1">A tuple containing the x, y, and z components to subtract from.</param>
 1200    /// <param name="v2">The Vector3d whose components are subtracted from the corresponding components of the tuple.</p
 1201    /// <returns>A Vector3d whose components are the result of subtracting the components of v2 from the corresponding c
 1202    /// of v1.</returns>
 1203    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1204    public static Vector3d operator -((int x, int y, int z) v1, Vector3d v2)
 11205    {
 11206        return new Vector3d(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
 11207    }
 1208
 1209    /// <summary>
 1210    /// Negates each component of the specified vector.
 1211    /// </summary>
 1212    /// <param name="v1">The vector whose components are to be negated.</param>
 1213    /// <returns>A new vector whose components are the negated values of the input vector.</returns>
 1214    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1215    public static Vector3d operator -(Vector3d v1)
 4851216    {
 4851217        return new Vector3d(v1.x * -Fixed64.One, v1.y * -Fixed64.One, v1.z * -Fixed64.One);
 4851218    }
 1219
 1220    /// <summary>
 1221    /// Multiplies the specified vector by a scalar value.
 1222    /// </summary>
 1223    /// <param name="v1">The vector to be scaled.</param>
 1224    /// <param name="mag">The scalar value by which to multiply each component of the vector.</param>
 1225    /// <returns>A new vector whose components are the products of the corresponding components of the input vector and 
 1226    /// scalar value.</returns>
 1227    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1228    public static Vector3d operator *(Vector3d v1, Fixed64 mag)
 15031229    {
 15031230        return new Vector3d(v1.x * mag, v1.y * mag, v1.z * mag);
 15031231    }
 1232
 1233    /// <inheritdoc cref="operator *(Vector3d, Fixed64)"/>
 1234    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1235    public static Vector3d operator *(Fixed64 mag, Vector3d v1)
 131236    {
 131237        return new Vector3d(v1.x * mag, v1.y * mag, v1.z * mag);
 131238    }
 1239
 1240    /// <summary>
 1241    /// Multiplies each component of the specified vector by the given scalar value.
 1242    /// </summary>
 1243    /// <param name="v1">The vector whose components are to be multiplied.</param>
 1244    /// <param name="mag">The scalar value by which to multiply each component of the vector.</param>
 1245    /// <returns>A new Vector3d whose components are the products of the corresponding components of the input vector an
 1246    /// scalar value.</returns>
 1247    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1248    public static Vector3d operator *(Vector3d v1, int mag)
 01249    {
 01250        return new Vector3d(v1.x * mag, v1.y * mag, v1.z * mag);
 01251    }
 1252
 1253    /// <inheritdoc cref="operator *(Vector3d, int)"/>
 1254    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1255    public static Vector3d operator *(int mag, Vector3d v1)
 11256    {
 11257        return new Vector3d(v1.x * mag, v1.y * mag, v1.z * mag);
 11258    }
 1259
 1260    /// <summary>
 1261    /// Multiplies a 3x3 matrix by a 3-dimensional vector and returns the resulting vector.
 1262    /// </summary>
 1263    /// <remarks>
 1264    /// This operation applies the linear transformation represented by the matrix to the vector.
 1265    /// The multiplication is performed using standard matrix-vector multiplication rules.
 1266    /// </remarks>
 1267    /// <param name="matrix">The 3x3 matrix to multiply.</param>
 1268    /// <param name="vector">The 3-dimensional vector to be transformed by the matrix.</param>
 1269    /// <returns>A new Vector3d that is the result of multiplying the specified matrix by the specified vector.</returns
 1270    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1271    public static Vector3d operator *(Fixed3x3 matrix, Vector3d vector)
 21272    {
 21273        return new Vector3d(
 21274            matrix.m00 * vector.x + matrix.m01 * vector.y + matrix.m02 * vector.z,
 21275            matrix.m10 * vector.x + matrix.m11 * vector.y + matrix.m12 * vector.z,
 21276            matrix.m20 * vector.x + matrix.m21 * vector.y + matrix.m22 * vector.z
 21277        );
 21278    }
 1279
 1280    /// <inheritdoc cref="operator *(Fixed3x3, Vector3d)"/>
 1281    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1282    public static Vector3d operator *(Vector3d vector, Fixed3x3 matrix)
 11283    {
 11284        return matrix * vector;
 11285    }
 1286
 1287    /// <summary>
 1288    /// Transforms the specified 3D vector by the given 4x4 matrix using homogeneous coordinates.
 1289    /// </summary>
 1290    /// <remarks>
 1291    /// If the matrix is affine, the transformation is performed without perspective division.
 1292    /// For non-affine matrices, the result is divided by the computed w component to account for perspective
 1293    /// transformations.
 1294    /// If the computed w component is zero, it is treated as one to avoid division by zero.
 1295    /// </remarks>
 1296    /// <param name="matrix">The 4x4 matrix to apply to the vector. Must represent a valid transformation.</param>
 1297    /// <param name="point">The 3D vector to be transformed.</param>
 1298    /// <returns>A new Vector3d representing the transformed vector after applying the matrix.</returns>
 1299    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1300    public static Vector3d operator *(Fixed4x4 matrix, Vector3d point)
 61301    {
 61302        if (matrix.IsAffine)
 21303        {
 21304            return new Vector3d(
 21305                matrix.m00 * point.x + matrix.m01 * point.y + matrix.m02 * point.z + matrix.m03 + matrix.m30,
 21306                matrix.m10 * point.x + matrix.m11 * point.y + matrix.m12 * point.z + matrix.m13 + matrix.m31,
 21307                matrix.m20 * point.x + matrix.m21 * point.y + matrix.m22 * point.z + matrix.m23 + matrix.m32
 21308            );
 1309        }
 1310
 1311        // Full 4×4 transformation
 41312        Fixed64 w = matrix.m03 * point.x + matrix.m13 * point.y + matrix.m23 * point.z + matrix.m33;
 61313        if (w == Fixed64.Zero) w = Fixed64.One;  // Prevent divide-by-zero
 1314
 41315        return new Vector3d(
 41316            (matrix.m00 * point.x + matrix.m01 * point.y + matrix.m02 * point.z + matrix.m03 + matrix.m30) / w,
 41317            (matrix.m10 * point.x + matrix.m11 * point.y + matrix.m12 * point.z + matrix.m13 + matrix.m31) / w,
 41318            (matrix.m20 * point.x + matrix.m21 * point.y + matrix.m22 * point.z + matrix.m23 + matrix.m32) / w
 41319        );
 61320    }
 1321
 1322    /// <inheritdoc cref="operator *(Fixed4x4, Vector3d)"/>
 1323    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1324    public static Vector3d operator *(Vector3d vector, Fixed4x4 matrix)
 31325    {
 31326        return matrix * vector;
 31327    }
 1328
 1329    /// <summary>
 1330    /// Multiplies the corresponding components of two vectors and returns the resulting vector.
 1331    /// </summary>
 1332    /// <remarks>
 1333    /// This operation performs component-wise multiplication, not a dot or cross product.
 1334    /// Each component of the result is calculated as the product of the corresponding components of the input
 1335    /// vectors.
 1336    /// </remarks>
 1337    /// <param name="v1">The first vector to multiply.</param>
 1338    /// <param name="v2">The second vector to multiply.</param>
 1339    /// <returns>A new Vector3d whose components are the products of the corresponding components of the input vectors.<
 1340    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1341    public static Vector3d operator *(Vector3d v1, Vector3d v2)
 11342    {
 11343        return new Vector3d(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
 11344    }
 1345
 1346    /// <summary>
 1347    /// Divides each component of a vector by a specified scalar value.
 1348    /// </summary>
 1349    /// <remarks>If the scalar value is zero, the result is a zero vector to avoid division by zero.</remarks>
 1350    /// <param name="v1">The vector whose components are to be divided.</param>
 1351    /// <param name="div">The scalar value by which to divide each component of the vector.</param>
 1352    /// <returns>
 1353    /// A new vector whose components are the result of dividing the corresponding components of the input vector by the
 1354    /// specified scalar.
 1355    /// Returns a zero vector if the scalar is zero.
 1356    /// </returns>
 1357    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1358    public static Vector3d operator /(Vector3d v1, Fixed64 div)
 3561359    {
 3561360        return div == Fixed64.Zero ? Zero : new Vector3d(v1.x / div, v1.y / div, v1.z / div);
 3561361    }
 1362
 1363    /// <summary>
 1364    /// Divides each component of one vector by the corresponding component of another vector.
 1365    /// </summary>
 1366    /// <remarks>Division by zero for any component in v2 results in a zero value for the corresponding
 1367    /// component in the result vector.</remarks>
 1368    /// <param name="v1">The vector whose components are to be divided (the dividend).</param>
 1369    /// <param name="v2">The vector whose components are used as divisors.</param>
 1370    /// <returns>
 1371    /// A new Vector3d whose components are the result of dividing the corresponding components of v1 by v2.
 1372    /// If a component of v2 is zero, the corresponding result component is set to zero.
 1373    /// </returns>
 1374    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1375    public static Vector3d operator /(Vector3d v1, Vector3d v2)
 61376    {
 61377        return new Vector3d(
 61378            v2.x == Fixed64.Zero ? Fixed64.Zero : v1.x / v2.x,
 61379            v2.y == Fixed64.Zero ? Fixed64.Zero : v1.y / v2.y,
 61380            v2.z == Fixed64.Zero ? Fixed64.Zero : v1.z / v2.z);
 61381    }
 1382
 1383    /// <summary>
 1384    /// Divides each component of a vector by the specified integer value.
 1385    /// </summary>
 1386    /// <param name="v1">The vector whose components are to be divided.</param>
 1387    /// <param name="div">The integer divisor. If zero, the result is a zero vector.</param>
 1388    /// <returns>
 1389    /// A new vector whose components are the result of dividing each component of the input vector by the specified
 1390    /// divisor.
 1391    /// Returns a zero vector if the divisor is zero.
 1392    /// </returns>
 1393    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1394    public static Vector3d operator /(Vector3d v1, int div)
 21395    {
 21396        return div == 0 ? Zero : new Vector3d(v1.x / div, v1.y / div, v1.z / div);
 21397    }
 1398
 1399    /// <summary>
 1400    /// Rotates the specified 3D point by the given quaternion.
 1401    /// </summary>
 1402    /// <remarks>
 1403    /// This operator applies the rotation to the point as if performing a geometric transformation in 3D space.</remark
 1404    /// <param name="point">The 3D point to be rotated.</param>
 1405    /// <param name="rotation">The quaternion representing the rotation to apply.</param>
 1406    /// <returns>A new Vector3d representing the rotated point.</returns>
 1407    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1408    public static Vector3d operator *(Vector3d point, FixedQuaternion rotation)
 11409    {
 11410        return rotation * point;
 11411    }
 1412
 1413    /// <inheritdoc cref="operator *(Vector3d, FixedQuaternion)"/>
 1414    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1415    public static Vector3d operator *(FixedQuaternion rotation, Vector3d point)
 41416    {
 41417        Fixed64 num1 = rotation.x * 2;
 41418        Fixed64 num2 = rotation.y * 2;
 41419        Fixed64 num3 = rotation.z * 2;
 41420        Fixed64 num4 = rotation.x * num1;
 41421        Fixed64 num5 = rotation.y * num2;
 41422        Fixed64 num6 = rotation.z * num3;
 41423        Fixed64 num7 = rotation.x * num2;
 41424        Fixed64 num8 = rotation.x * num3;
 41425        Fixed64 num9 = rotation.y * num3;
 41426        Fixed64 num10 = rotation.w * num1;
 41427        Fixed64 num11 = rotation.w * num2;
 41428        Fixed64 num12 = rotation.w * num3;
 41429        Vector3d vector3 = new(
 41430            (Fixed64.One - (num5 + num6)) * point.x + (num7 - num12) * point.y + (num8 + num11) * point.z,
 41431            (num7 + num12) * point.x + (Fixed64.One - (num4 + num6)) * point.y + (num9 - num10) * point.z,
 41432            (num8 - num11) * point.x + (num9 + num10) * point.y + (Fixed64.One - (num4 + num5)) * point.z
 41433        );
 41434        return vector3;
 41435    }
 1436
 1437    /// <summary>
 1438    /// Determines whether two Vector3d instances are equal.
 1439    /// </summary>
 1440    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 11441    public static bool operator ==(Vector3d left, Vector3d right) => left.Equals(right);
 1442
 1443    /// <summary>
 1444    /// Determines whether two Vector3d instances are not equal.
 1445    /// </summary>
 1446    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 11447    public static bool operator !=(Vector3d left, Vector3d right) => !left.Equals(right);
 1448
 1449    /// <summary>
 1450    /// Determines whether each component of the left vector is greater than the corresponding component of the right
 1451    /// vector.
 1452    /// </summary>
 1453    /// <param name="left">The first vector to compare.</param>
 1454    /// <param name="right">The second vector to compare.</param>
 1455    /// <returns>true if the x, y, and z components of left are all greater than those of right; otherwise, false.</retu
 1456    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1457    public static bool operator >(Vector3d left, Vector3d right)
 41458    {
 41459        return left.x > right.x
 41460            && left.y > right.y
 41461            && left.z > right.z;
 41462    }
 1463
 1464    /// <summary>
 1465    /// Determines whether each component of the first Vector3d is less than the corresponding component of the second
 1466    /// Vector3d.
 1467    /// </summary>
 1468    /// <remarks>
 1469    /// This operator performs a component-wise comparison.
 1470    /// All components of left must be less than the corresponding components of right for the result to be true.</remar
 1471    /// <param name="left">The first Vector3d to compare.</param>
 1472    /// <param name="right">The second Vector3d to compare.</param>
 1473    /// <returns>true if the x, y, and z components of left are all less than those of right; otherwise, false.</returns
 1474    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1475    public static bool operator <(Vector3d left, Vector3d right)
 41476    {
 41477        return left.x < right.x
 41478            && left.y < right.y
 41479            && left.z < right.z;
 41480    }
 1481
 1482    /// <summary>
 1483    /// Determines whether each component of the left Vector3d is greater than or equal to the corresponding component
 1484    /// of the right Vector3d.
 1485    /// </summary>
 1486    /// <param name="left">The first Vector3d to compare.</param>
 1487    /// <param name="right">The second Vector3d to compare.</param>
 1488    /// <returns>true if the x, y, and z components of left are each greater than or equal to those of right; otherwise,
 1489    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1490    public static bool operator >=(Vector3d left, Vector3d right)
 41491    {
 41492        return left.x >= right.x
 41493            && left.y >= right.y
 41494            && left.z >= right.z;
 41495    }
 1496
 1497    /// <summary>
 1498    /// Determines whether each component of the first Vector3d is less than or equal to the corresponding component of
 1499    /// the second Vector3d.
 1500    /// </summary>
 1501    /// <param name="left">The first Vector3d to compare.</param>
 1502    /// <param name="right">The second Vector3d to compare.</param>
 1503    /// <returns>true if the x, y, and z components of left are each less than or equal to the corresponding components 
 1504    /// otherwise, false.</returns>
 1505    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1506    public static bool operator <=(Vector3d left, Vector3d right)
 41507    {
 41508        return left.x <= right.x
 41509            && left.y <= right.y
 41510            && left.z <= right.z;
 41511    }
 1512
 1513    #endregion
 1514
 1515    #region Conversion
 1516
 1517    /// <summary>
 1518    /// Returns a string that represents the current object in the format "(x, y, z)".
 1519    /// </summary>
 1520    /// <returns>A string representation of the object, displaying the x, y, and z values in a formatted tuple.</returns
 1521    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1522    public override string ToString()
 7631523    {
 7631524        return string.Format("({0}, {1}, {2})", x.ToFormattedDouble(), y.ToFormattedDouble(), z.ToFormattedDouble());
 7631525    }
 1526
 1527    /// <summary>
 1528    /// Converts this <see cref="Vector3d"/> to a <see cref="Vector2d"/>,
 1529    /// dropping the Y component (height) of this vector in the resulting vector.
 1530    /// </summary>
 1531    /// <returns>
 1532    /// A new <see cref="Vector2d"/> where (X, Z) from this <see cref="Vector3d"/>
 1533    /// become (X, Y) in the resulting vector.
 1534    /// </returns>
 1535    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1536    public Vector2d ToVector2d()
 11537    {
 11538        return new Vector2d(x, z);
 11539    }
 1540
 1541    /// <summary>
 1542    /// Converts this <see cref="Vector3d"/> to a <see cref="Vector4d"/> with an explicit W component.
 1543    /// </summary>
 1544    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1545    public Vector4d ToVector4d(Fixed64 w)
 11546    {
 11547        return new Vector4d(x, y, z, w);
 11548    }
 1549
 1550    /// <summary>
 1551    /// Deconstructs the vector into its X, Y, and Z components as single-precision floating-point values.
 1552    /// </summary>
 1553    /// <param name="x">When this method returns, contains the X component of the vector as a single-precision floating-
 1554    /// <param name="y">When this method returns, contains the Y component of the vector as a single-precision floating-
 1555    /// <param name="z">When this method returns, contains the Z component of the vector as a single-precision floating-
 1556    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1557    public readonly void Deconstruct(out float x, out float y, out float z)
 11558    {
 11559        x = this.x.ToPreciseFloat();
 11560        y = this.y.ToPreciseFloat();
 11561        z = this.z.ToPreciseFloat();
 11562    }
 1563
 1564    /// <summary>
 1565    /// Deconstructs the current instance into its component integer values.
 1566    /// </summary>
 1567    /// <remarks>This method enables deconstruction syntax, allowing the instance to be unpacked into three
 1568    /// integer variables representing its components.</remarks>
 1569    /// <param name="x">When this method returns, contains the rounded integer value of the X component.</param>
 1570    /// <param name="y">When this method returns, contains the rounded integer value of the Y component.</param>
 1571    /// <param name="z">When this method returns, contains the rounded integer value of the Z component.</param>
 1572    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1573    public readonly void Deconstruct(out int x, out int y, out int z)
 11574    {
 11575        x = this.x.RoundToInt();
 11576        y = this.y.RoundToInt();
 11577        z = this.z.RoundToInt();
 11578    }
 1579
 1580    /// <summary>
 1581    /// Converts each component of the vector from radians to degrees.
 1582    /// </summary>
 1583    /// <param name="radians">The vector with components in radians.</param>
 1584    /// <returns>A new vector with components converted to degrees.</returns>
 1585    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1586    public static Vector3d ToDegrees(Vector3d radians)
 11587    {
 11588        return new Vector3d(
 11589            FixedMath.RadToDeg(radians.x),
 11590            FixedMath.RadToDeg(radians.y),
 11591            FixedMath.RadToDeg(radians.z));
 11592    }
 1593
 1594    /// <summary>
 1595    /// Converts each component of the vector from degrees to radians.
 1596    /// </summary>
 1597    /// <param name="degrees">The vector with components in degrees.</param>
 1598    /// <returns>A new vector with components converted to radians.</returns>
 1599    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1600    public static Vector3d ToRadians(Vector3d degrees)
 11601    {
 11602        return new Vector3d(
 11603            FixedMath.DegToRad(degrees.x),
 11604            FixedMath.DegToRad(degrees.y),
 11605            FixedMath.DegToRad(degrees.z));
 11606    }
 1607
 1608    #endregion
 1609
 1610    #region Equality and HashCode Overrides
 1611
 1612    /// <inheritdoc/>
 1613    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 51614    public override bool Equals(object? obj) => obj is Vector3d other && Equals(other);
 1615
 1616    /// <inheritdoc/>
 1617    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1618    public bool Equals(Vector3d other)
 3551619    {
 3551620        return other.x == x && other.y == y && other.z == z;
 3551621    }
 1622
 1623    /// <inheritdoc/>
 21624    public bool Equals(Vector3d x, Vector3d y) => x.Equals(y);
 1625
 1626    /// <inheritdoc/>
 1627    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 301628    public override int GetHashCode() => StateHash;
 1629
 1630    /// <inheritdoc/>
 11631    public int GetHashCode(Vector3d obj) => obj.GetHashCode();
 1632
 1633
 1634    /// <summary>
 1635    /// Compares the current Vector3d instance with another Vector3d based on their squared magnitudes.
 1636    /// </summary>
 1637    /// <remarks>
 1638    /// This comparison uses the squared magnitude of each vector, which avoids the computational
 1639    /// cost of calculating the actual magnitude.
 1640    /// Use this method when only relative vector lengths are
 1641    /// important.
 1642    /// </remarks>
 1643    /// <param name="other">The Vector3d instance to compare with the current instance.</param>
 1644    /// <returns>A value less than zero if this instance is less than <paramref name="other"/>; zero if this instance is
 1645    /// <paramref name="other"/>; or a value greater than zero if this instance is greater than <paramref
 1646    /// name="other"/>, as determined by their squared magnitudes.</returns>
 11647    public int CompareTo(Vector3d other) => SqrMagnitude.CompareTo(other.SqrMagnitude);
 1648
 1649    #endregion
 1650}

Methods/Properties

.ctor(System.Int32,System.Int32,System.Int32)
.ctor(System.Double,System.Double,System.Double)
.ctor(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
get_RightHandNormal()
get_LeftHandNormal()
get_Normal()
get_Magnitude()
get_Direction()
get_IsZero()
get_SqrMagnitude()
get_LongStateHash()
get_StateHash()
get_Item(System.Int32)
set_Item(System.Int32,FixedMathSharp.Fixed64)
Set(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
AddInPlace(FixedMathSharp.Fixed64)
AddInPlace(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
AddInPlace(FixedMathSharp.Vector3d)
SubtractInPlace(FixedMathSharp.Fixed64)
SubtractInPlace(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
SubtractInPlace(FixedMathSharp.Vector3d)
ScaleInPlace(FixedMathSharp.Fixed64)
ScaleInPlace(FixedMathSharp.Vector3d)
Normalize()
Normalize(FixedMathSharp.Fixed64&)
IsNormalized()
AllComponentsGreaterThanEpsilon()
SnapSmallComponentsToZero(System.Nullable`1<FixedMathSharp.Fixed64>)
Distance(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
SqrDistance(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Dot(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CrossProduct(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Cross(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Lerp(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
UnclampedLerp(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
SpeedLerp(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Slerp(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
GetNormalized(FixedMathSharp.Vector3d)
GetMagnitude(FixedMathSharp.Vector3d)
Abs(FixedMathSharp.Vector3d)
Sign(FixedMathSharp.Vector3d)
Clamp(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
ClampMagnitude(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
AreParallel(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
AreAlmostParallel(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
Midpoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Distance(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
SqrDistance(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
ClosestPointsOnTwoLines(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
SolveClosestLineParameters(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ClampSegmentParameter(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ClosestPointOnLineSegment(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Dot(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Scale(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Cross(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
CrossProduct(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Project(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
ProjectOnPlane(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
ProjectOnPlane(FixedMathSharp.Vector3d,FixedMathSharp.FixedPlane)
Angle(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Max(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Min(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Rotate(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
InverseRotate(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
op_Addition(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_Addition(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
op_Addition(FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
op_Addition(FixedMathSharp.Vector3d,System.ValueTuple`3<System.Int32,System.Int32,System.Int32>)
op_Addition(System.ValueTuple`3<System.Int32,System.Int32,System.Int32>,FixedMathSharp.Vector3d)
op_Subtraction(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_Subtraction(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
op_Subtraction(FixedMathSharp.Vector3d,System.ValueTuple`3<System.Int32,System.Int32,System.Int32>)
op_Subtraction(System.ValueTuple`3<System.Int32,System.Int32,System.Int32>,FixedMathSharp.Vector3d)
op_UnaryNegation(FixedMathSharp.Vector3d)
op_Multiply(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
op_Multiply(FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
op_Multiply(FixedMathSharp.Vector3d,System.Int32)
op_Multiply(System.Int32,FixedMathSharp.Vector3d)
op_Multiply(FixedMathSharp.Fixed3x3,FixedMathSharp.Vector3d)
op_Multiply(FixedMathSharp.Vector3d,FixedMathSharp.Fixed3x3)
op_Multiply(FixedMathSharp.Fixed4x4,FixedMathSharp.Vector3d)
op_Multiply(FixedMathSharp.Vector3d,FixedMathSharp.Fixed4x4)
op_Multiply(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_Division(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
op_Division(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_Division(FixedMathSharp.Vector3d,System.Int32)
op_Multiply(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
op_Multiply(FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d)
op_Equality(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_Inequality(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_GreaterThan(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_LessThan(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_GreaterThanOrEqual(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
op_LessThanOrEqual(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
ToString()
ToVector2d()
ToVector4d(FixedMathSharp.Fixed64)
Deconstruct(System.Single&,System.Single&,System.Single&)
Deconstruct(System.Int32&,System.Int32&,System.Int32&)
ToDegrees(FixedMathSharp.Vector3d)
ToRadians(FixedMathSharp.Vector3d)
Equals(System.Object)
Equals(FixedMathSharp.Vector3d)
Equals(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetHashCode()
GetHashCode(FixedMathSharp.Vector3d)
CompareTo(FixedMathSharp.Vector3d)