C++ Quaternions.

UE 5.1

Hi,

So I’m facing the eternal gimbal lock problem.

I have a camera pawn than user can control on pitch, yaw and roll and of course, the gimbal lock prevents the user to pass the limits for rotation on pitch and roll.

So I tried to use quaternions to solve that issue but my code does not seem to work.

void ACameraPawn::ControllerRotateYawAndPitch(const FInputActionValue& Value)
{
	FVector2D LookAxisVector = Value.Get<FVector2D>();

	if(Controller==nullptr) return;

	UE_LOG(LogTemp,Warning,TEXT("PITCH INPUT RECEIVED, Y IS  / %f, X IS / %f"), LookAxisVector.Y,LookAxisVector.X);

	//The Add Controller Pitch Input does not pass 90 and -90 degres because of gimbal lock.

	//AddControllerPitchInput(LookAxisVector.Y* BaseLookUpRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);


	FRotator CurrentRotator{LookAxisVector.Y,0,0};
		
	FQuat NewQuatRotation=URotationHelpers::Euler_To_Quaternion(CurrentRotator);

	URotationHelpers::AddActorLocalRotationQuat(this,NewQuatRotation);
		
	
}

And the static functions that are supposed to handle the quaternion conversion :

FQuat URotationHelpers::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
}


void URotationHelpers::AddActorLocalRotationQuat(AActor* Actor, const FQuat& Delta_Rotation)
{
    if (Actor)
    {
        Actor->AddActorLocalRotation (Delta_Rotation);

        UE_LOG(LogTemp,Warning,TEXT("RotationHelpers is rotating the actor "));
    }
}

Currently the code does not event make the pitch move even though the input values are well received and I have no clues as to why.

Thank you in advance.

Hi jdgfkf,

FRotator has a built-in method called “Quaternion()” - you can just use that to convert to an FQuat.

I tried comparing the results between your conversion and the built-in one and they are different…

Hi,

Thank you for your answer, that simplified the process.

Long story short, I got tricked because the pawn did not have a default camera and the component I’m using was not a real “camera”, by adding a true camera on top and attaching the one we are using to it, it works as expected.

Thanks

void ACameraPawn::ControllerRotateYawAndPitch(const FInputActionValue& Value)
{
	const FVector2D LookAxisVector = Value.Get<FVector2D>();

	if(Controller==nullptr) return;

	if(!bIsPitchAxisLocked)
	{

		UE_LOG(LogTemp,Warning,TEXT("PITCH INPUT RECEIVED, Y IS  / %f, X IS / %f"), LookAxisVector.Y,LookAxisVector.X);

		const float PitchInputValue=(LookAxisVector.Y*-1);

		const FRotator PitchDeltaRotation=UKismetMathLibrary::MakeRotator(0,PitchInputValue,0);
		
		PawnCamera->AddRelativeRotation(PitchDeltaRotation.Quaternion(),false);
	}
		
	if(!bIsYawAxisLocked)
	{
		AddControllerYawInput(LookAxisVector.X* BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);

	}
}
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.