Align Camera with different Coordinate System and Track Actor

How to maintain camera alignment with World Surface and track actor?

Please correct me if I have made any mistakes please…

The problem: I have a very large map where a world is represented, Spherical World / Earth. I have an object that is flying around the world and I want to make a camera which is stationary follow/track the object but not replicate the rotation of the object. Instead it should be perpendicular to the surface of the world directly beneath it. In other words the downward direction as represented by the camera view should be towards the ground beneath the camera itself, not the orientation of the Actor being tracked. The Camera would then appear to only rotate on a yaw and pitch w.r.t. the world (So not really UE yaw and pitch) as it tracks the Actor.

The Attempt to Solve: I have a Class that has inherited the ACineCameraActor and I have overridden the tick with hopes in fixing the issue where if a ACineCameraActor is used it will orientate the camera with respect to the rotation of the object. What I currently have is the following:

        FQuat NextQuat = FQuat::FindBetween(FVector(X_QUAT, Y_QUAT, Z_QUAT), ActorToTrack->GetActorLocation() - GetActorLocation());
        FRotator LookAtRotaion = FQuat::Slerp(GetActorRotation().Quaternion(), NextQuat, FMath::Min(1.0f, DeltaTime)).Rotator();
        SetActorRotation(LookAtRotaion);

The FindBetween Vector is essentially the forward vector which should be {1.0f,0.0f,0.0f} I exposed the X, Y, Z_QUAT so that I could understand what happens when I change the values. “Still learning about Quaternions”.

With the settings of the Camera as follows:

		NewCamera =
			GetWorld()->SpawnActor<NewCineCameraActor>(
				UePosition,
				UeRotation,
				SpawnParams);

		NewCamera->GetCineCameraComponent()->SetConstraintAspectRatio(false);
		NewCamera->LookatTrackingSettings.ActorToTrack = TSoftObjectPtr<AActor>(TrackingActor);
		NewCamera->LookatTrackingSettings.bEnableLookAtTracking = true;
		NewCamera->LookatTrackingSettings.LookAtTrackingInterpSpeed = 100.0f;
		NewCamera->LookatTrackingSettings.bAllowRoll = true;

Note: The UeRotation used when spawning the camera is a correct calculation of the camera rotation it should start with so the downward direction is towards the world surface.

This consequently does exactly the same thing… derr face palm my particular example the camera downward direction appears to be rolled roughly 45 degrees, so the surface of the world looks tilted.
The issues I’m observing is that you can not just add an arbitrary rotation to realign with the world surface it must be calculated during runtime. Because if the camera were to move to another location its orientation to the world surface would be different. I feel the answer resides in calculating the correct LookAtRotation, by including the UeRotation calculated at spawn but I’m unsure how to include it in the Quaternion FindBetween our Camera and Tracking Actor. Or possibly there is a much simpler solution… Any suggestions?

Funnily enough I have found a relatively good solution already for slightly different context.

SoSeductive69_Tv FindLookAtRotation

Rough Solution:

  1. I acquired the NewCamera->GetActorUpVector() when the camera was created which uses the UeRotation as it was spawned previously mentioned and stored it on the camera class.
  2. Then I used the UpVector stored which is reflective of the UeRotation on spawn which points upwards from the world surface as the upDirection in the MyLookRotation function.
  3. The lookAt as the Tracking Actor location vector.
  4. And it returns the needed FRotator you need for the FQuat::Slerp Quat2 param.

Visually it looks like this:

FRotator LookTo = MyLookRotation(ActorToTrack->GetActorLocation(), InitUpVector);
FRotator LookAtRotaion = FQuat::Slerp(GetActorRotation().Quaternion(), LookTo.Quaternion(), FMath::Min(1.0f, DeltaTime)).Rotator();
SetActorRotation(LookAtRotaion);

What I have yet to fully understand is the Math and if some of the existing functions in UnrealEngine could be used instead.

Would like to know If anyone else found a more refined solution?

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