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?
collision-detection
Michael Stachowsky
quelle
quelle
Antworten:
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 Vector
mit 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 einLine
und einCurve
. Wir werden hier entscheiden, dass aCurve
außerhalb des Anwendungsbereichs liegt und viel Spezialisierung erfordert (das Konzept, das Sie oben als Erstellen vieler Sonderfallfunktionen bezeichnen). VonVector
würde ich auch einRectangle
als 4-Vector
Primitiv komponieren,Circle
aus dem Vektor mit aVector
und aradius
komponieren und dann würde ich auch einPolygon
von komponierenVector
.Polygon
sollte vonVector
und nichtLine
hier 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
Rectangle
wir 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 BoxA
kein Teil der Box darinB
vorhanden istA
. Es folgt aus der Annahme, dass kein Teil vonB
innerhalbA
einer 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
,CollisionObject
usw. , 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,Solver
das die Unterschiede zwischen all den verschiedenen Formen, die kollidieren könnten, abstrahieren sollte, indem Sie nur einManifold
und keine bestimmten Informationen über die Formen akzeptieren.Zusammenfassung Der
Solver
wird dasManifold
durch Kollision eines PrimitivsA
mit einem Primitiv erzeugte nehmenB
, wobei zuerst eine breite Phasengruppierung (alle gegen Welt) und dann eine Schmalphasendetektion (A gegen B) verwendet werden. Wenn Formen nicht polygon sind, muss dasSolver
dann entweder neu erzeugt werdenVector
s für die Positionen und Geschwindigkeiten der kollidierten Formen oder für ein Objekt, mit dem dasPhysicsEnvironment
oderWorld
dann die Kollision seiner untergeordneten Elemente auflösen kann, aktualisieren Sie dasQuadTree
und 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 Trennachsensatzesquelle
Vector direction,Magnitude
kann als a angesehen werden,Point x,y
wenn Sie einige der von ihm bereitgestellten Vorgänge einfach ignorierenVector
. 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.typedef
aus einem Vektor oder alias dem Begriff "Punkt" verwenden, um dasselbe wie "Vektor" zu bedeuten.