Wątek przeniesiony 2015-04-19 15:32 z Off-Topic przez somekind.

Jak fajnie zaprogramować naturalne animacje?

0

Chcę zrobić kilka animacji, ale nie ze spritesheetów (tj szybkie podmienianie obrazków, które ułożą się w ruch) tylko tak jak (chyba) we flashu się robi, tj np postać składa się z kilku części (bones) na głowę, ciało i kończyny, i te kończyny są odpowiednio układane a potem obracane i poruszane (przez co ten ruch jest płynniejszy).

Wszystko mam gotowe, oprócz realistycznych animacji. Zrobiłem sobie toola (załącznik) do tego celu właśnie, w którym robię ramki kluczowe a program robi takie fajne przejścia między nimi...
1239cfee2a.png
i poświęciłem chyba godzinę żeby sprawić żeby ten ruch był w miarę naturalny, potem znalazłem jakieś obrazki z których ściągnąłem pozycję kości, ale ten ruch i tak mi się nie podoba. Zacząłem oglądać tutoriale ale moja animacja nie wiele się przez to poprawiła.

Wiem że to forum programistyczne, a nie jakieś od motion designu, ale nie mam gdzie się z tym zwrócić.

2

W jaki sposób interpolujesz współrzędne? Zakładam, że masz wiele klatek w pewnych odstępach czasowych, ale by uzyskać odpowiednią ilość klatek na sekundę musisz je interpolować. Jeżeli interpolujesz liniowo to ruch będzie wyglądał biednie. Musisz interpolować czymś sprytniejszym, np funkcjami sklejanymi: http://en.wikipedia.org/wiki/Spline_(mathematics)

0

Okej, co do tej interpolacji... będę miał problem. Na razie wektory reprezentujące kości nie są w postaci Vector(posx, posy) tylko Vector(angle, length) dzięki czemu te małe przejścia między keyframes'ami wyglądają tak jak po lewej, a nie prawej.

5ced3e1501.png

Dopiero przy renderze zamieniam je na posx, posy do wyświetlenia.

Iii teraz problem jest taki że przejścia między kątami nie da się zrobić tak jak przejścia między punktami, tj wziąć różnicę między nimi i podzielić np na dwa (czy ile tam klatek pomiędzy chcemy); dlatego że miary kątów poszczególnych wektorów należą do <0; 2π), przez co taką metodą np kąt pomiędzy 10° a 340°, miałby miarę 175°, a nie 355°.

Rozwiązałem to tak że przy transition między dwoma kątami sprawdzam czy różnica między nimi jest większa od 180° i jeżeli tak, to ten większy "cofam" o 360°, dzięki czemu np z kątów 10° i 340° uzyskuję spodziewane 355° (tak na prawdę o -5°) a nie 175°.

Nie wiem jak to osiągnąć w funkcjach sklejanych.

PS; Czyli wykres takiej funkcji musiałby wyglądać jak na obrazku 2, a nie 1.

51bba040e2.png

Przy czym linie muszą iść "w dół" tzn dążyć do punktów po drugiej stronie osi od 90° i niżej (te będą dążyć do punktów od 270°); oraz analogicznie kąty od 270° i wyżej będą dążyć przez drugą stronę osi do punktów 90° i niżej.

Jak to ugryść?

1

Do wyznaczenia odcinka krzywej sklejanej pomiędzy dwoma punktami wystarczą chyba jeszcze ekstra dwa punkty tuż obok. Stąd możesz posłużyć się oknem zawierającym 4 punkty (odpowiadające kątom) przy interpolowaniu odcinka pomiędzy środowymi dwoma. Mając 4 kąty możesz zwiększyć zakres z <0, 2 * pi) do <0, 8 * pi), zinterpolować, a potem wyniki brać modulo (2 * pi).

0

SortAlgoBox? :D Brzmi nieźle, postuj na forum jak skończysz.

Tak, nawet bez przeskoku, na razie czytam te:
http://math.stackexchange.com/questions/829371/determine-a-polynomial-whose-graph-passes-through-the-given-points-1-0-2
http://www.dms.uaf.edu/~bueler/polybasics.pdf
http://en.wikipedia.org/wiki/Polynomial_interpolation

Ale nie potrafię tego przenieść na kod :/

1

Coś już tam mam: https://github.com/tarsa/SortAlgoBox :]

Interpolacja wielomianowa jest tutaj: http://www.algorytm.org/procedury-numeryczne/interpolacja-wielomianowa.html
Na osi X będzie czas, na osi Y będzie kąt. Stopień wielomianu, tak jak napisałem wcześniej, będzie stały i będzie wynosił 3, bo będziesz wykorzystywał okno złożone z 4 punktów.

0

Jeśli program ma być tylko pod Windowsa, to od Visty w górę jest do takich zabaw gotowa biblioteka systemowa :-)

0

Jestem taki happy że udało mi się to znaleźć że aż udostępnię klasę dzięki której można znaleźć funkcję która przechodzi przez punkty, oraz demo do niej :> (dla potomnych)

@Wibowit Zerknąłbyś czy jest dobrze skomentowana i takie tam?

0

Chybaaaa to nie jest dobre podejście, albowiem dla 9 takich samych wartości i jednej z odstępem... dostaję takie coś

c65f0bc070.png

Więęęęęęć po wielomian który przechodzi przez punkty to złe wyjście.. i ciągle nie wiem jak zaimplementować funkcję sklejaną.

2

Jeśli masz n + 1 punktów p0, p1, p2, ..., pn to:

  • krzywą między p0, a p1 wyznaczasz z wielomianu przechodzącego przez punkty p0, p1, p2 i p3,
  • krzywą między pn-1, a pn wyznaczasz z wielomianu przechodzącego przez punkty pn-3, pn-2, pn-1 i pn,
  • krzywą między pi, a pi+1 (dla i > 0 i i + 1 < n) wyznaczasz z wielomianu przechodzącego przez punkty pi-1, pi, pi+1 i pi+2,

Wszędzie są wielomiany stopnia 3-go.

Jeżeli wszystkich punktów jest mniej niż 4 to nie będzie sensu robić krzywych sklejanych, wystarczy funkcja kwadratowa (dla 3 punktów) lub odcinek (dla 2 punktów).

edit:
W sumie takie podejście to mocne upraszczanie i nie wiem czy efekt będzie dobry. Wyznaczanie krzywych sklejanych wymaga trochę więcej pracy, ale możesz na razie zaimplementować to uproszczone podejście i zobaczyć co wyjdzie.

update:
Znalazłem taki artykuł: http://paulbourke.net/miscellaneous/interpolation/
Spróbuj to zaimplementować :)

0

@Wibowit, @TomRiddle: z powyższej stronki polecałbym krzywe Beziera, dają duże możliwości i ładnie wyglądają ;-)
http://paulbourke.net/geometry/bezier/

0

Zacząłem od tej pierwszej, ale wynik nie jest powalający. Przy okazji sprawdziłem sobie te linie i faktycznie różnica nie jest zbyt duża.

1b480fb3ba.png

1

proponuję kupić sobie używanego kinecta - koszt niecałe 200 zł, a będziesz mógł szybko przenieść ruch swojego ciała na naturalną animację

0

Jest duży problem z połączaniem tego i z przeniesieniem animacji do programu/pliku?

jeszcze się tym nie bawiłem - na razie kinecta używałem tylko do gier
z tego co widziałem nie ma problemu z przeniesiem na animację 3d, są do tego gotowe narzędzia
na animację 2d pewnie będziesz musiał sobie to oprogramować - poza tym i tak będziesz musiał się pozbyć "szumów" czy jak to zwać - chodzi o drgania z odczytów i dochodzi jeszcze zgranie końca animacji z początkiem
może być problem z animacją boczną - kinect znajduje postać ustalając pozycję obu nóg i rąk - może być problem gdy połowa ciała będzie zasłonięta, ale już same odczyty z kamery z uwzględnieniem głębi powinny wystarczyć żeby to przerobić na animację

0

właściwie to wystarczy zwykła kamerka i dorobienie do Twojego narzędzia puszczenia nagrania w tle - klatka po klatce można dostosować pozycję szkieletu do filmiku

0
TomRiddle napisał(a)

Właśnie zaimplementowałem to z czterema punktami. Działa wyśmienicie! Jeżeli tylko kąt nie są od siebie większe niż 180°. Muszę tylko ogarnąć to przejście między osiami. - TomRiddle 29 minut temu

Wibowit napisał(a):

Mając 4 kąty możesz zwiększyć zakres z <0, 2 * pi) do <0, 8 * pi), zinterpolować, a potem wyniki brać modulo (2 * pi).

Pseudokod przedstawiający ten pomysł ze zwiększeniem zakresu:

double okno[4];
skopiujDaneDoOkna(okno);
for (int i = 1; i < 4; i++) {
  if (okno[i - 1] - okno[i] > PI) {
    for (int j = i; j < 4; j++) {
      okno[j] += 2 * PI;
    }
  } else if (okno[i] - okno[i - 1] > PI) {
    for (int j = 0; j < i; j++) {
      okno[j] += 2 * PI;
    }
  }
}

Tak jak pokazuje kod, powyższa operacja zwiększania zakresu jest zawsze poprzedzona kopiowaniem oryginalnych danych do okna. Jeżeli będziesz ją odpalał na tablicy wejściowej bezpośrednio to wartości się rozjadą.

Interpolacja zostaje taka sama jak wcześniej, a sama operacja modulo jest chyba na tyle prosta, że nie trzeba jej wyjaśniać.

0

Czemu po prostu nie skorzystasz z algorytmów do animacji szkieletowej?
http://content.gpwiki.org/index.php/OpenGL:Tutorials:Basic_Bones_System

1 użytkowników online, w tym zalogowanych: 0, gości: 1