tengri/Content/UE/MathLibrary.ts

315 lines
8.8 KiB
TypeScript

// UE/SystemLibrary.ts
import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts';
import type { Color } from '#root/UE/Color.ts';
import type { Float } from '#root/UE/Float.ts';
import type { Integer } from '#root/UE/Integer.ts';
import { LinearColor } from '#root/UE/LinearColor.ts';
import { Vector } from '#root/UE/Vector.ts';
/**
* System Library: Core Mathematical Functions
* Wrapper for JavaScript Math functions with UE5 compatibility
* Provides deterministic mathematical operations for movement calculations
*/
class MathLibraryClass extends BlueprintFunctionLibrary {
constructor(
outer: null | BlueprintFunctionLibrary = null,
name: string = 'MathLibrary'
) {
super(outer, name);
}
// ════════════════════════════════════════════════════════════════════════════════════════
// FUNCTIONS
// ════════════════════════════════════════════════════════════════════════════════════════
/**
* Convert degrees to radians
* @param Degrees - Angle in degrees
* @returns Angle in radians
* @example
* // Convert 90 degrees to radians
* DegreesToRadians(90) // returns π/2
*/
public DegreesToRadians(Degrees: Float): Float {
return (Degrees * Math.PI) / 180;
}
/**
* Convert radians to degrees
* @param Radians - Angle in radians
* @returns Angle in degrees
* @example
* // Convert π/2 radians to degrees
* RadiansToDegrees(Math.PI / 2) // returns 90
*/
public RadiansToDegrees(Radians: Float): Float {
return (Radians * 180) / Math.PI;
}
/**
* Calculate sine of angle in radians
* @param Value - Angle in radians
* @returns Sine value (-1 to 1)
*/
public Sin(Value: Float): Float {
return Math.sin(Value);
}
/**
* Calculate cosine of angle in radians
* @param Value - Angle in radians
* @returns Cosine value (-1 to 1)
*/
public Cos(Value: Float): Float {
return Math.cos(Value);
}
/**
* Calculate arccosine (inverse cosine) of value
* @param Value - Input value (-1 to 1)
* @returns Angle in radians (0 to π)
*/
public Acos(Value: Float): Float {
return Math.acos(Value);
}
/**
* Calculate arctangent2 of Y and X
* @param Y - Y coordinate
* @param X - X coordinate
* @returns Angle in radians (-π to π)
*/
public Atan2(Y: Float, X: Float): Float {
return Math.atan2(Y, X);
}
/**
* Calculate dot product of two vectors
* @param Vector1 - First vector
* @param Vector2 - Second vector
* @returns Dot product scalar value
* @example
* // Dot product of perpendicular vectors
* Dot(new Vector(1,0,0), new Vector(0,1,0)) // returns 0
*/
public Dot(Vector1: Vector, Vector2: Vector): Float {
return (
Vector1.X * Vector2.X + Vector1.Y * Vector2.Y + Vector1.Z * Vector2.Z
);
}
/**
* Color to LinearColor conversion
* @param color - Color with 0-255 RGBA components
* @returns LinearColor with 0-1 RGBA components
* @example
* // Convert Color(255,0,0,255) to LinearColor
* ColorToLinearColor(new Color(255,0,0,255)) // returns LinearColor(1,0,0,1)
*/
public ColorToLinearColor(color: Color): LinearColor {
return new LinearColor(
color.R / 255,
color.G / 255,
color.B / 255,
color.A / 255
);
}
/**
* Clamp a float value between a minimum and maximum
* @param Value - Value to clamp
* @param Min - Minimum limit
* @param Max - Maximum limit
* @returns Clamped value
* @example
* // Clamp 10 between 0 and 5
* Clamp(10, 0, 5) // returns 5
*/
public ClampFloat(Value: Float, Min: Float, Max: Float): Float {
return Math.min(Math.max(Value, Min), Max);
}
/**
* Calculate vector length (magnitude)
* @param Vector - Input vector
* @returns Length (magnitude) of vector
* @example
* // Length of vector (3,4,0)
* VectorLength(new Vector(3,4,0)) // returns 5
*/
public VectorLength(Vector: Vector): Float {
return Math.sqrt(
Vector.X * Vector.X + Vector.Y * Vector.Y + Vector.Z * Vector.Z
);
}
/**
* Interpolate a float value towards a target
* @param Current - Current value
* @param Target - Target value
* @param DeltaTime - Time since last update
* @param InterpSpeed - Speed of interpolation
* @returns New interpolated value
* @example
* // Interpolate 0 towards 10 over 1 second at speed 5
* FInterpTo(0, 10, 1, 5) // returns 5
*/
public FInterpTo(
Current: Float,
Target: Float,
DeltaTime: Float,
InterpSpeed: Float
): Float {
if (InterpSpeed <= 0) {
return Target;
}
const Dist = Target - Current;
if (Dist * Dist < 0.00001) {
return Target;
}
const DeltaMove = Dist * Math.min(DeltaTime * InterpSpeed, 1);
return Current + DeltaMove;
}
/**
* Absolute value of a float
* @param Value - Input value
* @returns Absolute value
* @example
* // Absolute value of -5
* abs(-5) // returns 5
*/
public abs(Value: Float): Float {
return Math.abs(Value);
}
/**
* Interpolate a vector towards a target vector
* @param Current - Current vector
* @param Target - Target vector
* @param DeltaTime - Time since last update
* @param InterpSpeed - Speed of interpolation
* @returns New interpolated vector
* @example
* // Interpolate (0,0,0) towards (10,10,10) over 1 second at speed 5
* VInterpTo(new Vector(0,0,0), new Vector(10,10,10), 1, 5) // returns Vector(5,5,5)
*/
public VInterpTo(
Current: Vector = new Vector(0, 0, 0),
Target: Vector = new Vector(0, 0, 0),
DeltaTime: Float = 0,
InterpSpeed: Float = 0
): Vector {
return new Vector(
this.FInterpTo(Current.X, Target.X, DeltaTime, InterpSpeed),
this.FInterpTo(Current.Y, Target.Y, DeltaTime, InterpSpeed),
this.FInterpTo(Current.Z, Target.Z, DeltaTime, InterpSpeed)
);
}
/**
* Normalize a vector to unit length
* @param A - Input vector
* @param Tolerance - Minimum length to avoid division by zero
* @returns Normalized vector (length 1) or zero vector if input is zero
* @example
* // Normalize vector (3,4,0)
* Normalize(new Vector(3,4,0)) // returns Vector(0.6,0.8,0)
*/
public Normal(
A: Vector = new Vector(0, 0, 0),
Tolerance: Float = 0.0001
): Vector {
const length = this.VectorLength(A);
if (length > Tolerance) {
return new Vector(A.X / length, A.Y / length, A.Z / length);
}
return new Vector(0, 0, 0);
}
/**
* Get the minimum of two float values
* @param A - First value
* @param B - Second value
* @returns Minimum value
* @example
* // Minimum of 3 and 5
* Min(3, 5) // returns 3
*/
public Min(A: Float, B: Float): Float {
return Math.min(A, B);
}
/**
* Get right vector from roll, pitch, yaw angles
* @param Roll - Rotation around forward axis in radians
* @param Pitch - Rotation around right axis in radians
* @param Yaw - Rotation around up axis in radians
* @returns Right direction vector
* @example
* // Right vector for no rotation
* GetRightVector(0, 0, 0) // returns Vector(1,0,0)
*/
public GetRightVector(
Roll: Float = 0,
Pitch: Float = 0,
Yaw: Float = 0
): Vector {
const CP = this.Cos(Pitch);
const SP = this.Sin(Pitch);
const CY = this.Cos(Yaw);
const SY = this.Sin(Yaw);
console.log(Roll);
return new Vector(CP * CY, CP * SY, SP);
}
/**
* Get forward vector from roll, pitch, yaw angles
* @param Roll - Rotation around forward axis in radians
* @param Pitch - Rotation around right axis in radians
* @param Yaw - Rotation around up axis in radians
* @returns Forward direction vector
* @example
* // Forward vector for no rotation
* GetForwardVector(0, 0, 0) // returns Vector(1,0,0)
*/
public GetForwardVector(
Roll: Float = 0,
Pitch: Float = 0,
Yaw: Float = 0
): Vector {
const CP = this.Cos(Pitch);
const SP = this.Sin(Pitch);
const CY = this.Cos(Yaw);
const SY = this.Sin(Yaw);
console.log(Roll);
return new Vector(CP * CY, CP * SY, SP);
}
/**
* Floor a float value to the nearest lower integer
* @param Value - Input float value
* @returns Floored integer value
* @example
* // Floor 3.7 to 3
* Floor(3.7) // returns 3
*/
public Ceil(Value: Float): Integer {
return Math.ceil(Value);
}
}
/**
* Global instance of math library
* Used throughout the movement system for mathematical calculations
*/
export const MathLibrary = new MathLibraryClass();