diff --git a/Engine.Core/Extensions/Vector2DExtensions.cs b/Engine.Core/Extensions/Vector2DExtensions.cs new file mode 100644 index 0000000..800510e --- /dev/null +++ b/Engine.Core/Extensions/Vector2DExtensions.cs @@ -0,0 +1,22 @@ +namespace Syntriax.Engine.Core; + +public static class Vector2DExtensions +{ + public static float Length(this Vector2D vector) => Vector2D.Length(vector); + public static float LengthSquared(this Vector2D vector) => Vector2D.LengthSquared(vector); + public static float Distance(this Vector2D from, Vector2D to) => Vector2D.Distance(from, to); + + public static Vector2D Reflect(this Vector2D vector, Vector2D normal) => Vector2D.Reflect(vector, normal); + public static Vector2D Normalize(this Vector2D vector) => Vector2D.Normalize(vector); + public static Vector2D FromTo(this Vector2D from, Vector2D to) => Vector2D.FromTo(from, to); + public static Vector2D Scale(this Vector2D vector, Vector2D scale) => Vector2D.FromTo(vector, scale); + + public static Vector2D Min(this Vector2D left, Vector2D right) => Vector2D.Min(left, right); + public static Vector2D Max(this Vector2D left, Vector2D right) => Vector2D.Max(left, right); + public static Vector2D Clamp(this Vector2D vector, Vector2D min, Vector2D max) => Vector2D.Clamp(vector, min, max); + public static Vector2D Lerp(this Vector2D from, Vector2D to, float t) => Vector2D.Lerp(from, to, t); + + public static float Cross(this Vector2D left, Vector2D right) => Vector2D.Cross(left, right); + public static float AngleBetween(this Vector2D left, Vector2D right) => Vector2D.Angle(left, right); + public static float Dot(this Vector2D left, Vector2D right) => Vector2D.Dot(left, right); +} diff --git a/Engine.Core/Vector2D.cs b/Engine.Core/Vector2D.cs new file mode 100644 index 0000000..bd15af2 --- /dev/null +++ b/Engine.Core/Vector2D.cs @@ -0,0 +1,46 @@ +using System; + +namespace Syntriax.Engine.Core; + +[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized}")] +public record Vector2D(float X, float Y) +{ + public float Magnitude => Length(this); + public float MagnitudeSquared => LengthSquared(this); + public Vector2D Normalized => Normalize(this); + + public readonly static Vector2D Up = new(0f, 1f); + public readonly static Vector2D Down = new(0f, -1f); + public readonly static Vector2D Left = new(-1f, 0f); + public readonly static Vector2D Right = new(1f, 0f); + public readonly static Vector2D Zero = new(0f, 0f); + public readonly static Vector2D One = new(1f, 1f); + + public static Vector2D operator -(Vector2D vector) => new(0f - vector.X, 0f - vector.Y); + public static Vector2D operator +(Vector2D left, Vector2D right) => new(left.X + right.X, left.Y + right.Y); + public static Vector2D operator -(Vector2D left, Vector2D right) => new(left.X - right.X, left.Y - right.Y); + public static Vector2D operator *(Vector2D vector, float value) => new(vector.X * value, vector.Y * value); + public static Vector2D operator *(float value, Vector2D vector) => new(vector.X * value, vector.Y * value); + public static Vector2D operator /(Vector2D vector, float value) => new(vector.X / value, vector.Y / value); + + public static float Length(Vector2D vector) => MathF.Sqrt(LengthSquared(vector)); + public static float LengthSquared(Vector2D vector) => vector.X * vector.X + vector.Y * vector.Y; + + public static float Distance(Vector2D from, Vector2D to) => Length(FromTo(from, to)); + + public static Vector2D Normalize(Vector2D vector) => vector / Length(vector); + public static Vector2D Reflect(Vector2D vector, Vector2D normal) => vector - 2f * Dot(vector, normal) * normal; + public static Vector2D FromTo(Vector2D from, Vector2D to) => to - from; + public static Vector2D Scale(Vector2D vector, Vector2D scale) => new(vector.X * scale.X, vector.Y * scale.Y); + + public static Vector2D Min(Vector2D left, Vector2D right) => new((left.X < right.X) ? left.X : right.X, (left.Y < right.Y) ? left.Y : right.Y); + public static Vector2D Max(Vector2D left, Vector2D right) => new((left.X > right.X) ? left.X : right.X, (left.Y > right.Y) ? left.Y : right.Y); + public static Vector2D Clamp(Vector2D vector, Vector2D min, Vector2D max) => new(Math.Clamp(vector.X, min.X, max.X), Math.Clamp(vector.Y, min.Y, max.Y)); + public static Vector2D Lerp(Vector2D from, Vector2D to, float t) => from + FromTo(from, to) * t; + + public static float Cross(Vector2D left, Vector2D right) => left.X * right.Y - left.Y * right.X; + public static float Angle(Vector2D left, Vector2D right) => MathF.Acos(Dot(left, right) / (Length(left) * Length(right))); + public static float Dot(Vector2D left, Vector2D right) => left.X * right.X + left.Y * right.Y; + + public override string ToString() => $"{nameof(Vector2D)}({X}, {Y})"; +}