319 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
 | 
						|
using System;
 | 
						|
 | 
						|
namespace Engine.Core;
 | 
						|
 | 
						|
/// <summary>
 | 
						|
/// Represents a four-dimensional vector.
 | 
						|
/// </summary>
 | 
						|
/// <param name="x">X position of the <see cref="Vector4D"/>.</param>
 | 
						|
/// <param name="y">Y position of the <see cref="Vector4D"/>.</param>
 | 
						|
/// <param name="z">Z position of the <see cref="Vector4D"/>.</param>
 | 
						|
/// <param name="w">W position of the <see cref="Vector4D"/>.</param>
 | 
						|
/// <remarks>
 | 
						|
/// Initializes a new instance of the <see cref="Vector4D"/> struct with the specified positions.
 | 
						|
/// </remarks>
 | 
						|
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized.ToString(),nq}")]
 | 
						|
public readonly struct Vector4D(float x, float y, float z, float w) : IEquatable<Vector4D>
 | 
						|
{
 | 
						|
    /// <summary>
 | 
						|
    /// The X coordinate of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly float X = x;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The Y coordinate of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly float Y = y;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The Z coordinate of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly float Z = z;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The W coordinate of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly float W = w;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The magnitude (length) of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public float Magnitude => Length(this);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The squared magnitude (length) of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public float MagnitudeSquared => LengthSquared(this);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The normalized form of the <see cref="Vector4D"/> (a <see cref="Vector4D"/> with the same direction and a magnitude of 1).
 | 
						|
    /// </summary>
 | 
						|
    public Vector4D Normalized => Normalize(this);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Represents the zero <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly static Vector4D Zero = new(0f, 0f, 0f, 0f);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Represents the one <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly static Vector4D One = new(1f, 1f, 1f, 1f);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Represents the unit X <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly static Vector4D UnitX = new(1f, 0f, 0f, 0f);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Represents the unit Y <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly static Vector4D UnitY = new(0f, 1f, 0f, 0f);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Represents the unit Z <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly static Vector4D UnitZ = new(0f, 0f, 1f, 0f);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Represents the unit W <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    public readonly static Vector4D UnitW = new(0f, 0f, 0f, 1f);
 | 
						|
 | 
						|
    public static Vector4D operator -(Vector4D vector) => new(0f - vector.X, 0f - vector.Y, 0f - vector.Z, 0f - vector.W);
 | 
						|
    public static Vector4D operator +(Vector4D left, Vector4D right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
 | 
						|
    public static Vector4D operator -(Vector4D left, Vector4D right) => new(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
 | 
						|
    public static Vector4D operator *(Vector4D vector, float value) => new(vector.X * value, vector.Y * value, vector.Z * value, vector.W * value);
 | 
						|
    public static Vector4D operator *(float value, Vector4D vector) => new(vector.X * value, vector.Y * value, vector.Z * value, vector.W * value);
 | 
						|
    public static Vector4D operator /(Vector4D vector, float value) => new(vector.X / value, vector.Y / value, vector.Z / value, vector.W / value);
 | 
						|
    public static bool operator ==(Vector4D left, Vector4D right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z && left.W == right.W;
 | 
						|
    public static bool operator !=(Vector4D left, Vector4D right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z || left.W != right.W;
 | 
						|
 | 
						|
    public static implicit operator System.Numerics.Vector4(Vector4D vector) => new(vector.X, vector.Y, vector.Z, vector.W);
 | 
						|
    public static implicit operator Vector4D(System.Numerics.Vector4 vector) => new(vector.X, vector.Y, vector.Z, vector.W);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Calculates the length of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The length of the <see cref="Vector4D"/>.</returns>
 | 
						|
    public static float Length(Vector4D vector) => Math.Sqrt(LengthSquared(vector));
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Calculates the squared length of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The squared length of the <see cref="Vector4D"/>.</returns>
 | 
						|
    public static float LengthSquared(Vector4D vector) => vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z + vector.W * vector.W;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Calculates the distance between two <see cref="Vector4D"/>s.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="from">The start <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="to">The end <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The distance between the two <see cref="Vector4D"/>s.</returns>
 | 
						|
    public static float Distance(Vector4D from, Vector4D to) => Length(FromTo(from, to));
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Inverts the direction of the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The inverted <see cref="Vector4D"/>.</returns>
 | 
						|
    public static Vector4D Invert(Vector4D vector) => -vector;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Adds two <see cref="Vector4D"/>s.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The sum of the two <see cref="Vector4D"/>s.</returns>
 | 
						|
    public static Vector4D Add(Vector4D left, Vector4D right) => left + right;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Subtracts one <see cref="Vector4D"/> from another.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The <see cref="Vector4D"/> to subtract from.</param>
 | 
						|
    /// <param name="right">The <see cref="Vector4D"/> to subtract.</param>
 | 
						|
    /// <returns>The result of subtracting the second <see cref="Vector4D"/> from the first.</returns>
 | 
						|
    public static Vector4D Subtract(Vector4D left, Vector4D right) => left - right;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Multiplies a <see cref="Vector4D"/> by a scalar value.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="value">The scalar value.</param>
 | 
						|
    /// <returns>The result of multiplying the <see cref="Vector4D"/> by the scalar value.</returns>
 | 
						|
    public static Vector4D Multiply(Vector4D vector, float value) => vector * value;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Divides a <see cref="Vector4D"/> by a scalar value.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="value">The scalar value.</param>
 | 
						|
    /// <returns>The result of dividing the <see cref="Vector4D"/> by the scalar value.</returns>
 | 
						|
    public static Vector4D Divide(Vector4D vector, float value) => vector / value;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Calculates the absolute value of each component of the vector.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The <see cref="Vector4D"/> with each component's absolute value.</returns>
 | 
						|
    public static Vector4D Abs(Vector4D vector) => new(Math.Abs(vector.X), Math.Abs(vector.Y), Math.Abs(vector.Z), Math.Abs(vector.W));
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Normalizes the <see cref="Vector4D"/> (creates a unit <see cref="Vector4D"/> with the same direction).
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/> to normalize.</param>
 | 
						|
    /// <returns>The normalized <see cref="Vector4D"/>.</returns>
 | 
						|
    public static Vector4D Normalize(Vector4D vector) => vector / Length(vector);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Calculates the <see cref="Vector4D"/> from one point to another.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="from">The starting point.</param>
 | 
						|
    /// <param name="to">The ending point.</param>
 | 
						|
    /// <returns>The <see cref="Vector4D"/> from the starting point to the ending point.</returns>
 | 
						|
    public static Vector4D FromTo(Vector4D from, Vector4D to) => to - from;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Scales a <see cref="Vector4D"/> by another <see cref="Vector4D"/> component-wise.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/> to scale.</param>
 | 
						|
    /// <param name="scale">The <see cref="Vector4D"/> containing the scaling factors for each component.</param>
 | 
						|
    /// <returns>The scaled <see cref="Vector4D"/>.</returns>
 | 
						|
    public static Vector4D Scale(Vector4D vector, Vector4D scale) => new(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z, vector.W * scale.W);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the component-wise minimum of two <see cref="Vector4D"/>s.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The <see cref="Vector4D"/> containing the minimum components from both input <see cref="Vector4D"/>s.</returns>
 | 
						|
    public static Vector4D Min(Vector4D left, Vector4D 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, (left.W < right.W) ? left.W : right.W);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the component-wise maximum of two <see cref="Vector4D"/>s.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The <see cref="Vector4D"/> containing the maximum components from both input <see cref="Vector4D"/>s.</returns>
 | 
						|
    public static Vector4D Max(Vector4D left, Vector4D 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, (left.W > right.W) ? left.W : right.W);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Clamps each component of a <see cref="Vector4D"/> between the corresponding component of two other <see cref="Vector4D"/>s.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="vector">The <see cref="Vector4D"/> to clamp.</param>
 | 
						|
    /// <param name="min">The <see cref="Vector4D"/> representing the minimum values for each component.</param>
 | 
						|
    /// <param name="max">The <see cref="Vector4D"/> representing the maximum values for each component.</param>
 | 
						|
    /// <returns>A <see cref="Vector4D"/> with each component clamped between the corresponding components of the min and max <see cref="Vector4D"/>s.</returns>
 | 
						|
    public static Vector4D Clamp(Vector4D vector, Vector4D min, Vector4D 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), Math.Clamp(vector.W, min.W, max.W));
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Performs linear interpolation between two <see cref="Vector4D"/>s.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="from">The starting <see cref="Vector4D"/> (t = 0).</param>
 | 
						|
    /// <param name="to">The ending <see cref="Vector4D"/> (t = 1).</param>
 | 
						|
    /// <param name="t">The interpolation parameter.</param>
 | 
						|
    /// <returns>The interpolated <see cref="Vector4D"/>.</returns>
 | 
						|
    public static Vector4D Lerp(Vector4D from, Vector4D to, float t) => from + FromTo(from, to) * t;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Calculates the dot product of two <see cref="Vector4D"/>s.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns>The dot product of the two <see cref="Vector4D"/>s.</returns>
 | 
						|
    public static float Dot(Vector4D left, Vector4D right) => left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Checks if two <see cref="Vector4D"/>s are approximately equal within a specified epsilon range.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
						|
    /// <param name="epsilon">The epsilon range.</param>
 | 
						|
    /// <returns><see cref="true"/> if the <see cref="Vector4D"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
 | 
						|
    public static bool ApproximatelyEquals(Vector4D left, Vector4D right, float epsilon = float.Epsilon)
 | 
						|
        => left.X.ApproximatelyEquals(right.X, epsilon) && left.Y.ApproximatelyEquals(right.Y, epsilon) && left.Z.ApproximatelyEquals(right.Z, epsilon) && left.Z.ApproximatelyEquals(right.W, epsilon);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Determines whether the specified object is equal to the current <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="obj">The object to compare with the current <see cref="Vector4D"/>.</param>
 | 
						|
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Vector4D"/>; otherwise, <see cref="false"/>.</returns>
 | 
						|
    public override bool Equals(object? obj) => obj is Vector4D vector4D && this == vector4D;
 | 
						|
    public bool Equals(Vector4D other) => this == other;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Generates a hash code for the <see cref="Vector4D"/>.
 | 
						|
    /// </summary>
 | 
						|
    /// <returns>A hash code for the <see cref="Vector4D"/>.</returns>
 | 
						|
    public override int GetHashCode() => System.HashCode.Combine(X, Y, Z, W);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Converts the <see cref="Vector4D"/> to its string representation.
 | 
						|
    /// </summary>
 | 
						|
    /// <returns>A string representation of the <see cref="Vector4D"/>.</returns>
 | 
						|
    public override string ToString() => $"{nameof(Vector4D)}({X}, {Y}, {Z}, {W})";
 | 
						|
}
 | 
						|
 | 
						|
/// <summary>
 | 
						|
/// Provides extension methods for <see cref="Vector4D"/> type.
 | 
						|
/// </summary>
 | 
						|
public static class Vector4DExtensions
 | 
						|
{
 | 
						|
    /// <inheritdoc cref="Vector4D.Length(Vector4D)" />
 | 
						|
    public static float Length(this Vector4D vector) => Vector4D.Length(vector);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.LengthSquared(Vector4D)" />
 | 
						|
    public static float LengthSquared(this Vector4D vector) => Vector4D.LengthSquared(vector);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Distance(Vector4D, Vector4D)" />
 | 
						|
    public static float Distance(this Vector4D from, Vector4D to) => Vector4D.Distance(from, to);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Invert(Vector4D)" />
 | 
						|
    public static Vector4D Invert(this Vector4D vector) => Vector4D.Invert(vector);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Add(Vector4D, Vector4D)" />
 | 
						|
    public static Vector4D Add(this Vector4D vector, Vector4D vectorToAdd) => Vector4D.Add(vector, vectorToAdd);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Subtract(Vector4D, Vector4D)" />
 | 
						|
    public static Vector4D Subtract(this Vector4D vector, Vector4D vectorToSubtract) => Vector4D.Subtract(vector, vectorToSubtract);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Multiply(Vector4D, float)" />
 | 
						|
    public static Vector4D Multiply(this Vector4D vector, float value) => Vector4D.Multiply(vector, value);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Divide(Vector4D, float)" />
 | 
						|
    public static Vector4D Divide(this Vector4D vector, float value) => Vector4D.Divide(vector, value);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Abs(Vector4D)" />
 | 
						|
    public static Vector4D Abs(this Vector4D vector) => Vector4D.Abs(vector);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Normalize(Vector4D)" />
 | 
						|
    public static Vector4D Normalize(this Vector4D vector) => Vector4D.Normalize(vector);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.FromTo(Vector4D, Vector4D)" />
 | 
						|
    public static Vector4D FromTo(this Vector4D from, Vector4D to) => Vector4D.FromTo(from, to);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Scale(Vector4D, Vector4D)" />
 | 
						|
    public static Vector4D Scale(this Vector4D vector, Vector4D scale) => Vector4D.Scale(vector, scale);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Min(Vector4D, Vector4D)" />
 | 
						|
    public static Vector4D Min(this Vector4D left, Vector4D right) => Vector4D.Min(left, right);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Max(Vector4D, Vector4D)" />
 | 
						|
    public static Vector4D Max(this Vector4D left, Vector4D right) => Vector4D.Max(left, right);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Clamp(Vector4D, Vector4D, Vector4D)" />
 | 
						|
    public static Vector4D Clamp(this Vector4D vector, Vector4D min, Vector4D max) => Vector4D.Clamp(vector, min, max);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Lerp(Vector4D, Vector4D, float)" />
 | 
						|
    public static Vector4D Lerp(this Vector4D from, Vector4D to, float t) => Vector4D.Lerp(from, to, t);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.Dot(Vector4D, Vector4D)" />
 | 
						|
    public static float Dot(this Vector4D left, Vector4D right) => Vector4D.Dot(left, right);
 | 
						|
 | 
						|
    /// <inheritdoc cref="Vector4D.ApproximatelyEquals(Vector4D, Vector4D, float)" />
 | 
						|
    public static bool ApproximatelyEquals(this Vector4D left, Vector4D right, float epsilon = float.Epsilon) => Vector4D.ApproximatelyEquals(left, right, epsilon);
 | 
						|
}
 |