Is there a better way of using Quaternions in Blueprints?

In my current project I´ve found a Gimbal lock problem trying to rotate around an actor based on a VR controller input. The VR controller that I´m developing outputs the orientation as a quaternion. As far as I know there´s not support of the Quat class in Blueprints so I have to figure out a way to use the Rotator functionality in order to avoid the Gimbal lock. So my solution is to write a custom function in Bluprint called “QuatToAxisAngle” that converts the quaternion to its AxisAngle representation ( Q (qx, qy, qz, qw) → Angle = acos(qw) * 2, Axis = [(qx / sqrt(1 - qw ^ 2), (qy / sqrt(1 - qw ^ 2) , (qz / sqrt(1 - qw ^ 2) ] ). Then I simply use the “Rotator from Axis and Angle” node in Blueprint to create a Rotator that changes the actor orientation. It works perfectly but I wonder if there is a clever way to do this stuff. I hope this solution was useful for people having a hard time with Gimbal lock in their blueprints.

I have been having a nightmare with gimbal lock recently in a blueprint orientated project. It comes down to the rotation function nodes not having the Quat versions exposed. You can expose them or do what you did and write a new function to encapsulate what you need. Here is a pastebin of how to expose the FQuat version of AddLocalRotation.

Pastebin link

Thank you Doublezer0. I´ll have a look at the code you suggest. It´d be great if UE4 exposed this functionality out of the box without forcing developers to do these kind of extra work. Quaternions are a key feature in 3d programming and use it in blueprints should be a must have functionality in this engine.

Sorry to necropost this topic, but I’m having trouble using Doublezer0’s code, it throws several errors for me, would either of you mind clarifying how it is implemented?

I’m getting:

Function return type: Missing variable type

And in a different arrangement

Inappropriate '*' on variable of type ‘FHitResult’, cannot have an exposed pointer to this type.

Hi Zmalsberg, From looking at the date of this post I can see it was done in the 4.8-4.9 version of the engine. Could you tell us what engine release you are using?

To clarify how it is used, The header file contains the definition/declaration with these two lines :

UFUNCTION(BlueprintCallable, Category=“Utilities|Transformation”, meta=(DisplayName=“AddLocalRotationQuat”, AdvancedDisplay=“bSweep,SweepHitResult,bTeleport”))
void AddLocalRotationQuat(const FQuat& DeltaRotation, bool bSweep=false, FHitResult* OutSweepHitResult=nullptr, ETeleportType Teleport = ETeleportType::None);

The cpp file would contain the method with these two lines :

void AddLocalRotationQuat(const FQuat& DeltaRotation, bool bSweep=false, FHitResult* OutSweepHitResult=nullptr, ETeleportType Teleport = ETeleportType::None);
AddLocalRotation(DeltaRotation,bSweep,OutSweepHitResult,Teleport);
}

Now some things can change. Also there was a spelling mistake in the hastebin code originally in the AddLocalRotation() section where DeltaRotation actually says DeltaRotationm. My mistake there but an obvious one, you probably already caught it.

Thank you for taking the time to respond, but I’m still having issues with the code. I’m using 4.10.2, in a new Pawn class.

In the .h, AddLocalRotationQuat can’t find the definition in the .cpp file, including the function in the AMyPawn:: class scope didn’t seem to help either.

In the .cpp, VS tells me identifier “AddLocalRotation” is undefined, I assumed the last bracket in your code meant AddLocalRotation was part of the function AddLocalRotationQuat, but it also gives the same error when declared on its own line.

Attached is the code in a new project:

You didn’t add the Class Identifier before the AddLocalRotationQuat part in the cpp.
It should read void AMyPawn::AddLocalRotationQuat()
You see how the rest of the functions are declared the same way.

I still get the: “Inappropriate ‘*’ on variable of type ‘FHitResult’” error with a AMyPawn:: class declaration on AddLocalRotationQuat(), and/or on AddLocalRotation().

I’ve tried switching the code into a new Actor class, but I received the same errors.

I’m not sure where the function AddLocalRotation is supposed to be defined, I couldn’t find it in Pawn.h or Actor.h, and it seems to only appear in Actor.cpp and USceneComponent.cpp

What would happen if you fed euler rotators into Combine Rotators? Would that give you correct rotation transformation without gimbal lock? I heard on another thread that Combine Rotators node takes Euler rotator vector as input and gives it as output, but does the calculation using Quaternions.

it does indeed do that with transforms but I never seem to see it working like it should. All this was a long time ago now (4.9 era) and things are a little different now. I wouldn’t bother trying to do things like this in blueprints anymore anyway. It’s time to step away from BP only projects :smiley:

Ive made a simple, easy to use plugin that exposes quats to blueprints for those still interested