164 lines
5.6 KiB
C++
164 lines
5.6 KiB
C++
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "Kismet/BlueprintFunctionLibrary.h"
|
|
#include "GMS_Vector.generated.h"
|
|
|
|
UCLASS(Meta = (BlueprintThreadSafe))
|
|
class GENERICMOVEMENTSYSTEM_API UGMS_Vector : public UBlueprintFunctionLibrary
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Vector", ReturnDisplayName = "Vector"))
|
|
static FVector ClampMagnitude01(const FVector& Vector);
|
|
|
|
static FVector3f ClampMagnitude01(const FVector3f& Vector);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", DisplayName = "Clamp Magnitude 01 2D",
|
|
Meta = (AutoCreateRefTerm = "Vector", ReturnDisplayName = "Vector"))
|
|
static FVector2D ClampMagnitude012D(const FVector2D& Vector);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (ReturnDisplayName = "Direction"))
|
|
static FVector2D RadianToDirection(float Radian);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (ReturnDisplayName = "Direction"))
|
|
static FVector RadianToDirectionXY(float Radian);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (ReturnDisplayName = "Direction"))
|
|
static FVector2D AngleToDirection(float Angle);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (ReturnDisplayName = "Direction"))
|
|
static FVector AngleToDirectionXY(float Angle);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Direction", ReturnDisplayName = "Angle"))
|
|
static double DirectionToAngle(const FVector2D& Direction);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Direction", ReturnDisplayName = "Angle"))
|
|
static double DirectionToAngleXY(const FVector& Direction);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Vector", ReturnDisplayName = "Vector"))
|
|
static FVector PerpendicularClockwiseXY(const FVector& Vector);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "Vector", ReturnDisplayName = "Vector"))
|
|
static FVector PerpendicularCounterClockwiseXY(const FVector& Vector);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", DisplayName = "Angle Between (Skip Normalization)",
|
|
Meta = (AutoCreateRefTerm = "From, To", ReturnDisplayName = "Angle"))
|
|
static double AngleBetweenSkipNormalization(const FVector& From, const FVector& To);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", Meta = (AutoCreateRefTerm = "From, To", ReturnDisplayName = "Angle"))
|
|
static float AngleBetweenSignedXY(const FVector3f& From, const FVector3f& To);
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "GMS|Vector Utility", DisplayName = "Slerp (Skip Normalization)",
|
|
Meta = (AutoCreateRefTerm = "From, To", ReturnDisplayName = "Direction"))
|
|
static FVector SlerpSkipNormalization(const FVector& From, const FVector& To, float Ratio);
|
|
};
|
|
|
|
inline FVector UGMS_Vector::ClampMagnitude01(const FVector& Vector)
|
|
{
|
|
const auto MagnitudeSquared{Vector.SizeSquared()};
|
|
|
|
if (MagnitudeSquared <= 1.0f)
|
|
{
|
|
return Vector;
|
|
}
|
|
|
|
const auto Scale{FMath::InvSqrt(MagnitudeSquared)};
|
|
|
|
return {Vector.X * Scale, Vector.Y * Scale, Vector.Z * Scale};
|
|
}
|
|
|
|
inline FVector3f UGMS_Vector::ClampMagnitude01(const FVector3f& Vector)
|
|
{
|
|
const auto MagnitudeSquared{Vector.SizeSquared()};
|
|
|
|
if (MagnitudeSquared <= 1.0f)
|
|
{
|
|
return Vector;
|
|
}
|
|
|
|
const auto Scale{FMath::InvSqrt(MagnitudeSquared)};
|
|
|
|
return {Vector.X * Scale, Vector.Y * Scale, Vector.Z * Scale};
|
|
}
|
|
|
|
inline FVector2D UGMS_Vector::ClampMagnitude012D(const FVector2D& Vector)
|
|
{
|
|
const auto MagnitudeSquared{Vector.SizeSquared()};
|
|
|
|
if (MagnitudeSquared <= 1.0f)
|
|
{
|
|
return Vector;
|
|
}
|
|
|
|
const auto Scale{FMath::InvSqrt(MagnitudeSquared)};
|
|
|
|
return {Vector.X * Scale, Vector.Y * Scale};
|
|
}
|
|
|
|
inline FVector2D UGMS_Vector::RadianToDirection(const float Radian)
|
|
{
|
|
float Sin, Cos;
|
|
FMath::SinCos(&Sin, &Cos, Radian);
|
|
|
|
return {Cos, Sin};
|
|
}
|
|
|
|
inline FVector UGMS_Vector::RadianToDirectionXY(const float Radian)
|
|
{
|
|
float Sin, Cos;
|
|
FMath::SinCos(&Sin, &Cos, Radian);
|
|
|
|
return {Cos, Sin, 0.0f};
|
|
}
|
|
|
|
inline FVector2D UGMS_Vector::AngleToDirection(const float Angle)
|
|
{
|
|
return RadianToDirection(FMath::DegreesToRadians(Angle));
|
|
}
|
|
|
|
inline FVector UGMS_Vector::AngleToDirectionXY(const float Angle)
|
|
{
|
|
return RadianToDirectionXY(FMath::DegreesToRadians(Angle));
|
|
}
|
|
|
|
inline double UGMS_Vector::DirectionToAngle(const FVector2D& Direction)
|
|
{
|
|
return FMath::RadiansToDegrees(FMath::Atan2(Direction.Y, Direction.X));
|
|
}
|
|
|
|
inline double UGMS_Vector::DirectionToAngleXY(const FVector& Direction)
|
|
{
|
|
return FMath::RadiansToDegrees(FMath::Atan2(Direction.Y, Direction.X));
|
|
}
|
|
|
|
inline FVector UGMS_Vector::PerpendicularClockwiseXY(const FVector& Vector)
|
|
{
|
|
return {Vector.Y, -Vector.X, Vector.Z};
|
|
}
|
|
|
|
inline FVector UGMS_Vector::PerpendicularCounterClockwiseXY(const FVector& Vector)
|
|
{
|
|
return {-Vector.Y, Vector.X, Vector.Z};
|
|
}
|
|
|
|
inline double UGMS_Vector::AngleBetweenSkipNormalization(const FVector& From, const FVector& To)
|
|
{
|
|
return FMath::RadiansToDegrees(FMath::Acos(From | To));
|
|
}
|
|
|
|
inline float UGMS_Vector::AngleBetweenSignedXY(const FVector3f& From, const FVector3f& To)
|
|
{
|
|
FVector2f FromXY{From};
|
|
FromXY.Normalize();
|
|
|
|
FVector2f ToXY{To};
|
|
ToXY.Normalize();
|
|
|
|
// return FMath::RadiansToDegrees(FMath::Atan2(FromXY ^ ToXY, FromXY | ToXY));
|
|
|
|
return FMath::RadiansToDegrees(FMath::Acos(FromXY | ToXY)) * FMath::Sign(FromXY ^ ToXY);
|
|
}
|