}w !"#$%&'()+,-./012345
Masarykova univerzita Fakulta informatiky
Využití pohybového snímače Kinect ve virtuální realitě Diplomová práce
Michal Vinkler
Brno, jaro 2012
Prohlášení Prohlašuji, že tato diplomová práce je mým původním autorským dílem, které jsem vypracoval samostatně. Všechny zdroje, prameny a literaturu, které jsem při vypracování používal nebo z nich čerpal, v práci řádně cituji s uvedením úplného odkazu na příslušný zdroj.
Michal Vinkler
Vedoucí práce: Mgr. Jiří Chmelík ii
Poděkování Na tomto místě bych rád poděkoval vedoucímu své práce, Mgr. Jiřímu Chmelíkovi, za jeho trpělivost, odborné vedení práce a poskytování cenných rad. Dále bych chtěl poděkovat všem členům laboratoře Interakce člověka s počítačem za ochotu a pomoc při řešení problémů a zejména za skvělou atmosféru, která v laboratoři vždy vládla. Také děkuji členům jMonkeyEngine fóra za trpělivé zodpovídání mých četných dotazů a všem, kteří mě při psaní podporovali.
iii
Shrnutí Pohybový senzor Microsoft Kinect pro Xbox 360 je zcela novým prvkem na poli přirozené interakce člověka s počítačem. Za pomoci různých typů senzorů dokáže zaznamenávat obraz, zvuk a vzdálenost jednotlivých objektů ve scéně a na základě těchto informací je schopen detekovat pohyby, identifikovat postavy a jejich obličeje, rozpoznat hlasové příkazy a gesta. Hlavním účelem této práce je prakticky ověřit možnosti spojení prostředků virtuální reality (stereoskopická projekce, snímání pohybu) se zvoleným grafickým a fyzikálním enginem (Java Monkey Engine společně s jBullet). Pro interakci uživatele s ukázkovou aplikací bylo zvoleno právě zařízení Kinect. Úvodní část práce se věnuje popisu senzoru, jeho hardwarovému návrhu a možným způsobům využití. Navazuje kapitola shrnující poznatky získané studiem použitých technologií. Ty jsou následně prakticky využity v části pojednávající o implementaci vybraných prostředků virtuální reality do Java Monkey enginu. V závěru jsou shrnuty dosažené výsledky a navržena možná rozšíření. Součástí práce je rovněž ukázková aplikace – pohybová hra, která demonstruje spojení daných technologií v praxi.
iv
Klíčová slova virtuální realita, virtual reality, VR, snímání pohybu, motion capture, pohybový senzor, motion sensor, Kinect, Java Monkey Engine, jME, jBullet, stereoskopická projekce, stereoscopic projection
v
Obsah 1 Úvod . . . . . . . . . . . . . . . . . . . . . . . . 2 Virtuální realita a pohybový senzor Kinect 2.1 Pojem virtuální realita . . . . . . . . . . . . 2.1.1 Druhy aplikací virtuální reality . . . 2.2 Přirozená interakce . . . . . . . . . . . . . . 2.3 Pohybový senzor Kinect . . . . . . . . . . . 2.3.1 Referenční návrh PrimeSensor . . . . 2.3.2 Hardwarové komponenty . . . . . . . 2.3.3 Omezení . . . . . . . . . . . . . . . . 2.4 Alternativní senzory . . . . . . . . . . . . . 2.4.1 Microsoft Kinect for Windows . . . . 2.4.2 Asus Xtion . . . . . . . . . . . . . . 2.5 Nové způsoby využití . . . . . . . . . . . . . 2.5.1 Telekomunikace . . . . . . . . . . . . 2.5.2 Mobilní robotika a detekce překážek 2.5.3 Lékařství . . . . . . . . . . . . . . . 2.5.4 Počítačová grafika . . . . . . . . . . 3 Použité technologie . . . . . . . . . . . . . . . 3.1 jMonkeyEngine . . . . . . . . . . . . . . . . 3.2 jBullet Physics Engine . . . . . . . . . . . . 3.3 Nifty GUI . . . . . . . . . . . . . . . . . . . 3.4 Stereoskopická projekce . . . . . . . . . . . . 3.5 OpenNI Framework . . . . . . . . . . . . . . 3.5.1 Modulární přístup . . . . . . . . . . 3.5.2 Produkční uzly . . . . . . . . . . . . 3.5.3 Produkční řetězce . . . . . . . . . . . 3.5.4 Volitelná funkcionalita . . . . . . . . 3.6 PrimeSense NITE Middleware . . . . . . . . 3.6.1 Vnitřní členění NITE . . . . . . . . . 3.6.2 NITE ovládací prvky . . . . . . . . . 4 Implementace . . . . . . . . . . . . . . . . . . . 4.1 Ukládání dat . . . . . . . . . . . . . . . . . 4.2 OpenNI a NITE . . . . . . . . . . . . . . . . 4.2.1 Aktualizace dat ve vlastním vlákně . 4.2.2 Rozhraní KinectListener . . . . . . . 4.3 Třída KinectHandler . . . . . . . . . . . . . 4.4 Implementace rozpoznávání gest . . . . . . . 4.5 jBullet Physics . . . . . . . . . . . . . . . . 4.6 Nifty GUI . . . . . . . . . . . . . . . . . . . 4.7 Stereoprojekce . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1 2 2 2 3 3 4 4 7 8 8 8 8 8 10 10 10 12 12 13 14 15 17 19 20 21 21 22 24 25 29 30 30 31 33 34 34 37 40 41 vi
5 A B
C
4.8 Třída Labyrinth . . . . . . . . . . . Závěr . . . . . . . . . . . . . . . . . . . 5.1 Možnosti rozšíření . . . . . . . . . . Doplňující snímky . . . . . . . . . . . Uživatelský manuál . . . . . . . . . . B.1 Začínáme . . . . . . . . . . . . . . B.1.1 Hardwarové nároky . . . . . B.2 Spuštění aplikace . . . . . . . . . . B.2.1 Java Monkey Engine projekt B.2.2 Zkompilovaný JAR soubor . B.2.3 Zkompilovaný EXE soubor . B.3 Popis ovládání . . . . . . . . . . . . B.3.1 GUI . . . . . . . . . . . . . B.3.2 Konfigurační soubory . . . . B.3.3 Přehrávání hudby . . . . . . B.3.4 Rozložení klávesnice . . . . Obsah přiloženého CD . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
42 43 43 44 50 50 50 50 50 52 52 52 54 56 56 57 59
vii
1 Úvod Pro virtuální realitu je kromě vytvoření co nejvěrohodnější iluze působící na smysly uživatele také velice důležitý opačný směr předávání informací, a to od člověka směrem k počítači. Možnost přirozené interakce uživatele se systémem hraje pro komplexní vjem zásadní roli. Vývoj rozhraní umožňující komunikovat s počítačem obdobně, jak jsme zvyklí interagovat s reálným světem, byl vždy považován za výzvu. Způsob ovládání založený pouze na gestech, pohybech a hlasových pokynech, u kterého nejsou potřeba žádné dálkové ovladače a jiná zařízení, umožní uživateli ještě hlouběji se ponořit do virtuálního světa. Zde přichází ke slovu herní senzor Microsoft Kinect pro Xbox 360 (dále označován jako „Kinect“), který přináší zcela nový pohled na možnosti ovládání systémů virtuální reality. Pomocí několika typů senzorů zaznamenává obraz, zvuk a vzdálenost jednotlivých objektů ve scéně; ze získaných dat pomocí specializovaných algoritmů detekuje pohyby, identifikuje postavy a jejich obličeje, rozpoznává hlasové příkazy. I když se jedná o novou technologii, která prozatím trpí množstvím neduhů, již nyní se kromě herního průmyslu objevují zajímavé možnosti využití i v dalších oblastech lidské činnosti. Koncept tohoto senzoru v sobě skrývá obrovský potenciál, a je tak velice pravděpodobné, že se během několika let stane běžnou součástí televizí, notebooků a dalších systémů a zcela přirozeně tak rozšíří možnosti ovládání těchto zařízení. Cílem této práce je prakticky ověřit možnosti spojení vybraných prostředků virtuální reality, konkrétně stereoskopické projekce a interakce pomocí přirozeného rozhraní, se zvoleným grafickým a fyzikálním enginem (Java Monkey Engine společně s jBullet). Interakce uživatele s ukázkovou aplikací je realizována pomocí senzoru Kinect. Úvodní část práce vysvětluje pojmy virtuální realita a přirozená interakce, dále se věnuje popisu senzoru, jeho hardwarovému návrhu a novým způsobům využití v telekomunikaci, mobilní robotice, lékařství či počítačové grafice. Navazuje kapitola shrnující poznatky získané studiem použitých technologií. Jsou zde popsány použitý grafický a fyzikální engine, knihovna pro tvorbu interaktivních menu a princip stereoskopické projekce. Pozornost je však soustředěna zejména na framework OpenNI v kombinaci s NITE middleware, které představují klíčové technologie pro práci s Kinectem. Tyto znalosti jsou následně prakticky využity v kapitole čtvrté, pojednávající o implementaci technologií virtuální reality do vybraného enginu. V této části je také popsána ukázková aplikace - pohybová hra, která demonstruje spojení daných technologií v praxi. V závěru jsou shrnuty dosažené výsledky a navržena další možná rozšíření a využití této práce.
1
2 Virtuální realita a pohybový senzor Kinect V následujících odstavcích se seznámíme s pojmy virtuální realita a přirozená interakce, popíšeme koncept herního ovladače Microsoft Kinect a nastíníme nové možnosti využití tohoto zařízení mimo herní průmysl. Také krátce představíme dnes dostupné alternativní senzory podobného návrhu.
2.1
Pojem virtuální realita
Virtuální realita (anglicky Virtual Reality, VR) představuje způsob interpretace komplexních informací, manipulace a interakce člověka s nimi prostřednictvím počítače. Tento poměrně široký pojem obecně označuje počítačem generované prostředí, které uživateli dokáže navodit pocit, že se jedná o prostředí reálné. Hlavním způsobem vytvoření této iluze je působení na lidské smysly, nejčastěji na zrak a sluch, případně také na hmat a rovnováhu [1]. Stereoskopická projekce dále umocňuje pocit skutečnosti virtuálního světa, je proto velice vítaným doplňkem každého systému virtuální reality. Více o technikách stereoskopie se lze dočíst v části 3.4. 2.1.1 Druhy aplikací virtuální reality •
Pohlcující (Immersive) Je spojena se speciálními technickými zařízeními, které se snaží v co největší míře potlačit naše vnímání reálného světa a místo něho vytvářejí obraz velice komplexního světa virtuálního [20]. Uplatnění zde nacházejí vysoce specializovaná zařízení, jako jsou helmy pro virtuální realitu typu HMD (head-mounted display) a na míru vytvořené repliky kokpitů závodních vozů nebo pilotních kabin, sloužící pro co nejvěrohodnější simulaci určité situace.
•
Rozšiřující (Augmented) Je označení používané pro zobrazení kombinace obrazu reálného světa s prvky virtuální reality. Základem takového systému bývá kamera snímající skutečný obraz, který je doplněný o digitální objekty existující pouze ve virtuálním prostoru [20]. Nabízí se nespočet způsobů možného využití, ať už se jedná o letecký, vojenský, zábavní průmysl, či vědu a vzdělání.
•
Jednoduchá (Desktop-based) Zahrnuje zobrazení 3D scény na běžném monitoru počítače bez použití speciálních zařízení pro umocnění pocitu pohlcení virtuální realitou. Pro interakci slouží pouze standardní zařízení, jako jsou klávesnice a myš. Příkladem může být většina moderních počítačových her [20]. 2
2. Virtuální realita a pohybový senzor Kinect
2.2
Přirozená interakce
Pojmem přirozená interakce (anglicky Natural Interaction) rozumíme koncept, ve kterém je komunikace člověka s počítačem založena na lidských smyslech, zejména pak na zraku a sluchu. Vstupní zařízení, jako jsou herní ovladače, klávesnice a myš ztrácejí v rámci přirozené interakce svůj smysl a stávají se zastaralými [18]. Uživatel dokáže ovládat cílové zařízení pouze pomocí svého hlasu a pohybů těla. Každodenní prvky založené na přirozené interakci člověka s počítačem zahrnují: •
Rozpoznání hlasových příkazů a ovládání spotřební elektroniky pomocí těchto příkazů;
•
rozpoznání předem definovaných gest a reakce na ně;
•
sledování pohybu těla a přenesení jednotlivých pohybů uživatele na virtuální postavu, např. pro herní účely.
Zcela novým prvkem ve způsobu přirozené interakce člověka s počítačem je pohybový senzor Kinect. S cenou srovnatelnou s levným mobilním telefonem dokáže za určitých podmínek konkurovat profesionálním systémům pro snímání pohybu řádově stonásobně dražších. Následující část této kapitoly je věnována popisu tohoto zařízení.
2.3
Pohybový senzor Kinect
Herní senzor Microsoft Kinect pro Xbox 360 lze považovat za revoluci ve způsobu interakce uživatele a ovládaného zařízení, ať už se jedná o herní konzoli Xbox 360 nebo osobní počítač. Kinect byl poprvé představen na herní konferenci Electronic Entertainment Expo 1. června 2009, v té době ještě označován kódovým jménem „Projekt Natal“. Shane Kim, generální ředitel herní divize Microsoftu, tehdy o Kinectu prohlásil, že „vytyčuje nový způsob ovládání her pomocí řeči, gest a celého těla“ [15]. Kinect je periferní zařízení vyvinuté firmou Microsoft pro herní konzoli Xbox 360. Pomocí RGB kamery a pole čtyř mikrofonů zaznamenává obraz a zvuk; hloubkový senzor mu umožňuje určovat vzdálenost jednotlivých objektů ve scéně. Na základě analýzy získaných dat dokáže Kinect identifikovat postavy ve scéně, sledovat pohyb jednotlivých částí těla uživatele, rozpoznat předem definovaná gesta a hlasové příkazy. Hráč tak může ovládat hru pouze svým tělem, bez nutnosti používat další ovladač. Snímání a detekce probíhá bez nutnosti zadání jakýchkoliv dodatečných informací o uživateli nebo okolním prostředí [11]. Pracovní označení latinského původu „Natal“ (v překladu znamená „být zrozen“) bylo 13. června 2010 nahrazeno finálním jménem senzoru, Kinect. To vzniklo spojením dvou klíčových slov popisujících tento systém – „kinetic“ (pohybový) a „connect“ (propojit). Prodej pro Severní Ameriku začal 4. listopadu 2010, na evropský trh byl produkt uveden o týden později, 10. listopadu 2010 [15]. Na rozdíl od drtivé většiny ostatních systémů pro snímání pohybu, Kinect nevyžaduje, aby uživatel nosil speciální typ oděvu (např. s jednotlivými částmi odlišenými barevně) nebo 3
2. Virtuální realita a pohybový senzor Kinect aby měl na svém těle připevněny jakékoliv značky. I přes některá omezení, tato vlastnost spolu s nízkou pořizovací cenou (na jaře 2012 přibližně 3000 Kč) činí z Kinectu vskutku unikátní zařízení. Prodání celkem osmi milionů kusů v prvních 60 dnech od uvedení na trh zajistilo Kinectu Guinessův světový rekord v kategorii „nejrychleji prodávaná spotřební elektronika“ [11]. Způsob práce jednotlivých systémů pro snímání pohybu a popis problematiky snímání pohybu obecně lze nalézt například v [22]. 2.3.1 Referenční návrh PrimeSensor Zařízení Microsoft Kinect je postaveno na referenčním designu PrimeSensor [19] izraelské firmy PrimeSense1 . Toto řešení se skládá jednak ze senzorové komponenty produkující obrazové a zvukové informace, a jednak ze softwarové komponenty starající se o zpracování snímaných dat. PrimeSense 3D Sensor je referenční zařízení, které umožňuje počítači vidět a slyšet okolní svět ve třech dimenzích a jednotlivé obrazové i zvukové vstupy spojit za pomoci softwarové komponenty do výsledného vjemu obdobným způsobem, jako to dělají lidé [19]. Výstupem 3D sensoru je tzv. hloubková mapa scény. Hloubkovou mapu lze interpretovat jako obraz, v němž každý pixel nese informaci o vzdálenosti objektu (který se nachází na souřadnicích daného pixelu, pokud by byl zachycen běžnou RGB kamerou) od samotného senzoru. Hardwarová komponenta je v podstatě beze zbytku obsažena v těle snímače Kinect. Softwarovou komponentu představuje NITE middleware, které je dále rozebráno v 3.6. Nyní si podrobněji popišme samotné zařízení. 2.3.2 Hardwarové komponenty Klíčové hardwarové komponenty Kinectu jsou RBG kamera, hloubkový senzor, pole skládající se ze čtyř mikrofonů, motorizovaná základna a SoC (System-on-a-chip) procesor PS1080 firmy Primesense. Jejich rozmístění na těle Kinectu si lze prohlédnout na obrázku 2.1.
Obrázek 2.1: Umístění hardwarových komponent v senzoru Kinect. 1.
http://primesense.360.co.il/
4
2. Virtuální realita a pohybový senzor Kinect RGB kamera zachycuje standardní dvourozměrný obraz scény, který je používán pro identifikaci obličejů a zobrazování reálného pozadí na obrazovce během hraní. Jednou z výhod funkce rozpoznávání obličejů je možnost přihlášení se do svého herního účtu pouze tím, že se uživatel postaví do zorného pole kamery2 . Standardním výstupem této kamery je video o snímkové frekvenci 30 Hz, rozlišení 640 × 480 obrazových bodů a 24bitové barevné hloubky. Hloubkový senzor se skládá ze dvou klíčových komponent; jsou jimi zdroj infračerveného (IR) záření a IR snímač. Zdrojem IR záření je laser, který promítá síť bodů ve směru zorného pole kamery [4]. Síť bodů zachycenou pomocí infrakamery můžeme vidět na obrázku 2.2.
(a)
(b)
Obrázek 2.2: Síť bodů emitovaná IR zářičem. (a) Celkový pohled. (b) Detail vzoru. Převzato z [2]. Na základě záření odraženého od objektů ve scéně, které detekuje monochromatický CMOS senzor, je vytvořena hloubková mapa. Ta specifikuje vzdálenost povrchů jednotlivých objektů ve scéně od snímače. Většina systémů pro měření vzdálenosti objektů vytváří hloubkovou mapu scény na základě časové prodlevy, s níž se vrací emitované světlo, které se odrazilo od objektů v prostoru. Kinect však pro další zpřesnění vytvářeného 3D hloubkového obrazu navíc do vyzařovaného IR paprsku kóduje určitou informaci a analyzuje následné zkreslení odraženého signálu [11]. Hloubková mapa je dále zpracovávána Primesense procesorem. Rozlišovací schopnost tohoto řešení je vskutku překvapivá – podél osy Z (tzn. osy určující vzdálenost od senzoru) je přibližně jeden centimetr, zatímco podél os X a Y se počítá na milimetry. Obrazové úhly senzoru jsou 57° horizontálně a 43° vertikálně [14]. Při minimální možné vzdálenosti od senzoru (cca 0,8 m) tak Kinect v horizontální rovině snímá prostor o přibližné délce 87 cm, ve vertikální rovině pak 63 cm. Při daném rozlišení hloubkové kamery lze snadno dopočítat, že na jeden obrazový pixel připadá pouze 1,3 mm snímaného prostoru. S rostoucí vzdáleností však rozlišovací schopnost senzoru klesá. Snímky 2.
http://gamesforkinect.org/kinect-information/how-does-the-kinect-sensors-work/
5
2. Virtuální realita a pohybový senzor Kinect jsou generované ve VGA rozlišení s 16bitovou hloubkou při frekvenci 30 Hz [4]. Na obrázku 2.3 lze vidět schematický postup při vytváření hloubkové mapy.
Obrázek 2.3: Schematický postup při vytváření hloubkové mapy. Převzato z [19]. Celkem čtyři mikrofony jsou připevněny podél spodní strany těla senzoru; tři jsou lokalizovány na pravé straně, zbývající na levé. Zvolené rozložení mikrofonů se ukázalo být optimálním při rozpoznávání směru, ze kterého zvuk přichází, a určilo výsledný tvar a rozměry přístroje. Kinect navíc dokáže rozlišovat příkazy od jednotlivých hráčů, filtrovat okolní šum (noise suppression) a eliminovat ozvěny (acoustic echo cancellation) [14]. Výstupem každého mikrofonu je zvukový kanál o parametrech 16 kHz, 16bit mono PCM (Pulse Code Modulation). V základně celého zařízení se nachází malý servomotor, který je schopen naklonit tělo Kinectu ve vertikální rovině až o 27° v kladném nebo záporném směru od vodorovné osy. Díky naklonění do potřebného úhlu dokáže Kinect kompenzovat rozdíly ve výšce, v jaké je umístěn, a zajistit tak, aby se sledovaný uživatel nacházel vždy co nejvíce v zorném poli kamer [15]. Srdcem Kinectu je bezpochyby čip PS1080 SoC3 . V něm je integrována extrémně paralelní výpočetní logika přijímající infračervený obraz s kódovanou informací na vstupu, ze kterého vypočítává hloubkový obraz scény ve VGA rozlišení. Tento proud navíc synchronizuje s výstupem z RGB kamery a zaznamenaným audiem. Výsledná data jsou předávána cílovému zařízení pomocí USB 2.0 rozhraní. Čip není limitován procesorovým výkonem cílového zařízení – veškeré algoritmy pro získání hloubkového obrazu jsou vypočítávány přímo na PS1080, zatímco host obstarává pouze komunikaci po USB rozhraní. Na obrázku 2.4 čtenář nalezne diagram zapojení jednotlivých komponent. 3.
http://www.primesense.com/en/component/content/article/9-solutions/114-the-ps1080
6
2. Virtuální realita a pohybový senzor Kinect
Obrázek 2.4: Diagram zapojení jednotlivých komponent pro SoC PS1080. Převzato z [19]. Zařízení má odběr 12 W, což je více energie, než je schopen dodat standardní USB port. Při připojení k PC je tedy nutné použít dodávaný adaptér. Webový portál iFixit zdokumentoval kompletní postup rozebrání celého senzoru s detailními fotografiemi jednotlivých součástí, k nalezení na4 . 2.3.3 Omezení Softwarová komponenta referenčního návrhu (viz. 2.3.1) dokáže na základě informací z hloubkového obrazu ve scéně detekovat lidské postavy. V reálném čase porovnává obraz hloubkové kamery s databází 20 milionů obrazů s 200 různými pózami5 . Výsledkem je identifikace významné části těla, jako jsou hlava, trup, nohy a ruce. Z těchto informací pak vytvoří kostru uživatele, skládající se až z dvaceti uzlů, kterou dále předává cílové aplikaci. I když nemá přímý výhled na všechny části těla, Kinect dokáže s určitou pravděpodobností odhadnout, kde se jednotlivé končetiny nachází. Při použití oficiálního SDK je počet rozpoznaných uživatelů ve scéně softwarově omezen na šest, z toho maximálně dva mohou být v daném okamžiku sledováni (tzn. je pro ně vypočítávána kostra). Firma Primesense však uvedla, že toto omezení není dáno přímo hardwarovým návrhem. Teoreticky, při dostatečném výpočetním výkonu, je počet sledovaných hráčů neomezený6 . Praktická vzdálenost, na kterou je Kinect schopen sledovat uživatele, se pohybuje v rozmezí 1,2 m až 3,5 m (za specifických podmínek lze rozsah zvětšit až na 0,8-6 m). 4. 5. 6.
http://www.ifixit.com/Teardown/Microsoft-Kinect-Teardown/4066/1 http://gizmodo.com/project-natal http://www.joystiq.com/2010/06/19/kinect-how-it-works-from-the-company-behind-the-tech/
7
2. Virtuální realita a pohybový senzor Kinect Prostor využitelný pro hraní je přibližně 6 m2 . Pro jednoho hráče je ideální vzdálenost od senzoru 1,8 m, při sledování dvou hráčů pak 2,4 m, viz7 .
2.4
Alternativní senzory
2.4.1 Microsoft Kinect for Windows Microsoft Kinect for Windows je v prodeji od 1. února 2012. Jedná se o mírně upravenou verzi původního senzoru. Nejpodstatnější změnou je update firmware, který nyní umožňuje hloubkovému senzoru rozlišovat objekty vzdálené pouhých 40 cm bez jakýchkoliv artefaktů v hloubkové mapě. Jelikož obsahuje totožné snímače jako jeho předchůdce, FOV8 kamer se nezměnil. Méně podstatnými změnami jsou oficiální potvrzení kompatibility zařízení s Kinect for Windows SDK a úprava USB konektoru pro možnost přímého připojení Kinectu k PC. Podrobnější informace lze najít na9 . 2.4.2 Asus Xtion Xtion10 je pohybový senzor konkurenční firmy Asus založený taktéž na PrimeSensor referenčním návrhu. Hardwarově se tedy jedná o velice podobné zařízení. Levnější varianty oproti plně vybavenému Xtion PRO Live postrádají RGB kameru a mikrofon. Xtion je primárně určen pro stolní počítače, uveden na trh byl v dubnu 2011. Firma Asus se tímto výrobkem snažila (vcelku neúspěšně) využít zaváhání Microsoftu s uvolněním Kinectu pro PC platformu a zaplnit tak volné místo na trhu.
2.5
Nové způsoby využití
Původně zamýšlené použití Kinectu je zřejmé – definovat zcela nový způsob ovládání her. Jeho možnosti jsou však mnohem větší. Již zanedlouho poté, co byl vydán první ovladač s otevřeným zdrojovým kódem pro připojení senzoru k počítači, se objevily zajímavé projekty, které ukazují nespočetné množství různých aplikací tohoto původně ryze herního periferního zařízení. Jednotliví nadšenci i celé týmy akademiků po celém světě začaly vytvářet aplikace, které ukazují obrovský potenciál Kinectu, v podstatně důležitějších oblastech lidské činnosti, než pouze pro pobavení a zábavu. Uveďme nyní několik příkladů. 2.5.1 Telekomunikace Andrew Maimone a Henry Fuchs, zaměstnanci University of North Carolina at Chapel Hill, vytvořili systém, který za pomoci několika spolupracujících senzorů dokáže zachytit kompletní 3D obraz snímané scény v reálném čase. Ten je pak zobrazován na stereo displeji 7. 8. 9. 10.
http://support.xbox.com/cs-CZ/kinect/setup-and-playspace/getting-started Field of view, v překladu „zorné pole“, je část prostoru, kterou je oko anebo jiné optické zařízení schopné zachytit http://www.microsoft.com/en-us/kinectforwindows/news/faq.aspx http://www.asus.com/Search/?SearchKey=xtion
8
2. Virtuální realita a pohybový senzor Kinect bez nutnosti použití polarizačních brýlí. Stereo obraz je vhodně upravován v reálném čase na základě sledování pohybu hlavy pozorovatele a vytváří tak dojem, jako bychom se do snímané místnosti dívali skrz okno (obecně je tento způsob komunikace nazýván teleprezence). Senzory jsou rozmístěny tak, aby pokrývaly snímaný prostor z různých úhlů s překrývajícím se zorným polem jednotlivých kamer. Speciálně vyvinutý algoritmus poté dokáže spojit jednotlivé hloubkové mapy a rekonstruovat z nich kompletní trojrozměrný obraz [13]. Na obrázku 2.5 lze vidět realizaci tohoto návrhu. Videoukázku a navazující projekty autorů lze najít na11 .
(a)
(b)
(c)
(d)
Obrázek 2.5: Ukázka 3D teleprezence. (a) Pokrytí snímané scény. (b-c) Průběh komunikace. (d) Pohled z ostrého úhlu. Převzato z [13].
11. http://www.cs.unc.edu/~maimone/research.html
9
2. Virtuální realita a pohybový senzor Kinect 2.5.2 Mobilní robotika a detekce překážek Pattrick Bouffard, absolvent University of California, Berkeley, připevnil Kinect k čtyřrotorové helikoptéře nazývané quadrotor a získávanou hloubkovou mapu použil k určení letové hladiny a k předcházení kolizí. Helikoptéra je schopna autonomního pohybu podél předem definovaných bodů. Pokud je detekována překážka, quadrotor zastaví; po odstranění překážky automaticky pokračuje v letu. Výška letu je vypočítávána pouze na základě informací poskytovaných Kinectem [3]. 2.5.3 Lékařství Po celou dobu operativního zákroku musí chirurgovy rukavice zůstat sterilní, aby se zabránilo případné kontaminaci rány. Pokud chce lékař manipulovat s radiologickými snímky, musí se dotýkat klávesnice, myši či dotykové obrazovky, a riziko přenesení infekce vzrůstá. Projekty Virtopsy12 a KineMED13 našly řešení tohoto problému – pomocí snímače Kinect a bezdrátových sluchátek vytvářejí bezdotykové rozhraní pro ovládání specializovaných programů pro prohlížení radiologických snímků. Za použití jednoduchých gest a hlasových příkazů je chirurg schopen procházet určitou sekvenci snímků nebo přepínat mezi jednotlivými sekvencemi, aniž by se musel čehokoliv dotknout. 2.5.4 Počítačová grafika V současné době již existuje několik na sobě nezávisle vyvíjených projektů, které používají hloubkový senzor pro vytváření 3D modelů podle skutečných předloh v reálném čase. Mezi nejznámější patří ReconstructMe14 (vyvíjený firmou Profactor), KinectFusion15 (produkt z dílen Microsoft Research) a jeho open-source varianta KinFu16 (zastřešen organizací Pointclouds.org). Všechny pracují na stejném principu – rekonstruovaný objekt postupně otáčíme v zorném poli kamery nebo naopak pohybujeme samotným Kinectem a statický objekt nasnímáme ze všech stran. Vygenerovaný model lze exportovat do běžných formátů (např. OBJ, STL) a dále s nimi pracovat v jakémkoliv grafickém programu. Modely je samozřejmě nutné ručně doopravit, odstranit možné artefakty a nanést textury. I přesto je ale rychlost, s jakou jsme schopni vytvořit 3D modely jednotlivých objektů nebo i celých místností, vskutku fascinující. Ukázku modelování pomocí programu ReconstructMe lze shlédnout na obr. 2.6 Závěrem zmiňme, že vznikla také celá řada dalších více či méně zdařilých programů používajících Kinect pro další různorodé účely, např. pro ovládání již stávajících aplikací či her, které byly původně navrženy pro manipulaci pomocí klávesnice a myši (a pro vytvoření rozšířené virtuální reality obecně); pro snímání pohybu za účelem vytvoření pohybových 12. 13. 14. 15. 16.
http://www.qj.net/qjnet/xbox-360/medical-practice-finds-use-for-kinect-hack.html http://www.kinecthacks.net/kinemed-gestural-interface-for-operating-rooms/ http://reconstructme.net/ http://research.microsoft.com/en-us/projects/surfacerecon/ http://www.brekel.com/?p=749
10
2. Virtuální realita a pohybový senzor Kinect
(a)
(b)
Obrázek 2.6: Modelování pomocí programu ReconstructMe. (a) Obraz viděný RGB kamerou, (b) 3D model vytvářený v reálném čase (snímaný prostor je omezen na 1 m3 ). animací (motion capture), aj. Stránky dedikované těmto projektům jsou např. http://www. kinecthacks.com/, http://kinect.dashhacks.com/ a http://kinect-hacks.net/.
11
3 Použité technologie V této kapitole jsou stručně popsány grafický a fyzikální engine použité při tvorbě ukázkové aplikace, hlavní pozornost je však soustředěna na framework OpenNI v kombinaci s NITE middleware, což jsou klíčové technologie při práci s Kinectem. Z důvodu neexistence jednotného českého názvosloví bylo použito názvosloví původní, doplněné o český překlad.
3.1
jMonkeyEngine
jMonkey Engine (zkráceně jME) [9] je vysoce výkonné, robustní rozhraní pro programování Java aplikací, jehož autoři se inspirovali knihou 3D Game Engine Design od Davida Eberlyho [19]. Jeho vznik byl podmíněn absencí plnohodnotných grafických enginů napsaných v Javě. V současné době je aktuální verze 3.0. Klíčové vlastnosti: •
jME je projekt s otevřeným zdrojovým kódem (tzv. open source), který je distribuován pod BSD1 licencí. Je určen k volnému použití pro soukromé, vzdělávací i komerční účely.
•
Vývoj pro různé platformy (web, PC, mobilní telefony) s minimálními dodatečnými úpravami kódu. Aplikaci napsanou v jME lze používat na jakémkoliv zařízení s Java Virtual Machine podporujícím OpenGL 2+.
•
Architektura založená na shaderech v souladu se současnými grafickými standardy.
•
Na míru vytvořené SDK – kompletní vývojové prostředí s vizuálními editory, integrovanými nástroji a zásuvnými pluginy usnadňujícími vývoj her a aplikací.
Kompletní seznam všech vlastností společně s prezentačním videem lze nalézt na2 . Díky přítomnosti abstraktní vrstvy je možno použít jakýkoliv systém pro vykreslování scény. Programátor si tak může zvolit vlastní vykreslovací systém a integrovat jej do jME. V současné době je z hlediska integrace a spektra dostupných funkcí zcela jednoznačně preferováno LWJGL (Lightweight Java Game Library). LWJGL je knihovna napsaná v jazyce Java; využívá zejména knihovny OpenGL a OpenAL. Jejími stěžejními vlastnostmi jsou vykreslování 3D grafiky, ale také přehrávání 3D zvuku. Dále poskytuje rozhraní pro komunikaci s různými vstupními zařízeními (klávesnice, myš, joystick). jME používá architekturu grafu scény (tzv. scene graph architecture). Tento graf umožňuje organizaci herních dat ve stromové struktuře, ve které rodičovský uzel může obsahovat neomezený počet potomků, ale každý potomek má pouze jednoho rodiče. Listy v jME slouží pro uložení geometrie objektů (souřadnic vrcholů, textur, normál). Vnitřní 1. 2.
http://jmonkeyengine.org/wiki/doku.php/bsd_license http://jmonkeyengine.com/engine/
12
3. Použité technologie uzly navíc nesou informace o obalových tělesech a stavech objektů. Poslední dvě jmenované vlastnosti ovlivňují chování všech potomků daného uzlu. Změnou informace v jediném uzlu tak můžeme měnit rozsáhlé části scény – např. změnou pozice určitého uzlu se odpovídajícím způsobem posunou všichni potomci (relativní pozice potomků vůči rodiči se nemění). Hierarchická struktura uzlů umožňuje jednoduché odpojení celých větví stromu, které následně nebudou zpracovány. jME také podporuje široké množství grafických efektů, jako jsou bump mapping, multitexturing či normal mapping. Jednoduše lze používat částicové systémy (simulace deště, sněhu, oblaků), stíny, odlesky, efekt vodní hladiny nebo mlhy. Podrobnější informace o jMe lze nalézt například v práci V. Hynka [7], která obsahuje popis stěžejních tříd pro vývoj aplikací, dále popis integrace LWJGL, fungování grafu scény, správy stavů a obalových těles.
3.2
jBullet Physics Engine
V dnešní době je fyzikálně reagující prostředí základem velkého množství her a dalších aplikací. Objekty ve scéně jsou vystavovány působení gravitace, tření a dalších fyzikálních sil a získávají tak momenty hybnosti projevující se změnou rychlosti, dochází ke srážkám těles atd. Hlavním úkolem fyzikálního enginu je detekce kolizí, určení interakcí na základě kolizí a výpočet změn transformací pro určité objekty ve scéně. jMonkeyEngine 3 má zabudovanou podporu pro jBullet Physics3 (port Bullet Physics4 do Javy). Současná implementace podporuje pouze softwarově počítanou fyziku, do budoucna se však počítá s implementací hardwarové akcelerace pomocí GPU. Fyzikální engine je (stejně jako původní Bullet) distribuován pod Zlib5 licencí (volné použití pro osobní i komerční účely). jBullet je počítán v samostatném vlákně, implicitně při 60 fps. Rychlost běhu fyzikálního enginu není závislá na aktuální rychlosti běhu celé aplikace a nevynucuje synchronizaci s hlavní aplikací na stejné snímkové frekvenci. Aktualizace fyzikálního stavu a synchronizace s hlavní aplikací probíhá v tomto pořadí [10]:
3. 4. 5.
1.
Zaslání událostí týkajících se kolizí zaregistrovaným posluchačům (metoda BulletAppState.update()).
2.
Uživatelem definované aktualizace fyziky (metoda simpleUpdate() v hlavní smyčce, update() ve třídách Controls, AppStates).
3.
Aktualizace fyzikálních updateLogicalState()).
4.
Výpočet dalšího kroku fyziky (před nebo paralelně s voláním metody Application.render()).
vlastností
objektů
v
grafu
scény
(metoda
http://jbullet.advel.cz/ http://bulletphysics.org/wordpress/ http://opensource.org/licenses/zlib-license.php
13
3. Použité technologie Pro každý objekt v grafu scény, který má být kontrolován fyzikálním enginem, musíme provést následující kroky: 1.
Vytvořit vhodnou kolizní geometrii.
2.
Na základě kolizní geometrie a požadované hmotnosti tělesa definovat ovládací prvek (PhysicsControl).
3.
Přiřadit danému objektu ovládací prvek.
4.
(Volitelně) Zařadit ovládací prvek do určité kolizní skupiny a definovat, s jakými skupinami má kolidovat.
5.
Přidat ovládací prvek do množiny všech objektů kontrolovaných fyzikálním enginem.
6.
Vložit objekt do grafu scény.
7.
(Volitelně) Implementovat rozhraní třídy PhysicsCollisionListener pro možnost reakce na události označující kolizi s jinými tělesy.
Kolizní geometrie představuje obalové těleso objektu využívané pro účely fyzikální simulace. Pokud dojde ke kontaktu dvou takových těles, nastává kolize. jBullet nabízí jak základní tvary geometrií (koule, kvádr) tak i tvary vytvořené na základě trojúhelníkové sítě objektu (přesně kopírující tvar objektu). Pro každý ovládací prvek lze individuálně nastavit koeficient tření, odrazivost a také velikost a směr gravitační síly působící na jemu přiřazený objekt. Popis jednotlivých kolizních geometrií, ovládacích prvků a dalších implementačních detailů lze nalézt v [10].
3.3
Nifty GUI
Nifty GUI je knihovna napsaná v programovacím jazyku Java pro vytváření interaktivních uživatelských rozhraní. Je dobře integrována do mnoha existujících systémů včetně Java Monkey Engine (mezi další patří např. LWJGL, JOGL, Slick2D a Java2D). Navíc může být jednoduše začleněna do dalších – stačí implementovat připravené rozhraní [6]. Nifty GUI staví na třech fundamentálních prvcích – obrazovkách, vrstvách a panelech. Základní koncept je následující: •
Na nejvyšší úrovni je Nifty GUI tvořeno jednou nebo více obrazovkami. V daném čase může být aktivní pouze jedna obrazovka; každá má definovanou vlastní kontrolní třídu.
•
Obrazovka pracuje s jednou nebo více vrstvami. Vrstvy jsou kontejnery, které definují rozmístění obsažených prvků (vertikální, horizontální nebo centrované). Jednotlivé vrstvy se mohou překrývat, ale nemohou se zanořovat do sebe (v jedné vrstvě nemůže být definována další vrstva). 14
3. Použité technologie •
Každá vrstva obsahuje jeden nebo více panelů. Ty stejně jako vrstvy určují rozmístění svých prvků. Panely se nemohou překrývat, ale mohou tvořit hierarchickou strukturu.
•
Panely jsou kontejnery pro všechny ostatní prvky (např. obrázky, textové popisky, ovládací prvky).
Schematické znázornění konceptu lze vidět na obrázku 3.1.
Obrázek 3.1: Základní koncept výstavby Nifty GUI. Převzato z [8]. Samotný návrh GUI je uložen v XML souborech (používajících na míru modifikovanou strukturu) nebo může být generován přímo z aplikace. Programátorem napsaný kód (který je součástí kontrolní třídy starající se o správu GUI) pak definuje způsob, jakým se bude reagovat na události generované rozhraním (typicky např. po kliknutí na tlačítko či posunutí kurzoru myši na určitý objekt). Takto můžeme definovat funkcionalitu samotného grafického rozhraní – ať už se jedná o programové akce, které budou vykonány v naší aplikaci, nebo o změny ve vzhledu Nifty GUI (zobrazení či skrytí některých vrstev, změna textových popisků, fontů, obrázků, atd.). Dále je k dispozici velké množství efektů, které lze přiřadit jednotlivým komponentám – např. efekt zvýraznění při výběru myší nebo plynulé posunutí prvku mimo obrazovku při skrytí příslušné vrstvy. Nifty GUI nabízí kromě standardních ovládacích prvků (tlačítko, textové pole, scrollbar, checkbox, radiobutton, atd.) navíc možnost vytvořit si ovládací prvky zcela vlastní. Umožňuje také vytvářet displeje typu HUD (head-up display) typické pro hry.
3.4
Stereoskopická projekce
Pro vnímání prostoru je kromě sluchu klíčovým smyslem zrak. Princip prostorového vidění je založen na schopnosti mozku porovnat obraz z levého a pravého oka a následně z nich vytvořit prostorový vjem. Oči dospělého člověka jsou od sebe vzdáleny cca 7 cm; díky tomu získáváme z každého oka pohled z mírně odlišného úhlu v horizontálním směru. Na základě 15
3. Použité technologie tohoto rozdílu v porovnávaných obrazech jsme schopni určit vzdálenost jednotlivých objektů a vnímat tak prostorový obraz. Tato schopnost se nazývá binokulární disparita a je jedním z tzv. fyziologických klíčů (neboli vrozených dovedností člověka pro vnímání prostoru). Mezi další patří schopnost oka akomodace, konvergence a pohybová paralaxa. Mimo to se však mozek snaží určit správnou hloubku a geometrii scény na základě dřívějších zkušeností. Vodítka v obraze pomáhající k přesnějšímu určení prostoru se nazývají psychologické klíče. Zejména se jedná o umístění světla a stínu, relativní velikost a překrývání viděných předmětů, perspektivu či gradient textury. Podrobný popis těchto klíčů lze nalézt v [12] a [17]. Stereoskopické vidění se dá simulovat i v umělých podmínkách – právě tímto úkolem se zabývá stereoskopie. Slovo stereoskopie má původ v řeckých výrazech stereos (pevný, trojrozměrný) a skopien (vidět). Přestože je pojem stereo hojně používán především u způsobu záznamu zvuku, původně byl spjat s obrazem. Princip prostorového vidění je znám již přes 160 let [12]. Cílem je zobrazit prostorová dat tak, aby uživatel správně vnímal „hloubku“ jednotlivých objektů ve scéně. Každé oko tak musí vidět mírně odlišný obraz sledované scény – levý a pravý pohled musejí být vzájemně posunuty ve vodorovné rovině. To má za následek, že ve dvou korespondujících záběrech dochází k relativnímu horizontálnímu posunu některých objektů (v závislosti na jejich vzdálenosti od uživatele). Vzdálenost mezi souhlasnými prvky levého a pravého záběru se označuje paralaxa. Označme vzdálenost středů čoček jako d a velikost paralaxy jako p. Rozlišujeme čtyři druhy paralaxy: •
Nulová paralaxa – dva korespondující body nejsou vzájemně posunuté, osy očí konvergují na zobrazovací rovinu (tzv. rovina konvergence).
•
Pozitivní paralaxa – optické osy očí konvergují za zobrazovací rovinu (ke spojení obrazů dochází až za plátnem); na zobrazovací rovině je obraz pro pravé oko napravo a obraz pro levé oko nalevo.
•
Negativní paralaxa – opakem pozitivní paralaxy. Optické osy očí konvergují před zobrazovací rovinu (obraz „vystupuje“ před plátno).
•
Divergentní paralaxa – speciální případ pozitivní paralaxy, při které vzdálenost mezi korespondujícími prvky přesahuje rozestup očí pozorovatele. Osy očí by v takovém případě musely překročit svou limitní paralelní polohu, přičemž by neexistoval společný bod, na který by obě oči mohly zaostřit. V reálném světě k divergentní paralaxe nedochází a je potřeba se jí vyvarovat.
Rozdíly v jednotlivých paralaxách lze vidět na obrázku 3.2. Ukázková aplikace umožňuje plynulé nastavení paralaxy, a to zvlášť pro samotné objekty ve scéně a zvlášť pro kurzor myši, kterým je hra ovládána. Přímo za běhu lze tedy vyzkoušet rozdíl mezi pozitivní, nulovou a negativní paralaxou. Zvětšováním její hodnoty dosáhneme silnějšího prostorového vjemu – objekty více „vystupují“ před plátno (v případě negativní paralaxy) nebo se naopak více „zanořují“ do prostoru za plátnem (pozitivní paralaxa). 16
3. Použité technologie
(a)
(c)
(b)
(d)
Obrázek 3.2: Druhy paralax. a) nulová paralaxa, b) negativní paralaxa, c) pozitivní paralaxa, d) divergentní paralaxa. Převzato z [12]. Stereoskopickou projekci lze rozlišit na různé typy podle způsobu, jakým je kýženého efektu dosahováno. Popis jednotlivých postupů pro vytváření 3D obrazu lze nalézt v [12], [17] a [7].
3.5
OpenNI Framework
Firma Microsoft zpočátku nevydala žádné ovladače ani SDK (software development kit), které by umožňovaly použití Kinectu po připojení k počítači, a cíleně odrazovala snahy počítačové komunity o vytvoření takové funkcionality6 . Daleko zásadnější však byla pro komunitu výzva společnosti Adafruit Industries. Ta nabídla odměnu 1000 dolarů tomu, kdo jako první pomocí reversního inženýrství vytvoří ovladač s otevřeným zdrojovým kódem, pomocí kterého bude možno získat obraz z VGA a hloubkové kamery7 . Vzhledem k negativní reakci Microsoftu byla odměna postupně zvýšena až na 3000 dolarů. Trvalo přesně 6 dní od uvedení senzoru na trh, kdy byl tento ovladač zveřejněn8 . Microsoft ale později změnil svůj postoj a prohlásil, že USB port používaný pro připojení zařízení ke konzoli Xbox 360 byl „záměrně ponechán otevřený“ bez speciální ochrany9 . Tím bylo legálně umožněno 6. 7.
http://news.cnet.com/8301-13772_3-20021836-52.html http://www.adafruit.com/blog/2010/11/04/the-open-kinect-project-the-ok-prize-get-1000-bounty-for-
kinect-for-xbox-360-open-source-drivers/ 8. http://www.readwriteweb.com/hack/2010/11/kinect-drivers-hacked---what-w.php 9. http://www.myce.com/news/microsoft-kinect-usb-connection-left-open-intentionally-36914/
17
3. Použité technologie nadšencům z celého světa začít pracovat na ovladačích a celých vývojových prostředích s otevřeným zdrojovým kódem pro použití s počítačem. OpenNI (Open Natural Interaction, česky „otevřená přirozená interakce“) je nezisková organizace, která vznikla za účelem certifikovat a podpořit kompatibilitu mezi zařízeními umožňujícími přirozenou interakci, aplikacemi používajícími tato zařízení a jejich spojujícím článkem – middlewarem. Zakládajícím členem byla mimo jiné společnost PrimeSense. Prvním krokem ke splnění stanoveného cíle bylo vytvoření multiplatformního frameworku s otevřeným zdrojovým kódem, jenž definuje rozhraní pro programování aplikací (tzv. API - Application Programming Interface) používajících přirozenou interakci [5]. V současné době (květen 2012) jsou dostupné knihovny pro programovací jazyky C#, C++ a Java. Z platforem jsou podporovány Windows (32bit i 64bit) a Linux (Ubuntu 10.10, 32bit i 64bit). Hlavním úkolem OpenNI je zformovat API umožňující komunikaci jak s fyzickými zařízeními (video a audio senzory), ze kterých jsou získávány datové vstupy, tak s middleware komponentami, které tyto vstupy dále zpracovávají. Rozhraní OpenNI nabízí dvě hlavní výhody. Rozbitím závislostí mezi senzory a middlewarem je možné psát aplikace tak, aby byly použity bez jakýchkoliv dalších úprav s rozdílnými middleware moduly (tzv. „write once, deploy everywhere“ přístup). Druhá výhoda spočívá v tom, že algoritmy obsažené v middleware modulech jsou psány bez konkrétní závislosti na vstupním zařízení, a díky jednotnému rozhraní nezáleží na tom, jaké zařízení produkuje dále zpracovávaná data [15]. Na obrázku 3.3 je znázorněn třívrstvý model konceptu OpenNI API.
Obrázek 3.3: Třívrstvý model konceptu OpenNI API. Převzato z [16]. 18
3. Použité technologie Aplikační vrstva představuje námi vyvíjený software, který poskytuje uživateli přirozenou interakci pomocí pohybu svého těla, gest a hlasových příkazů. Prostřední část je tvořena samotným OpenNI, jenž vytváří rozhraní umožňující komunikaci jednak se senzory a jednak s middleware komponentami. Spodní vrstva zahrnuje hardwarová zařízení generující datové vstupy. Ty jsou zpracovávány jednotlivými middleware komponentami, které ze surových dat pomocí inteligentních algoritmů získají informace o rozmístění jednotlivých uživatelů, určí pozici dlaní či rozpoznají gesta. Extrahovaná data pak využívá software aplikační vrstvy. Rozhraní pro komunikaci se senzory je v OpenNI plně implementováno, zatímco funkcionalita v podobě middleware komponent přímo obsažena není – v současnosti jediná, nám známá, existující implementace tohoto rozhraní je distribuována v rámci balíku PrimeSense NITE Middleware (viz 3.6). 3.5.1 Modulární přístup Modulárně navržené API umožňuje, aby byla v ten samý okamžik zaregistrována víc než jedna komponenta. Tyto komponenty jsou označovány jako moduly. Výběr a následná práce s určitou hardwarovou nebo middleware komponentou jsou velice jednoduché. V současné době jsou vytvořeny moduly pro tyto senzory (implementovány přímo v OpenNI): •
3D senzor;
•
RGB kamera;
•
IR kamera;
•
Audio (samostatný mikrofon nebo pole mikrofonů).
Z middleware komponent jsou pak podporovány následující (implementovány v rámci NITE): •
Middleware pro analýzu celého těla – generuje kostru snímaného uživatele spolu s informacemi o jednotlivých uzlech.
•
Middleware pro analýzu pozice dlaní – určuje souřadnice sledovaného bodu, typicky dlaně.
•
Middleware pro detekci gest – identifikuje předdefinovaná gesta (např. zamávání) a rozpoznaná gesta předává dále aplikaci.
•
Middleware pro analýzu scény – provádí rozdělení scény na popředí (tj. snímané postavy) a pozadí, určuje souřadnice roviny tvořící podlahu, rozlišuje jednotlivé siluety postav ve scéně. 19
3. Použité technologie 3.5.2 Produkční uzly Fundamentálními prvky OpenNI rozhraní jsou tzv. produkční uzly (PU). Jsou definovány jako množina komponent, které mají produktivní roli v procesu vytváření zdrojových dat. Příkladem může být „User Generator“ (volně přeloženo jako „generátor dat týkajících se postav“) vytvářející kostru uživatele, nebo „Depth Generator“ poskytující hloubkovou mapu. Každý PU zapouzdřuje funkcionalitu vztahující se ke generování specifického typu dat a je schopen tato data poskytnout jakémukoliv objektu. Tímto objektem může být další PU, nebo aplikace samotná. Typickým scénářem je, kdy některé PU vyšší úrovně pro svoji funkcionalitu využívají uzly nižší úrovně (produkující surová data) [16]. Jejich výstupem je pak například aktuální pozice a rotace uzlů tvořících kostru v prostoru, souřadnice středu dlaně nebo konečků prstů nebo událost značící detekci určitého gesta. Produkční uzly se dělí do tří kategorií – záznamové, senzorové a middleware PU. V současné době jsou podporovány následující: Senzorové produkční uzly •
Device. Představuje fyzické zařízení (např. hloubkový senzor nebo RGB kameru). Umožňuje konfiguraci daného zařízení.
•
Depth Generator. Generuje hloubkovou mapu.
•
Image Generator. Generuje barevný obraz z RGB kamery.
•
IR Generator. Generuje infračervenou mapu.
•
Audio Generator. Generuje zvukový stream.
Middleware produkční uzly •
Gesture Alert Generator. Generuje události pro aplikaci při detekci specifického gesta.
•
Scene Analyzer. Analyzuje snímanou scénu. Odděluje pravděpodobné kandidáty ke snímání od pozadí. Detekuje rovinu podlahy.
•
Hand Point Generator. Podporuje detekci dlaní a jejich sledování. Dále vytváří události značící detekci dlaně a změnu polohy aktuálně sledované dlaně.
•
User Generator. Produkuje reprezentaci celého těla nebo jeho části (např. pouze horní poloviny) ve 3D scéně.
Záznamové produkční uzly •
Recorder. Implementuje záznam zdrojových dat. 20
3. Použité technologie •
Player. Čte dříve zaznamenaná data, která nabízí dalším uzlům, a simuluje tak samotné fyzické zařízení.
•
Codec. Používán výše zmíněnými záznamovými uzly pro kompresi a následnou dekompresi nahrávaných dat.
3.5.3 Produkční řetězce Produkční řetězce jsou posloupnosti uzlů s definovanými závislostmi mezi jednotlivými uzly. Pokud by existovaly dvě nezávislé implementace některého middleware modulu, tvořila by každá společně s příslušným modulem pro senzor vlastní produkční řetězec. OpenNI na základě registrovaných modulů nabízí aplikaci všechny možné posloupnosti a umožňuje jí zvolit, kterou použít. Aplikace typicky požaduje pouze data generovaná posledním uzlem každého řetězce, např. Hand Point generatorem. OpenNI interface umožňuje aplikaci, aby používala pouze tento specifický uzel, aniž by si byla vědoma produkčního řetězce, jehož je daný uzel součástí [15]. 3.5.4 Volitelná funkcionalita OpenNI svým návrhem podporuje flexibilitu v rámci registrace více různých komponent od různých výrobců (implementačně ekvivalentních), přitom však bere v úvahu, že jednotliví výrobci mohou přidávat do svých zařízení a odpovídajících modulů další funkcionalitu. K tomuto účelu jsou určena rozšíření (tzv. „Capabilities“) definovaná OpenNI rozhraním. Každého produkčního uzlu se lze dotázat, zda podporuje určité rozšíření, a v případě kladné odpovědi toto rozšíření použít na aplikační úrovni. Při zjišťování dostupných produkčních řetězců je možné specifikovat požadovaná rozšíření, která musí být podporována jednotlivými uzly tvořícími daný řetězec. Některá z podporovaných rozšíření: •
Alternate View. Senzory Kinectu jsou od sebe vzdáleny několik cm a proto každý z nich vidí snímanou scénu z trochu jiného pohledu. Toto rozšíření umožňuje určitému generátoru obrazových dat (např. VGA obrazu nebo hloubkové mapy) transformovat generovaný výstup vůči jinému senzoru tak, aby byl přesně srovnán s obrazem vytvářeným druhým senzorem (tím se vytvoří dojem, že oba senzory jsou fyzicky umístěny ve stejném místě).
•
Mirror. Zapne zrcadlení dat produkovaných určitým generátorem.
•
Frame Sync. Synchronizuje snímkovou frekvenci, se kterou určité dva uzly generují obrazová data.
Výčet všech podporovaných rozšíření lze nalézt v [16]. 21
3. Použité technologie
3.6
PrimeSense NITE Middleware
NITE – Natural Interaction Technology for End-user (česky technologie využívající přirozené interakce určená pro koncového uživatele) je middleware, které na základě hloubkového obrazu snímá okolní svět v 3D a tento vstup převádí na smysluplná data obdobným způsobem, jako to dělají lidé. Zatímco senzor (Kinect, Xtion nebo referenční 3D senzor od PrimeSense) zachytává snímanou scénu, NITE představuje logiku, která dokáže rozpoznat a porozumět přirozené interakci uživatele ve scéně. NITE obsahuje jak algoritmy zpracovávající obrazové vstupy pro identifikaci uživatelů a sledování jejich pohybů, tak API pro implementaci ovládacích prvků (tzv. „Controls“) založených na rozpoznaných gestech uživatele [18]. Middleware NITE bylo založeno na konceptu obsahujícím dvě klíčová paradigmata: princip ovládání pomocí ruky (tzv. „Point Control“) a princip ovládání pomocí celého těla (tzv. „Full Body Control“). Point Control je používán, když uživatelé ovládají aplikaci pomocí gest. Typickým příkladem použití je ovládání spotřební elektroniky v obývacím pokoji, ať už se jedná o přepínání televizních programů televize či výběr přehrávané hudby nebo filmu na domácím kinu. Toto paradigma rozlišuje mezi dvěma módy: 1.
Čekání na tzv. „Focus“ gesto – během této doby systém sleduje scénu a snaží se detekovat žádost o získání kontroly ve formě speciálního gesta (např. zamávání rukou). Tento mód je aktivní v době, kdy není vybrán žádný uživatel, který má kontrolu nad systémem.
2.
Ovládací mód – do tohoto režimu systém přechází ve chvíli, kdy nějaký uživatel provede Focus gesto a získá kontrolu. Systém pak sleduje ruku uživatele a snaží se rozpoznat specifická gesta.
Princip ovládání pomocí ruky je znázorněn na obrázku 3.4. V části (a) lze vidět snímanou scénu, ve které se nacházejí čtyři pozorovatelé. NITE je schopno sledovat dlaně všech lidí ve scéně a vytvářet tak seznam možných kandidátů pro získání kontroly. Získat kontrolu v určitém čase může ale pouze jediný uživatel – ten, který provedl Focus gesto. V části (b) došlo k přechodu do ovládacího módu, ve kterém je NITE zaměřeno pouze na dlaň určitého uživatele. Jakmile dojde k rozpoznání gesta (c), je předána informace cílové aplikaci (d). Gesto je předem definovaný pohyb dlaně, např. zamávání, opsání kruhu, zmáčknutí imaginárního tlačítka, aj. V ukázkové aplikaci bylo použito ovládání pomocí dlaně pro pohyb kurzoru v menu a dále pro ovládání náklonu roviny bludiště při samotné hře (viz kapitola 4). Druhé paradigma – sledování celého těla – je typicky asociováno s hraním her, kde jeden nebo více hráčů stojí před televizí a na základě svých pohybů interagují s objekty ve virtuálním prostoru. Cílem principu ovládání pomocí celého těla je extrahovat informace o poloze kostry uživatele a sledovat změny polohy jednotlivých částí těla v čase. Aplikace tak nemusí pracovat s hloubkovou mapou, ale má k dispozici přímo informace o poloze a rotaci jednotlivých bodů tvořících kostru uživatele. Na rozdíl od point control přístupu musí programátor sám definovat, jak bude aplikace postupovat při zjištění nového uživatele v zorném poli. Příklad použití ovládání pomocí celého těla lze vidět na obr. 3.5. 22
3. Použité technologie
Obrázek 3.4: Princip ovládání aplikace pomocí dlaně. Převzato z [18].
Obrázek 3.5: Princip ovládání aplikace pomocí celého těla. Převzato z [18].
23
3. Použité technologie Typický přístup zahrnuje čekání na kalibrační pózu (předem definovaný postoj, který musí hráč zaujmout), spuštění kalibrace a zahájení sledování kostry uživatele po jejím úspěšném dokončení. S novou verzí OpenNI (1.5.2.23) lze krok představující čekání na pózu vynechat a zahájit kalibrační proces okamžitě po detekování nového uživatele. Volitelně můžeme definovat chování aplikace během probíhající kalibrace či při odchodu uživatele ze zorného pole kamery. Běžně používanou pózou pro kalibraci je tzv. „PSI“ póza (viz obr. 3.6).
Obrázek 3.6: „PSI“ kalibrační póza. Cílem NITE je zabránit zahlcení cílové aplikace nutností zpracovávat jednotlivé vstupy ze senzorů. Místo toho jsou implementovány specializované algoritmy, které tuto analýzu provádí s vysokou efektivitou. 3.6.1 Vnitřní členění NITE Jak již bylo zmíněno dříve, NITE obsahuje jak algoritmy zpracovávající obrazové vstupy, tak API pro implementaci ovládacích prvků. Toto členění se promítá do dvou vrstev tvořících NITE: 1.
NITE Algoritmy – nižší vrstva obstarávající zpracování hloubkové mapy a obrazu z RGB kamery. Tato vrstva obsahuje algoritmy, které vykonávají následující činnosti: (a) Segmentace scény – proces, při kterém jsou jednotliví uživatelé odděleni od pozadí a označeni pro snadnou identifikaci v rámci koncové aplikace. 24
3. Použité technologie (b) Detekce a sledování bodu – umožňuje rozpoznat a sledovat body představující dlaně uživatelů ve scéně. (c) Sledování celého těla – na základě výstupu algoritmu pro segmentaci scény jsou sledována těla jednotlivých uživatelů. Pro každého uživatele je výstupem množina bodů představujících důležité klouby nebo jiné významné části těla, dohromady tvořících ucelenou kostru. 2.
NITE ovládací prvky – vyšší vrstva analyzující sledované body generované NITE Algoritmy. Poskytuje nástroje, které umožňují programátorovi navrhnout odpovídající reakce aplikace na základě gest a pohybů sledované dlaně. Rozpoznává specifická gesta a na jejich základě generuje události, na které může reagovat cílová aplikace.
3.6.2 NITE ovládací prvky Správa relací Relace (anglicky Session) je stav běhu aplikace, při kterém je sledována dlaň uživatele (systém je v tzv. ovládacím módu – viz 3.6). Bod představující dlaň má přiřazeno jedinečné ID po celou dobu trvání relace. Relace typicky začíná provedením Focus gesta a končí ve chvíli, kdy systém již dále nedokáže daný bod sledovat (uživatel odejde ze snímané scény, skryje ruku za záda, a podobně). Existují tři možné stavy, ve kterých se aplikace může nacházet: •
Relace není vytvořena (Not In Session) – systém nepřetržitě skenuje scénu a čeká na provedení Focus gesta. Jakmile je toto gesto rozpoznáno, je vytvořena nová relace.
•
V relaci (In Session) – v tomto stavu systém sleduje dlaň uživatele a rozpoznává specifická gesta.
•
Rychlé obnovení (Quick Refocus) – přechodný stav, do kterého se aplikace dostane, pokud v probíhající relaci dojde ke ztrátě sledovaného bodu. V takovém případě většinou nechceme okamžitě ukončit probíhající relaci, ale v určeném časovém limitu umožníme aplikaci, aby mohla znovu zaměřit dlaň. Obnovení sledování může být docíleno provedením klasického Focus gesta, nebo jiného, speciálně zvoleného (většinou jednoduššího a kratšího) – tzv. gesta rychlé obnovy (anglicky Quick Refocus Gesture). Systém se také snaží identifikovat dlaň v blízkém okolí poslední známé pozice bodu a obnovit tak snímání automaticky. Pokud limit vyprší, relace definitivně zaniká. Stav rychlého obnovení není povinný.
O vytváření, udržování a ukončování relací se stará správce relací [18]. Diagram pro přechody mezi jednotlivými stavy lze nalézt na obrázku 3.7. 25
3. Použité technologie
Obrázek 3.7: Stavový diagram pro správu relací.
26
3. Použité technologie Sledování bodu Ovládací prvky pro sledování bodu (tzv. „Point Controls“) tvoří množinu objektů, které pro každý snímek obdrží souřadnice obecně všech sledovaných bodů, analyzují je a provedou odpovídající akce. V současné implementaci bohužel všechny ovládací prvky operují pouze na tzv. primárním bodu, takže nelze sledovat gesta pro více dlaní zároveň. Tento fakt je poměrně hodně omezující pro potřeby ukázkové aplikace, protože se ukázalo jako velice nepraktické používat sledovanou dlaň (určující pohyb kurzoru/naklonění roviny bludiště) ještě k dalšímu ovládání aplikace pomocí gest. Proto jsem přistoupil k implementaci vlastních gest pro druhou dlaň. Této problematika je popsána v 4.4. Jako primární bod je zvolen první rozpoznaný bod (reprezentující dlaň, která provedla Focus gesto). Pokud přestane být primární bod aktivní (relace přidružená k tomuto bodu zanikne) a existují jiné rozpoznané body, jeden z nich převezme funkci primárního bodu. O jeho určení se stará správce relací. Předávání zpráv Tok dat mezi jednotlivými NITE ovládacími prvky je realizován pomocí zpráv. Zprávy jsou posílány generátory zpráv (tzv. Message Generators) a zachytávány posluchači (Message Listeners). Existují různé druhy zpráv, např. PointMessage, ActivationMessage, SessionMessage, atd. Pokud posluchač dostane zprávu, většinou extrahuje obsaženou informaci a na jejím základě vytvoří a rozešle příslušné události. Uveďme jednoduchý příklad. Třída XnVPointControl přijímá XnVPointMessage; z ní extrahuje objekt XnVMultipleHands – kontejner pro všechny identifikované body. Z těchto bodů rozpozná nově přidané (a odešle odpovídající OnPointCreate událost), již existující (pro něž je vytvořena OnPointUpdate událost) a body, které přestaly být sledovány (jimž odpovídá OnPointDestroy událost). Také je rozpoznán primární bod, pro který jsou volány další relevantní události. Události pro sledování bodu Každý ovládací prvek pro sledování bodu poskytuje následující obecné události, které mohou jiné objekty odebírat, pokud se zaregistrují jako posluchači: •
Vytvoření nového bodu.
•
Pohyb existujícího bodu.
•
Ztráta existujícího bodu.
•
Vytvoření primárního bodu.
•
Změna primárního bodu (bod reprezentující primární bod již není dále dostupný, ale existuje jiný bod, který převzal úlohu primárního bodu). 27
3. Použité technologie •
Ztráta primárního bodu (bod reprezentující primární bod již není dále dostupný a neexistuje žádný další sledovaný bod).
•
Žádný sledovaný bod.
Mimo tyto události poskytuje každý ovládací prvek specifické události související s jeho funkcionalitou. Uveďme nyní jeden z ovládacích prvků. Popis zbývajících lze nalézt v [18]. Push Detector Tento ovládací prvek se snaží rozpoznat gesto odpovídající stlačení imaginárního tlačítka. Stlačení je detekováno, jestliže je při pohybu dlaní ve směru od uživatele ke snímači (osa Z) dosaženo určité rychlosti. Programátor může nastavit míru benevolence rozpoznávání gesta pomocí několika parametrů, např. minimální potřebné rychlosti při vykonávání gesta nebo maximální možné odchylky směru pohybu ruky od osy Z. Podporované specifické události jsou: •
Push. Vytvořena v momentě detekce kompletního gesta stlačení, které svými parametry splňuje definované podmínky.
•
Stabilized. Tato událost je generována po detekci stlačení v momentě, kdy je dlaň uživatele relativně stabilní. Detekce dalšího gesta stlačení je možná až po vytvoření této události. Lze tak zabránit nechtěnému duplikování gesta Push.
28
4 Implementace Součástí práce bylo také vytvoření ukázkové aplikace, která využívá technologie popsané v předchozí kapitole. Jedná se o jednoduchou pohybovou hru a již podle názvu aplikace – Labyrinth – můžeme odhadnout její zaměření. Základní hrací plochou je bludiště obdélníkového tvaru, v němž se nachází kovová kulička. Labyrint lze naklánět do všech směrů a určovat tak pohyb kuličky uvnitř. Na hrací ploše jsou rozmístěny důlky, do kterých kulička nesmí spadnout, a překážky definující vnitřní uspořádání bludiště. Hráč má za úkol pomocí naklánění roviny bludiště navigovat kuličku tak, aby ji dovedl k cílové jamce a přitom se vyhnul všem ostatním. Během hry je stopován čas (od prvního kontaktu kuličky s hrací plochou až po její umístění do finálního důlku). Pro snadnou orientaci a určení náklonu je ve hře zobrazen kurzor myši, popř. pomocný kříž vyznačující střed obrazovky. Nejlepší čas pro každé bludiště je zaznamenán. Hráč má na výběr ze tří různých způsobů ovládání hry – pomocí myši, pohybu dlaně nebo pohybu celého těla. Poslední dvě jmenované možnosti jsou dostupné pouze tehdy, pokud je připojen Kinect. Jelikož jednotlivé způsoby ovládání nejsou obtížnostně srovnatelné, nejlepší dosažený čas se ukládá pro každý z nich zvlášť. Hráč má možnost přepnout způsob ovládání přímo v probíhající hře. Pokud tak ale učiní, případný nejrychlejší čas nebude zaznamenán, aby se zabránilo cíleným manipulacím s výsledky. Bludiště byla vymodelována pomocí programu Cinema 4D Studio1 . Ukázku herní plochy lze vidět na obr 4.1.
Obrázek 4.1: Pohled na herní plochu ukázkové aplikace. 1.
http://www.maxon.net/products/cinema-4d-studio/who-should-use-it.html
29
4. Implementace Java Monkey Engine není primárně určen k využití ve virtuální realitě; jeho hlavním úkolem je vykreslovat realistickou trojrozměrnou scénu. V této kapitole se zaměříme na propojení jME s knihovnami OpenNI společně s NITE; dále popíšeme tvorbu vlastních gest, implementaci stereoskopické projekce a dalších vybraných částí aplikace.
4.1
Ukládání dat
Pro uložení základních parametrů týkajících se grafického nastavení a použití vstupů má Java Monkey Engine připravenu třídu AppSettings. Tyto parametry mohou být načteny z registrů (pouze při použití OS Windows), z textového souboru na disku (preferovaná varianta) nebo mohou být nastaveny až za běhu aplikace. Pohybová hra však umožňuje kromě grafické stránky upravovat také další nastavení (např. nutnost použití kalibrační pózy, citlivost vstupů, hlasitost zvuků a hudby, atd.) a také si pamatuje nejlepší časové výsledky pro každé bludiště. Tyto dodatečné informace jsou ukládány zvlášť. Pro dosažené časy byl zvolen binární formát ukládání (třída BinaryExporter) zabraňující ruční editaci výsledků, ostatní nastavení se ukládají do XML souboru (třída XmlExporter) a mohou tak být naopak společně se základními nastaveními jednoduše upravena i mimo aplikaci. Soubory se ukládají do složky ./Assets/Saves relativně vůči lokaci, ve které je spouštěcí soubor labyrinth.exe. Aplikace byla navržena tak, aby její spuštění nebylo závislé na existenci konfiguračních souborů. Toto robustní řešení umožňuje kterýkoliv z nich smazat; při dalším spuštění bude chybějící soubor vygenerován znovu s implicitními hodnotami. Takto lze tedy resetovat grafická či herní nastavení nebo smazat nejlepší dosažené výsledky.
4.2
OpenNI a NITE
Při integraci vstupů z Kinectu do jME se nabízelo použití stejného principu, jakým je implementován například vstup z joysticku. Ve třídě AppSettings tedy byla vytvořena nová dvojice ("DisableKinect", boolean), která definuje, zda se při spuštění má vytvořit spojení s Kinectem. Při zpracování nastavení ve třídě Application pak dojde v závislosti na definovaném nastavení k inicializaci – viz následující ukázka. 1 2 3 4 5 6 7 8
// vytvoreni vstupu p re d st av ov an e ho Kinectem if (! settings . getBoolean ( " DisableKinect " ) ) { // Singleton - ziskani jedine instance tridy KinectInput kinectInput = jmeContext . getKinec tInput () ; if ( kinectInput != null ) { kinectInput . initialize () ; // inicializace vstupu } }
Objekt kinectInput dále nabízí metody pro přístup ke všem důležitým komponentám OpenNI i NITE, např. se jedná o instance všech generátorů (poskytujících VGA obraz, hloubkovou mapu, atd.). Důležitým krokem je volání metody initialize(). V ní proběhne příkazem 30
4. Implementace context = Context .createFromXmlFile ( xmlContextFileSource , scriptNode ) ;
vytvoření kontextu na základě konfiguračního XML souboru. V tomto souboru je definováno, které senzorové produkční uzly chceme používat (viz 3.5.2). Následně dojde k inicializaci jednotlivých OpenNI generátorů produkujících data. Příkazem ve třídě Generators sess ionManag er = new Se ssionMan ager ( context , " Wave " , " RaiseHand " ) ;
je instanciován správce relací (viz 3.6.2). Při vytváření definujeme kromě kontextu také tzv. Focus a Quick Refocus gesto. Na základě dlouhodobých zkušeností se ukázala jako nejvhodnější kombinace zamávání (Focus) a zvednutí dlaně (Quick Refocus). Dále jsou inicializovány ovládací prvky, zejména v ukázkové aplikaci používaný PointControl. Posledním krokem je vytvoření instance třídy GestureManager a následné zaregistrování třídy ArmGestureDetector. První zmiňovaná obstarává obecně správu všech zaregistrovaných detektorů, druhá pak v každém kroku výpočetní smyčky kontroluje, zda nedošlo k provedení gesta. Problematice použití vlastních gest se věnuje část 4.4 . Pomocí dvojice ("DisableKinect", boolean) lze tedy obecně rozhodnout, zda se aplikace pokusí použít Kinect, nebo nikoli. Při inicializaci v momentě, kdy není Kinect připojen (nebo nejsou nainstalovány odpovídající ovladače), dojde k vygenerování výjimky org.OpenNI.GeneralException. Vzhledem k tomu, že ukázková hra je primárně určena právě pro Kinect, přiklonil jsem se k plně automatizovanému způsobu inicializace. Aplikace se při spuštění vždy pokusí spojit s Kinectem, v případě neúspěchu je zachycena výše zmíněná výjimka a do nastavení dodatečně uložena dvojice ("DisableKinect", true). Nevýhodou tohoto přístupu je v některých případech zbytečné vynucení inicializace Kinectu a následné zpracování výjimkového stavu. Velkým kladem je naopak skutečnost, že uživatel nemusí při zapnutí aplikace kontrolovat povolení spojení s Kinectem v menu, popř. v XML souboru s nastavením. 4.2.1 Aktualizace dat ve vlastním vlákně Pohybový senzor generuje VGA obraz, hloubkovou mapu a z nich vypočítávané informace s frekvencí 30 Hz. Pro aktualizaci dat dostupných aplikaci musíme zavolat na objektu context jednu z metod WaitXUpdateAll() (viz následující výčet). Každá z metod implementuje jiný přístup při čekání na nová data; u každé z nich dojde v dalším kroku k aktualizaci všech uzlů v produkčním řetězci. Na výběr máme následující možnosti: •
waitAnyUpdateAll() – čeká, dokud některý z produkčních uzlů nemá k dispozici nová data.
•
waitOneUpdateAll(ProductionNode pn) – čeká, dokud jeden konkrétní uzel (specifikovaný jako parametr) neoznámí dostupnost nových dat. Tento přístup je vhodný v případě, že používáme více produkčních uzlů, ale pouze jeden je zásadní pro další běh aplikace. 31
4. Implementace •
waitNoneUpdateAll() – pouze aktualizuje všechny uzly v řetězci, nečeká na obnovení dat žádného z nich.
•
waitAndUpdateAll() – čeká na obnovu dat ve všech uzlech.
Po aktualizaci uzlu jsou data generovaná tímto uzlem dostupná pro další zpracování pomocí volání metody getData(), popř. getMetaData(). Pokud dojde k aktualizaci uzlu, který zatím nevygeneroval žádné nové informace, po zavolání metody getData() vrátí ten samý objekt, co v předchozím volání. Z výše uvedeného popisu je patrné, že pro kontinuální získávání nových informací z Kinectu musíme jednu z metod ’WaitXUpdateAll()’ provádět cyklicky. Pokud bychom ji však volali v hlavní smyčce programu (metoda simpleUpdate()), došlo by v důsledku čekání na nová data k omezení horní hranice snímkové frekvence celé aplikace na cca 25-50 FPS (v závislosti na tom, který přístup zvolíme). Metoda waitNoneUpdateAll() by toto omezení přímo nezpůsobila, ale aktualizace všech uzlů v produkčním řetězci je náročná operace a nemá smysl ji provádět dříve, než některý z nich vygeneruje nová data. Pro plynulé renderování scény a eliminaci artefaktů v obraze je ale potřeba vykreslovat obraz se snímkovou frekvencí alespoň stejnou, jako je obnovovací frekvence monitoru (typicky 60 Hz). Poté má smysl zapnout tzv. vertikální synchronizaci – jejím cílem je zajistit, aby se na obrazovce objevovaly kompletní snímky a nikoli obraz složený z poloviny snímku A a poloviny snímku A+1. Ty na sebe totiž vzhledem k časovému posunu nenavazují a tvoří zlomy známé pod anglickým názvem tearing. Při frekvenci 25 Hz a nižší se navíc obraz může subjektivně jevit jako značně trhaný. Volání z hlavní smyčky programu tedy nepřichází v úvahu. Řešením je pro běh metody WaitXUpdateAll() dedikovat zvláštní vlákno. Java Monkey Engine 3 je oproti minulé verzi plně připraven pro používání více vláken při výpočtech. Kromě hlavního vlákna se zcela automaticky vytváří samostatné vlákno pro vykreslování grafiky, práci se zvukem a pro počítání fyzikálních interakcí. Balík java.util.concurrent dále poskytuje jednoduchý způsob, jak pro dlouhotrvající úkoly vytvořit další vlákna, která mohou být spouštěna souběžně. Třemi základními komponentami jsou třída Executor (spravuje uživatelem definovaná vlákna), objekt typu Callable (úloha běžící ve vlastním vlákně) a objekt typu Future (výsledek běhu). Každý Callable objekt je spuštěn pomocí metody call() implementované z rozhraní Callable. Executor představuje centrální prvek, který spravuje všechny objekty typu Callable. Pokaždé, když naplánujeme běh některého Callable, Executor vrátí objekt typu Future. Ten můžeme použít pro zjištění stavu naplánované úlohy. Více se o tomto konceptu lze dočíst v oficiální dokumentaci2 . Pro spuštění nového vlákna nejdříve vytvoříme instanci třídy ScheduledThreadPoolExecutor: private S c h e d u l e d T h r e a d P o o l E x e c u t o r executor = new S c h e d u l e d T h r e a d P o o l E x e c u t o r (1) ;
2.
http://download.oracle.com/javase/tutorial/essential/concurrency/
32
4. Implementace Číselný parametr předávaný konstruktoru značí, kolik chceme pro naše úlohy vytvořit vláken. Tento počet vláken bude aktivní po celou dobu běhu aplikace. Nemá však valný smysl vytvářet jich více, než kolika jádry disponuje procesor, na kterém aplikace poběží. Nyní vytvoříme Callable objekt, ve kterém implementujeme metodu call(). Ta bude obsahovat volání časově náročné metody context.waitAnyUpdateAll() a na ni navazujících metod. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
if ( updateCall == null ) { updateCall = new Callable () { public Object call () throws Exception { if ( initialized ) { try { // ceka , az nektery uzel vygeneruje nova data , pak aktualizuje vsechny uzly context . w a i t An y U p d a t e A l l () ; generators . sessio nManager . update ( context ) ; gest ureManag er . update () ; // zkontroluje , zda nebylo provedeno gesto } catch ( Exception ex ) { logger. log ( Level .SEVERE, " Error while updating Kinect . " , ex ) ; } return null ; } }; } }
4.2.2 Rozhraní KinectListener Vytvořené rozhraní KinectListener umožňuje jakékoliv třídě jednoduše získat přístup k událostem generovaným NITE ovládacími prvky. Poté, co implementujeme metody předepsané rozhraním (stačí ty, které chceme doopravdy využívat), stačí zaregistrovat implementující třídu jako posluchače vybraných událostí. V případě vygenerování události se pak automaticky bude volat relevantní metoda v naší třídě. Registrace probíhá ve dvou krocích: 1.
Nejdříve do inputManageru přidáme nové mapování názvu události (textový řetězec) na objekt KinectTrigger představujícím danou událost.
2.
Poté v inputManageru zaregistrujeme danou třídu jako posluchače pro nově vytvořené mapování.
Pokud nyní kterýkoliv z přidaných KinectTrigger objektů vytvoří novou událost, posluchači zaregistrovaní pro mapování přiřazené tomuto objektu danou událost obdrží (ve formě volání onEvent() metody implementované v posluchači). Příklad jednoduchého mapování: inputManager . addMapping ( " new user " , new KinectTrigger ( kinectInput .NEW_USER) ) ; inputManager . addListener ( this , " new user " ) ;
33
4. Implementace
4.3
Třída KinectHandler
Třída KinectHandler v sobě soustřeďuje veškerou logiku zpracovávající vstupy z Kinectu. Implementuje rozhraní KinectListener, ke generátorům má přístup pomocí objektu kinectInput, předaného pomocí konstruktoru třídou Labyrinth (viz. 4.8). Třída je zaregistrovaná jako posluchač pro události týkající se detekce/ztráty uživatele, detekce pózy, průběhu kalibrace a vytvoření/ztráty sledovaného bodu. S novou stabilní verzí OpenNI 1.5.2.23 byla přidána zajímavá funkce – možnost zahájení kalibrace, aniž by uživatel musel zaujmout kalibrační pózu. Ve vhodné aplikaci se tak hráč může interaktivně zapojit do hry pouhým vstoupením do zorného pole Kinectu, zcela automatické je spuštění kalibrace a sledování uživatele po jejím úspěšném dokončení. Dochází tak k dalšímu zjednodušení a zpříjemnění manipulace s Kinectem. Jedná se o jeden z prvků rozšiřujících funkcionalitu (viz sekce 3.5.4), obecně tedy nemusí být dostupný u všech senzorů. Automatickou kalibraci oceníme obzvláště v případě, kdy se během hraní v zorném poli kamer kromě nás nepohybuje nikdo jiný. Tento přístup s sebou však přináší i jednu nevýhodu. Je-li ve scéně více lidí, nemáme prakticky žádnou možnost, jak určit, kdo bude snímán. Pokud je vybrána nesprávná osoba, musí odejít ze zorného pole kamer, aby došlo přerušení sledování a byla umožněna kalibrace jiného hráče. Při předvádění aplikace velké skupině lidí by automatické snímání mohlo značně omezit její použitelnost. Po uvážení těchto skutečností jsem se rozhodl ponechat na rozhodnutí uživatele, zda bude PSI póza vyžadována, či nikoli. Tomuto faktu musela být přizpůsobena implementace relevantních metod. Pro ukázkovou aplikaci není v současné verzi nijak přínosné sledování více než jednoho hráče. Pokud tedy již existuje jeden aktivní uživatel, kalibrace ostatních je zamítnuta. Rozhodovací strom definující postup při kalibraci lze vidět na obrázku 4.2. Třída KinectHandler dále spravuje zobrazování VGA vstupu, popř. hloubkové mapy s vyznačením sledovaného uživatele a lokace primárního bodu. Obraz je umístěn v levé části herního menu; kliknutím lze přepínat mezi VGA a hloubkovou mapou. Během sledování primárního bodu je pozice korespondující dlaně vyznačena záměrným křížem.
4.4
Implementace rozpoznávání gest
NITE nabízí pro primární bod sledování základních gest, současná implementace neumožňuje rozpoznávání pro další body. V ukázkové aplikaci představuje primární bod pravou dlaň uživatele, ovládající kurzor. Jako velmi nepraktický se ukázal způsob ovládání, ve kterém tuto dlaň používáme také k potvrzování akcí (simulace stisku levého tlačítka myši). U způsobu ovládání aplikace pomocí ruky nejsme díky principu fungování samotné technologie ani zdaleka schopni dosáhnout takové citlivosti a jistoty, jako při použití myši (kde snadno dokážeme posouvat kurzor po jednotlivých pixelech). Tomu byla uzpůsobena většina ovládacích prvků – např. tlačítka jsou dostatečně rozměrná, aby uživatel snadno vybral požadovanou položku. Pokud by však měl nyní pomocí pravé dlaně (určující aktuální výběr) provést Push gesto (viz Push Detector v sekci 3.6.2), musel by dlaní pohnout ideálně 34
4. Implementace
Obrázek 4.2: Schéma znázorňující postup demonstrační aplikace při detekci nového uživatele.
35
4. Implementace přesně v záporném směru osy Z (tzn. od těla hráče ke Kinectu). Během provádění gesta je ale velice obtížné mírně se neodchýlit od požadovaného směru, a tak se často stane, že se dlaň (a tedy i kurzor) při provádění gesta posune také ve směru osy X nebo Y. To může mít za následek potvrzení jiného, než původně zamýšleného prvku. Pro rušení akce (simulace klávesy Escape) se nabízelo další intuitivní gesto, a to zvednutí dlaně (RaiseHand). To je však právě pro svoji jednoduchost provedení s výhodou používáno pro rychlou obnovu sledování bodu (Quick Refocus, viz 3.6.2). I při vyřešení zmíněných problémů by způsob ovládání nebyl optimální, protože veškeré akce by byly vykonávány pravou rukou a levá by zůstala zcela nevyužita. Vzhledem k tomu, že Push gesto nemá v aplikaci žádný jiný význam, byla mu ponechána akce potvrzení výběru. Hráč tak může sám posoudit obtíže spojené s jeho používáním. Detekci gesta lze vypnout v menu Game Settings. [15] zmiňuje tyto různé strategie pro výběr a následné potvrzení výběru: •
Výběr předmětu primární dlaní. Potvrzení pomocí gesta Push realizovaného tou samou dlaní.
•
Výběr předmětu primární dlaní. Potvrzení pomocí gesta Push realizovaného sekundární dlaní.
•
Výběr dlaní. Dostatečně dlouhý časový interval, ve kterém dlaň setrvá v nehybné poloze na zvoleném objektu, je interpretován jako potvrzení výběru.
•
Výběr pomocí dlaně nebo hlasového příkazu za použití klíčového slova „select“. Potvrzení výběru hlasovým příkazem „click“.
•
Standardní způsob výběru, realizace následného potvrzení pomocí komplexnějších gest (např. sevřením dlaně v pěst).
Každý z přístupů má své výhody a nevýhody, [15] pojednává o srovnání některých z nich a vyvozuje poměrně objektivní závěry. Všechny zmíněné poznatky mě vedly k rozhodnutí použít pro ukázkovou aplikaci druhý uvedený způsob ovládání a pro tento účel implementovat rozpoznávání gest Push a RaiseHand pro levou dlaň. V předchozí ukázce kódu si můžeme všimnout volání metody gestureManager.update() po každém obnovení dat některého z produkčních uzlů. Ta zajistí volání update() metody třídy ArmGestureDetector (obecně každého ze zaregistrovaných detektorů). Jejím obsahem je mimo jiné následující funkcionalita: 1 2 3 4 5
// pokud je sledovana kostra uzivatele .. if ( skeleton . isAvailable () ) { // .. a pokud jsou zname pozice leve dlane a leveho ramene .. if ( skeleton . i s J o i n t A v a i l a b le ( SkeletonJoint .LEFT_HAND) && skeleton . i s J o i n t A v ai l a b l e ( SkeletonJoint .LEFT_SHOULDER) ) {
6
// .. detekujeme gesta pro levou pazi d e t e c t A r m G e s t u r e s ( skeleton , SkeletonJoint .LEFT_HAND, SkeletonJoint .LEFT_SHOULDER, leftArmForwards , leftArmDown , leftArmUp , leftArmOut , leftArmAcross ) ;
7 8 9
}
10 11
}
36
4. Implementace Lze vidět, že dochází k rozpoznání celkem čtyř událostí: pohyb dlaně ve směru dolů, nahoru, doleva a doprava od pozice ramene. Používány jsou pak tři z nich – předpažení pro potvrzení nabídky, zvednutí dlaně pro zrušení akce, pohyb dlaně ve směru doleva od ramene pro kalibraci ovládání pomocí dlaně. Metoda detectArmGestures() potom volá jednotlivé funkce pro rozpoznání čtyř jmenovaných gest. Zaměřme se na tělo metody detectArmForwards(): 1 2 3 4 5 6 7 8 9
// pokud jsou splneny podminky pro rozpoznani gesta ... if ( handPosition . getZ () < s h o u l d e r P o s i t i o n . getZ () && FastMath .abs ( handPosition . getZ () - s h o u l d e r P o s i t i o n . getZ () ) >= distance ) { // .. a pokud gesto nebylo platne pri minulem vyhodnoceni ,.. if (! armForwards . isTrue () ) { // .. upozorni za registrov ane posluchace na vznik gesta n ot if yL i st en er s ( new G e s t u r e D e t e c t e d E v e n t ( jointPrefix + " Arm Forwards " , armForwards . set ( true ) ) ) ; }
10 11 12 13 14 15 16
// pokud nejsou splneny podminky a pri minulem vyhodnoceni bylo gesto aktivni ,.. } else if ( armForwards . isTrue () ) { // .. upozorni za registrov ane posluchace na ukonceni gesta n ot if yL i st en er s ( new G e s t u r e D e t e c t e d E v e n t ( jointPrefix + " Arm Forwards " , armForwards . set ( false ) ) ) ; }
Proměnná distance je typu float a implicitně obsahuje hodnotu 400. Představuje minimální přípustnou vzdálenost levého ramene a levé dlaně (v milimetrech) ve směru osy Z, aby došlo k detekování gesta. Objekt armForwards v sobě nese informaci o tom, zda je gesto v daném okamžiku aktivní, či nikoli. V budoucnu by mohl být rozšířen o další parametry, například čas v milisekundách, kdy bylo gesto aktivováno, nebo délku jeho trvání. Schematické znázornění detekce gesta lze vidět na obrázku 4.3. Na rozdíl od standardního gesta Push implementovaného v NITE, gesto ArmForwards je dvoustavové – obdobně jako při stlačení a uvolnění tlačítka myši, i zde jsou generovány dvě události. První značí aktivaci gesta, druhá deaktivaci. Samotné rozpoznávání bohužel není příliš robustní, protože je postaveno pouze na sledování vzdáleností dvou bodů. Nabízí se prostor pro zlepšení přidáním nastavitelných parametrů ovlivňujících úspěšnou detekci gesta, např. minimální délku trvání, maximální akceptovatelnou odchylku od směrodatné osy, atd.
4.5
jBullet Physics
Fyzikální engine je do jME implementován jako jeden z tzv. aplikačních stavů. Jako všechny stavy jej tedy lze v případě potřeby uspat a konkrétně u tohoto tak způsobit zmrazení fyzikálních interakcí. To je velmi výhodné např. při přerušení hry vstupem do menu aplikace, nebo při resetování kuličky na startovní pozici. Obecně lze vytvořit více fyzikální stavů současně, aktivní může být vždy ale pouze jeden. O všechny aplikační stavy se stará správce stavů (instance třídy AppStateManager). Fyzikální interakce jsou vypočítávány s frekvencí 60 kroků za vteřinu v samostatném vlákně. Aplikování sil na objekty nebo testování kolizí má smysl pouze v každém kroku 37
4. Implementace
Ki ne
ct
distance
GESTO ROZPOZNÁNO
GESTO NEROZPOZNÁNO
Uživatel rameno
dlaň
loket
Obrázek 4.3: Schematické znázornění detekce gesta ArmForwards. výpočtu fyzikálního vlákna. To však nemusí být synchronizováno s vláknem hlavní aplikace, které typicky běží s daleko vyšší snímkovou frekvencí. Pokud bychom se pokoušeli manipulovat s fyzikálními interakcemi z metody simpleUpdate() (cyklicky volána z hlavního vlákna), byly by některé z takto provedených změn zahozeny kvůli provedení mimo krok výpočtu fyzikálního vlákna. Stejně tak kontrolu kolizí musíme provádět vždy po dokončení jednoho běhu [10]. Pro tento účel slouží rozhraní PhysicsTickListener, které předepisuje dvě metody - prePhysicsTick() a physicsTick(). •
Metoda prePhysicsTick(PhysicsSpace space, float tpf) je volána před každým krokem výpočtu fyzikálního vlákna. V rámci této metody lze pozměnit stávající síly nebo aplikovat nové; změny budou zahrnuty v následujícím kroku.
•
Metoda physicsTick(PhysicsSpace space, float tpf) je naopak volána po dokončení výpočtu. Zde se můžeme dotazovat na výsledek fyzikálních interakcí pro daný krok, zjistit kolize, atd.
Metoda physicsTick() v pohybové hře řeší dva problémy. Pomocí volání metod f i n i s h G h o s t C o n t r o l . g e t O v e r l a p p i n g O b j e c t s () . contains ( b a l l P h y s i c s C o n t r o l ) r e s e t D e sk C o nt r o l . g e t O v e r l a p p i n g O b j e c t s () . contains ( b a l l P h y s i c s C o n t r o l )
kontroluje, zda kulička spadla do cílové nebo jiné jamky a patřičně na to zareaguje – ukončením současné hry nebo resetováním pozice míčku na startovní bod. 38
4. Implementace V části 3.2 byl popsán obecný postup pro umožnění ovládání určitého objektu fyzikálním enginem. Uveďme nyní konkrétní příklad pro kovovou kuličku. 1 2 3 4 5 6 7
S p h e r e C o l l i s i o n S h a p e ballCollShape = new S p h e r e C o l l i s i o n S h a p e ( ballRadius ) ; // krok 1 b a l l P h y s i c s C o n t r o l = new R i g i d B o d y C o n t r o l ( ballCollShape , ballMass ) ; // krok 2 ball . addControl ( b a l l P h y s i c s C o n t r o l ) ; // krok 3 b a l l P h y s i c s C o n t r o l . s e t C o l l i s i o n G r o u p (1) ; // krok 4 b a l l P h y s i c s C o n t r o l . s e t C o l l i d e W i t h G r o u p s (3) ; // krok 4 physicsSpace . add ( b a l l P h y s i c s C o n t r o l ) ; // krok 5 rootNode . attachChild ( ball ) ; // krok 6
Z kódu je patrné, že jsme ovládací prvek kuličky zařadili do kolizní skupiny číslo 1. Kulička tak bude automaticky kolidovat se všemi objekty v této skupině. Navíc jsme ale povolili kolize i s objekty ze skupiny č. 3. Takto můžeme jednoduše definovat, které objekty spolu budou interagovat, a které nikoli. Abychom byli informováni o detekovaných kolizích, musíme implementovat rozhraní třídy PhysicsCollisionListener a jeho metodu collision(). Ta ale není synchronizována s jednotlivými kroky výpočtu fyzikálního vlákna; pokud chceme na základě vzniklých srážek manuálně upravovat fyziku, z dříve popsaných důvodů se jako vhodnější přístup jeví použití rozhraní PhysicsTickListener a metody prePhysicsTick(). Metoda collision() se v ukázkové aplikaci stará o následující: •
Spuštění časomíry, pokud je detekována úplně první kolize v právě probíhající hře. Ta značí náraz kuličky do desky představující podlahu bludiště.
•
Přehrání zvuku pro náraz při detekci dotyku kuličky se stěnami bludiště. Hlasitost zvuku je navíc upravena na základě rychlosti, s jakou kulička do překážky narazila.
Dále si můžeme povšimnout, že jsme jako kolizní geometrii pro kuličku zvolili třídu SphereCollisionShape. Pro složitější (obecně nekonvexní) tvar máme dvě možnosti. Geometrii buď rozdělíme na několik jednoduchých částí, které budou dohromady tvarem odpovídat složitému objektu a pro něž jsou v jME přichystány jednoduché kolizní geometrie. Druhou možností je pak využití třídy CollisionShapeFactory, která nabízí sadu statických metod pro vytvoření geometrií na základě trojúhelníkových sítí objektů. Příkladem může být následující příkaz, použitý pro vytvoření kolizní geometrie podlahy. Coll isionSha pe f loorColl Shape = C o l l i s i o n S h a p e F a c t o r y .createMeshShape ( floor ) ;
Při vytváření ovládacích prvků máme na výběr ze standardních (RigidBodyControl, GhostControl) a speciálních (např. RagDollControl). RigidBodyControl je nejčastěji používaným ovládacím prvkem. Může být použit jak pro dynamické objekty (tzn. pevné objekty, které jsou ovlivňovány kolizemi, působením sil a gravitace), tak pro statické objekty (pevné objekty, jež kolidují s jinými předměty, ale nepůsobí na ně žádné síly, samy se tedy nepohybují). GhostControl je používán pro detekci prolínání dvou objektů. Tento ovládací prvek je sám o sobě nehmotný. To znamená, že objekt ovládaný pomocí GhostControl na rozdíl od jiného s přiřazeným RigidBodyControl nebude způsobovat kolize s dalšími předměty, ale bude procházet volně skrz ně. Příklad použití je nasnadě – po připojení 39
4. Implementace k samostatnému uzlu (bez přiřazené geometrie) může GhostControl sloužit jako neviditelný spínač, který při průchodu hráče aktivuje nějakou událost. V ukázkové aplikaci jsou zastoupeny oba tyto ovládací prvky. RigidBodyControl je použit pro téměř všechny viditelné objekty ve scéně (kulička, podlaha a stěny bludiště). GhostControl pak slouží k detekci propadnutí kuličky některou z jamek (s rozlišením cílové jamky od ostatních). Speciální ovládací prvky mají velice úzké zaměření. Jejich popis lze nalézt v [10].
4.6
Nifty GUI
Obecný způsob práce Nifty GUI byl popsán v 3.3. Nyní se podrobněji zaměřme na propojení XML návrhu a kontrolní třídy UserInterfaceController. Podobně jako fyzikální engine jBullet, také Nifty GUI je implementováno jako jeden z aplikačních stavů. Jeho inicializaci provedeme následujícím kódem: 1 2 3 4 5 6 7 8
niftyDisplay = new N if t yJ me Di s pl ay ( this , assetManager , inputManager , audioRenderer , guiViewPort ) ; nifty = niftyDisplay . getNifty () ; nifty . fromXml ( " Interface / UserInterface . xml " , " start " ) ; // nacteni XML souboru screen = nifty . g e tC u r r e n t S c r e e n () ; // ziskani startovni obrazovky ui = (( U s e r I n t e r f a c e C o n t r o l l e r ) screen . g e t S c r e e n C o n t r o l l e r () ) ; // kontrolni trida stateManager . attach ( ui ) ; // prirazeni kontrolni tridy manazeru stavu guiViewPort . addProcessor ( niftyDisplay ) ;
Pomocí metody nifty.fromXml("Interface/UserInterface.xml", "start") načteme XML soubor s definicí vzhledu celého menu a určíme startovní obrazovku. Obecně každá obrazovka má v XML souboru definovanou vlastní kontrolní třídu, ukázková aplikace si vystačí s jedinou obrazovkou nazvanou „start“. Podívejme se nyní na strukturu XML dokumentu: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
< screen id=" start " controller=" labyrinth . U s e r I n t e r f a c e C o n t r o l l e r " > < layer id=" controlLayer " b ac k gr ou nd Co l or =" #0007 " childLayout=" vertical " visible=" true " > < panel id=" controlPanel " height=" 118 px " width=" 530 px " style=" nifty - panel - no - shadow " padding=" 9 px ,10 px ,9 px ,10 px " align=" center " valign=" top " childLayout=" horizontal " > < effect > < onShow name=" move " n e v e r S t o p R e n d e r i n g =" false " mode=" in " direction=" top " length=" 200 " startDelay=" 0 " inherit=" true " / > < onHide name=" move " n e v e r S t o p R e n d e r i n g =" false " mode=" out " direction=" top " length=" 200 " startDelay=" 300 " inherit=" true " / > effect > < control id=" c o n t r o l M u s i c B u t t o n " type=" button " label=" music " vi sibleToM ouse=" true " width=" 100 px " height=" 100 px " > < interact onClick=" o n C o n t r o l M u s i c B u t t o n () " / > control > . . . panel > layer > screen >
Z ukázky lze vidět definici obrazovky „start“ společně s její kontrolní třídou a dále vnořenou vrstvu „controlLayer“, která bude zobrazena hned po spuštění aplikace. Součástí vrstvy je panel „controlPanel“, využívající efekt plynulého posunu panelu mimo obrazovku 40
4. Implementace a zpět při jeho skrytí a zobrazení. Také má přiřazen ovládací prvek (tlačítko); ten při stisknutí volá metodu onControlMusicButton() definovanou v kontrolní třídě obrazovky. Téměř veškeré nastavení uložené v XML souboru lze měnit přímo za běhu aplikace z kontrolní třídy. Pro implementaci ovládání pomocí Kinectu bylo potřeba upravit třídu InputSystemJme z balíku com.jme3.niftygui. Tato třída je zaregistrovaná jako posluchač jednak NITE událostí a jednak vlastnoručně definovaných gest (viz 4.4). V této třídě je obsažena logika, která na základě pohybu primárního bodu generuje příslušné události pro Nifty GUI. Stejně tak rozpoznání vlastního gesta je překládáno na událost značící stisk tlačítka Enter, popř. klávesy Escape. Samotné Nifty GUI tak zpracovává jeden unifikovaný vstup, nezávisle na tom, zda je pro ovládání použit Kinect, nebo klávesnice a myš.
4.7
Stereoprojekce
Java Monkey Engine byl primárně navržen pro zobrazování monokulárního obrazu. Celá struktura výstavby aplikace se tedy opírá pouze o jednu kameru tvořící pohled na scénu a jednu kameru pro vykreslování GUI. Standardní kurzor je hardwarový, poskytovaný operačním systémem. Editací některých tříd tvořících jádro jME lze ale patřičně duplikovat potřebné prvky a vytvořit tak pravý stereoskopický obraz, a to včetně ovládacích prvků v menu nebo kurzoru myši. Nejdříve se však zamysleme, jak získané obrazy prezentovat uživateli. Laboratoř Interakce člověka s počítačem je vybavena stereoskopickou projekcí, která využívá dvou datových projektorů promítajících obraz na jediné plátno. Pasivní polarizační brýle pak zajistí, abychom každým okem viděli obraz pouze z jednoho projektoru. Každý z projektorů má rozlišení 1280 × 1024 obrazových bodů a je připojen k jednomu z výstupů grafické karty počítače. Pro stereoskopické zobrazení je vhodný režim rozšířené plochy, díky němuž je v rámci operačního systému vytvořena jedna virtuální plocha o rozlišení 2560 × 1024 pixelů. Samotný systém pak plochu rozdělí na levou a pravou část a posílá je na odpovídající výstupy. Na aplikační úrovni je tedy potřeba vytvořit okno překrývající celou plochu, ve kterém jsou vedle sebe umístěny pohledy pro levé a pravé oko (tzv. „side-by-side stereo“). Toho dosáhneme pomocí zobrazovací transformace – ta určuje tvar pohledu na obrazovce, do kterého má být vykreslená scéna mapována (více o této problematice lze nalézt například v [21]). Pro její nastavení slouží v jME metoda setViewPort(). Potřebné úpravy začínají ve třídě Application. Zduplikujeme kameru společně s pohledem používaným pro zobrazení GUI a umístíme ji do pravé poloviny vykreslovaného okna: 1 2 3 4 5 6 7
// kamera je vytvorena s polovicnim rozlisenim Camera guiCamLeft = new Camera ( settings . getWidth () /2 , settings . getHeight () ) ; g ui Vi ew P or tL ef t = renderManager . create PostView ( " Gui Default left " , guiCamLeft ) ; Camera guiCamRight = guiCamLeft . clone () ; // duplikovani kamery g u i V i e w Po r t R ig h t = renderManager . createPo stView ( " Gui Default Right " , guiCamRight ) ; guiCamLeft . setViewPort (0 f , 1f , 0f , 1 f ) ; // umisteni do leve poloviny guiCamRight . setViewPort (1 f , 2f , 0f , 1 f ) ; // umisteni do prave poloviny
41
4. Implementace Ve třídě SimpleApplication pak místo hlavního uzlu, k němuž se připojují všechny objekty viditelné v GUI, vytvoříme dva nové uzly a každému přiřadíme jeden pohled. 1 2 3 4
protected Node gu iCamLeft Node = new Node ( " Gui Cam Left Node " ) ; protected Node gu iC a mR ig ht N od e = new Node ( " Gui Cam Right Node " ) ; g ui Vi ew P or tL ef t . attachScene ( gu iCamLeft Node ) ; g u i V i e w Po r t R ig h t . attachScene ( gu iC am R ig ht No d e ) ;
Dalším krokem je úprava Nifty GUI tak, aby se vykreslovalo do obou pohledů zaráz. Úpravou konstruktoru třídy NiftyJmeDisplay získáme přístup k oběma pohledům. Poté vynutíme dvojí vykreslení v metodě postQueue()): 1 2 3 4 5
// nastaveni kamery , ktera bude pouzita pro render renderManager . setCamera ( vpLeft . getCamera () , true ) ; nifty . render ( false ) ; // render leveho obrazu renderManager . setCamera ( vpRight . getCamera () , true ) ; nifty . render ( false ) ; // render praveho obrazu
Oba obrazy představující Nifty GUI vůči sobě nejsou posunuty, samotné menu proto nevytváří dojem prostorovosti. Hardwarový kurzor poskytovaný operačním systémem nelze duplikovat, je tedy potřeba jej skrýt a použít dva kurzory softwarové. Potřebné metody lze nalézt ve třídě CursorManager. Díky možnosti korekce vzájemného horizontálního posunutí kurzorů lze korigovat hloubkový vjem, který výsledný „3D“ kurzor vytváří. Vytvoření druhého pohledu na samotnou scénu s bludištěm je realizováno ve třídě Labyrinth. Princip je obdobný, jako u postupu pro GUI. Nezávisle na rozestupu kurzorů, i u těchto pohledů lze měnit vzájemnou polohu v horizontální rovině a určovat tak typ paralaxy a míru stereoskopického vjemu. Snadno si tak lze vyzkoušet rozdíl mezi negativní a pozitivní paralaxou. Nesmíme také zapomenout na duplikaci všech post-efektů, které se vážou ke konkrétnímu pohledu, nikoli celé scéně (např. reálné stínování či zvýraznění hran).
4.8
Třída Labyrinth
Třída Labyrinth tvoří srdce celé aplikace. Obsahuje hlavní metodu main() volanou při startu. Po spuštění zkontroluje připojení Kinectu, načte data z konfiguračních souborů, inicializuje scénu, Nifty GUI, zvuky, fyzikální engine. Její součástí je metoda simpleUpdate() představující hlavní smyčku aplikace volanou při každém průchodu. Stará se o načítání modelů, jsou zde definovány reakce na vstupy z klávesnice. Také má na starosti provádění fyzikálních výpočtů – implementuje rozhraní PhysicsTickListener, PhysicsCollisionListener (viz 4.5). Při požadavku ukončení aplikace uloží konfiguraci na disk a ukončí postupně všechna vlákna.
42
5 Závěr Cílem této práce bylo prakticky ověřit možnosti spojení vybraných prostředků virtuální reality s grafickým enginem Java Monkey Engine a fyzikálním enginem jBullet. Pozornost byla soustředěna zejména na možnost přirozené interakce člověka s počítačem, realizované pomocí snímače Kinect. Úvodní část práce je věnována zejména popisu samotného senzoru a jeho využití mimo herní průmysl. Druhá kapitola se soustředí na popis použitých technologií, v následující části jsou rozebrány vybrané implementační detaily, zejména způsob práce s pohybovým senzorem. Výsledkem je ukázková aplikace, kterou lze ovládat zcela výhradně pomocí gest a pohybů těla. Aplikace bude sloužit jako ukázka demonstrace technologií virtuální reality dostupných v Laboratoři interakce člověka s počítačem. Kromě toho je ale také plně použitelná jako jednoduchá hra, která nabízí relativně dobrou hratelnost a možnost soutěžení mezi jednotlivými hráči. Zdrojový kód aplikace je cenným zdrojem informací a může tak posloužit jako základní stavební kámen pro vývoj dalších aplikací ve virtuální realitě.
5.1
Možnosti rozšíření
Do budoucna se nabízí různé možnosti rozšíření. Bylo by vhodné umožnit předávání ovládání mezi uživateli, aniž by některý z nich musel opustit prostor snímaný Kinectem. Obrovský potenciál senzoru vybízí k použití mnohem většího počtu vlastních gest. Citlivost jejich rozpoznávání by mohla být nastavena pomocí různých parametrů ve stylu NITE gest. Mezi neméně důležité vlastnosti, které by bylo přínosné implementovat, jsou lokalizace programu do více jazyků či možnost výběru ovládání pro leváky. Třešničkou na pomyslném dortu by pak byl vestavěný editor, který by uživateli umožňoval vytvářet zcela vlastní nové úrovně.
43
A Doplňující snímky
Obrázek A.1: Ukázka ovládání aplikace pomocí dlaně.
44
A. Doplňující snímky
Obrázek A.2: Ukázka provedení gesta RaiseHand.
45
A. Doplňující snímky
Obrázek A.3: Ukázka provedení gesta Push.
46
A. Doplňující snímky
Obrázek A.4: Ukázka provedení gesta pro kalibraci ovládání pomocí dlaně.
47
A. Doplňující snímky
Obrázek A.5: Ukázka menu pro výběr nové hry.
48
A. Doplňující snímky
Obrázek A.6: Ukázka menu zobrazeného po dokončení úrovně.
49
B Uživatelský manuál B.1 Začínáme Tento manuál slouží k seznámení uživatele s aplikací Labyrinth, jejím ovládáním a možnostmi konfigurace. Manuál je psán implicitně pro operační systém Microsoft Windows 7, s menšími změnami je však aplikovatelný i na jiné systémy. Pro ovládání pomocí pohybového senzoru je vyžadováno, aby bylo nainstalováno OpenNI & NITE (pro samotný běh aplikace nikoli). Návod na instalaci lze najít na URL http://fivedots.coe.psu.ac.th/ ~ad/kinect/installation.html. B.1.1 Hardwarové nároky Program nabízí možnost vybrat vlastní rozlišení, vypnout náročné grafické efekty, vypnout antialiasing a snížit tak hardwarové nároky na minimum. Pro spuštění je vyžadována podpora OpenGL 2.0. Při běhu aplikace lze zapnout zobrazování FPS a dalších ladicích informací.
B.2 Spuštění aplikace Uživatel má aplikaci k dispozici v těchto formách: •
Projekt se zdrojovými kódy pro vývojové prostředí Java Monkey Engine (projekt lze otevřít i ve vývojovém prostředí NetBeans).
•
Zkompilovaný projekt ve formě JAR souboru (multiplatformní).
•
Zkompilovaný projekt ve formě EXE souboru (platforma Windows).
B.2.1 Java Monkey Engine projekt Projekt byl vytvářen ve vývojovém prostředí jMonkeyEngine SDK 3.0 Beta, předpokládá se kompatibilita i s novějšími verzemi. Projekt lze podle uvedeného návodu taktéž otevřít ve vývojovém prostředí NetBeans. Aby bylo možno zkompilovat projekt, je potřeba mít nainstalováno: •
jMonkeyEngine SDK (lze stáhnout na URL http://jmonkeyengine.org/ downloads/);
•
JDK (dostupné na URL http://java.sun.com/javase/downloads/index.jsp). 50
B. Uživatelský manuál Otevření projektu •
Spustíme jMonkeyEngine SDK, v nabídce [File] zvolíme [Open Project...], ve stromové struktuře nalezneme cestu k projektu, projekt vybereme;
•
ponecháme zatrženo [Open as main project], zvolíme [Open Project].
Kontrola knihoven Pokud se u nově otevřeného projektu neobjeví žlutý či červený vykřičník, je vše v pořádku. V opačném případě se pravděpodobně objeví chybová hláška:
Zkontrolujeme cesty ke knihovnám: •
klikneme pravým tlačítkem myši na projekt, vybereme [Properties];
•
vybereme kategorii [Libraries] vlevo, záložku [Compile] vpravo;
•
zkontrolujeme, zda jMonkeyEngine SDK nalezlo všechny uvedené knihovny (u žádné není žlutý vykřičník);
•
pokud tomu tak není, označíme všechny knihovny a pomocí tlačítka [Remove] je smažeme, dále klikneme na tlačítko [Add JAR/Folder], otevřeme adresář lib, který se nachází ve složce projektu Labyrinth, zde vybereme všechny JAR soubory a pomocí tlačítka [Open] je přidáme;
•
potvrdíme stisknutím [OK], v tuto chvíli by měly výstražné trojúhelníky zmizet.
51
B. Uživatelský manuál Kompilace projektu Klikneme pravým tlačítkem myši na projekt a zvolíme [Clean and Build]. Pokud proběhla kompilace bez chyb, je projekt připraven ke spuštění. V opačném případě bude chyba nejspíše ve špatně definovaných knihovnách. Spuštění projektu Klikneme pravým tlačítkem myši na projekt a zvolíme [Run]. B.2.2 Zkompilovaný JAR soubor Aby bylo možno spustit aplikaci, je potřeba mít nainstalováno: •
JRE (dostupné na URL http://java.sun.com/javase/downloads/index.jsp).
Spuštění z příkazového řádku: •
Otevřeme příkazový řádek, jako aktivní adresář nastavíme složku se zkompilovaným JAR souborem.
•
Zadáním příkazu „java -jar Labyrinth.jar“ spustíme aplikaci.
B.2.3 Zkompilovaný EXE soubor Aby bylo možno spustit aplikaci, je potřeba mít nainstalováno: •
JRE (dostupné na URL http://java.sun.com/javase/downloads/index.jsp).
Poté stačí pouze spustit soubor Labyrinth.exe.
B.3 Popis ovládání Aplikaci lze ovládat a většinu parametrů modifikovat pomocí GUI. Některá nastavení lze měnit pouze pomocí klávesnice, určité konfigurační parametry lze měnit pouze editací souborů s nastavením. Po spuštění aplikace se zobrazí hlavní nabídka. Pokud je připojen Kinect, je zobrazen výstup RGB, popř. hloubkové kamery (zrcadlově převrácený). Výstupy lze přepínat kliknutím na obraz. Rozpoznaní uživatelé jsou obarveni žlutě, sledovaný uživatel modře. Sledovaný bod (reprezentovaný dlaní) je vyznačen červeným záměrným křížem. Horní navigační lišta obsahuje tlačítka (zleva doprava): •
Předchozí hudební skladba. Aktivní pouze tehdy, pokud je povoleno přehrávání hudby. 52
B. Uživatelský manuál •
Následující hudební skladba. Aktivní pouze tehdy, pokud je povoleno přehrávání hudby.
•
Zapnutí/vypnutí přehrávání hudby.
•
Zapnutí/vypnutí doprovodných zvukových efektů.
•
Ovládání hry pomocí myši. Zobrazuje se pouze tehdy, pokud je připojen Kinect.
•
Ovládání hry pomocí dlaně. Zobrazuje se pouze tehdy, pokud je připojen Kinect.
•
Ovládání hry pomocí pohybu těla. Zobrazuje se pouze tehdy, pokud je připojen Kinect.
Spodní informační lišta obsahuje ikony (zleva doprava): •
Signalizace připojení Kinectu. Aktivní, pokud je připojen Kinect.
•
Signalizace sledování kostry uživatele. Nutné pro rozpoznávání gest pro levou ruku.
•
Signalizace sledování dlaně uživatele. Nutné pro možnost ovládání kurzoru pomocí dlaně.
Ukázku hlavní nabídky lze vidět na obrázcích A.3 a A.4. Postup pro získání plné kontroly: 1.
2.
•
Použití PSI kalibrační pózy zapnuto: Postavte se do zorného pole Kinectu. Vyčkejte, dokud nebudete rozpoznáni (signalizováno žlutým obarvením). Proveďte PSI kalibrační pózu (viz 3.6). Úspěšná kalibrace je signalizována modrým obarvením postavy a zaktivováním ikony hlavy ve spodní informační liště.
•
Použití PSI kalibrační pózy vypnuto: Postavte se do zorného pole Kinectu. Vyčkejte, dokud nebudete rozpoznáni (signalizováno žlutým obarvením) a následně proběhne i automatická kalibrace. Její dokončení je signalizováno modrým obarvením postavy a zaktivováním ikony hlavy ve spodní informační liště.
Zamávejte několikrát pravou rukou. Rozpoznání Focus gesta je signalizováno zobrazením červeného záměrného kříže ve výstupním obraze a zaktivováním ikony dlaně ve spodní informační liště.
Pokud kdykoliv během hry odejdete ze zorného pole senzoru, sledování kostry uživatele bude po určité době ukončeno. Pro znovuzahájení sledování může kterýkoliv uživatel provést PSI pózu, popř. při vypnutém použití pózy je kalibrace provedena automaticky pro prvního uživatele, který vstoupí do zorného pole Kinectu. Dále pokud dojde ke ztrátě sledování dlaně, pro znovuzískání kontroly je potřeba provést Quick Refocus gesto (zvednutí dlaně nad hlavu) nebo Focus gesto (zamávání). 53
B. Uživatelský manuál Vzhledem k tomu, že pohybový snímač Kinect může být v různých lokalitách umístěn v rozdílné výšce a uživatel nestojí vždy přesně naproti senzoru, nemusí být při ovládání kurzoru pomocí dlaně všechny prvky v menu dosažitelné. V takovém případě je nutno provést kalibraci (lze pouze v hlavní nabídce hry). Postup: •
Získejte plnou kontrolu (viz předchozí odstavec).
•
V hlavní nabídce umístěte ruku do prostoru tak, aby byla uprostřed kruhu, který jste s ní schopni opsat.
•
Levou rukou proveďte gesto pro kalibraci (viz obr. A.4), tzn. umístěte levou ruku do vodorovné roviny ve směru od těla na levou stranu.
•
Takto setrvejte dvě vteřiny (délku intervalu lze změnit v GameSettings.xml).
•
Po úspěšné kalibraci je kurzor umístěn do středu obrazovky.
Při ovládání pomocí přirozeného rozhraní (realizovaného senzorem Kinect) uživatel pohybuje kurzorem myši pomocí dlaně pravé ruky, potvrzuje akce pomocí gesta Push provedeného levou rukou (viz obr. A.3) a ruší akce pomocí gesta RaiseHand (taktéž realizovaného levou rukou, viz obr. A.2). B.3.1 GUI Popis položek grafického rozhraní: Start New Game Nabídne výběr herního bludiště a možnost spustit novou hru. Hra se zahájí kliknutím na vybrané bludiště. Pro každé bludiště lze vidět nejlepší zaznamenané časy. Settings Zobrazí submenu s možnostmi nastavení herních parametrů, grafiky a zvuků. Game Settings Umístěno v menu Settings. Umožňuje měnit následující nastavení: •
PSI Pose Required. Zapnutí/vypnutí požadování PSI pózy při kalibraci.
•
Auxiliary Cross. Zapnutí/vypnutí zobrazování pomocného kříže určujícího střed obrazovky ve hře.
•
Use Push Gesture. Zapnutí/vypnutí rozpoznávání NITE gesta Push pro pravou dlaň. Lze použít jako náhradu gesta Push pro levou dlaň kdekoliv ve hře.
•
Use Swipe Gestures. Zapnutí/vypnutí rozpoznávání NITE gest Swipe Left a Swipe Right pro pravou dlaň. Lze použít pro přepínání mezi bludišti v nabídce Start New Game. 54
B. Uživatelský manuál •
Mouse Tracking Sensitivity. Nastavení citlivosti ovládání náklonu bludiště pro ovládání pomocí myši. Číslo značí akční rádius (v obrazových pixelech) myši od středu obrazovky.
•
Hand Tracking Sensitivity. Nastavení citlivosti ovládání náklonu bludiště pro ovládání pomocí dlaně. Číslo značí akční rádius (v milimetrech) dlaně v prostoru (podél os x a y) od středu nastaveného kalibrací.
•
Body Tracking Sensitivity. Nastavení citlivosti ovládání náklonu bludiště pro ovládání pomocí pohybu těla. Číslo značí akční rádius (v milimetrech) v prostoru (podél os x a z) od počáteční pozice uživatele při zahájení nové hry. Náklon bludiště je určován podle souřadnic hlavy uživatele v prostoru. Při nastavení dostatečně malé hodnoty se tak stačí pouze naklánět; při větších hodnotách se musíme pohybovat po místnosti.
Pozor! U všech tří nastavení citlivosti ovládání platí, že čím menší hodnotu nastavíme, tím bude ovládání citlivější (akční rádius bude menší). Display Settings Umístěno v menu Settings. Při normálním zobrazení umožní za běhu aplikace změnit zobrazení v okně/fullscreen, rozlišení, antialiasing a vertikální synchronizaci. Při stereoskopickém zobrazení tato nastavení za běhu měnit nelze – je nutné editovat soubor AppSettings.jme a spustit program znovu. Lze však nastavit typ paralaxy a míru 3D efektu, a to zvlášť pro kurzor myši, a zvlášť pro samotné bludiště. Také je možné vybrat jednu ze tří přednastavených konfigurací (lze upravit na míru editací souboru GameSettings.xml). Sound Settings Umístěno v menu Settings. Umožňuje nastavení hlasitosti a zapnutí/vypnutí přehrávání hudby a doprovodných zvukových efektů. Back to Menu Umístěno v menu Settings. Návrat do hlavní nabídky. Credits Zobrazí jméno autora aplikace a zdroje, ze kterých bylo čerpáno při výběru hudby a zvuků (všechny obsažené zvuky jsou volně použitelné pro nekomerční použití). Quit Zobrazí výzvu k ukončení aplikace.
55
B. Uživatelský manuál B.3.2 Konfigurační soubory Aplikace pracuje s dvěma konfiguračními soubory, oba jsou umístěny ve složce ./Assets/Saves/ relativně vůči spouštěcímu JAR/EXE souboru. AppSettings.jme Obsahuje grafická a jiná klíčová nastavení potřebná pro spuštění aplikace (použití vstupů, atd.). Popis jednotlivých parametrů lze najít v souboru DESC_AppSettings.jme.txt umístěném ve stejné složce. GameSettings.xml Obsahuje zejména uživatelská nastavení (zvuky, stereoskopie, citlivost ovládání, atd.). Popis jednotlivých parametrů lze najít v souboru DESC_GameSettings.xml umístěném ve stejné složce. Zapnutí stereoprojekce Pro snadnou manipulaci se stereoprojekcí byly vytvořeny dvě kopie aplikace (rozlišené podle názvu složky projektu): •
Labyrinth. Aplikace je nakonfigurována pro monokulární obraz.
•
Labyrinth_stereo. Aplikace je nakonfigurována pro stereoskopický obraz.
Aplikaci lze ale nastavit také manuálně. Postup pro nastavení stereoprojekce v konfiguraci vhodné pro zobrazení v Laboratoři člověka s počítačem: •
Otevřete soubor AppSettings.jme v textovém editoru.
•
Změňte parametr StereoSide(bool) na hodnotu true.
•
Změňte parametr DisplayType(string) na hodnotu Desktop.
•
Změňte parametr Width(int) na hodnotu 2560.
•
Změňte parametr Width(int) na hodnotu 1024.
•
Uložte změny.
B.3.3 Přehrávání hudby Jako hudbu na pozadí program přehrává všechny soubory (nezáleží na pojmenování) ze složky ./Assets/Sounds/BackgroundMusic/. Soubory musí být formátu OGG.
56
B. Uživatelský manuál B.3.4 Rozložení klávesnice Celkový pohled na rozložení kláves s přiřazenou funkcionalitou:
Legenda: •
Tmavě modrá – nastavení citlivosti ovládání.
•
Zelená – Změna grafických nastavení.
•
Žlutá – Zapnutí/vypnutí vykreslování určitého prvku ve hře.
•
Fialová – Změna paralaxy a míry 3D vjemu.
•
Červená – ovládání a pohyb v nabídkách menu.
•
Světle modrá – cyklování mezi hudebními skladbami. 57
B. Uživatelský manuál Modrá Y/Z X C Shift
plynule zvětšuje akční radius pro ovládání pomocí myši plynule zvětšuje akční radius pro ovládání pomocí dlaně plynule zvětšuje akční radius pro ovládání pomocí pohybu těla v kombinaci s klávesami Z(Y),X,C plynule zmenšuje akční radius pro daný způsob ovládání
Zelená G H T B I K O L
zapnutí/vypnutí použití normálového a paralaxního mapování zapnutí/vypnutí zobrazování stínů zapnutí/vypnutí zvýraznění hran (Toon) zapnutí/vypnutí zesvětlení (Bloom), lze pouze při zapnutém zvýraznění hran ztmavení stínů o jeden krok zesvětlení stínů o jeden krok rozostření hran stínů o jeden krok zostření hran stínů o jeden krok
Žlutá P V F R
zapnutí/vypnutí zapnutí/vypnutí zapnutí/vypnutí zapnutí/vypnutí
Fialová NUM 1 NUM 2 NUM 3 NUM 4 NUM 5 NUM 6 NUM 7 NUM 9 Delete End Page Down
plynulá změna paralaxy pro bludiště směrem od pozitivní k negativní vynulování paralaxy pro bludiště plynulá změna paralaxy pro bludiště směrem od negativní k pozitivní plynulá změna paralaxy pro kurzor myši směrem od pozitivní k negativní vynulování paralaxy pro kurzor myši plynulá změna paralaxy pro kurzor myši směrem od negativní k pozitivní plynulá změna paralaxy pro kurzor i bludiště od pozitivní k negativní plynulá změna paralaxy pro kurzor i bludiště od negativní k pozitivní Nastavení paralax podle předvolby 1 Nastavení paralax podle předvolby 2 Nastavení paralax podle předvolby 3
Červená Enter/Space Esc Tabulátor Šipky
potvrzení nabídky/akce zrušení nabídky/akce posun na další prvek v menu posun v menu
Světle modrá M N
další hudební skladba v pořadí předchozí hudební skladba v pořadí
ladicího režimu pro fyzikální engine zobrazení pomocného kříže zobrazení počtu FPS ladicích informací
58
C Obsah přiloženého CD Přiložené CD obsahuje následující soubory: •
Text této práce ve formátu PDF.
•
Zdrojový kód aplikace Labyrinth ve formě projektu pro vývojové prostředí Java Monkey Engine (projekt lze otevřít i ve vývojovém prostředí NetBeans).
•
Knihovny potřebné ke kompilaci projektu.
•
Modely bludišť ve formátu C4D a OBJ.
•
Zkompilovaná (multiplatformní) verze výsledného programu ve formátu JAR a dále verze ve formátu EXE pro snadné spuštění na platformě Windows.
59
Seznam obrázků 2.1 2.2 2.3 2.4 2.5 2.6
3.1 3.2 3.3 3.4 3.5 3.6 3.7 4.1 4.2
Umístění hardwarových komponent v senzoru Kinect. 4 Síť bodů emitovaná IR zářičem. (a) Celkový pohled. (b) Detail vzoru. Převzato z [2]. 5 Schematický postup při vytváření hloubkové mapy. Převzato z [19]. 6 Diagram zapojení jednotlivých komponent pro SoC PS1080. Převzato z [19]. 7 Ukázka 3D teleprezence. (a) Pokrytí snímané scény. (b-c) Průběh komunikace. (d) Pohled z ostrého úhlu. Převzato z [13]. 9 Modelování pomocí programu ReconstructMe. (a) Obraz viděný RGB kamerou, (b) 3D model vytvářený v reálném čase (snímaný prostor je omezen na 1 m3 ). 11 Základní koncept výstavby Nifty GUI. Převzato z [8]. 15 Druhy paralax. a) nulová paralaxa, b) negativní paralaxa, c) pozitivní paralaxa, d) divergentní paralaxa. Převzato z [12]. 17 Třívrstvý model konceptu OpenNI API. Převzato z [16]. 18 Princip ovládání aplikace pomocí dlaně. Převzato z [18]. 23 Princip ovládání aplikace pomocí celého těla. Převzato z [18]. 23 „PSI“ kalibrační póza. 24 Stavový diagram pro správu relací. 26
4.3
Pohled na herní plochu ukázkové aplikace. 29 Schéma znázorňující postup demonstrační aplikace při detekci nového uživatele. 35 Schematické znázornění detekce gesta ArmForwards. 38
A.1 A.2 A.3 A.4 A.5 A.6
Ukázka Ukázka Ukázka Ukázka Ukázka Ukázka
ovládání aplikace pomocí dlaně. 44 provedení gesta RaiseHand. 45 provedení gesta Push. 46 provedení gesta pro kalibraci ovládání pomocí dlaně. 47 menu pro výběr nové hry. 48 menu zobrazeného po dokončení úrovně. 49
60
Literatura [1] AUKSTAKALNIS, Steve; LANIER, Jaron; BLATNER, David: Reálně o virtuální realitě: Umění a věda virtuální reality. Brno: Jota, 1994. 283 stran, ISBN 9788085617412. 2 [2] Kinect in infrared. [online]. 2010 [cit. 2012-05-12], dostupné z WWW
. 5, 60 [3] BOUFFARD, Patrick: Quadrotor Autonomous Flight and Obstacle Avoidance with Kinect Sensor. [online]. 2010 [cit. 2012-05-12], dostupné z WWW
. 10 [4] DAVISON, Andrew: Kinect Open Source Programming Secrets: Hacking the Kinect with OpenNI, NITE, and Java. McGraw-Hill Professional, 2012. 336 stran, ISBN 9780071783187. 5, 6 [5] DotNetNuke Corporation: Open Natural Interaction. [online]. 2011 [cit. 2012-05-12], dostupné z WWW . 18 [6] HOHMUTH, Jens; KARING, Martin: Nifty GUI 1.3.1 – The Missing Manual. [online]. 2011 [cit. 2012-05-12], dostupné z WWW . 14 [7] HYNEK, Vladimír: Využití grafického enginu ve virtuální realitě. [online]. Diplomová práce, Masarykova univerzita, Fakulta informatiky, 2010 [cit. 2012-05-12], dostupné z WWW . 13, 17 [8] jMonkey Engine Core Team: Creating JME3 User Interfaces with Nifty GUI. [online]. 2012 [cit. 2012-05-12], dostupné z WWW . 15, 60 [9] jMonkey Engine Core Team: jMonkey Engine. [online]. 2012 [cit. 2012-05-12], dostupné z WWW . 12 [10] jMonkey Engine Core Team: jMonkey Engine Physics: Gravity, Collisions, Forces. [online]. 2012 [cit. 2012-05-12], dostupné z WWW . 13, 14, 38, 40 [11] LaBELLE, Kathryn: Evaluation of Kinect joint tracking for clinical and in-home stroke rehabilitation tools. [online]. Diploma thesis, University of Notre Dame, Faculty of Computer Science and Engineering, 2011 [cit. 2012-05-12], dostupné z WWW . 3, 4, 5 61
[12] LAUBR, Daniel: Stereoskopická projekce. [online]. Diplomová práce, České vysoké učení technické v Praze, Fakulta elektrotechnická, 2006 [cit. 2012-05-12], dostupné z WWW . 16, 17, 60 [13] MAIMONE, Andrew; FUCHS, Henry: A First Look at a Telepresence System with Room-Sized Real-Time 3D Capture and Large Tracked Display. [online]. The 21st International Conference on Artificial Reality and Telexistence (ICAT), Osaka, Japan, November 28-30, 2011 [cit. 2012-05-12], dostupné z WWW . 9, 60 [14] Microsoft: Kinect Sensor Specifications. [online]. 2012 [cit. 2012-05-12], dostupné z WWW . 5, 6 [15] NITESCU, Daria: Evaluation of Pointing Strategies for Microsoft Kinect Sensor Device. [online]. Diploma thesis, University of Fribourg, Department of Informatics, 2012 [cit. 2012-05-12], dostupné z WWW . 3, 6, 18, 21, 36 [16] OpenNI organization: OpenNI Programmer Guide. [online]. 2011 [cit. 2012-05-12], dostupné z WWW . 18, 20, 21, 60 [17] PAULIS, Branislav: Stereo adventura s využitím programu Adobe Flash. [online]. Bakalářská práce, Masarykova univerzita, Fakulta informatiky, 2011 [cit. 2012-05-12], dostupné z WWW . 16, 17 [18] PrimeSense Ltd.: PrimeSense NITE Controls User Guide. [online]. 2010 [cit. 2012-0512], dostupné z WWW . 3, 22, 23, 25, 28, 60 [19] PrimeSense Ltd.: The PrimeSensor™ Reference Design. [online]. 2010 [cit. 2012-05-12], dostupné z WWW . 4, 6, 7, 60 [20] ŽÁRA, Jiří; BENEŠ, Bedřich; SOCHOR, Jiří aj.: Moderní počítačová grafika. 2. vydání, Brno: Computer Press, 2004. 609 stran, ISBN 9788025104545. 2 [21] SHREINER, Dave: OpenGL: průvodce programátora. Brno: Computer Press, 2006. 679 stran, ISBN 9788025112755. 41 [22] VINKLER, Michal: Snímání a rekonstrukce pohybu postavy. [online]. Bakalářská práce, Masarykova univerzita, Fakulta informatiky, 2009 [cit. 2012-05-12], dostupné z WWW . 4
62