Uploaded by Jorge Gutierrez

ARKit by Tutorials v2.0 Handout

advertisement
ARKit by Tutorials
Table of Contents: Overview
About This Book Sample ........................................................ 5
What You Need ....................................................................... 12
Book License ............................................................................ 13
Book Source Code & Forums ............................................. 14
About the Cover ..................................................................... 15
Chapter 7: Building a Portal ............................................... 16
Chapter 8: Adding Objects to Your World ................... 28
Chapter 9: Geometry, Textures & Lighting................... 44
Where to Go From Here? .................................................... 64
raywenderlich.com
2
ARKit by Tutorials
Table of Contents: Extended
About This Book Sample ........................................................ 5
About the Authors ............................................................................................................... 9
About the Editors............................................................................................................... 10
About the Artist.................................................................................................................. 11
What You Need ....................................................................... 12
Book License ............................................................................ 13
Book Source Code & Forums ............................................. 14
About the Cover ..................................................................... 15
Chapter 7: Building a Portal ............................................... 16
The portal app ..................................................................................................................... 16
Getting started ................................................................................................................... 17
Setting up ARKit ................................................................................................................. 18
Plane detection and rendering ..................................................................................... 21
Where to go from here? .................................................................................................. 27
Chapter 8: Adding Objects to Your World ................... 28
Getting started ................................................................................................................... 28
Hit testing ............................................................................................................................. 33
Adding crosshairs .............................................................................................................. 34
Adding a state machine ................................................................................................... 39
Where to go from here? .................................................................................................. 43
Chapter 9: Geometry, Textures & Lighting................... 44
Getting started ................................................................................................................... 44
Building the portal ............................................................................................................. 46
Adding the doorway ......................................................................................................... 58
Placing lights ........................................................................................................................ 61
Where to go from here? .................................................................................................. 63
raywenderlich.com
3
ARKit by Tutorials
Where to Go From Here? .................................................... 64
raywenderlich.com
4
A
About This Book Sample
ARKit is Apple’s mobile AR development framework. With it, you can create an
immersive, engaging experience, mixing virtual 2D and 3D content with the live camera
feed of the world around you. You may be surprised to learn that, at this very moment,
millions of Apple users already have a sophisticated AR device right in their pockets!
We are pleased to offer you this sample from the full ARKit by Tutorials book. The three
chapters that follow will take you through building a complete app: You'll implement a
sci-fi portal right before your eyes and learn some important AR concepts along the
way.
The three chapters include:
• Chapter 7: Building a Portal: In this chapter, you’ll explore an app to review the
basics of ARKit development. You’ll set up an ARSession and add plane detection and
other functions so that the app can render horizontal planes using the
ARSCNViewDelegate protocol.
• Chapter 8: Adding Objects to Your World: Over the course of building your portal,
you’ll learn how to handle ARSession interruptions elegantly when your app goes to
the background. You’ll then explore how hit-testing with an ARSCNView works as you
start adding objects to the detected horizontal plane in the device’s surroundings.
For adding virtual objects, you’ll use ARAnchors and SCNNode objects to define their
position and geometry.
• Chapter 9: Geometry, Textures & Lighting: In the final chapter of this section,
you’ll first dive deeper to understand SceneKit’s coordinate system and materials.
Next, you’ll use SCNNode objects with different geometries and attach textures to
them to create the walls, floor and ceiling of your portal. Finally, you’ll make your
portal appear realistic by adding lighting.
raywenderlich.com
5
ARKit by Tutorials
About This Book Sample
We hope this hands-on look inside the book will give you a good idea of what's to come
in the full version and show you why this book is a must-have for any app developer.
In the full version of this book, you’ll create five immersive and engaging apps: a
tabletop poker dice game, an immersive sci-fi portal, a 3D face-tracking mask app, a
location-based AR ad network, and monster truck simulation with realistic vehicle
physics.
The full book is now available for purchase:
• www.store.raywenderlich.com/products/arkit-by-tutorials.
Enjoy!
The ARKit by Tutorials team
raywenderlich.com
6
ARKit by Tutorials
About This Book Sample
ARKit by Tutorials
By Chris Language, Namrata Bandekar, Antonio Bello & Tammy Coron
Copyright ©2018 Razeware LLC.
Notice of Rights
All rights reserved. No part of this book or corresponding materials (such as text,
images, or source code) may be reproduced or distributed by any means without prior
written permission of the copyright owner.
Notice of Liability
This book and all corresponding materials (such as source code) are provided on an “as
is” basis, without warranty of any kind, express of implied, including but not limited to
the warranties of merchantability, fitness for a particular purpose, and
noninfringement. In no event shall the authors or copyright holders be liable for any
claim, damages or other liability, whether in action of contract, tort or otherwise,
arising from, out of or in connection with the software or the use of other dealing in the
software.
Trademarks
All trademarks and registered trademarks appearing in this book are the property of
their own respective owners.
raywenderlich.com
7
ARKit by Tutorials
About This Book Sample
Dedications
"To my wife Corné and my daughter Marizé. Thank you for your
patience, support, belief, and most of all, your love. Everything I do, I
do for you."
— Chris Language
"To my parents and my husband, for supporting me and to Ginger,
my puppy, for all the smiles. :)"
— Namrata Bandekar
"For my evil cat, Jetsam."
— Tammy Coron
raywenderlich.com
8
ARKit by Tutorials
About This Book Sample
About the Authors
Chris Language is a seasoned coder with 20+ years of experience,
and the author of 3D Apple Games by Tutorials. He has fond
memories of his childhood and his Commodore 64; more recently he
started adding more good memories of life with all his Apple devices.
By day, he fights for survival in the corporate jungle of Johannesburg,
South Africa. By night he fights demons, dragons and zombies! For
relaxation, he codes. You can find him on Twitter @ChrisLanguage
Forever Coder, Artist, Musician, Gamer and Dreamer.
Namrata Bandekar is an author of this book. Namrata is a Principal
Software Engineer at Zynga building addictive games. She is also a
member of the Ray Wenderlich Tutorial Team. She is the co-author of
ARKit by Tutorials and one of the Tech Editors on the Android
Apprentice book. Apart from building apps, she is passionate about
travelling, scuba diving and hiking with her dog.Say hi to Namrata on
Twitter: @NamrataCodes
Antonio Bello is an author of this book. Antonio has spent most of
his life writing code, and he’s gained a lot of experience in several
languages and technologies. A few years ago he fell in love with iOS
development, and that’s what he mostly works on since then,
although he’s always open for challenges and for playing with new
toys. He believes that reputation is the most important skill in his job,
and that “it cannot be done” actually means “it can be done, but it’s
not economically convenient." When he’s not working, he’s probably
playing drums or making songs in his small, but well fitted, home
recording studio.
Tammy Coron is an independent creative professional and the host
of Roundabout: Creative Chaos. She’s also the founder of Just Write
Code. Find out more at tammycoron.com.
raywenderlich.com
9
ARKit by Tutorials
About This Book Sample
About the Editors
Jerry Beers is a tech editor of this book. Jerry is co-founder of Five
Pack Creative, a mobile development company specializing in iOS
development. He is passionate about creating well-crafted code and
teaching others. You can find him on Twitter @jerrybeers or his
company's site fivepackcreative.com.
Joey deVilla is a tech editor on this book. Joey is a developer turned
accordionist turned tech evangelist turned developer cat-herder. A
Canadian turned Tampanian, he works at Sourcetoad, blogs at
globalnerdy.com and joeydevilla.com, and does what he can to avoid
becoming a “Florida Man” news story.
Morten Faarkrog is a tech editor on this book. Morten is an app
developer from Denmark who works at the digital agency Adapt.
When not developing apps he enjoys reading, travelling, and running.
To connect with Morten you can find him on LinkedIn.
Matthew Morey is a tech editor on this book. Matt is an engineer,
author, hacker, creator and tinkerer. As an active member of the iOS
community and CTO at MJD Interactive he has led numerous
successful mobile projects worldwide. When not developing apps he
enjoys traveling, snowboarding, and surfing. He blogs about
technology and business at matthewmorey.com.
Wendy Lincoln is an editor of this book. She is driven by an
insatiable curiosity about technology, and as a result she manages
technical projects, does technical editing, and squanders her spare
time learning about tech. When she’s not geeking out, you’ll find her
in the waves or doing home-improvement projects with her husband.
Chris Belanger is the editor of this book. Chris is the Editor in Chief
at raywenderlich.com, and was a developer for nearly 20 years in
various fields from e-health to aerial surveillance to industrial
controls. If there are words to wrangle or a paragraph to ponder, he’s
on the case. When he kicks back, you can usually find Chris with
guitar in hand, looking for the nearest beach. Twitter: @crispytwit.
raywenderlich.com
10
ARKit by Tutorials
About This Book Sample
About the Artist
Vicki Wenderlich is the designer and artist of the cover of this book.
She is Ray’s wife and business partner. She is a digital artist who
creates illustrations, game art and a lot of other art or design work for
the tutorials and books on raywenderlich.com. When she’s not
making art, she loves hiking, a good glass of wine and attempting to
create the perfect cheese plate.
raywenderlich.com
11
W
What You Need
To follow along with this book, you'll need the following:
• A Mac running macOS 10.13.4, at a minimum, with the latest point release and
security patches installed. This is so you can install the latest version of the required
development tool: Xcode.
• Xcode 10 or later. Xcode is the main development tool for writing code in Swift. You
need Xcode 10 at a minimum, since that version supports iOS 12.0 and ARKit 2.0,
which is what we use in the book. You can download the latest version of Xcode for
free from the Mac App Store, here: apple.co/1FLn51R.
If you haven't installed the latest version of Xcode, be sure to do that before continuing
with the book. The code covered in this book depends on Swift 4.2 and Xcode 10 — you
may get lost if you try to work with an older version.
raywenderlich.com
12
L
Book License
By purchasing ARKit by Tutorials, you have the following license:
• You are allowed to use and/or modify the source code in ARKit by Tutorials in as
many apps as you want, with no attribution required.
• You are allowed to use and/or modify all art, images and designs that are included in
ARKit by Tutorials in as many apps as you want, but must include this attribution line
somewhere inside your app: “Artwork/images/designs: from ARKit by Tutorials,
available at www.raywenderlich.com”.
• The source code included in ARKit by Tutorials is for your personal use only. You are
NOT allowed to distribute or sell the source code in ARKit by Tutorials without prior
authorization.
• This book is for your personal use only. You are NOT allowed to sell this book
without prior authorization, or distribute it to friends, coworkers or students; they
would need to purchase their own copies.
All materials provided with this book are provided on an “as is” basis, without warranty
of any kind, express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose and noninfringement. In no event shall
the authors or copyright holders be liable for any claim, damages or other liability,
whether in an action of contract, tort or otherwise, arising from, out of or in connection
with the software or the use or other dealings in the software.
All trademarks and registered trademarks appearing in this guide are the properties of
their respective owners.
raywenderlich.com
13
B
Book Source Code &
Forums
This book comes with the source code for the starter and completed projects for each
chapter. These resources are shipped with the digital edition you downloaded from
store.raywenderlich.com.
We’ve also set up an official forum for the book at forums.raywenderlich.com. This is a
great place to ask questions about the book or to submit any errors you may find.
raywenderlich.com
14
A
About the Cover
Plesiosaurs were ancient marine reptiles; there are records of Plesiosaur fossils being
studied as far back as the 1600’s, which makes them one of the first orders of extinct
reptiles to be recognized as such. By the mid 1800’s, researchers had a pretty good idea
of what Plesiosaurs looked like and how they behaved. But a string of recent discoveries
of new types of Plesiosaurs have helped scientists clarify how they looked, how they
evolved, and even how they hunted prey.
Just as paleontologists bring the past alive through their discoveries, ARKit brings
things real or imagined into reality through your smartphone. Whether you’re bringing
dinosaurs to life in your dining room, creating portals to play in, or simply want to play
Pac-Man on your city streets, ARKit can help make sure your great idea for an AR app
will never become extinct!
raywenderlich.com
15
7
Chapter 7: Building a Portal
By Namrata Bandekar
In this sample chapter, you’ll implement a portal app using ARKit and SceneKit. Portal
apps can be used for educational purposes, like a virtual tour of the solar system from
space, or for more leisurely activities, like enjoying a virtual beach vacation.
The portal app
The portal app you’ll build lets you place a virtual doorway to a futuristic room,
somewhere on a horizontal plane in the real world. You can walk in and out of this
virtual room, and you can explore what’s inside.
In this chapter, you’ll set up the basics for your portal app. By the end of the chapter,
you’ll know how to:
• Set up an ARSession
• Detect and render horizontal planes using ARKit
Are you ready to build a gateway into another world? Perfect!
raywenderlich.com
16
ARKit by Tutorials
Chapter 7: Building a Portal
Getting started
In Xcode, open the starter project, Portal.xcodeproj. Build and run the project, and
you’ll see a blank white screen.
Ah, yes, the blank canvas of opportunity!
Open Main.storyboard and expand the Portal View Controller Scene.
raywenderlich.com
17
ARKit by Tutorials
Chapter 7: Building a Portal
The PortalViewController is presented to the user when the app is launched. The
PortalViewController contains an ARSCNView that displays the camera preview. It also
contains two UILabels that provide instructions and feedback to the user.
Now, open PortalViewController.swift. In this file, you’ll see the following variables,
which represent the elements in the storyboard:
// 1
@IBOutlet var sceneView: ARSCNView?
// 2
@IBOutlet weak var messageLabel: UILabel?
// 3
@IBOutlet weak var sessionStateLabel: UILabel?
Let’s take a look at what each one does:
1. sceneView is used to augment the camera view with 3D SceneKit objects.
2. messageLabel, which is a UILabel, will display instructional messages to the user.
For example, telling them how to interact with your app.
3. sessionStateLabel, another UILabel, will inform the user about session
interruptions, such as when the app goes into the background or if the ambient
lighting is insufficient.
Note: ARKit processes all of the sensor and camera data, but it doesn’t render any
of the virtual content. To render content in your scenes, there are various
renderers you can use alongside ARKit, such as SceneKit or SpriteKit.
ARSCNView is a framework provided by Apple which you can use to integrate ARKit
data with SceneKit easily. There are many benefits to using ARSCNView, which is
why you’ll use it in this chapter’s project.
In the starter project, you’ll also find a few utility classes in the Helpers group. You’ll
be using these as you develop the app further.
Setting up ARKit
As you learned earlier in the book, the first step to setting things up is to capture the
device’s video stream using the camera. For that, you’ll be using an ARSCNView object.
raywenderlich.com
18
ARKit by Tutorials
Chapter 7: Building a Portal
Open PortalViewController.swift and add the following method:
func runSession() {
// 1
let configuration = ARWorldTrackingConfiguration.init()
// 2
configuration.planeDetection = .horizontal
// 3
configuration.isLightEstimationEnabled = true
// 4
sceneView?.session.run(configuration)
}
// 5
#if DEBUG
sceneView?.debugOptions = [ARSCNDebugOptions.showFeaturePoints]
#endif
Let’s take a look at what’s happening with this code:
1. You first instantiate an ARWorldTrackingConfiguration object. This defines the
configuration for your ARSession. There are two types of configurations available for
an ARSession: ARSessionConfiguration and ARWorldTrackingConfiguration.
Using ARSessionConfiguration is not recommended because it only accounts for
the rotation of the device, not its position. For devices that use an A9 processor,
ARWorldTrackingSessionConfiguration gives the best results, as it tracks all
degrees of movement of the device.
2. configuration.planeDetection is set to detect horizontal planes. The extent of the
plane can change, and multiple planes can merge into one as the camera moves. It
can find planes on any horizontal surface such as a floor, table or couch.
3. This enables light estimation calculations, which can be used by the rendering
framework to make the virtual content look more realistic.
4. Start the session’s AR processing with the specified session configuration. This will
start the ARKit session and video capturing from the camera, which is displayed in
the sceneView.
5. For debug builds, this adds visible feature points; these are overlaid on the camera
view.
Now it’s time to set up the defaults for the labels. Replace resetLabels() with the
following:
func resetLabels() {
messageLabel?.alpha = 1.0
messageLabel?.text =
raywenderlich.com
19
ARKit by Tutorials
}
Chapter 7: Building a Portal
"Move the phone around and allow the app to find a plane." +
"You will see a yellow horizontal plane."
sessionStateLabel?.alpha = 0.0
sessionStateLabel?.text = ""
This resets the opacity and text of messageLabel and sessionStateLabel. Remember,
messageLabel is used to display instructions to the user, while sessionStateLabel is
used to display any error messages, in the case something goes wrong.
Now, add runSession() to viewDidLoad() of PortalViewController:
override func viewDidLoad() {
super.viewDidLoad()
resetLabels()
runSession()
}
This will run the ARKit session when the app launches and loads the view.
Next, build and run the app. Don’t forget — you’ll need to grant camera permissions to
the app.
ARSCNView does the heavy lifting of displaying the camera video capture. Because you’re
in debug mode, you can also see the rendered feature points, which form a point cloud
showing the intermediate results of scene analysis.
raywenderlich.com
20
ARKit by Tutorials
Chapter 7: Building a Portal
Plane detection and rendering
Previously, in runSession(), you set planeDetection to .horizontal, which means your
app can detect horizontal planes. You can obtain the captured plane information in the
delegate callback methods of the ARSCNViewDelegate protocol.
Start by extending PortalViewController so it implements the ARSCNViewDelegate
protocol:
extension PortalViewController: ARSCNViewDelegate {
}
Add the following line to the very end of runSession():
sceneView?.delegate = self
This sets the ARSCNViewDelegate delegate property of the sceneView as the
PortalViewController.
ARPlaneAnchors are added automatically to the ARSession anchors array, and ARSCNView
automatically converts ARPlaneAnchor objects to SCNNode nodes.
Now, to render the planes, all you need to do is implement the delegate method in the
ARSCNViewDelegate extension of PortalViewController:
// 1
func renderer(_ renderer: SCNSceneRenderer,
didAdd node: SCNNode,
for anchor: ARAnchor) {
// 2
DispatchQueue.main.async {
// 3
if let planeAnchor = anchor as? ARPlaneAnchor {
// 4
#if DEBUG
// 5
let debugPlaneNode = createPlaneNode(
center: planeAnchor.center,
extent: planeAnchor.extent)
// 6
node.addChildNode(debugPlaneNode)
#endif
// 7
self.messageLabel?.text =
"Tap on the detected horizontal plane to place the portal"
}
}
}
raywenderlich.com
21
ARKit by Tutorials
Chapter 7: Building a Portal
Here’s what’s happening:
1. The delegate method, renderer(_:didAdd:for:), is called when ARSession detects a
new plane, and the ARSCNView automatically adds an ARPlaneAnchor for the plane.
2. The callbacks occur on a background thread. Here, you dispatch the block to the
main queue because any operations updating the UI should be done on the main UI
thread.
3. This checks if the ARAnchor that was added is an ARPlaneAnchor.
4. This checks to see if you’re in debug mode.
5. If so, create the plane SCNNode object by passing in the center and extent
coordinates of the planeAnchor detected by ARKit. The createPlaneNode() is a
helper method which you’ll implement shortly.
6. The node object is an empty SCNNode that’s automatically added to the scene by
ARSCNView; its coordinates correspond to the ARAnchor’s position. Here, you add the
debugPlaneNode as a child node, so that it gets placed in the same position as the
node.
7. Finally, regardless of whether or not you’re in debug mode, you update the
instructional message to the user to indicate that the app is now ready to place the
portal into the scene.
Now it’s time to set up the helper methods.
Create a new Swift file named SCNNodeHelpers.swift in the Helpers group. This file
will contain all of the utility methods related to rendering SCNNode objects.
Import SceneKit into this file by adding the following line:
import SceneKit
Now, add the following helper method:
// 1
func createPlaneNode(center: vector_float3,
extent: vector_float3) -> SCNNode {
// 2
let plane = SCNPlane(width: CGFloat(extent.x),
height: CGFloat(extent.z))
// 3
let planeMaterial = SCNMaterial()
planeMaterial.diffuse.contents = UIColor.yellow.withAlphaComponent(0.4)
// 4
plane.materials = [planeMaterial]
// 5
raywenderlich.com
22
ARKit by Tutorials
}
Chapter 7: Building a Portal
let planeNode = SCNNode(geometry: plane)
// 6
planeNode.position = SCNVector3Make(center.x, 0, center.z)
// 7
planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
// 8
return planeNode
Let’s go through this step-by-step:
1. The createPlaneNode method has two arguments: the center and extent of the
plane to be rendered, both of type vector_float3. This type denotes the coordinates
of the points. The function returns the SCNNode object created for the plane.
2. You instantiate the SCNPlane by specifying the width and height of the plane. You
get the width from the x coordinate of the extent and the height from its z
coordinate.
3. You initialize and assign the diffuse content for the SCNMaterial object. The diffuse
layer color is set to a translucent yellow.
4. The SCNMaterial object is then added to the materials array of the plane. This
defines the texture and color of the plane.
5. This creates an SCNNode with the geometry of the plane. The SCNPlane inherits from
the SCNGeometry class, which only provides the form of a visible object rendered by
SceneKit. You specify the position and orientation of the geometry by attaching it
to an SCNNode object. Multiple nodes can reference the same geometry object,
allowing it to appear at different positions in a scene.
6. You set the position of the planeNode. Note that the node is translated to
coordinates (center.x, 0, center.z) reported by ARKit via the ARPlaneAnchor
instance.
7. Planes in SceneKit are vertical by default, so you need to rotate the plane by 90
degrees to make it horizontal.
8. This returns the planeNode object created in the previous steps.
raywenderlich.com
23
ARKit by Tutorials
Chapter 7: Building a Portal
Build and run the app. If ARKit can detect a suitable surface in your camera view, you’ll
see a yellow horizontal plane.
Move the device around, and you’ll notice the app sometimes shows multiple planes. As
it finds more planes, it adds them to the view. Existing planes, however, do not update
or change size as ARKit analyzes more features in the scene.
raywenderlich.com
24
ARKit by Tutorials
Chapter 7: Building a Portal
ARKit constantly updates the plane’s position and extents based on new feature points
it finds. To receive these updates in your app, add the following
renderer(_:didUpdate:for:) delegate method to PortalViewController.swift:
// 1
func renderer(_ renderer: SCNSceneRenderer,
didUpdate node: SCNNode,
for anchor: ARAnchor) {
// 2
DispatchQueue.main.async {
// 3
if let planeAnchor = anchor as? ARPlaneAnchor,
node.childNodes.count > 0 {
// 4
updatePlaneNode(node.childNodes[0],
center: planeAnchor.center,
extent: planeAnchor.extent)
}
}
}
Here’s what’s happening:
1. renderer(_:didUpdate:for:) is called when the corresponding ARAnchor updates.
2. Operations that update the UI should be executed on the main UI thread.
3. Check that the ARAnchor is an ARPlaneAnchor and make sure it has at least one child
node that corresponds to the plane’s SCNNode.
4. updatePlaneNode(_:center:extent:) is a method that you’ll implement shortly. It
updates the coordinates and size of the plane to the updated values contained in
the ARPlaneAnchor.
Open SCNNodeHelpers.swift and add the following code:
func updatePlaneNode(_ node: SCNNode,
center: vector_float3,
extent: vector_float3) {
// 1
let geometry = node.geometry as? SCNPlane
// 2
geometry?.width = CGFloat(extent.x)
geometry?.height = CGFloat(extent.z)
// 3
node.position = SCNVector3Make(center.x, 0, center.z)
}
raywenderlich.com
25
ARKit by Tutorials
Chapter 7: Building a Portal
Going through this code step-by-step:
1. Check if the node has SCNPlane geometry.
2. Update the node geometry using the new values that are passed in. Use the extent
or size of the ARPlaneAnchor to update the width and height of the plane.
3. Update the position of the plane node with the new position.
Now that you can successfully update the position of the plane, build and run the app.
You’ll see that the plane’s size and position shifts as it detects new feature points.
There’s still one problem that needs to be solved. Once the app detects the plane, if you
exit the app and come back in, you’ll see that the previously detected plane is now on
top of other objects within the camera view; it no longer matches the plane surface it
previously detected.
To fix this, you need to remove the plane node whenever the ARSession is interrupted.
You’ll handle that in the next chapter.
raywenderlich.com
26
ARKit by Tutorials
Chapter 7: Building a Portal
Where to go from here?
You may not realize it, but you have come a long way in building your portal app! Sure,
there’s more to do, but you’re well on your way to traveling to another virtual
dimension.
Here’s a quick summary of what you did in this chapter:
• You explored the starter project and reviewed the basics of ARKit.
• You configured an ARSession so that it displays camera output within the app.
• You added plane detection and other functions so that the app can render horizontal
planes using the ARSCNViewDelegate protocol.
In the next chapter, you’ll learn how to handle session interruptions and place rendered
3D objects in the view using SceneKit.
raywenderlich.com
27
8
Chapter 8: Adding Objects
to Your World
By Namrata Bandekar
In the previous chapter, you learned how to set up your iOS app to use ARKit sessions
and detect horizontal planes. In this chapter, you’re going to build up your app and add
3D virtual content to the camera scene via SceneKit. By the end of this chapter, you’ll
know how to:
• Handle session interruptions
• Place objects on a detected horizontal plane
Before jumping in, load the starter project from the starter folder.
Getting started
Now that you can detect and render horizontal planes, you need to reset the state of the
session if there are any interruptions. ARSession is interrupted when the app moves
into the background or when multiple applications are in the foreground. Once
interrupted, the video capture will fail, and the ARSession will be unable to do any
tracking as it will no longer receive the required sensor data. When the app returns to
the foreground, the rendered plane will still be present in the view. However, if your
device has changed its position or rotation, the ARSession tracking will not work
anymore. This is when you need to restart the session.
The ARSCNViewDelegate implements the ARSessionObserver protocol. This protocol
contains the methods that are called when the ARSession detects interruptions or
session errors.
raywenderlich.com
28
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
Open PortalViewController.swift and add the following implementation for the
delegate methods to the existing extension.
// 1
func session(_ session: ARSession, didFailWithError error: Error) {
// 2
guard let label = self.sessionStateLabel else { return }
showMessage(error.localizedDescription, label: label, seconds: 3)
}
// 3
func sessionWasInterrupted(_ session: ARSession) {
guard let label = self.sessionStateLabel else { return }
showMessage("Session interrupted", label: label, seconds: 3)
}
// 4
func sessionInterruptionEnded(_ session: ARSession) {
// 5
guard let label = self.sessionStateLabel else { return }
showMessage("Session resumed", label: label, seconds: 3)
}
// 6
DispatchQueue.main.async {
self.removeAllNodes()
self.resetLabels()
}
// 7
runSession()
Let’s go over this step-by-step.
1. session(_:, didFailWithError:) is called when the session fails. On failure, the
session is paused, and it does not receive sensor data.
2. Here, you set the sessionStateLabel text to the error message that was reported as
a result of the session failure. showMessage(_:, label:, seconds:) shows the
message in the specified label for the given number of seconds.
3. The sessionWasInterrupted(_:) method is called when the video capture is
interrupted as a result of the app moving to the background. No additional frame
updates are delivered until the interruption ends. Here you display a "Session
interrupted" message in the label for 3 seconds.
4. The sessionInterruptionEnded(_:) method is called after the session interruption
has ended. A session will continue running from the last known state once the
interruption has ended. If the device has moved, any anchors will be misaligned. To
avoid this, you restart the session.
5. Show a "Session resumed" message on the screen for three seconds.
raywenderlich.com
29
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
6. Remove previously rendered objects and reset all labels. You will implement these
methods soon. These methods update the UI, so they need to be called on the main
thread.
7. Restart the session. runSession() resets the session configuration and restarts the
tracking with the new configuration.
You will notice there are some compiler errors. You’ll resolve these errors by
implementing the missing methods.
Place the following variable in PortalViewController below the other variables:
var debugPlanes: [SCNNode] = []
You’ll use debugPlanes, which is an array of SCNNode objects that keep track of all the
rendered horizontal planes in debug mode.
Then, place the following methods below resetLabels():
// 1
func showMessage(_ message: String, label: UILabel, seconds: Double) {
label.text = message
label.alpha = 1
}
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
if label.text == message {
label.text = ""
label.alpha = 0
}
}
// 2
func removeAllNodes() {
removeDebugPlanes()
}
// 3
func removeDebugPlanes() {
for debugPlaneNode in self.debugPlanes {
debugPlaneNode.removeFromParentNode()
}
}
self.debugPlanes = []
raywenderlich.com
30
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
Take a look at what’s happening:
1. You define a helper method to show a message string in a given UILabel for the
specified duration in seconds. Once the specified number of seconds pass, you reset
the visibility and text for the label.
2. removeAllNodes() removes all existing SCNNode objects added to the scene.
Currently, you only remove the rendered horizontal planes here.
3. This method removes all the rendered horizontal planes from the scene and resets
the debugPlanes array.
Now, place the following line in renderer(_:, didAdd:, for:) just before the #endif of
the #if DEBUG preprocessor directive:
self.debugPlanes.append(debugPlaneNode)
This adds the horizontal plane that was just added to the scene to the debugPlanes
array.
Note that in runSession(), the session executes with a given configuration:
sceneView?.session.run(configuration)
Replace the line above with the code below:
sceneView?.session.run(configuration,
options: [.resetTracking, .removeExistingAnchors])
Here you run the ARSession associated with your sceneView by passing the
configuration object and an array of ARSession.RunOptions, with the following run
options:
1. resetTracking:The session does not continue device position and motion tracking
from the previous configuration.
2. removeExistingAnchors: Any anchor objects associated with the session in its
previous configuration are removed.
raywenderlich.com
31
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
Run the app and try to detect a horizontal plane.
Now send the app to the background and then re-open the app. Notice that the
previously rendered horizontal plane is removed from the scene and the app resets the
label to display the correct instructions to the user.
raywenderlich.com
32
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
Hit testing
You are now ready to start placing objects on the detected horizontal planes. You will be
using ARSCNView’s hit testing to detect touches from the user’s finger on the screen to
see where they land in the virtual scene. A 2D point in the view’s coordinate space can
refer to any point along a line segment in the 3D coordinate space. Hit-testing is the
process of finding objects in the world located along this line segment.
Open PortalViewController.swift and add the following variable.
var viewCenter: CGPoint {
let viewBounds = view.bounds
return CGPoint(x: viewBounds.width / 2.0, y: viewBounds.height / 2.0)
}
In the above block of code, you set the variable viewCenter to the center of the
PortalViewController’s view.
Now add the following method:
// 1
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
// 2
if let hit = sceneView?.hitTest(viewCenter, types:
[.existingPlaneUsingExtent]).first {
// 3
sceneView?.session.add(anchor: ARAnchor.init(transform:
hit.worldTransform))
}
}
Here’s what’s happening:
1. ARSCNView has touches enabled. When the user taps on the view, touchesBegan() is
called with a set of UITouch objects and a UIEvent which defines the touch event.
You override this touch handling method to add an ARAnchor to the sceneView.
2. You call hitTest(_:, types:) on the sceneView object. The hitTest method has
two parameters. It takes a CGPoint in the view’s coordinate system, in this case, the
screen’s center, and the type of ARHitTestResult to search for.
Here, you use the existingPlaneUsingExtent result type, which searches for points
where the ray from the viewCenter intersects with any detected horizontal planes
while considering the limited extent of the planes.
The result of hitTest(_:, types:) is an array of all hit test results sorted from the
nearest to the farthest. You pick the first plane that the ray intersects. You will get
raywenderlich.com
33
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
results for hitTest(_:, types:) any time the screen’s center falls within the
rendered horizontal plane.
3. You add an ARAnchor to the ARSession at the point where your object will be placed.
The ARAnchor object is initialized with a transformation matrix that defines the
anchor’s rotation, translation and scale in world coordinates.
The ARSCNView receives a callback in the delegate method renderer(_:didAdd:for:)
after the anchor is added. This is where you handle rendering your portal.
Adding crosshairs
Before you add the portal to the scene, there is one last thing you need to add in the
view. In the previous section, you implemented detecting hit testing for sceneView with
the center of the device screen. In this section, you’ll work on adding a view to display
the screen’s center to help the user position the device.
Open Main.storyboard. Navigate to the Object Library by pressing ⇧+⌘+L or by
clicking on the Library button in the toolbar. Search for UIView and select the View
object.
raywenderlich.com
34
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
Drag and drop the view object onto the PortalViewController.
Change the name of the view to Crosshair. Add layout constraints to the view such that
its center matches its superview’s center. Add constraints to set the width and height of
the view to 10.
raywenderlich.com
35
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
In the Size Inspector tab, your constraints should look like this:
Navigate to the Attributes inspector tab and change the background color of the
Crosshair view to Light Gray Color.
Select the assistant editor and you’ll see PortalViewController.swift on the right.
raywenderlich.com
36
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
Press Ctrl and drag from the Crosshair view in storyboard to the PortalViewController
code, just above the declaration for sceneView.
Enter crosshair for the name of the IBOutlet and click Connect.
Build and run the app. Notice there’s a gray square view at the center of the screen. This
is the crosshair view that you just added.
raywenderlich.com
37
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
Now add the following code to the ARSCNViewDelegate extension of the
PortalViewController.
// 1
func renderer(_ renderer: SCNSceneRenderer,
updateAtTime time: TimeInterval) {
// 2
DispatchQueue.main.async {
// 3
if let _ = self.sceneView?.hitTest(self.viewCenter,
types: [.existingPlaneUsingExtent]).first {
self.crosshair.backgroundColor = UIColor.green
} else { // 4
self.crosshair.backgroundColor = UIColor.lightGray
}
}
}
Here’s what’s happening with the code you just added:
1. This method is part of the SCNSceneRendererDelegate protocol which is
implemented by the ARSCNViewDelegate. It contains callbacks which can be used to
perform operations at various times during the rendering. renderer(_:
updateAtTime:) is called exactly once per frame and should be used to perform any
per-frame logic.
2. You run the code to detect if the screen’s center falls in the existing detected
horizontal planes and update the UI accordingly on the main queue.
3. This performs a hit test on the sceneView with the viewCenter to determine if the
view center indeed intersects with a horizontal plane. If there’s at least one result
detected, the crosshair view’s background color is changed to green.
4. If the hit test does not return any results, the crosshair view’s background color is
reset to light gray.
Build and run the app.
Move the device around so that it detects and renders a horizontal plane, as shown on
the left. Now move the device such that the device screen’s center falls within the plane,
as shown on the right.
raywenderlich.com
38
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
Notice that the center view’s color changes to green.
Adding a state machine
Now that you have set up the app for detecting planes and placing an ARAnchor, you can
get started with adding the portal.
To track the state your app, add the following variables to PortalViewController:
var portalNode: SCNNode? = nil
var isPortalPlaced = false
You store the SCNNode object that represents your portal in portalNode and use
isPortalPlaced to keep track of whether the portal is rendered in the scene.
Add the following method to PortalViewController:
func makePortal() -> SCNNode {
// 1
let portal = SCNNode()
// 2
let box = SCNBox(width: 1.0,
height: 1.0,
raywenderlich.com
39
ARKit by Tutorials
}
Chapter 8: Adding Objects to Your World
length: 1.0,
chamferRadius: 0)
let boxNode = SCNNode(geometry: box)
// 3
portal.addChildNode(boxNode)
return portal
Here you define makePortal(), a method that will configure and render the portal. A few
things are happening here:
1. You create an SCNNode object which will represent your portal.
2. This initializes a SCNBox object which is a cube and makes a SCNNode object for the
box using the SCNBox geometry.
3. You add the boxNode as a child node to your portal and return the portal node.
Here, makePortal() is creating a portal node with a box object inside it as a placeholder.
Now replace the renderer(_:, didAdd:, for:) and renderer(_:, didUpdate:, for:)
methods for the SCNSceneRendererDelegate with the following:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for
anchor: ARAnchor) {
DispatchQueue.main.async {
// 1
if let planeAnchor = anchor as? ARPlaneAnchor,
!self.isPortalPlaced {
#if DEBUG
let debugPlaneNode = createPlaneNode(
center: planeAnchor.center,
extent: planeAnchor.extent)
node.addChildNode(debugPlaneNode)
self.debugPlanes.append(debugPlaneNode)
#endif
self.messageLabel?.alpha = 1.0
self.messageLabel?.text = """
Tap on the detected \
horizontal plane to place the portal
"""
}
else if !self.isPortalPlaced {// 2
// 3
self.portalNode = self.makePortal()
if let portal = self.portalNode {
// 4
node.addChildNode(portal)
self.isPortalPlaced = true
// 5
self.removeDebugPlanes()
self.sceneView?.debugOptions = []
raywenderlich.com
40
ARKit by Tutorials
}
}
}
Chapter 8: Adding Objects to Your World
// 6
DispatchQueue.main.async {
self.messageLabel?.text = ""
self.messageLabel?.alpha = 0
}
}
func renderer(_ renderer: SCNSceneRenderer,
didUpdate node: SCNNode,
for anchor: ARAnchor) {
DispatchQueue.main.async {
// 7
if let planeAnchor = anchor as? ARPlaneAnchor,
node.childNodes.count > 0,
!self.isPortalPlaced {
updatePlaneNode(node.childNodes[0],
center: planeAnchor.center,
extent: planeAnchor.extent)
}
}
}
Here are the changes you made:
1. You’re adding a horizontal plane to the scene to show the detected planes only if
the anchor that was added to the scene is an ARPlaneAnchor, and only if
isPortalPlaced equals false, which means the portal has not yet been placed.
2. If the anchor that was added was not an ARPlaneAnchor, and the portal node still
hasn’t been placed, this must be the anchor you add when the user taps on the
screen to place the portal.
3. You create the portal node by calling makePortal().
4. renderer(_:, didAdd:, for:) is called with the SCNNode object, node, that is added
to the scene. You want to place the portal node at the location of the node. So you
add the portal node as a child node of node, and you set isPortalPlaced to true to
track that the portal node has been added.
5. To clean up the scene, you remove all rendered horizontal planes and reset the
debugOptions for sceneView so that the feature points are no longer rendered on
screen.
6. You update the messageLabel on the main thread to reset its text and hide it.
raywenderlich.com
41
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
7. In the renderer(_:, didUpdate:, for:) you update the rendered horizontal plane
only if the given anchor is an ARPlaneAnchor, if the node has at least one child node
and if the portal hasn’t been placed yet.
Finally, replace removeAllNodes() with the following.
func removeAllNodes() {
// 1
removeDebugPlanes()
// 2
self.portalNode?.removeFromParentNode()
// 3
self.isPortalPlaced = false
}
This method is used for cleanup and removing all rendered objects from the scene.
Here’s a closer look at what’s happening:
1. You remove all the rendered horizontal planes.
2. You then remove the portalNode from its parent node.
3. Change the isPortalPlaced variable to false to reset the state.
Build and run the app; let the app detect a horizontal plane and then tap on the screen
when the crosshair view turns green. You will see a rather plain-looking, huge white
box.
raywenderlich.com
42
ARKit by Tutorials
Chapter 8: Adding Objects to Your World
This is the placeholder for your portal. In the next chapter, you’ll add some walls and a
doorway to the portal. You’ll also add textures to the walls so that they look more
realistic.
Where to go from here?
This has been quite a ride! Here’s a summary of what you learned in this chapter:
• You can now detect and handle ARSession interruptions when the app goes to the
background.
• You understand how hit testing works with an ARSCNView and the detected horizontal
planes in the scene.
• You can use the results of hit testing to place ARAnchors and SCNNode objects
corresponding to them.
In the next chapter, you’ll learn how to use SceneKit to build your portal’s walls and
learn more about how to use textures and lighting inside your Portal.
raywenderlich.com
43
9
Chapter 9: Geometry,
Textures & Lighting
By Namrata Bandekar
You learned how to add 3D objects to your scene with SceneKit. Now it’s time to put
that knowledge to use and build a portal. In this chapter, you will learn how to:
• Create walls, a ceiling and roof for your portal and adjust their position and rotation.
• Make the inside of the portal look more realistic with different textures.
• Add lighting to your scene.
Getting started
Before you begin, here’s an overview of how SceneKit works. Load up the starter project
from the starter folder.
The SceneKit coordinate system
As you saw in the previous chapter, SceneKit can be used to add virtual 3D objects to
your view. The SceneKit content view is comprised of a hierarchical tree structure of
nodes, also known as the scene graph. A scene consists of a root node, which defines a
coordinate space for the world of the scene, and other nodes that populate the world
with visible content. Each node or 3D object that you render on screen is an object of
type SCNNode. An SCNNode object defines the coordinate space transform (position,
orientation and scale) relative to its parent node. It doesn’t have any visible content by
itself.
The rootNode object in a scene defines the coordinate system of the world rendered by
SceneKit. Each child node you add to this root node creates its own coordinate system,
which, in turn, is inherited by its own children.
raywenderlich.com
44
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
SceneKit uses a right-handed coordinate system where (by default) the direction of view
is along the negative z-axis, as illustrated below.
The position of the SCNNode object is defined using an SCNVector3 which locates it
within the coordinate system of its parent. The default position is the zero vector,
indicating that the node is placed at the origin of the parent node’s coordinate system.
In this case, SCNVector3 is a three-component vector where each of the components is a
Float value representing the coordinate on each axis.
The SCNNode object’s orientation — expressed as pitch, yaw, and roll angles — is defined
by its eulerAngles property. This is also represented by an SCNVector3 struct where
each vector component is an angle in radians.
Textures
The SCNNode object by itself doesn’t have any visible content. You add 2D and 3D
objects to a scene by attaching SCNGeometry objects to nodes. Geometries have attached
SCNMaterial objects that determine their appearance.
An SCNMaterial has several visual properties. Each visual property is an instance of the
SCNMaterialProperty class that provides a solid color, texture or other 2D content.
There are a variety of visual properties for basic shading, physically based shading, and
special effects that you can use to make the material look more realistic.
raywenderlich.com
45
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
The SceneKit asset catalog is explicitly designed to help you manage your project’s
assets separately from the code. In your starter project, open the Assets.scnassets
folder. Notice that you already have images representing different visual properties for
the ceiling, floor and walls.
With SceneKit, you can also use nodes with attached SCNLight objects to shade the
geometries in a scene with light and shadow effects.
Building the portal
Let’s jump right into creating the floor for the portal. Open SCNNodeHelpers.swift and
add the following to the top of the file just below the import SceneKit statement.
// 1
let SURFACE_LENGTH: CGFloat = 3.0
let SURFACE_HEIGHT: CGFloat = 0.2
let SURFACE_WIDTH: CGFloat = 3.0
// 2
let SCALEX: Float = 2.0
let SCALEY: Float = 2.0
// 3
let WALL_WIDTH:CGFloat = 0.2
let WALL_HEIGHT:CGFloat = 3.0
let WALL_LENGTH:CGFloat = 3.0
raywenderlich.com
46
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
You’re doing a few things here:
1. You define constants for the dimensions of the floor and ceiling of your portal. The
height of the roof and ceiling corresponds to the thickness.
2. These are constants to scale and repeat the textures over the surfaces.
3. These define the width, height and length of the wall nodes.
Next, add the following method to SCNNodeHelpers:
func repeatTextures(geometry: SCNGeometry, scaleX: Float, scaleY: Float)
{
// 1
geometry.firstMaterial?.diffuse.wrapS = SCNWrapMode.repeat
geometry.firstMaterial?.selfIllumination.wrapS = SCNWrapMode.repeat
geometry.firstMaterial?.normal.wrapS = SCNWrapMode.repeat
geometry.firstMaterial?.specular.wrapS = SCNWrapMode.repeat
geometry.firstMaterial?.emission.wrapS = SCNWrapMode.repeat
geometry.firstMaterial?.roughness.wrapS = SCNWrapMode.repeat
// 2
geometry.firstMaterial?.diffuse.wrapT = SCNWrapMode.repeat
geometry.firstMaterial?.selfIllumination.wrapT = SCNWrapMode.repeat
geometry.firstMaterial?.normal.wrapT = SCNWrapMode.repeat
geometry.firstMaterial?.specular.wrapT = SCNWrapMode.repeat
geometry.firstMaterial?.emission.wrapT = SCNWrapMode.repeat
geometry.firstMaterial?.roughness.wrapT = SCNWrapMode.repeat
}
// 3
geometry.firstMaterial?.diffuse.contentsTransform =
SCNMatrix4MakeScale(scaleX, scaleY, 0)
geometry.firstMaterial?.selfIllumination.contentsTransform =
SCNMatrix4MakeScale(scaleX, scaleY, 0)
geometry.firstMaterial?.normal.contentsTransform =
SCNMatrix4MakeScale(scaleX, scaleY, 0)
geometry.firstMaterial?.specular.contentsTransform =
SCNMatrix4MakeScale(scaleX, scaleY, 0)
geometry.firstMaterial?.emission.contentsTransform =
SCNMatrix4MakeScale(scaleX, scaleY, 0)
geometry.firstMaterial?.roughness.contentsTransform =
SCNMatrix4MakeScale(scaleX, scaleY, 0)
This defines a method to repeat the texture images over the surface in the X and Y
dimensions.
raywenderlich.com
47
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
Here’s the breakdown:
1. The method takes an SCNGeometry object and the X and Y scaling factors as the
input. Texture mapping uses the S and T coordinate system which is just another
naming convention: S corresponds to X and T corresponds to Y. Here you define the
wrapping mode for the S dimension as SCNWrapMode.repeat for all the visual
properties of your material.
2. You define the wrapping mode for the T dimension as SCNWrapMode.repeat as well
for all visual properties. With the repeat mode, texture sampling uses only the
fractional part of texture coordinates.
3. Here, each of the visual properties contentsTransform is set to a scale transform
described by anSCNMatrix4 struct. You set the X and Y scaling factors to scaleX and
scaleY respectively.
You only want to show the floor and ceiling nodes when the user is inside the portal;
any other time, you need to hide them. To implement this, add the following method to
SCNNodeHelpers:
func makeOuterSurfaceNode(width: CGFloat,
height: CGFloat,
length: CGFloat) -> SCNNode {
// 1
let outerSurface = SCNBox(width: SURFACE_WIDTH,
height: SURFACE_HEIGHT,
length: SURFACE_LENGTH,
chamferRadius: 0)
// 2
outerSurface.firstMaterial?.diffuse.contents = UIColor.white
outerSurface.firstMaterial?.transparency = 0.000001
}
// 3
let outerSurfaceNode = SCNNode(geometry: outerSurface)
outerSurfaceNode.renderingOrder = 10
return outerSurfaceNode
Taking a look at each numbered comment:
1. Create an outerSurface scene box geometry object with the dimensions of the floor
and ceiling.
2. Add visible content to the box object’s diffuse property so it’s rendered. You set the
transparency to a low value, so the object is hidden from view.
raywenderlich.com
48
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
3. Create an SCNNode object from the outerSurface geometry. Set renderingOrder for
the node to 10. Nodes with a larger rendering order are rendered last. To make the
ceiling and floor invisible from outside the portal, you will make the rendering order
of the inner ceiling and floor nodes much larger than 10.
Now add the following code to SCNNodeHelpers to create the portal floor:
func makeFloorNode() -> SCNNode {
// 1
let outerFloorNode = makeOuterSurfaceNode(
width: SURFACE_WIDTH,
height: SURFACE_HEIGHT,
length: SURFACE_LENGTH)
// 2
outerFloorNode.position = SCNVector3(SURFACE_HEIGHT * 0.5,
-SURFACE_HEIGHT, 0)
let floorNode = SCNNode()
floorNode.addChildNode(outerFloorNode)
// 3
let innerFloor = SCNBox(width: SURFACE_WIDTH,
height: SURFACE_HEIGHT,
length: SURFACE_LENGTH,
chamferRadius: 0)
// 4
innerFloor.firstMaterial?.lightingModel = .physicallyBased
innerFloor.firstMaterial?.diffuse.contents =
UIImage(named:
"Assets.scnassets/floor/textures/Floor_Diffuse.png")
innerFloor.firstMaterial?.normal.contents =
UIImage(named:
"Assets.scnassets/floor/textures/Floor_Normal.png")
innerFloor.firstMaterial?.roughness.contents =
UIImage(named:
"Assets.scnassets/floor/textures/Floor_Roughness.png")
innerFloor.firstMaterial?.specular.contents =
UIImage(named:
"Assets.scnassets/floor/textures/Floor_Specular.png")
innerFloor.firstMaterial?.selfIllumination.contents =
UIImage(named:
"Assets.scnassets/floor/textures/Floor_Gloss.png")
// 5
repeatTextures(geometry: innerFloor,
scaleX: SCALEX, scaleY: SCALEY)
// 6
let innerFloorNode = SCNNode(geometry: innerFloor)
innerFloorNode.renderingOrder = 100
// 7
innerFloorNode.position = SCNVector3(SURFACE_HEIGHT * 0.5,
0, 0)
floorNode.addChildNode(innerFloorNode)
raywenderlich.com
49
ARKit by Tutorials
}
Chapter 9: Geometry, Textures & Lighting
return floorNode
Breaking this down:
1. Create the lower side of the floor node using the floor’s dimensions.
2. Position outerFloorNode such that it’s laid out on the bottom side of the floor node.
Add the node to the floorNode which holds both the inner and outer surfaces of the
floor.
3. You make the geometry of the floor using the SCNBox object initialized with the
constants declared previously for each dimension.
4. The lightingModel of the material for the floor is set to physicallyBased. This type
of shading incorporates a realistic abstraction of physical lights and materials. The
contents for various visual properties for the material are set using texture images
from the scnassets catalog.
5. The texture for the material is repeated over the X and Y dimensions using
repeatTextures(), which you defined before.
6. You create a node for the floor using the innerFloor geometry object and set the
rendering order to higher than that of the outerFloorNode. This ensures that when
the user is outside the portal, the floor node will be invisible.
7. Finally, set the position of innerFloorNode to sit above the outerFloorNode and add
it as a child to floorNode. Return the floor node object to the caller.
Open PortalViewController.swift and add the following constants:
let POSITION_Y: CGFloat = -WALL_HEIGHT*0.5
let POSITION_Z: CGFloat = -SURFACE_LENGTH*0.5
These constants represent the position offsets for nodes in the Y and Z dimensions.
Add the floor node to your portal by replacing makePortal().
func makePortal() -> SCNNode {
// 1
let portal = SCNNode()
// 2
let floorNode = makeFloorNode()
floorNode.position = SCNVector3(0, POSITION_Y, POSITION_Z)
}
// 3
portal.addChildNode(floorNode)
return portal
raywenderlich.com
50
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
Fairly straightforward code:
1. You create a SCNNode object to hold the portal.
2. You create the floor node using makeFloorNode() defined in SCNNodeHelpers. You set
the position of floorNode using the constant offsets. The center of the SCNGeometry
is set to this location in the node’s parent’s coordinate system.
3. Add the floorNode to the portal node and return the portal node. Note that the
portal node is added to the node created at the anchor’s position when the user taps
the view in renderer(_ :, didAdd:, for:).
Build and run the app. You’ll notice the floor node is dark. That’s because you haven’t
added a light source yet!
Now add the ceiling node. Open SCNNodeHelpers.swift and add the following method:
func makeCeilingNode() -> SCNNode {
// 1
let outerCeilingNode = makeOuterSurfaceNode(
width: SURFACE_WIDTH,
height: SURFACE_HEIGHT,
raywenderlich.com
51
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
length: SURFACE_LENGTH)
// 2
outerCeilingNode.position = SCNVector3(SURFACE_HEIGHT * 0.5,
SURFACE_HEIGHT, 0)
let ceilingNode = SCNNode()
ceilingNode.addChildNode(outerCeilingNode)
// 3
let innerCeiling = SCNBox(width: SURFACE_WIDTH,
height: SURFACE_HEIGHT,
length: SURFACE_LENGTH,
chamferRadius: 0)
// 4
innerCeiling.firstMaterial?.lightingModel = .physicallyBased
innerCeiling.firstMaterial?.diffuse.contents =
UIImage(named:
"Assets.scnassets/ceiling/textures/Ceiling_Diffuse.png")
innerCeiling.firstMaterial?.emission.contents =
UIImage(named:
"Assets.scnassets/ceiling/textures/Ceiling_Emis.png")
innerCeiling.firstMaterial?.normal.contents =
UIImage(named:
"Assets.scnassets/ceiling/textures/Ceiling_Normal.png")
innerCeiling.firstMaterial?.specular.contents =
UIImage(named:
"Assets.scnassets/ceiling/textures/Ceiling_Specular.png")
innerCeiling.firstMaterial?.selfIllumination.contents =
UIImage(named:
"Assets.scnassets/ceiling/textures/Ceiling_Gloss.png")
// 5
repeatTextures(geometry: innerCeiling, scaleX:
SCALEX, scaleY: SCALEY)
// 6
let innerCeilingNode = SCNNode(geometry: innerCeiling)
innerCeilingNode.renderingOrder = 100
}
// 7
innerCeilingNode.position = SCNVector3(SURFACE_HEIGHT * 0.5,
0, 0)
ceilingNode.addChildNode(innerCeilingNode)
return ceilingNode
Here’s what’s happening:
1. Similar to the floor, you create an outerCeilingNode with the dimensions for the
ceiling.
2. Set the position of the outer ceiling node so that it goes on top of the ceiling. Create
a node to hold the inner and outer sides of the ceiling. Add outerCeilingNode as a
child of the ceilingNode.
raywenderlich.com
52
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
3. Make innerCeiling an SCNBox object with the respective dimensions.
4. Set the lightingModel to physicallyBased. Also, set the contents of the visual
properties that are defined by various texture images found in the assets catalog.
5. repeatTextures() wraps the texture images in both the X and Y dimensions to
create a repeated pattern for the ceiling.
6. Create innerCeilingNode using the innerCeiling geometry and set its
renderingOrder property to a high value so that it gets rendered after the
outerCeilingNode.
7. Position innerCeilingNode within its parent node and add it as a child of
ceilingNode. Return ceilingNode to the caller.
Now to call this from somewhere. Open PortalViewController.swift and add the
following block of code to makePortal() just before the return statement:
// 1
let ceilingNode = makeCeilingNode()
ceilingNode.position = SCNVector3(0,
POSITION_Y+WALL_HEIGHT,
POSITION_Z)
// 2
portal.addChildNode(ceilingNode)
1. Create the ceiling node using makeCeilingNode() which you just defined. Set the
position of the center of ceilingNode to the SCNVector3 struct. The Y coordinate of
the center is offset by the Y position of the floor added to the height of the wall.
You also subtract SURFACE_HEIGHT to account for the thickness of the ceiling. The Z
coordinate is set to the POSITION_Z offset similar to the floor. This is how far away
from the center of the ceiling is from the camera along the Z axis.
2. Add ceilingNode as a child of the portal.
raywenderlich.com
53
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
Build and run the app. Here’s what you’ll see:
Time to add the walls!
Open SCNNodeHelpers.swift and add the following method:
func makeWallNode(length: CGFloat = WALL_LENGTH,
height: CGFloat = WALL_HEIGHT,
maskLowerSide:Bool = false) -> SCNNode {
// 1
let outerWall = SCNBox(width: WALL_WIDTH,
height: height,
length: length,
chamferRadius: 0)
// 2
outerWall.firstMaterial?.diffuse.contents = UIColor.white
outerWall.firstMaterial?.transparency = 0.000001
// 3
let outerWallNode = SCNNode(geometry: outerWall)
let multiplier: CGFloat = maskLowerSide ? -1 : 1
outerWallNode.position = SCNVector3(WALL_WIDTH*multiplier,0,0)
outerWallNode.renderingOrder = 10
// 4
let wallNode = SCNNode()
wallNode.addChildNode(outerWallNode)
// 5
let innerWall = SCNBox(width: WALL_WIDTH,
height: height,
length: length,
chamferRadius: 0)
// 6
innerWall.firstMaterial?.lightingModel = .physicallyBased
innerWall.firstMaterial?.diffuse.contents =
UIImage(named:
raywenderlich.com
54
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
"Assets.scnassets/wall/textures/Walls_Diffuse.png")
innerWall.firstMaterial?.metalness.contents =
UIImage(named:
"Assets.scnassets/wall/textures/Walls_Metalness.png")
innerWall.firstMaterial?.roughness.contents =
UIImage(named:
"Assets.scnassets/wall/textures/Walls_Roughness.png")
innerWall.firstMaterial?.normal.contents =
UIImage(named:
"Assets.scnassets/wall/textures/Walls_Normal.png")
innerWall.firstMaterial?.specular.contents =
UIImage(named:
"Assets.scnassets/wall/textures/Walls_Spec.png")
innerWall.firstMaterial?.selfIllumination.contents =
UIImage(named:
"Assets.scnassets/wall/textures/Walls_Gloss.png")
}
// 7
let innerWallNode = SCNNode(geometry: innerWall)
wallNode.addChildNode(innerWallNode)
return wallNode
Going over the code step-by-step:
1. You create an outerWall node that will sit on the outside of the wall to make it
appear transparent from the outside. You create an SCNBox object matching the
wall’s dimensions.
2. You set the diffuse contents of the material to a monochrome white color and the
transparency to a low number. This helps achieve the see-through effect if you look
at the wall from outside of the room.
3. You create a node with the outerWall geometry. The multiplier is set based on
which side of the wall the outer wall needs to be rendered. If maskLowerSide is set to
true, the outer wall is placed below the inner wall in the wall node’s coordinate
system; otherwise, it’s placed above.
You set the position of the node such that the outer wall is offset by the wall width
in the X dimension. Set the rendering order for the outer wall to a low number so
that it’s rendered first. This makes the walls invisible from the outside.
4. You also create a node to hold the wall and add the outerWallNode as its child node.
5. You make innerWall an SCNBox object with the respective wall dimensions.
6. You set the lightingModel to physicallyBased. Similar to the ceiling and floor
nodes, you set the contents of the visual properties that are defined by various
texture images for the walls.
raywenderlich.com
55
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
7. Finally, you create an innerWallNode object using the innerWall geometry. Add this
node to the parent wallNode object. By default, innerWallNode is placed at the origin
of wallNode. Return the node to the caller.
Now add the far wall for the portal. Open PortalViewController.swift and add the
following to the end of makePortal() just before the return statement:
// 1
let farWallNode = makeWallNode()
// 2
farWallNode.eulerAngles = SCNVector3(0,
90.0.degreesToRadians, 0)
// 3
farWallNode.position = SCNVector3(0,
POSITION_Y+WALL_HEIGHT*0.5,
POSITION_Z-SURFACE_LENGTH*0.5)
portal.addChildNode(farWallNode)
This is fairly straightforward:
1. Create a node for the far wall. farWallNode needs the mask on the lower side. So the
default value of false for maskLowerSide will do.
2. Add eulerAngles to the node. Since the wall is rotated along the Y axis and
perpendicular to the camera, it has a rotation of 90 degrees for the second
component. The wall does not have a rotation angle for the X and Z axes.
3. Set the position of the center of farWallNode such that its height is offset by
POSITION_Y. Its depth is calculated by adding the depth of the center of the ceiling
to the distance from the center of the ceiling to its far end.
Build and run the app, and you will see the far wall attached to the ceiling on top and
attached to the floor on the bottom.
raywenderlich.com
56
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
Next up you will add the right and left walls. In makePortal(), add the following code
just before the return portal statement to create the right and left side walls:
// 1
let rightSideWallNode = makeWallNode(maskLowerSide: true)
// 2
rightSideWallNode.eulerAngles = SCNVector3(0, 180.0.degreesToRadians, 0)
// 3
rightSideWallNode.position = SCNVector3(WALL_LENGTH*0.5,
POSITION_Y+WALL_HEIGHT*0.5,
POSITION_Z)
portal.addChildNode(rightSideWallNode)
// 4
let leftSideWallNode = makeWallNode(maskLowerSide: true)
// 5
leftSideWallNode.position = SCNVector3(-WALL_LENGTH*0.5,
POSITION_Y+WALL_HEIGHT*0.5,
POSITION_Z)
portal.addChildNode(leftSideWallNode)
Going through this step-by-step:
1. Create a node for the right wall. You want to put the outer wall on the lower side of
the node, so you set maskLowerSide to true.
2. You set the rotation of the wall along the Y axis to 180 degrees. This ensures the
wall has its inner side facing the right way.
3. Set the location of the wall so that it’s flush with the right edge of the far wall,
ceiling and floor. Add rightSideWallNode as a child node of portal.
4. Similar to the right wall node, create a node to represent the left wall with
maskLowerSide set to true.
5. The left wall does not have any rotation applied to it, but you adjust its location so
that it’s flush with the left edge of the far wall, floor and ceiling. You add the left
wall node as a child node of the portal node.
raywenderlich.com
57
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
Build and run the app, and your portal now has three walls. If you move out of the
portal, none of the walls are visible.
Adding the doorway
There’s one thing missing in your portal: an entrance! Currently, the portal does not
have a fourth wall. Instead of adding another wall, you will add just the necessary parts
of a wall to leave room for a doorway.
Open PortalViewController.swift and add these constants:
let DOOR_WIDTH:CGFloat = 1.0
let DOOR_HEIGHT:CGFloat = 2.4
As their names suggest, these define the width and height of the doorway.
Add the following to PortalViewController:
func addDoorway(node: SCNNode) {
// 1
let halfWallLength: CGFloat = WALL_LENGTH * 0.5
let frontHalfWallLength: CGFloat =
(WALL_LENGTH - DOOR_WIDTH) * 0.5
raywenderlich.com
58
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
// 2
let rightDoorSideNode = makeWallNode(length: frontHalfWallLength)
rightDoorSideNode.eulerAngles = SCNVector3(0,270.0.degreesToRadians, 0)
rightDoorSideNode.position = SCNVector3(halfWallLength - 0.5 *
DOOR_WIDTH,
POSITION_Y+WALL_HEIGHT*0.5,
POSITION_Z+SURFACE_LENGTH*0.5)
node.addChildNode(rightDoorSideNode)
// 3
let leftDoorSideNode = makeWallNode(length: frontHalfWallLength)
leftDoorSideNode.eulerAngles = SCNVector3(0, 270.0.degreesToRadians, 0)
leftDoorSideNode.position = SCNVector3(-halfWallLength + 0.5 *
frontHalfWallLength,
POSITION_Y+WALL_HEIGHT*0.5,
POSITION_Z+SURFACE_LENGTH*0.5)
node.addChildNode(leftDoorSideNode)
}
addDoorway(node:) is a method that adds a wall with an entrance to the given node.
Here’s what you’re doing:
1. Define constants to store the half wall length and the length of the front wall on
each side of the door.
2. Create a node to represent the wall on the right side of the entrance using the
constants declared in the previous step. You also adjust the rotation and location of
the node so that it’s attached to the front edge of the right wall, ceiling and floor.
You then add rightDoorSideNode as a child of the given node.
3. Similar to step 2, you create a node for the left side of the doorway, and set the
rotation and location of leftDoorSideNode so that it is flush with the front edge of
the left wall, ceiling and floor nodes. Finally, you use addChildNode() to add it as a
child node to node.
In makePortal(), add the following just before return portal:
addDoorway(node: portal)
Here, you add the doorway to the portal node.
raywenderlich.com
59
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
Build and run the app. You’ll see the doorway on the portal, but the top of the door is
currently touching the ceiling. You’ll need to add another piece of the wall to make the
doorway span the pre-defined DOOR_HEIGHT.
Add the following at the end of addDoorway(node:):
// 1
let aboveDoorNode = makeWallNode(length: DOOR_WIDTH,
height: WALL_HEIGHT - DOOR_HEIGHT)
// 2
aboveDoorNode.eulerAngles = SCNVector3(0, 270.0.degreesToRadians, 0)
// 3
aboveDoorNode.position =
SCNVector3(0,
POSITION_Y+(WALL_HEIGHT-DOOR_HEIGHT)*0.5+DOOR_HEIGHT,
POSITION_Z+SURFACE_LENGTH*0.5)
node.addChildNode(aboveDoorNode)
1. Create a wall node with the respective dimensions to fit above the entrance of the
portal.
2. Adjust the rotation of aboveDoorNode so that it’s at the front of the portal. The
masked side is placed on the outside.
raywenderlich.com
60
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
3. Set the position of the node so that it’s placed on top of the doorway that you just
built. Add it as a child node of node.
Build and run. This time you’ll notice the doorway is now complete with a proper wall.
Placing lights
That portal doesn’t look too inviting; it’s rather dark and gloomy. You can add a light
source to brighten it up!
Add the following method to PortalViewController:
func placeLightSource(rootNode: SCNNode) {
// 1
let light = SCNLight()
light.intensity = 10
// 2
light.type = .omni
// 3
let lightNode = SCNNode()
lightNode.light = light
// 4
raywenderlich.com
61
ARKit by Tutorials
}
Chapter 9: Geometry, Textures & Lighting
lightNode.position = SCNVector3(0,
POSITION_Y+WALL_HEIGHT,
POSITION_Z)
rootNode.addChildNode(lightNode)
Here’s how it works:
1. Create an SCNLight object and set its intensity. Since you’re using the
physicallyBased lighting model, this value is the luminous flux of the light source.
The default value is 1000 lumens, but you want an intensity which is much lower,
giving it a slightly darker look.
2. A light’s type determines the shape and direction of illumination provided by the
light, as well as the set of attributes available for modifying the light’s behavior.
Here, you set the type of the light to omnidirectional, also known as a point light.
An omnidirectional light has constant intensity and a direction. The light’s position
relative to other objects in your scene determines its direction.
3. You create a node to hold the light and attach the light object to the node using its
light property.
4. Place the light at the center of the ceiling using the Y and Z offsets and then add
lightNode as a child of the rootNode.
In makePortal(), add the following just before return portal.
placeLightSource(rootNode: portal)
This places the light source inside the portal. Build and run the app, and you’ll see a
brighter, more inviting doorway to your virtual world!
raywenderlich.com
62
ARKit by Tutorials
Chapter 9: Geometry, Textures & Lighting
Where to go from here?
The portal is complete! You have learned a lot through creating this sci-fi portal. Let’s
take a quick look at all the things you covered in this chapter.
• You have a basic understanding of SceneKit’s coordinate system and materials.
• You learned how to create SCNNode objects with different geometries and attach
textures to them.
• You also placed light sources in your scene so that the portal looked more realistic.
Going forward, there are many changes you can make to the portal project. You can:
• Make a door that opens or shuts when the user taps on the screen.
• Explore various geometries to create a room that spans infinitely.
• Experiment with different shapes for the doorway.
Don’t stop here. Let your sci-fi imagination run wild.
raywenderlich.com
63
W
Where to Go From Here?
We hope you enjoyed this sample of ARKit by Tutorials!
If you enjoyed this sample, be sure to check out the full book, which contains the
following chapters:
• Chapter 1: Hello ARKit!: You’ll start off at the very beginning with a guided tour of
what augmented reality is and how ARKit can help. You’ll also learn about the
limitations of ARKit, which is equally important.
• Chapter 2: Your First ARKit App: Once you’ve covered the basics, you’ll get your
hands dirty by creating your own ARKit app. This will be the start of creating a fun
augmented reality poker dice table-top game.
• Chapter 3: Basic Session Management: Here, you’ll learn about session
management, an essential part of every ARKit app. Not only will your app comply
with the basic requirements, but it will also provide the users with a seamless AR
experience.
• Chapter 4: Adding 3D Objects & Textures: Next, you’ll add some basic 3D objects
to your project. You’ll also create some materials and learn about the different types
of textures used in PBR-based materials.
• Chapter 5: Detecting Surfaces: In this chapter, you’ll learn how to detect and
manage surfaces — like floors, walls and tables — with ARKit. Once you know how to
do that, you’ll know where (and how) to place AR content within the scene.
• Chapter 6: Adding Physics: Finally, you’ll add physics to your virtual content. With
physics, you can make things bounce off of surfaces or interactive with other virtual
contents, just like the real thing.
raywenderlich.com
64
ARKit by Tutorials
Where to Go From Here?
• Chapter 7: Building a Portal: In this chapter, you’ll explore an app to review the
basics of ARKit development. You’ll set up an ARSession and add plane detection and
other functions so that the app can render horizontal planes using the
ARSCNViewDelegate protocol.
• Chapter 8: Adding Objects to Your World: Over the course of building your portal,
you’ll learn how to handle ARSession interruptions elegantly when your app goes to
the background. You’ll then explore how hit-testing with an ARSCNView works as you
start adding objects to the detected horizontal plane in the device’s surroundings.
For adding virtual objects, you’ll use ARAnchors and SCNNode objects to define their
position and geometry.
• Chapter 9: Geometry, Textures & Lighting: In the final chapter of this section,
you’ll first dive deeper to understand SceneKit’s coordinate system and materials.
Next, you’ll use SCNNode objects with different geometries and attach textures to
them to create the walls, floor and ceiling of your portal. Finally, you’ll make your
portal appear realistic by adding lighting.
• Chapter 10: Detecting Placeholders: In the first chapter of this section, you’ll start
with detecting a rectangular placeholder. You’ll display some place markers above its
edges and then a plane on top of it — although initially it won’t be oriented correctly.
• Chapter 11: Beginning User Interaction: In the second chapter, you’ll fix the plane
orientation issue so that it’s parallel to and covering the detected placeholder.
However, this is only the beginning. You’ll also replace arbitrary rectangle detection
with QR code detection, and then you’ll add some interactive content to the
rectangular plane; first an image, then a carousel, and finally a video player.
• Chapter 12: Advanced User Interaction: In this chapter, you're going to improve
user interaction by using storyboards instead of standalone view controllers. You’ll
add a full screen mode for the interactive content, and you’ll learn an alternative
detection method: image detection.
• Chapter 13: Location Tracking & Beacons: The last chapter in this section focuses
on using location and proximity features to monitor the user’s location, geofencing
to detect when they enter or leave a monitored area and beacons to detect when
they’re very close to a predefined location.
• Chapter 14: Getting Started with Face-Based AR: Start your journey with FaceBased AR here! In this chapter, you’ll discover the four primary features that ARKit
provides for face tracking. You’ll also learn how to add face-base session tracking to
your own iOS apps.
raywenderlich.com
65
ARKit by Tutorials
Where to Go From Here?
• Chapter 15: Tracking the User’s Face: Learn how to work with ARFaceAnchor
objects, and get a brief overview of how the face position and orientation work within
a SceneKit scene. Use different techniques to change the appearance of things.
• Chapter 16: Creating Assets for Face-Based AR: Learn how to create 3D content
using 3D Text, and discover how you can use occlusion geometry to obscure parts of
the user’s face.
• Chapter 17: Working with Blend Shapes: Make your own Pig Animoji! Discover
how you can track specific user expressions using 53 different blend shapes, like
jawOpen, eyeBlinkLeft and eyeBlinkRight.
• Chapter 18: Recording Your ARKit Experience with ReplayKit: Extend your app
with ReplayKit. Using RPScreenRecorder and RPPreviewViewController, you can
record, preview, edit and share your AR experiences.
• Chapter 19: Beginning Game Physics: Here, you’ll learn more about SceneKit’s
built-in physics simulation capabilities. SceneKit has decent vehicle physics
simulation right out-of-the-box, and you’ll be using it to build a fun, little remotecontrolled AR monster truck.
• Chapter 20: Advanced Game Physics: By this point, you’ve got the Monster Truck
built, but it’s not doing much — at least not yet. In this chapter, you’ll add the
finishing touches, like throttle control, braking and steering — you know, everything
that you’d need to control a little monster truck.
• Chapter 21: World Tracking & Persistent AR Experiences: This chapter starts off
with a fun Sketch app. You’ll explore the concept of an ARWorldMap to save custom
ARAnchor objects in your session and how to save its space-mapping to local storage
on the device.
In this process, you’ll learn how to find the best time to capture a world map to
enable reliable restoration later on. After that, you’ll add functionality to load the
world map from a file and enable the user to assist with relocalizing the data. Finally,
you’ll restore custom nodes from saved anchors to recreate the AR content from a
previous session.
• Chapter 22: Shared AR Experiences: In the second chapter of this section, you’ll
dive deep into understanding the Multipeer Connectivity framework, an Apple
framework used to connect two or more devices. This chapter starts off by
demonstrating how to browse for nearby devices and send a world map from one
device to all others in an MCSession.
raywenderlich.com
66
ARKit by Tutorials
Where to Go From Here?
Next, you’ll learn how to handle received world map data from another device, and
how to parse and relocalize that data to restore the contents of the shared ARSession.
Finally, you’ll tie together learnings from both chapters to save, restore and share the
data on a real-time basis, creating a multi-user Sketch app.
• Chapter 23: Introducing USDZ & AR Quick Look: In this chapter, you’ll learn
about Apple’s new USDZ file format and walk through converting 3D models into this
new, universal format. After converting, you’ll explore integrating AR Quick Look
into your existing web pages and apps to enable them to display USDZ content in
stunning augmented reality.
• Chapter 24: Detecting Images & 3D Objects: If you need a word to describe this
chapter, here it is: detection. You'll learn how to detect 2D images and track their
position when moving. You’ll also take a look at how to detect 3D objects.
The full book is now available for purchase:
• www.store.raywenderlich.com/products/arkit-by-tutorials.
We hope you enjoy the book!
— The ARKit by Tutorials team
raywenderlich.com
67
ARKit by Tutorials
raywenderlich.com
Where to Go From Here?
68
Download