Kollisionserkennung: eine Reihe von Sonderfällen?

8

Ich schreibe eine einfache Physik-Engine in 2D. Mein erstes Ziel ist es, die Kollisionserkennung zum Laufen zu bringen. Ich weiß, dass meine Objekte irgendwann aus primitiven Formen bestehen werden, aber ich habe mich gefragt, ob eine Kollisionserkennungsbibliothek aus einer Reihe von Sonderfallfunktionen wie "rayAndLine", "rechteckrechteck", "rechteckkreis" usw. bestehen würde oder ist Gibt es ein gemeinsames, zugrunde liegendes Framework für die Kollisionserkennung, das unabhängig davon funktioniert, welche Grundelemente zur Herstellung der Form verwendet werden?

Michael Stachowsky
quelle
Sie fragen nach einem zugrunde liegenden Framework, geben jedoch ausdrücklich an, dass Sie diesen Teil selbst erstellen möchten. Können Sie den letzten Satz klären, in dem Ihre eigentliche Frage gestellt wird, um Ihr Anliegen, sie selbst zu erstellen, genauer von der Verwendung des Frameworks eines anderen zu trennen, das er erstellt hat? Ich werde auch eine Antwort geben.
Joshua Hedges
Gutes Argument. Ich meinte die zugrunde liegende Theorie, aus der die gesamte Kollisionserkennung hervorgeht. Mit anderen Worten, wenn ich ein Kollisionserkennungssubsystem schreibe, muss ich eine Funktion für jeden Typ einer primitiven / primitiven Kollision schreiben, oder gibt es eine einzelne generische Funktion, die unabhängig vom Primitiv funktioniert?
Michael Stachowsky
Art von. Ich habe es gerade beantwortet. Es gibt einige, die Lösungen sehr gut verallgemeinern, wie SAT für jedes konvexe Polygon funktioniert und jedes konkave Polygon in konvexe Polygone zerlegt werden kann, wodurch es für jedes Polygon mit etwas Arbeit funktioniert. Danach müssten Sie sich auf Kurven, Kugeln und Ovale spezialisieren. Ich habe es unten skizziert. Es ist ein großes Thema, also ist es lang. Lassen Sie mich wissen, wenn Sie Fragen zu Einzelheiten oder etwas anderem haben
Joshua Hedges
2
Diese vorherige Frage zum Abstrahieren verschiedener Formtypen könnte ebenfalls nützlich sein.
DMGregory
1
Je mehr gemeinsam genutzter Code, desto besser. Wenn Sie jemals das Kopieren und Einfügen verwenden, überprüfen Sie sich ernsthaft!
CorsiKa

Antworten:

9

Die Kollisionserkennung zum Laufen zu bringen, ist ein großartiges erstes Ziel für Ihre 2D-Physik-Engine. Es ist gut, dass Sie sich entschieden haben, dass Sie im Moment speziell in 2D arbeiten, da nicht jede Regel in 2D in 3D funktioniert, trotz der Menge an n-dimensionalen Algorithmen. Irgendwann müssen Sie sie spezialisieren (mehr tun) spezifische Variante, wie Kreuzprodukt nur die Jacobi-Identität in 3D erfüllt).

Ihre Frage bezieht sich von Natur aus auf Architektur und Framework-Design, nicht auf die 2D-Physik. Daher geht es darum, was Ihr Gebäude für die Verwendung dieser Teile in Ihrem Kopf trennen sollte. Im Wesentlichen müssen Sie die Mentalität beim Erstellen der Engine / Bibliothek / des Frameworks von der Verwendung in einem anderen Projekt trennen.

Architektur von Lösungs-Engines: Mit jeder Mathematik-Engine möchten wir im Wesentlichen Werte in eine Funktion einfügen, und wir erwarten, dass die herauskommenden Werte für eine interessante Simulation nützlich sind.

Die Kernelemente dieses Prozesses sollten so abstrakt wie möglich sein, während die atomaren Elemente (kleinste nützliche Daten / Methoden) für einzelne Zwecke spezifisch und nützlich sein sollten, um zusammen zu komponieren. In unserem Fall ist fast das einzige nützliche Atom ein 2D-Vektor, der eine einzelne Objektklasse sein sollte, die den Ausdruck einer (x, y) -Struktur ermöglicht, und über Methoden für alle grundlegenden mathematischen Operationen verfügt, die für Vektorberechnungen in 2D nützlich sind. Addition, Subtraktion, Normalisierung, Normal (senkrecht), Kreuzprodukt, Punktprodukt, Größe / Länge und alles, was Ihnen sonst noch begegnet, das speziell Vektor -> Vektoroperationen oder Vektor -> reelle Zahlenoperationen eigen ist. Wenn Sie eine klassenbasierte Sprache verwenden, ist eine einfache class Vectormit jeder dieser Sprachen als Elementfunktion oder Operatorüberladung sehr gut geeignet.

Nachdem alle Atomtypen konstruiert wurden, würden Sie ihre Algorithmen in einer weiteren Ebene über unserem Atomtyp zusammensetzen Vector. Mein Ziel wäre ein Lineund ein Curve. Wir werden hier entscheiden, dass a Curveaußerhalb des Anwendungsbereichs liegt und viel Spezialisierung erfordert (das Konzept, das Sie oben als Erstellen vieler Sonderfallfunktionen bezeichnen). Von Vectorwürde ich auch ein Rectangleals 4- VectorPrimitiv komponieren, Circleaus dem Vektor mit a Vectorund a radiuskomponieren und dann würde ich auch ein Polygonvon komponieren Vector. Polygonsollte von Vectorund nicht Linehier gemacht werden, da jede Linie einen doppelten Punkt mit der letzten Linie im Polygon teilen würde.

Jetzt haben Sie Formen, aber wir wissen nicht, was wir damit machen sollen.

Kollisionserkennung Die Kollisionserkennung ist keine exakte Wissenschaft und es gibt keinen einzigen perfekten Algorithmus (oder einen). Es gibt viele Methoden, mit denen eine Vielzahl von Effektqualitäten erzielt werden kann oder die sogar genauer sind als andere. Grundsätzlich kann es jedoch in einige unterschiedliche Anliegensebenen und damit in einige unterschiedliche Prozesse unterteilt werden.

Bei der Erkennung breiter Phasenkollisionen werden Bereiche unterteilt, in denen wir uns darum kümmern, was möglicherweise / könnte / tut, und diese für den Schmalphasenprozess trennen. In 2D würde ich normalerweise empfehlen, dafür einen Quad-Baum zu verwenden. Dafür brauchen Rectanglewir unser früher gebautes und um es mit einer AABB-Kollisionserkennung auszustatten. Dies steht für Axis Aligned Bounding Box und wir werden es verwenden, um zu bestimmen, dass für eine nicht rotierende Box Akein Teil der Box darin Bvorhanden ist A. Es folgt aus der Annahme, dass kein Teil von Binnerhalb Aeiner Kollision existieren kann, wenn sie sich überschneiden.

Ein Quad-Baum ist ein rekursiver Prozess, bei dem Sie eine maximale Tiefe bestimmen oder Ihrer Objektmenge erlauben, stattdessen eine unendliche Rekursionstiefe zu verhindern. Es gruppiert Physikkörper in 4 Regionen (daher der Name) und sollte es Ihnen ermöglichen, auf jedes Quad separat zuzugreifen. Sie würden dann in jedes dieser vier Quads eintreten und denselben Prozess ausführen, den ich hier der Kürze halber nicht skizziere, der jedoch hier verfügbar ist: https://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees- wahrscheinliche Kollisionen im 2D-Raum zu erkennen - gamedev-374

Enge Phasenkollisionist der Prozess des Durchlaufens Ihrer Gruppen von Formen, von denen wir bereits festgestellt haben, dass sie kollidieren werden / könnten / tun, und der Durchführung einer diskreteren Kollisionsprüfung. Zu diesem Zeitpunkt kümmern wir uns darum, ob sich die Objekte drehen oder nicht (ich habe gewonnen). Wenn Sie diese Kollisionsphasen durchlaufen haben, untersuchen Sie, ob Sie eine Kollision mit Drehimpuls erkennen und welche Form ihr Kollisionskörper tatsächlich hat. Um diesen Teil der Kollision auszuführen, würden Sie Ihre Methoden wie oben beschrieben spezialisieren (bestimmte Funktionen für AABBvsCircle, OBBvsCircle, CirclevsCircle, PolygonvsPoint, PolygonvsCircle, PointvsCircle usw. erstellen). Diese Methoden selbst können jedoch auch in mehreren Ebenen ausgeführt werden wie oben.

Ihre primitive Trennung Kontrollen sind die diskreten, spezialisierten Kollisionserkennungsverfahren oder allgemeine Art wie SAT je nach Anwendungsfall und alle sollte einfach zurückgeben entweder einen Wahr / Falsch - Wert, oder gibt ein relationales Objekt wie einen Manifold, Joint, CollisionObjectusw. , die eine Verbindung haben würde Die beiden Formen kollidieren und alle Informationen über sie sind zur Lösung der Kollision erforderlich, z. B. wie tief sie kollidieren oder mit welcher Geschwindigkeit (welche Daten Sie in Ihrem Verteiler benötigen, hängt von der verwendeten Auflösungsmethode ab). Dieses Objekt übergeben Sie dann an ein Objekt, Solverdas die Unterschiede zwischen all den verschiedenen Formen, die kollidieren könnten, abstrahieren sollte, indem Sie nur ein Manifoldund keine bestimmten Informationen über die Formen akzeptieren.

Zusammenfassung Der Solverwird das Manifolddurch Kollision eines Primitivs Amit einem Primitiv erzeugte nehmen B, wobei zuerst eine breite Phasengruppierung (alle gegen Welt) und dann eine Schmalphasendetektion (A gegen B) verwendet werden. Wenn Formen nicht polygon sind, muss das Solverdann entweder neu erzeugt werden Vectors für die Positionen und Geschwindigkeiten der kollidierten Formen oder für ein Objekt, mit dem das PhysicsEnvironmentoder Worlddann die Kollision seiner untergeordneten Elemente auflösen kann, aktualisieren Sie das QuadTreeund wiederholen Sie diesen Vorgang im nächsten Frame. Wenn beide kollidierenden Formen Polygone sind, sollte die Spezialisierung nur unter Berücksichtigung einer Leistungssteigerung erfolgen, andernfalls einfach unter Verwendung des Trennachsensatzes

Joshua Hedges
quelle
1
Tolle Antwort, danke. Ich bin jedoch neugierig: Ich hatte ursprünglich überlegt, mein primitivstes Objekt auf den Punkt zu stützen und dann von dort aus einen Vektor zu erstellen. Ich sehe aus Ihrer Antwort, dass dies nicht unbedingt die beste Wahl war. Warum ist das so?
Michael Stachowsky
1
Der Grund dafür ist, dass in zwei Dimensionen ein Vektor und ein Punkt tatsächlich dieselbe Definition haben. a Vector direction,Magnitudekann als a angesehen werden, Point x,ywenn Sie einige der von ihm bereitgestellten Vorgänge einfach ignorieren Vector. Das Beste daran ist, dass Sie diese Operationen jetzt ignorieren können, wenn Sie beispielsweise den Drehimpuls bestimmen möchten, ohne die Objekttypen zu ändern. Es ist dann fast Geschmackssache, denn was Spieleentwickler als "Punkt" -Mathematiker bezeichnen, nennt man tatsächlich "Vektor". Nennen Sie es so, wie Sie es wollen. Wichtig ist, was es bietet.
Joshua Hedges
1
Wenn ich in einer Sprache im C-Stil die "Punkt" -Definition für die Lesbarkeit verwenden möchte, würde ich sie einfach typedefaus einem Vektor oder alias dem Begriff "Punkt" verwenden, um dasselbe wie "Vektor" zu bedeuten.
Joshua Hedges