Timebased Animation, zusätzliche Gedanken zur FAQ



  • die faq scheint leider nur auf die typische methode einzugehen, ohne jeden schnickschnack.

    probleme damit:
    -nicht-lineare bewegungen laufen immer noch verschieden
    -sprünge in der framedauer erzeugen sprünge in der animation

    entsprechende anregungen sind also:
    -"glätten" der zeitdeltas (durchschnitt der letzten x frames)
    -feste timesteps

    letzteres heißt, man nimmt sich feste schritte (z.b. 1/25s), addiert nach jedem frame die vergangene zeit auf und macht prinzipiell:

    while (time>step) {dostep(); time-=step;}

    nachteil:
    bei sehr komplexen updates und langsamem rechner hängt man im extremfall mehr und mehr hinterher und muß in jedem frame mehr und mehr updates berechnen (wichtig: NICHT nach jedem timestep einen neuen frame rendern, sonst holt man garantiert nicht mehr auf)

    vorteil:
    z.b. ballistische flugbahnen sind auf allen rechnern identisch (die sonst im extremfall zu 1-2 liniensegmenten verkommen würden -> kollisionsberechnung ungenau und nicht mehr konsistent/nachstellbar)

    andere kleinigkeit: finger weg von timern/countern mit 1ms auflösung. einen "guten" zu finden kann aber grade unter windows schwierig werden.

    alter performance counter:
    +sehr hohe auflösung
    -großer overhead
    -windows only

    rdtsc:
    +sehr hohe auflösung
    +minimaler overhead
    +perfekt für profiling
    -gute annäherung an cpu takt nötig (notebooks und intel cpus können den aber beliebig einfach so ändern, z.b. bei leerer batterie oder temperaturanstieg)
    -rdtsc könnte bald aus dem befehlssatz rausfliegen

    neuer performance counter (nutzt intern rdtsc -clever gemacht *datsch*-):
    +nimmt einem die takt-annäherung ab
    -sag good bye zur ehemaligen alternative
    -immer noch windows only



  • die faq scheint leider nur auf die typische methode einzugehen, ohne jeden schnickschnack.
    wo ist das in der faq? hab nichmal was über die suche finden können

    probleme damit:
    -nicht-lineare bewegungen laufen immer noch verschieden
    -sprünge in der framedauer erzeugen sprünge in der animation
    sprünge in der framedauer sorgen immer für sprünge in der animation, die kann man nie verhindern, aber über die interpolation kann man immer eine halbwegs genaue annäherung erhalten 🙂

    entsprechende anregungen sind also:
    -"glätten" der zeitdeltas (durchschnitt der letzten x frames)
    das is nicht gut, braucht ein frame mal ungewöhnlich lange, hinkst du im nächsten frame automatisch hinterher
    -feste timesteps

    letzteres heißt, man nimmt sich feste schritte (z.b. 1/25s), addiert nach jedem frame die vergangene zeit auf und macht prinzipiell:

    while (time>step) {dostep(); time-=step;}
    ich dachte,du wolltest sprünge verhindern? diese technik fördert sprünge doch gerade erst.

    nachteil:
    bei sehr komplexen updates und langsamem rechner hängt man im extremfall mehr und mehr hinterher und muß in jedem frame mehr und mehr updates berechnen (wichtig: NICHT nach jedem timestep einen neuen frame rendern, sonst holt man garantiert nicht mehr auf)

    und flüssiger wirds auch nicht gerade, ein schönerer ansatz wäre doch die interpolation über shader, man übergibt dem shader den vom zeitwert der animation jeweils letzten und nächsten keyframe, dazu einen zeitwert, mit dessen hilfe dann zwischen den frames interpoliert wird.

    vorteil:
    z.b. ballistische flugbahnen sind auf allen rechnern identisch (die sonst im extremfall zu 1-2 liniensegmenten verkommen würden -> kollisionsberechnung ungenau und nicht mehr konsistent/nachstellbar)
    flugbahnen haben mit der animation herzlich wenig zu tun,genausowenig wie die kollisionsberechnung mit der animation, die kollision wird aus performancegründen immer auf einfachere kollisionsobjekte ausgelagert, da die kollision auf vertice basis performancemäßig der exitus ist. wenn man balistische flugbahnen hat, kann man sie wunderbar interpolieren, dann sind sie aufjedenfall nachstellbar, egal wie die frames auf 2 pcs gegeneinander ersetzt sind. die kollision ansich ist aber bei ballistischen flugbahnen eine sache für sich, die kannst du nie genau hinbekommen, da kann man ansich nur eine linie zwischen der alten und der neuen position testen...(oder überseh ich was?)

    //edit wenn ich mich irgendwo beim thema ansich irren sollte, sorry, konnte den faq eintrag ja nicht finden.



  • Trienco schrieb:

    -nicht-lineare bewegungen laufen immer noch verschieden

    Wieso? Wer sagt, du darfst nur mit linearen Funktionen rechnen?

    Bye, TGGC \-/



  • Trienco schrieb:

    die faq scheint leider nur auf die typische methode einzugehen, ohne jeden schnickschnack.

    probleme damit:
    -nicht-lineare bewegungen laufen immer noch verschieden
    -sprünge in der framedauer erzeugen sprünge in der animation

    entsprechende anregungen sind also:
    -"glätten" der zeitdeltas (durchschnitt der letzten x frames)
    -feste timesteps

    letzteres heißt, man nimmt sich feste schritte (z.b. 1/25s), addiert nach jedem frame die vergangene zeit auf und macht prinzipiell:

    while (time>step) {dostep(); time-=step;}

    nachteil:
    bei sehr komplexen updates und langsamem rechner hängt man im extremfall mehr und mehr hinterher und muß in jedem frame mehr und mehr updates berechnen (wichtig: NICHT nach jedem timestep einen neuen frame rendern, sonst holt man garantiert nicht mehr auf)

    vorteil:
    z.b. ballistische flugbahnen sind auf allen rechnern identisch (die sonst im extremfall zu 1-2 liniensegmenten verkommen würden -> kollisionsberechnung ungenau und nicht mehr konsistent/nachstellbar)

    andere kleinigkeit: finger weg von timern/countern mit 1ms auflösung. einen "guten" zu finden kann aber grade unter windows schwierig werden.

    alter performance counter:
    +sehr hohe auflösung
    -großer overhead
    -windows only

    rdtsc:
    +sehr hohe auflösung
    +minimaler overhead
    +perfekt für profiling
    -gute annäherung an cpu takt nötig (notebooks und intel cpus können den aber beliebig einfach so ändern, z.b. bei leerer batterie oder temperaturanstieg)
    -rdtsc könnte bald aus dem befehlssatz rausfliegen

    neuer performance counter (nutzt intern rdtsc -clever gemacht *datsch*-):
    +nimmt einem die takt-annäherung ab
    -sag good bye zur ehemaligen alternative
    -immer noch windows only

    1. sprünge hast du bei deiner methode auch (wüßte auch nicht wie man das verhindern sollte oO)
    2. deine dostep()-methode muss ziemlich schnell berechnet werden können (muss zumindest kürzer dauern als deine step-schritte)
    3. bei deinen ballistischen flugbahnen würd ich die kollisionsabfrage nicht mit einer linearen funktion machen (daher Schnittpunkt zwischen möglichen kollisionsobjekt und linienfunktion (die durch alte und neue position geht) berechnen), sondern mit einer passenden funktion (halt mit der gleichen funktionen, die dir auch die neue position abhängig von der vergangenen zeit berechnet)



  • halt mit der gleichen funktionen, die dir auch die neue position abhängig von der vergangenen zeit berechnet)

    dann hast du 2 möglichkeiten:
    1. jeden punkt auf dem weg der flugbahn des geschosses seit dem letzten frame auf kollision testen(performance, ich komme ;))
    2. eine kollision parabel/objekt schreiben(auch wenn ich absolut keine ahnung hab wie das geht^^)



  • Um den Kollisionspunkt zu erhalten berechnet man einfach den Schnittpunkt von der Flugbahnfunktion mit deinem Kollisionsobjekt (beispielsweise ein dreieck). Um dies zutun berechnet man nun einfach die Gradenfunktionen der 3 Seiten und berechnet die Schnittpunkte zwischen Gradenfunktionen und Flugbahnfunktion. Zum Schluss muss man noch gucken ob die Schnittpunkte im gültigen Bereich liegen (die 3 Seiten des Dreieckes sind wahrscheinlich nicht unendlich lang ;)) .. Fertig ist die pixelgenaue kollisionsabfrage, die garantiert völlig unabhängig von deinen fps ist 😛



  • Um den Kollisionspunkt zu erhalten berechnet man einfach den Schnittpunkt von der Flugbahnfunktion mit deinem Kollisionsobjekt (beispielsweise ein dreieck).
    ach? wirklich? da wäre ich nie drauf gekommen 😉
    Um dies zutun berechnet man nun einfach die Gradenfunktionen der 3 Seiten und berechnet die Schnittpunkte zwischen Gradenfunktionen und Flugbahnfunktion.
    und wir willst du an die schnittpunkte kommen? du lässt geschickt das hauptproblem aus,btw es werden wohl in dem fall keine gradenfunktionen sein, sondern die ebenen des dreiecks, wir sind immerhin im 3 dimensionalen raum :p
    Zum Schluss muss man noch gucken ob die Schnittpunkte im gültigen Bereich liegen (die 3 Seiten des Dreieckes sind wahrscheinlich nicht unendlich lang ;)) .. Fertig ist die pixelgenaue kollisionsabfrage, die garantiert völlig unabhängig von deinen fps ist 😛
    dazu kann ich erst was sagen, wenn du mir erklärt hast, wie du an die schnittpunkte kommen willst



  • "ach? wirklich? da wäre ich nie drauf gekommen 😉 "

    du wolltest doch jeden punkt abfragen statt einfach den Schnittpunkt zu berechnen 😛

    jeden punkt auf dem weg der flugbahn des geschosses seit dem letzten frame auf kollision testen

    "und wir willst du an die schnittpunkte kommen? du lässt geschickt das hauptproblem aus"

    na ausrechnen oo. Welches Hauptproblem?

    "btw es werden wohl in dem fall keine gradenfunktionen sein, sondern die ebenen des dreiecks, wir sind immerhin im 3 dimensionalen raum :p "

    Wer sagt das? Du? nagut.. im 3D raum wirds natürlich komplizierter. Da muss man wirklich die ebenen des dreiecks berechnet. Dann wieder Schnittpunkt mit der Funktion --> man erhält nen Punkt oder Schnittfunktion (oO) --> wenn Punkt muss man wieder überprüfen obs im gültigen Bereich liegt (daher wirklich im Dreieck liegt) und wenn die Funktion überall geschnitten wird (daher liegt in Ebene) dann kannste wieder den 2d ansatz nehmen 🙂



  • text aus dem zusammenhang reissen kann ich auch, das muss ich aber nicht oder?

    also setzen wir an:

    jeden punkt auf dem weg der flugbahn des geschosses seit dem letzten frame auf kollision testen

    ein

    (performance, ich komme ;))

    und beachten den smiley 🙄

    ansonsten sit ein

    Um den Kollisionspunkt zu erhalten berechnet man einfach den Schnittpunkt von der Flugbahnfunktion mit deinem Kollisionsobjekt

    gleichbedeutend mit ausprobieren, immerhin hat man bei einer mathematischen funktion mindestens einen wert den man einsetzen muss. wenn ich bewegung mit konstanter steigung hab, ist die sache ganz einfach: alte position mit neuer mithilfe einer linie verbinden, und dann die kollision objekt/linie verwenden.
    bei einer funktion ohne konstante steigung geht das natürlich nicht, also was machen? benutz ich eine linie, kann ich bei einer extrem miesen framezeit die sache vergessen, die linie wird bei kleinen objekten bestimmt nicht das richtige treffen.
    Das hauptproblem ist aber auch, dass man ja die bewegung zur zeit ineterpoliert, dh wenn ein objekt die geschwindigkeit 90m/s hat, und man alle 2 sekunden die programmlogik durchläuft,man das objekt um 2*90m verschiebt.
    liegt der kollisionspunkt bei 130m kriegst du sofort das problem die richtige kollision zu erkennen. wie gesagt, mithilfe der hilfslinie kann man das noch sehr schön machen, aber wie sollte man zb bei einer parabel vorgehen? das ist das hauptproblem,die bewegung des objekts ist zwar nachvollziehbar,sodass man durch ausprobieren den kollisionspunkt herausbekommen könnte,aber einen performanten trick wie die linie im flal der linearen bewegung gibts halt nicht, ohne dass man einiges an genauigkeit einbüßt.

    punkt 2:

    na ausrechnen oo. Welches Hauptproblem?

    dann erklär mir mal, wie man ein objekt auf kollision testen soll, welches sich mit folgender funktion fortbewegt:
    f(x)=sin(x).
    als rahmenbedingung legen wir noch fest, dass wir 2 fps haben, und ein sinusdurchlauf genau eine sekunde dauert(dh das objekt bewegt sich genau um 360 längeneinheiten pro sekunde genau in richtung der x achse).



  • life schrieb:

    Um den Kollisionspunkt zu erhalten berechnet man einfach den Schnittpunkt von der Flugbahnfunktion mit deinem Kollisionsobjekt (beispielsweise ein dreieck). Um dies zutun berechnet man nun einfach die Gradenfunktionen der 3 Seiten und berechnet die Schnittpunkte zwischen Gradenfunktionen und Flugbahnfunktion. Zum Schluss muss man noch gucken ob die Schnittpunkte im gültigen Bereich liegen (die 3 Seiten des Dreieckes sind wahrscheinlich nicht unendlich lang ;)) .. Fertig ist die pixelgenaue kollisionsabfrage, die garantiert völlig unabhängig von deinen fps ist 😛

    Das ist nicht pixelgenau.

    @otze:
    Eine Parabel liegt immerin einer Ebene, nur die muss man betrachten. Schnittpunkte bekommt man einfach durch Gleichsetzen der Gleichungen, 8. Klasse oder sowas.

    Bye, TGGC \-/



  • dann erklär mir mal, wie man ein objekt auf kollision testen soll, welches sich mit folgender funktion fortbewegt:
    f(x)=sin(x).
    als rahmenbedingung legen wir noch fest, dass wir 2 fps haben, und ein sinusdurchlauf genau eine sekunde dauert(dh das objekt bewegt sich genau um 360 längeneinheiten pro sekunde genau in richtung der x achse).

    Gut bei dieser funktion kann man die lösung algebraisch nicht berechnen.. raus bekommt mans aber trotzdem 😛 :

    Also rechnen wir einfach mal den Schnittpunkt von der Funktion mit einer Gradenfunktion aus (z.b. y= 1/2*x)

    y = sin(x)
    y = 1/2 * x

    sin(x) - 1/2 *x = 0

    Gut hier kommt man rechnerisch nicht weiter. Um jetzt die Lösung zu bekommen guckt man zuerst, welches x man eigentlich vor der bewegung hatte und welches nachher. Beispielsweise hatte man vorher pi/2 und nachher pi (daher ist man beim 2. frame). Dann benutzt man ein Nullstellensuchalgorithmus und lässt ihn in diesem bereich drüberlaufen und schwupps hat man seine Lösung (oder auch nicht ;)) 🙂



  • TGGC schrieb:

    Wieso? Wer sagt, du darfst nur mit linearen Funktionen rechnen?

    mal stellvertretend den hier nehmen.

    stellen wir uns zum verdeutlichen wirklich große sprünge vor. wie sieht die bahn für einen geworfenen ball aus (mit nichts als anfängliche beschleunigung und schwerkraft).
    schritt eins:
    -ball wird in richtung bewegt mit pos=vt;
    -neue richtung durch addieren der v+=g
    t;

    bei vielen schritten nähert das brauchbar die flugbahn an.
    bei einem großen schritt aber:

    -ball fliegt viel zu weit mit pos=vfat_t;
    -extreme änderung von v mit v+=g
    fat_t;
    -im nächsten frame klatscht das ding schnell nach unten.

    aus der hübschen kurve wird ein viel zu langer strich in die alte wurfrichtung gefolgt von einem langen strich steil nach unten, der evtl. weit hinter dem eigentlichen aufschlag punkt liegt.

    was, wenn man v zuerst aktualisiert und dann die bewegung macht? es wird ein riesen g*fat_t aufaddiert und der ball fällt fast senkrecht nach unten.

    deswegen sind nicht lineare bewegungen mit der methode nur dann brauchbar, wenn man sie "sauber" berechnet (nur: will wirklich jemand mit integralen hantieren?)

    für das einfache beispiel hier bin ich vor langer zeit mal bei sowas gelandet, um partikel im system auch "mittendrin" starten zu lassen:
    pos+=(g*t*t)/2 + (vt);
    v+=g
    t;

    das sah zumindest optisch richtig aus und irgendwas hab ich mir dabei auch mal gedacht (nur was?)

    wenn man davon ausgeht, daß solche updates recht schnell gehen, dann lassen sich nach einem langen frame auch mal mehrere am stück durchziehen. wenn der rechner dann wirklich zu langsam ist, dann kann man immer noch auf größere steps umsteigen. der wesentliche punkt ist einfach, daß das ganze deterministischer abläuft.

    kleiner bonus ist vielleicht noch, daß man mit floats davonkommt und bei extremen geschwindigkeiten nicht plötzlich mit lauter t=0 dasteht. dann reicht ein double um die einzelnen framezeiten aufzuaddieren und für die eigentlichen berechnungen reichen wieder handliche floats.

    das glätten von spikes ist weniger für korrektheit, sondern für optik. wenn ein frame lange dauert ist die kurze verzögerung schon lästig genug, der folgende sprung umso lästiger. (und ich hoffe mal, die hätten in gpg 4 keinen ähnlich ausgerichteten artikel gepackt, wenn es komplett unsinnig wäre).

    anhang: google spuckt da eine lange discussion bei flipcode aus und ein wichtiger punkt fehlte da wirklich noch *hust*.

    es kann viel öfter gerendert werden als die spiel logik läuft, rendert man zwischen zwei timesteps wird aber nicht der letzte zustand wiederholt, sondern zwischen beiden interpoliert. dann sind animationen wieder "flüssig" während die "richtigen" berechnungen einfacher sind und/oder seltener durchgeführt werden müssen.

    http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-MainLoopTimeSteps&forum=totd&id=-1



  • //edit life hat ja geedited, mein beitrag hat nu keinen sinn mehr-.-



  • ?
    Ball wird geworfen:

    xposition nach t sekunden: v * t
    yposition nach t sekunden: h - 1/2 * g * t^2 (oder so ~~)



  • life schrieb:

    ?
    Ball wird geworfen:

    xposition nach t sekunden: v * t
    yposition nach t sekunden: h - 1/2 * g * t^2 (oder so ~~)

    ähm.. oder so... v hat bei dir keinen y anteil (oder auch z).
    statt g könnte es auch wind oder jede beliebige andere beschleunigung sein, die nicht zufällig nur in y wirkt. evtl. hätte ich oben erwähnen sollen, daß v und g vektoren sind.

    oder physik für ein auto. jede menge geschwindigkeiten und beschleunigungen, die wild zusammenwirken.



  • Naja das war jetzt waagerechter wurf .. Es stimmt schon, dass es kompliziert werden kann, aber es ist durchaus möglich das ganze als Funktion darzustellen 🙂



  • life schrieb:

    Naja das war jetzt waagerechter wurf .. Es stimmt schon, dass es kompliziert werden kann, aber es ist durchaus möglich das ganze als Funktion darzustellen 🙂

    stimmt, und dann berechne das mal für ein paar tausend bälle/partikel oder sonstwas, wo einem jede unnötige division so richtig weh tut. klar, man kann alles "richtig" und mit tausend integralen berechnen, die frage ist wohl nur, was der spieler dann von der dia-show hält ,-)



  • wie meinste das mit "integralen berechnen" ?
    Sagen wir bei deinem verfahren steht sowas wie

    speed = speed * 2;

    speed fängt mit 1 hat und nach 4 steps haste dann einen speed von 32. Also würd bei dem "normalen" verfahren sowas wie

    speed = 2^steps;

    stehn. Ich seh jetzt aber nicht den Zusammenhang mit integralen oO



  • life schrieb:

    wie meinste das mit "integralen berechnen" ?
    Sagen wir bei deinem verfahren steht sowas wie

    speed = speed * 2;

    speed fängt mit 1 hat und nach 4 steps haste dann einen speed von 32. Also würd bei dem "normalen" verfahren sowas wie

    speed = 2^steps;

    stehn. Ich seh jetzt aber nicht den Zusammenhang mit integralen oO

    wo kommen die denn her? wenn die geschwindigkeit in jedem schritt verdoppelt wird, dann ist nichtmal mehr die beschleunigung konstant.

    dann so:

    auto A fährt mit s kmh, seitenwind erzeugt eine beschleunigung von w m/s^2, die eigenbeschleunigung ist a und weil sich der bleifuß allmählich senkt steigt sie um "da" pro sekunde.

    wenn die startposition p ist, wo ist die karre nach 5.63 sekunden?

    und ist es jetzt angenehmer alle 1/25s die beschleunigung zu aktualisieren und beide beschleunigungen auf die geschwindigkeit zu addieren und letztere auf die position oder in jedem frame die mathematisch korrekte formel zu benutzen?

    ein billiges 1/2 att + 1/2 wtt + vt (a,w,v vektoren)
    klappt hier schon nicht mehr, weil a nicht konstant ist.

    physik ist vollgestopft mit integralen und die zu vermeiden ist sicher nicht die schlechteste idee.



  • das war nur ein einfaches beispiel an dem du mir die sache mit den integralen verdeutlichen solltest:

    deswegen sind nicht lineare bewegungen mit der methode nur dann brauchbar, wenn man sie "sauber" berechnet (nur: will wirklich jemand mit integralen hantieren?)


Anmelden zum Antworten