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