8. Animációk¶
Az animáció nagyvonalakban annyit jelent, hogy bizonyos értékeket az idő függvényében változtatunk.
Jelölje \(t \in \mathbb{R}\) az időt!
Változtathatjuk a modellek helyzetét, színét, a textúraleképzést például.
\(\rhd\) Soroljuk fel, hogy például mi az amit még tudunk animálni!
Függvény megadása¶
Jelölje \(\textbf{x}(t)\) az idő függvényében változtatott értéket a \(t\) időpillanatban. Hogy ha ezt formula formájában fel tudjuk írni, azzal gyakorlatilag meg is oldottuk az animálás problémáját.
Példa
Tegyük fel, hogy egy pontot szeretnénk fel-le mozgatni folyamatosan a \(z \in [5, 10]\) intervallumon úgy, hogy 2 másodperc alatt tegyen meg egy teljes periódust. Ezt például színusz függvénnyel oldhatjuk meg:
Példa
Jelenítsünk meg egy modellt, és animáljuk az anyagjellemző szórt fény összetevőjét! Ehhez az egyes színkomponensekhez használjuk az alábbi összefüggést!
Az egyes színkomponensekhez használjunk különféle \(\alpha\) és \(\beta\) paramétereket (így összesen 6 paramétert)!
Vizsgáljuk meg a különféle paraméterek hatását!
Ábrázoljuk a 3 függvényt!
Kulcsképkocka animáció¶
Az animáció készítésének egy további módja, hogy ha bizonyos időpontokban ismerjük az animált értéket.
\(\rhd\) Soroljuk fel, hogy milyen esetekben tudunk kulcsképkocka animációt használni?
Lineáris interpoláció¶
A közbülső időpontokhoz tartozó értékeket a szomszédos időpontok értékei alapján lineáris interpolációval is meghatározhatjuk.
Megjegyzés
Nem szükségszerű, hogy csak a szomszédosakat vegyük figyelembe. Általánosan bármilyen interpolációs vagy approximációs módszert is használhatnánk.
Tegyük fel, hogy a \(t \in [t_i, t_{i+1}]\) időpontban lévő értéket szeretnénk meghatározni.
Megtehetjük, hogy ekkor \(\textbf{x}(t) = \textbf{x}(t_i)\) értékkel számolunk. Ez viszont nem fog folytonos mozgást eredményezni (legfeljebb akkor, hogy ha nagyon nagy felbontással vettük fel az ismert pontokat).
Lineáris interpolációt használva az alábbi képlettel számolhatunk:
Megjegyzés
A lineáris interpolációval mozgatott pont mozgása ugyan folytonos, de szögletes lehet. Ezen különféle paraméteres görbék, magasabb rendű interpolációs módszerek használatával lehet segíteni.
Fizikai animáció¶
Figyelem
A következőkben javaslatok szerepelnek a fizikai jelenségek modellezéséhez. Az alkalmazott számítási módok egyszerűsítések, helyenként heurisztikák. Nem szükségszerűen tükrözik a valós fizikai jelenségeket.
A következőkben a \(t\) érték a keretidőt, vagyis a képkockák kirajzolása között (pontosabban az előző update óta) eltelt időt adja meg másodpercben.
Egyenes vonalú egyenletes mozgás¶
Tegyük fel, hogy ismerjük a pontunk koordinátáit a \(t = 0\) időpillanatban, továbbá tudjuk a sebességét. Feltételezzük továbbá, hogy egyenes vonalú, egyenletes mozgást végez. Ekkor a \(t\) időpillanatban a pont a következőképpen számolható:
\(\rhd\) Tekintsük át a pong példa ide vonatkozó részét!
Forgatás¶
Az egyenes vonalú egyenletes mozgáshoz hasonlóan kezelhető a forgatás. Ekkor a sebesség szögsebesség lesz, és a pozíció helyett az elforgatás szögével számolhatunk.
Jelölje \(\varphi(t)\) az elforgatás szögét az idő függvényében, \(\textbf{r}\) pedig a forgatás sebességét. Tegyük fel, hogy ismerjük a szöget a \(t = 0\) időpillanatban. Ezek alapján a számítás:
Szabadesés¶
Feltételezzük, hogy a pontunkra gravitációs erő hat, és így szabadon esik. Jelölje a gravitációs erőt a \(\textbf{g}\) vektor. A pont aktuális sebességét jelölje \(\textbf{v}\).
A gyorsulást jelölje \(\textbf{a}\). Ennek mértékegysége \(\dfrac{m}{s^2}\), tehát azt mutatja meg, hogy egy másodperc alatt mennyit változik a sebesség.
Egyszerűen úgy tudjuk figyelembe venni, hogy ha a pont sebességét ennek függvényében változtatjuk:
A gyorsulást a testre ható erőből kaphatjuk. Ezt jelölje \(\textbf{F}\) (force). Ennek mértékegysége \(kg \cdot \dfrac{m}{s^2}\). A következőképpen számíthatjuk:
ahol az \(m\) a test tömegét jelöli (mass). A testre ható erők eredőjét azok összegéből kaphatjuk meg. (Hogy ha a testre csak a gravitációs erő hat, és a test tömegét egységnyinek tekintjük, akkor \(\textbf{a} = \textbf{g}\).)
Ütközés, pattanás, visszaverődés¶
Feltételezzük, hogy a pontunk egy adott síkon nem tud keresztül menni, arról visszapattan. Tegyük fel, hogy ez a sík a \(z = 0\) sík. Tegyük fel továbbá, hogy a pont aktuális pozíciója és a \(t\) időponttal későbbi pozíciója közötti szakasz metszi ezt a síkot. A metszéspontot jelölje \(\textbf{x}_c\), a mozgó pont aktuális időpontjához tartozó erőt pedig \(\textbf{F}_c\).
Ideális visszaverődést feltételezve az ütközés pillanatához tartozó erőt úgy kapjuk, hogy ha az \(\textbf{F}_c\) erő \(z\) komponensét negáljuk.
Hogy ha nem ideális visszaverődéssel szeretnénk számolni, akkor az erőt valamilyen \([0, 1)\) közötti értékkel szorozhatjuk.
A pont helyzetét a \(\textbf{x}_c\) pozícióra kellene állítani. Ez problémát jelenthet, hogy ha az újabb ütközésvizsgálatkor a pont „beleragad” a felületbe. Ezen úgy segíthetünk, hogy ha a pontot egy kis értékkel arrébb toljuk a felülettől (például a felületi normális mentén).
Surlódás, fékezés¶
Modellezni szeretnénk, ahogy egy test sebessége a surlódás következtében folyamatosan csökken. Feltételezzük a következőket.
A számításokat \(t = 0\) időpillanattól kezdjük.
A test sebessége az idő függvénye, kezdetben \(v(0) = v_0\).
A sebesség csökkenését az eltelt idővel tekintjük arányosnak. (Lehetne a sebességgel is.)
A test sebessége egységnyi idő alatt mindig konstansszorosára változik. Jelöljük ezt \(\lambda\)-val (\(\lambda \in [0, 1]\))!
Ezek alapján a test aktuális sebességét a következőképpen számíthatjuk ki:
Számítsuk ki a \(t\) időpillanatig megtett út hosszát! Ehhez az alábbi határozott integrál kiszámítására van szükség:
Behelyettesítve azt kapjuk, hogy
A programban a keretidő (\(\Delta t\)) alapján kell meghatározni, hogy a csúszó/fékező test sebessége milyen. Ehhez tehát ki kell számolni, hogy
mekkora a \(\Delta t\)-hez tartozó elmozdulásvektor, és hogy
mennyi lesz a sebessége a testnek a keretidő végén.
A \(v_0\) ilyen esetben már a keretidő elején lévő sebességet jelenti.
A \(\Delta t\) értékét érdemes másodpercben meghatározni. A \(\lambda\) ekkor azt fogja jelenteni, hogy másodpercenként hányszorosára fog változni a test sebessége. Például, hogy ha \(\lambda = 0.5\), akkor az azt jelenti, hogy a test sebessége másodpercenként a felére fog csökkenni.
A \(v(t) = v_0 \cdot \lambda^t\) helyett használhatunk \(e\) alapú exponenciális függvényt. Ekkor a \(\lambda\) jelentése (mértékegysége) más lesz, de a \(\lambda\) konstans ismeretében a számítások egyszerűsödnek.
Csontozás¶
Az animált karaktereink (például emberek, állatok, járművek) általában egymástól függetlenül mozgatható kisebb részekből állnak.
A karakter aktuális helyzetének megadásához ezeket fa struktúrába szervezhetjük.
Az összekapcsolt elemeket (a kapcsolódási pontokat) joint-oknak szokták nevezni.
Az animációhoz ezekből egy csontvázat (skeleton-t) hozunk létre. Tulajdonképpen ezt mozgatjuk, és ez alapján lehet kiszámolni a hozzá rendelt alakzatok, modell elemek helyzetét.
Egy joint-hoz jellemzően az alábbiak tartoznak:
egy tetszőleges transzformációs mátrixot,
a gyerekelemek (mint további joint-ok),
a megjelenítendő modell.
Egy lehetséges Joint
struktúra például az alábbi.
typedef struct Joint {
double translation[3];
double rotation[3];
double scale[3];
Model* model;
int texture_id;
Joint* children;
int n_children;
} Joint;
\(\rhd\) Milyen műveleteket érdemes megadni a Joint
struktúrához?
A karakterünk animálásához az alábbiakra hagyatkozhatunk.
Feltételezzük, hogy a gyerekelemekre az összes korábbi transzformáció hat.
A skeleton mélységi bejárásakor elegendő az aktuális transzformációs mátrixra alkalmazni az aktuális gyerekelem transzformációs mátrixát.
Azért, hogy ne kelljen inverz transzformációs mátrixokat számolni, a bejárás során minden csomóponthoz érve lementhetjük az aktuális transzformációs mátrixot (
glPushMatrix()
), a csomópontot elhagyva visszaállíthatjuk a transzformációs verem tetején lévőt (glPopMatrix()
).
Kérdések¶
A virtuális színterünkben mi az amit animálni tudunk? (Soroljon fel legalább 5-öt!)
Mi a keretidő fogalma és mértékegysége?
Hogyan tudjuk animáció készítése során megvalósítani az egyenes vonalú egyenletes mozgást?
Mi a szögsebesség mértékegysége? (Adjon meg legalább két alternatívát!)
Hogyan működik a kulcsképkocka animáció, és hozzá kapcsolódóan a lineáris interpoláció?
Hogyan tudjuk megvalósítani az egyenletes sebességgel történő forgatást?
Karakter animáció esetén mit nevezünk joint-nak és milyen adatok tartoznak hozzá?
Hogyan használható a transzformációs verem a karakterek animálásához?
Számítási feladatok¶
Ismerünk egy értéket a \(t_5\) és \(t_6\) időpontokban. Lineáris interpolációval hogyan határozhatjuk meg ennek az értékét a \(t\) időpontban, feltételezve, hogy \(t \in [t_5, t_6]\)?
Animálni szeretnénk, és ismerjük a \(\varphi_1 = 20^{\circ}, \varphi_2 = 80^{\circ}\) és \(\varphi_4 = 50^{\circ}\) szögeket, amelyek rendre az 1, 2 és 4 másodperchez tartoznak. Mennyi lesz a szög értéke 2.22 másodpercnél (lineáris interpolációt használva)?
Programozási feladatok¶
Animáljunk egy ingát (például színusz függvény segítségével), amelyik a \([-40, 40]\) szögtartományban mozog, és 3 másodperc alatt lendül ki az egyik végállásából a másikba!
Animáljunk egy pattogó labdát! Vizsgáljuk meg az ideális, és a nem ideális ütközés esetét is!
Próbáljuk meg animálni egy 4 lábú állat mozgását!