Euler Rotationen für LookAt < Topologie+Geometrie < Hochschule < Mathe < Vorhilfe
|
Aufgabe | Keine, selbstgemachtes Problem. :P |
(Ich habe diese Frage in keinem Forum auf anderen Internetseiten gestellt.)
Zuerst der Hintergrund:
Ich benutzt einen internen Spiele-Engine (Teil eines GIS) um ein kleines (Lern-)Spiel zu stricken. Ich habe zwei Flugzeuge (meins und ein Ziel) und eine Kamera in meinem Flugzeug, die auf das andere Flugzeug schauen soll, dabei aber parallel zum Horizont gedreht.
Der Engine gibt mir Euler Angles für meine eigene Rotation:
Pitch: Oben Negativ
Bank: Rechts Negativ
Heading: Rechts Positiv
Die Kamera benutzt dasselbe Koordinatensystem, wenn sie also 90° nach Rechts schaut, verändert Flugzeug Bank den Kamera-Pitch.
Ich habe bereits berechnet, wo das andere Flugzeug ist, allerdings basierend auf dem Horizont der Erde, da das GIS mir Lat/Lon/Alt auswirft. Ich weiss also:
OffsetPitch und OffsetHeading (relativ zu der Ebene des Horizont, also 0°Bank und 0°Pitch, aber mit Flugzeug Heading).
Ok, und nun hier mein Problem, dass mich jetzt seit ca. 3 Tagen beschäftigt:
Ich möchte, dass meine Kamera genau auf den Punkt schaut, der durch den OffsetPitch und OffsetHeading bestimmt ist. Gleichzeitig soll die Kamera aber parallel mit dem Horizont sein (0°Bank).
(Ich weiss bereits, das vernünftige Engines sowas mit Quaternions machen, aber sagen wir mal, ich möchte es aus nostalgischen Gründen halt mit dem machen, was ich habe. :P Ich weiss auch schon, dass es Gimbal Lock gibt, aus dem Grund möchte ich auch keine Quaternions nutzen, da ich mit dem Gimbal Lock spielen möchte.)
Meine erste Idee war die Folgende:
"Rotiere die Winkel zuerst mit Bank und Pitch, um sie vom Horizont zum Kamera System zu bringen."
Das sah dann so aus, ich habe dafür zuerst eine 3D Rotationsmatrix benutzt:
CamPitch =
TgtCamOffsetPitch * cos((Player.heading)) * cos((Player.bank)) +
TgtCamOffsetHeading * (cos((Player.pitch)) * sin((Player.bank)) + sin((Player.pitch)) * sin((Player.heading)) * cos((Player.bank)));
CamHeading =
TgtCamOffsetPitch * -cos((Player.heading)) * sin((Player.bank)) +
TgtCamOffsetHeading * (cos((Player.pitch)) * cos((Player.bank)) - sin((Player.pitch)) * sin((Player.heading))* sin((Player.bank)));
CamBank =
TgtCamOffsetPitch * sin((Player.heading)) * cos((Player.bank)) +
TgtCamOffsetHeading * -sin((Player.pitch)) * cos((Player.heading));
Das Resultat war ein Desaster. Ich habe dann in den letzten drei Tagen so ca. Hundert verschiedene Vorzeichen und andere Experimente gestartet, sogar alle sin/cos visuell überprüft... aber die Grundidee ist vermutlich falsch. Mittlerweile bin ich bei dem hier, was FAST funktioniert:
CamPitch = -Player.pitch * cos((TgtCamOffsetHeading)) * cos((Player.bank)) +
-Player.bank * sin((TgtCamOffsetHeading)) * cos((Player.pitch)) +
TgtCamOffsetPitch * cos((Player.bank)) +
TgtCamOffsetHeading * sin((Player.bank));
CamHeading = -Player.pitch * sin((TgtCamOffsetHeading)) * sin((Player.bank)) +
-Player.bank * sin((Player.pitch)) * cos((TgtCamOffsetHeading)) +
TgtCamOffsetPitch * -sin((Player.bank)) +
TgtCamOffsetHeading * cos((Player.bank));
CamBank = -Player.pitch * sin(DegreeToRadian(TgtCamOffsetHeading)) * cos(DegreeToRadian(Player.bank)) +
-Player.bank * cos(DegreeToRadian(TgtCamOffsetHeading)) * cos(DegreeToRadian(Player.pitch));
Aber auch hier klappt es nur, solange ich mit 0°Bank herumfliege. Sobald mein Flugzeug links oder rechts Bank hat, schaut die Kamera überall hin, nur nicht wo sie soll. Also muss irgendeine Grundannahme von mir irgendwie falsch sein, da ich offensichtlich Player.bank oben in der Formel habe, und ein ändern der Vorzeichen oder sin/cos Wechsel auch keinerlei positiven Effekt hatte.
Meine Frage ist also:
Wie kann ich meine zwei Winkel (TgtCamOffsetPitch / TgtCamOffsetHeading / der Bank soll immer null sein, also horizontal zum Horizont), die den Höhenwinkel des Ziels relativ vom Horizont der Erde und den Winkel zwischen meinem Flugzeug Heading und der Richtung in der das Ziel ist beschreiben, in drei Winkel (CamPitch, CamBank, CamHeadingOffset) umwandeln, die dafür sorgen, das meine Kamera auf das Ziel schaut?
Ich habe das Gefühl, ich sehe den Wald vor lauter Bäumen nicht, und das sollte doch eigentlich nicht so schwer sein!?
Ich bin gerade relativ frustriert und würde mich über Anregungen und Ideen sehr freuen. :P
Danke!
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 18:16 So 13.04.2014 | Autor: | skyflash |
Ja, danke. :P
Ich war bereits dran, und habe das Problem jetzt halbwegs im Griff. Jetzt ist mir auch klar geworden, was mir noch alles fehlte bei den Euler angles.
Meine Rotationssequenz sieht jetzt so aus, und ich weiss nicht warum. Ich habe zwar ne grobe Ahnung, aber ein paar Details gehen mir noch ab.
TargetRotation =
AngleAxisd(DegreeToRadian(-Player.pitch), Vector3d::UnitY()) *
AngleAxisd(DegreeToRadian(-Player.bank), Vector3d::UnitZ())*
AngleAxisd(DegreeToRadian(Player.bank), Vector3d::UnitZ()) *
AngleAxisd(DegreeToRadian(Player.pitch), Vector3d::UnitY()) *
AngleAxisd(DegreeToRadian(TgtPodOffsetPitch), Vector3d::UnitY()) *
AngleAxisd(DegreeToRadian(TgtPodOffsetHeading), Vector3d::UnitX()) *
AngleAxisd(DegreeToRadian(-Player.pitch), Vector3d::UnitY()) *
AngleAxisd(DegreeToRadian(-Player.bank), Vector3d::UnitZ());
Also ich drehe die Kamera erst zum Horizont, dann benutze ich die zwei Rotationen die relativ dazu sind, und drehe dann wieder umgekehrt zurück. Soweit so gut.
Aber warum ich jetzt dann zuerst zurück drehen muss, und DANACH wieder hin, verstehe ich noch nicht. Anders funktioniert es aber nicht. :P
Ich bin immer noch an einer Lösung des Euler Wegs interessiert, wenn irgendjemand es richtig drauf hat... einfach nur um zu verstehen, warum das nicht klappt. :P
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 06:47 Mi 16.04.2014 | Autor: | felixf |
Moin!
> Meine Rotationssequenz sieht jetzt so aus, und ich weiss
> nicht warum. Ich habe zwar ne grobe Ahnung, aber ein paar
> Details gehen mir noch ab.
>
> TargetRotation =
> AngleAxisd(DegreeToRadian(-Player.pitch),
> Vector3d::UnitY()) *
> AngleAxisd(DegreeToRadian(-Player.bank),
> Vector3d::UnitZ())*
> AngleAxisd(DegreeToRadian(Player.bank),
> Vector3d::UnitZ()) *
> AngleAxisd(DegreeToRadian(Player.pitch),
> Vector3d::UnitY()) *
Also, wenn die ersten vier Zeilen tun was ich denke (AngleAxisd(Winkel, Achse) erstellt eine Drehmatrix mit gegebenen Winkel um die gegebene Achse), dann sollten die ersten vier Zeilen insgesamt die Identitaet ergeben.
> AngleAxisd(DegreeToRadian(TgtPodOffsetPitch),
> Vector3d::UnitY()) *
> AngleAxisd(DegreeToRadian(TgtPodOffsetHeading),
> Vector3d::UnitX()) *
> AngleAxisd(DegreeToRadian(-Player.pitch),
> Vector3d::UnitY()) *
> AngleAxisd(DegreeToRadian(-Player.bank),
> Vector3d::UnitZ());
>
> Also ich drehe die Kamera erst zum Horizont, dann benutze
> ich die zwei Rotationen die relativ dazu sind, und drehe
> dann wieder umgekehrt zurück. Soweit so gut.
Das macht auch Sinn.
> Aber warum ich jetzt dann zuerst zurück drehen muss, und
> DANACH wieder hin, verstehe ich noch nicht. Anders
> funktioniert es aber nicht. :P
Meinst du damit die ersten vier Zeilen? Ja, das ist eine gute Frage.
Kannst du die Matrizen direkt ausgeben lassen? Also z.B. die erste, zweite, dritte, vierte Matrix getrennt und das Produkt von zweiter und dritter Matrix? Und das Produkt von erster und vierter?
LG Felix
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 21:20 Sa 19.04.2014 | Autor: | matux |
$MATUXTEXT(ueberfaellige_frage)
|
|
|
|