diff --git a/Engine.Core/Primitives/Vector2DInt.cs b/Engine.Core/Primitives/Vector2DInt.cs new file mode 100644 index 0000000..b060953 --- /dev/null +++ b/Engine.Core/Primitives/Vector2DInt.cs @@ -0,0 +1,305 @@ +using System; + +namespace Engine.Core; + +/// +/// Represents a two-dimensional integer vector. +/// +/// X position of the . +/// Y position of the . +/// +/// Initializes a new instance of the struct with the specified positions. +/// +[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")] +public readonly struct Vector2DInt(int x, int y) : IEquatable +{ + /// + /// The X coordinate of the . + /// + public readonly int X = x; + + /// + /// The Y coordinate of the . + /// + public readonly int Y = y; + + /// + /// The magnitude (length) of the . + /// + public float Magnitude => Length(this); + + /// + /// The squared magnitude (length) of the . + /// + public float MagnitudeSquared => LengthSquared(this); + + /// + /// Gets a with the direction reversed. + /// + public readonly Vector2DInt Reversed => -this; + + /// + /// Represents the unit pointing upwards. + /// + public readonly static Vector2DInt Up = new(0, 1); + + /// + /// Represents the unit pointing downwards. + /// + public readonly static Vector2DInt Down = new(0, -1); + + /// + /// Represents the unit pointing leftwards. + /// + public readonly static Vector2DInt Left = new(-1, 0); + + /// + /// Represents the unit pointing rightwards. + /// + public readonly static Vector2DInt Right = new(1, 0); + + /// + /// Represents the zero . + /// + public readonly static Vector2DInt Zero = new(0, 0); + + /// + /// Represents the with both components equal to 1. + /// + public readonly static Vector2DInt One = new(1, 1); + + public static Vector2DInt operator -(Vector2DInt vector) => new(0 - vector.X, 0 - vector.Y); + public static Vector2DInt operator +(Vector2DInt left, Vector2DInt right) => new(left.X + right.X, left.Y + right.Y); + public static Vector2DInt operator -(Vector2DInt left, Vector2DInt right) => new(left.X - right.X, left.Y - right.Y); + public static Vector2DInt operator *(Vector2DInt vector, int value) => new(vector.X * value, vector.Y * value); + public static Vector2DInt operator *(int value, Vector2DInt vector) => new(vector.X * value, vector.Y * value); + public static Vector2DInt operator /(Vector2DInt vector, int value) => new(vector.X / value, vector.Y / value); + public static bool operator ==(Vector2DInt left, Vector2DInt right) => left.X == right.X && left.Y == right.Y; + public static bool operator !=(Vector2DInt left, Vector2DInt right) => left.X != right.X || left.Y != right.Y; + + public static implicit operator Vector2DInt(Vector3DInt vector) => new(vector.X, vector.Y); + + /// + /// Calculates the length of the . + /// + /// The . + /// The length of the . + public static float Length(Vector2DInt vector) => Engine.Core.Math.Sqrt(LengthSquared(vector)); + + /// + /// Calculates the squared length of the . + /// + /// The . + /// The squared length of the . + public static float LengthSquared(Vector2DInt vector) => vector.X * vector.X + vector.Y * vector.Y; + + /// + /// Calculates the distance between two s. + /// + /// The start . + /// The end . + /// The distance between the two s. + public static float Distance(Vector2DInt from, Vector2DInt to) => Length(FromTo(from, to)); + + /// + /// Inverts the direction of the . + /// + /// The . + /// The inverted . + public static Vector2DInt Invert(Vector2DInt vector) => -vector; + + /// + /// Adds two s. + /// + /// The first . + /// The second . + /// The sum of the two s. + public static Vector2DInt Add(Vector2DInt left, Vector2DInt right) => left + right; + + /// + /// Subtracts one from another. + /// + /// The to subtract from. + /// The to subtract. + /// The result of subtracting the second from the first. + public static Vector2DInt Subtract(Vector2DInt left, Vector2DInt right) => left - right; + + /// + /// Multiplies a by a scalar value. + /// + /// The . + /// The scalar value. + /// The result of multiplying the by the scalar value. + public static Vector2DInt Multiply(Vector2DInt vector, int value) => vector * value; + + /// + /// Divides a by a scalar value. + /// + /// The . + /// The scalar value. + /// The result of dividing the by the scalar value. + public static Vector2DInt Divide(Vector2DInt vector, int value) => vector / value; + + /// + /// Calculates the absolute value of each component of the vector. + /// + /// The . + /// The with each component's absolute value. + public static Vector2DInt Abs(Vector2DInt vector) => new(Engine.Core.Math.Abs(vector.X), Engine.Core.Math.Abs(vector.Y)); + + /// + /// Calculates the from one point to another. + /// + /// The starting point. + /// The ending point. + /// The from the starting point to the ending point. + public static Vector2DInt FromTo(Vector2DInt from, Vector2DInt to) => to - from; + + /// + /// Scales a by another component-wise. + /// + /// The to scale. + /// The containing the scaling factors for each component. + /// The scaled . + public static Vector2DInt Scale(Vector2DInt vector, Vector2DInt scale) => new(vector.X * scale.X, vector.Y * scale.Y); + + /// + /// Calculates a perpendicular to the given . + /// + /// The input . + /// A perpendicular to the input . + public static Vector2DInt Perpendicular(Vector2DInt vector) => new(-vector.Y, vector.X); + + /// + /// Returns the component-wise minimum of two s. + /// + /// The first . + /// The second . + /// The containing the minimum components from both input s. + public static Vector2DInt Min(Vector2DInt left, Vector2DInt right) => new((left.X < right.X) ? left.X : right.X, (left.Y < right.Y) ? left.Y : right.Y); + + /// + /// Returns the component-wise maximum of two s. + /// + /// The first . + /// The second . + /// The containing the maximum components from both input s. + public static Vector2DInt Max(Vector2DInt left, Vector2DInt right) => new((left.X > right.X) ? left.X : right.X, (left.Y > right.Y) ? left.Y : right.Y); + + /// + /// Clamps each component of a between the corresponding component of two other s. + /// + /// The to clamp. + /// The representing the minimum values for each component. + /// The representing the maximum values for each component. + /// A with each component clamped between the corresponding components of the min and max s. + public static Vector2DInt Clamp(Vector2DInt vector, Vector2DInt min, Vector2DInt max) => new(Engine.Core.Math.Clamp(vector.X, min.X, max.X), Engine.Core.Math.Clamp(vector.Y, min.Y, max.Y)); + + /// + /// Performs linear interpolation between two s. + /// + /// The starting (t = 0). + /// The ending (t = 1). + /// The interpolation parameter. + /// The interpolated . + public static Vector2DInt Lerp(Vector2DInt from, Vector2DInt to, int t) => from + FromTo(from, to) * t; + + /// + /// Calculates the cross product of two s. + /// + /// The first . + /// The second . + /// The cross product of the two s. + public static int Cross(Vector2DInt left, Vector2DInt right) => left.X * right.Y - left.Y * right.X; + + /// + /// Calculates the dot product of two s. + /// + /// The first . + /// The second . + /// The dot product of the two s. + public static int Dot(Vector2DInt left, Vector2DInt right) => left.X * right.X + left.Y * right.Y; + + /// + /// Determines whether the specified object is equal to the current . + /// + /// The object to compare with the current . + /// if the specified object is equal to the current ; otherwise, . + public override bool Equals(object? obj) => obj is Vector2DInt vector2DInt && this == vector2DInt; + public bool Equals(Vector2DInt other) => this == other; + + /// + /// Generates a hash code for the . + /// + /// A hash code for the . + public override int GetHashCode() => System.HashCode.Combine(X, Y); + + /// + /// Converts the to its string representation. + /// + /// A string representation of the . + public override string ToString() => $"{nameof(Vector2DInt)}({X}, {Y})"; +} + +/// +/// Provides extension methods for type. +/// +public static class Vector2DIntExtensions +{ + /// + public static float Length(this Vector2DInt vector) => Vector2DInt.Length(vector); + + /// + public static float Distance(this Vector2DInt from, Vector2DInt to) => Vector2DInt.Distance(from, to); + + /// + public static Vector2DInt Add(this Vector2DInt vector, Vector2DInt vectorToAdd) => Vector2DInt.Add(vector, vectorToAdd); + + /// + public static Vector2DInt Subtract(this Vector2DInt vector, Vector2DInt vectorToSubtract) => Vector2DInt.Subtract(vector, vectorToSubtract); + + /// + public static Vector2DInt Multiply(this Vector2DInt vector, int value) => Vector2DInt.Multiply(vector, value); + + /// + public static Vector2DInt Divide(this Vector2DInt vector, int value) => Vector2DInt.Divide(vector, value); + + /// + public static Vector2DInt Abs(this Vector2DInt vector) => Vector2DInt.Abs(vector); + + /// + public static Vector2DInt FromTo(this Vector2DInt from, Vector2DInt to) => Vector2DInt.FromTo(from, to); + + /// + public static Vector2DInt Scale(this Vector2DInt vector, Vector2DInt scale) => Vector2DInt.Scale(vector, scale); + + /// + public static Vector2DInt Perpendicular(this Vector2DInt vector) => Vector2DInt.Perpendicular(vector); + + /// + public static Vector2DInt Min(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Min(left, right); + + /// + public static Vector2DInt Max(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Max(left, right); + + /// + public static Vector2DInt Clamp(this Vector2DInt vector, Vector2DInt min, Vector2DInt max) => Vector2DInt.Clamp(vector, min, max); + + /// + public static Vector2DInt Lerp(this Vector2DInt from, Vector2DInt to, int t) => Vector2DInt.Lerp(from, to, t); + + /// + public static int Cross(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Cross(left, right); + + /// + public static float AngleBetween(this Vector2D left, Vector2D right) => Vector2D.Angle(left, right); + + /// + public static int Dot(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Dot(left, right); +} diff --git a/Engine.Core/Primitives/Vector3DInt.cs b/Engine.Core/Primitives/Vector3DInt.cs new file mode 100644 index 0000000..1dbe037 --- /dev/null +++ b/Engine.Core/Primitives/Vector3DInt.cs @@ -0,0 +1,313 @@ +using System; + +namespace Engine.Core; + +/// +/// Represents a three-dimensional integer vector. +/// +/// X position of the . +/// Y position of the . +/// Z position of the . +/// +/// Initializes a new instance of the struct with the specified positions. +/// +[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")] +public readonly struct Vector3DInt(int x, int y, int z) : IEquatable +{ + /// + /// The X coordinate of the . + /// + public readonly int X = x; + + /// + /// The Y coordinate of the . + /// + public readonly int Y = y; + + /// + /// The Z coordinate of the . + /// + public readonly int Z = z; + + /// + /// The magnitude (length) of the . + /// + public float Magnitude => Length(this); + + /// + /// The squared magnitude (length) of the . + /// + public float MagnitudeSquared => LengthSquared(this); + + /// + /// Represents the unit pointing upwards. + /// + public readonly static Vector3DInt Up = new(0, 1, 0); + + /// + /// Represents the unit pointing downwards. + /// + public readonly static Vector3DInt Down = new(0, -1, 0); + + /// + /// Represents the unit pointing leftwards. + /// + public readonly static Vector3DInt Left = new(-1, 0, 0); + + /// + /// Represents the unit pointing rightwards. + /// + public readonly static Vector3DInt Right = new(1, 0, 0); + + /// + /// Represents the unit pointing forwards. + /// + public readonly static Vector3DInt Forward = new(0, 0, 1); + + /// + /// Represents the unit pointing backwards. + public readonly static Vector3DInt Backward = new(0, 0, -1); + + /// + /// Represents the zero . + /// + public readonly static Vector3DInt Zero = new(0, 0, 0); + + /// + /// Represents the with both components equal to 1. + /// + public readonly static Vector3DInt One = new(1, 1, 1); + + public static Vector3DInt operator -(Vector3DInt vector) => new(0 - vector.X, 0 - vector.Y, 0 - vector.Z); + public static Vector3DInt operator +(Vector3DInt left, Vector3DInt right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z); + public static Vector3DInt operator -(Vector3DInt left, Vector3DInt right) => new(left.X - right.X, left.Y - right.Y, left.Z - right.Z); + public static Vector3DInt operator *(Vector3DInt vector, int value) => new(vector.X * value, vector.Y * value, vector.Z * value); + public static Vector3DInt operator *(int value, Vector3DInt vector) => new(vector.X * value, vector.Y * value, vector.Z * value); + public static Vector3DInt operator /(Vector3DInt vector, int value) => new(vector.X / value, vector.Y / value, vector.Z / value); + public static bool operator ==(Vector3DInt left, Vector3DInt right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z; + public static bool operator !=(Vector3DInt left, Vector3DInt right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z; + + public static implicit operator Vector3DInt(Vector2DInt vector) => new(vector.X, vector.Y, 0); + + /// + /// Calculates the length of the . + /// + /// The . + /// The length of the . + public static float Length(Vector3DInt vector) => Math.Sqrt(LengthSquared(vector)); + + /// + /// Calculates the squared length of the . + /// + /// The . + /// The squared length of the . + public static float LengthSquared(Vector3DInt vector) => vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z; + + /// + /// Calculates the distance between two s. + /// + /// The start . + /// The end . + /// The distance between the two s. + public static float Distance(Vector3DInt from, Vector3DInt to) => Length(FromTo(from, to)); + + /// + /// Inverts the direction of the . + /// + /// The . + /// The inverted . + public static Vector3DInt Invert(Vector3DInt vector) => -vector; + + /// + /// Adds two s. + /// + /// The first . + /// The second . + /// The sum of the two s. + public static Vector3DInt Add(Vector3DInt left, Vector3DInt right) => left + right; + + /// + /// Subtracts one from another. + /// + /// The to subtract from. + /// The to subtract. + /// The result of subtracting the second from the first. + public static Vector3DInt Subtract(Vector3DInt left, Vector3DInt right) => left - right; + + /// + /// Multiplies a by a scalar value. + /// + /// The . + /// The scalar value. + /// The result of multiplying the by the scalar value. + public static Vector3DInt Multiply(Vector3DInt vector, int value) => vector * value; + + /// + /// Divides a by a scalar value. + /// + /// The . + /// The scalar value. + /// The result of dividing the by the scalar value. + public static Vector3DInt Divide(Vector3DInt vector, int value) => vector / value; + + /// + /// Calculates the absolute value of each component of the vector. + /// + /// The . + /// The with each component's absolute value. + public static Vector3DInt Abs(Vector3DInt vector) => new(Math.Abs(vector.X), Math.Abs(vector.Y), Math.Abs(vector.Z)); + + /// + /// Calculates the from one point to another. + /// + /// The starting point. + /// The ending point. + /// The from the starting point to the ending point. + public static Vector3DInt FromTo(Vector3DInt from, Vector3DInt to) => to - from; + + /// + /// Scales a by another component-wise. + /// + /// The to scale. + /// The containing the scaling factors for each component. + /// The scaled . + public static Vector3DInt Scale(Vector3DInt vector, Vector3DInt scale) => new(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z); + + /// + /// Returns the component-wise minimum of two s. + /// + /// The first . + /// The second . + /// The containing the minimum components from both input s. + public static Vector3DInt Min(Vector3DInt left, Vector3DInt right) => new((left.X < right.X) ? left.X : right.X, (left.Y < right.Y) ? left.Y : right.Y, (left.Z < right.Z) ? left.Z : right.Z); + + /// + /// Returns the component-wise maximum of two s. + /// + /// The first . + /// The second . + /// The containing the maximum components from both input s. + public static Vector3DInt Max(Vector3DInt left, Vector3DInt right) => new((left.X > right.X) ? left.X : right.X, (left.Y > right.Y) ? left.Y : right.Y, (left.Z > right.Z) ? left.Z : right.Z); + + /// + /// Clamps each component of a between the corresponding component of two other s. + /// + /// The to clamp. + /// The representing the minimum values for each component. + /// The representing the maximum values for each component. + /// A with each component clamped between the corresponding components of the min and max s. + public static Vector3DInt Clamp(Vector3DInt vector, Vector3DInt min, Vector3DInt max) => new(Math.Clamp(vector.X, min.X, max.X), Math.Clamp(vector.Y, min.Y, max.Y), Math.Clamp(vector.Z, min.Z, max.Z)); + + /// + /// Performs linear interpolation between two s. + /// + /// The starting (t = 0). + /// The ending (t = 1). + /// The interpolation parameter. + /// The interpolated . + public static Vector3DInt Lerp(Vector3DInt from, Vector3DInt to, int t) => from + FromTo(from, to) * t; + + /// + /// Calculates the cross product of two s. + /// + /// The first . + /// The second . + /// The cross product of the two s. + public static Vector3DInt Cross(Vector3DInt left, Vector3DInt right) => new(left.Y * right.Z - left.Z * right.Y, left.Z * right.X - left.X * right.Z, left.X * right.Y - left.Y * right.X); + + /// + /// Calculates the angle between two s. + /// + /// The first . + /// The second . + /// The angle between the two s in radians. + public static float Angle(Vector3DInt left, Vector3DInt right) => Math.Acos(Dot(left, right) / (Length(left) * Length(right))); + + /// + /// Calculates the dot product of two s. + /// + /// The first . + /// The second . + /// The dot product of the two s. + public static int Dot(Vector3DInt left, Vector3DInt right) => left.X * right.X + left.Y * right.Y + left.Z * right.Z; + + /// + /// Determines whether the specified object is equal to the current . + /// + /// The object to compare with the current . + /// if the specified object is equal to the current ; otherwise, . + public override bool Equals(object? obj) => obj is Vector3DInt vector3D && this == vector3D; + public bool Equals(Vector3DInt other) => this == other; + + /// + /// Generates a hash code for the . + /// + /// A hash code for the . + public override int GetHashCode() => System.HashCode.Combine(X, Y, Z); + + /// + /// Converts the to its string representation. + /// + /// A string representation of the . + public override string ToString() => $"{nameof(Vector3DInt)}({X}, {Y}, {Z})"; +} + +/// +/// Provides extension methods for type. +/// +public static class Vector3DIntExtensions +{ + /// + public static float Length(this Vector3DInt vector) => Vector3DInt.Length(vector); + + /// + public static float LengthSquared(this Vector3DInt vector) => Vector3DInt.LengthSquared(vector); + + /// + public static float Distance(this Vector3DInt from, Vector3DInt to) => Vector3DInt.Distance(from, to); + + /// + public static Vector3DInt Invert(this Vector3DInt vector) => Vector3DInt.Invert(vector); + + /// + public static Vector3DInt Add(this Vector3DInt vector, Vector3DInt vectorToAdd) => Vector3DInt.Add(vector, vectorToAdd); + + /// + public static Vector3DInt Subtract(this Vector3DInt vector, Vector3DInt vectorToSubtract) => Vector3DInt.Subtract(vector, vectorToSubtract); + + /// + public static Vector3DInt Multiply(this Vector3DInt vector, int value) => Vector3DInt.Multiply(vector, value); + + /// + public static Vector3DInt Divide(this Vector3DInt vector, int value) => Vector3DInt.Divide(vector, value); + + /// + public static Vector3DInt Abs(this Vector3DInt vector) => Vector3DInt.Abs(vector); + + /// + public static Vector3DInt FromTo(this Vector3DInt from, Vector3DInt to) => Vector3DInt.FromTo(from, to); + + /// + public static Vector3DInt Scale(this Vector3DInt vector, Vector3DInt scale) => Vector3DInt.Scale(vector, scale); + + /// + public static Vector3DInt Min(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Min(left, right); + + /// + public static Vector3DInt Max(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Max(left, right); + + /// + public static Vector3DInt Clamp(this Vector3DInt vector, Vector3DInt min, Vector3DInt max) => Vector3DInt.Clamp(vector, min, max); + + /// + public static Vector3DInt Lerp(this Vector3DInt from, Vector3DInt to, int t) => Vector3DInt.Lerp(from, to, t); + + /// + public static Vector3DInt Cross(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Cross(left, right); + + /// + public static float AngleBetween(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Angle(left, right); + + /// + public static int Dot(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Dot(left, right); +}