Mein Spiel muss sich um einen bestimmten Winkel bewegen. Dazu erhalte ich den Vektor des Winkels über sin und cos. Leider sind Sünde und Kosten mein Engpass. Ich bin mir sicher, dass ich nicht so viel Präzision brauche. Gibt es eine Alternative zu einem C sin & amp; Cos und Look-Up-Tabelle, die anständig ist, aber sehr schnell?
Ich hatte das gefunden:
%Vor%Leider scheint das nicht zu funktionieren. Ich erhalte ein signifikant anderes Verhalten, wenn ich diese Sünde anstelle von C sin verwende.
Danke
Für Ihre fastSin()
sollten Sie in der Dokumentation nachsehen, für welchen Bereich sie gültig ist. Die Einheiten, die du für dein Spiel verwendest, könnten zu groß oder zu klein sein und sie so skalieren, dass sie in den erwarteten Bereich dieser Funktion passen, könnte es besser machen.
BEARBEITEN:
Jemand anders hat erwähnt, dass man ihn in den gewünschten Bereich bringen kann, indem man PI subtrahiert, aber anscheinend gibt es eine Funktion namens fmod
um Modulo-Divisionen auf Floats / Doubles zu machen, sollte dies Folgendes tun:
Ich habe keine Ahnung, wie teuer fmod
ist, also werde ich als nächstes einen schnellen Benchmark versuchen.
Benchmark-Ergebnisse
Ich habe das mit -O2
kompiliert und das Ergebnis mit dem Programm Unix time
ausgeführt:
Das Ergebnis ist, dass sin
etwa 1,8 mal langsamer ist (wenn fastSin
5 Sekunden dauert, sin
9). Die Genauigkeit schien auch ziemlich gut zu sein.
Wenn Sie diese Route gewählt haben, stellen Sie sicher, dass Sie die Optimierung mit ( -O2
in gcc) durchführen.
Ich weiß, das ist schon ein altes Thema, aber für Leute, die die gleiche Frage haben, hier ist ein Tipp.
Viele Male in 2D- und 3D-Rotation werden alle Vektoren mit einem festen Winkel gedreht. Anstatt die cos()
oder sin()
für jeden Zyklus der Schleife aufzurufen, erstellen Sie eine Variable vor der Schleife, die bereits den Wert cos(angle)
oder sin(angle)
enthält. Sie können diese Variable in Ihrer Schleife verwenden. Auf diese Weise muss die Funktion nur einmal aufgerufen werden.
Sie können eine Tabelle S mit 256 Werten berechnen, von sin (0) bis sin (2 * pi). Um dann sin (x) auszuwählen, bringe x in [0, 2 * pi] zurück, kannst du 2 Werte S [a], S [b] aus der Tabelle auswählen, wie etwa & lt; x & lt; b. Daraus ergibt sich eine lineare Interpolation, und Sie sollten eine gute Annäherung haben
Wenn Sie die Rückgabe in fastSin als
umformulieren %Vor%Und schreibe y als (für x & gt; 0)
um %Vor% Sie können sehen, dass y eine parabolische Näherung erster Ordnung zu sin(x)
ist, die so gewählt ist, dass es (0,0), (pi / 2,1) und (pi, 0) durchläuft. Das y*abs(y)
ist ein "Korrekturbegriff", der diese Punkte ebenfalls durchläuft.
Diese Form der Approximationsfunktion garantiert, dass die Funktion (1-P) * y + P * y * y auch (0,0), (pi / 2,1) und (pi, 0) durchläuft.
Eine Frage ist "Wie wurde P ausgewählt?". Persönlich würde ich das P wählen, das den geringsten RMS-Fehler über das 0, pi / 2-Intervall erzeugte. (Ich bin mir nicht sicher, ob das P gewählt wurde)
Minimiert dies wrt. P gibt
Dies kann für p
neu definiert und gelöst werdenNicht sicher, ob dies zu P = 0,225 kommt oder nicht. Wenn nicht, dann ist dieser Wert von P wahrscheinlich eine Verbesserung. (Es sei denn, der andere Wert von P wurde ausgewählt, um eine andere undokumentierte Eigenschaft zu erhalten).
Sie können die Genauigkeit durch Hinzufügen eines zusätzlichen Korrekturterms erhöhen. geben Sie ein Formular so etwas wie return (1-a-b)*y + a y * abs(y) + b y * y * abs(y)
. Ich würde a
und b
by auf die gleiche Weise wie oben finden, wobei diesmal ein System von zwei linearen Gleichungen in a
und b
zu lösen wäre, anstatt einer einzelnen Gleichung in p
. Ich werde die Ableitung nicht als langwierig und die Umwandlung in Latexbilder ist schmerzhaft ...;)
HINWEIS: Bei der Beantwortung einer anderen Frage habe ich an eine andere gültige Wahl für P gedacht. Das Problem ist, dass die Verwendung von Reflektion, um die Kurve in (-pi, 0) zu erweitern, einen Knick in der Kurve bei x = 0 hinterlässt. Ich vermute jedoch, dass wir P so wählen können, dass der Knick glatt wird. Um dies zu tun, nehmen Sie die linken und rechten Ableitungen bei x = 0 und stellen Sie sicher, dass sie gleich sind. Dies ergibt eine Gleichung für P.
Dies (d. h. die Fastsin-Funktion) approximiert die Sinusfunktion unter Verwendung einer Parabel. Ich vermute, dass es nur für Werte zwischen -π und + π gut ist. Glücklicherweise können Sie 2π addieren oder subtrahieren, bis Sie in diesen Bereich kommen. (Bearbeitet, um anzugeben, was die Sinusfunktion mithilfe einer Parabel approximiert.)