124 lines
4.5 KiB
TypeScript
124 lines
4.5 KiB
TypeScript
// Movement/Surface/BFL_SurfaceClassifier.ts
|
|
|
|
import { BFL_Vectors } from '#root/Math/Libraries/BFL_Vectors.ts';
|
|
import { E_SurfaceType } from '#root/Movement/Surface/E_SurfaceType.ts';
|
|
import type { S_AngleThresholds } from '#root/Movement/Surface/S_AngleThresholds.ts';
|
|
import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts';
|
|
import { Vector } from '#root/UE/Vector.ts';
|
|
|
|
class BFL_SurfaceClassifierClass extends BlueprintFunctionLibrary {
|
|
// ════════════════════════════════════════════════════════════════════════════════════════
|
|
// CLASSIFICATION
|
|
// ════════════════════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Classify surface type based on normal vector and angle thresholds
|
|
*
|
|
* @param SurfaceNormal - Normalized surface normal vector (from hit result)
|
|
* @param AngleThresholdsRads - Angle thresholds in radians (pre-converted for performance)
|
|
* @returns Surface type classification
|
|
*
|
|
* @example
|
|
* // Flat ground (normal pointing up)
|
|
* const flat = SurfaceClassifier.Classify(new Vector(0, 0, 1), thresholds);
|
|
* // Returns: E_SurfaceType.Walkable
|
|
*
|
|
* @example
|
|
* // Steep slope (50° angle)
|
|
* const steep = SurfaceClassifier.Classify(BFL_Vectors.GetNormalFromAngle(50), thresholds);
|
|
* // Returns: E_SurfaceType.SteepSlope
|
|
*
|
|
* @pure true
|
|
* @category Classification
|
|
*/
|
|
public Classify(
|
|
SurfaceNormal: Vector,
|
|
AngleThresholdsRads: S_AngleThresholds
|
|
): E_SurfaceType {
|
|
// Calculate angle between surface normal and up vector
|
|
const surfaceAngle = BFL_Vectors.GetSurfaceAngle(SurfaceNormal);
|
|
|
|
// Classify based on angle thresholds
|
|
if (surfaceAngle <= AngleThresholdsRads.Walkable) {
|
|
return E_SurfaceType.Walkable;
|
|
} else if (surfaceAngle <= AngleThresholdsRads.SteepSlope) {
|
|
return E_SurfaceType.SteepSlope;
|
|
} else if (surfaceAngle <= AngleThresholdsRads.Wall) {
|
|
return E_SurfaceType.Wall;
|
|
} else {
|
|
return E_SurfaceType.Ceiling;
|
|
}
|
|
}
|
|
|
|
// ════════════════════════════════════════════════════════════════════════════════════════
|
|
// TYPE CHECKS
|
|
// ════════════════════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Check if surface allows normal walking movement
|
|
*
|
|
* @param surfaceType - Surface type to check
|
|
* @returns True if surface is walkable
|
|
*
|
|
* @pure true
|
|
* @category Type Checks
|
|
*/
|
|
public IsWalkable(surfaceType: E_SurfaceType): boolean {
|
|
return surfaceType === E_SurfaceType.Walkable;
|
|
}
|
|
|
|
/**
|
|
* Check if surface causes sliding behavior
|
|
*
|
|
* @param surfaceType - Surface type to check
|
|
* @returns True if surface is steep slope
|
|
*
|
|
* @pure true
|
|
* @category Type Checks
|
|
*/
|
|
public IsSteep(surfaceType: E_SurfaceType): boolean {
|
|
return surfaceType === E_SurfaceType.SteepSlope;
|
|
}
|
|
|
|
/**
|
|
* Check if surface blocks movement (collision wall)
|
|
*
|
|
* @param surfaceType - Surface type to check
|
|
* @returns True if surface is a wall
|
|
*
|
|
* @pure true
|
|
* @category Type Checks
|
|
*/
|
|
public IsWall(surfaceType: E_SurfaceType): boolean {
|
|
return surfaceType === E_SurfaceType.Wall;
|
|
}
|
|
|
|
/**
|
|
* Check if surface is overhead (ceiling)
|
|
*
|
|
* @param surfaceType - Surface type to check
|
|
* @returns True if surface is ceiling
|
|
*
|
|
* @pure true
|
|
* @category Type Checks
|
|
*/
|
|
public IsCeiling(surfaceType: E_SurfaceType): boolean {
|
|
return surfaceType === E_SurfaceType.Ceiling;
|
|
}
|
|
|
|
/**
|
|
* Check if no surface detected (airborne state)
|
|
*
|
|
* @param surfaceType - Surface type to check
|
|
* @returns True if no surface contact
|
|
*
|
|
* @pure true
|
|
* @category Type Checks
|
|
*/
|
|
public IsNone(surfaceType: E_SurfaceType): boolean {
|
|
return surfaceType === E_SurfaceType.None;
|
|
}
|
|
}
|
|
|
|
export const BFL_SurfaceClassifier = new BFL_SurfaceClassifierClass();
|