Guten Abend,
ich benötige ein wenig Hilfe bei einer Kamerarotation die ich implementiert habe.
Ich verwende die Unreal Engine 4 und es handelt sich dabei um ein Strategiespiel, dafür möchte ich die Kamera mit dem Mausrad um den fokussierten Punkt (auf dem Boden) drehen (kennt man vielleicht aus dem ein oder anderen Spiel).
Dafür führe ich einen Trace von der Kamera in ihre Vorwärtsrichtung durch. Dieser wird vom Boden blockiert und ich erhalte damit meinen fokussierten Punkt. Mithilfe von Kugelkoordinaten berechne ich dann die neue Position der Kamera und richte sie danach wieder auf selbigen Punkt aus. Das Problem ist, dass der nächste Trace mir einen anderen Punkt liefert. Dieser liegt zwar in nächster Nähe, aber der Kamerashift, wenn sie sich plötzlich auf den neuen Punkt ausrichtet, ist deutlich bemerkbar wenn man rotieren will. Daher berechne ich den Punkt auch sobald man die Rotation beginnt und speicher ihn. Ich berechne ihn aber nicht jeden Frame von neu, sonst landet die Kamera irgendwo. Sobald man aber das Mausrad drückt rotiert die Kamera leicht und "fokussiert" einen anderen Punkt.
Hier habe ich erstmal den Quellcode (aus der Tick-Funktion):
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
if (PC && bIsRotating)
{
FVector2D MousePos;
PC->GetMousePosition(MousePos.X, MousePos.Y);
FVector2D MouseDelta = MousePos - LastMousePosition;
FTransform RotationCenterTransform = FTransform(FRotator::ZeroRotator, RotationCenter);
FVector RelativeLocation = RotationCenterTransform.InverseTransformPosition(GetActorLocation());
float Theta, Phi;
GetSphericalCoords(RelativeLocation, Theta, Phi);
Theta -= MouseDelta.Y * RotateSpeed * DeltaTime;
Phi += MouseDelta.X * RotateSpeed * DeltaTime;
Theta = FMath::DegreesToRadians(FMath::ClampAngle(FMath::RadiansToDegrees(Theta), 1.0f, 90.0f));
FVector NewLocation = GetCartesianCoords(RelativeLocation.Size(), Theta, Phi);
SetActorLocation(RotationCenterTransform.TransformPosition(NewLocation), true);
SetActorRotation((RotationCenter - GetActorLocation()).Rotation());
LastMousePosition = MousePos;
}
|
Ich vermute, dass es einfach die Präzision ist, dass der LineTrace nicht denselben Punkt findet, auf den die Kamera direkt draufzeigt. Aber vielleicht habe ich auch nur einen Fehler gemacht.
Ich bräuchte dann eventuell einen anderen Ansatz um mein Problem zu umgehen. Folgende Ideen hatte ich:
- Da der Boden uneben ist, eventuell den Trace gegen einen Ebene ausführen (also eine LinePlaneIntersection), die ungefähr auf Höhe des Bodens liegt.
- Im ersten Frame nach dem Rotationsbeginn die neue Position speichern (diese wird "geshiftet" sein, da sich die Kamera auf das RotationCenter ausrichtet, welches davor getraced wurde, danach bleibt sie konstant auf den gleichen Punkt gerichtet) und in jedem weiteren Schritt gegen diese interpolieren, dass man keiner
Bevor ich das aber ändere, wollte ich erstmal die Meinung und Erfahrungen der anderen hören.
Danke schonmal im Voraus.