Create bare godot project

This commit is contained in:
2026-04-14 02:22:05 +02:00
commit 0b53ab9133
24 changed files with 29544 additions and 0 deletions

1237
FixPoint/FixPoint16.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
uid://d1ymd8m2to6u

386
FixPoint/FixPoint16Long.cs Normal file
View File

@@ -0,0 +1,386 @@
#if DEBUG
#define RANGE_CHECK
#endif
using System;
using System.Runtime.CompilerServices;
namespace MagmaEngine.Math;
public struct FixPoint16Long : IComparable, IComparable<FixPoint16Long>, IEquatable<FixPoint16Long>
{
public FixPoint16Long(FixPoint16Long other)
{
m_Value = other.m_Value;
}
public FixPoint16Long(int value)
{
m_Value = (long)value << c_Shift;
}
public FixPoint16Long(long value)
{
#if RANGE_CHECK
if (value < c_IntegerMin || value > c_IntegerMax)
{
throw new ArithmeticException($"Long to FixPoint argument out of range: {value}");
}
#endif
m_Value = value << c_Shift;
}
public FixPoint16Long(double value)
{
#if RANGE_CHECK
if (value < c_IntegerMin || value > c_IntegerMax)
{
throw new ArithmeticException($"Double to FixPoint argument out of range: {value}");
}
#endif
if (value < 0.0)
{
m_Value = (int)((value * c_Multiplier) - 0.5);
}
else
{
m_Value = (int)((value * c_Multiplier) + 0.5);
}
}
public FixPoint16Long(float value)
{
#if RANGE_CHECK
if (value < c_IntegerMin || value > c_IntegerMax)
{
throw new ArithmeticException($"Single to FixPoint argument out of range: {value}");
}
#endif
if (value < 0.0f)
{
m_Value = (int)((value * c_MultiplierFloat) - 0.5f);
}
else
{
m_Value = (int)((value * c_MultiplierFloat) + 0.5f);
}
}
public long ToLongFloor()
{
return m_Value >> c_Shift;
}
public long ToLongCeil()
{
return (m_Value + c_FractionMask) >> c_Shift;
}
public long ToLongRound()
{
if (m_Value < 0)
{
return -((-m_Value + c_Half) >> c_Shift);
}
return (m_Value + c_Half) >> c_Shift;
}
public long ToLong()
{
if (m_Value < 0)
{
return -(-m_Value >> c_Shift);
}
return m_Value >> c_Shift;
}
public double ToDouble()
{
return c_Divisor * m_Value;
}
public float ToFloat()
{
return c_DivisorFloat * m_Value;
}
public override string ToString()
{
return $"{ToDouble()}[0x{m_Value:x16}]";
}
public override int GetHashCode()
{
return m_Value.GetHashCode();
}
public int CompareTo(object? obj)
{
if (obj is not FixPoint16Long other)
return -1;
return m_Value.CompareTo(other.m_Value);
}
public int CompareTo(FixPoint16Long other)
{
return m_Value.CompareTo(other.m_Value);
}
public override bool Equals(object? obj)
{
if (obj == null)
{
return false;
}
return ((FixPoint16Long)obj).m_Value == m_Value;
}
public bool Equals(FixPoint16Long other)
{
return other.m_Value == m_Value;
}
public bool IsZero()
{
return m_Value == 0L;
}
public static bool operator ==(FixPoint16Long a, FixPoint16Long b)
{
return a.m_Value == b.m_Value;
}
public static bool operator !=(FixPoint16Long a, FixPoint16Long b)
{
return a.m_Value != b.m_Value;
}
public static bool operator <(FixPoint16Long a, FixPoint16Long b)
{
return a.m_Value < b.m_Value;
}
public static bool operator >(FixPoint16Long a, FixPoint16Long b)
{
return a.m_Value > b.m_Value;
}
public static bool operator <=(FixPoint16Long a, FixPoint16Long b)
{
return a.m_Value <= b.m_Value;
}
public static bool operator >=(FixPoint16Long a, FixPoint16Long b)
{
return a.m_Value >= b.m_Value;
}
public static FixPoint16Long operator <<(FixPoint16Long a, int shift)
{
return new() { m_Value = a.m_Value << shift };
}
public static FixPoint16Long operator >> (FixPoint16Long a, int shift)
{
return new() { m_Value = a.m_Value >> shift };
}
public static FixPoint16Long operator +(FixPoint16Long a, FixPoint16Long b)
{
return new() { m_Value = a.m_Value + b.m_Value };
}
public static FixPoint16Long operator -(FixPoint16Long a, FixPoint16Long b)
{
return new() { m_Value = a.m_Value - b.m_Value };
}
public static FixPoint16Long operator *(FixPoint16Long a, FixPoint16Long b)
{
Int128 bigA = a.m_Value;
Int128 bigB = b.m_Value;
var result = ((bigA * bigB) + c_Half) >> c_Shift;
#if RANGE_CHECK
if (result < long.MinValue || result > long.MaxValue)
{
throw new ArithmeticException($"Multiplication result out of range: {result}");
}
#endif
return new() { m_Value = (long)result };
}
public static FixPoint16Long operator /(FixPoint16Long a, FixPoint16Long b)
{
#if RANGE_CHECK
if (b.m_Value == 0)
{
throw new ArithmeticException("Divison by zero");
}
#endif
Int128 result;
if (((ulong)a.m_Value & 0x8000000000000000UL) == ((ulong)b.m_Value & 0x8000000000000000UL))
{
result = (((Int128)a.m_Value << c_Shift) + (b.m_Value / 2)) / b.m_Value;
}
else
{
result = (((Int128)a.m_Value << c_Shift) - (b.m_Value / 2)) / b.m_Value;
}
#if RANGE_CHECK
if (result < long.MinValue || result > long.MaxValue)
{
throw new ArithmeticException($"Division result out of range: {result}");
}
#endif
return new() { m_Value = (long)result };
}
public static FixPoint16Long operator -(FixPoint16Long a)
{
return new() { m_Value = -a.m_Value };
}
public static FixPoint16Long operator *(FixPoint16Long a, int value)
{
return new() { m_Value = a.m_Value * value };
}
public static FixPoint16Long operator /(FixPoint16Long a, int value)
{
#if RANGE_CHECK
if (value == 0)
{
throw new ArithmeticException("Divison by zero");
}
#endif
if (((a.m_Value >> 32) & 0x80000000) == (value & 0x80000000))
{
return new() { m_Value = (long)(((Int128)a.m_Value + (value / 2)) / value) };
}
return new() { m_Value = (long)(((Int128)a.m_Value - (value / 2)) / value) };
}
public static implicit operator FixPoint16Long(int value)
{
return new(value);
}
public static implicit operator FixPoint16Long(long value)
{
return new(value);
}
public static implicit operator FixPoint16Long(FixPoint16 value)
{
return new() { m_Value = value.m_Value };
}
public static explicit operator FixPoint16Long(double value)
{
return new(value);
}
public static explicit operator FixPoint16Long(float value)
{
return new(value);
}
public static explicit operator int(FixPoint16Long value)
{
return (int)value.ToLong();
}
public static explicit operator long(FixPoint16Long value)
{
return value.ToLong();
}
public static explicit operator double(FixPoint16Long value)
{
return value.ToDouble();
}
public static explicit operator float(FixPoint16Long value)
{
return value.ToFloat();
}
public static FixPoint16Long Floor(FixPoint16Long value)
{
return value.ToLongFloor();
}
public static FixPoint16Long Ceil(FixPoint16Long value)
{
return value.ToLongCeil();
}
public static FixPoint16Long Round(FixPoint16Long value)
{
return value.ToLongRound();
}
public static int Sign(FixPoint16Long value)
{
return System.Math.Sign(value.m_Value);
}
public static FixPoint16Long Abs(FixPoint16Long value)
{
return new() { m_Value = System.Math.Abs(value.m_Value) };
}
public static FixPoint16Long Min(FixPoint16Long value1, FixPoint16Long value2)
{
return new() { m_Value = System.Math.Min(value1.m_Value, value2.m_Value) };
}
public static FixPoint16Long Max(FixPoint16Long value1, FixPoint16Long value2)
{
return new() { m_Value = System.Math.Max(value1.m_Value, value2.m_Value) };
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static FixPoint16Long Length(FixPoint16Long a, FixPoint16Long b)
{
var aSquared = a.m_Value * a.m_Value;
var bSquared = b.m_Value * b.m_Value;
var value = aSquared + bSquared;
#if RANGE_CHECK
if (value < 0)
{
throw new ArithmeticException($"Length squared out of range: {value}");
}
#endif
return new() { m_Value = IntMath.Sqrt(value) };
}
private const int c_Shift = 16;
private const long c_IntegerMin = -140737488355327L;
private const long c_IntegerMax = 140737488355327L;
private const long c_Half = 32786L;
private const long c_FractionMask = 0x000000000000ffffL;
private const double c_Multiplier = 65536.0;
private const double c_Divisor = 1.0 / 65536.0;
private const float c_MultiplierFloat = 65536.0f;
private const float c_DivisorFloat = (float)c_Divisor;
public long m_Value;
public static readonly FixPoint16Long Zero = new() { m_Value = 0 };
public static readonly FixPoint16Long MinValue = new() { m_Value = long.MinValue };
public static readonly FixPoint16Long MaxValue = new() { m_Value = long.MaxValue };
public static readonly FixPoint16Long Epsilon = new() { m_Value = 1 };
public static readonly FixPoint16Long MinusEpsilon = new() { m_Value = -1 };
public static readonly FixPoint16Long One = new(1);
public static readonly FixPoint16Long MinusOne = new(-1);
public static readonly FixPoint16Long Half = new() { m_Value = One.m_Value / 2 };
public static readonly FixPoint16Long MinusHalf = -Half;
}

View File

@@ -0,0 +1 @@
uid://i21oxan7sd8p

24670
FixPoint/FixPoint16Tables.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
uid://c10dgxlu0d17c

69
FixPoint/FixPointUtil.cs Normal file
View File

@@ -0,0 +1,69 @@
namespace MagmaEngine.Math;
public static class FixPointUtil
{
public static long DistancePointToSegmentSquared(FixPointVector2 point, FixPointVector2 segmentStart, FixPointVector2 segmentEnd)
{
var segment = segmentEnd - segmentStart;
var toStart = point - segmentStart;
var segmentLengthSquared = FixPointVector2.DotLong(segment, segment);
if (segmentLengthSquared == 0L)
return FixPointVector2.DotLong(toStart, toStart);
var projection = FixPointVector2.DotLong(toStart, segment);
if (projection <= 0)
return FixPointVector2.DotLong(toStart, toStart);
FixPointVector2 toPointOnSegment;
if (projection >= segmentLengthSquared)
toPointOnSegment = point - segmentEnd;
else
toPointOnSegment = toStart - segment * FixPoint16.FromRational(projection, segmentLengthSquared);
return FixPointVector2.DotLong(toPointOnSegment, toPointOnSegment);
}
public static FixPoint16 DistancePointToSegment(FixPointVector2 point, FixPointVector2 segmentStart, FixPointVector2 segmentEnd)
{
return FixPoint16.SqrtLong(DistancePointToSegmentSquared(point, segmentStart, segmentEnd));
}
public static bool LineLineIntersection(FixPointVector2 line1Start, FixPointVector2 line1End, FixPointVector2 line2Start, FixPointVector2 line2End, out FixPointVector2 intersectionPoint)
{
intersectionPoint = default;
var s1 = line1End - line1Start;
var s2 = line2End - line2Start;
var det = (FixPoint16Long)(-s2.m_X) * s1.m_Y + (FixPoint16Long)(s1.m_X) * s2.m_Y;
if (FixPoint16Long.Abs(det) < s_IntersectionEpsilon)
return false;
var t = ((FixPoint16Long)s2.m_X * (line1Start.m_Y - line2Start.m_Y) - (FixPoint16Long)s2.m_Y * (line1Start .m_X - line2Start.m_X)) / det;
var px = line1Start.m_X + (t * s1.m_X);
var py = line1Start.m_Y + (t * s1.m_Y);
if (px.m_Value > s_LineIntersectionMax || px.m_Value < s_LineIntersectionMin || py.m_Value > s_LineIntersectionMax || py.m_Value < s_LineIntersectionMin)
return false;
intersectionPoint = new FixPointVector2(FixPoint16.FromValue(px.m_Value), FixPoint16.FromValue(py.m_Value));
return true;
}
public static FixPoint16 MultiplyClamped(FixPoint16 a, FixPoint16 b)
{
var iResult = (((long)a.m_Value * b.m_Value) + FixPoint16.c_Half) >> FixPoint16.c_Shift;
if (iResult < FixPoint16.c_LongMin)
iResult = FixPoint16.c_LongMin;
else if (iResult > FixPoint16.c_LongMax)
iResult = FixPoint16.c_LongMax;
return new() { m_Value = (int)iResult };
}
private static readonly FixPoint16 s_IntersectionEpsilon = FixPoint16.Epsilon * 30;
private static readonly long s_LineIntersectionMax = FixPoint16.c_LongMax / 4;
private static readonly long s_LineIntersectionMin = FixPoint16.c_LongMin / 4;
}

View File

@@ -0,0 +1 @@
uid://bxrdtopa5ct2u

1245
FixPoint/FixPointVector2.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
uid://cn1byd6pp54cv

993
FixPoint/FixPointVector3.cs Normal file
View File

@@ -0,0 +1,993 @@
using System;
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace MagmaEngine.Math;
public struct SFixPointVector3 : IEquatable<SFixPointVector3>
{
/// <summary>
/// Initializes a new instance of FixPointVector3
/// </summary>
/// <param name="x">Initial value for the x-component of the vector.</param>
/// <param name="y">Initial value for the y-component of the vector.</param>
/// <param name="z">Initial value for the z-component of the vector.</param>
[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));
}
}
}
/// <summary>
/// Returns a new normalized FixPointVector3 from the current vector.
/// </summary>
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 ---------------------------------------------
/// <summary>
/// Calculates the length of the current vector.
/// </summary>
/// <returns>The Length of the current vector.</returns>
[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));
}
}
/// <summary>
/// Normalizes the current vector
/// </summary>
[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();
}
/// <summary>
/// Adds a given scalar value to each component of the current FixPointVector3.
/// </summary>
/// <param name="value">The scalar value</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(FixPoint16 value)
{
unchecked
{
m_X = m_X + value;
m_Y = m_Y + value;
m_Z = m_Z + value;
}
}
/// <summary>
/// Adds a given FixPointVector3 to the current FixPointVector3.
/// </summary>
/// <param name="other">The vector to be added.</param>
[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;
}
}
/// <summary>
/// Subtracts a scalar value from each component of the current FixPointVector3.
/// </summary>
/// <param name="value">The scalar value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Subtract(FixPoint16 value)
{
unchecked
{
m_X = m_X - value;
m_Y = m_Y - value;
m_Z = m_Z - value;
}
}
/// <summary>
/// Subtracts a given FixPointVector3 from the current FixPointVector3.
/// </summary>
/// <param name="other">The vector to be subtracted.</param>
[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;
}
}
/// <summary>
/// Multiplies each component of the current FixPointVector3 by a given scalar value.
/// </summary>
/// <param name="scalar">The scalar value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Multiply(FixPoint16 scalar)
{
unchecked
{
m_X = m_X * scalar;
m_Y = m_Y * scalar;
m_Z = m_Z * scalar;
}
}
/// <summary>
/// Multiplies the current FixPointVector3 by another FixPointVector3.
/// </summary>
/// <param name="other">The source vector.</param>
[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;
}
}
/// <summary>
/// Divides each component of the current FixPointVector3 by a given scalar value.
/// </summary>
/// <param name="divider">The scalar divider.</param>
[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;
}
}
/// <summary>
/// Divides the current FixPointVector3 by another FixPointVector3.
/// </summary>
/// <param name="other">The vector divider.</param>
[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
}
}
/// <summary>
/// Transforms a FixPointVector3.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public static SFixPointVector3 Transform(SFixPointVector3 v, SFixPointQuaternionTransform t)
{
return Transform(v * t.m_Size, t.m_Orientation) + t.m_Position;
}
/// <summary>
/// Transforms a vector by the given Quaternion rotation value.
/// </summary>
/// <param name="value">The source vector to be rotated.</param>
/// <param name="rotation">The rotation to apply.</param>
/// <returns>The transformed vector.</returns>
[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 --------------------------------------
/// <summary>
/// Calculates the length of the given vector.
/// </summary>
/// <returns>The Length of the given vector.</returns>
[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));
}
}
/// <summary>
/// Computes the cross product of two vectors.
/// </summary>
/// <param name="vector1">The first vector.</param>
/// <param name="vector2">The second vector.</param>
/// <returns>The cross product.</returns>
[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));
}
/// <summary>
/// Calculates the distance between two vectors. (manhatten/taxi-cab metrix)
/// </summary>
/// <param name="left">The source vector</param>
/// <param name="right">The source vector</param>
/// <returns>Distance between the two vectors.</returns>
[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);
}
/// <summary>
/// Calculates the distance between two vectors.
/// </summary>
/// <param name="left">The source vector</param>
/// <param name="right">The source vector</param>
/// <returns>Distance between the two vectors.</returns>
[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);
}
/// <summary>
/// Calculates the dot product of two vectors.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="right">The source vector.</param>
/// <returns>The dot product of the two vectors.</returns>
[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);
}
/// <summary>
/// Calculates the dot product of two vectors.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="right">The source vector.</param>
/// <returns>The dot product of the two vectors.</returns>
[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) };
}
/// <summary>
/// Calculates the sign of the dot product of two vectors.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="right">The source vector.</param>
/// <returns>The sign of the dot product of the two vectors.</returns>
[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);
}
}
/// <summary>
/// Creates a unit vector from the specified vector.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The created unit vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SFixPointVector3 Normalize(SFixPointVector3 value)
{
return value.Normalized;
}
/// <summary>
/// Returns a vector that contains the lowest value from each matching pair of components.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The source vector.</param>
/// <returns>The minimized vector.</returns>
[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;
}
/// <summary>
/// Returns a vector that contains the highest value from each matching pair of components.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The source vector.</param>
/// <returns>The maximized vector.</returns>
[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;
}
/// <summary>
/// Returns a vector pointing in the opposite direction.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>A new vector pointing in the opposite direction.</returns>
[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;
}
}
/// <summary>
/// Adds two vectors
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The source vector.</param>
/// <returns>A new vector representing the sum of the source vectors.</returns>
[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;
}
}
/// <summary>
/// Adds a given scalar value to each component of a given vector.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The scalar value to be added to the vector.</param>
/// <returns>A new FixPointVector3 representing the sum of the given vector and scalar.</returns>
[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;
}
}
/// <summary>
/// Subtracts a vector from another vector.
/// </summary>
/// <param name="value1">The vector to be subtracted from.</param>
/// <param name="value2">The vector to be subtracted.</param>
/// <returns>A new vector representing the result of the subtraction.</returns>
[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;
}
}
/// <summary>
/// Subtracts a given scalar value from each component of a given vector.
/// </summary>
/// <param name="value1">The vector to be subtracted from.</param>
/// <param name="value2">The scalar value to subtracted.</param>
/// <returns>A new FixPointVector3 representing the result of the subtraction.</returns>
[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;
}
}
/// <summary>
/// Multiplies the components of two vectors by each other.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The source vector.</param>
/// <returns>A new vector representing the result of the mulitiplication.</returns>
[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;
}
}
/// <summary>
/// Multiplies a vector by a scalar value.
/// </summary>
/// <param name="value">The source vector.</param>
/// <param name="scalar">The scalar value.</param>
/// <returns>A new vector representing the result of the mulitiplication.</returns>
[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;
}
}
/// <summary>
/// Divides the components of a vector by the components of another vector.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The divisor vector.</param>
/// <returns>A new vector representing the result of the division.</returns>
[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;
}
}
/// <summary>
/// Projects a vector onto another vector.
/// </summary>
/// <param name="projected">The projected vector.</param>
/// <param name="projectionTarget">The vector the projected vector is being projected on.</param>
/// <returns>A new vector representing the result of the division.</returns>
[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;
}
}
/// <summary>
/// Divides a vector by a scalar value.
/// </summary>
/// <param name="value">The source vector.</param>
/// <param name="divider">The divider</param>
/// <returns>A new vector representing the result of the division.</returns>
[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;
}
}
/// <summary>
/// Creates a new FixPointVector3 with each component being the result of dividing a scalar value by the corresponding
/// component of a vector.
/// </summary>
/// <param name="value">The scalar value to be divided.</param>
/// <param name="divider">The divider vector</param>
/// <returns>
/// A new vector with each component being the result of dividing the scalar value by the corresponding component
/// of the vector.
/// </returns>
[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;
}
}
/// <summary>
/// Performs a linear interpolation between two vectors.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The source vector.</param>
/// <param name="amount">
/// 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.
/// </param>
/// <returns>The linear interpolation of the two vectors.</returns>
[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;
}
}
/// <summary>
/// Interpolates between two vectors using a cubic equation.
/// </summary>
/// <param name="value1">The source value.</param>
/// <param name="value2">The source value.</param>
/// <param name="amount">The weighting value.</param>
/// <returns>The interpolated value.</returns>
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);
}
/// <summary>
/// Returns a FixPointVector3 containing the 2D Cartesian coordinates of a point specified in barycentric (areal)
/// coordinates relative to a 2D triangle.
/// </summary>
/// <param name="value1">A FixPointVector3 containing the 2D Cartesian coordinates of vertex 1 of the triangle.</param>
/// <param name="value2">A FixPointVector3 containing the 2D Cartesian coordinates of vertex 2 of the triangle.</param>
/// <param name="value3">A FixPointVector3 containing the 2D Cartesian coordinates of vertex 3 of the triangle.</param>
/// <param name="amount1">
/// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in
/// _value2).
/// </param>
/// <param name="amount2">
/// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in
/// _value3).
/// </param>
/// <returns>A new FixPointVector3 containing the 2D Cartesian coordinates of the specified point.</returns>
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
/// <summary>
/// The x-component of the vector.
/// </summary>
public FixPoint16 m_X;
/// <summary>
/// The y-component of the vector.
/// </summary>
public FixPoint16 m_Y;
/// <summary>
/// The z-component of the vector.
/// </summary>
public FixPoint16 m_Z;
}

View File

@@ -0,0 +1 @@
uid://dci3uksrcv47

119
FixPoint/IntRandom.cs Normal file
View File

@@ -0,0 +1,119 @@
using System;
namespace MagmaEngine.Math;
/// <summary>
/// Implements a XorShift* PRNG, with 64 bits of internal state.
/// See http://en.wikipedia.org/wiki/Xorshift
/// </summary>
public struct SIntRandom
{
public SIntRandom(ulong seed)
{
if (seed == 0)
throw new InvalidOperationException("Seed needs to be bigger than zero.");
m_Seed = seed;
}
public ulong Next()
{
m_Seed ^= m_Seed >> 12;
m_Seed ^= m_Seed << 25;
m_Seed ^= m_Seed >> 27;
return m_Seed * 2685821657736338717UL; // multiplier taken from wikipedia article on XorShift PRNGs
}
public ulong Next(ulong upperLimit)
{
if (upperLimit == 0)
{
return 0;
}
return Next() % upperLimit;
}
public FixPoint16 NextFixPoint16()
{
return new() { m_Value = (int)(Next() & 0xffffUL) };
}
public int RandomizedRound(FixPoint16 value)
{
int ret = value.ToIntFloor();
if (NextFixPoint16() < FixPoint16.Fract(value))
ret++;
return ret;
}
public uint Next(uint upperLimit)
{
if (upperLimit == 0)
{
return 0;
}
return (uint)(Next() % upperLimit);
}
public uint Next(uint lowerLimit, uint upperLimit)
{
if (upperLimit == 0)
{
return 0;
}
if (lowerLimit == upperLimit)
{
return lowerLimit;
}
return lowerLimit + (uint)(Next() % (upperLimit - lowerLimit));
}
public int Next(int upperLimit)
{
if (upperLimit == 0)
{
return 0;
}
return (int)(Next() % (uint)(upperLimit & 0x7fffffff));
}
public int Next(int lowerLimit, int upperLimit)
{
if (upperLimit == 0)
{
return 0;
}
if (lowerLimit == upperLimit)
{
return lowerLimit;
}
return lowerLimit + (int)(Next() % (uint)((upperLimit - lowerLimit) & 0x7fffffff));
}
public double NextDouble()
{
return Next(int.MaxValue) * (1.0 / int.MaxValue);
}
public float NextSingle()
{
return (float)NextDouble();
}
public override readonly string ToString()
{
return $"0x{m_Seed:X}";
}
public readonly ulong Seed => m_Seed;
private ulong m_Seed;
}