Download

Finding the average of 2 normals in Blueprints and setting it as an actors roll rotation.

When I click two surfaces I find the Normals and average them. I then set the yaw and pitch to a target and set the roll to the normal average.
These are some snippets of my C# code in unity that works well. I’m currently moving the project over to Unreal and i’m having a hard time doing this in blueprints. I can get the actor to point towards target but since i’m using break hit result of a line trace its all Vector 3 and not quats so i don’t know how to average my normals. Any help would be really cool. Thanks

// C# version
normal1 = Quaternion.LookRotation(Vector3.ProjectOnPlane(transform.forward, hit.normal), hit.normal);

normal2 = Quaternion.LookRotation(Vector3.ProjectOnPlane(transform.forward, hit.normal), hit.normal);

Quaternion q;

//Create the average of the two vectors
q = Quaternion.Slerp(normal1, normal2, 0.5f);
normalAverage = q * Vector3.up;

transform.LookAt(target,normalAverage);

Most quaternion operations, like Slerp, are usually not available in Blueprints. But you can make them visible with a C++ function library. Here is the one I am using:



#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "QuaternionFunctionLibrary.generated.h"

/**
*
*/
UCLASS()
class BRICKGAMEVRCPP_API UQuaternionFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()

public:
// Convert Euler Rotations To Quaternions
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Euler To Quaternion", Keywords = "rotation, quaterion"), Category = "Quaternion Rotation")
static FQuat Euler_To_Quaternion(FRotator Current_Rotation);

// Function to set world rotation of scene component to input quaternion rotation
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set World Rotation (Quaterion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static void SetWorldRotationQuat(USceneComponent* SceneComponent, const FQuat& Desired_Rotation);

// Function to set relative rotation of scene component to input quaternion rotation
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set Relative Rotation (Quaterion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static void SetRelativeRotationQuat(USceneComponent* SceneComponent, const FQuat& Desired_Rotation);

// Function to add delta rotation to current local rotation of scene component
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Add Local Rotation (Quaterion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static void AddLocalRotationQuat(USceneComponent* SceneComponent, const FQuat& Delta_Rotation);

// Function to add delta rotation to current relative rotation of scene component
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Add Relative Rotation (Quaterion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static void AddRelativeRotationQuat(USceneComponent* SceneComponent, const FQuat& Delta_Rotation);

// Function to set world rotation of Actor to input quaternion rotation
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set Actor World Rotation (Quaternion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static void SetActorWorldRotationQuat(AActor* Actor, const FQuat& Desired_Rotation);

// Function to set relative rotation of Actor to input quaternion rotation
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set Actor Relative Rotation (Quaternion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static void SetActorRelativeRotationQuat(AActor* Actor, const FQuat& Desired_Rotation);

// Function to add delta rotation to current local rotation of Actor
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Add Actor Local Rotation (Quaternion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static void AddActorLocalRotationQuat(AActor* Actor, const FQuat& Delta_Rotation);

UFUNCTION(BlueprintCallable, meta = (DisplayName = "Spherical Interpolation (Quaternion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static void Slerp(const FQuat& Quat1, const FQuat& Quat2, float Slerp, FQuat& Result);

UFUNCTION(BlueprintCallable, meta = (DisplayName = "QInterpTo", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static FQuat QInterpTo(const FQuat& Current, const FQuat& Target, float DeltaTime, float InterpSpeed);

UFUNCTION(BlueprintCallable, meta = (DisplayName = "QInterpConstantTo", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation")
static FQuat QInterpConstantTo(const FQuat& Current, const FQuat& Target, float DeltaTime, float InterpSpeed);
};





#include "QuaternionFunctionLibrary.h"

// Formula to convert a Euler angle in degrees to a quaternion rotation
FQuat UQuaternionFunctionLibrary::Euler_To_Quaternion(FRotator Current_Rotation)
{
FQuat q; // Declare output quaternion
float yaw = Current_Rotation.Yaw * PI / 180; // Convert degrees to radians
float roll = Current_Rotation.Roll * PI / 180;
float pitch = Current_Rotation.Pitch * PI / 180;

double cy = cos(yaw * 0.5);
double sy = sin(yaw * 0.5);
double cr = cos(roll * 0.5);
double sr = sin(roll * 0.5);
double cp = cos(pitch * 0.5);
double sp = sin(pitch * 0.5);

q.W = cy * cr * cp + sy * sr * sp;
q.X = cy * sr * cp - sy * cr * sp;
q.Y = cy * cr * sp + sy * sr * cp;
q.Z = sy * cr * cp - cy * sr * sp;

return q; // Return the quaternion of the input Euler rotation
}

// Set the scene component's world rotation to the input quaternion
void UQuaternionFunctionLibrary::SetWorldRotationQuat(USceneComponent* SceneComponent, const FQuat& Desired_Rotation)
{
if (SceneComponent)
{

SceneComponent->SetWorldRotation(Desired_Rotation);
}
}

// Set the scene component's relative rotation to the input quaternion
void UQuaternionFunctionLibrary::SetRelativeRotationQuat(USceneComponent* SceneComponent, const FQuat& Desired_Rotation)
{
if (SceneComponent)
{
SceneComponent->SetRelativeRotation(Desired_Rotation);
}
}

// Add the input delta rotation to the scene component's current local rotation
void UQuaternionFunctionLibrary::AddLocalRotationQuat(USceneComponent* SceneComponent, const FQuat& Delta_Rotation)
{
if (SceneComponent)
{
SceneComponent->AddLocalRotation(Delta_Rotation);
}
}

// Add the input delta rotation to the scene component's current relative rotation
void UQuaternionFunctionLibrary::AddRelativeRotationQuat(USceneComponent* SceneComponent, const FQuat& Delta_Rotation)
{
if (SceneComponent)
{
SceneComponent->AddRelativeRotation(Delta_Rotation);
}
}

// Set the Actor's world rotation to the input quaternion
void UQuaternionFunctionLibrary::SetActorWorldRotationQuat(AActor* Actor, const FQuat& Desired_Rotation)
{
if (Actor)
{
Actor->SetActorRotation(Desired_Rotation);
}
}

// Set the Actor's relative rotation to the input quaternion
void UQuaternionFunctionLibrary::SetActorRelativeRotationQuat(AActor* Actor, const FQuat& Desired_Rotation)
{
if (Actor)
{
Actor->SetActorRelativeRotation(Desired_Rotation);
}
}

// Add the input delta rotation to the Actor's current local rotation
void UQuaternionFunctionLibrary::AddActorLocalRotationQuat(AActor* Actor, const FQuat& Delta_Rotation)
{
if (Actor)
{
Actor->AddActorLocalRotation(Delta_Rotation);
}
}

void UQuaternionFunctionLibrary::Slerp(const FQuat& Quat1, const FQuat& Quat2, float Slerp, FQuat& Result)
{
Result = FQuat::Slerp(Quat1, Quat2, Slerp);
}

FQuat UQuaternionFunctionLibrary::QInterpTo(const FQuat& Current, const FQuat& Target, float DeltaTime, float InterpSpeed)
{
return FMath::QInterpTo(Current, Target, DeltaTime, InterpSpeed);
}

FQuat UQuaternionFunctionLibrary::QInterpConstantTo(const FQuat& Current, const FQuat& Target, float DeltaTime, float InterpSpeed)
{
return FMath::QInterpConstantTo(Current, Target, DeltaTime, InterpSpeed);
}


Yes, this is what I needed thanks! Also how do get this library working. lol

Edit: The manual is enough. It walks you right through it! Again thanks.