In continuation of my previous post where I added planes, now I want to add captions to these planes. It should look like a few strings of text with plane info, and these labels should always be looking to camera. The problem is again with rotation.
To my AAircraftActor I add UTextRenderComponent* text_aircraftId; the following way:
text_aircraftId = CreateDefaultSubobject<UTextRenderComponent>("TextComponent");
text_aircraftId->SetRelativeLocation(FVector(0.0f, -500.0f, 500.0f));
text_aircraftId->SetRelativeRotation(FRotator(0.0, 0.0, 0.0));
And then, on every frame I calculate FRotator for (cameraLocation to actorLocation):
void AAircraftActor::Tick(float DeltaTime)
FVector cameraLocation = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorLocation();
FRotator rotatorToCamera = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), cameraLocation);
FQuat4d localPlaneRotationQuat = this->cesiumGeoreference->ComputeEastNorthUpToUnreal(GetActorLocation()).ToQuat();
text_aircraftId->SetWorldRotation((localPlaneRotationQuat * rotatorToCamera.Quaternion()).Rotator());
Around CesiumGeoreference Origin everything works fine. But if I put a plane to the other part of the world, the rotation starts to break. Here is the video with 2 planes showing the problem:
It looks like your rotatorToCamera is already being computed in the Unreal reference frame, so rotating it further using the ESU → Unreal transform won’t make sense. Now, if you skipped the rotation and just used rotatorToCamera as your world rotation, you would find that the label faces the camera, but may appear upside down on the other side of the world.
The solution is probably to calculate the “lookAt” rotation (rotatorToCamera) in ESU, so it respects the correct “up” direction in that part of the world. You can do this by giving that function ESU coordinates instead of Unreal coordinates. Something like this should probably work (although I haven’t actually tried it).
const FVector& cameraLocation = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorLocation();
const FVector& actorLocation = GetActorLocation();
FVector cameraLocationRelative = cameraLocation - actorLocation;
FQuat4d esuToUnrealRotation = this->cesiumGeoreference->ComputeEastNorthUpToUnreal(GetActorLocation()).ToQuat();
FVector cameraEsu = esuToUnrealRotation.UnrotateVector(cameraLocationRelative);
// Actor location in ESU will just be (0,0,0)
FRotator rotatorToCamera = UKismetMathLibrary::FindLookAtRotation(FVector(0,0,0), cameraEsu);
text_aircraftId->SetWorldRotation((esuToUnrealRotation * rotatorToCamera.Quaternion()).Rotator());
Let me know how that goes!
It works correctly with the code you proposed, thank you very much!
If someone has thoughts on how to make such labels in Unreal Engine properly (maybe there is a better way than adding UTextRenderComponent* to each aircraft), you are welcome to share it. I’m just starting to use Unreal Engine. There may be dozens or hundreds of such aircraft, and I don’t know yet how this will affect performance.