Physik Problem: Elastischer Stoß, plötzliche fehl kalkulationen

  • C#

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Mangafreak1995.

    Physik Problem: Elastischer Stoß, plötzliche fehl kalkulationen

    Hey Leute,

    Ich baue gerade an einer kleinen simplen Physik Engine, und soweit funktioniert auch alles, falls Partikel mit den Boden oder einen anderen Partikel kollidieren, wird überprüft ob die beiden Elemente elastisch sind, und je nach dem wird ein Elastischer oder ein Unelastischer Stoß ausgeführt. Falls nun aber mehr als 2 kollidieren wird eine viel zu hohe Geschwindigkeit berechnet und die Elemente fliegen einfach quer durch den Bildschirm.
    Ich habe mal dazu ein kleines Video gemacht, welches das verdeutlicht, im ersten Video funktioniert alles relativ gut, es gibt noch Schönheitsfehler, aber im ganzen funktioniert es, im zweiten seht ihr dann den Fehler.




    youtube.com/watch?v=-ZRl9KYJ8yM
    youtube.com/watch?v=EjvARuIPaQ8

    PhysicEngine

    C#-Quellcode

    1. using System.Collections.Generic;
    2. using SharpexGL.Framework.Game.Timing;
    3. using SharpexGL.Framework.Math;
    4. using SharpexGL.Framework.Physics.Collision;
    5. using SharpexGL.Framework.Rendering;


    Könnt ihr irgendwelche Fehler entdecken? Ich denke der Code ist ausreichend kommentiert, wenn nicht könnt ihr auch gerne fragen.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ThuCommix“ ()

    ThuCommix schrieb:

    Ich habe mal dazu ein kleines Video gemacht
    Das würde ich gern mal sehen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @ThuCommix:: Ohne es ganz tief zu verfolgen: Kommen die Querflieger vom unelastischen Stoß?
    Setz da mal einen Haltepunkt rein.
    Gib dem Teilchen ggf. noch eine Property History (List<Stöße>) oder so, da kannst Du sie besser analysieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die Querflieger stammen vom elastischen Stoß, das mit dem Haltepunkt und der History habe ich bereits gemacht, die Berechnungen Stimmen, aber aus irgendeinen Grund wird der Elastische Stoß sehr oft ausgeführt ohne das ich weiß warum..

    Ich habe bereits probiert nach dem Elastischen Stoß die alte Partikel Position wiederherzustellen, da dann keine Kollision stattfindet, und so der Elastische Stoß nicht zu oft ausgeführt wird, funktioniert aber auch nicht.
    Du könntest versuchen, die Partikel in ein Dictionary<Particle, bool> reinzulegen.
    Nachdem eine kollision stattgefunden hat setzt du die bool auf true und lässt nur eine Kollision zu, wenn die bool den Wert false hat.

    Ich bin mir nicht sicher ob das funktioniert, aber probieren geht über studieren :D
    Der Fehler sollte sich also irgendwo hier befinden, denkst du?

    C#-Quellcode

    1. //compute elastic impact and apply new velocities
    2. var callback = ElasticImpact(particle, _particles[i]);
    3. var param = new RecoilParams { InvolvedParticles = new[] { particle, _particles[i] } };
    4. particle.Velocity = callback[0];
    5. _particles[i].Velocity = callback[1];
    6. particle.OnRecoil(param);
    7. _particles[i].OnRecoil(param);
    8. //_particles[i].Position += _particles[i].Velocity; Update in next tick call
    9. particle.Position = posBeforUpdate;

    Für mich sieht das so aus (Zeile 4 + 5), als ob du bei einer Kollision beide Objekte beschleunigst. Allerdings werden ja alle Partikel geupdatet, weshalb später dann auch das andere Objekt auf Kollision geprüft wird, und somit beschleunigst du alles doppelt, oder im Falle, dass mehr als 2 Partikel zusammenstoßen, auch mehrfach. Du musst dafür sorgen, dass eine schon berechnete Kollision nicht nochmal berechnet wird, oder du beschleunigst nur das aktuelle Objekt, nicht das andere. Ich hab das in meiner Engine z.B. so gemacht:

    C#-Quellcode

    1. for (int i = 0; i < objects.Count; i++)
    2. {
    3. for (int j = i + 1; j < objects.Count; j++)
    4. {
    5. }
    6. }
    Damit werden keine Kombinationen doppelt geprüft, ich weiß aber nicht, ob du das so ohne weiteres auf dein System übertragen kannst.
    Ich hoffe das war tatsächlich das Problem, und ich habe nicht nur gerade Glück. Jeder Kollision bekommt einen Eintrag mit den beteiligten Partikeln, vor einer neuen Kollision wird überprüft, ob sie in den aktuellen Tick bereits geprüft wurden, wenn ja, wird nicht erneut berechnet.



    Schönheitsfehler werden noch verbessert :)

    Großen dank an Artentus und SplittyDev für die Ideen.
    naja, die Überlagerung der horizontalen Bewegung ist immer noch physik-widrig. Die sollte zunächstmal konstant sein, solange sie nicht kollidiert, und dann die Richtung wechseln, und die gewechselte Richtung dann auch beibehalten.
    Tatsächlich scheint sie aber im freien Fall auch horizontal zuzunehmen, und nach der Kollision kullert das Ding erstmal stück weg, und kommt dann aber wieder her.
    Guck dir mal Box2D an. Die 2D-Physikengine gefiel mir bis dato am besten.