| Autor |
Beitrag |
F34r0fTh3D4rk
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 13.03.08 18:05
Hallo,
Ich schreibe gerade an einer 2D Physik Engine auf der Basis dieses Tutorials:
teknikus.dk/tj/gdc2001.htm
Soweit so gut, bisher konnte ich schon einige wirklich passable Ergebnisse erzielen.
Allerdings stellen sich mir momentan zwei Probleme, eines der beiden sei dieses Topic gewidmet
Zunächst einmal arbeite ich ohne Geschwindigkeiten (Verlet integration) und Rotationen werden auch nicht explizit behandelt.
Meine Polygone bestehen aus Punktmassen, die mit unendlich steifen Federn miteinander verbunden sind.
Bei einer Kollision bestimme ich zunächst die Kollisionsnormale und dann die Kontaktpunkte. Ich habe aus dem Code erst einmal Reibung und Restitution entfernt un es auf etwas überschaubares reduziert.
Dies ist der (verkürzte) Code meiner Kollisionsbehandlung:
Ac und Bc beinhalten die Kontaktpunkte, MTD ist die Kollisionsnormale mit der Eindringtiefe als Länge:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| suminvmasses := A.invmass + B.invmass; mf := A.invmass * suminvmasses; for i := 0 to high(Bc) do B.vertices[Bc[i]].position := v2f_add(B.vertices[Bc[i]].position, v2f_scale(mtd, -1-mf)); for i := 0 to high(Ac) do A.vertices[Ac[i]].position := v2f_add(A.vertices[Ac[i]].position, v2f_scale(mtd, mf)); |
Ich könnte die beiden Objekte auch ungeachtet ihrer Massen trennen, das Problem bleibt bestehen.
Nun komme ich zum Problem selbst, es ist schwer zu beschreiben, da ich die Ursache nicht kenne.
Nehmen wir mal folgende Situation:
Hier sieht man nun, dass das 2. Rechteck zu fallen beginnt, obwohl sein Schwerpunkt über dem anderen Rechteck liegt.
Ich habe dazu mal eine kleine Simulation gebastelt, die dieses Problem verdeutlicht zeigen soll:
www.exec-dev.de/mass.zip
Das Rechteck fällt, obwohl es nur einen Pixel über das andere hinausragt. Sehr merkwürdig.
Die Frage ist nun, woran kann das liegen und wie kann ich es möglichst einfachen beheben ?
Vielen Dank schonmal,
mfg
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Do 13.03.08 18:38
Hm ich schätze mal das Problem ist die Reibung.
Da das zweite Rechteck nicht bündig aufliegt ergibt sich mit der Gravitation eine Kraftkomponente entlang der langen Seite des Rechtecks. Ohne Reibung wird diese niemals verschwinden und die Rechtecke früher oder später "auseinanderfallen".
Edit hab mir die mass.zip mal angesehen. Für mich passt das klar ins Konzept keine Reibung. Aber bei den Stößen berücksichtigst du doch offenbar Inelastizität, sonst müssten die ja ewig weiterspringen. Da fände ich Reibung auch nur konsequent
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 13.03.08 18:44
hi, mit Reibung sieht das ganze noch viel dramatischer aus  Daran liegt es nicht, da ja alle Punkte des Objektes die gleiche Kraft nach unten ausüben.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Do 13.03.08 18:48
Hallo,
das sieht so aus, als ob der Schwerpunkt um einen Pixel über die Kante herausragt und nicht nur die Kante selbst.
Halt!
Du hast Massepunkte durch starre Federn, reibunbsfreie Federn verbunden.
Deine Federn sind nicht unendlich starr.
Beim Auftreffen auf das untere Rechteck ensteht eine Pendelbewegung. Erst trifft es vorne dann hinten auf ...
Die überhämgende Masse erzeugt eine minimale Biegung der Feder über den Rand, was eine minimale Kraft in x-Richtung erzeugt.
Aber wieso hebt die linke Ecke nun ab? Eine Wippe würde erst bei Gleichstand der Drehmomente links,rechts indifferent und dann w(k)ippen.
Und warum kippt das dann nicht weiter, sondern verharrt bis zum Absturz in einer Schräglage??
Witzig ist, das zweite Rechteck von oben ganz langsam nach links wandert während das oberste schon ins Nirvana geplumpst ist.
Gruß Horst
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Do 13.03.08 18:58
Ich denke schon, dass es daran liegt. Aber ich denke da spielen vlt noch einige andere Sachen mit rein. Deine "Kippabfrage" könnte dafür verantwortlich sein. Bei mir fängt das Rechteck obwohl es schon weit über die Hälfte sich von dem anderen runtergeschoben hat nicht an zu kippen. Das sieht erstens reichlich unphysikalisch aus.
Zweitens und da weiß ich leider zu wenig über deine Implementierung aber hier mein Verdacht:Du berücksichtigst die Hebelgesetze über den Auflagepunkt des unteren Dreiecks nicht => dadurch kommt das REchteck auch nicht wieder bündig auf dem unteren Rechteck zu liegen. (Ich deenke der Knackpunkt ist dabei der Hebel, denn wenn das REchteck heruntergefallen ist und auf den "Boden aufkommt" da funktioniert das ja (aber da ist der Hebelpunkt auch mit der Ecke identisch).
Wenn das Rechteck nur auf einem Punkt aufliegt führen natürlich die meisten Reibungsformleln (die ja auf Flächen basieren) zu Unsinn.
Mögliche Lösungen:
1. du unterscheidest Nulldimensionale und eindimensionale Reibung (in 3D also sozusagen Kantenreibung und Flächenreibung)
2. du lässt die Seitenkanten minimal elastisch sein, dadurch wird sich immer eine Auflagefläche herausbilden.
Zuletzt bearbeitet von Allesquarks am Do 13.03.08 19:01, insgesamt 1-mal bearbeitet
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 13.03.08 18:58
hi,
mein Code für die steifen Federn sieht so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| procedure CorrectDistance(var a, b: TParticle; d: double); var delta: TVector2f; dlen, diff: double; begin delta := v2f_sub(b.position, a.position); dlen := v2f_length(delta); if dlen = 0 then dlen := 1; if a.fixed then begin diff := (dlen - d) / dlen; b.position := v2f_add(b.position, v2f_scale(delta, -diff)); exit; end; if b.fixed then begin diff := (dlen - d) / dlen; a.position := v2f_add(a.position, v2f_scale(delta, diff)); exit; end; diff := (dlen - d) / (dlen * (a.invmass + b.invmass)); a.position := v2f_add(a.position, v2f_scale(delta, a.invmass * diff)); b.position := v2f_add(b.position, v2f_scale(delta, -b.invmass * diff)); end; |
Auch hier könnte ich die Betrachtung unterschiedlicher Massen entfernen, allerdings müsste ich dann fixe Objekte gesondert behandeln, dies wird hier automatisch erledigt, da fixe Objekte eine inverse Masse von 0 haben.
Ich werfe des weiteren mal ein Bild der beiden Problemfälle in den Raum, damit jeder das gleiche Bild vor Augen hat:
Beide Fälle haben gleiche Kontaktpunkte und Kollisionsnormalen.
mfg
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Do 13.03.08 19:08
Also ich bin verwirrt: Manchmal legt sich das obere Rechteck wieder waagerecht manchmal nicht. Hm.
Bin mir ziemlich sicher dass es an der Reibung liegt. Würde dir auch gerne helfen aber dein correctdistance versteh ich nicht und ich versteh auch nicht wofür es gut ist und wann du es verwendest. Mir würde es helfen, wenn du einfach nochmal kurz erklärst, wie du die momentane Gesamtkinematik des Rechteckes errechnest
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 13.03.08 19:15
hi,
ich hole mal ein wenig weiter aus
Der CorrectDistance Code sorgt dafür, dass der Abstand der einzelnen Ecken des Polygons konstant bleibt, da es sich um Punktmassen handelt. (Das ist auch der Grund, weshalb Rotation nicht explizit behandelt werden muss)
Die einzelnen Ecken (oder auch Partikel) werden mittels Verlet integration (linear) bewegt:
Quelltext 1: 2: 3:
| x' = 2 * x - x* + a * dt² x* = x // x' ist das neue x, x ist das jetzige x und x* das alte x; (x = position) |
Da sich die Rotationsbewegung der Polygone durch lineare Bewegungen der einzelnen Partikel ausdrücken lässt, kann man sich Dinge wie Winkel hier sparen. (auch die Geschwindigkeit wird implizit behandelt, indem sie sich nach einer Bewegung der Partikel selbst anpasst [2*x - x*])
Reibung ist nicht implementiert, aber selbst mit Reibung besteht dieses Problem (hatte Reibung schon drin, schien auch ganz gut zu funktionieren)
mfg
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Do 13.03.08 19:32
Hm ok gegen die Verlet hab ich ja gar nichts und korrekt distance ist wahrscheinlich auch eine vertretbare Näherung.
Das Problem ist, dass du schon für die Veränderung der Verticeskoordinaten die Gesamtbeschleunigung einrechnen musst. Ich nehme an du berücksichtigst hier nur die Gravitation plus evt Stöße hier kommt aber noch die Kraft durch das über den Hebelpunkt übersetzte Drehmoment des anderen Vertex hinzu. Wenn das drin wäre würde das Rechteck wenigstens wieder horizontal fallen und dann würde ein Reibungsansatz dem Spuk auch ein Ende machen.
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 13.03.08 19:38
ok, danke, dann werde ich als nächstes versuchen, bei der Kollision die Verschiebung in Abhängigkeit des Massezentrums zu bestimmen.
Wobei ich noch ein weiteres Problem mit Massen hab und zwar wirkt bisher keine Gewichtskraft, ich hatte da nen Ansatz, der allerdings noch nicht so ganz funktionierte. (Ich habe dem unten liegenden Objekt immer die Gewichtskraft des oben liegenden hinzugefügt, was nicht gerade sehr elegant war ^^)
mfg
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Fr 14.03.08 22:49
Leider habe ich dafür noch keinen gescheiten Ansatz gefunden. Ich habe ja nicht immer (aber meistens) die Situtation gegeben, dass ich zwei Ecken des einen und eine Ecke des anderen Polygons habe. Diese könnte ich jetzt mit den Schwerpunkten ins Verhältnis setzen. Allerdings weiß ich nicht genau wie und auch nicht ob da was gutes bei rauskommt
Hier mal eine Version mit Reibung und Restitution. Interaktionsmöglichkeiten sind das Hinzufügen von Rechtecken mittels Mausklick und das Bewegen des Polygons mit den Pfeiltasten. In der Titelleiste sind nun auch noch ein paar weitere Informationen angezeigt. (lasst euch nicht irritieren, dass ab und zu nicht alle Kontaktpunkte angezeigt werden, diese werden korrekt behandelt, allerdings kommt es durch Subsampling vor, dass diese inzwischen nicht mehr vorhanden sind. Sprich der Kollisionscode wird mehrfach pro Frame ausgeführt)
www.exec-dev.de/verlet.zip
mfg
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Sa 15.03.08 00:46
Das sieht doch schon viel besser aus. Aber was hast du denn jetzt hinzugefügt und wie berücksichtigst du das Rechnest du jetzt mit Schwerpunkten oder hast du für die Vertices Drehmomente berücksichtigt?
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Sa 15.03.08 10:25
naja leider hab ich das noch nicht, weshalb du auch sehen kannst, dass das immer noch unrealistisch fällt, ich hatte halt nur für die andere version Reibung etc. rausgenommen um das problem zu vereinfachen. (Gewichtskraft fehlt zB auch noch, hab ich auch noch net gescheit hinbekommen), aber erstmal muss das mit der Rotation richtig klappen.
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Sa 22.03.08 13:19
leider hab ichs immer noch nicht hinbekommen, die Rotation bei der Kollision korrekt einzubinden. Ich bin deshalb für weitere Vorschläge offen
mfg
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: Sa 22.03.08 14:51
Hi,
ich würde die vier Punkte bei der Kollision als ein Objekt rechnen und das dann am Ende wieder aufdröseln... durch die Kollisionspunkte hast du dann die Ansatzpunte der Kräfte und der Rest ist eigentlich nurnoch Formelsammlung... Oder?
Ansonsten beschreib mal konkreter, was bei meinem Ansatz das Problem wäre.
mfG,
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Sa 22.03.08 15:07
hi,
es ist nicht die Frage nach dem was, sondern nach dem wie ^^
Reduzieren wir das Ganze doch mal auf den Code hier:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| suminvmasses := A.invmass + B.invmass; mf := A.invmass * suminvmasses; for i := 0 to high(Bc) do B.vertices[Bc[i]].position := v2f_add(B.vertices[Bc[i]].position, v2f_scale(mtd, -1-mf)); for i := 0 to high(Ac) do A.vertices[Ac[i]].position := v2f_add(A.vertices[Ac[i]].position, v2f_scale(mtd, mf)); |
Diese Code soll dahingehend erweitert werden, dass die Rotation unter Beachtung des Massezentrums korrekt durchgeführt wird.
mfg
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Sa 22.03.08 16:18
Ich würde sagen du musst einfach in deiner Verlet Routine die Kraft oder die Beschleunigung anders berechnen.
Du berechnest ja korrekt den Auflagepunkt. Ausgehend von diesem musst du jetzt zu allen Vertices/Ecken des Objektes Vektoren berechnen und damit die Drehmomente ausrechnen M=r kreuz F. Vorsicht diese wirken nicht unbedingt parallel zur Verbindungslinie. Deine Kraft ist also nicht mehr zwangsläufig in z Richtung.
|
|
Dornathal
      
Beiträge: 38
|
Verfasst: Di 13.05.08 14:23
www.myphysicslab.com/collision.html
schau dir dieses Beispiel mal an und stelle deine Simulation mal nach. Wenn du nun die Reibung auf 0 setzt, dann bewet sih auch das obere Rechteck vom unteren weg. Gut man kann das vielleicht nihct genau aufeinander setzen aber trotzdem ist der Problemfall denk ich der selbe.
Mit Reibung bleiben sie aufeinander liegen.
Weis nicht ob du das bereits gefixt hast wollt ich nur nochmal posten.
|
|