2D Kollisionsabfragen

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 2D Kollisionsabfragen

Beitrag von Glocke » Mi Feb 06, 2013 8:22 pm

Glocke hat geschrieben:Naja für die 3. Phase (vom Kontext her beziehe ich mich erstmal auf 2D) würde ich konvexe Boost-Polygone verwenden.
Game Over :D So wie ich das sehe, kann ich mit boost::polygon nur prüfen, ob ein PUNKT in einem Polygon liegt. Eben habe ich nochmal die alte Geradengleichungsgeschichte aufgegriffen und nochmal umgestellt. Unter der Voraussetzung, dass für beide Skalare gilt 0<=r,s<=1 habe ich dann folgenden Python-Code (als Test des Algorithmus) geschrieben:

Code: Alles auswählen

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def getCut(a, b, c, d):
    tmp1 = c.x - a.x
    tmp2 = d.x - c.x
    tmp3 = (b.x - a.x)
    q1 = (c.y - a.y) * (b.x - a.x) - tmp1 * (b.y - a.y)
    q2 = tmp2 * (b.y - a.y) - (d.y - c.y) * tmp3
    q = float(q1) / float(q2)
    if (q < 0 or q > 1):
        return False
    p = (tmp1 + q * tmp2) / float(tmp3)
    if (p < 0 or p > 1):
        return False
    return True

A = Vector(1, 1)
B = Vector(13, 8)
C = Vector(2, 7)
D = Vector(10, 2)

print getCut(A, B, C, D)
Im Anschluss habe ich den Geradenschnitt in C++ implementiert und eine Polygon-Klasse darauf aufgebaut. Der gebe ich Koordinaten (in der Reihenfolge, in der die Strecken zwischen den Punkten liegen) an. Eine

Code: Alles auswählen

bool Polygon::doesIntersect(Polygon* other)
prüft, ob sich die Polygone schneiden. Dazu geht es alle Geraden durch (von Punkt 0 bis len-2, dazu der Folgepunkt, also von 1 bis len), nimmt alle Geraden des zweiten Polygons und führt den Schnittalgorithmus aus. Das ist zwar ziemlicher Aufwand, aber es funktioniert erstmal :)

Als Approximation des Kollisionspolygons habe ich mich für einen Kreis entschieden. D.h. ich werde - bevor polygonbasiert getestet wird - einen Kreisschnitt als approximative Kollisionserkennung durchführen (oben hatte ich glaube von einem Rechteck gesprochen). Der Kreis hat aus meiner Sicht zwei Vorteile:
  • Ich gebe Polygon-Ecken relativ zum lokalen Koordinatensystem der Figur an. Das Koord.-System liegt in der Weltposition der Figur, so dass ich nicht nur bequem die absoluten Polygon-Eckpunkt-Koordinaten ermitteln kann, sondern auch jenen Punkt ermitteln, der vom lokalen Ursprung am weiteste entfernt liegt (auf Basis des Euklidischen Abstandes). Dieser Abstand bildet den Radius des Approximationskreises; sein Mittelpunkt ist die Weltposition der Figur. Bei einer Bewegung muss ich also nur die Weltposition und die Polygon-Ecken verschieben, der Kreis geht automatisch mit.
  • Der Schnitt zweier Kreise lässt sich imho schneller Berechnen als der zweier Rechtecke: Abstand beider Kreismittelpunkte bestimmen und gucken, ob der Abstand kleiner als die Summe der Radien ist.
Für eine noch approximativere Kollisionserkennung (Quadtree oder ähnlich) überlege ich noch genau wie ich das realisiere.

LG Glocke :geek:

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 2D Kollisionsabfragen

Beitrag von Glocke » Do Feb 07, 2013 1:27 pm

Glocke hat geschrieben:Für eine noch approximativere Kollisionserkennung (Quadtree oder ähnlich) überlege ich noch genau wie ich das realisiere.
Wenn ich einen Quadtree implementieren will, muss ich wissen wie groß der Kollisionsbereich um ein Objekt maximal werden kann. Ist die Größe bekannt, kann ich einschränken in welchen Quadranten bzw. Unterquadranten sich mein Objekt befinden. Fehlt dieses obere Limit, muss ich prinzipiell davon ausgehen, dass mein Objekt in allen vier Quadranten Kollisionspunkte hat.

Sehe ich das richtig? (Darstellung wie ich das meine siehe Anhang, collsize.png).

Ausgehend von "Ich brauche eine maximale Kollisionsgröße" oder "Ich verwende eine maximale Kollisionsgröße" bräuchte ich gar keine weitere Stufe vor der groben (kreisbasierten) Kollision, sondern bräuchte nur vom Mittelpunkt meines Objektes den doppelten maximalen Kollisionsradius abzuklappern (siehe zweite Grafik, 1stphase.png).

Wie seht ihr das?

LG Glocke
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: 2D Kollisionsabfragen

Beitrag von Xin » Do Feb 07, 2013 1:38 pm

Außer Quadtree habe ich ehrlich gesagt nicht viel verstanden. ^^

Zwei Dinge: Mach die Grafiken so groß, dass man die Schrift lesen kann und Du kannst die Grafiken ins Posting einfügen. Die "erste" Grafik ist nämlich die untere und entsprechend.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 2D Kollisionsabfragen

Beitrag von Glocke » Do Feb 07, 2013 1:46 pm

Xin hat geschrieben:Mach die Grafiken so groß, dass man die Schrift lesen kann
Ups xD
Xin hat geschrieben:Du kannst die Grafiken ins Posting einfügen. Die "erste" Grafik ist nämlich die untere und entsprechend.
Das habe ich nicht hinbekommen und deswegen den Dateinamen (der glaube dabei steht) mit hingeschrieben.
Xin hat geschrieben:Außer Quadtree habe ich ehrlich gesagt nicht viel verstanden. ^^
Also.. :D Ich bin der Meinung, dass ich eine maximale Kollisionsgröße brauche, um den Quadtree zu implementieren. Schauen wir uns das unterste der beiden Bilder an:
  • Links ist ein Objekt mit maximalem Kollisionsradius. Klar ist, in welchen Quadranten es liegt. Damit kann ich es auf die Quadranten und ggf. auf die Unterquadranten der Quadranten reduzieren, um weniger Objekte mit meinem primären Objekt vergleichen zu müssen.
  • Rechts ist ein Objekt, das nicht dem maximalen Kollisionsradius unterliegt. Ich muss daher in jedem Quadranten schauen.
Naja unterm Strich meine ich, dass ich bei einer Quadtree-Implementierung eine maximale Kollisionsgröße brauche.

Und auf Basis dessen war meine Überlegung: siehe erstes Bild (der große Kreis ist z, der mittlere y und der kleine x).
Der Text der da steht ist:
  • Die Kantenlänge des Quadrates ist der doppelte, maximale Kollisionsradius. Das Quadrat ist um den Kreis x aufgebaut.
  • z hat den maximalen Kollisionsradius und schneidet x offensichtlich.
  • Der Mittelpunkt von z muss somit im Quadraten um x liegen, da der maximale Kollisionsradius ( = Kollisionsradius von z) kleiner als die Kantenlänge des Quadrates ist.
  • Bei der Kollision würden somit die Kreise y und z auf Schnitte mit x überprüft werden, da deren Mittelpunkt im Quadrat um x liegen.
Klappt das so, oder habe ich einen Denkfehler drinne?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: 2D Kollisionsabfragen

Beitrag von Xin » Do Feb 07, 2013 2:01 pm

Glocke hat geschrieben:
Xin hat geschrieben:Du kannst die Grafiken ins Posting einfügen. Die "erste" Grafik ist nämlich die untere und entsprechend.
Das habe ich nicht hinbekommen und deswegen den Dateinamen (der glaube dabei steht) mit hingeschrieben.
Wenn Du die Datei hochgeladen hast, gibt es einen Button 'In Posting einfügen' oder so ähnlich.
Glocke hat geschrieben:
Xin hat geschrieben:Außer Quadtree habe ich ehrlich gesagt nicht viel verstanden. ^^
Also.. :D Ich bin der Meinung, dass ich eine maximale Kollisionsgröße brauche, um den Quadtree zu implementieren. Schauen wir uns das unterste der beiden Bilder an:
Ich bin mir noch nicht sicher, was Du mit dem Quadtree erreichen möchtest!?
Willst Du ihn je nach Spielsituation überarbeiten - das könnte ich mir sinnvoll vorstellen, weil sich die Kollisionsabfrage damit ergibt, dass zwei Objekte kollidieren, wenn sie im gleichen Quadranten liegen und der Quadrant kleiner ist, als die Summe der Kollisionsradien beider Objekte. Wenn nicht - wird der Quadrant weiter unterteilt. Wenn doch, bestimmt man die Distanz der beiden Objekte. Kollidieren Objekte mit dem Rand ihres Quadranten muss, muss der Ast neu bestimmt werden, womit zwei Objekte wieder in den gleichen Quadranten kommen könnten und eventuell auch kollidieren.

Ich habe aber keinen Hinweis darauf erkennen können, dass Du das so implementieren möchtest. Womit ich eben sagen muss, dass ich nicht verstehe, was Du implementieren möchtest oder wofür Du den maximalen Kollisionsradius brauchst und ob eine maximale Kollisionsgröße etwas anderes ist als der Kollisionsradius.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 2D Kollisionsabfragen

Beitrag von Glocke » Do Feb 07, 2013 4:58 pm

Naja also ich suche - wie bereits der Titel verrät - eine Möglichkeit zur Kollisionserkennung. Schieben wir die Sache mit dem Quadtree erstmal weg. Jedes Objekt besitzt ein Polygon, das zur Kollisionserkennung maßgeblich ist:
polygon.png
Die polygonbasierte-Kollisionserkennung ist dabei recht aufwändig, so dass ich sie nicht immer ausführen möchte. Das Polygon möchte ich mit einem Kreis approximieren. Dabei ist der Radius r der größte Abstand, den die Polygoneckpunkte von der Objektposition M haben.
kreis.png
Auf Basis des "Umkreises" (ein echter Umkreis ist es ja nicht ^^) des Polygons, möchte ich zunächst näherungsweise bestimmen, ob eine Kollision möglich ist. Dazu müssen sich beide "Umkreise" schneiden.
kollision.png
Damit ich nicht für jede Kollisionsabfrage die Kreise aller Objekte auf der Karte prüfen muss, habe ich mir folgendes überlegt:
  • Ich setze ein Maximum für Kollisionsradius.
  • Jeder Kollisionskreis darf maximal diesen Radius haben.
  • Abhängig von der Position des primären Objektes (das, zu dem ich Kollisionen suche), durchsuche ich in einem (vom maximalen Kollisionsradius abhängigen) Bereich alle Objekte, deren "Mittelpunkt" sich in diesem Bereich befindet.
  • Für diese Objekte prüfe ich die Kreis-Kollision. Trifft die Kollision zu, kann ich polygonbasiert prüfen, um eine finale Entscheidung zu fällen. Kollidieren die Kreise nicht, können die Polygone auch nicht kollidieren, da die Kreise die Polygone komplett umschließen.
Der Rest des Posts kommt gleich - ich kann maximal 3 Anhänge anhängen.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Zuletzt geändert von Glocke am Do Feb 07, 2013 5:54 pm, insgesamt 1-mal geändert.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 2D Kollisionsabfragen

Beitrag von Glocke » Do Feb 07, 2013 5:00 pm

So:

Für den genannten Bereich hatte ich überlegt, wie groß der sein muss. Ein Quadrat mit einer Kantenlänge vom doppelten maximalen Radius klappt nicht. Es müsste das 4-fache sein.
quadrat.png
In diesem Bereich kann ich dann suchen. Warum 4-fach? Wenn sich im Extremfall (beide Kreise maximal groß) beide berühren, liegt der Mittelpunkt des zweiten Kreises noch im Quadrat - mindestens aber auf der Kante (und für mich noch drinnen). Vorhin schrieb ich 2-fach, das war falsch.
maximal.png
Ich hoffe das ist so anschaulicher erklärt :)

LG Glocke
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 2D Kollisionsabfragen

Beitrag von Glocke » Fr Feb 08, 2013 8:32 am

Moin moin,

gestern fiel mir beim Warten auf den Zug ein, dass das mit dem doppelten Radius Quatsch ist und der 4-fache vllt. eher Erfolgt bringt. Heute früh fiel mir dann im Bad ein, dass der Aufwand, in diesem (4*r)^2 großen Feld nach Mittelpunkten zu suchen wahrscheinlich übelster Aufwand ist (ich beziele ca. auf r=20 ab) - spätestens aber, wenn das sehr oft gemacht werden soll :D

Daher würde ich mich jetzt - ohne weitere, schlechte Ideen zu entwickeln :lol: - mal direkt mit Quadtrees beschäftigen. Aus mehreren Quellen wurde mir gesagt, dass man die für die Kollisionserkennung mit verwenden kann, um die Objekte so zu strukturieren, dass man i.d.R. schneller alle verdächtigen Objekte hat.

Kann mir jemand dazu irgendwelche E-Literatur (Tutorials, Wikis etc.) empfehlen? Meine aktuelle Lektüre ist http://en.wikipedia.org/wiki/Quadtree :oops:

LG Glocke

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: 2D Kollisionsabfragen

Beitrag von Xin » Fr Feb 08, 2013 10:44 am

Glocke hat geschrieben:gestern fiel mir beim Warten auf den Zug ein, dass das mit dem doppelten Radius Quatsch ist und der 4-fache vllt. eher Erfolgt bringt. Heute früh fiel mir dann im Bad ein, dass der Aufwand, in diesem (4*r)^2 großen Feld nach Mittelpunkten zu suchen wahrscheinlich übelster Aufwand ist (ich beziele ca. auf r=20 ab) - spätestens aber, wenn das sehr oft gemacht werden soll :D
Ich kann ja nicht behaupten, die Idee der Rasterung bisher verstanden zu haben, aber ich ging schon davon aus, dass jeder Rasterpunkt die Information besitzt, welche Objekte enthalten sind - sie eben nicht gesucht werden müssen. Ansonsten würde das ... nunja, doch eigentlich gar keinen Sinn ergeben!?

Bzgl der QuadTree Geschichte, wüsste ich jetzt spontan online nichts. Aber letztendlich... halt ein Baum mit vier statt zwei Kindern, die ein quadratisches Gebiet in vier Unterquadrate unterteilen!? Also das selbe wie ein binäre Baum im eindimensionalen!?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 2D Kollisionsabfragen

Beitrag von Glocke » Fr Feb 08, 2013 11:12 am

Xin hat geschrieben:Ich kann ja nicht behaupten, die Idee der Rasterung bisher verstanden zu haben, aber ich ging schon davon aus, dass jeder Rasterpunkt die Information besitzt, welche Objekte enthalten sind - sie eben nicht gesucht werden müssen. Ansonsten würde das ... nunja, doch eigentlich gar keinen Sinn ergeben!?
Naja eine direkte Rasterung ist es nicht - eher ein Eingrenzen des Bereichs um den Kreis anhand des Wissens, wie groß die Kreise maximal werden dürfen.
Xin hat geschrieben:Bzgl der QuadTree Geschichte, wüsste ich jetzt spontan online nichts. Aber letztendlich... halt ein Baum mit vier statt zwei Kindern, die ein quadratisches Gebiet in vier Unterquadrate unterteilen!? Also das selbe wie ein binäre Baum im eindimensionalen!?
Ja soweit isses mir klar. Effektiv bekomme ich das auch hin, Objekte hinzuzufügen und den Baum dynamisch zu erweitern. Nur fehlt mir die richtige Herangehensweise, wenn ich für einen gegebenen Kreis die Kollisionen haben will.

Antworten