Auflösen einer Kollision mit Kräften

14

In meiner 2D-Physik-Engine kann ich AABB-gegen-AABB-Kollisionen erkennen und beheben, indem ich den kürzesten Penetrationsvektor finde und ihn zur Position der AABB hinzufüge.

Dadurch wird der erste AABB außerhalb des zweiten AABB "gedrückt", es werden jedoch überhaupt keine Geschwindigkeits- / Beschleunigungsänderungen behandelt.

Wenn ich meiner Simulation eine Schwerkraftbeschleunigung hinzufüge, wächst die Geschwindigkeit des ersten dynamischen AABB weiter, selbst wenn er auf dem zweiten statischen AABB aufliegt. Schließlich wird die Geschwindigkeit zu groß und die Kollision wird nicht erkannt (der dynamische AABB fällt durch den statischen).

Ich habe versucht, die Geschwindigkeit nach dem Auflösen auf Null zu setzen, aber es hat offensichtlich nicht gut funktioniert und unrealistische Simulationen erstellt.

Ich habe online gelesen, dass das Auflösen von Kollisionen durch manuelles Bearbeiten der Position oder der Geschwindigkeit nicht korrekt ist. Ich habe versucht, Kräfte zu implementieren (Masse ist vorerst eine "fest codierte" 1):

void Body::applyForce(sf::Vector2f mForce) { acceleration += mForce; }

void Body::integrate(float mFrameTime)
{
    velocity += acceleration * mFrameTime;
    position += velocity * mFrameTime;

    acceleration = {0, 0};
}

Wenn ich während der Kollisionsauflösung den kürzesten Eindringvektor als Kraft anwende, wird der dynamische AABB aus dem statischen "herausgedrückt", aber seine Geschwindigkeit wird in einer Simulation ohne Schwerkraft niemals abnehmen und er wird für immer in Bewegung bleiben.

Gibt es eine Möglichkeit, eine "temporäre" Kraft anzuwenden? Eine Kraft, die sich mit dem Herausdrücken des ersten AABB aus dem zweiten AABB befasst und dann aufhört, wenn der AABB nicht mehr kollidiert?

Der gesamte Quellcode ist hier verfügbar: https://github.com/SuperV1234/SSVSCollision

Vittorio Romeo
quelle
1
Das interessiert mich. Haben Sie schon eine Lösung gefunden?
TravisG
@ TravisG: leider noch nicht. Ich werde morgen ein Kopfgeld hinzufügen, wenn ich keine Antwort bekomme.
Vittorio Romeo
Kraft ist zuallererst nicht gleich Beschleunigung. Sie benötigen Masse, um die Beschleunigung zu berechnen. Wenn Sie die Positionen ändern, um das Eindringen der beiden Körper zu verhindern, sollten Sie auch die Masse verwenden und beide Körper darauf basierend bewegen. Das Anlegen einer Kraft, die dem Eindringvektor entspricht, ist nicht sinnvoll. Box2D basiert auf Impulsen, arbeitet direkt mit Geschwindigkeiten, ist zwar nicht "korrekt", aber gut genug. Der Umgang mit Geschwindigkeitsänderungen in einem impulsbasierten Motor ist sehr einfach. Geben Sie also an, ob Sie definitiv eine kraftbasierte Lösung wünschen oder ob die wesentlich einfachere impulsbasierte Lösung gut genug ist.
Dreta
Persönlich würde ich vorschlagen, ein Buch über Physik-Engines zu lesen, zumindest die ersten Kapitel über die Newtonsche Physik. Ihre Annahmen sind falsch und der Versuch, diese Frage zu beantworten, würde bedeuten, dass Sie Grundlagen der Physik lernen müssen, während Sie versuchen, Algorithmen auf hoher Ebene zur Lösung von Kollisionen zu erklären.
dreta
@dreta seine annahmen sind in ordnung. Er wies darauf hin, dass seine Masse für alle Objekte im Moment einfach "1" ist, was seine Codeabschnitte gültig macht. Übrigens, obwohl Box2D direkt mit Geschwindigkeiten umgehen kann, muss es sich irgendwie um dasselbe Problem handeln. Wenn Box2D keine Kraft ausübt, sondern einen Impuls ausübt, muss es trotzdem irgendwie damit umgehen, dass der Impuls nicht einfach verschwindet, sobald die Objekte getrennt sind. Obwohl es möglich ist, dass es tatsächlich überhaupt nicht damit
fertig wird

Antworten:

13

Zunächst empfehle ich, eine kostenlose Open-Source- Physikbibliothek wie Box2D zu verwenden und mich nur auf die Aspekte Ihres Spiels zu konzentrieren, die es einzigartig machen! Wenn Sie darauf bestehen, das Rad neu zu erfinden, lesen Sie weiter ... Beachten Sie, dass es sich bei allen Physik-Motoren um Näherungswerte handelt. Die unten beschriebene Methode ist zwar genauer als Ihr aktuelles Modell, die Ergebnisse von Box2D sind jedoch weitaus realistischer.


So modellieren Sie schnell eine genauere Kollisionsauflösung von zwei Objekten A und B:

  1. Finde die Positionen kurz vor der Kollision. Sie approximieren dies bereits, indem Sie "den kürzesten Penetrationsvektor finden und ihn zur Position der AABB addieren".
  2. Finden Sie die Geschwindigkeiten direkt nach der Kollision mit der Newtonschen Physik :
    • Für den Fall, dass die Masse fest mit 1 codiert ist, tauschen Sie einfach die Geschwindigkeiten aus (dies gilt nicht für statische Objekte, die eine unendliche Masse haben müssen):
      • Av = Bu
      • Bv = Au
    • Wenn die Objekte A und B unterschiedliche Massen haben:
      • Av = (Au * (Am - Bm) + (2 * Bm * Bu)) / (Am + Bm)
      • Bv = (Bu * (Bm - Am) + (2 * Am * Au)) / (Am + Bm)
    • wo:
      • v: Geschwindigkeit nach der Kollision
      • o: Geschwindigkeit vor der Kollision
      • m: Masse (Verwenden Sie die größtmögliche Anzahl für die Masse eines festen, statischen Objekts)
  3. Beschleunigung auf 0 setzen: Die Beschleunigung aus der Kollision wurde oben bei den Geschwindigkeitsberechnungen in Schritt 2 berücksichtigt.

Bitte schauen Sie sich mein Beispielprogramm für Asteroiden an, das diese Konzepte demonstriert.


Als nächstes berücksichtigen Sie gestapelte Objekte:

Wie Sie bemerkt haben, funktioniert die Verwendung von Geschwindigkeit zur Simulation gestapelter / ruhender Objekte nicht gut: Geschwindigkeit ist die Geschwindigkeit, mit der sich ein Objekt bewegt. Wenn es sich also auf einem statischen Objekt befindet, sollte die Geschwindigkeit nahe 0 sein. Es ist nicht sinnvoll, die Geschwindigkeit zu erhöhen Die Geschwindigkeit eines Objekts, um es in Ruhe erscheinen zu lassen:

Wenn ich meiner Simulation eine Schwerkraftbeschleunigung hinzufüge, wächst die Geschwindigkeit des ersten dynamischen AABB weiter, selbst wenn er auf dem zweiten statischen AABB aufliegt. Schließlich wird die Geschwindigkeit zu groß und die Kollision wird nicht erkannt (der dynamische AABB fällt durch den statischen).

Was wirklich passieren sollte, ist eine Beschleunigungskraft, die in die entgegengesetzte Richtung geht, da die Schwerkraft die Schwerkraft aufheben sollte. (Dies wird als normale Kontaktkraft bezeichnet). Eine Abkürzung ist, einfach keine Schwerkraft auf Körper anzuwenden, die nicht in der Luft sind:

  • Eine Methode, dies zu tun, besteht darin, einen "geerdeten" Zustand beizubehalten:
    • Wenden Sie keine Schwerkraft auf geerdete Gegenstände an.
    • Wenn ein Objekt von unten mit einem Objekt kollidiert und seine Geschwindigkeit sehr gering ist, geht es in den geerdeten Zustand über.
    • Ein Objekt verlässt den Grundzustand, wenn seine Vertikalgeschwindigkeit einen bestimmten positiven Wert überschreitet.

Aktualisieren:

  • In Laienbegriffen sagt die Newtonsche Physik, dass die Gesamtenergie vor und nach einer Kollision übereinstimmen muss. Wenn zwei Objekte ineinander stoßen, wird ihre Energie neu verteilt. Energie ist eine Kombination aus Geschwindigkeit und Gewicht: Schwere, schnellere Dinge haben mehr Energie. Das ist intuitiv. Was jedoch nicht intuitiv ist, ist die genaue Art und Weise, wie Gewichte die Energieumverteilung beeinflussen.
  • Das Tauschen von Geschwindigkeiten ist nur eine Abkürzung für zwei dynamische, nicht fixierte Körper mit derselben Masse (statische, feste Objekte haben sehr große, unendliche Massen).
  • Die Abkürzung, wenn ein statischer Körper fixiert ist, lautet: Der andere dynamische, nicht fixierte Körper behält die gleiche Geschwindigkeit bei; Nur der Winkel wird geändert (stellen Sie sich einen Billardtisch vor, wenn eine Kugel auf die Schiene trifft. Die Schiene hat im Wesentlichen eine sehr große, unendliche Masse).
  • In anderen Fällen, wie bei drei oder mehr Objekten, müssen die vollständigen Newtonschen Bewegungsgleichungen gelöst werden (Impulserhaltung und Erhaltung der kinetischen Energie).
  • Ich bin nicht sicher, ob die Newtonschen Bewegungsgleichungen für mehr als zwei Körper gelöst werden können. Glücklicherweise kollidieren jedoch drei Objekte fast nie genau zur gleichen Zeit. Es ist ausreichend, die ersten beiden kollidierenden Körper zu behandeln und dann alle folgenden Kollisionen mit den neuen Geschwindigkeiten aus den vorherigen Kollisionsauflösungen zu behandeln. Dies ist ein guter Grund, um die Zeitschritte Ihrer Physik so gering wie möglich zu halten und Kollisionen zu bewältigen, bevor Penetrationen auftreten.
  • Sie werden feststellen, dass in meiner Asteroiden-Demo viele Körper erzeugt werden, wenn größere Steine ​​in kleinere aufgeteilt werden. Ich behandle jedoch immer Kollisionen zwischen Körperpaaren; Behandle niemals explizit eine Kollision mit mehr als zwei Körpern.
Leftium
quelle
Danke für die ausführliche Antwort. Es gibt jedoch etwas, das ich nicht verstehe: Tauschgeschwindigkeiten funktionieren gut bei einer Kollision mit zwei Körpern - ich verstehe jedoch nicht, wie es funktionieren kann, wenn mehrere Körper (und auch statische Körper) gleichzeitig kollidieren. Selbst ohne Schwerkraft verursacht es Probleme, wenn ein dynamischer Körper gleichzeitig mit einem statischen Körper und einem anderen dynamischen Körper kollidiert. Da die Geschwindigkeit vertauscht ist, hängt alles von der Reihenfolge der Kollision ab. Wenn der statische Körper zuletzt kollidiert, hört der Körper auf, sich zu bewegen. Wenn dies der Fall ist, bewegt sich der Körper wieder. Wie ist das behoben?
Vittorio Romeo
@Vee: Gute Fragen! Drei + Körper und statische Körper sind zwei getrennte Themen. Ich habe beide in einem Update angesprochen. Zusammenfassung: Behandeln Sie Kollisionen von zwei Objekten gleichzeitig. statische Körper haben eine sehr große, unendliche Masse.
Leftium
Ihr Modell zum Ausruhen von Kontakten ist ungerade. Ruhekontakte sind nicht nur für die Schwerkraft gedacht, sie sollten für jede Kraft funktionieren. Die einfachste Möglichkeit besteht darin, die Geschwindigkeit, die durch die Beschleunigung im vorherigen Frame beim Kontakt gewonnen wurde, einfach zu entfernen. Auch bei kleinen Geschwindigkeiten können Sie die Rückgabe vollständig entfernen, obwohl Ihre Berechnungen die Rückgabe nicht berücksichtigen. Dieser Ansatz funktioniert für alle Kräfte, ist einfach zu implementieren und sieht gut genug aus.
Dreta
16

Um dieses Problem zu lösen, müssen Position und möglicherweise Geschwindigkeit angepasst werden. Rigid-Body-Physics-Engines verfügen über einen Solver, mit dem Objekte unter Verwendung der Newtonschen Bewegungsgesetze zeitlich vorwärts bewegt werden und gleichzeitig Nicht-Penetrations-Beschränkungen und Reibung gelöst werden. Diese Motoren können die richtige Kombination aus linearen und winkligen Bewegungen berechnen, um plausible Flugbahnen zu erstellen.

Wenn Sie nur Überlappungen auflösen möchten, können Sie Pseudo-Geschwindigkeiten verwenden, die Trenntrajektorien erzeugen, ohne den Schwung zu erhöhen. Dies geschieht im Positionslöser von Box2D.

Ich empfehle meine GDC-Präsentationen von 2006 und 2007 hier zu bekommen:

http://code.google.com/p/box2d/downloads/list

Sie können sich auch Box2D Lite für eine vereinfachte Implementierung ansehen.

Erin Catto
quelle
+1 für die Bemerkung, dass auch die Position angepasst werden muss. Nur wenige Leute geben sich damit zufrieden, aber um die Stabilität der Simulation zu erhöhen, schummeln die meisten Motoren, indem sie die Positionen direkt anpassen. Alles in allem funktioniert es für Spiele, wenn es plausibel ist.
Teodron
Danke für die Antwort. Ich wollte etwas wissen, was ich wahrscheinlich in der Präsentation verpasst habe: Werden statische Körper in Box2D auf besondere Weise behandelt? Ich meine - was passiert, wenn ein dynamischer Körper auf einen statischen Körper trifft?
Vittorio Romeo
2

Bildbeschreibung hier eingeben

In der realen Welt gibt es keine Kraft, die einen Körper aus einem anderen "herausdrückt", weil Objekte sich nie gegenseitig durchdringen. Das Nächste ist die Normalkraft : Sie entsteht im Moment des Kontakts bei realen Kollisionen und verhindert das Eindringen.

Der Winkel dieser Normalkraft steht senkrecht zur Kontaktfläche der beiden kollidierenden Objekte. Die Größe hängt davon ab, wie viel Kraft erforderlich ist, um ein Eindringen zu verhindern. (Beachten Sie, dass nur die y-Komponente der Normalkraft verwendet werden sollte, es sei denn, andere Kräfte wie die Reibungskraft werden ebenfalls modelliert.)

Während es möglich ist, die Normalkraft explizit zu modellieren, ist es einfacher, nur ihre Auswirkungen zu modellieren:

  1. Verhindern Sie Objektüberschneidungen durch:
    • Anpassen der Geschwindigkeiten durch Beheben von Kollisionen im Moment des Aufpralls. (Beste)
    • Manuelles Anpassen der Positionen der Körper, damit sie sich nicht schneiden. (einfacher) Sie tun dies bereits, "indem Sie den kürzesten Penetrationsvektor finden und ihn zur Position des AABB hinzufügen".
  2. Wenden Sie die Schwerkraft nicht dort an, wo eine normale Kraft die Schwerkraft aufheben würde.
    • Ein Objekt, das mit einem anderen Objekt darunter in Kontakt steht, unterliegt der normalen Kraft. Es geht also darum, diese Objekte im Auge zu behalten. (Tatsächlich sollte auf alle Objekte, die sich in Kontakt befinden, eine normale Kraft ausgeübt werden, aber nicht alle haben einen Nettoeffekt in Bezug auf die Schwerkraft.)
    • Wenn Sie Objekte hinzufügen möchten, die andere schräg nach unten gleiten können, müssen Sie die Reibungskraft und die x-Komponente der Normalkraft hinzufügen.

Ich habe dies in meiner anderen Antwort, die sich eher auf Kollisionen im Allgemeinen bezieht, etwas anders beschrieben .

Leftium
quelle