de Ranadhir Dey

Cum să începeți cu realitatea augmentată în Swift, modul simplu

Dacă te uiți în jur, aceasta este epoca de aur a tehnologiei. Fiecare keynote adaugă ceva nou la teancul existent de tehnologii. Este interesant să vedem cum aceste tehnologii emergente ne-au îmbunătățit limitele imaginației. Ca dezvoltator, trebuie să fim mândri că suntem utilizatorii direct ai acestor tehnologii.

Dar fiecare nouă tehnologie vine cu o curbă de învățare destul de abruptă. Pur și simplu nu puteți viziona o prezentare sau un videoclip pe Youtube și începeți să dezvoltați o aplicație. Dar vestea bună este că, cu AR în Swift, este remarcabil de ușor să lucrați cu aplicații AR de bază. Apple a făcut majoritatea pentru tine. Urmăriți și veți vedea cât de ușor poate fi.

Hai să sapăm …

În acest tutorial, vom învăța instrumentele și tehnicile necesare ale AR în Swift, care ne vor permite să creăm o aplicație care să vă decoreze podeaua cu niște plăci de pardoseală și texturi din lemn. Aplicația terminată va arăta cam așa:

Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Să începem prin a crea un vedere unică aplicație în Xcode și denumiți-l Home Decor.

Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Adăugarea permisiunilor camerei

Acum, primul lucru pe care îl vom face este să navigăm la fișierul info.plist și să activăm utilizarea camerei. Capacitatea camerei este primul lucru de care aveți nevoie pentru o aplicație AR. Găsiți cheia Descriere utilizare camera, precum imaginea de mai jos, și dați-i un mesaj adecvat. Acest mesaj va apărea chiar în prima lansare a aplicației în timp ce solicitați permisiunea camerei de la utilizator.

1611994393 532 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Adăugarea de capacități ARKit la aplicație

Accesați Main.storyboard. Glisați și fixați o vizualizare ARKit SceneKit pe ViewController și fixați ARSCNView la marginile ViewController.

1611994394 390 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Creați un IBOutlet pentru clasa ViewController și denumiți-l sceneView. De îndată ce faceți acest lucru, o eroare de precizare ARSCNView nedeclarat, va apărea, deoarece controlerul nostru de vizualizare nu recunoaște nimic de tip ARSCNView. Pentru a rezolva acest lucru și pentru a utiliza alte caracteristici ARKit, trebuie să importăm ARKit în controlerul de vizualizare.

1611994394 191 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Acum, treceți de la storyboard la fișierul view controller.swift. Declarați o proprietate de tip ARWorldTrackingConfiguration înainte de metoda viewDidLoad () și denumiți-o config. Și controlerul nostru de vizualizare va arăta astfel (am eliminat metoda didReceiveMemoryWarning):

import UIKitimport ARKit
class ViewController: UIViewController {
@IBOutlet weak var sceneView: ARSCNView!let config = ARWorldTrackingConfiguration()
override func viewDidLoad() {super.viewDidLoad()}

Permiteți depanarea

Această variabilă de configurare va determina configurațiile sesiunii de scenă. Vom vedea utilizarea acestuia mai târziu în secțiune. Acum, în metoda viewDidLoad după super.viewDidLoad (), adăugați următoarele:

sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]

Aici activăm opțiunile de depanare pentru sceneView, care nu este altceva decât vizualizarea camerei cu capacitățile cadrului AR. ARSCNDebugOptions.showWorldOrigin va afișa originea lumii pe ecran. Acest lucru ne va ajuta să găsim punctul de referință al tuturor celorlalte poziții. ARSCNDebugOptions.showFeaturePoints va afișa toate punctele de pe ecran pe care camera AR le-a recunoscut în împrejurimi.

Acum, pentru a începe sesiunea AR, trebuie să rulăm o sesiune în sceneView cu configurațiile menționate în variabila config. Chiar sub linia sceneView.debugOptions, scrieți:

sceneView.session.run(config)

Acum rulați aplicația pe dispozitivul dvs. (nu pe un simulator, deoarece nu are camera). Va apărea alerta care solicită permisiunea camerei cu mesajul pe care l-ați scris și trebuie să o permiteți. Așteptați puțin cât încarcă originea lumii.

1611994395 682 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Dacă sunteți aici, aveți deja o aplicație AR care rulează. Felicitări!

Cum funcționează AR Axes

Bara roșie sau axa X este utilizată pentru a poziționa obiecte la stânga sau la dreapta originii lumii. Bara verde sau axa Y este utilizată pentru a poziționa obiectele în partea de sus sau de jos a originii lumii. Și bara albastră sau axa Z este utilizată pentru a determina cât de aproape sau de departe va fi plasat un obiect de la originea lumii.

O valoare pozitivă a lui X va poziționa un obiect în dreapta originii lumii, iar negativ îl va plasa în stânga. Pozitiv pentru Y îl va plasa deasupra, iar negativ îl va plasa în partea de jos a originii lumii. Pozitiv pentru Z îl va pune mai aproape, iar negativ îl va plasa mai departe de originea lumii.

Adăugarea unui obiect virtual

Să adăugăm câteva obiecte virtuale la scenă. Capsula 3D ar fi o alegere bună. Declarați o capsulăNod de tip SCNNode și dă-i o geometrie de capsulă. Acordați-i o înălțime de 0,1 metri și o rază de 0,03 metri.

let capsuleNode = SCNNode(geometry: SCNCapsule(capRadius: 0.03, height: 0.1

Acum poziționați-l la 0,1 metri la stânga de origine mondială, la 0,1 metri deasupra originii mondiale și la 0,1 metri distanță de origine mondială:

capsuleNode.position = SCNVector3(0.1, 0.1, -0.1)

Acum, adăugați nodul la scenă:

sceneView.scene.rootNode.addChildNode(capsuleNode)

ScenaView conține o scenă care este responsabilă pentru păstrarea tuturor obiectelor 3D în format SCNNode care vor forma scena 3D. Adăugăm capsula la nodul rădăcină al scenei. Poziția nodului rădăcină este exact aliniată cu poziția originii lumii. Asta înseamnă că poziția sa este (0,0,0).

În prezent, metoda noastră viewDidLoad arată astfel:

override func viewDidLoad() {
super.viewDidLoad()
sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
sceneView.session.run(config)
let capsuleNode = SCNNode(geometry: SCNCapsule(capRadius: 0.03, height: 0.1))
capsuleNode.position = SCNVector3(0.1, 0.1, -0.1)
sceneView.scene.rootNode.addChildNode(capsuleNode)
}

Acum rulați aplicația.

1611994396 340 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Misto! Tocmai am poziționat un obiect virtual în lumea reală. Puteți juca cu diferite poziții și diferite geometrii pentru a explora mai mult. Acum să rotim capsula cu 90 de grade în jurul axei Z, astfel încât să se așeze plat pe axa X și să-și schimbe culoarea în albastru.

Unghiurile lui Euler

Unghiurile Euler sunt responsabile pentru unghiul de afișare al SCNNode. Vom vedea cum să-l folosim pentru a roti capsula.

Fiecare SCNGeometry poate avea materiale adăugate, ceea ce definește aspectul geometriei. Materialele au o proprietate difuză care, atunci când sunt setate, își răspândește conținutul pe toată geometria.

În viewDidLoad, adăugați liniile de mai jos după ce setați poziția capsulei.

capsuleNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue //1capsuleNode.eulerAngles = SCNVector3(0,0,Double.pi/2)//2

Aici, în prima linie, setăm culoarea albastră pe primul material al nodului care se va răspândi pe capsulă și îl va face să arate albastru. În linia 2, setăm unghiul Z Euler la radiani de 90 de grade. În cele din urmă, vizualizarea noastră se încarcă și arată astfel:

override func viewDidLoad() {
super.viewDidLoad()
sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
sceneView.session.run(config)
let capsuleNode = SCNNode(geometry: SCNCapsule(capRadius: 0.03, height: 0.1))
capsuleNode.position = SCNVector3(0.1, 0.1, -0.1)
capsuleNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue //1
capsuleNode.eulerAngles = SCNVector3(0,0,Double.pi/2)//2
sceneView.scene.rootNode.addChildNode(capsuleNode)
}

Acum rulați aplicația.

1611994397 680 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Grozav! O capsulă de dormit de culoare albastră pe perete! Puteți adăuga chiar texturi ca conținut difuz pentru a face un obiect să pară mai realist. Vom folosi acest lucru în secțiunea următoare atunci când așezăm texturile plăcilor pe podea.

Acum, că am plasat cu succes obiecte virtuale pe lumea reală, este timpul să ne decorăm pardoseala reală cu gresie virtuală. Pentru a obține efectul de podea, vom folosi un SCNPlane geometrie. SCNPlane nu are nici o adâncime ca alte geometrii 3D, ceea ce îl face o potrivire perfectă pentru aplicația noastră.

ARSCENEView Delegates

Înainte de a începe detectarea pardoselii, vom explora câteva metode delegate ale scenei noastre ViewView pentru a înțelege cu ce capabilități suntem echipați pentru a interacționa cu o sesiune AR în desfășurare.

func renderer(SCNSceneRenderer, didAdd: SCNNode, for: ARAnchor)

Ori de câte ori ne mișcăm sau înclinăm dispozitivul cu o sesiune AR activată, ARKit încearcă să găsească diferite ARAnchors în împrejurimi. Un ARAnchor conține informații despre poziția și orientarea lumii reale care pot fi folosite pentru a plasa un obiect.

Odată găsită o ancoră diferită, un nou nod se adaugă la scenă cu aceleași informații pentru a găzdui această ancoră nou găsită. Această metodă de delegat ne va informa despre asta. Îl vom folosi pentru a găsi toate pozițiile de pe podea pentru a plasa plăcile.

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor)

De cele mai multe ori, toate nodurile care se adaugă de la ancore aparțin aceluiași obiect. Să presupunem că vă deplasați în jurul podelei, iar dispozitivul găsește o serie de ancore în diferite poziții. Încearcă să adauge toate nodurile pentru acele ancore, deoarece crede că toate aceste ancore aparțin unor obiecte diferite.

Dar ARKit recunoaște în cele din urmă că toate aparțin aceluiași etaj, așa că actualizează chiar nodul de la primul etaj adăugând dimensiunile altor noduri duplicate. Această metodă de delegat ne va informa despre asta.

func renderer(SCNSceneRenderer, didRemove: SCNNode, for: ARAnchor)

După actualizarea primului nod unic cu dimensiunile tuturor celorlalte noduri duplicate, ARKit elimină toate nodurile duplicate și metoda delegată ne anunță. Vom folosi toate metodele de delegare de mai sus în aplicația noastră (iar scopul lor va deveni mai clar).

Detectarea avionului

În prezent, scena noastră încearcă să adune toate ancorele pe care le întâlnește, deoarece acesta este comportamentul implicit. Dar, deoarece o podea este o suprafață orizontală, ne interesează doar ancorele care se află pe planuri orizontale. Deci, reveniți la metoda noastră viewDidLoad și scrieți codul de mai jos inainte de rularea sesiunii (adică înainte de linia sceneView.session.run (config)).

config.planeDetection = .horizontal

În metoda viewDidLoad, puteți elimina totul după sceneView.session.run (config), deoarece a fost pentru plasarea capsulei pe ecran și nu mai avem nevoie de asta. Deoarece vom folosi toate metodele de delegat menționate mai sus, trebuie să facem din viewController un delegat al sceneView. Înainte de acostarea de închidere a metodei viewDidLoad (), adăugați linia de mai jos.

sceneView.delegate = self

Ar trebui să primiți o eroare acum, deoarece controlerul nostru de vizualizare încă nu este conform delegatului sceneView. Pentru a implementa acest lucru, să creăm o extensie a controlerului de vizualizare la sfârșitul fișierului ViewController.swift.

extension ViewController:ARSCNViewDelegate{}

Metoda delegată didAdd SCNNode va fi declanșată de fiecare dată când o parte a podelei este descoperită și un nou nod este adăugat la scenă pe baza ancorei. În cadrul acestei metode, vom crea un nod de podea și îl vom adăuga ca un copil al nodului adăugat recent în poziția ancorei.

ARArchor poate fi de patru tipuri diferite pentru a rezolva patru scopuri diferite. Aici ne interesează doar ARPlaneAnchor care detectează planurile orizontale sau verticale.

Crearea nodurilor de etaj AR

Să creăm o funcție care ar primi un parametru ARPlaneAnchor, să creăm un nod de podea la poziția ancorei și să-l returnăm.

func createFloorNode(anchor:ARPlaneAnchor) ->SCNNode{
let floorNode = SCNNode(geometry: SCNPlane(width: CGFloat(anchor.extent.x), height: CGFloat(anchor.extent.z))) //1
floorNode.position=SCNVector3(anchor.center.x,0,anchor.center.z)                                               //2
floorNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue                                             //3
floorNode.geometry?.firstMaterial?.isDoubleSided = true                                                        //4
floorNode.eulerAngles = SCNVector3(Double.pi/2,0,0)                                                    //5
return floorNode                                                                                               //6
}

Să parcurgem funcția linie cu linie și să o discutăm mai detaliat. Vă rugăm să urmați descrierea fiecărui rând, deoarece este partea cea mai dificilă.

1. Creăm un nod cu o geometrie SCNPlane care are dimensiunea ancorei. Extinderea ARPlaneAnchor deține informațiile despre poziție. Faptul că extensia.z a fost utilizată ca înălțime și nu extensie.y, ar putea fi puțin confuz. Dacă vizualizați că un cub 3D este așezat pe o podea și doriți să-l faceți plat de-a lungul unei suprafețe 2D, veți schimba y-ul la zero și ar deveni plat. Acum, pentru a obține lungimea acestei suprafețe 2D, ai lua în considerare z, nu-i așa? Etajul nostru este plat, deci avem nevoie de un nod plat, nu de un cub.

2. Stabilim poziția nodului. Deoarece nu avem nevoie de nicio altitudine, facem y zero.

3. Setați culoarea podelei la albastru.

4. Culoarea materialului va fi afișată doar pe o singură față, cu excepția cazului în care menționăm în mod specific că este față-verso.

5. În mod implicit, planul va fi plasat vertical. Pentru a-l face orizontal, trebuie să-l rotim cu 90 de grade.

Implementarea metodelor de delegat

Acum, să implementăm metoda delegată didAdd SCNNode.

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else {return} //1
let planeNode = createFloorNode(anchor: planeAnchor) //2
node.addChildNode(planeNode) //3
}

În linia 1, verificăm dacă ancora este un ARPlaneAnchor, deoarece ne-am ocupa doar de acest tip de ancoră.

În linia 2, se creează un nou nod bazat pe ancoră. În linia 3, se adaugă la nod.

Acum, în delegatul didUpdate SCNNode, vom șterge toate nodurile noastre de etaj. Vom face acest lucru, deoarece dimensiunile nodului curent au fost modificate, iar vechile noduri de podea nu se vor potrivi. Apoi vom adăuga din nou un nou nod de podea la acest nod actualizat.

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else {return}
node.enumerateChildNodes { (node, _) in
node.removeFromParentNode()
}
let planeNode = createFloorNode(anchor: planeAnchor)
node.addChildNode(planeNode)
}

În metoda delegată didRemove SCNNode, vrem să curățăm toate nodurile noastre nedorite într-un mod civilizat.

func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {
guard let _ = anchor as? ARPlaneAnchor else {return}
node.enumerateChildNodes { (node, _) in
node.removeFromParentNode()
}
}

Phew! Asta este! Rulați aplicația.

1611994397 747 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Adăugarea efectului de țiglă

Stai ce? O podea albastră? Nu, încă nu am terminat complet. Doar o mică schimbare și vom avea o podea uimitoare!

Pentru a schimba podeaua albastră în gresie, avem nevoie de o textură. Să căutăm o textură pentru gresie. Am căutat „textura podelei din lemn” și am găsit câteva imagini frumoase de textură. Salvați oricare dintre acestea pe Mac și trageți-l în Assets.xcassets.

1611994397 365 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

L-am numit WoodenFloorTile. Îl poți numi orice vrei. Înapoi la fișierul ViewController.swift din nou. În funcția createFloorNode, în loc să setați UIColor.blue ca conținut difuz, faceți-l o imagine UII cu numele pe care l-ați dat imaginii din folderul activului.

floorNode.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "WoodenFloorTile")

Acum rulați aplicația și așteptați până când se încarcă originea lumii. Odată ce podeaua este detectată, deplasați-vă pentru a actualiza informațiile despre nod.

1611994398 631 Cum sa incepeti cu realitatea augmentata in Swift modul simplu

Uau, chiar ai o podea superba! Puteți descărca mai multe texturi și le puteți plasa într-un listView. Acest lucru vă permite să schimbați podeaua pe baza texturii selectate, așa cum a fost arătat în prima parte.

Descărcați proiectul complet de pe GitHub aici.

Acum că aveți o podea frumoasă, trebuie să vă lipsească niște mobilier frumos pentru a oferi camerei dvs. un aspect minunat! Vom lucra la asta mai târziu.