 Howdy guys, this is IndiePixel, and I am happy to bring the fourth video in the intro to VEX series. Alright, so in this particular video we are going to talk about ray casting. Alright, and then we're going to look at a way to do selection based off of the number of objects that you have and a bunch of points. Alright, so these are two methods that I use quite often in my workflows every day. So I just wanted to cover them because they're super useful. And I also just wanted to talk about why they're so useful. Okay, so let's get started. What I'm going to do first is talk about the ray casting over here. So I'm going to drop down a geometry node like so. I'm going to delete that file node that always comes with it. And I'm going to show my properties up here on my parameters pane. Alright, so the first thing that we need is a line. So I'm just going to drop down the line. I'm not going to actually make a line from scratch this time. So I'm going to then point that in the z direction. Now you don't necessarily have to do this. I'm just doing this for example purposes here. So I just want this to lay down flat because I'm going to project this line onto a grid. Okay, so then I'm going to move it back in the z direction. So it's centered over the world center. So I'm just going to grab that z direction parameter and also need to make sure that I multiply that there and then move back with the negative sign. So now we're centered right over that middle area right there. Okay, and what I want to do now is add some more points and I want to create a grid. Now this grid is going to be the object that we're going to snap onto. Okay, and to prove that I don't want to just have any flat grid because that wouldn't really prove anything because our line is also already flat right here. Okay, so what I'm going to do is drop down the size to something like 2 by 2 and we'll leave the rows and columns as saying I'm going to just make this dependent on the rows there. Okay, and then I'm going to drop down a mountain, sop. All right, and then we'll just perturb it a little bit. That way we actually have something that's a little bit more like terrain. Now I do use this technique quite often with terrains because let's say I want to lay down a road onto the terrain. This is a great way to do that. Okay, so I'm going to get rid of the world grid there and turn off these point numbers like that. Okay, so now we have a grid and we have a line and what I want to do is first transform this line above that grid. So to do that all I need to do is just put this on template like so. All I need to do is actually move this line to the y-max of the bounding box of this grid. So I'm going to take this transform node here and just type in the bbbox function and give it the grid object to process. And I want the dy-max. That should have done it. We need the mountain actually, not the grid because the grid itself is flat. So we want the mountain. All right, so what that does is put that right above the top and you can always add a little bit extra might help 0.1. So now you can be assured that this line is always above that grid like so. Okay, so what I want to do now is write some vex that will actually cast some rays down onto this grid right here and snap the line to wherever it hits the grid. And if it doesn't hit the grid, it shouldn't do anything. So let's do that. So I'm going to drop down a wrangle node, white wrangle. All right. And I'm going to feed the line into the first input and the mountain into the second input. All right, because what we're going to do is we're going to use the second input to use as the processing, the geometry that we're going to process. Okay, and we're going to apply the modifications to the line. All right. So the first thing that we need to do is figure out how we're going to cast rays. So inside of vex, we actually have a function called intersect. And this basically will cast a ray given by a direction from a certain point onto another piece of geometry. Okay, so what we need to do is we need to take advantage. I'm going to be using this particular function right here. And you'll notice that there are these weird arguments here at the end of this intersect. So if you're familiar with something like C sharp, this is basically like an out type of argument or a reference type of argument. If you feed in a variable, it'll output the results of this function into that particular variable. And so that's what this little and means. Okay, so we need to set up those particular variables. And we also need to set up a couple other variables like this direction. Okay, so let's do that. So what I want to do is I want to type out int, we're going to say primnum. Okay, because once again, let me cover that really quick because if we come down here, well, this says it says this function computes the intersection of the specified ray with the geometry and the primitive number is returned or negative one if there was no intersection found or there was an error. So we're basically going to be getting the primitive number of this. So it's going to return whatever primitive we hit or negative one if it didn't hit anything. Okay, so knowing that what we can do is store this primnum. So I'm just going to call the variable primnum and it equals intersect. And let's go take a look at the next argument here. So we need a file name or an input so we can input a file or we can input the geometry that we want to intersect against. So in this case, the geometry that we want to intersect is coming into the input one. So I'm just going to put a one right there. And then I want to provide it an origin. In this case, it's just going to be the current point that we're on in the line. So we're going to utilize the position of these points. So I'm just going to say at p because that's a vector and that gives us that position of that point that we're currently on because we are running over points. So for each point, we're running this operation. So then the next argument here is the direction. And we can always expose this so we can say vector hitter or you can call it whatever you want is equal to we'll just say actually we'll make this a property or a parameter. We're going to call this hitter like so and make sure that it's a vector. And then let's create that so now we hit a hitter so we can do a negative 10 in this case. So it's pointing straight down 10 units. All right, so I'm going to provide that hitter here. And then the next argument is those two values. So we have the origin and we have the direction that we want to ray cast in and I want to store the result of that. So I want to store the position that we hit and I want to store the UVW or the UV position of that because we're going to use that to get the normal from the primitive as well. Okay, so let's go back and do that. So I need to create two variables here and they're both going to be vectors. So there's a vector that's going to be hit point. Okay, we're going to call that we don't need to call it anything actually. Then we need another vector and we're going to call this UVW. Okay, so we're going to provide those two parameters UVW. All right, and so what's going to happen is that hit position is going to be stored now in this hit point so we can use it later. We're also going to get the UV position that we hit at. So very useful information when dealing with primitives. So what we can do now is we can say if the primnum is greater than zero because remember if it fails, actually we can say greater than or equal because we could be hitting the primitive zero. But if it's negative one then it failed and let's not run any of this code, let's just leave the point where it's at. So what we can say then is that the at P is equal to the hit point because that hit position is being stored in that reference variable. There you go. We are now snapped to the geometry perfectly. See, not too hard and this runs super fast, way faster than doing it through a point bop. So if I were to offset this, you can see that I mean this is a very basic example, but when you start dealing with large trains and like roads and stuff like that or train tracks, this is a very fast technique and it works well with the Houdini engine as well. So the other ways that you would do it that are really slow, the slowest way would be to use the race op, snap these guys down like so and you actually need to provide it a normal. So you would have to give it a point here, do a normal like so and we would just say set zero, negative ten, zero, there you go. So that's the slower way to do it and then you can do it in a point bop. So we jump in here and we drop down the intersect node and you can see it's looking for the same information. So the file that we want to intersect against is going to be from op input two in this case. The array origin is the current point position that we're on and then we need a constant or you could make a parameter as well but in this case I'm just going to make a constant because I don't need to expose this for this particular demonstration. So I'm going to pass that into the raider and then the new pause is going to be that and you get the same sort of snapping. So three different ways you could do the snapping. I do prefer the point wrangle and the more and more you become familiar with vex, you'll find yourself just using the wrangle nodes mostly because this starts adding complexity to your graphs and while it's easy and visual, it just makes your graphs explode into complexity and just a ton of nodes everywhere. So I still just wanted to show those other ways of doing that because there are three ways. Well, there's probably more but those are the three more common ways to do this particular technique. Okay, so the last thing I want to do is actually provide the normals from our hit point. Because currently we don't have any normals. That is no good. So what we want to do is drop down a normal so that way we can actually create normals. And what I'm going to do is actually put this, I have to put this onto primitives. That way we are actually pulling in the normal from the primitive. So these are the normals that we're going to extract basically. So let's go back to our wrangle node here and let's get that done. So what we want to do is utilize the prim function. This allows us to access attributes. So if I were to type in prim here, go to that vex function for it. So what it's looking for is the geometry or the op input. So in this case, it's just going to be one. And the string attribute name, so in this case it's going to be n. And then the primitive that we hit. Now remember, the current primnum is being stored or given to us by this intersect function. So this is going to be super easy. So all we need to do now is just say at n equals prim1, we want to pull the normal out. And we want to give it that primnum that we just hit. Because remember if we don't hit anything, none of this stuff is going to run. And we wouldn't have any information pull out anyway. So there you go. And now we have the normals. So we've extracted those guys off of the geometry that we hit off of that grid. All right. So that is what I wanted to show there. Super useful technique. Comes in handy all the time. And now obviously the terrain and roads example is the more common and more obvious one. I just use that quite often. You can use this for anything that you need to snap one object to another. So definitely keep this one in your toolbox. Okay. So moving on, let's go and do the selection. So the selection example here. Let's take a look at this guy. So the selection allows us to provide a bunch of points. Okay. And then create IDs on each of those points. So if we come down here, you can see that I randomly assign some IDs to these points. And I can change those IDs as I see fit. So I can also change our seed value. So we get different selection types. Right. But what it's really doing is it's going through and it's picking particular objects here. And from that object ID and using that piece of geometry. So we're just using a switch node to select between a bunch of different objects. Now imagine that you wanted to scatter rocks along the terrain. Okay. And you have three different models of rocks that have been provided to you by an artist. Or maybe you created a rock maker node inside of Houdini. And every single time you want to basically select a different type of rock. You don't want to just stamp the same rock over all the points and then just randomly rotate them. Because it's going to look kind of obvious. So you might as well switch and select between three different types of rocks. Or five different types of rocks. How many of our types of rocks you want. So this is what we're going to do now. Okay. So let's create a new node. So I'm going to do geometry. Delete that file. What I want to do is create a circle in this case. Okay. So imagine that we have a plot of land that we want to scatter points onto. I'm going to actually make that into a polygon and reverse it. Alright. Cool. And then what I want to do is give this some normals. But I want normals that are radiating out from the center. And so what I want to do is select normal and then just type in at P. And you'll notice that all of our normals are now radiating outwards. And this is useful because then I can use the mountain stop to create different shapes on that plot. Just to create random shapes out of that circle. Nice quick and easy, cheap randomization or procedural thing to get different looks. Okay. And then on that particular plot, I'm going to scatter some points like so. And definitely change that ray count. We don't need as many. Okay. So now we have our points. And what I want to do is I want to create an ID for each one of these points. And I want it to be random. Okay. So I'm going to drop down a wrangle node. Like so. In this case, an attribute wrangle node. Alright. And what I want to do is, is really simple. What I want to do is first create a float called seed. And this is going to be our seed value. Just so it'll allow us to change randomization. And then I want to give an int called obj count. And this is going to be CHI object count. And that's going to allow us to tell how many objects we want to select from. Okay. So the final property or the attribute that we're going to put on each one of these points is just going to be a fit01 with a random function. Okay. So let's do an I at because this is going to be an attribute, not a variable. These are variables. This is going to be an attribute that sits on the point. And we're going to call this obj ID. And that's going to be equal to a fit01, a random function. And in that random function, we're going to provide the current point number times our seed value so we can change the randomness. And now this random function will return us a value from zero to one. So what we want to do is we want to fit it between a new range. And that's going to be zero to that object count. And with that, you can see that we don't have any, we just have zero for our obj ID over here. And that's because we need to create the channels over here. So I'm going to increase my seed and increase the object count. And you can start to see that we are getting just random selection. Okay. So these values are actually on these points. So what we can do is we can go and use those values with a copy stamp. That's what I usually do. So let me create a box. I'm going to create a sphere. And I'm going to create a tube. And I'm going to scale all these guys down. So I just want to check their sizes here. I need the grid for this. So for this cube, I'm going to put it down to something like that. And for our sphere, I'm going to pull that down to about the same size as that box. And then the same for this tube. There we go. And then what we want to do is give us a way to select which one we should be using. So I'm going to drop down a switch node. And I'm going to put the box in for the zero input. The sphere in for the one input, the ID of one. And then a tube for the second input. And now what I can do is I can use that switch to select which object I want to use for a particular point. I'm going to turn all these guys off here. So what we can do now is use a copy stamp. Now this is what I do. You can probably use the copy two points and just pass the attribute. But I need to look into that. So with this copy stamp node, let's go into stamp. We'll stamp the inputs. And we're going to create a new variable called object ID. And we're just going to utilize this OBJ ID in here. So all you need to do is just put in at OBJ ID. Now with that, we can go and utilize a stamp function up here. So stamp, give it the node or the copy node that we want. So in this case, we just have the one. So it's just copy one. We want to get the variable name off of that. Object ID. And then the default. And you can see now we're getting a box and tubes and a sphere. And now the tubes are oriented along the Z. Because remember that when we copy something to a point using any of these copy nodes, it uses the Z direction to orient the tube. So I want to point this in Z. And that'll make the tube sit up appropriately. And so with that, we're done. Now we can go and change the seed bound and change the object count number. So we can get to all cubes. Now we have mostly cylinders or get a nice mix of the three. Tubes, spheres, and cubes. Top quality CG right there. Anyways, it's a cool technique. It really comes in handy when you start to place things into a level using Houdini. Without having to hand place things and make it look random, you can use this technique to place anything from floor tiles to plants, tons of things. A good example is if you have like a sci-fi corridor, you can use this as a way to randomize which modular piece you want to use for the walls or the floor or the ceiling, those kinds of things. So that's what I wanted to show today. Hopefully you guys like that. Thanks again for subscribing. And I will talk to you guys in part 5.