0 1 00:00:00,810 --> 00:00:01,170 All right. 1 2 00:00:01,200 --> 00:00:09,000 So in previous lessons, we managed to get our code to recognize the Pokémon card, and to be able to render 2 3 00:00:09,090 --> 00:00:15,040 a 3D model of the Eevee Pokémon on top of the card so that it's standing on the card. 3 4 00:00:15,060 --> 00:00:21,750 Now, in this lesson, it's mostly a challenge for you because I want to be able to have, say, two card side 4 5 00:00:21,750 --> 00:00:28,170 by side. Say, you know, my Pokémon is battling somebody else's Pokémon, and I want it such that when two 5 6 00:00:28,170 --> 00:00:34,200 players when they're both revealing their Pokémons, the 3D models should appear on top of each 6 7 00:00:34,200 --> 00:00:41,340 card. So the card that I'm gonna be working with is the Offish card. And the first thing we need to do 7 8 00:00:41,430 --> 00:00:45,630 is we need to add the Oddish card image to our project. 8 9 00:00:45,690 --> 00:00:50,850 So if you have your own Pokémon cards and you want to work with a different model, that's perfectly fine, 9 10 00:00:50,910 --> 00:00:55,500 or if you want to use another card that you have lying around, a playing card, a business card, that's 10 11 00:00:55,590 --> 00:00:56,430 also fine. 11 12 00:00:56,580 --> 00:00:59,900 But you need to add that into your project. 12 13 00:00:59,890 --> 00:01:06,660 Now, if you want to work along with me, then just head over to this website here and print out the Oddish 13 14 00:01:06,690 --> 00:01:11,340 card so that you can follow along with the tutorial as well. 14 15 00:01:11,340 --> 00:01:17,190 So here I've saved an image of the Oddish card and I'm simply going to rename it, 15 16 00:01:20,090 --> 00:01:29,390 oddish-card, and I'm going to drag this into my project under my assets. 16 17 00:01:29,390 --> 00:01:35,450 So notice that we've got our Pokémon cards folder already, and all I need to do is open my downloads 17 18 00:01:35,450 --> 00:01:40,550 folder and drag my Oddish card into my Pokemon cards 18 19 00:01:40,550 --> 00:01:45,580 group. So, again, we get a warning 19 20 00:01:45,660 --> 00:01:49,590 and that's because we haven't provided a physical dimension to it. 20 21 00:01:49,740 --> 00:01:51,060 So let's tap that in, 21 22 00:01:51,060 --> 00:01:53,510 0.065, hit Enter, 22 23 00:01:53,520 --> 00:01:56,710 so the height gets calculated automatically. 23 24 00:01:56,700 --> 00:02:02,640 Now, while I'm here, I'm going to switch out my Eevee card as well, just so that it's a little bit more 24 25 00:02:02,640 --> 00:02:08,970 clear and it works a little better, just because it has much higher resolution and a better clarity than 25 26 00:02:08,970 --> 00:02:15,030 what I can get from taking a photo of it. And I'm just going to drag that new card back in and delete 26 27 00:02:15,030 --> 00:02:16,470 the old one as well. 27 28 00:02:16,560 --> 00:02:21,430 And, of course, update my dimensions, 0.065. 28 29 00:02:21,540 --> 00:02:28,410 So that means if you have images that are high resolution that already digital, then perfect, upload those. 29 30 00:02:28,860 --> 00:02:35,460 If you don't and you want a particular card to be recognized, then using the camera or using a scanner 30 31 00:02:35,730 --> 00:02:37,810 will work just as well. 31 32 00:02:37,830 --> 00:02:46,530 So, now that we have both cards incorporated to our Pokémon cards set, the next challenge is to incorporate 32 33 00:02:46,680 --> 00:02:49,060 the Oddish 3D model. 33 34 00:02:49,110 --> 00:02:51,230 So we're going to do exactly the same. 34 35 00:02:51,270 --> 00:03:00,390 You're going to download it from Roestudios and you can just command F to find Oddish, and download 35 36 00:03:00,450 --> 00:03:08,220 the file, use the Oddish model, and convert it to usdz and include it into your project. 36 37 00:03:08,220 --> 00:03:12,690 So pause the video and give that a go. All right. 37 38 00:03:12,720 --> 00:03:16,470 So this should be incredibly easy as we did it before. 38 39 00:03:16,560 --> 00:03:22,310 So we're just going to agree to the Terms and Conditions, we're going to unzip the Oddish folder. 39 40 00:03:22,710 --> 00:03:29,370 And here we have all of those different types and different file formats, but we're going to use the 40 41 00:03:29,370 --> 00:03:34,930 one that is just called Oddish.obj as we did before. 41 42 00:03:35,310 --> 00:03:44,820 And then we're going to pull up Terminal and I'm going to use Xcode command line, run, usdz_converter, 42 43 00:03:44,820 --> 00:03:52,410 and then I have a space, and then I drag in the file I want to convert, and then after a space, 43 44 00:03:52,470 --> 00:04:00,740 I add the location that I want to place my converted file. And that's just going to be called 44 45 00:04:00,960 --> 00:04:06,720 Oddish.usdz in my downloads folder. And there you have it. 45 46 00:04:06,770 --> 00:04:10,180 There's our new Oddish model. 46 47 00:04:10,500 --> 00:04:18,870 So, now that we have that model, we can drag it into our art.scnassets folder, and we can now convert 47 48 00:04:18,870 --> 00:04:22,620 it to a SceneKit scene format. 48 49 00:04:22,620 --> 00:04:24,610 And it does that for a little while. 49 50 00:04:24,630 --> 00:04:28,080 And now we have oddish.scn. And there you go, 50 51 00:04:28,110 --> 00:04:31,650 There's little Oddish. As we did previously, 51 52 00:04:31,650 --> 00:04:39,240 we're going to simplify our nodes by flattening them into one, just so that we don't have the eyes and 52 53 00:04:39,240 --> 00:04:41,550 the mouth and the body all separate, 53 54 00:04:41,550 --> 00:04:46,310 and we're going to rename this node to oddish. 54 55 00:04:46,830 --> 00:04:49,430 And at the moment, again, it's a little bit too big, 55 56 00:04:49,440 --> 00:04:52,850 so we're going to scale it down by the same scale format, 56 57 00:04:52,860 --> 00:04:58,470 So 0.05 on the height, width, and the depth. 57 58 00:04:58,710 --> 00:05:06,070 And now, this audition is about the same size as our Eevee which is the perfect size for rendering onto 58 59 00:05:06,090 --> 00:05:08,040 the card. 59 60 00:05:08,040 --> 00:05:08,370 All right. 60 61 00:05:08,370 --> 00:05:18,450 So now that we've got two 3D models and both Pokémon cards into our project, the next step is to figure 61 62 00:05:18,450 --> 00:05:27,150 out how can we know whether if the Oddish card was detected, or whether if the Eevee card was detected, 62 63 00:05:27,160 --> 00:05:29,550 how can we differentiate that. 63 64 00:05:29,580 --> 00:05:35,330 Well, you can see the anchor here is the item that triggered this function. 64 65 00:05:35,340 --> 00:05:43,200 So it's the thing that got detected using the mode of detection that we chose here which is image tracking, 65 66 00:05:43,200 --> 00:05:48,540 so the anchor is then the image that was recognized and detected. 66 67 00:05:48,750 --> 00:05:57,390 If we make sure that the image anchor is indeed an ARImageAnchor, then we should be able to tap into some 67 68 00:05:57,390 --> 00:05:58,760 its properties. 68 69 00:05:58,770 --> 00:06:06,090 Now, what kind of properties does it have? If you hold on option and you click on ARImageAnchor, then 69 70 00:06:06,180 --> 00:06:10,000 you can see this brief description about what it is. 70 71 00:06:10,140 --> 00:06:16,770 But if you want to read more, we can click on Open Developer Documentation and this takes us to the 71 72 00:06:16,830 --> 00:06:18,870 ARImageAnchor Docs. 72 73 00:06:18,900 --> 00:06:25,480 Now, it says that when you run a world-tracking AR session and specify ARReferenceImageObjects, 73 74 00:06:25,500 --> 00:06:30,930 now you might be wondering, we're not running a world tracking AR session actually, we're running 74 75 00:06:30,960 --> 00:06:33,750 a ARImageTrackingConfiguration. 75 76 00:06:33,900 --> 00:06:42,320 But if you actually change this to ARWorldTrackingConfiguration, this image tracking also works. 76 77 00:06:42,390 --> 00:06:46,030 So you can now detect planes as well as images. 77 78 00:06:46,140 --> 00:06:54,030 All you have to do is change this configuration. Instead of tracking images, you change it to 78 79 00:06:54,060 --> 00:06:57,040 detectionImages, and it'll work exactly the same. 79 80 00:06:57,060 --> 00:07:04,030 But now, you're able to detect planes in the world tracking as well as images., so you can do both. 80 81 00:07:04,080 --> 00:07:10,530 But if you only need one, then try to keep it to imageTracking so that it's less resource-intensive. 81 82 00:07:12,250 --> 00:07:19,110 So an ARImageAnchor contains ARReferenceImage objects. 82 83 00:07:19,150 --> 00:07:27,310 So if we look inside the ARReferenceImage object, you could see that it has a number of properties, for example, 83 84 00:07:27,370 --> 00:07:36,450 the name property which is a descriptive name for the image which was recognized in the ARSession, 84 85 00:07:36,460 --> 00:07:48,340 so that means that if we print the imageAnchor.referenceImage.name, then we can figure out which 85 86 00:07:48,340 --> 00:07:52,870 card was detected when this function was called. 86 87 00:07:56,160 --> 00:08:05,160 So, now if I flip over this card, which is Eevee, you can see that in my debug console, I've got the 87 88 00:08:05,190 --> 00:08:12,960 Eevee-card which, remember, is the name of that card over here. And that is what it's printing here. 88 89 00:08:12,960 --> 00:08:22,680 Now, if I turn over the Oddish card, then you can see I've got the Oddish card being printed over here, 89 90 00:08:23,130 --> 00:08:26,520 and that refers to this one being detected. 90 91 00:08:26,640 --> 00:08:33,930 So at the moment, an Eevee is being rendered on both cards, and we're only getting one card recognized 91 92 00:08:34,020 --> 00:08:35,610 at one time. 92 93 00:08:35,610 --> 00:08:38,940 So let's try and change that. 93 94 00:08:39,240 --> 00:08:45,360 Let's head back to our ViewController and we can be pretty certain that we can access the image that 94 95 00:08:45,360 --> 00:08:50,780 was detected through using the imageAnchor.referenceImage.name. 95 96 00:08:50,820 --> 00:08:53,910 So let's go ahead and delete this print statement. 96 97 00:08:54,210 --> 00:09:01,150 Now, if you scroll up to our viewWillAppear, you can see that at one point, we set the maximum number 97 98 00:09:01,150 --> 00:09:04,010 of tracked images in our configuration to 1. 98 99 00:09:04,140 --> 00:09:10,560 And that's why at any moment in time, we're only tracking one image and we're only able to render our 99 100 00:09:10,560 --> 00:09:12,510 3D model onto one image. 100 101 00:09:12,900 --> 00:09:20,280 So let's raise that number to two so that we can simultaneously track and render for two images. 101 102 00:09:20,280 --> 00:09:28,600 Now, down here, when we render our pokeScene, at the moment, it only renders eeveee.scn. 102 103 00:09:28,620 --> 00:09:35,820 But we want to be able to render the oddish.scn, as well as eevee, depending on which card and which 103 104 00:09:35,850 --> 00:09:37,630 images were detected. 104 105 00:09:37,650 --> 00:09:45,620 So as a challenge, can you modify this code so that when the orange card is detected, 105 106 00:09:45,630 --> 00:09:51,630 so we only have Oddish on the table, then we should only see the Oddish model rendered. 106 107 00:09:51,780 --> 00:09:57,810 But when we have Eevee on the table as well, then we should be able to see both models rendered onto 107 108 00:09:57,810 --> 00:09:58,990 the correct card. 108 109 00:09:59,190 --> 00:10:05,070 So pause the video and see if you can complete this challenge. 109 110 00:10:05,120 --> 00:10:05,480 All right. 110 111 00:10:05,510 --> 00:10:06,560 So how did that go? 111 112 00:10:07,250 --> 00:10:20,500 Let's say that if imageAnchor.referenceImage.name == "eevee-card," 112 113 00:10:20,580 --> 00:10:26,700 and remember, this is the name that we had printed in our debug console and it also refers to the name 113 114 00:10:26,700 --> 00:10:28,910 of the card over here. 114 115 00:10:29,220 --> 00:10:32,210 And, again, make sure you don't have any typos there. 115 116 00:10:32,280 --> 00:10:39,270 So if the card that was recognized was the eevee-card, then, in that case, we should be rendering a 116 117 00:10:39,270 --> 00:10:42,060 pokeScene with the eevee.scn. 117 118 00:10:42,270 --> 00:10:53,250 And we should be rendering that onto the card. Now at the same time, if the imageAnchor.referenceImage.name 118 119 00:10:53,250 --> 00:10:57,780 was "oddish-card," 119 120 00:10:57,810 --> 00:11:00,600 so the app saw the oddish-card, 120 121 00:11:00,630 --> 00:11:06,160 then we should be rendering the oddish.scn file or the Oddish scene, 121 122 00:11:06,450 --> 00:11:16,290 and we should be adding that node to our planeNode. So, now let's just briefly review our code. This delegate 122 123 00:11:16,290 --> 00:11:25,380 method gets triggered whenever any of the images in the group that's Pokémon cards gets detected, and 123 124 00:11:25,380 --> 00:11:33,120 that is because we added all of those groups over here, so that our AR app starts tracking all of those 124 125 00:11:33,120 --> 00:11:34,110 cuts. 125 126 00:11:34,590 --> 00:11:41,090 And when one of them or both of them gets detected, then we add a plane to that 126 127 00:11:41,100 --> 00:11:44,390 imageAnchor at the position of the image. 127 128 00:11:44,490 --> 00:11:51,440 So that's when we end up with that see-through white panel that's flushed with the card. 128 129 00:11:51,450 --> 00:11:58,930 Now, if there's two cards that get detected, then they both get a white panel or a plane added to it. 129 130 00:12:00,470 --> 00:12:07,180 If the image that was detected is the eevee-card, then we create a scene using eevee.scn, 130 131 00:12:07,290 --> 00:12:10,510 and we add it onto the plane. 131 132 00:12:10,510 --> 00:12:14,580 Now, if the image that was detected was the oddish-card, 132 133 00:12:14,580 --> 00:12:25,230 then we add our oddish scene to the plane. And because we've set our maximumNumberOfTrackedImages to 2, 133 134 00:12:25,530 --> 00:12:34,170 then we can now simultaneously track movements and location for two images. 134 135 00:12:34,170 --> 00:12:40,640 So this should now fulfill all our requirements. And let's run our app to see if it does indeed work. 135 136 00:12:42,750 --> 00:12:43,020 Okay. 136 137 00:12:43,050 --> 00:12:48,690 So here's our app running. And let's just flip over one of these cards. 137 138 00:12:48,720 --> 00:12:50,090 There's Eevee 138 139 00:12:50,590 --> 00:12:54,870 and there's all Oddish. And I can move them around, 139 140 00:12:54,870 --> 00:12:56,640 I can rotate them. 140 141 00:12:56,730 --> 00:13:00,150 I can lift them up off the ground. 141 142 00:13:00,150 --> 00:13:09,570 I can move them around. And at the same time, I can have both of these guys on the screen and moving, so 142 143 00:13:09,570 --> 00:13:13,610 they could be attacking each other or something like that. 143 144 00:13:15,230 --> 00:13:22,100 So, I hope you had fun building this project along with me, and I hope this project has inspired you to create 144 145 00:13:22,100 --> 00:13:31,340 some awesome things using ARKit and SceneKit. Now, I look forward to hearing all about the amazing 145 146 00:13:31,340 --> 00:13:33,960 incredible things that you guys are building. 146 147 00:13:34,010 --> 00:13:38,310 So be sure to hit up the team at robots@londonappbrewery. com 147 148 00:13:38,390 --> 00:13:45,980 if you build something fantastic and you want to be entered into the Monthly Student App Selection that 148 149 00:13:45,980 --> 00:13:50,270 will go out in the newsletter to all of our students worldwide. 149 150 00:13:50,300 --> 00:13:59,300 So in the next module, we're going to be looking at how we can stop playing video when we track and recognize 150 151 00:13:59,420 --> 00:14:01,580 images in AR. 151 152 00:14:01,610 --> 00:14:08,450 So we're going to be building the interactive Harry Potter style newspapers where everything on the 152 153 00:14:08,450 --> 00:14:10,640 page comes alive. 153 154 00:14:10,640 --> 00:14:13,970 So for all of that and more, I'll see you on the next module.