Understanding Rotation

Hello,

I need to create a functionality that limits the camera rotation between a given range. If my full ration is 360 degrees. I need to be able to rotate the camera starting from 0 - 180(Camera is attached to a spring arm component).


Please refer above image for better understanding of my requirement.

I saw that there are possibilities for me to do this using existing functions. But What I require is to do this manually using C++. So far what I have done is this

void APlayerCharacter::MouseXAxis(float Value)
{
	// default way of doing this method
	// OwnPlayerController->AddYawInput(Value);

	if (Value == 0.0f) return;
	APlayerController *OwnPlayerController = Cast<APlayerController>(Controller);
	if (OwnPlayerController)
	{

		if (GetControlRotation().Yaw < 180.f)
		{
			UE_LOG(LogTemp, Warning, TEXT("Debug value %f"), GetControlRotation().Yaw);
			FRotator CurrentRotation = OwnPlayerController->RotationInput;
			float RotationYawValue = !OwnPlayerController->IsLookInputIgnored() ? Value * OwnPlayerController->InputYawScale : 0.f;
		
			FRotator NewBoomRotation = FRotator(CurrentRotation.Pitch, CurrentRotation.Yaw, CurrentRotation.Roll);
			NewBoomRotation.Yaw = CurrentRotation.Yaw + RotationYawValue;


			UE_LOG(LogTemp, Warning, TEXT("Calculated Value %f"), NewBoomRotation.Yaw);
			UE_LOG(LogTemp, Warning, TEXT("Denormalized Value %f"), NewBoomRotation.GetDenormalized().Yaw);

			OwnPlayerController->RotationInput = NewBoomRotation;
		}
	}
}

This is around Z axis. Therefore I’m trying to limit the Yaw axis rotation. But this wont work until I am able to clamp the actual new Yaw value that I am trying to assign to NewBoomRotation.Yaw. But I cant seem to understand the value that I am getting from this CurrentRotation.Yaw + RotationYawValue.

Can anyone please explain why I am getting this value ranging from 0-1 when I do this calculation CurrentRotation.Yaw + RotationYawValue. And how to Denormalized that value in order for me to clamp it between 0-180. I tried this NewBoomRotation.GetDenormalized().Yaw but it didnt give me the value that I expect either.

For this I believe I need basic understanding of how Rotation works in unreal. Hence the topic title.

Thanks in advance.

Hi!

GetControlRotation() gives you the control rotation in world space meaning when looking down the world X axis the yaw is always going to be 0. When you circle your view to the right around your pawn the value will increase until it rolls over to 0 again when a full rotation has been completed. This happens irrespective of your pawn’s own rotation so if your pawn can rotate at all you can’t just check the world space yaw. You need to transform the world control rotation into local space, for example like this:

  FRotator WorldControlRotation = GetControlRotation();
  FRotator LocalControlRotation = FRotator(RootComponent->GetComponentTransform().GetRotation() * WorldControlRotation.Quaternion().Inverse());

Now whenever you look to the left of your pawn the local yaw value will be -90 and if you look to the right it will be 90, no matter what the absolute rotation of the pawn in world space is:

  if (LocalControlRotation.Yaw >= -90.f && LocalControlRotation.Yaw =< 90.f)
  {
       // Still in your desired range.
  }
  else
  {
       // Outside of your desired range.
  }

Little hint when you continue working on this now:
You might be tempted to just add the input when the first branch is true and just don’t do anything when going into the else branch. That won’t work because if the local control rot is currently 90 or almost 90 for example and you add the input, next time it will be something like 90.01 and then it will never enter the branch again and you will be stuck.

Hope this helps.

1 Like

Hey,
Thank you very much for you response!

Now when you point it out I looked into it using the details of controller in game. I see now when rotation is changed to world space the value of Z axis changes but with local space it always stays 0.
Is there a better location for me to understand rotation a bit more clearly ? Like how world space and local space differ ? Also how to work with Vectors/Quaternion when you want to manipulate rotation of an actor?

about the latter part. Yes that’s why I need to clamp the values between -90 – +90 I guess?
but when I do this to calculate the rotation amount from the input given like below

float RotationYawValue = !OwnPlayerController->IsLookInputIgnored() ? Value * OwnPlayerController->InputYawScale : 0.f;

I get a value between 0-1. I do not understand how to clamp that amount between this -90 – +90 range?

Please let me know if you dont understand my question. I will try to explain it more.

Again thank you for the response. :slight_smile:

You get the control rotation in world space and with the formula I used you can change it into local space which means it is then relative to the root component of your actor. If your values are always 0 that would indicate that you are somehow taking the rotation of the root component? Because local space means that everything is relative to the origin of the actor instead of the world origin (that’s why it’s also called object space sometimes) and therefore the values of the root component will always be 0 in local space. You are also talking about the Z axis instead of the yaw axis. Keep in mind that the ordering of an FRotator in C++ is different than the ordering used in Blueprint: it is Pitch(Y), Yaw(Z), Roll(X). Maybe you are looking at the wrong axis?

If you google you will find more resources on the topics, for example I found these, maybe they will help you:

https://ninepointeightgame.com/game-updates/quick-quaternion-tips

Yes, “Value” is basically how much delta will be added to the current rotation when you move your mouse. It will typically be a small value, so if you move your mouse slowly it’s something like 0.5 or -0.5 depending on the direction you move your mouse in. If you move your mouse very fast it will be higher like 5 or -5. It is not necessarily only between 0 and 1.

If you still have trouble you could show your new code (and maybe include a screenshot of how your pawn is set up) and I will try it out when I have some spare time.

One more thing:
With the code I have given you in my previous post you should log all values togeher and move the mouse to see how they relate, that might clear up some confusion.

  UE_LOG(LogTemp, Warning, TEXT("World Control Rotation: %s"), *WorldControlRotation.ToString());
  UE_LOG(LogTemp, Warning, TEXT("Local Control Rotation: %s"), *LocalControlRotation.ToString());
  UE_LOG(LogTemp, Warning, TEXT("MouseXAxis Input Value: %f"), Value);

Thank you for your response again. I will check these resources out. Yes I understood that axis order is different in blueprint compares to FRotator constructor in C++. I might be looking at this wrong. I will have to educate my self more on this. I will go through these resources and whats out there. I will post an answer If I figured it out. Otherwise I might just ask another question here :slight_smile:

Sorry for the late response. Got busy with some work.

Hey man how it going. Hope you are doing well.
I was able to improve upon the code for a bit. But right now I am kinda stuck with Pitch axis limitation. I have created a detailed post here https://www.reddit.com/r/unrealengine/comments/si391v/help_need_help_on_understanding_rotation_and_how/.

Could you please have a look at it :grimacing: