ARKit, SceneKit a ako ovládať svet

V časti 1 tejto série sme prešli pracovným postupom, v ktorom sme spracovali 3D model, vytvorili sme projekt AR v Xcode, začali reláciu AR a náš model umiestnili do našej rozšírenej scény.

V tomto príspevku začneme uvádzať model do činnosti pomocou rôznych metód SceneKit a začneme interagovať s objektmi v našom svete.

Projekt tohto príspevku nájdete na adrese https://github.com/AbovegroundDan/ARTutorial_Part2.

Akcie SceneKit

SceneKit poskytuje sadu akcií, ktoré je možné použiť na uzol. Tieto akcie môžu byť použité na animáciu pohybu, rotácie, škálovania a ďalších vlastností uzlov. Môžu byť zoskupené tak, aby bežali súčasne, sekvencované tak, aby bežali jeden po druhom, a môžu byť opakované alebo obrátené. Úplný zoznam nájdete na stránke https://developer.apple.com/documentation/scenekit/scnaction

Budeme pokračovať v úprave súčasného projektu a začneme pridávať niektoré akcie k nášmu objektu. Začnime pridaním rotácie do našej sféry.

Po použití metódy addSphere v našej HoverScene pridajte nasledujúcu metódu:

V tomto kóde vytvárame akciu, ktorá popisuje otočenie o 180 stupňov okolo osi Y. Dokončenie tejto rotácie by malo trvať 5 sekúnd. Potom podnikneme túto akciu a pridáme ju do uzla, ktorý prešiel. Teraz musíme túto metódu zavolať z našej metódy addSphere. Na konci metódy za riadok, do ktorého pridávame podradený uzol, pridajte nasledujúci riadok:

Ak teraz spustíme tento kód, uvidíme, ako sa naša sféra otáča tvárou v opačnom smere a potom sa zastaví. Teraz chceme, aby sa táto animácia opakovala, takže sa neustále otáča.

Zmeňte náš kód addAnimation na nasledujúci text:

Tu sme pridali opakujúcu sa večnú akciu, ktorá ako vstup použije rotačnú akciu. Potom namiesto akcie rotácie pridáme do nášho uzla akciu opakovania. Spustite kód znova a uvidíme, že naša sféra sa teraz neustále otáča.

Pridajte do gule trochu pizzu. Poďme to tiež trochu vznášať a klesať. Chystáme sa pridať akciu vznášať nahor, vznášať nadol, zoraďovať tieto dve akcie a potom ich zoskupiť do našej existujúcej rotácie. Takto by mala vyzerať metóda addAnimation:

Teraz máme rotujúcu, vznášajúcu sa guľu, ktorú môžeme umiestniť kdekoľvek v našom svete.

Testy a abstrakcie

Pridajme k scéne nejakú interaktivitu. Stanovme si cieľ začať scénu tak, že používateľ umiestni sféry do sveta, a potom ich aktivujte klepnutím na. Keďže s naším kódom sa trošku komplikujeme, je čas začať s abstraktovaním spôsobu, akým sa zaoberáme našimi scénickými objektmi. Vytvorte novú skupinu v našom projekte s názvom Objects. V tomto priečinku vytvoríme nový súbor Swift s názvom SceneObject.swift.

Chystáme sa vytvoriť základnú triedu SceneObject, ktorá pochádza z SCNNode.

Chceme odčítať načítanie objektu od zvyšku kódu, takže umožňuje vytvoriť metódu init (), ktorá preberá názov súboru. V tomto inicializátore presunieme kód, ktorý máme na načítanie zo súboru.

Teraz môžeme vytvoriť triedu Sphere, ktorá pochádza z SceneObject:

Teraz máme triedu objektov Sphere, ktorá sa môže načítať sama. Pretože po klepnutí na tieto sféry budeme animovať sféry, odstránime volanie metódy addAnimation z metódy addSphere v našej aplikácii HoverScene. Pretože sme teraz presunuli všetok zavádzací kód do triedy Sphere, môžeme Sphere iba inicializovať a pridať priamo do koreňového uzla scény. Naša výrazne zjednodušená metóda teraz vyzerá takto:

Veľa čistejšie!

Teraz sa pozrieme na to, ako môžeme vykonať test zásahov. V našom ovládači pohľadu už máme rozpoznávač gesta klepnutia, takže sa k nemu môžeme pripojiť, ale ako zistíme, či naše kohútiky zasiahnu guľu, iný objekt alebo vôbec nič?

Našťastie nám s tým môže náš ARSCNView pomôcť. Má nasledujúcu metódu:

Môžeme z neho nakrmiť miesto v zobrazení a dá nám späť niekoľko uzlov, ktoré sú pod týmto bodom, bez ohľadu na to, aká je hodnota z alebo hĺbka.

Pretože chceme iba chytiť objekty Sphere, umožňuje vytvoriť rýchly filter, ktorý skontroluje, či je každý uzol vrátený do hitTestu Sphere. Aby sme to dosiahli, musíme chytiť najvyšší nadradený uzol pre každý uzol, ktorý chceme skontrolovať. Vráťte sa k nášmu súboru Node + Extensions.swift a pridajte nasledujúcu metódu:

Pretože všetky objekty v našej scéne sú dieťaťom koreňového uzla scény, chceme zastaviť, keď sa dostaneme k tomuto uzlu a už ďalej nekontrolujeme. Od svojej rekurzívnej metódy sa zastavíme a vrátime, keď zistíme, že koreňový uzol je rodičom nášho uzla.

V pozadí toho sa vráťme k nášmu ViewControlleru a upravíme nášho delegáta rozpoznávania gesta klepnutím. Chceme pokračovať v pridávaní nových sfér, ak klepneme na prázdne miesto, ale ak klepneme na existujúcu sféru, chceme začať s jej animáciou.

Keď dosiahneme ťuknutie, chceme získať miesto v našom scénickom zobrazení, odovzdať ho metóde hitTest v scéne a zistiť, čo sa dostaneme späť. Pretože sa chceme zaoberať iba jedným objektom naraz, chytíme prvý (ak existujú zásahy), potom pomocou nášho najvyššieho () rozšírenia uchopíme najvyššieho rodiča a skontrolujeme, či ide o guľu. Ak je, pridáme k tomu našu animáciu. Ak by sme z nášho testu nezískali žiadne zásahy, urobíme to ako predtým a pred kameru pridáme novú guľu.

Pokračujte a znova spustite aplikáciu. Klepnutím môžeme pridať guľu a potom klepnutím na ktorúkoľvek guľu spustiť pohyb. Máme však chybu, ktorú sme predstavili. Môžeme pokračovať v klepaní na guľu a animácie sa budú vždy pridávať do objektu. Môžete to otestovať a zakaždým, keď na ňu klepnete, uvidíte, ako sa sféra otáča rýchlejšie a rýchlejšie a vyššie.

Keďže animácia je špecifická pre danú sféru, presuňte kód addAnimation do samotnej sféry a premenujte ho na animáciu (). Namiesto node.addAnimation môžeme iba zavolať addAnimation. Pridáme tiež príznak do triedy Sphere, ktorú pred pridaním animácie skontrolujeme, a pri prvom pridaní ju nastavíme na true:

Zostáva už len zmeniť kód v spätnom volaní gestami, aby sa tento nový hovor spustil v samotnej sfére.

S touto časťou sme sa už teraz stretli. Máme sféru, ktorú môžeme umiestniť na svete, pridali sme určité interakcie, aby sme mohli animáciu odštartovať a trošku vyčistiť kód.

Kredit naviac

Spôsob, akým umiestnime guľu do sveta, je dosť prudký. Ťukneme a tam to náhle je. Pridajme k tejto funkcii trochu pizzu a pri umiestnení ju oživíme.

V našej metóde addSphere v HoverScene pridajme mierkový efekt. Keď pridáme guľu, oživíme jej mierku a namiesto použitia štandardnej lineárnej mierky vložíme efekt odrazenia alebo vyskočenia.

Zmeňte našu metódu addSphere na nasledujúcu a pridajte funkciu časovania easyOutElastic, ktorá nám poskytne toto odskočenie:

Teraz, keď klepneme na miesto gule, dostaneme celkom cool animovaný efekt.

Extra kredit, časť deux

S SceneKit sme robili veľa vecí, ale iba sme sa pasili po povrchu niektorých vecí, ktoré môže ARKit urobiť. Ako rýchla ukážka skôr, ako sa dostaneme k ďalším funkciám ARKit, pridajte do scény trochu zábavy, keď sfériku „pozeráme“ na kameru. Už sme pripojili metódu updateAtTime renderera a máme tu aj odkaz na kameru. Začnime teda pridaním metódy do triedy Sphere, aby sa pozerala smerom k určitému smeru. „Oko“ gule už čelí zápornému Z, čo je smerom objektu smerom dopredu. Urobíme to, že vytvoríme metódu, ktorá vezme vektorové označenie miesto v priestore, ktorému bude naše „oko“ čeliť.

V tomto kóde sa pozeráme na vzdialenosť medzi guľou a cieľovou pozíciou (kamerou). Ak je to menšie ako nejaké množstvo, animujeme oko tak, aby smerovalo k cieľu. Ak sa oko obrátilo smerom k fotoaparátu a používateľ sa posunul ďalej, ako je nastavená vzdialenosť, prejdeme do našej „hliadkovej“ animácie. V tomto kóde je potrebné poznamenať, že keďže neexistuje žiadny šikovný nástroj SCNAction na použitie animácie „LookAt“, zabalíme náš vzhľad (na :) volanie do transakcie SCNTransaction, ktorá nám umožňuje animovať pohyb. Vyhradené 3D herné nástroje, ako sú Unity alebo Unreal, majú pre tieto veci pohodlie, ale SceneKit ešte nie je na tejto úrovni.

Môžete si všimnúť, že došlo k diaľkovému hovoru na targetPos SCNVector3, ktorý je odovzdaný, ale táto metóda pre SCNVector3 neexistuje. Čo urobíme, je pridať nové rozšírenie pre toto diaľkové volanie.

Tento kód som vložil do nového súboru UtilityExtensions.swift, ale môžete ho umiestniť kamkoľvek.

Ďalej budeme musieť zmeniť našu metódu updateAtTime, aby sme odstránili kontrolu príznakov a zavolali metódu do nášho ovládača scény každý rámec. Náš správca scény bude zodpovedný za odoslanie správy všetkým objektom Sphere na našej scéne.

V našej aplikácii HoverScene vytvoríme metódu makeUpdateCameraPos, ktorá bude filtrovať iba objekty Sphere a zavoláme metódu hliadky.

Zmeňte tiež náš spôsob umiestnenia, aby ste sféry posunuli o kúsok ďalej. Urobme metódu didTapScreen, umiestnime našu guľu do vzdialenosti 5 metrov namiesto 1:

V našej triede Sphere urobme náš prah, aby sme spustili zrakový zrak na 4,85 metra:

Zmeňte tiež našu animáciu Sphere tak, aby sa trochu rozhliadala a nekĺzala.

The Float.random je ďalšie rozšírenie, ktoré je jednoducho:

Dajte to beh a umiestnite niektoré gule. Teraz by mali animovať sami, bez toho, aby na ne museli klepať. Choďte bližšie ku každému z nich a mali by ste vidieť, ako sa na vás pozerajú. Choďte ďalej a mali by sa vrátiť k hliadkovaniu v ich okolí. Teraz máme scénu priamo z dystopickej budúcnosti a vznášajúce sa oči sledujú každý náš pohyb.

Zostaňte naladení na viac zábavy ARKit!