Android OpenGL Animace a ovládání pomocí dotykové obrazovky
Principy animace Animace udává pohyb objektů v čase Může být reprezentována mnoha způsoby Procedurální Pozice objektů se počítá přímo v programu Keyframe Animace je uložená jako data (klíčové snímky pozic objektů v čase) Program potom pozice jen interpoluje Další možnosti animace
Principy animace Pro účely animace je nutné mít přesnou časomíru Nemusí se jednat o absolutníčas a datum Důležité je rozlišení (méně než milisekundy)
Třída Timer Obsahuje jen dvě metody Reset() Nastaví čas na nulu f_time() Vrátíčas od vytvořeníčasovače nebo od Reset()
Třída Timer Implementace na všech platformách podobná Obsahuje čas a poslední časovou značku protected double time = 0; protected long laststamp; Časová značka se získá pomocí laststamp = System.nanoTime nanotime();
Třída Timer Při volání f_time() přečte se další časová značka long newstamp = System.nanoTime nanotime(); spočte se uplynulý čas od poslední značky long delta; if(newstamp >= laststamp) delta = newstamp - laststamp; else { delta = (Long.MAX_VALUE - laststamp) + (newstamp - Long.MIN_VALUE); // přetečení! }
Třída Timer Při volání f_time() uplynulý čas se připočte k času time += delta * 1e-9; poslední časová značka se přepíše aktuální laststamp = newstamp;
Třída Timer Pro každý snímek by se měl určovat čas pouze jednou V průběhu kreslení snímku se čas může změnit a mohlo by dojít k viditelnému oddělení objektů jež se měly pohybovat spolu Toto je obzvlášť rušivé protože rozdíl mezi časy je na pomezí přesnosti časovače a zpravidla mezi snímky kolísá
Jednoduchá animace
Jednoduchá animace Musíme upravit výpočet matice objektu Matrix.setIdentityM setidentitym(modelview, 0); Matrix.translateM translatem(modelview, 0, 0, 0, -2.5f); // nastavení pozice objektu Matrix.rotateM rotatem(modelview, 0, 30, 1, 0, 0); Matrix.rotateM rotatem(modelview, 0, 10, 0, 1, 0); // počáteční rotace Matrix.rotateM rotatem(modelview, 0, timer.f_time() * 10, 0, 1, 0); // + součin úhlové rychlosti a času
Dotyková obrazovka V mobilních aplikacích je často vyžadována interakce uživatele Lze přitom využít stejné principy jako při animaci pohybu objektů v čase Jen čas nahradíme pohybem prstu po dotykové obrazovce
Dotyková obrazovka Na platformě android pomocí třídy OnTouchListener Chceme se dotýkat přímo obrazu, voláme mglview.setontouchlistener setontouchlistener(listener); Potom musíme implementovat třídu, jejíž objektem je právě listener
OnTouchListener Třída s jedinou metodou public boolean ontouch(view view, MotionEvent event) objekt event obsahuje zajímavé metody getaction() typ akce: ACTION_DOWN, ACTION_MOVE a ACTION_UP (stlačení, pohyb, uvolnění) getx(), gety() Souřadnice středu prstu, v pixelech
OnTouchListener Událost MotionEvent typu ACTION_MOVE může obsahovat více než jeden bod pohybu (pohyb je snímán na vysoké frekvenci) getx() a gety() vracejí poslední souřadnice, pro animaci postačující Sled událostí stlačení, pohyb, uvolnění nemusí být nutně zachován, aplikace s tím musí počítat
Rotace objektu dotykem Postačí sledovat pozici dotyku a akumulovat rozdíly v pohybu float mx = 0, my = 0; // poslední hodnoty pozice (v pixelech) float mdeltax = 0, mdeltay = 0; // akumulované změny
Rotace objektu dotykem public boolean ontouch(view view, MotionEvent event) { } if(event.getaction() == MotionEvent.ACTION_DOWN) { mx = event.getx(); my = event.gety(); // uložení pozice dotyku } else if(event.getaction() == MotionEvent.ACTION_MOVE) { } float newx = event.getx(); float newy = event.gety(); // pohyb na novou pozici mdeltax += newx - mx; mdeltay += newy - my; // spočítáme rozdíl a akumulujeme mx = newx; my = newy; // zapamatujeme si novou pozici return true;
Rotace objektu dotykem Proměnné mdeltax a mdeltay lze použít přímo jako úhly na jednotlivých osách, případně jako argument funkce jež tyto úhly určí Při derivaci změn v čase lze jednoduše spočítat i setrvačnost rotace i poté co uživatel uvolnil dotyk, takže ovládaný pohyb se nezastaví najednou ale pozvolna Lze použít diferenci a klouzavý průměr
Konec