Synetech

Rozšířená realita a její jednodušší použití s iOS 13 a “Reality” nástroji? Ne tak docela...

Apple je bez debaty několik kroků před konkurencí co se práce s rozšířenou realitou týče. Na WWDC 2019 přišel s dalšími možnostmi, díky kterým konkurentům opět o něco utekl.

tisk appparade 7 copy

ARKit byl rozšířen o věci jako People occlusion - “překrytí” virtuálních objektů, pokud se nachází za člověkem, Body tracking - vytvoření kostry člověka a záznam pohybů této kostry nebo Collaborative sessions - jednoduché sdílení AR scény mezi více zařízení). A hlavně také opět o něco více otevřel dostupnost vývoje vytvořením high-level frameworku RealityKit a také všemocného AR nástroje Reality Composer. Tyto nástroje ještě více zjednodušily už tak velmi jednoduchou implementaci (vzhledem ke komplexnosti celého řešení technologie jménem rozšířená realita).

RealityKit a Reality Composer

RealityKit je prvním frameworkem pro realistické renderování obrazu z dílen Applu, který byl navržen přímo pro použití v rozšířené realitě. Sám řeší renderování a texturování objektů v závislosti na prostoru, do kterého jsou umístěny (physical based rendering). K tomu používá velmi efektivní framework Metal, díky čemuž je renderování ještě méně náročné na výkon a kapacitu zařízení. Byly také zjednodušeny typy objektů oproti dříve užívanému SceneKitu tak, aby vše vyhovovalo podmínkám rozšířené reality.

Čím ovšem Apple nejvíce zpřístupnil vývoj je Reality Composer (dále jen RC). Tato aplikace je k dispozici jak pro macOS, tak pro iOS, resp. iPadOS. Lze v ní jednoduše poskládat AR scénu, včetně animací a interakcí s objekty a vše lze připravit nejen ve virtuálním 3D prostoru, ale rovnou v reálném prostředí. Kotvou scény může být horizontální/vertikální plocha, obličej, obrázek nebo dokonce reálný objekt.

Vyexportovaný soubor s koncovkou .reality lze spustit a prohlédnout v rozšířené realitě bez nutnosti další aplikace přímo na iPhonu/iPadu. Stejně tak lze tento soubor, případně celý projekt, vložit přímo do Xcode, kde ho stačí jen v kódu načíst (použít kód, který je automaticky generován po přidání projektu) a vložit do AR scény. Tím, že se takto RC projekt může nacházet přímo v repozitáři, vzniká skvělá možnost živě promítat změny RC projektu přímo do kódu aplikace. Pokud tedy chceme například posunout jeden z objektů, stačí pouze otevřít RC projekt, posunout objekt a bez dalších kroků prostě jen vybuildit aplikaci.

Na to vše postačí jakýkoli iPhone nebo iPad s iOS 13 (resp. iPadOS 13) a čipem A9 a vyšším (čili iPhone 6S / iPad 2017 a novější).

Všechno to zní až moc krásně na to, aby to bylo opravdu tak jednoduché.

Vzhledem k tomu, že je rozšířená realita stále velmi čerstvá technologie, dalo se očekávat, že nebude vše dokonale vyladěné. I přesto, že Apple v tomto oboru představuje určitou záruku kvality, zdá se, že s loňskými novinkami trochu předběhl sám sebe.

Vidět to lze již na velmi frekventovaných aktualizacích operačního systému, ve kterém stále ladí nemalé množství chyb a nedostatků. Neminulo to ani zmíněné nástroje pro rozšířenou realitu, ve kterých jsme sami narazili na několik zásadních limitací a nefunkčností některých řešení. Rád bych vám některé z nich tímto přiblížil.

SYNETECH & rozšířená realita

Nové nástroje jsme vyzkoušeli v AR zóně na soutěži aplikací AppParade, kterou pořádáme. Pravidelně se snažíme lidem přiblížit a nechat je si osahat aktuální trendy a technologie, mezi které ARko nepochybně patří.

Rozšířená realita je technologie, které se aktivně věnujeme a rozvíjíme její možnosti v rámci vlastního produktu SYNEVISION. Tentokrát, v rámci AppParade 33, která se konala v listopadu 2019, jsme se rozhodli vytvořit koncept muzea budoucnosti. Spočíval v tom, že jsme vystavili pouze exponáty bez jakýchkoli dalších panelů a cedulí a návštěvník se informace o nich dozvídal právě v rozšířené realitě. Ústředním motivem byla otázka, co iPhone světu dal a zároveň vzal.

appparade 33 arzone

S tím, co Apple v červnu na WWDC nasliboval, se mělo jednat o opravdu jednoduchý projekt. Podle všeho stačilo naskenovat referenční modely exponátů (pomocí demo aplikace, která je poskytována přímo inženýry z Applu), vytvořit panely s textem a vše jen přidat do scény v Reality Composeru. Tento projekt poté vložit do aplikace a při startu AR scény vše načíst a přidat přímo do ARView. O vše ostatní se měl postarat RealityKit. I proto jsme očekávali, že nám vývoj zabere minimum času. Narazili jsme ovšem na tolik limitací, že se doba vývoje protáhla na několikanásobek. Naštěstí jsme začali v dostatečném předstihu 🙏🏼

Nejzásadnější problémy, na které jsme při implementaci řešení narazili

AR zónu se nám nakonec podařilo dostat do použitelné podoby a slavila svůj úspěch, a proto vám všechny vzniklé problémy popíšu i s jejich tehdejším řešením. Snad se tím podaří uchránit alespoň některé z vás od budoucích šedivých či rovnou vyrvaných vlasů 👴🏼

Jak již bylo zmíněno výše, v Reality Composer projektu lze vytvořit scénu, která se opírá o kotvu reálného fyzického objektu. Stačilo tedy referenční model přidat do projektu a rozmístit kolem něj informační panely. To vše poté vložit do Xcodu a následně přidat do scény při startu AR session. Do důsledku mělo jít vše zvládnout na těchto 3 řádcích kódu:

let entity = try! Entity.loadScene()
arView.scene.anchors.append(entity)
arView.session.run(config, options: options)

Ač referenční model v RC projektu s jistotou figuroval (při náhledu v rámci iOS aplikace Reality Composeru se správně detekoval), po přidání do naší aplikace se žádná detekce nezdařila. Po hodinách zkoušení všeho možného a pročítání různých fór jsem zjistil, že na detekování referenčního modelu zkrátka výstup z Reality Composeru není připraven. Nezbývalo než si tedy detekci obstarat sám.

Detekci lze spustit následovně:

// Načtení referenčních objektů z assetů
guard let referenceObjects = ARReferenceObject.referenceObjects(inGroupNamed: "AppParade33Exhibition",
bundle: nil) else { return }
config.detectionObjects = referenceObjects
// Pro "poslouchání" vývoje scény je nutné přiřadit delegáta session
arView.session.delegate = self
arView.session.run(config, options: options)

Po úspěšné detekci (zjištěné z delegátové metody ARSession) stačí na detekovaný Anchor vložit výstup z RC. Jelikož již není potřeba v RC projektu držet referenční kotvu reálného objektu, může být tato kotva změněna na horizontální plochu. Přidání výstupu z RC projektu do scény probíhá ve zjednodušené formě takto:

func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
// `ARObjectAnchor` je kotva definovaného referenčního objektu
guard let objectAnchor = (anchors.first(where: { $0 is ARObjectAnchor })) as? ARObjectAnchor else { return }
let entity = try! Entity.loadScene()
// Následujícím přiřazením `AnchoringComponent` (s identifikátorem nalezené kotvy) definujeme pozici přidané entity
entity.anchoring = AnchoringComponent(.anchor(identifier: objectAnchor.identifier))
arView.scene.addAnchor(entity)
}

Někdy se RC projekt prostě rozbil…

Dodnes jsem neodhalil příčinu, ale nejednou se stalo, že se RC projekt prostě rozhodl, že už ho nebude možné načíst z kódu. Následně jsem byl vždy nucen vytvořit nový projekt, ve kterém jsem udělal naprosto totožné kroky a scénu bylo zázračně opět možné načíst. Tato chyba se objevovala zcela náhodně.

“Naštěstí” nás tento problém výsledně nemusel trápit, protože RC projekt a jeho načítání přímo v kódu nakonec nebylo možné použít. Jedním z důvodů byla zpětná kompatibilita.

Podpora starších verzí iOS

Že bude vše, co stvoříme pomocí Reality nástrojů podporováno pouze od iOS 13 dále, TO jsme samozřejmě věděli a počítali s tím, že záložku *AR zóna* uvidí ve své aplikaci většina osazenstva s jablečnými telefony a ne úplně všichni. Fakt, že nám způsobí takové trable integrovat vše, co by normálně stačilo označkovat if available(iOS 13.0, *), resp. @available(iOS 13.0, *), ten jsme nečekali.

Veškerou funkcionalitu jsme od začátku vyvíjeli v oddělené knihovně pro možnost znovupoužití. Pro uvedení do funkčního stavu jsme tedy zatím neřešili nastavení nižší minimální verze než 13. Všechno se na nás tedy sesypalo až v moment, kdy jsme se pokusili zaintegrovat knihovnu do aplikace AppParade.

První problém nastal ještě během buildu. Netýkal se ničeho jiného než automaticky generovaného kódu pro interakci s RC projektem. To, že knihovna sama nebude moct poskytovat zdroje (jako právě RC projekty) bylo jasné ihned, když jsme přišli na to, že generované soubory jsou jaksi “někde schované“ a neukazují se ve stromu projektu. Ovšem vývojáře v Applu nenapadla jedna vcelku podstatná věc - že by někdo někdy mohl chtít použít výstupy z RC projektů pouze jako doplňkovou část aplikace a generovaný kód tudíž neobalili do bloků specifikujících nutnou verzi iOS (available(iOS 13.0, *)) 🤦‍♂️

Vzhledem k tomu, že součástí generovaného kódu byla i struktura notifikací, které objekty posílaly např. po interakci nebo skončení animace, byl generovaný kód více než nezbytný. Naštěstí jsme po analýze zjistili, že kód nedělá nic jiného, než že načítá .reality soubor, který je možné vyexportovat z RC projektu, a definuje jejich interakce pomocí klíčů definovaných v projektu. I vzhledem k tomu, že nás pomalu začal tlačit čas, nezbývalo nic jiného než si kód vygenerovat v projektu s minimální verzí iOS 13.0, zkopírovat ho a otagovat classy pomocí @available(iOS 13.0, *). Pak už jen stačilo si vygenerovat .reality soubory, vložit je do projektu a upravit cestu k nim v původně vygenerovaném kódu.

Původní nádherná myšlenka držet si RC projekty v repozitáři a přímo do kódu promítat živě změny tímto samozřejmě naprosto padla… Jediný chybějící řádek v templatu pro generování totálně rozbil původně krásnou ideu…

Po vyřešení úspěšné kompilace se objevil další problém. Abychom byli fér, tento problém se netýká přímo Reality nástrojů, ale obecně používání nativních frameworků iOS verzí vyšších než je deployment target aplikace. Rád bych to jen zmínil pro případ, že by se někdo zasekl na stejném problému.

Pokud chcete použít takový framework, nestačí pouze používání jeho funkcí zabalit do if #available bloků nebo celé classy, ve kterých figuruje, otagovat pomocí @available. Za těchto podmínek stejně aplikace na nižší verzi iOSu okamžitě spadne. Je nezbytné definovat také import frameworku jako weak. Stačí do Other Linker Flags v Build Settings přidat -weakframework ”FrameworkName”. iOS bude poté ignorovat všechny importy frameworků, které pro něj nejsou dostupné.

weak framework

Pokud knihovnu používáte v rámci cocoapodu, je nutné nechat tento flag vygenerovat také do Pod projektu. Toho docílíte přidáním následujícího bloku do Podfile:

post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
if target.name == '_The pod name_'
target.build_configurations.each do |config|
config.build_settings['OTHER_LDFLAGS'] = ["-weak_framework", "\"_The native framework name_\""]
end
end
end
end

Otáčení objektu za kamerou? Schopnost jako dělaná pro náš projekt! Skoro…

Když jsme narazili v Reality Composeru na funkci “otáčení za kamerou”, kterou bylo možné přiřadit objektu, měli jsme velkou radost, protože to byla přesně schopnost, kterou jsme očekávali od virtuálních informačních panelů (aby návštěvník nebyl závislý na tom, z jaké strany se na exponát dívá). Bohužel, opět to nebylo až tak jednoduché.

Akce objektů v Reality Composeru je možné vždy definovat pouze pro předem stanovený čas a nelze je v průběhu zrušit. Obecně by např. zrušení animace v jejím průběhu na základě interakce uživatele jinak krásně jednoduchému vytváření akcí velmi slušelo. Ovšem to, že výše popsané vlastnosti má i otáčení za kamerou, tuto akci naprosto kompromituje.

Pokud chci jen, aby se objekt otáčel za kamerou po celou dobu scény, nemám jinou možnost než nastavit fixní čas otáčení (až 5 minut) a poté vyslat notifikaci, na základě které mohu (již z kódu) spustit akci znovu. Ovšem tímto je naprosto pohřbena jakákoli další animace objektu. Již dříve jsme si navrhli informační panely oboustranné, aby měli správný virtuální “feeling” a sami se pohybovali v prostoru (tím, že na ně uživatel klikne a ony se otočí). Jenže, pokud bylo nastavené otáčení za kamerou, žádná animace samozřejmě nenastala, protože otáčení za kamerou jakýkoli pohyb přebilo.

Jedinou možností, jak v tu chvíli zajistit funkčnost obou akcí, bylo snížení délky otáčení za kamerou a dost práce s handlováním notifikací. Stačilo pak jen při rozhodování o pokračování otáčení za kamerou zvolit, jestli uživatel během posledního otáčení na panel kliknul. Pokud ano, spustila se animace otočení a po jejím skončení se znovu spustilo otáčení za kamerou. Vypadalo to, že bude vše fungovat krásně, ovšem jen dokud se do scény neumístila druhá sada panelů. I na těch nejvýkonnějších zařízeních se najednou stalo problémem utáhnout náročnost procesu (místo feedu kamery jsme viděli akorát mazance, které se obnovovaly po krásných 3 vteřinách). Zjistili jsme, že handlování notifikací je zkrátka neuvěřitelně neoptimalizované (resp. není zamýšlené k častým interakcím).

Nakonec jsme přišli i na řešení, jak by mohly fungovat obě animace zároveň. Stačilo přiřadit objektům jednu akci, vyexportovat .reality soubor a ten vložit do nového projektu, kde se přidala další akce. Jestliže jsem dříve zmínil, že jsme přišli o možnost živě promítat změny přímo do projektu aplikace, tak tohle ji už totálně rozbořilo. Nicméně deadline se neúprosně blížil a proto jsme se rozhodli raději pro bezpečnou cestu a vůbec otáčení za kamerou nepoužít.

Závěr

Směr, kterým se Apple ubírá v oblasti rozšířené reality, je rozhodně správný a přibližuje tento svět všem stále více - dokonce i lidem, kteří nemají žádné zkušenosti s programováním. Svůj náskok před konkurencí si nejen drží, ale ještě ho stále zvětšuje.

Bohužel, tento rok si Apple nejspíš ukousl až moc velké sousto. To se netýká jen rozšířené reality, svědčí o tom mimo jiné i to, že v prvních týdnech od vydání nového iOS přicházely aktualizace a opravy bugů v řádech dnů. Doufejme jen, že se Apple z těchto přešlapů poučí a bude opět poskytovat zaručeně kvalitní služby a to i za cenu menšího zpoždění.

Objevovaly se určité spekulace o tom, že v letošním roce by Apple konečně měl představit brýle pro rozšířenou realitu, ovšem jak jsme mohli zjistit na představeném případu, je stále ještě na čem pracovat. Uvidíme tedy, jaké další funkce budou představeny na letošním WWDC.

Nicméně, bez ohledu na současné mouchy, další přelomová technologie s potenciálem změnit vnímání světa každého z nás, již s jistotou klepe na dveře 👀