using System; using System.Diagnostics.Contracts; using System.Numerics; using System.Runtime.CompilerServices; namespace MagmaEngine.Math; public struct SFixPointVector3 : IEquatable { /// /// Initializes a new instance of FixPointVector3 /// /// Initial value for the x-component of the vector. /// Initial value for the y-component of the vector. /// Initial value for the z-component of the vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public SFixPointVector3(int x, int y, int z) { m_X = x; m_Y = y; m_Z = z; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SFixPointVector3(FixPoint16 x, FixPoint16 y, FixPoint16 z) { m_X = x; m_Y = y; m_Z = z; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SFixPointVector3(FixPoint16 x) { m_X = x; m_Y = x; m_Z = x; } public SFixPointVector3(float x, float y, float z) { m_X = new(x); m_Y = new(y); m_Z = new(z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SFixPointVector3(Vector3 coord) { m_X = new(coord.X); m_Y = new(coord.Y); m_Z = new(coord.Z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator SFixPointVector3(Vector3 coord) { return new(new(coord.X), new(coord.Y), new FixPoint16(coord.Z)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator Vector3(SFixPointVector3 coord) { return new(coord.m_X.ToFloat(), coord.m_Y.ToFloat(), coord.m_Z.ToFloat()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public Vector3 ToVector3() { return new(m_X.ToFloat(), m_Y.ToFloat(), m_Z.ToFloat()); } #region -- base overrides --------------------------------------------- [Pure] public override string ToString() { return $"({m_X.ToString()}, {m_Y.ToString()}, {m_Z.ToString()})"; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public bool Equals(SFixPointVector3 other) { return m_X == other.m_X && m_Y == other.m_Y && m_Z == other.m_Z; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public override bool Equals(object? obj) { if (obj is SFixPointVector3 fixPointVector3) return Equals(fixPointVector3); return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public override int GetHashCode() { return m_X.GetHashCode() + m_Y.GetHashCode() + m_Z.GetHashCode(); } #endregion #region -- static properties ------------------------------------------ public static readonly SFixPointVector3 s_Zero = new(0, 0, 0); public static readonly SFixPointVector3 s_One = new(1, 1, 1); public static readonly SFixPointVector3 s_UnitX = new(1, 0, 0); public static readonly SFixPointVector3 s_UnitY = new(0, 1, 0); public static readonly SFixPointVector3 s_UnitZ = new(0, 0, 1); public static readonly SFixPointVector3 s_MaxValue = new(FixPoint16.MaxValue, FixPoint16.MaxValue, FixPoint16.MaxValue); public static readonly SFixPointVector3 s_MinValue = new(FixPoint16.MinValue, FixPoint16.MinValue, FixPoint16.MinValue); #endregion #region -- public properties ----------------------------------------- public FixPoint16 this[int i] { [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] get { switch (i) { case 0: return m_X; case 1: return m_Y; case 2: return m_Z; default: throw new ArgumentOutOfRangeException(nameof(i)); } } set { switch (i) { case 0: m_X = value; break; case 1: m_Y = value; break; case 2: m_Z = value; break; default: throw new ArgumentOutOfRangeException(nameof(i)); } } } /// /// Returns a new normalized FixPointVector3 from the current vector. /// public SFixPointVector3 Normalized { [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] get { var length = Length(); if (!length.IsZero()) { SFixPointVector3 result = new(m_X / length, m_Y / length, m_Z / length); return result; } throw new InvalidOperationException("Error: can not normalize vector, the vector length is zero."); } } public FixPointVector2 XY { [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] get => new(m_X, m_Y); } public FixPointVector2 XZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] get => new(m_X, m_Z); } #endregion #region -- public methods --------------------------------------------- /// /// Calculates the length of the current vector. /// /// The Length of the current vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public FixPoint16 Length() { return FixPoint16.Length(m_X, m_Y, m_Z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public int CompareLength(FixPoint16 length) { unchecked { return ((m_X.m_Value * (long)m_X.m_Value) + (m_Y.m_Value * (long)m_Y.m_Value) + (m_Z.m_Value * (long)m_Z.m_Value)).CompareTo(length.m_Value * (long)length.m_Value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public long LengthSquaredLong() { unchecked { return (m_X.m_Value * (long)m_X.m_Value) + (m_Y.m_Value * (long)m_Y.m_Value) + (m_Z.m_Value * (long)m_Z.m_Value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public int CompareLength(SFixPointVector3 other) { unchecked { return ((m_X.m_Value * (long)m_X.m_Value) + (m_Y.m_Value * (long)m_Y.m_Value) + (m_Z.m_Value * (long)m_Z.m_Value)).CompareTo( (other.m_X.m_Value * (long)other.m_X.m_Value) + (other.m_Y.m_Value * (long)other.m_Y.m_Value) + (other.m_Z.m_Value * (long)other.m_Z.m_Value)); } } /// /// Normalizes the current vector /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Normalize() { unchecked { var length = Length(); if (!length.IsZero()) { m_X = m_X / length; m_Y = m_Y / length; m_Z = m_Z / length; } #if DEBUG else { throw new("Error: can not normalize vector, the vector length is zero."); } #endif } } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public bool IsZero() { return m_X.IsZero() && m_Y.IsZero() && m_Z.IsZero(); } /// /// Adds a given scalar value to each component of the current FixPointVector3. /// /// The scalar value [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(FixPoint16 value) { unchecked { m_X = m_X + value; m_Y = m_Y + value; m_Z = m_Z + value; } } /// /// Adds a given FixPointVector3 to the current FixPointVector3. /// /// The vector to be added. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(SFixPointVector3 other) { unchecked { m_X = m_X + other.m_X; m_Y = m_Y + other.m_Y; m_Z = m_Z + other.m_Z; } } /// /// Subtracts a scalar value from each component of the current FixPointVector3. /// /// The scalar value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Subtract(FixPoint16 value) { unchecked { m_X = m_X - value; m_Y = m_Y - value; m_Z = m_Z - value; } } /// /// Subtracts a given FixPointVector3 from the current FixPointVector3. /// /// The vector to be subtracted. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Subtract(SFixPointVector3 other) { unchecked { m_X = m_X - other.m_X; m_Y = m_Y - other.m_Y; m_Z = m_Z - other.m_Z; } } /// /// Multiplies each component of the current FixPointVector3 by a given scalar value. /// /// The scalar value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Multiply(FixPoint16 scalar) { unchecked { m_X = m_X * scalar; m_Y = m_Y * scalar; m_Z = m_Z * scalar; } } /// /// Multiplies the current FixPointVector3 by another FixPointVector3. /// /// The source vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Multiply(SFixPointVector3 other) { unchecked { m_X = m_X * other.m_X; m_Y = m_Y * other.m_Y; m_Z = m_Z * other.m_Z; } } /// /// Divides each component of the current FixPointVector3 by a given scalar value. /// /// The scalar divider. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Divide(FixPoint16 divider) { #if DEBUG if (divider.IsZero()) throw new("Error: divider is zero (FixPointVector3.Divide)."); #endif unchecked { m_X = m_X / divider; m_Y = m_Y / divider; m_Z = m_Z / divider; } } /// /// Divides the current FixPointVector3 by another FixPointVector3. /// /// The vector divider. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Divide(SFixPointVector3 other) { unchecked { if (!other.m_X.IsZero() && !other.m_Y.IsZero() && !other.m_Z.IsZero()) { m_X = m_X / other.m_X; m_Y = m_Y / other.m_Y; m_Z = m_Z / other.m_Z; } #if DEBUG else { throw new("Error: divider vector contains zero (FixPointVector3.Divide)."); } #endif } } /// /// Transforms a FixPointVector3. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public static SFixPointVector3 Transform(SFixPointVector3 v, SFixPointQuaternionTransform t) { return Transform(v * t.m_Size, t.m_Orientation) + t.m_Position; } /// /// Transforms a vector by the given Quaternion rotation value. /// /// The source vector to be rotated. /// The rotation to apply. /// The transformed vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Transform(SFixPointVector3 value, SFixPointQuaternion rotation) { var x2 = rotation.m_X + rotation.m_X; var y2 = rotation.m_Y + rotation.m_Y; var z2 = rotation.m_Z + rotation.m_Z; var wx2 = rotation.m_W * x2; var wy2 = rotation.m_W * y2; var wz2 = rotation.m_W * z2; var xx2 = rotation.m_X * x2; var xy2 = rotation.m_X * y2; var xz2 = rotation.m_X * z2; var yy2 = rotation.m_Y * y2; var yz2 = rotation.m_Y * z2; var zz2 = rotation.m_Z * z2; return new((value.m_X * (1 - yy2 - zz2)) + (value.m_Y * (xy2 - wz2)) + (value.m_Z * (xz2 + wy2)), (value.m_X * (xy2 + wz2)) + (value.m_Y * (1 - xx2 - zz2)) + (value.m_Z * (yz2 - wx2)), (value.m_X * (xz2 - wy2)) + (value.m_Y * (yz2 + wx2)) + (value.m_Z * (1 - xx2 - yy2))); } #endregion #region -- public static methods -------------------------------------- /// /// Calculates the length of the given vector. /// /// The Length of the given vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FixPoint16 Length(SFixPointVector3 value) { return value.Length(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CompareLength(SFixPointVector3 value, FixPoint16 fLength) { unchecked { return ((value.m_X.m_Value * (long)value.m_X.m_Value) + (value.m_Y.m_Value * (long)value.m_Y.m_Value) + (value.m_Z.m_Value * (long)value.m_Z.m_Value)).CompareTo( fLength.m_Value * (long)fLength.m_Value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CompareLength(SFixPointVector3 value1, SFixPointVector3 value2) { unchecked { return ((value1.m_X.m_Value * (long)value1.m_X.m_Value) + (value1.m_Y.m_Value * (long)value1.m_Y.m_Value) + (value1.m_Z.m_Value * (long)value1.m_Z.m_Value)).CompareTo( (value2.m_X.m_Value * (long)value2.m_X.m_Value) + (value2.m_Y.m_Value * (long)value2.m_Y.m_Value) + (value2.m_Z.m_Value * (long)value2.m_Z.m_Value)); } } /// /// Computes the cross product of two vectors. /// /// The first vector. /// The second vector. /// The cross product. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Cross(SFixPointVector3 vector1, SFixPointVector3 vector2) { return new((vector1.m_Y * vector2.m_Z) - (vector1.m_Z * vector2.m_Y), (vector1.m_Z * vector2.m_X) - (vector1.m_X * vector2.m_Z), (vector1.m_X * vector2.m_Y) - (vector1.m_Y * vector2.m_X)); } /// /// Calculates the distance between two vectors. (manhatten/taxi-cab metrix) /// /// The source vector /// The source vector /// Distance between the two vectors. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FixPoint16 DistanceManhattan(SFixPointVector3 left, SFixPointVector3 right) { return FixPoint16.Abs(left.m_X - right.m_X) + FixPoint16.Abs(left.m_Y - right.m_Y) + FixPoint16.Abs(left.m_Z - right.m_Z); } /// /// Calculates the distance between two vectors. /// /// The source vector /// The source vector /// Distance between the two vectors. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FixPoint16 Distance(SFixPointVector3 left, SFixPointVector3 right) { var dx = left.m_X - right.m_X; var dy = left.m_Y - right.m_Y; var dz = left.m_Z - right.m_Z; return FixPoint16.Length(dx, dy, dz); } /// /// Calculates the dot product of two vectors. /// /// The source vector. /// The source vector. /// The dot product of the two vectors. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FixPoint16 Dot(SFixPointVector3 left, SFixPointVector3 right) { return (left.m_X * right.m_X) + (left.m_Y * right.m_Y) + (left.m_Z * right.m_Z); } /// /// Calculates the dot product of two vectors. /// /// The source vector. /// The source vector. /// The dot product of the two vectors. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FixPoint16Long DotLong(SFixPointVector3 left, SFixPointVector3 right) { return new() { m_Value = (left.m_X.m_Value * (long)right.m_X.m_Value) + (left.m_Y.m_Value * (long)right.m_Y.m_Value) + (left.m_Z.m_Value * (long)right.m_Z.m_Value) }; } /// /// Calculates the sign of the dot product of two vectors. /// /// The source vector. /// The source vector. /// The sign of the dot product of the two vectors. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int DotSign(SFixPointVector3 left, SFixPointVector3 right) { unchecked { return ((left.m_X.m_Value * (long)right.m_X.m_Value) + (left.m_Y.m_Value * (long)right.m_Y.m_Value) + (left.m_Z.m_Value * (long)right.m_Z.m_Value)).CompareTo(0); } } /// /// Creates a unit vector from the specified vector. /// /// The source vector. /// The created unit vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Normalize(SFixPointVector3 value) { return value.Normalized; } /// /// Returns a vector that contains the lowest value from each matching pair of components. /// /// The source vector. /// The source vector. /// The minimized vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Min(SFixPointVector3 value1, SFixPointVector3 value2) { SFixPointVector3 result; result.m_X = FixPoint16.Min(value1.m_X, value2.m_X); result.m_Y = FixPoint16.Min(value1.m_Y, value2.m_Y); result.m_Z = FixPoint16.Min(value1.m_Z, value2.m_Z); return result; } /// /// Returns a vector that contains the highest value from each matching pair of components. /// /// The source vector. /// The source vector. /// The maximized vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Max(SFixPointVector3 value1, SFixPointVector3 value2) { SFixPointVector3 result; result.m_X = FixPoint16.Max(value1.m_X, value2.m_X); result.m_Y = FixPoint16.Max(value1.m_Y, value2.m_Y); result.m_Z = FixPoint16.Max(value1.m_Z, value2.m_Z); return result; } /// /// Returns a vector pointing in the opposite direction. /// /// The source vector. /// A new vector pointing in the opposite direction. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Negate(SFixPointVector3 value) { unchecked { SFixPointVector3 result; result.m_X = -value.m_X; result.m_Y = -value.m_Y; result.m_Z = -value.m_Z; return result; } } /// /// Adds two vectors /// /// The source vector. /// The source vector. /// A new vector representing the sum of the source vectors. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Add(SFixPointVector3 value1, SFixPointVector3 value2) { unchecked { SFixPointVector3 result; result.m_X = value1.m_X + value2.m_X; result.m_Y = value1.m_Y + value2.m_Y; result.m_Z = value1.m_Z + value2.m_Z; return result; } } /// /// Adds a given scalar value to each component of a given vector. /// /// The source vector. /// The scalar value to be added to the vector. /// A new FixPointVector3 representing the sum of the given vector and scalar. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Add(SFixPointVector3 value1, FixPoint16 value2) { unchecked { SFixPointVector3 result; result.m_X = value1.m_X + value2; result.m_Y = value1.m_Y + value2; result.m_Z = value1.m_Z + value2; return result; } } /// /// Subtracts a vector from another vector. /// /// The vector to be subtracted from. /// The vector to be subtracted. /// A new vector representing the result of the subtraction. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Subtract(SFixPointVector3 value1, SFixPointVector3 value2) { unchecked { SFixPointVector3 result; result.m_X = value1.m_X - value2.m_X; result.m_Y = value1.m_Y - value2.m_Y; result.m_Z = value1.m_Z - value2.m_Z; return result; } } /// /// Subtracts a given scalar value from each component of a given vector. /// /// The vector to be subtracted from. /// The scalar value to subtracted. /// A new FixPointVector3 representing the result of the subtraction. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Subtract(SFixPointVector3 value1, FixPoint16 value2) { unchecked { SFixPointVector3 result; result.m_X = value1.m_X - value2; result.m_Y = value1.m_Y - value2; result.m_Z = value1.m_Z - value2; return result; } } /// /// Multiplies the components of two vectors by each other. /// /// The source vector. /// The source vector. /// A new vector representing the result of the mulitiplication. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Multiply(SFixPointVector3 value1, SFixPointVector3 value2) { unchecked { SFixPointVector3 result; result.m_X = value1.m_X * value2.m_X; result.m_Y = value1.m_Y * value2.m_Y; result.m_Z = value1.m_Z * value2.m_Z; return result; } } /// /// Multiplies a vector by a scalar value. /// /// The source vector. /// The scalar value. /// A new vector representing the result of the mulitiplication. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Multiply(SFixPointVector3 value, FixPoint16 scalar) { unchecked { SFixPointVector3 result; result.m_X = value.m_X * scalar; result.m_Y = value.m_Y * scalar; result.m_Z = value.m_Z * scalar; return result; } } /// /// Divides the components of a vector by the components of another vector. /// /// The source vector. /// The divisor vector. /// A new vector representing the result of the division. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Divide(SFixPointVector3 value1, SFixPointVector3 value2) { unchecked { SFixPointVector3 result; result.m_X = value1.m_X / value2.m_X; result.m_Y = value1.m_Y / value2.m_Y; result.m_Z = value1.m_Z / value2.m_Z; return result; } } /// /// Projects a vector onto another vector. /// /// The projected vector. /// The vector the projected vector is being projected on. /// A new vector representing the result of the division. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Project(SFixPointVector3 projected, SFixPointVector3 projectionTarget) { unchecked { SFixPointVector3 result; var fpDot = Dot(projected, projectionTarget); var fpProjectionTargetLength = projectionTarget.Length(); var fpScalar = fpDot / (fpProjectionTargetLength * fpProjectionTargetLength); result = projectionTarget * fpScalar; return result; } } /// /// Divides a vector by a scalar value. /// /// The source vector. /// The divider /// A new vector representing the result of the division. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Divide(SFixPointVector3 value, FixPoint16 divider) { unchecked { SFixPointVector3 result; result.m_X = value.m_X / divider; result.m_Y = value.m_Y / divider; result.m_Z = value.m_Z / divider; return result; } } /// /// Creates a new FixPointVector3 with each component being the result of dividing a scalar value by the corresponding /// component of a vector. /// /// The scalar value to be divided. /// The divider vector /// /// A new vector with each component being the result of dividing the scalar value by the corresponding component /// of the vector. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Divide(FixPoint16 value, SFixPointVector3 divider) { unchecked { SFixPointVector3 result; result.m_X = value / divider.m_X; result.m_Y = value / divider.m_Y; result.m_Z = value / divider.m_Z; return result; } } /// /// Performs a linear interpolation between two vectors. /// /// The source vector. /// The source vector. /// /// The value between 0 and 1 indicating the weight of _value2. '0.0' will cause _value1 to be /// returned; '1.0' will cause _value2 to be returned. /// /// The linear interpolation of the two vectors. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 Lerp(SFixPointVector3 value1, SFixPointVector3 value2, FixPoint16 amount) { unchecked { SFixPointVector3 result; result.m_X = value1.m_X + (amount * (value2.m_X - value1.m_X)); result.m_Y = value1.m_Y + (amount * (value2.m_Y - value1.m_Y)); result.m_Z = value1.m_Z + (amount * (value2.m_Z - value1.m_Z)); return result; } } /// /// Interpolates between two vectors using a cubic equation. /// /// The source value. /// The source value. /// The weighting value. /// The interpolated value. public static SFixPointVector3 SmoothStep(SFixPointVector3 value1, SFixPointVector3 value2, FixPoint16 amount) { var smootstep = FixPoint16.Min(0, FixPoint16.Max(1, amount)); smootstep = smootstep * smootstep * (3 - (2 * smootstep)); return Lerp(value1, value2, smootstep); } /// /// Returns a FixPointVector3 containing the 2D Cartesian coordinates of a point specified in barycentric (areal) /// coordinates relative to a 2D triangle. /// /// A FixPointVector3 containing the 2D Cartesian coordinates of vertex 1 of the triangle. /// A FixPointVector3 containing the 2D Cartesian coordinates of vertex 2 of the triangle. /// A FixPointVector3 containing the 2D Cartesian coordinates of vertex 3 of the triangle. /// /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in /// _value2). /// /// /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in /// _value3). /// /// A new FixPointVector3 containing the 2D Cartesian coordinates of the specified point. public static SFixPointVector3 Barycentric(SFixPointVector3 value1, SFixPointVector3 value2, SFixPointVector3 value3, FixPoint16 amount1, FixPoint16 amount2) { SFixPointVector3 result; result.m_X = value1.m_X + (amount1 * (value2.m_X - value1.m_X)) + (amount2 * (value3.m_X - value1.m_X)); result.m_Y = value1.m_Y + (amount1 * (value2.m_Y - value1.m_Y)) + (amount2 * (value3.m_Y - value1.m_Y)); result.m_Z = value1.m_Z + (amount1 * (value2.m_Z - value1.m_Z)) + (amount2 * (value3.m_Z - value1.m_Z)); return result; } public static SFixPointVector3 Fract(SFixPointVector3 p) { return new(FixPoint16.Fract(p.m_X), FixPoint16.Fract(p.m_Y), FixPoint16.Fract(p.m_Z)); } #endregion #region -- operators -------------------------------------------------- [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(SFixPointVector3 left, SFixPointVector3 right) { return left.Equals(right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(SFixPointVector3 left, SFixPointVector3 right) { return !left.Equals(right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator -(SFixPointVector3 value) { return Negate(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator +(SFixPointVector3 left, SFixPointVector3 right) { unchecked { SFixPointVector3 result; result.m_X = left.m_X + right.m_X; result.m_Y = left.m_Y + right.m_Y; result.m_Z = left.m_Z + right.m_Z; return result; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator +(SFixPointVector3 left, FixPoint16 right) { return Add(left, right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator -(SFixPointVector3 left, SFixPointVector3 right) { unchecked { SFixPointVector3 result; result.m_X = left.m_X - right.m_X; result.m_Y = left.m_Y - right.m_Y; result.m_Z = left.m_Z - right.m_Z; return result; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator -(SFixPointVector3 left, FixPoint16 right) { return Subtract(left, right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator *(SFixPointVector3 left, SFixPointVector3 right) { return Multiply(left, right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator *(SFixPointVector3 left, FixPoint16 right) { return new() { m_X = left.m_X * right, m_Y = left.m_Y * right, m_Z = left.m_Z * right }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator *(FixPoint16 left, SFixPointVector3 right) { return Multiply(right, left); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator /(SFixPointVector3 left, SFixPointVector3 right) { return Divide(left, right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator /(SFixPointVector3 left, FixPoint16 right) { return new() { m_X = left.m_X / right, m_Y = left.m_Y / right, m_Z = left.m_Z / right }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SFixPointVector3 operator /(FixPoint16 left, SFixPointVector3 right) { return Divide(left, right); } #endregion /// /// The x-component of the vector. /// public FixPoint16 m_X; /// /// The y-component of the vector. /// public FixPoint16 m_Y; /// /// The z-component of the vector. /// public FixPoint16 m_Z; }