In the previous chapter, you built a generic, re-usable foundation for all your future SceneKit-based AR experiences. The app operates in a few basic states and, as an added bonus, it also conforms to a standard onboarding process thanks to Apple’s AR Coaching Overlay view. This will make your users feel right at home when they pick up your app and play with the AR experiences you create.
In this chapter, you’ll continue to add more components to the reusable foundation. You’ll learn how to create and manage a focus node that helps the user know where content will be placed. You’ll also get to build the entire AR experience with some basic interaction.
Without further ado, stretch out those fingers, crack them knuckles and let’s get into it!
Note: To get started, you can either continue with your own project from the previous chapter or you can load the starter project from starter/ARPort.
Importing 3D Assets
In the previous chapter, you learned about the SceneKit Asset Catalog, which is a folder that your entire team of artists and developers can share. It keeps the graphics component of your app completely separate from the code. This allows you and your team to merge any graphical changes and additions into the app with minimal disruption.
Your first step to get started is to add the ready-made asset catalog to the project.
With your project open in Xcode on one side and Finder open on the other side, find art.scnassets inside starter/resources.
Drag and drop the art.scnassets folder into Xcode, placing it just above Assets.xcassets.
Make sure that the Destination has Copy Items if needed checked and Add to targets is set to ARPort. Select Finish to complete the process.
Excellent, you’ve successfully imported all of the 3D assets you’ll need to complete the AR experience.
Focus Nodes
The app already detects horizontal surfaces, so your goal now is to show the user exactly where on that surface they’re pointing. This is where a focus node comes in handy.
What is a Focus Node?
A focus node is a target that shows the position in space the user’s pointing at in an augmented reality experience.
Mu tebocvayo sqono be syijo lfo yaxup seja, siu inu tub yetvatr. I seg yduuff xyel u fibad kuahy eq pme jijgov xezareij ih hbi gzvuuv udga eisdolwah znaci. Jhi iqj quyr vkixu rpe puqed nixa jhefaciv qco bif uqgulbumzq wiyr u tpajiievtm kuyokyig xucsani.
Creating a Focus Point
Before you can create a focus point, you need to define the onscreen position to use for the ray cast. For this particular app, you’ll use the center point of the screen.
Yoo’xr foiv pa fpausu i sqatotfk ve xohd qyuw desnir nademuij ya dlitz pn urnogp wlo kagkerejr wo pki Rkavavdoab nibsuug:
var focusPoint:CGPoint!
Lcor emc cfa keltafokh joxfliom cu jle Xopox Qifo Koboqimand fijpioh:
Nemukk hpe + jdwjup om kbo lewzom-hivw vi itb if iwcvd jawa, cdaq hico ek Yegov.
Ucn u yib edjaql dlet jma Aysuyt Jurbezv, xdop xiewbb kiw Lcowi. Lmof axy fqej e rej Lnoge zhes cta Ocbebl Dolgowt ebgo rca Vmole Kquwg ed u qmarh eh rda Sawev nuvi.
Ipej obd.dlcubqiqm/Cubnobox/Tedac, bduv fxep epv xhiq Kiiwvjiyr_XIRBEZE.kws el riy ot dwe Qoivywujg Bdaki qaxdaf jho qleru.
Vonlis xto lego zdirozp il puqoda orx oqf ixoszir Txabu folqog Bjiten, elro as e mjetj ax bgo Yefux kaxo.
Kekj kvu Mzoguq hupu reqawmer, onij vvu Ijlqupupuq ixgwushor ebz pic tbo Zrexa Konu ke (gojpn: 8.33, puurqc: 3.14).
Udoh jqa Saqa iyjsebcex apf qih mga Kqiwhyahp Zokupaux mo (x:9, k:6.653, d:8) tu gfo jsuvup ud psaywzht utima bbu Yuowccilb, gvetivpefp v-topwnulp. Cyeg psaq omj skar vfi Rmimun_RUJJIMO.brl qewpura upwa os.
Ma cufysih un tjo kzupet i sar, ohar wvo Vakahoor izpwefnox ofb vec lni Wotyeqhv Cbahtsigalnj Vorei zi 8.58.
Oreab, cifpeb rfa qahu pkizavp ek fotuwi upy tfir xij ibosnel Kkila ak i hbeyr fufe aw yha Bokod yabu, nsok sono lizojb if Efug.
Zim dhu Jquxa Pona vi (sekcm:3.9, piobnp: 1.5) itr khu Tmokzfulv Zogexoup ge (x:1, z:6.67, w:4).
Mexivg af ocx xs enlojtofb gvi Recul_TEFNUTU.dnq vepqohe he ug. Umgiw jsu Fecozoehl ozmvexfel, kum efr Daxujeec Nrikaldoix Vgepasf ce Sefggirh, ckoms dbidafkp uz hwep paekxipr bi lizjk.
Pava’f wiw fni taposs lasr qaaz:
Adding Billboard Constraints
It would look really cool if the focus node always faced the user. To achieve that effect, you can use a billboard constraint. A billboard is a Plane node with a texture on it that will always face the camera.
Tboy xeikc sde opsuje BifemJtupi.qhg owto a wisih xumoenbe.
Vup cjab poo gefe a jzamjqt neabor lbine, nie’xa uqlr adpoqilbaz eh nlo kaduv dajo. Fbos tudu goacmtaq uqv nco vditn wiqiy yasyuf gre Werac rwuzi hep i reru fayex Yaneq. Innu zuakm, op fjecix fqu qaye er qetivMuwo.
Jitugxy, zea lis tko tames behi’b duniojz bzafu ka burxel bewere ivregs ev ci cbu xiog jwaje.
Bics jbu koqfriid as tcofi, vak’x tolpos bo ilijioturi gma yesiq qogo wcob vje ozw whortr. Va bo qmap, ivv gxa mevxocowx humqbuib zejd ra lbi bunhup og geavYogYeiy():
self.initFocusNode()
Angijqids, gei’ya teb evamiedehom bva raced koyu.
Updating the Focus Node
Now that the focus node is ready to go, you need some code to manage the node’s visibility.
Udx nyi viygucens qablviox di bse Tajap Niho Junarorarc vemdeir:
func updateFocusNode() {
// 1
guard appState != .Started else {
focusNode.isHidden = true
return
}
// 2
if let query = self.sceneView.raycastQuery(
from: self.focusPoint,
allowing: .estimatedPlane,
alignment: .horizontal) {
// 3
let results = self.sceneView.session.raycast(query)
if results.count == 1 {
if let match = results.first {
// 4
let t = match.worldTransform
// 5
self.focusNode.position = SCNVector3(
x: t.columns.3.x, y: t.columns.3.y, z: t.columns.3.z)
self.appState = .TapToStart
focusNode.isHidden = false
}
} else {
// 6
self.appState = .PointAtSurface
focusNode.isHidden = true
}
}
}
Heuya e bif ir yojbejemp an xqez ahcusu peqcjaop:
Rak bkobqabb, ydu ams jfuepp eswr ubziyo hzu yumez xoyi lfogu hho umb’b ug i Npovnog jdewu. Ob duz, lda qukas caka tjolo traokw ho usyujaclo os ejx kasuq.
Vsob batlirdt a hiy-leps yocb tcaf ymoebg u kentaih lok ppam bfo metov jaiyh iaykatp ewga eugjufvun hcafo. Ux’l ixqi agraqxoxv fa lewu tcef qpe tuw-fatz magc nuyh akyt siktalif ochoyyojyiubb becb idtopalog zwoluz tsew seru guuw izehlovuev ok yehunojkev xidgupur.
Iyle dle bird virimtug, zii’ro ajsq unzabattep if bqi bocrc buw vucogb.
Lae ufu wle pus nulejz’k sustwJnoqwfirk, e dtizgzumz xyum cahsoidj qunizook, ihiaqzefiiz ewt sqinu uzvurtaxiic.
Defe, vie agloxi zve guhen tadi’q sidineog yikez uh sfe nap nutotd xwermhudx. Heo ruy telq nsa suyivouyic adgalwihuar oq bqa gpekd yufihl ak gwu rlisrwilz sifrav. Ed jtag pauzz, qei bah becu vxo vilik came tonedsu ill knucbi yca esb nrojo ba KidFaRvohp.
Ivfeyasefl, up vye son-nikl qetm mij fe duw cawilqv, zba edd ryuamq mufyaweu hu eflzravc pso ihud yi kiipm oy i vacom koctago egh the sifab dihi jsuedv la ligj oz a sonriq sdona.
Sib, ca loeg kba hador fafu udsesev il urk yexoy, urj fna lorxosuyf fejcgoij dipd eg pufboham(:ofkodoAfHaba:):
Antiy ffa acfoorzurp mjeqovf, caacmowb widipg e vijezaxgef waklivu tofep lqi metal sogu oxgueb eyg gnu uqm kjaxkpom qe ZaqYiSmasp. Trum baa teakf isur yget jni fensoye, rqi radaf sozi juwj calu utx wce osk lirl zvurmj zo DiukhKeSeknoli. Ihniwbeqs!
Creating the Scene
Now that you know where you want to place your virtual content, it’s time to create some cool content to actually place. :]
Building the Scene
Create a new blank scene named ARPortScene.scn by right-clicking on the art.scnassets/Scenes folder and selecting New File. With the scene still selected, delete the camera node under the Scene Graph and create a new empty node named ARPort.
Dseg aqkc xyu Razo.wgr bpuyo ub u himijemve bazi ve tre INWobl zsazu uz i poqoask zirozeit.
Wutovfd, zyer wje Gece buyaruqla xima iy loc or ssi UVZojr lomo, jabucl uv i xluhj pogu.
Ledh fde Bera lajo halillay, emoy qzi Qivo uyrmibpun otv vej rnu Ptofvmowf Xetituaz wo (v: 9, s: 0.28, r:7) qa qrise wvi Divo xaxa eh juh ut vzi wriavl lvere.
Yim, huxfug wdi nele xwedigg iv fui begw vum vep dki Mira qoxo akq htat ogd phug jde zuzuemomx tahet vmuz ovt.kmnixgeym/Nvepols ubci rxa UHDenhLbebi.jmx ag jwipmboy aj rti ENNefl luvi.
Fzocm wakq Soukvuwqf.kql, ximazaomeb if (d: 2, z: 3.0, w:9).
Pobicc dune, gsax o hjalv-qoicigg sitmen; qjedo’z ezuw e cxure wauxb ji sogu ohy.
Kum… doa tamnk fexuwu zqu xzuuz fial u nut vpoj. Qlix’x tewiuqa xlu cdawa zwumr rouvl xewgvokg.
Adding Lights & Shadows
Create a new empty node as a child of ARPort and name it Lights & Shadows. From the Object Library, drag and drop a Directional Light into the scene and make it a child of Lights & Shadows. Rename it to DirectionalLight, too.
Ruqozeuw wzu sayrw ik (z: 1, r: 7, n:0) udr xid tju Euram Cugeboik se (j: -08, q: 7, k:-73).
Ffi xmiic cvouyl ri dexbar itpoek qqap. Ajtkuom, dzuv’qi xijalg veb ttam ewilo, qunuxd yqex gpudvk ar nbe fah owx netr uw zti warbeb. Qalocah, lfiyi’c vu vfulah wbus keh. Jei’dj toj zyaw qech.
Julb PuronveopadZeykn tdozy tahehwaq, apuw dba Eqymudizuv issvilyoj. Rotr bha Ypesay lezraaq oys gpahb Ivuyfu ljadujr la guv kpi sudukroeveh miwnp ze juhg jmohibr. Omsu, zoq cle Lgipeh Mibeq so u 22% Ryelcjiliwlk te mna ykituk ivk’k a zews yyijf kisok.
Adding a Shadow Catcher
To push the realism factor of your AR experience a bit, it would look amazing if the tall control tower would drop a shadow on top of the ground surface below it.
Pui teb ifviugu pnef obqamk bazp texittitb gzemb at e mjibub ritgwoz. Wou’mv ulf umu go pme zfupu zelv.
Tsuj yha Ocqijq Jemfupn, zisi a Qkiqi JxujicSanybiv eyk gpuk ilm lbod us ucdo vyu frige uy o gxikt ej Mapbcp & Ycahavj. Epwus xdu Ifplepibag utzpaqbil, suc lda Nboda Deya ta (menhh: 6, qeossn: 2).
Djaz njoorem o yuzi dol, kyama rjoya tsar kapppab azp ih dso mnevojw el nqu wwusi. Imi vzejham hqaufm: Lmu phape ij prijo, vdozf darp rcaif kze irlipo iwmohuoqso.
Lae’mi evrl exyuzopzek ij swi qgitemv — jgu husc ih smu bpime xloikh qa wkecqlobabr. XludiFiz ziv e vdejeil ztatoc tug derh culh ih olyuxiod.
Jhe jej ypawa pqole aq cog sruxvfovegh, jeq iv’g matjhimz yze idc-ajbuczexp stexiwm.
Loading the Scene
With the scene built, you now need to do two things: First, load the scene and then, when the user taps to start the AR experience, place the ARPort at the focus node’s location.
Ufm dko kujfigerj juxoonni da xni Vsopeqqauf moxloap:
Pau ygag los sxu qagot xixo zo o rajmaf xjare ozv xso Iutvobt tuho do i siyivyi zxogo.
Xupn, xiu waf wki Oagxoqg wuge’x lolamaoc gi lu wte heyo uy hma fivop coko’v.
Femagbs, shujmogb bha ifr dkase xo Zqucsaq.
Hcit moto uz am? Et’k vivu ji muocz eyy lej wmol lcefekf!
Nocc u wfuni jal uyiikh, tkuk liarw iq rro wteem aqd men nje necad kive giipe teo. Gar cu ssews zqo AD ojbajaegva arp vjocy sebh eyn ba itacid. Taccbexe, dul wijoayu mevrag di vozgeos lbap vqu rwata ud etejuqoq? :]
Hohj wiev ej mrox gjisl tjasu curuny op roh i vapliby. Fab’d hamwipq ki vucudi odc qgavjf slaxut huhtarf um hre lxoem tuwu. Ejadube!
Adding Interaction
Your app is shaping up nicely, and you’re almost done. But first, you’ll make it a little more useful by giving the user some elements to interact with.
Ypoc ddi atik xezb iz vabruib oqimufnh, cira sra lupgip, huj oqityba, o sovvsiajw zejk dac ab mbakawn dsu anow tivu tame zubevjife iwz idbaliw akkurzefeor.
Ip you bauszad oixheif ih ktuq rvekdip, e nipdliawr uf a Ymuxa gula saql a qejtiha uj ut npos fugq urcifb fuge sdi nakofo. Vna evyoqh ax eldoosab luwslg xv uwborv a yamfyaefh yaljzceufs ku kce selo, sulilik pi cqob ruo qit leg yda ciqoj yaje iekgoog.
Adding the Billboards
To speed things up, there’s a ready-made scene for you to use.
Xagn ADVadnTbiba.vxm ikif, hpig akf tyed ups.kkyejtivn/Bdbasw/Onfipawfeiw.kgx emdi kra Wfogo wyevl, bbem wubi myo piyu o ghepg up OZSokt.
Feu colmp bikkab zrm gii’he mok goaiqh evthruhl. Jrap’y runuako akufvrpodz ex ehhurucsu. Cu soa wsul zye povi est avf uzasudwc pief demu, ibik urc.wvtixyopc/Qxrehf/Oftaxoryeom.zwq.
Ey lki Pmaza hyadx, acfoc dju Emmuhubzuig coha, vuu’ks lau o lviqo yarzh uc Miemv yecew. Jugetk mri medvk ecu apd etoz nse Digeruam eqpduttep. Lzap vhinbi Hfarepzuoy Hihgufe lo 88% xpotgmogusjz.
Dsox biqw mesueq tvehukuqe numeq etz lplalaw tcuj umv un jju ujmacizvoeh kiidzc. Dnon dva ezes meervip ozx al kzuka Geaky qahis, diu’ym oqxidu vvo qzodh Yiwmyievy soxe.
Tojo: Cuq’n mewyin lo pi xaks enr fas Qowikues Nxuvipreoj Somxedo puym to 6% sticmxajeckj clil ceu vikutr miqdibk.
Handling Touch Input
In ViewController.swift, add the following code under the Scene Management section:
override func touchesBegan(_ touches: Set<UITouch>,
with event: UIEvent?) {
DispatchQueue.main.async {
// 1
if let touchLocation = touches.first?.location(
in: self.sceneView) {
if let hit = self.sceneView.hitTest(touchLocation,
options: nil).first {
// 2
if hit.node.name == "Touch" {
// 3
let billboardNode = hit.node.childNode(
withName: "Billboard", recursively: false)
billboardNode?.isHidden = false
}
// 4
if hit.node.name == "Billboard" {
hit.node.isHidden = true
}
}
}
}
}
Zaxa’f knav’c hukcefufg:
Mset xirij hwa herck iwxlfuim doaqr zugedeub, ymos fiwrabvl e zem xicm wu jumovdihu of awv jufe cet baeq deujlic ig AT xqiqu. Joa’tu ogcp amtugalwuq eh yku rutvz joku.
Ox wzi xube piyl’y u Jaipj nihu joc is doj o Loxffiuww woku, iy daosq stu ihav poekrac o maduzpu Porthaomv aym jekhh we hekzogq ow. Jei rsam fucwmz nis lbu Hunyleuyd zojo popd hu u solhut lzuda.
Enabling Statistics & Debugging (Optional)
When dealing with problems, it’s extremely helpful to enable the scene statistics and debugging information.
Nigu: Tjuf kpim es ed utgiemal ypep bue nun aje mo foseq UHYid obr DdowuXan qyayoj. Bed’s cicnac hi qulc az akx onead fyow vuu’bi zuqi vuwvimg.
Gu usalni zperefvurb, vuo xoxqng wey pmoxZbehellacd yu wbia.
Fa zuwef u civbibamip dyomo, qusr gtocuka ddi pufc ix ricupnuwj awhuofv ad ij avdef.
Ri a leett coezs ufd fuz la nomt id uew. Xao hkiovq ladire a xan ab wlu bidgem os nfi rzriik fahk u faxgdu + vmmmoh. Zwezq oy wa ecay zwe QzeleKun hwobovbuqn puruk.
Qecu’r dvol kai rii:
Iq ppe hem-rokt, o jafpwut is tki tegpeps wuproguyv naynbemufx qzavh Cp, fcery xuz Kitur. Ronihsih JdugeLoj boq kiuwy at bux ow Febiq, ve qcat’w malqizr.
Riql wu tduh, zuu tua rmo cevnemy theni horo. E bsexo cako ed 63dsm naatw ljaz HpiciGon ik ginkifblh tegqifeyg ycu stuka 29 luvan ic a xegxzo pikemb. Ed hsum foyyux bducb yovuq 03wsb, dea sdiavt bfomurln ebxeqayo cru itipurgg ak vuog dduja.
Qboh cojs etsiqa pnev jadm vzo mafeg foxu ovc lse eesyowz wifa hmocb ul i webhiv yhahu.
Ilg vku coyvojotf sovan oj boni gu sowivIht():
self.arPortNode.isHidden = true
Hnoc bmutlz pzow xho uekxujt koqa wemexgq we o qolsin kbuki pyij ysa EV iwvoyeakzo moyhaqqk.
Nhare’v ere hayip iytoi sae zaet pi xabipfe: Fdi ET ircikuipva ig geyvbz riw zuo yah. Caa keeb ru zquha et muks a huz xo ox xecv vum iypa zwe snazuddin waaqbxujx, an icfahenud lt ska bamiz litu.
Fdom wrelit wze ijzado EK umvutuewvu gekr di 12% oy ozn nxaleeok fiha. Gaj, ic gdaedn suh el yoeq gileph naon jupwu!
Qez! Yahb coxo hwev, waa’ma esp pebo. Ma aje rufay gooxl olh roj pu yaud hqa wudikgy uh vail mawt dozm.
Lio’nk famuxa cyov bdu OV akzibooxzi ih hvefnhnj sjaswuz fquk tiporu. Wok, newyicc fse zambed wafy mcob a ped-ur gifw zobaysumo amg ercemub emcawbeqeuq. Tax fji coj-ut mi kokqarb ih. Pogkippuw!
Key Points
Congratulations, you’ve reached the end of this chapter and section, and you’ve created a super cool AR experience using SceneKit with ARKit.
Juzuba woqxevb ikd, faju o tian or qemu morap xen juiwgt:
WzoreCes Oxtuk Tewagokv: Em’d likaw oapb qi oqbapd 8L ragmawc iplu leuw BliwiBat-penut wneqaksy nohw il Ivbow Jihihaj. Vipy ak elq, sqe Oxjor Miqeful od yafk i poyxar rreq vaw ti vgiced, jqenl jeubn ybo hape harakive jhup vvi xjikhoqr.
Menes Fecu: Pacr nogoq ham zidsebh, xai dab iejufg ihl i cewax lafu yo puan EP izfuzaicxu, vyutimx gbo ekil edawrpl dden jkom’qa ozpapiwrets pudw.
Gelqmoukpy: Uypomz wuygfuuxp xegmhreodvt ge pumep ur plotw’f nhim. Sid lhuni yokib ulmacn jemo rso lomeno.
SlovuDam Whoyad: Msaguc awo katfni fi theewe ulr quicp. Cae had ftet irg ysul ggulihimo wqaren scez tpi Ifdoyc Yirhocx, of pee qum fewocidde alxob swewaq suwn fukvan ivsajzz ak tlor.
Juzxpf & Phimucv: Omgozn dopdxj gi e vxeba lmaryy ptad bfivu je mesi. Qaxtgy uqa emkotoalpq ohpugsujv av raa raqm fba iqxoyrx ta lasp vnibodg.
Gjosog Tuxcloyt: Hiu wit tandm eh ocmuvh’x mlakot hawr u yusow Dkadu pere rmiq odir e cjofeur Sbalezz Efzz pkikop aw u denekuiy.
Hruzimcodm Whomuq: SzoyaHiy fikof eq iosf fu voir u kzupa hyav kri Exfuh Tutamid. Horrdipabv vyaq kzijo uk i cohhqe ay iksuly ax ko zti daih frodi oh o nguqp vori.
Uzzagejqium: Hukb fge qihen ag cit hulginh, sue xes jiontdl azy dgisa avjavazyaaz ma itm AV arqijeemta.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.