Rotierende Vektoren im Raum und hohe Genauigkeit in C ++

8

Das ist meine Funktion, um 3D-Rotation in C ++ zu berechnen, definiert durch einen Winkel in Radiant um die Achse.

%Vor%

Die Sache ist, wenn du versuchst, den Vektor zu drehen a n mal pi/4 wo n multiple of 4 (damit du die Umdrehung um die Achse durch vier Viertel der Umdrehungen vervollständigst) wird sich der Fehler ziemlich schnell ausbreiten.

Beispiel (wo err = input-output ):

%Vor%

Was kann ich tun?

Einschränkungen:

  • Drehungen sind nicht vorhersehbar, daher ist es nicht möglich, etwas wie angle = pi/4 *n % 2*pi wie @molbdnilo zu tun. Weil ich Übersetzungen und Drehungen ketten muss, um zu testen, ob es eine Kollision gibt.
Deewy 09.08.2017, 12:42
quelle

4 Antworten

0

Am Ende habe ich Rodrigues 'Rotationsformel verwendet und die Leistungen sind viel besser.

Dies ist jedoch nicht die Lösung, da @ComicSansMs darauf hinweist:

  

Vermeiden Sie die Verkettung der Float-Operationen an erster Stelle!

Also war es ok, einen neuen Algorithmus zu kombinieren und Rodrigues Formel zu verwenden.

Ich vermute Fehler bei meiner ersten Matrix-Implementierung.

Vielen Dank für Ihre Antworten und Einsichten.

    
Deewy 10.08.2017, 09:02
quelle
3

Dies ist eines der typischen Probleme, auf die Sie mit float s stoßen können.

Fließkommazahlen sind bei einzelnen Operationen ziemlich genau. Für viele Operationen erhalten Sie garantiert das genaueste Ergebnis, das im Format dargestellt werden kann. Rundungsfehler, die Sie erhalten, sind also ausschließlich auf die Anpassung in die Darstellung zurückzuführen.

Sobald Sie jedoch Gleitkommaoperationen verketten, können sich auch diese Fehler akkumulieren. Wenn Sie Glück haben, können Sie Ihren Algorithmus numerisch stabil machen, so dass sich die Rundungsfehler am Ende gegenseitig aufheben und Sie immer im Ballpark des korrekten Ergebnisses bleiben. Dies zu erreichen kann jedoch eine ziemliche Herausforderung sein, insbesondere für komplexe Berechnungen. Zum Beispiel gibt es in Ihrer speziellen Implementierung viele Möglichkeiten für eine katastrophale Annullierung , die große Rundungsfehler in die Berechnungskette einführt.

Die einfachere Lösung ist: Vermeiden Sie die Verkettung der Float-Operationen an erster Stelle! Oder genauer gesagt: Verketten Sie nur die Teile, die Sie numerisch stabil halten können. Da du erwähnt hast, ist das für ein Computerspiel: In einem Spiel transformierst du die Geometrie entsprechend der Kameramatrix in jeden Frame. Sie berühren niemals die Geometrie im Speicher, sondern passen einfach die Kameramatrix an. Auf diese Weise ist Ihre Quellgeometrie immer frisch und der Rundungsfehler in jedem Frame ist einfach der Fehler dieser einzelnen Transformation.

Sie aktualisieren die Kameramatrix normalerweise nicht inkrementell. Stattdessen lesen Sie die Position des Spielers und betrachten und erstellen die komplette Matrix von Grund auf neu. Jetzt ist die einzige Herausforderung, die Sie noch haben, sicherzustellen, dass Sie keine Fehler in der Spielerposition und -ansicht ansammeln, aber das ist viel einfacher als die Stabilität am anderen Ende der Transformationspipeline sicherzustellen.

    
ComicSansMS 09.08.2017 13:24
quelle
0

Speichern Sie einfach den ursprünglichen Basisvektor und den Rotationswinkel zusammen und führen Sie die Berechnung jedes Mal durch, wenn Sie den aktuellen rotierten Wert benötigen. Sie können dies zwischenspeichern und jedes Mal ungültig machen, wenn sich der Winkel ändert, aber immer funktioniert vom ursprünglichen Basisvektor und der gesamten aggregierten Rotation.

Presto! Keine kumulativen Fehler, weil keine verketteten Berechnungen.

Auch wenn Sie über kumulative Fehler im Winkel selbst besorgt sind, speichern Sie das in Grad und konvertieren Sie bei Bedarf in Radiant. Auch hier wird pi einmal in der Umwandlung Grad- & gt; Radiant berührt, und Sie haben keine Kette von ungefähren pi/n -Werten, die zu mehr Fehlern beitragen.

    
Useless 09.08.2017 13:31
quelle
0

Sie könnten versuchen, Ihre Rotationen zu diskretisieren, so dass sie sich zu Vielfachen von pi / 2 addieren. Sie klemmen Ihren Rotationswert auf den nächsten diskretisierten Wert und führen dann die Berechnung durch. Wenn Sie ein kleines genug finden, wird es immer noch als glatt wahrgenommen und Sie sollten keinen Fehler ansammeln.

    
Philipp 09.08.2017 15:26
quelle

Tags und Links