Pitch Rotation stucks at [-90 90] C++

I searched all relative questions on this topic and i couldn’t find something useful. I use 4.15 and the pitch rotation bug is still there. My problem is not Gimbal Lock . My Actor just stops pitch rotating at (-)90 degrees. I tried SetActorLocation, LocalRotation,SetWorldRotation,SetActorRelativeLocation and every time i get the same result. I even tried quaternions.

Pitch code:

void ATest::Pitch(float Val) {

	SphereMovement.Pitch = FMath::Clamp(Val, -1.0f, 1.0f);
	if (Val != 0) {
		UE_LOG(LogTemp, Warning, TEXT("Pitch = %f"), GetActorRotation().Pitch);
	}
}

Tick:

 void ATest::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

	if (!SphereMovement.IsZero()) {
		FRotator newRotation = GetActorRotation() + (SphereMovement);
		SetActorRotation(newRotation);
	}
}

I looked a bit in the source code and saw, that the rotator is eventually turned into a quaternion. So when you call GetActorRotation, this quaternion is transformed back into a rotator, but because of mathematical reason I don’t understand, the pitch angle is clamped between -90 and 90 degree.

(Yaw and roll seem to be calculated with an atan2, which ranges from -180 to 180 degree, and pitch seem to be calculated with an asin, which results in a range from -90 to 90 degree. But again, I have no understanding about the mathematical reasons why to use asin and atan2.)

In the source code I could find references to this quaternion-to-rotator-transformation, perhaps they are helpful for you. And the function is question is FRotator FQuat::Rotator() in case you want to look it up.

http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/

The problem is happening on the “poles”, ill try to add the branch code for the poles and see what will happen.

The solution to my problem was:

void ATest::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

	if (!SphereMovement.IsZero()) {
		FRotator newRotation = SphereMovement ;

		FQuat quatRotation = FQuat(newRotation);

		AddActorLocalRotation(quatRotation,false,0,ETeleportType::None);
	}

}

Had to remove GetActorRotation and change SetActorRotation to AddActorLocalRotation

The quaternion part is not necessary .

1 Like