0 1 00:00:00,600 --> 00:00:09,000 Now, in the last lesson, we captured, processed, and incorporated our tracking image into our Xcode project 1 2 00:00:09,690 --> 00:00:16,740 and we added it to our configuration so that it knows what are the images that it should be detecting. 2 3 00:00:16,740 --> 00:00:23,070 Now, in this lesson, I want to show you how we can start recognizing those images using ARKit and how 3 4 00:00:23,070 --> 00:00:30,730 to turn the image into a plane that we're going to later use to set our 3D models on. 4 5 00:00:30,750 --> 00:00:37,110 So first things first, we're gonna be working within the ARSCNViewDelegate methods section, but 5 6 00:00:37,110 --> 00:00:41,140 we're going to delete all of these other methods because we're not going to be using it. 6 7 00:00:41,160 --> 00:00:46,040 Make sure you don't delete the last one because that's needed for the entire class. 7 8 00:00:46,080 --> 00:00:54,900 Now, the method that we're gonna add in here is called renderer nodeFor anchor. And this one asked the 8 9 00:00:54,900 --> 00:01:01,310 delegate to provide a SceneKit node corresponding to a newly added anchor. 9 10 00:01:01,320 --> 00:01:06,270 Now, if you remember from previous lessons, the anchor is the thing that was detected. 10 11 00:01:06,330 --> 00:01:13,680 So in our case, the anchor will be the image that got detected on screen, and the node is going to be 11 12 00:01:13,680 --> 00:01:18,510 a 3D object that we're going to provide in response to detecting the anchor, 12 13 00:01:18,900 --> 00:01:23,720 so that's basically what this method is all about. When the image gets detected, 13 14 00:01:23,760 --> 00:01:30,930 this method will get called and we can look at the image that got detected. And in response, we can provide 14 15 00:01:30,960 --> 00:01:35,040 a 3D object to be rendered into the screen. 15 16 00:01:35,160 --> 00:01:40,380 Now, the first thing we're going to do is we're going to create that brand-new 3D object or what we call 16 17 00:01:40,470 --> 00:01:47,410 a SCNNode. So this is our new node object. 17 18 00:01:47,540 --> 00:01:55,400 And once everything's all said and done, then we're going to return this node as the output of this method. 18 19 00:01:55,850 --> 00:01:56,470 As you can see, 19 20 00:01:56,470 --> 00:02:04,100 this method is expecting a output of SCNNode and it needs to send that back onto the scene so that 20 21 00:02:04,100 --> 00:02:07,310 it can render a 3D object. 21 22 00:02:07,400 --> 00:02:13,610 Now, in between these two lines of code is everything that we need to do to set up our plane and also 22 23 00:02:13,610 --> 00:02:15,560 render our 3D models. 23 24 00:02:15,560 --> 00:02:20,890 So first things first, we're going to check to see if the anchor that we detected, 24 25 00:02:20,900 --> 00:02:27,040 so if the item that was detected in the world was in fact an ARImageAnchor. 25 26 00:02:27,080 --> 00:02:29,220 So we're going to do a type check. 26 27 00:02:29,240 --> 00:02:32,450 So let's say let imageAnchor 27 28 00:02:34,950 --> 00:02:40,230 = anchor, and that, of course, comes from here. 28 29 00:02:40,530 --> 00:02:45,540 And we're going to check if the data type is an ARImageAnchor. 29 30 00:02:46,680 --> 00:02:52,890 And this, of course, contains information about the position and orientation of an image detected in the 30 31 00:02:53,020 --> 00:02:54,120 ARSession. 31 32 00:02:54,750 --> 00:03:03,130 If a detected, say, a plane or a point or anything else, then this is not going to carry out. 32 33 00:03:03,270 --> 00:03:08,730 In that case, we can use this with a "if let" to only carry out code 33 34 00:03:09,180 --> 00:03:14,190 if the anchor that was detected is in fact of data type ARImageAnchor. 34 35 00:03:14,340 --> 00:03:17,900 So it was in fact an image that got detected. 35 36 00:03:17,910 --> 00:03:25,170 Now, if that is true, then we're going to create a new plane using that image, and the plane is going be 36 37 00:03:25,170 --> 00:03:29,160 created as we did before using SCNPlane, 37 38 00:03:29,480 --> 00:03:33,920 and we're going to use the method that provides a width and a height. 38 39 00:03:33,930 --> 00:03:39,090 Now, this plane is going to be created from the image that was detected, 39 40 00:03:39,090 --> 00:03:46,200 so from our Pokémon card. And we want the width and height of the plane in the physical world to be the 40 41 00:03:46,200 --> 00:03:48,020 same as it is, 41 42 00:03:48,030 --> 00:03:48,330 right? 42 43 00:03:48,360 --> 00:03:53,060 So we want it to be exactly the size that our card is. 43 44 00:03:53,130 --> 00:04:00,420 Now, I can either provide in hard values that I've measured using a tape measure, or I can simply say 44 45 00:04:00,870 --> 00:04:07,920 look at the imageAnchor that you found and look at the referenceImage that it contains, and then get 45 46 00:04:07,980 --> 00:04:13,440 its physical size, and grab the width property. 46 47 00:04:13,620 --> 00:04:20,310 That means that it's going to look at the image that it detected and try to measure its actual physical 47 48 00:04:20,310 --> 00:04:28,830 size and get all of its height and width properties to put in here, instead of me having to hardcode it. 48 49 00:04:28,970 --> 00:04:37,510 So once we've got a dimension to our plane, then we're going to use it to create a planeNode, and this 49 50 00:04:37,510 --> 00:04:44,800 is going to be the 3D object that we're going to render just on top of our card so that we can tell 50 51 00:04:44,800 --> 00:04:46,950 that our card has been recognized. 51 52 00:04:46,990 --> 00:04:53,290 So the planeNode is going to be an SCNNode and it's going to be created with a geometry. And the 52 53 00:04:53,290 --> 00:05:02,220 geometry is, of course, this plane that we created over here. And now, we can tap into this node that we 53 54 00:05:02,220 --> 00:05:09,970 created earlier on and we can add a childNode which is going to be our planeNode. 54 55 00:05:10,350 --> 00:05:15,780 So, now let's hit run and let's see what we get when we tried to detect our card. 55 56 00:05:18,400 --> 00:05:24,400 When you run the app, you'll be asked to grant access to the camera so that we can start an 56 57 00:05:24,400 --> 00:05:25,480 ARSession. 57 58 00:05:25,480 --> 00:05:32,740 And once it has, then we can reveal the face of our card which is meant to be detected and you can see 58 59 00:05:32,740 --> 00:05:36,760 that we're getting this plane that's being rendered on top of it. 59 60 00:05:36,970 --> 00:05:42,610 Now, the only problem with this plane is that it's being rendered vertically, whereas what we actually 60 61 00:05:42,610 --> 00:05:48,620 want is for it to be lying down with the same dimension as our card. 61 62 00:05:48,640 --> 00:05:55,120 So in order to do that, we have to do a few transformations. Now, the transformation we need to make is 62 63 00:05:55,120 --> 00:06:06,520 to rotate this plane that we've created by 90 degrees, anticlockwise in the x axis. 63 64 00:06:06,520 --> 00:06:13,630 So here are our three axis: x, y, and Z. And currently, our card looks like this. 64 65 00:06:13,630 --> 00:06:22,210 So along the x axis, we're going to rotate it anticlockwise. And to do that, all we have to do is to take 65 66 00:06:22,210 --> 00:06:32,480 the planeNode and tap into the eulerAngles, which is the node orientation, and notice that it's expressed 66 67 00:06:32,690 --> 00:06:34,220 in radians, 67 68 00:06:34,220 --> 00:06:42,830 so that requires the use of pi. And the eulerAngle that we're going to change is the x or the first 68 69 00:06:42,830 --> 00:06:44,330 component. 69 70 00:06:44,330 --> 00:06:50,000 And in order to rotate anticlockwise, then I'm going to make it negative. 70 71 00:06:50,000 --> 00:06:56,120 And the amount that I want to rotate it by is only 90 degrees. So in radians, 71 72 00:06:56,120 --> 00:07:05,120 that's expressed as pi divided by 2. Half a pi is 90 degrees in radians. 72 73 00:07:05,120 --> 00:07:11,060 And you have to make sure that there's no space between the minus and the dot pi. 73 74 00:07:11,060 --> 00:07:18,620 Now, you can also write pi as Float.pi or you can simply use the shorthand way which simply assumes 74 75 00:07:18,620 --> 00:07:24,780 that it's a float and we're tapping into the constant of pi. 75 76 00:07:24,790 --> 00:07:32,720 So, now let's hit run again and see what happens this time. 76 77 00:07:32,720 --> 00:07:41,180 So, now you can see that this plane has been generated is now completely attached to the dimension of 77 78 00:07:41,180 --> 00:07:45,170 the card, and it is flush with the surface of the card. 78 79 00:07:45,620 --> 00:07:54,650 And this gives us a perfect place to start projecting 3D images onto, and for 3D images to be tracked. 79 80 00:07:54,680 --> 00:07:56,290 Now, there's just one thing. 80 81 00:07:56,360 --> 00:08:02,270 Once we've got the plane show up, it's completely white and completely opaque. And we can't really see 81 82 00:08:02,270 --> 00:08:03,620 our card anymore, 82 83 00:08:03,740 --> 00:08:09,380 which means I don't really know what was on the card, so it would be really nice if I can make this plane 83 84 00:08:09,500 --> 00:08:12,110 a little bit more transparent. 84 85 00:08:12,350 --> 00:08:20,980 So let's give that a go. Now, in order to make our plane transparent, before we set the geometry, 85 86 00:08:21,120 --> 00:08:29,700 we can set another one of its properties which is its material and it's diffuse. So we can say 86 87 00:08:29,850 --> 00:08:42,610 plane.firstMaterial.diffuse.contents = UIColor that is created using this method. 87 88 00:08:42,660 --> 00:08:45,420 These are the grayscale and the alpha values. 88 89 00:08:45,810 --> 00:08:46,840 So the grayscale, 89 90 00:08:46,860 --> 00:08:50,950 I'll leave it as completely white. And the alpha, 90 91 00:08:51,190 --> 00:08:57,670 I'll change that to 0.5 so that it's half as transparent as it used to be. 91 92 00:08:57,970 --> 00:09:04,770 And let's try that out. 92 93 00:09:04,810 --> 00:09:13,000 So, now you can see that the plane is rendered on top of my Pokémon card, but it's also transparent so 93 94 00:09:13,000 --> 00:09:18,030 that I can see through it into my actual card. 94 95 00:09:18,070 --> 00:09:26,200 So, now we're at the position when we are ready to start rendering our 3D Eevee on top of this playing card 95 96 00:09:26,740 --> 00:09:35,800 and using that plane to track and render the 3D model, and to move the 3D model as I move this physical 96 97 00:09:35,800 --> 00:09:37,120 card. 97 98 00:09:37,300 --> 00:09:39,880 That is what we're going to be learning in the next lesson. 98 99 00:09:40,240 --> 00:09:42,850 So for all of that and more, I'll see you there.