Verwenden von Quaternions: Was kann ich damit machen? (ohne die Mathematik)

24

Ich bin ein Spieleentwickler und habe keine Mathematik studiert. Ich möchte also nur Quaternions als Werkzeug verwenden. Um mit 3D-Rotation arbeiten zu können, ist es erforderlich, Quaternions (oder Matrizen) zu verwenden. Lassen Sie uns jedoch in dieser Frage bei Quaternions bleiben. Ich denke, dass es für viele Entwickler wichtig ist, sie zu verwenden. Deshalb möchte ich mein Wissen teilen und hoffentlich die Lücken füllen, die ich habe. Jetzt....

So weit ich verstanden habe:

Eine Quaternion kann zwei Dinge beschreiben:

  1. Die aktuelle Ausrichtung eines 3D-Objekts.
  2. Die Rotationstransformation, die ein Objekt ausführen könnte. (rotationChange)

Du kannst mit einer Quaternion machen:

Multiplikationen:

  1. Quaternion endOrientation = Quaternion rotationChange * Quaternion currentOrientation;

    Zum Beispiel: Mein 3D-Objekt ist um 90 ° nach links gedreht - und meine Drehung, die ich multipliziere, ist eine Drehung um 180 ° nach rechts, am Ende ist mein 3D-Objekt um 90 ° nach rechts gedreht.

  2. Quaternion rotationChange = Quaternion endRotation * Quaternion.Inverse (startRotation);

    Hiermit erhalten Sie eine Rotationsänderung, die auf eine andere Ausrichtung angewendet werden kann.

  3. Vector3 endPostion = Quaternion rotationChange * Vector3 currentPosition;

    Zum Beispiel: Mein 3D-Objekt ist auf Position (0,0,0) und meine Drehung, die ich multipliziere, ist eine Drehung um 180 ° nach rechts, meine Endposition ist ungefähr (0, -50,0). In dieser Quaternion gibt es eine Achse - und eine Drehung um diese Achse. Sie drehen Ihren Punkt um diese Achse Y Grad.

  4. Vector3 turnedOffsetVector = Quaternion rotationChange * Vector3 currentOffsetVector;

    Zum Beispiel: Meine Startrichtung zeigt UP - (0,1,0), und meine Drehung, die ich multipliziere, ist eine Drehung um 180 ° nach rechts, meine Endrichtung zeigt nach unten. (0, -1,0)

Mischen (Lerp und Slerp):

  1. Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, interpolator)

    Wenn der Interpolator 1 ist: currentOrientation = endOrientation

    Wenn der Interpolator 0 ist: currentOrientation = startOrientation

    Slerp interpoliert präziser, Lerp interpoliert performanter.

Meine Fragen):

Ist alles, was ich bis jetzt erklärt habe, richtig?

Ist das "alles", was Sie mit Quaternions tun können? (obv. nicht)

Was können Sie sonst noch mit ihnen machen?

Wofür eignen sich das Dot-Produkt und das Cross-Produkt zwischen 2 Quaternionen?

Bearbeiten:

Aktualisierte Frage mit einigen Antworten

OC_RaizW
quelle
Angenommen, Sie haben nicht zwei, sondern nunterschiedliche Ausrichtungen (Einstellungen, Posen usw.). Dann können Sie sie mit Gewichten mitteln und so Slerp / Lerp effektiv verallgemeinern. Sie können ein Quaternion auch in einen Rotor umwandeln, was dem Anwenden einer Winkelgeschwindigkeit für einen bestimmten Zeitraum auf einen starren Körper entspricht. Daher können Sie die Winkelgeschwindigkeitsintegration auch mit Quaternionen beschreiben. Sie können auch schätzen, wie unterschiedlich zwei Ausrichtungen sind (berechnen Sie die Länge des Bogens, der von den beiden Quaternionen auf der Hypersphäre gespannt wird).
Teodron
Und ja, auf den ersten Blick ist Ihre Begründung richtig (Ihr Verständnis von Quaternionen ist für eine nicht-technische Person recht gut). Dies ist für einen Kommentar ungeeignet, aber Glückwunsch! Nicht einmal die technisch Begabten kennen alle Quaternion-Anwendungen, obwohl sie sie nur als Software-Engineering-Tools für einen bestimmten Zweck verwenden.
Teodron
4
"Um mit 3D-Rotation arbeiten zu können, müssen Quaternionen verwendet werden." Ich kann gar nicht genug betonen, wie falsch dieser Satz ist. Sie können Euler- oder Tait-Bryan-Winkel für die Spielentwicklung verwenden. Das einzige Problem ist die kardanische Verriegelung. Wenn du ein Spieleentwickler sein willst, brauchst du Mathe an einem Punkt, lerne es.
Bálint
1
"Spieleentwickler" und "kein Mathematikstudium" ist ein Widerspruch.
Margaret Bloom
2
Ich weiß zu schätzen, was Sie mit der Frage anfangen wollen, aber die Antworten sollten eine Antwort sein, nicht die Frage. Erstellen Sie eine "Zusammenfassung", wenn Sie der Meinung sind, dass es sich lohnt, sie zusammenzustellen.
Grund

Antworten:

23

Multiplikation

Zumindest im Hinblick auf die Implementierung von Quaternions durch Unity ist die in der Frage beschriebene Multiplikationsreihenfolge nicht korrekt. Dies ist wichtig, da die 3D-Drehung nicht kommutativ ist .

Wenn ich also ein Objekt drehen möchte, indem ich rotationChangevon dem Objekt currentOrientationausgehe, würde ich es folgendermaßen schreiben:

Quaternion newOrientation = rotationChange * currentOrientation;

(dh Transformationen stapeln sich bis zur linken Seite - genau wie bei der Unity-Matrixkonvention. Die Drehung ganz rechts wird zuerst / am "lokalsten" Ende angewendet.)

Und wenn ich eine Richtung oder einen Versatzvektor um eine Drehung transformieren wollte, würde ich das so schreiben:

Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;

(Unity erzeugt einen Kompilierungsfehler, wenn Sie das Gegenteil tun.)

Mischen

In den meisten Fällen kommt man mit Lerping-Rotationen davon. Dies liegt daran, dass der Winkel, der "unter der Haube" in einem Quaternion verwendet wird, halb so groß ist wie der Drehwinkel, wodurch er der linearen Annäherung von Lerp wesentlich näher kommt als so etwas wie eine Matrix (die im Allgemeinen nicht gut funktioniert!). Weitere Erklärungen finden Sie in ca. 40 Minuten in diesem Video .

Der einzige Fall, in dem Sie Slerp wirklich brauchen, ist, wenn Sie im Laufe der Zeit eine konstante Geschwindigkeit benötigen, z. B. das Interpolieren zwischen Keyframes auf einer Animationszeitleiste. In Fällen, in denen es Ihnen nur wichtig ist, dass eine Ausgabe zwischen zwei Eingaben liegt (wie das Mischen von Ebenen einer Animation), eignet sich Lerp normalerweise sehr gut.

Was sonst?

Das Skalarprodukt zweier Einheitsquaternionen gibt den Kosinus des Winkels zwischen ihnen an, sodass Sie das Skalarprodukt als Maß für die Ähnlichkeit verwenden können, wenn Sie Rotationen vergleichen müssen. Dies ist allerdings etwas undurchsichtig, sodass ich für besser lesbaren Code häufig Quaternion.Angle (a, b) verwende, was deutlicher ausdrückt, dass wir Winkel in vertrauten Einheiten (Grad) vergleichen.

Diese Arten von praktischen Methoden, die Unity für Quaternions bereitstellt, sind sehr nützlich. In fast jedem Projekt verwende ich dieses mindestens ein paar Mal :

Quaternion.LookRotation(Vector3 forward, Vector3 up)

Dies bildet eine Quaternion, die:

  • Dreht die lokale z + -Achse, um genau auf das forwardVektorargument zu zeigen
  • Dreht die lokale y + -Achse, um so nah wie möglich an das upVektorargument zu zeigen, sofern dies angegeben oder (0, 1, 0)weggelassen wird

Der Grund, warum das "Auf" nur "so nah wie möglich" kommt, ist, dass das System überbestimmt ist. Wenn forwardwir z + gegenüberstellen, um zwei Freiheitsgrade (dh Gieren und Nicken) zu verbrauchen, bleibt uns nur ein Freiheitsgrad (Rollen).

Ich finde ziemlich oft, dass ich etwas mit den entgegengesetzten Genauigkeitseigenschaften möchte: Ich möchte, dass lokales y + genau entlang upzeigt und lokales z + forwardmit der verbleibenden Freiheit so nahe wie möglich kommt .

Dies ist zum Beispiel der Fall, wenn Sie versuchen, einen kamerarelativen Koordinatenrahmen für die Bewegungseingabe zu erstellen: Ich möchte, dass meine lokale Aufwärtsrichtung senkrecht zum Boden oder zur Normalen der geneigten Oberfläche bleibt, damit meine Eingabe nicht versucht, den Charakter in das Gelände zu tunneln oder schweben sie davon ab.

Dies kann auch der Fall sein, wenn das Turmgehäuse eines Panzers auf ein Ziel gerichtet sein soll, ohne sich beim Zielen nach oben / unten vom Panzerkörper abzuziehen.

Dazu können wir unsere eigene Komfortfunktion aufbauen, die LookRotationfür das schwere Heben verwendet wird:

Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
    Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
    Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);

    return rotateZToUp * rotateYToZ;
}

Hier drehen wir zuerst das lokale y + zu z + und das lokale z + zu y-.

Dann drehen wir das neue z + in unsere Aufwärtsrichtung (so dass das Nettoergebnis lokal y + zeigt direkt entlang exactUp) und das neue y + so nah wie möglich an der negierten Vorwärtsrichtung (so dass das Nettoergebnis lokal z + zeigt so nah wie möglich entlang) approximateForward)

Eine andere praktische Bequemlichkeitsmethode Quaternion.RotateTowards, die ich oft so benutze:

Quaternion newRotation = Quaternion.RotateTowards(
                             oldRotation, 
                             targetRotation,
                             maxDegreesPerSecond * Time.deltaTime
                         );

Auf diese Weise können wir targetRotationunabhängig von der Framerate mit einer konstanten, steuerbaren Geschwindigkeit näherkommen - wichtig für Rotationen, die das Ergebnis / die Fairness der Spielmechanik beeinflussen (wie das Drehen der Bewegung eines Charakters oder das Einfahren eines Turmes auf dem Spieler). Naives Lerping / Slerping in dieser Situation kann leicht zu Fällen führen, in denen die Bewegung bei hohen Frameraten schneller wird und die Spielbalance beeinträchtigt. (Das heißt nicht, dass diese Methoden falsch sind - es gibt Möglichkeiten, sie korrekt anzuwenden, ohne die Fairness zu ändern. Sie erfordern lediglich Sorgfalt. Es RotateTowardsgibt eine praktische Verknüpfung, die dies für uns erledigt.)

DMGregory
quelle
Tipp: Fügen Sie & t = 40m zum Ende der Video-URL hinzu, damit sie direkt dort abspringt (optional z. B. 40m5s). Quaternion-Dot-Produkte eignen sich auch für sphärische Spielwelten - oder allgemeiner für die Ausrichtung von rotierenden Kugelstücken.
Luke Briggs
@Luke Briggs: Der Punkt der sphärischen Spielwelt hört sich so an, als ob es sich lohnen würde, in einer eigenen Antwort (insbesondere mit Diagrammen) näher darauf einzugehen, wenn Sie dazu bereit wären. :)
DMGregory
Tolle Idee - hier ist es 3 Uhr morgens (also denke ich, es würde ein bisschen Kauderwelsch rauskommen!), Aber ich würde mich freuen, morgen etwas zusammenzubekommen (wenn ich mich erinnere!)
Luke Briggs
1
Edit: Ich habe ein wenig mitgerissen darüber nachzudenken, eine Antwort, also Herausforderung angenommen! Ich werde es zumindest als grobkörnig markieren, damit die Leute wissen, dass es spät in die Nacht ging: P
Luke Briggs
Da gehen wir! Ich habe versucht, es in einem grafischen Überblick zu behandeln, auf der Grundlage, dass Ihre Antwort die zugrunde liegenden Funktionen bereits sehr gut abdeckt. Zeit für etwas Schlaf, denke ich!
Luke Briggs
14

Wo wird das Skalarprodukt verwendet?

In Unity ist einer der häufigsten Benutzer des Skalarprodukts immer dann, wenn Sie über ==oder prüfen, ob zwei Quaternionen gleich sind !=. Unity berechnet das Skalarprodukt, um die Ähnlichkeit zu überprüfen, anstatt die internen x-, y-, z- und w-Werte direkt zu vergleichen. Es lohnt sich, dies zu bedenken, da es den Anruf teurer macht, als Sie vielleicht erwarten.

Wir verwenden es auch in einem interessanten Anwendungsfall.

Spaß mit Quaternion Dot Produkten - Sphärische Welten und Orbitale

Simulationen ganzer Planeten und sogar ganzer Sonnensysteme werden immer häufiger. Um dies in Echtzeit umzusetzen, benötigen wir auch das Quaternion Dot-Produkt. Viele von ihnen. Das Quaternion-Dot-Produkt ist sehr wenig genutzt, hat aber durchaus seine Verwendungsmöglichkeiten - Schauen wir uns das an!

Erstens müssen wir eine ganze Reihe von Rotationen berücksichtigen:

  1. (Optional) Der Stern um das galaktische Zentrum
  2. Der Planet um den Stern
  3. Die Neigung des Planeten
  4. Der Spin des Planeten
  5. Die Position von Gitterzellen in der Nähe (gedreht um den Planetenkern) *
  6. Mehrere Umlaufbahnebenen

Kombinieren Sie sie alle zusammen und Sie erhalten eine Menge Komplexität (und eine Menge riesiger Zahlen!). Wenn der Betrachter auf der Oberfläche des Planeten steht, wollen wir nicht, dass sie mit einer verrückten Geschwindigkeit durch unseren Spielweltraum rasen. Wir möchten, dass sie stationär sind und sich irgendwo in der Nähe des Ursprungs befinden. Bewegen Sie das Universum stattdessen um den Spieler.

Rotierender Planet

Wichtig ist, dass wir, damit wir in diesem Szenario in der Lage sind, die Drehung und Neigung des Planeten richtig zu machen, die Stange in der Achse arretieren müssen, damit sie auf dem obigen Bild nur auf- und abschwingen kann (dh aufschwingen, wenn sich der Spieler bewegt) Norden). Hier kommt ein Quaternion Dot-Produkt ins Spiel. Wenn wir hier kein Dot-Produkt verwenden und stattdessen auch nur die Neigung multiplizieren würden, würde dies passieren:

Falsch geneigte "Planeten"

Beachten Sie, wie die Pole unserer umlaufenden "Planeten" immer in Richtung des Sterns geneigt sind. Dies ist nicht das, was in der Realität passiert - die Neigung ist in eine feste Richtung .

Hier eine kurze Zusammenfassung, ohne zu weit vom Thema abzuweichen:

  • Auf einer Kugel beschreibt eine Orientierung auch genau eine Oberflächenposition.
  • Wir müssen viele Rotationen miteinander kombinieren.
  • Beschreibe alles als Rotation; auch die Position des Betrachters. Dies trägt zur Leistungssteigerung bei, da letztendlich weniger Operationen ausgeführt werden.
  • Der Winkel zwischen den Umdrehungen (unser Skalarprodukt) hilft dann beim Messen der Länge und eignet sich besonders für den Umgang mit Neigungen.

Indem wir nur den Winkel erhalten, lassen wir einen Teil dieser unerwünschten Drehung fallen . Gleichzeitig haben wir eine Längenmessung durchgeführt, die sowohl für die Navigation als auch für das lokale Klima nützlich ist.

* Planeten bestehen aus vielen Gitterzellen . Es werden nur die in der Nähe befindlichen angezeigt.

Luke Briggs
quelle
2
Dies macht einen großartigen Job, um die Szene zu setzen und das Problem zu motivieren, aber ich bin immer noch ein bisschen unsicher, wie die Mathematik des Quaternion Dot-Produkts (dh des Skalarprodukts dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.wim Gegensatz zur Quaternion- Zusammensetzung, die wir zum Verketten verwenden würden) funktioniert Rotationen) würde uns helfen, dieses Problem zu lösen. Ich würde mich freuen, wenn Sie dies etwas später erläutern können (ich möchte Sie nicht von Ihrem Slerp fernhalten ... ich meine den Schlaf!)
DMGregory
@DmGregory die kurze Antwort ist Tilt ist die ungerade; alles ist gut komponiert, bis auf das eine (der Planet scheint sonst um seinen Stern zu wackeln). Ich werde (hoffentlich!) Morgen etwas mehr Kontext hinzufügen!
Luke Briggs
@DMGregory Ich habe einige zusätzliche Informationen hinzugefügt (ich konnte nicht schlafen!) - hoffentlich macht das es klarer.
Luke Briggs
1
Es tut mir leid, wenn ich ein bisschen dicht bin, aber nach mehrmaligem Nachlesen weiß ich immer noch nicht, wie ich das Skalarprodukt in einer Formel verwenden würde, um die von Ihnen beschriebene Transformation zu erreichen. Könnten Sie einen kleinen Pseudocode hinzufügen, in dem die von Ihnen explizit ausgeführten Vorgänge aufgeführt sind?
DMGregory
@DMGregory Ich kenne die Quaternionen nicht, aber wenn dies Rotationen auf einer Kugel sind, dann sind dies keine Rotationskompositionen. Hierbei wird eine sphärische Geometrie mit Vektoren verwendet, um den Normalenvektor für eine "Linie" auf der Oberfläche einer Kugel AKA eines beliebigen Umfangs zu berechnen. Wiederum macht die Antwort wenig Sinn und auch diese Frage nicht, aber ich glaube, sie verwenden sphärische Geometrie.
Die große Ente