2009-06-12 14 views
1

Für eine Physik-Engine, die ich baue, muss ich schnell feststellen, ob zwei starre Körper in Kontakt waren, im vorherigen Frame. Ich möchte, dass es so schnell wie möglich ist, also könntest ihr vielleicht ein paar Ideen mitbringen?Kontakt Graph

Das ist, was ich bisher habe. (Und es funktioniert gut, aber die ganze Sache bekam frage ich, wie ich es verbessern könnte.)

// I thought using a struct would be a good idea with only two values? 
    struct Contact 
    { 
     public readonly PhyRigidBody Body1; 
     public readonly PhyRigidBody Body2; 

     public Contact(PhyRigidBody body1, PhyRigidBody body2) 
     { 
      Body1 = body1; 
      Body2 = body2; 
     } 
    } 

    class ContactComparer : IEqualityComparer<Contact> 
    { 
     public bool Equals(Contact x, Contact y) 
     { 
      // It just have to be the two same bodies, nevermind the order. 
      return (x.Body1 == y.Body1 && x.Body2 == y.Body2) || (x.Body1 == y.Body2 && x.Body2 == y.Body1); 
     } 

     public int GetHashCode(Contact obj) 
     { 
      // There has got to be a better way than this? 
      return RuntimeHelpers.GetHashCode(obj.Body1) + RuntimeHelpers.GetHashCode(obj.Body2); 
     } 
    } 

    // Hold all contacts in one big HashSet. 
    private HashSet<Contact> _contactGraph = new HashSet<Contact>(new ContactComparer()); 



    // To query for contacts I do this 
    Contact contactKey = new Contact(body1, body2); 
    bool prevFrameContact = _contactGraph.Remove(contactKey); 
    // ... and then I re-insert it later, if there is still contact. 

Antwort

1

Sie könnten stattdessen ein Dictionary<PhyRigidBody, HashSet<PhyRigidBody>> verwenden, das einen bestimmten Körper zu einer Reihe von anderen Einrichtungen bildet sie in Kontakt war mit (Das heißt, Sie behalten jeden "Kontakt" zweimal, da jeder Körper in der Kontaktgruppe des anderen enthalten ist). Das würde die Struktur zusammen mit der etwas fischigen Equals Methode vermeiden. Ich bin mir nicht sicher, ob es eine Verbesserung ist, aber es ist eine Überlegung wert.

+0

Was ist mit dem Extrahieren einer Erweiterung oder Klasse-Level-Methode, "Kontakt" für PhyRigidBody - d.bool Kontakt = SomePhyRigidBody.Contact (anotherObject). Besser noch, wenn Sie später nicht-starre Physik implementieren wollten, sollten Sie darüber nachdenken, die Contact() - Methode Teil einer Schnittstelle zu machen, so dass Sie Ihre Bibliothek einfach erweitern können. –

+0

Ich denke, du mischst hier zwei verschiedene Probleme: Wie man den Kontakt bestimmt, sollte in der Tat irgendwo hingehen, wo er überschrieben werden kann (wie eine Schnittstelle, etc.). Aber der Typ fragt, wie man die Kontaktdaten für das vorherige Bild * speichert * angeblich * nachdem * es berechnet hat. – Avish

+0

Danke für die Ideen. Ich denke, ich werde jedem PhyRigidBody einen "HashSet contacts" hinzufügen. Immer noch müssen die Kontakte doppelt gehalten werden, es sei denn, ich überprüfe einfach beide Stellen, wenn ich nach Kontakten suche. – LaZe

0

Ich bin verwirrt durch diese:

// It just have to be the two same bodies, nevermind the order. 
return (x.Body1 == y.Body1 && x.Body2 == y.Body2) || (x.Body1 == y.Body2 && x.Body2 == y.Body1); 

aber alles in allem kann ich nicht den Punkt. Wie viele Körper gibt es? Bewegen sich die Körper, so dass sich ihre Kontaktfähigkeit oft ändert? Könnten Sie sie einfach in ein räumliches Gitter fallen lassen? Wie oft müssen Sie wissen, was die Kontakte sind?

Ohne mehr über das Problem zu wissen, ist es schwer, viel zu sagen, obwohl mein Bauchgefühl ist, dass alles in Hash-Codes und Datenstruktur eingewickelt werden wird, kostet Sie große Zeit.

+0

Bei jedem Frame muss ich feststellen können, ob sich zwei Körper am vorherigen Frame berührten. Ich brauche diese Information für viele Körperpaare in jedem Bild. Es könnte eine Menge Körper in der Szene geben (Tausende), aber dann ist ein großer Teil von ihnen wahrscheinlich statisch oder schläft. Ich muss in der Lage sein, nach Kontakten auf zwei beliebigen Körpern zu suchen. – LaZe

+0

Grundsätzlich ist es eine spärliche boolesche Matrix. Sie könnten ein 1-d-Array haben, das durch body1 indiziert wird, wobei jedes Element eine Liste von body2-Nummern enthält. Das ist im Grunde ein Hash-Setup. Auf der anderen Seite, wenn Ihre Abfragesequenz sehr vorhersehbar oder sequentiell ist, könnten Sie davon profitieren. –