All right, guys. I hope you're enjoying the ARKit tutorial so far because we are going to embark on creating 1
yet another really awesome ARKit app. 2
So the first thing that we're gonna do is create a brand-new Xcode project. And, of course, we are going 3
to choose the augmented reality app template. Hit Next. 4
And I'm just gonna call mine AR Ruler because that's what we're making. 5
Feel free to call yours whatever you like. 6
All right. 7
So here's our brand-new ARKit project. 8
And the first thing I'm going to do is delete the unnecessary template code that Apple gave us. 9
So I'm gonna get rid of all three lines here and just leave sceneView.delegates and self. 10
And then if you scroll down to the bottom, I'm going to delete all of these delegate methods and also 11
that didReceiveMemoryWarning method. 12
All right. 13
So that makes our view a little bit cleaner and easier to work with. 14
All right. 15
So the next thing I'm gonna do is I'm going to add some debug options. So I'm gonna say 16
sceneView.debugOtions = ARSCNDebugOptions, and I'm gonna go for the one that just showsFeaturePoints 17
because we're going to be using the automatically detected feature points to figure out which 18
parts of the scene are a continuous surface and be able to measure something on that surface. 19
All right. 20
So once we've done that, the next thing we need to do is to detect user touch on the screen. 21
So we're going to use the method touchesBegan and we're simply going to print the console that a touch 22
was detected. 23
So you can pause the video now and try and give it a go. 24
So there's nothing new here. 25
You've done this in the last tutorial, so why don't you give it a go and see if you can do it yourself? 26
All right. 27
So I hope that wasn't too difficult. 28
We're going to head below viewWillDisappear and we're simply going to start typing touchesBegan to 29
search for the one that we want. 30
So this is the method that tells the object and the object is, obviously, our ViewController here that 31
one or more new touches occurred in a view or window, 32
so exactly what we want. Now, inside here, where it says code, we're going to print to the console and say, 33
"touch detected." All right, let's give it a spin. 34
So the crazier thing is, actually, you can make this endless hallway illusion. 35
All right, enough playing around. 36
Let's have a look. 37
So we've got feature points detected on screen. 38
And if I tap anywhere on the screen, you'll see "touches detected" showing up. Perfect. 39
All right. So, now that we know that our code for detecting touch is working, we're going to grab the location 40
of the touch on the 2D screen. 41
So instead of printing to the console, I'm just going to delete that, 42
I'm going to use optional binding to grab hold of the location of the touch. 43
So I'm going to say if let touchLocation = touches, 44
so this is that set of UITouches that we get back whenever a user touches the screen. 45
So in this set of touches, I'm going to grab the first one if it exists, and then I'm going to check for 46
its location inside the sceneView. 47
Now, if that succeeds, then we have this object touchLocation and I'm going to perform a hitTest using 48
that touchLocation and see if it corresponds to a feature point. 49
So I'm going to write let hitTestResults = sceneView.hitTest. 50
And the point is going to be the touchLocation which is a CGPoint, as you can see. And the type is 51
going to be a .featurePoint. 52
So as Xcode explains, the .featurePoint ResultType is a point automatically identified by 53
ARKitv as a part of a continuous surface, but without a corresponding anchor. 54
So we're not interested here in detecting planes or going into the planeAnchors or 3D anchors, we're 55
actually just interested in using the code inside ARKit to detect continuous surfaces. 56
And this will give us the 3D location of a continuous surface 57
I'm tapping on if it exists. 58
So go ahead and hit enter. 59
So, now we have this hitTestResult object that we can work with. 60
Now, what I want to do is to use this hitTestResult which is the location in 3D space inside the real 61
world 62
that's on our scene. 63
And I want to add a simple red dot to that location. 64
So I'm going to say if let hitResult = hitTestResult. 65
So you can see that hitTestResults are actually a array of hitTestResults, 66
so we can actually change that to results which might make it more understandable semantically. 67
So if let hitResult = hitTestResults.first, 68
so grabbing that first object in that array. And if that exists, i.e., this is not nil, then we're going 69
to call a function called addDot to add a dot to the scene 70
basically. We're going to specify a location which is going to be the location of the hitTestResult. 71
So, of course, Xcode is going to complain 'cause I don't have this method could addDot yet, it has no 72
idea what I'm talking about. 73
So I'm going to go ahead and create it down here. 74
So I'm going to create a function called addDot and this addDot is going to have a internal and an 75
external parameter. 76
So remember we talked about internal/external parameters in Swift before. 77
So the internal one is the one that you referred to inside the function, but the external one is the 78
one that you use when you're calling the function. 79
So the external one for addDot is "at" and the internal one is the hitResult, and then we have to specify 80
a data type which is going to be ARHitTestResult data type. 81
So it's a little bit mad at me because I'm missing a bracket, so I'm going to hit command A to select 82
all, and I'm going to hit option control I to indent everything and make it look beautiful once more. 83
Okay. So, now I'm going to open a set of curly braces and inside addDot, we are going to create a new 84
.geometry. 85
So this dot is going to be a SCNSphere. 86
So just the same in the tutorial where we created the moon, 87
we're going to create a 3D sphere. 88
So I'm going to give this to you as a challenge and see if you remember how we created these geometries 89
in previous tutorials. 90
So you're going to be creating something called a dotGeometry and it is going to be a SCNSphere, 91
so a 3D sphere. I'm not sure you can have non-3D spheres. And the material of that sphere is simply going 92
to be a red UIColor. And then you're going to create a dotNode that has the geometry of this newly 93
created dotGeometry. 94
So pause the video give that a go and see if you can remember how we created 3D spheres in ARKit. 95
All right. 96
So let's go ahead and do that. 97
So we said we're going to call it dotGeometry and it is going to be a SCNSphere, and we're going 98
to create it with a radius of-- 99
I mean, it's really up to you how big you want it, 100
but I'm actually going to make it quite small. 101
So half a centimeter thereabouts should do just fine. 102
So we're creating a new SCNSphere 103
that's about half a centimeter in radius, 104
so about one centimeter in diameter, and then we're going to create a material for it. 105
So let material = SCNMaterial and let's define the material's diffuse.contents that is going 106
to consist of a UIColor that is a red color, as we said, and then I'm going to assign this material 107
to my dotGeometry, so dotGeometry.materials = an array of materials that only contains 108
our single red color material. 109
Okay. 110
So, and then we said we're going to create a node called dotNode that was going to be a SCNNode, and 111
it was going to be created using our dotGeometry. 112
All right. 113
And that's it. 114
So how is that? 115
So if that was confusing at all, have a look back at the lesson 116
where we created the moon and we created spheres and 3D objects in ARKit to refresh your memory. 117
Okay. 118
So let's go on to the next part and it's, you guessed it, another challenge. 119
So what I want you to do is to assign the position of this dotNode using the hitResult that we passed 120
in here. 121
So over here, we first detected and it touches on the 2D iPad or iPhone screen, and then we converted 122
those 2D coordinates into 3D coordinates by performing a hitTest on the scene using that location. 123
Now, the hitTest is going to look for any featurePoints that match up with a 3D continuous surface, 124
so, say, a table or your laptop. And then we grabbed the first object in that array of hitTest results, 125
and then we passed that location in 3D called hitResult into this addDot method that we're creating 126
right now. 127
So, now that location is contained inside this internal parameter called hitResult. 128
So can you use this hitResult to specify the position of our dotNode in 3D. 129
So it's a little bit similar to when we created the dice. 130
We want to create this dot where we tap on the screen. So to do this, you're going to have to specify 131
the dotNodes position property. And it is going to be a SCNVector3, 132
so it has an x, y, and z. And you're going to use the hitResult to specify the position. 133
So if you're up to the challenge, pause the video and give that a go. 134
All right. 135
So I hope that was okay. 136
So as we said, we're going to specify the dotNodes position property. 137
And as you can see here, it's expecting a SCNVector3, so a vector that has three components. 138
So I'm going to use the SCNVector3 overload to create a new one. 139
And if you scroll down here, there's one that says x, y, and z using CGFloats, 140
and that's what we're gonna choose. 141
Now, inside these placeholders, I'm going to specify the x, so left and right, the y, up and down, and z 142
towards or away from us. 143
So I'm going to use the hitResult that we passed in here. 144
And for the x, I'm just gonna say hitResult.worldTransform.columns.3.x. And then 145
for the y position, I'm gonna say hitResults.worldTransform.columns.3.y. 146
And finally, I'm going to specify the z. 147
So hitResult.worldTransform.columns.3.z. 148
All right. So all three dimensions are specified, 149
so now it will know where to position our dot on the scene. 150
And one final thing we need to do to add our dotNode onto the scene is, of course, say, 151
sceneView.scene.rootNode.addChildNode. And the child is, of course, our brand-new dotNode. 152
Okay. 153
So let's go ahead and run it and see how it goes. 154
All right. 155
So that's the first part of creating our ARRuler. 156
We're able to specify a location in the real world in 3D that we want to measure from and to, and we're 157
able to put down this red dot to show on the scene where we want to start and where we want to end. 158
So stay tuned because in the next lesson, we're going to be taking these positions and working out the 159
distance between the start and endpoints in order to actually have the functionality of an ARRuler. 160
So I'll see you there.