C++ OpenGL Tutorial - 22 - Bounding Regions/Collisions

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody and welcome back uh to another opengl stream and uh for those of you who tuned in last thursday you may be wondering well michael you have the same title and that is intentional because in the last stream uh when we did this i there were some inaccuracies in there um uh there was code that was just outright wrong and then i did end up realizing a couple of errors um and how to fix them after the fact so i just figured i'd redo the whole thing and um and just uh you know make those errors correct or correct those errors um so you don't necessarily want to make a second video which will say oh go to this time here but for anyway we're just gonna go through it so today we're going to be learning about bounding regions and how to use them to detect collisions so what is a bounding region well in graphics people use regions it can be any sort of shape it can be a box a sphere or any sort of complex polygon and it contains every vertex of an object so if you see in this model here you can think about where these triangles intersect those are the vertices and all of these boxes contain every of those vertices and like i said they can be as complex or as simple as you want them to be um the most complex would be the model itself because the model has every single face in it so every single vertex and you know you might be thinking well that's a very complex polygon because i mean with the sphere there's like several thousand indices more than ten thousand uh so it becomes very complex to actually um to actually do calculations with so what we do is we make less complex shapes to represent the bounding area of these of these models and it turns out that you you're mainly going to be using a box or a sphere and this makes calculations a lot more simple um but as we do go more complex it it does take some more computing power um like i said so you know with if if we were to have the model as our bounding region and we try to do collision detection we would have to brute force every single um triangle which would do be a thousand to the thousandth or whatever you if you just did two so that would be a lot of them um but if you just have a box the calculations to detect if they're overlapping or become a lot more simple um so why do we use them like i said collisions it's the which is essentially just an intersection between two regions now there is one solution that people have found is that since these models that you generate for your game are going to be a lot very complex with many many polygons or many many vertices some people might create what's called a collision mesh or collision model and what these are are simplified regions that essentially contain every single vertex but they're just very less complex like look at this thing right here um this uh column has 500 triangles in its base model and that's that's kind of small to be honest but the collision model only has 20 triangles now it is less accurate but if you do this it reduces the amount of calculations by so much it's completely exponential so you can do a lot of this stuff and unfortunately they aren't pre-packaged with most models you would have to create these by yourself um but you know when you do use when you do make your own game you're typically going to make your own models so you do have the freedom to do this yourself um okay so let's um address one error at first so in the last video when we did our instancing stuff we created an extra shader for the launch objects now what i didn't do was um i i kind of messed up with the shader activation so when we run this i didn't catch this la on in the 21st episode but the that troll that we wanted never rendered like that model should be there but it's where's the for there it is but it's just not there even though the spheres are now the reason why is because in our shader we are actually we actually have this shader activated right here so the so the instance shader um because we don't reactivate the the regular shader before so what it does is it calculates position time size we can actually just change this to a pose times a size and that would be the same thing but size was zero because we didn't pass anything in for the fourth uh attribute pointer so just put it as zero now um to fix that we're going to do to do a lot of just clunky um but essentially we're gonna have to activate each shader for each lighting thing and then when we render it and it's gonna be a lot of copying and pasting but it's going to make it better in the end um and i'm gonna introduce a solution for this at the end all right so all we got to do is you just gotta put shader.activate before where we set a value for the shader so here um for the direction light before each uh point light before that before this before the number of spotlights as well um and then activate it before we set the view on projection and the reason why is because in our shader class we only set the uh it only sets the value of the active it sets to this variable in the active shader so we have to make sure that the shader is active by before setting any values and then we do the same thing with the launch shader so put it there there now you have to be a little careful here so you have to put that there put it in front of this setting the number and then in flashlight what you have to do is you have to um uh let's see um what do you have to do you have to put it before there but then also say um s dot render launch shader zero and then paste activate it here again so you essentially just want to activate it you essentially just want to do the same thing for both shaders but in but independently you can't do that at the same time all right and then just activate the launch shader before we render and now we should get the troll model yes there we go okay so now uh all the lighting works with him um and that's all looking he's looking kind of dark i won't lie oh god do you think he has tonsil stones in here now i can do that all right anyway all right so let's get into the actual coding of this so um today we're going to be doing bounding regions and we're going to create a class to represent this so what we have to do is um i'm going to go into a source folder and i'm going to create a new folder for algorithms um this is just because i just want to organize where all the like graphics independent algorithms will be there we go okay um so this is gonna be where we put our collision algorithms and then we'll eventually put our awk tree in here as well so i'm just gonna go ahead and create um a header file called bounds.h a source file as well let me just pin that there all right all right so let's start in the header file and let's do our macros so if not defined bounds h define bounds h and if all right um so we are going to need glm for this because we're in need vectors so include glam slash glm.hpp and now let's go ahead and create a class so we're gonna have a class to model this bounding region so class bounding oops bounding region and we're going to have republican so for our purposes right now we are going to going to be using a box or a sphere for this um so in order to i don't want to create inheritance because that's going to be that's going to get very clunky with all the definite function definitions it's going to be annoying um so all we're going to do is we're going to have a type variable and i'll create an enum class up here so enum class bound types and then we're going to call one type of box in the other sphere so for the box it's actually called an axis aligned bounding box or aabb and i'm just going to set and then that's the box and then sphere for the second one so i'll just put axis aligned bounding a box all right let me actually just touch you real quick don't worry i don't have the brownie i i just have a little runny nose right now okay um so in each bounding region we want to specify the type so we're going to say bound types type and we'll specify that in the constructor or whatever um now for each type there's going to be different values that define that region for the sphere so sphere values it's just going to be a center and a radius so glm vector3 center and float radius i mean you can just see this uh general formula for sphere um i mean i i'm not finding it here but generally here it is oh no it's for a circle um but the general formula for a sphere only contains the center and the radius it's like it's like the general form of a circle just with a third dimension added um all right and then for the bounding box um we're gonna have a minimum and a maximum point the reason why is because it's easier to do comparison if you just have a min and a max rather than a center and dimensions because you don't have to do any extra calculations to determine if something is inside of that box so we're going to say glm vect3 min and glm vect3 max all right so now we're going to have our constructors here so for the first one we're just going to initialize with type and you might want to do this when um if you want to construct the bounding box like as you're processing a mesh and that's what we will do so we'll initialize it with a type and then we'll put in the other values after so we're going to say bounding region um bound types type and this will just initialize with the type um or we can initialize uh as a sphere so we'll pass in the values there so bounding region and passing a 3d vector for the center and a float for the radius we'll also initialize it as um an array axis aligned bounding box keep forgetting that and then for here we'll just pass in two 3d vectors one for the min and one for the max all right next we have two calculation methods so calculating values for the region and it's going to be as simple as just the center and the radius so center so uh this will return a glm vect3 so calc relate to center and then for the dimensions so calculate dimensions so this will also return a 3d vector because dimensions are have three components x component y component and z component it's essentially going to be the vector that goes from the minimum to the maximum of the box so glm vect3 um calculate dimensions all right i did something wrong okay all right for the next one or for the next couple of methods these are going to be testing methods so this is where we're going to write our collision algorithms and we are going to write them today because it's actually pretty simple with the sphere in a box um so these are going to be our testing methods so um first one is going to be determine if the region contains a point so determine if point inside so this will return boolean and it just contains point and we'll pass in a glm vector3 point oops next we're going to have to determine if a region is inside of a region and this is going to be necessary for our octree algorithm because we're going to want to determine if a one of the sectors contains a whole bounding region so we'll say determine if region inside so boolean contains region and pass in a bounding region br and then next we're going to do our collision so determine and if region intersects let me turn this up a little bit all right so this will be uh boolean uh intersects with and that'll just pass in a boundary region vr all right this is just slaps my god this song is always amazing you know what i did find is um i was uh looking for some new music and um i found the minecraft dungeon soundtrack which actually is pretty good and there are a couple songs that are slapper um unfortunately though there is no artist so i wouldn't be able to attribute it to anyone but that's once there is an artist i will definitely put play that on stream it'll it'll be nice to listen to because it's a little nice blend of there are some songs that are like a nice blend of minecraft and more in a more arcade style um like old minecraft music and and then an arcade style so that's that's pretty good actually all right well back to the uh code that was my little spiel for the day um so now let's actually write all these methods so i'm going to do so for in the source file bounce.cpp you can also just put this in in a hpp file it might be smarter but you know i'm just gonna do it like this so include balance dockage um typically my rule for either doing a header a separate header and source file or them combined is um i would use a a dot hpp file when i want concise code um or if i can't or if it just simply doesn't work like with templates you can it it'll give you an an unresolved external if you define a template function and then don't def and don't define in that same header file don't know why um well that is because templates are are defined at run time so it won't actually find it then um but um otherwise it's usually made it usually is better to put stuff separate them so like in the library or something people will know what functions belong to which class and they won't have to scroll through whatever like 30 100 lines of code there that's in a single method so it just makes it a little easier to read and it's also easier for documentation too because if you put all of your documentation in one class or in one file it's a little easier all right so let's go back to this so i'm going to paste all that stuff in there um align it properly and then i'm going to put my my bounding tag my uh or bounding tags i'm going to put my class tags on there on each method and then after that i will replace each semicolon with a set of brackets all right this is the most tedious part of uh doing this but i mean if if you did a hpp file you know you'd already be ahead of the curve all right um so let's start with the constructor so if you're initializing with the type all you got to do is just say type becomes type we're going to be using our kind of class initializer lists there and then for if you initialize as a sphere what you want to do first is initialize the type as a bound types sphere and then initialize the center to a center and then a radius to a radius just like that or you know what we can do i'm gonna do something really shaky here in order to in order to um take up less memory i'm going to say uh this is equal to 0 x 0 0 and these are that's an unsigned char and this is also equal to or this is equal to 0 x 0 1 and the reason why is because zero zero x zero zero is equal to zero and zero x zero one is equal to one and this is in hexadecimal and that just takes up less memory because you have 16 to the squared which is 256 which is only a single byte instead of four bytes for a whole integer so that just makes things a little a little less memory intensive um yeah all right so now off the tangent once again um for the if you initialize as a box you want to initialize the type to bound types and we'll say aabb and then initialize them in to min any max to maps all right all right so uh calculation methods pretty simple um let me just make sure i do this right so for the center um we're gonna have two cases uh we're gonna put this in a ternary operator just because i really wanna look cool and i wanna just flex my skills um but also just because it's easier to write so i'm going to say return type is equal to bound types a a b b so if it's a box we're going to want to return the average of the minimum and the maximum so to say that we're going to say min plus max divided by 2.0 float and if it's a sphere we're just going to return the center so that's just the vector operations there just vector combinations and then uh constant division or scalar division all right for the dimensions it's going to be um a little weird here so we're going to say return type is equal to bound types aabb and if it is a box like i said the dimensions are going to be uh the distance from the minimum to the maximum so we're going to say if it's a box return max minus min and otherwise return glm vect3 of 2.0f times the radius now the reason i do this is because when we want to render the bounding sphere of a sphere it's not going to be easy to do that because we'd have to load a whole model in and then draw it with lines so we're just gonna use a box and trust that it's the same thing or trust that that's what we want um so it turns out that if you just wanna box around a sphere you just multiply the radius by two and you get that in all dimensions or in all directions okay now for contains point um we are going to be uh doing a little bit of stuff here so we're we'll you're we're gonna have to treat stuff um a little differently uh okay let me actually no all right um we're going to treat stuff a little differently for each type um in these testing methods because it's not the same for each i mean that's pretty self-explanatory that was so circular reasoning god i hate doing that all right anyway so if type is equal to bound or bound types a a b b x and p t dot x is less than or equal to min dot or max dot x and then do the same thing for the other two uh directions all right that was pretty simple and now for the sphere so this is going to go back to the basic definition of a sphere so what is a sphere a sphere is essentially it can it is every single point in the 3d coordinate system that is a fixed distance or the radius a radial distance away from a center um and essentially if it's within the sphere that means that the distance is is uh less than the um than the radius so we're gonna say so if it's a sphere distance must be last float so float distance is equal to 0.0 f here and then i'm going to do something that we haven't done before and i'm going to be iterating through a 3d vector using a for loop now what is this going to look like so 4 into i is equal to 0 i is less than 3 i plus plus you can do this in a in a vector because a 3d vector in glm is essentially a structure and it's an array of three floats that's how that's that works so all we're going to do is we're just going to add the square or we should make this dist squared um so um so yeah the the distance squared um and we're going to add the the difference between the point and the center at each point so we're gonna say uh um dist squared plus equals and we're gonna say um center dot x minus pt.x times center center at i with the square brackets because it's an array it's actually minus pt at i times the same thing so center at i minus pt at i um we could do pow but that would just be calling a function unnecessarily and it's pretty simple and we don't we also don't have to worry about sign somewhere right here all right and i'm going to copy and paste this here get the sphere um you might be seeing what i'm creating here it's essentially a matrix of the possibilities it's it's a i fear i forgot what this is like technically called it's kind of like a it's like a payoff matrix and uh you know economics um or it's just like it's i mean it just lays out the different possibilities so in each of these methods um we are going to have um a fur let me actually just move all this stuff over a little bit oops that didn't move over so we're going to have our first box oh my god i'm sorry i really should have had this freaking um so let me just say uh before oh not that's too big so br one and then we'll have the second one over here so br2 um so there are four different combinations they can both be a box both a sphere or they can be either one um we're going to treat this differently for each possibility now you'll see that just have to be inside of the sphere or the box so it just has to contain min and maps i mean that kind of makes sense because there's nothing that's below the minimum and there's nothing above the maximum in the box and as a result um if it contains both it contains the whole shape so we're going to say uh return contains points br.min and contains points br.max oh did i lose connection hold on i'm just hoping that i'm oh no i'm good okay i thought i lost connection for a second there all right um yeah so now if we go back to our matrix over here uh and let's call let's let's say this is br and then the top one is this so the object that we're testing right now so the cloud the current class that we're in so when we say if br is aabb we are knocking out this entire um let me let me make these white so you can see the is there way to do that no fill there we go oh i know i need to make the borders oh come on table sign there we go that's what you want borders there you go look at that there we go okay so if when we test if br is an aab b if it's a box we're knocking out this whole row because it doesn't matter if this isn't a box or a sphere it just matters that br is a box so we've knocked out two of the four now we only need two more statements um so i can actually just say uh done oh it's in white what's up with that done and uh done that this is i'm sorry about the just the lack of preparation um yeah so done and done so we've knocked out the whole first row now the next one we're gonna do is else if type is equal to bound types sphere so if this is a sphere and br type is equal to a sphere so bound types sphere so if they are both a sphere if both spheres all we have to say is that the distance from the center to between the two centers plus the radius of br just has to be less than the radius of this so let me let me see this combined distance from our combination of distance from centers and br dot radius must be is less than radius i mean i'm just going to write that out so return the glm length so we can that just gets the length of the vector of center minus br dot center plus vr.radius is less than radius so let's kind of look at this in paint. or paint 3d so we have our sphere right here and let me get a new uh sphere in here and i'll make it smaller so if this were to can if this was contained in here i mean you can't see anybody all right let's let's how is that is that good aha it is so now it actually is outlined so that's nice so the center of the red sphere goes from here or the distance from the center of the red sphere to the smaller sphere goes from here to here and that distance plus the radius of this smaller sphere goes from here all the way to here and that combined distance is less than the radius of the of this sphere of the larger sphere therefore it is contained now if it was outside like if it was over here what you would see is that the distance from the center of the red sphere to the blue sphere is from here to here and then the plus the radius of the uh of the blue sphere that's larger than the radius of the red star therefore it does not contain it it's essentially just saying oh what's the maximum distance um or the max yeah essentially the maximum distance of any point on the smaller sphere and if it's larger than the radius of this sphere then it is not contained in this here okay now um that is knocked out so we did this one and now if we just checked if they were both spheres so that's this cell here now we have one sphere left so all we can say is just else because there's only one possibility that's left so else so if this is box and i'm speaking that that's just not english at all and br is uh a sphere you know actually i'll add my proper nouns there if this is a box and br is a sphere okay oh i want why do i keep losing connection i mean i'm hoping i'm not losing connection now the stream looks good oh it's just my phone then that's iron that's stupid as then okay whatever no i should actually reconnect that's i don't think that's good hold on i'm sorry about this connection okay we're all good there we go that's what you love to see all right um all right so if this is a box in br's this year we're gonna have a singular termination condition and that's and that is if uh does not contains point um br dot center so if the box does not contain the center of the sphere the center is outside of the box so center is outside of the box and therefore we can just return false and i mean that's it's relatively simple right if if there's no um i mean i mean let's go in here you see that the center of both of these spheres is outside of the box and that will work anywhere like even if part of it is inside of the box part of it part of it is inside of the if part of the sphere is inside the box the center still outside so therefore it is not inside the box completely this is only testing if completely so i i gotta actually change this to region completely inside all right so that's just a singular termination condition so now we know that the center is inside the box so what we have to do is for each axis so that x y and z um we have to say if the distance to each side is smaller then the radius return false i mean and that also kind of makes intuitive sense if the distance from the center um of the uh let me use the red one now if the distance from the center of the sphere to either side of the box in in in the x or y x y z independently is smaller than the radius that means that there is some section of the sphere that is outside of the box so all we're going to say is we're going to use our little for loop trick again we're going to say 4 into i is equal to 0 i is less than 3 i plus plus and we're going to say um if let's see um if um [Music] the absolute value of br or of max at i minus br center at i is less than uh br.radius because br is the sphere or the absolute value of br dot center at i minus min at i is less than vr.radius return false and otherwise we're just going to return true so at the end of the else statement just say return sure so that determines if region is completely inside of the region so if okay so now we've done the contains and next we're going to do the region intersection so this is a partial contains or not a partial contains but rather or yeah since we're working with 3d objects that means that the volume will partially contain the other region so partial containment i can't speak english today okay let me just put this over here all right so once again uh we're going to be um having a evaluate four different cases and it's going to be kind of annoying but that's how that's how it's going to work so let me just reset our little matrix here oops no god damn come on no damn let me come on let me just select this stuff come on ah no there we go okay that's what you're about to see okay so let's start with um if they're both a box so if type is equal to bound types aabb and br.type is equal to bound types aabb so this means that they are both boxes and as a result they must overlap on all three axes and this is actually going to be the same for all of them they have to overlap on all three axes so just a general thing overlap on all axes this is going to be a general this is going to be something that we see in all in all four cases actually um so essentially we're going to say um overlap on all axes i mean i'm just all right so both boxes whatever all right so first thing we're going to do is we're going to calculate essentially the radius of each box and i'm not i'm you can't see me i wish i had a webcam now but i'm putting radius in quotations because it's not actually a radius it's just half of the dimensions it's essentially the vector distance from the center to either the min or the maximum so all we're going to say is glm vector3 red is equal to calculate dimensions divided by 2.0 float and this becomes the radius of this box next we're going to say glm vector3 rad and i'm just going to say br is equal to calculate or br dot calculate dimensions divided by 2.0 float and this is the radius of vr i'm just using nothing for this and then br for the parameter that was passed um next we're going to get the center so glm vect3 cent cent all right center let's say that is equal to uh calculate center and then glm vect3 br or center br is equal to br.calculate center so this is the center of this box and then this is the other one is the center of br um okay so now what we are going to do is we are going to get the distance between the centers so glm effect 3 distance is equal to the absolute value of c minus um earth's center minus center vr and what you you actually can use an absolute value in uh a glm with the vectors because they have they have actually overflowed that um that function to allow vectors and essentially just makes everything positive and we only care about the positive value here um okay next we are going to uh say we're gonna now test to see if in each on each axis if the distance between the centers is greater than the combined radius once again i'm putting radius in quotations then there is no overlap on that axis so i'm going to say four into i is equal to zero i is less than three i plus plus oh my god oh i can't type um so we're gonna say if the glm length wait what am i saying why am i putting length there there is no length there i'm i'm i'm on crack hold on so if distance at i is greater than rad at i plus rad br at i that means that there is no overlap on this axis and we return false and if we fail to prove it wrong we're just going to return true so failed to prove wrong on each axis so let's look at this visually so i'll leave that there um so if we take the sphere out of there um so we have our blue box and then let's get another box in here and i'll make this one red that's a big box all right so you can see that there's no overlap on all three axes you see that you send i mean kind of visual cues that you can see light coming in between the the two on each axis so we can see that coming in here right here and then also light here um let's say that this part was partially contained so i have to move it in there okay so you can see that is partially contained um and essentially intersects so the distance between the centers has some vector from here to here and then the radius of the two boxes there and there or here to here and here to here when you add those two together the distance between the centers is going to be um uh it's going to be um less than the combined radius i mean it kind of you kind of tell that but it's i can't really i can't really draw lines in here so it's going to be hard to explain but it's essentially that you just have to prove it on all that it is on all three axes so that's that um so in our matrix we we have did we have performed this check here so when they're both boxes now for the second case um we're going to say uh else if um the type is equal if this type is equal to bound types sphere and vr.type is equal to bound types sphere so if they are both spheres um and this is actually simpler than the other one and all you have to do to determine if the spheres are or the spheres intersect um you don't have to do any axes uh determine like axes um uh like test on each axis you just have to determine if the centers are far are further away from the combine than the combined radius so distance between centers must be less than combined radius and we'll look at that in a second so all it's going to be is just a one-liner i love these return glm length between center minus br dot center that just gets you the distance is less than radius plus br dot radius and glm length returns a float so you can compare two floats now graphically what this looks like is the set the distance between these two centers is whatever that distance is the radius from here to here is let's call that um let's say that the radius is 1 and then 0.5 so the combined radius is 1.5 but the distance between the two centers is about 2 probably i'm just estimating on my fictional coordinate system now if they would now if it did uh contain it i host that no no come on there we go that's what you'd love to see there you go now the distance between the two sphere the two centers is less than one essentially um and that's less than 1.5 that means that they intersect and you can kind of prove this mathematically um or just kind of make a conjecture about how it looks but um i mean it's it's relative it's not that hard to understand i mean you see that like as they as this as the radii just tangentially touch the combined radius will equal the distance um so if the distance exceeds then that means that there's no intersection and if it's less that means that there is intersection between okay now we have done where they're both spheres so we've done this one now we have the other two and but it turns out that these two are actually the same so we'll knock out both of these but it is going to be kind of weird because we're going to do them in two if statements and i'll show why so next we're going to say else if type is equal to bound types sphere so this means that uh this is a sphere and br is a box how do i know that br is a box because um we have four possibilities so if this is a sphere we have these two possibilities here but we know that br is not a sphere because we've already tested that they are that they if they're both spheres so it only leaves this uh this one right here this cell over here um so if this is a sphere in br is a box all we have to do is we're going to determine if sphere is above the top below bottom etc and then find the distance to the closest plane and we're going to get the square distance so distance squared so find that the square distance to the closest plane so what we're going to say is we're going to have a value for the distance so flow dist squared is equal to 0.0 float um and then we're going to iterate through our three dimensions so we're going to say four into i is equal to zero i is less than three i plus plus um so we're going to test to determine um where it where the sphere is relative to the box on this certain axis so if center is less than br center at i is less than br.min and i um we're going to say uh beyond min so dist squared plus equals br.min at i minus center at i times br.min at i times center and i this is more pythagorean theorem stuff if you want to look at 3d distance from i can actually just get it right now 3d distance formula it's just um the pythagorean theorem for 2d just extended into three dimensions um so we're essentially getting the distance to the closest plane um in this axis next we're going to say else if center at i is greater than vr.maxiti so it's beyond the maximum we're going to add dist squared plus equals um center center at i minus pr.max at i times center at i minus vr.maximum and once again we don't have to worry about sine or anything because um we're squaring something otherwise it's going to be inside and we're not going to do any other calculations for here because um we don't care if it's inside then we don't want to subtract anything or add anything there and you'll see why in a second um so at the end we're going to say return dist squared is less than radius times radius so what we're essentially saying here is if the distance to the closest plane it could be the top bottom front back right left there's six planes on a box if the distance to that closest plane is less than the squared radius if the square distance is less than the squared radius then that means that it is intersecting and so we don't really care if it's oh if it's inside on one axis like if the center is inside the box on one axis then then then we don't it it's just it's we we don't want to make it uh kind of count that towards the square distance because it's it's not really negative but it's not positive either because it's under the maximum but it's also also above them the minimum so it's kind of weird there but anyway this is that that's just this test here okay now we have done um let me see we've uh finished this one and we have this box this cell left and all we're going to do here is that's just an else once again because that's the only other possibility we're going to say this is a box br is a sphere so all we can say is just call algorithm for br defined um in preceding else if block reason why is because if we say return br dot intersects with and then pass in a d reference to this so make sure you put that you put the asterisk there because that dereference is this or you know we can actually just pass in um oh no you have to put that um because it's just calling the reverse so now it's going to go here and say oh this which is br which was br is now a sphere and br the new br which was this is now a box you're just switching the spots essentially so that is um this one right here so we have done that all right nice so now um no i'm gonna go refill my water i will be right back oh i'm uh my uh all right whatever i'll just you know i'll leave this here for two seconds i'll be right back don't worry i'm back uh anyway hope you're uh is it monday geez i'm off schedule hope your mondays are going well it's last weekend i was i was fidgeting with a lot of code especially in this that i'll be presenting on either tomorrow or thursday um probably thursday i'm not gonna make any promises um but there there is a lot of cleanup that i was working on um and that's gonna break down a lot of code that we have to write as in the main loop especially and it'll make things a lot uh a lot um easier to read and easier to keep up with um yeah okay so now that we are done with the uh bounding region class um we're now going to go ahead and generate them so let me just find my code all right so what do i want to start with um all right so let's go into our mesh class so i'll actually pin the uh bounds there all right so for each um worst times you can have a bounding region for each mesh just because that's where we actually iterate through each vertex like when we load in models from a simp we are looking at each vertex in that mesh and we and we only uh we evaluate all the meshes independently and i mean like i think we yeah like you can think of each of these little areas as meshes and each box contains one of those meshes so that's how that works um so we're going to generate a different box for each mesh now let's go ahead and include that before i forget so we'd say in mesh.h include dot dot slash algorithm slash bounce up h and we'll have it as a public variable for now we'll say bounding region br um and then all we want to do is we want to add this parameter to our constructor because we don't actually process our vertices in the mesh rather we process them when loading the models that's going to be with a simp or if we self-define the vertices that would be with the cube or stuff i know this looks really messy and it's we're just adding more parameters to the freaking uh to the stupid to the constructors and i'm we are going to cut this down in a second i promise um or not in a second in the next video um so we now have to redefine our constructors so in mesh.cpp we just want to initialize brs br in here and that's simple as that just like that okay now in model we have to actually generate these meshes because that's where we pass in or that's where we call the constructor of the mesh um so model i don't think i have to oh in mono we do have to add one thing we're going to add a type of bounds because we're going to we're going to want to pass that type into each mesh we don't want to have some as spheres some as boxes and then store an effector it would just be easier to um uh just just have one bound type for each uh for each model so we're gonna have to include this file as well so include dot dot slash algorithm slash bounds and we're going to have a bound type in the model so bound types type or map bound type and then we will add that to the constructor as well we can also delete this empty constructor oh yeah where am i going bound type bound type and we'll set that to an access aligned bounding box by default oh bound types all right just like that um now we have to redefine our header constructor again so bound types bound type and we're going to say um initialize bound type as bound type so now let's find where we actually processed the mesh did i lose my spawn i think i did yeah i did oh no i didn't i'm okay so where do we actually kind of go through each vertex um it's um down here when we say pro in the process mesh function this is where we add all the vertex data from a simps data to our vector of vertices um so let's go ahead and create our bounding region up here so we're going to say bounding region br and we're going to initialize it with bound type and this is where the uh initializing what the type became useful because we're essentially going to create this mesh or the bounding region as we go through the vertices um and then all you have to do is just add it into the constructor for each mesh down here uh what this isn't familiar all right whatever okay all right now let's uh so now let's go ahead and start so they're going to be two different ways to um or i mean because we're using a box or a sphere so for each case actually we're going to have to find the minimum and the maximum points but what we do with those points afterwards is what differentiates two so we're gonna have our variables up here so glm vect3 min and i'll initialize it in a second with some really cool high octane and then we're gonna have our glm vec3 max hold on just a second and this one will be the uh um min point and max point so what do we want to set these two well you know i guess we could just send to the first index but what if there are no indices that will give us an error so what you want to do is you want to be really sleek here and what we're going to say is the minimum is going to be the largest float possible now how do we do that without being in without using limits and just converting into max to a float now what you could do is we did a little bit of this in our last programming challenge with the uh bitwise operators and if you take the bitwise complement of zero you actually get the maximum integer so what we're gonna say is we're gonna set the minimum value to float of the bitwise complement of zero and that is set and that is equal to the maximum float at first and the reason why this works in this algorithm is because if it's the maximum possible value all the floats in this array will be smaller than it so the first one we run into will automatically be smaller than that and then that and it will set it to a um [Music] and it will set it to that i mean this is completely unnecessary i'm just trying to flex once again but come on it's pretty pretty cool stuff and then likewise we're going to set the maximum point to the negative of the bitwise complement of zero because all points are larger than the than a minimum float so is equal to the midfield i actually don't think this is technically true because an integer is four bytes and a float is also four bytes but you know it works for now all right i'm not gonna worry about it okay so now let's actually go through the cell grid it's your simple um detect minimum detect maximum um algorithm so what we're gonna say is for each vertex four into i is equal to zero i is less than three i plus plus we're going to go through each or not oh i think i screwed up oh we have to use j for this one i think i screwed up in my testing i used either that might be a source of couple problems i'm not gonna lie yeesh that doesn't look too good okay anyway um so we're going to see if smaller than min or if small larger than max and if it is it becomes the new min or max respectively so we're going to say if vertex dot position at i j is less than min at j we found a new minimum so min at j is equal to vertex dot pose at j and likewise for the max but it's just in the opposite so if vertex hose at j is greater than max of j we have found a new maximum so we're going to say max at j is equal to vertex dot cos at j okay so now we've found the minimum the maximum points in our entire mesh we can process them so we're gonna go ahead and process min max for br um so the first one we're gonna do is just if bound type is equal to bound types aab um and if it is it's just simple assign max and min because that's all the bounding region is to fire that the box is defined by so br dot so we're going to say br dot max is equal to max and br dot min is equal to min and you can put those in reverse order just to keep it as is okay now if it's a sphere else so sphere we have to calculate max distance from the center i mean this what this means is we're going to iterate through each vertex again but the reason why is because the center might not always be zero zero zero for each mesh i i found a model where the minimum was a zero zero zero um so the maximum distance was to the maximum point but whatever radius that was kind of it it would kind of look like this if i go back in here i think you can i'm you you can put a 3d person yeah you can there you go that's what you love to see that's elon musk's son spooky so if we have it like this um oh i really wish you could make this transparent all right i need my gonna kind of put it like that so you can kind of you can kind of see it oh there you go that looks good so the center measured it from or the minimum was here and the maximum was up here but you see that this bounding sphere is way too big for this model so instead what we have to do is we have to find the new um center and kind of center the uh the sphere around that point so that it's let me just select this again oops oops so it kind of represents it more like that and there's no extra space i mean typically we're going to be using these for spheres so it won't be that discreet or that outrageous but you know you might run into them and once again you're all you're typically going to be designing your own meshes um so or your own model so that you won't run into this um so anyway what we have to do is we have to get the center so br.center and we're going to calculate the center between the minimum and the maximum and we already have a function to do this just going to be bounding region we're going to create a bounding region between min and max and we're just going to calculate to center just like that that's just creating a temporary variable to get the center between the two points and then once again we do our maximum variable so we're gonna have float max radius squared is equal to or we'll just set it to 0.0 fps we have to do our comparisons once again um so now we have to go between go through each vertex so for int um let's say unsigned into i is equal to zero i is less than mesh m num vertices i'm just using the same numbers as above just uh this right here um and then i plus plus um so we're gonna get a radius squared for this for this um vertex so float radius squared is equal to zero point zero f and this is equal to uh or this will be radiator distance for this vertex and we're going to calculate that distance just by saying four into j is equal to zero j is less than three j plus plus radius squared plus equals and we're going to get the distance so vertices at i dot position at j so the jth element of the position of the i vertices vertex because remember we have our vertices vertices in a vector that we've constructed over here so we've accumulated all these now we can just iterate through it so um that minus br dot center at um j times the same thing so vertices at i dot pose at j minus vr.center you can obviously use um power for this but i'm just gonna avoid the function call nothing again nothing against pow in general but you know all right now we're going to do our comparison so if radius squared is greater than max radius squared found new squared radius and it is proven that if the square of a number is greater than the square of another number or if the square of a is greater than b squared then a is greater than b i mean um i mean i cannot kind of just say if a squared is greater than b squared then this implies that a is greater than b or the absolute value rather but because we're in radius a radii the absolute value we just consider the positive distance that's just the radius so we're going to say max radius squared is equal to radius squared and then at the end we're going to say br dot radius is equal to the square root of max radius square now the reason why i don't do square root in here is because that's just cos that's like a another costly function call that we don't need when we can just compare the squares because if we're calculating glm length of the distance between the two that's going to be calculating the squares either way but it's just going to be taken taking an extra square root in the in the process so we don't have to do that and we can just do take the square root at the end instead of um every time in between all right so that's how you generate it for a mesh um i do remember that i we do have to add this somewhere else because with the not the box the cube we have to do with the cube um the reason why is because we don't actually have a synth model here so we just have to specify the mesh bounding bounding box right now so we're going to just going to pass in um we're going to say bounding region brz is and we'll initialize it with a minimum maximum now the minimum for this cube is negative negative negative 0.5 and the maximum is point positive part is positive positive positive 0.5 so i'm going to say um glm vect3 negative 0.5 f and then glm like 3 0.5 f and that should initialize as a um box and then we just add this parameter in there and then we should be let me just run this to make or build this just to make sure we don't get any errors of course oh right um when we initialize the cube we have to just give it our bound types a bb and we do that for literally every other one too because so uh cube the gun i'm just going to use all of them for as boxes except for the sphere because why would you use a box for a sphere when you have a sphere and then in our troll as well look at that as simple as that [Music] all right so now let me build it and make sure that we're all good and blah blah oh i didn't even oh god all right yeah just make sure that your syntax is right there okay we're okay all right so now now that we have calculated the bounding region we're not going to do any calculations with them yet we're just going to display it so all we already have the model do this it's the box so what we have to do is um where do we have to put this uh let me just make sure i i'm doing this right because this is annoying to do i'm i'm gonna tell you right now this is gonna be annoying to write because we have to add parameters left and right um um so let's actually get our box value and just put it in our main loop because our main function because we don't need it elsewhere and we're going to leave it like that and then you can also just remove the part where we add offsets and sizes to it like that um and then the second thing i want to do before we write any other code is update the box class i just want to um add a function called uh void add instance where we pass in we just get it um where we passing bounding region br uh glm effect 3 pose and glm effect 3 size so i'm just going to add use this function because we're going to call it several times from different places um so what we're going to say here is when we want to push an instance we're going to pass a bounding region a an instance position and an instance size and this already screams model array and i mean this is good this that we're going to be calling it separately from model array and then also model itself because they're two different things they're two different rendering styles so we're going to say positions dot pushback br dot calculate center time size plus position and then sizes dot push back br dot calculate dimensions times oh it's offset stop push back i'm sorry okay so this makes sense because we're just multiplying the size components together but here what are we doing if we just add the position of the center we are not scaling the center so we're we're going to be scaling around the existing center of the object but the center will not change so let's see that we have an object um let's say let's take this this little child let's say it's like that so the center of this is i'll just make the sphere really small and just put it right here so this center is about right there right above his little uh crotch reach oh that that's a child i can't say that i hope i don't get banned for that um so anyway we have our let's call that a a man how would that makes it more acceptable so what we're doing so what happens is if we scale down the the model you see that the center doesn't move of the bounding region itself for this instance is size because we're not scaling down every single vertex on the cpu we do that in the in the vertex shader but because we want to scale down the center as well we have to we have to multiply it by the size to get it right above his the man the man's the man above 18 his crotch as well once again right yeah yeah i hope that made sense okay let's go back into code all right so that was our ad instance now we gotta actually tell um opengl how to add this or what to add and what in ins and where to add the instances so we're going to start in our um model array class because that's the easiest because everything is already there um so let me just get the code um so we're going to say when we render the instance data we're going to say for each mesh we're going to pass in or we're going to add a box for each mesh for each instance so there's going to be for each instance there's going to be a a different set of boxes for each mesh so we're going to say 4 unsigned i'm in model array by the way in the render method um so for unsigned and j is equal to zero i'm using j because we already are inside the mesh loop j is equal to zero j is less than or we can say um let's let's change this variable to instances the size here variable to instances because i think there was a little bit of naming before so if we're going to say j is less than instances so for each instance j plus plus and we also have to rename this to instance instances so there were five or we're now using instances six times if you want to if you want to look at it's highlighted in visual studio right now if you just want to look at where to change it um so anyway for each instance we're going to say box push oh but i'm an idiot i can even add the parameter so we have to add in the box as a parameter so in model array we're going to pass in a pointer to the box because oh i need to include the box at first actually um so we're going to pass a pointer because we don't want to modify copy we want to modify the box instances itself so pointer to box so for each instance we're going to say box um add instance we're gonna pass in um model dot meshes at i dot br so the bounding region of this mesh and then we're gonna pass in the jth position and then the jth you know the jth position and the jth size oh make that position essentially oh i've got a scratch right on my itch on my shoulder blade i can't get it this is probably sounding amazing on the microphone isn't it let me just find something real quick hopefully that makes a little bit of sense about passing in the the box as a pointer all right we are all good um so the next thing we have to do is um we have to do this for the meshes as well for the regular um model rendering um so in oh i have so many files open so close out a couple of these um so in model.render we have to add three or no we only have to add one parameter which is the box right oh we're already it is has been an hour and a half so all right so in model render or we have to first include the uh model first so include um models slash box.hpp so we're in the model render we're going to add the parameter box pointer b box and then in model.cpp we want to do the same thing like that and then we're going to patch and pass in uh message.render we're gonna add a couple of variables so in between shader and do render or you know let's actually just go into mesh first and add these variables so um we have to include the box again so include models slash box.hpp so in the render we have to add a couple things so when we say box.push instance it wants a position and a size not of the mesh but of the entire object so we have to pass in glm vect3 position glm vect3 size and then we also want the box so pointer a box pointer box there so let's add these three parameters to the mesh.cpp file mesh.render so once again it's a 3d vector for our position 3d vector for size and then a box pointer for the box so we're going to say if do render so we only want to do this if we are rendering we're going to uh say box add instance and then we say position size wait no no the bounding region first so br position and that size all right so that should do that and then now we just have to add those parameters to the when we call mesh.render from model um so all we just say here is message.render and then pass in rb.position because the rigid body holds the position then the size of the model and then box okay um and then we have to add that extra parameter when we call model.render here um so just say um null pointer so in model array when we call model.render you can just pass a null pointer because we we're not telling it to render so it's never gonna so model isn't it's not going to call um boxes.pushback so we can just pass a null point to there okay finally we just have to add update our parameters in the main class and there's only two i think so we just have to pass in in m when we render our models just pass in the box oh oh we have to pass in a reference the box because it wants a pointer once again um and then do it for the launch objects as well so a reference to box and then for the lamps as well oh i need to add that the that parameter to the lamps too so in lamp.hpp just um add a box parameter right there and then box so lamps.render just add that box parameter in there just because we because we override the render method there i hope that we also yeah we got rid of that okay all right um so add to the box there and then what's going too on oh we have to update the lamp array as well god damn it so add the parameter to um the lamp array as well okay now we should be all good um the one thing we do have to do though at the end is just or at the beginning of each sleep loop we just have to clear the positions and uh sizes so we're going to say b dot or box dot offsets dot clear and box dot sizes dot there okay now let's build this and for our second oh son of a did i not include bounding region i did not all right in box on hpp we need to include bounding region so include dot slash dot dot slash algorithm slash bound side h and then this box add instance it does take three what all right let me just build this again hopefully all the errors go away all right oh and the gun oh we have to add the box parameter for the gun as well that makes sense what's your way to give us that oh well because i did another file okay all right so now let's build it make sure it works all right succeeded now let's run this times and you see the box but it looks like because this the troll is a very low mesh figure there's no like mesh anime skeletal animations but you can see for the lamp we see that there's an outline now let's launch an object you see that the box is outlining it just like that perfect perfect nice i'll put some links in the description later on about with higher models that have a higher mesh count so that you can actually see how this works it's pretty cool i like it looks nice um there was one last thing that i did want to do and delete that because we don't need it instanced oh um in box out vs you don't have to multiply the components individually i learned this um over the weekend that when you multiply two vectors you're not doing the dot product or the cross product you're just multiplying the two uh um the just the components it just does the components individually but you it does the same exact thing okay um so yeah that's pretty much it i have nothing else for anyone um i i really wish i had a better model for you other than this fat slug literal one two meshes with his long as arms that probably reached down to his feet but i mean this model does look pretty nice um yeah anyway um i have no promises about tomorrow but it's most likely going to be thursday when i when we do a cleanup stream and then after that i will finally be alleviating everyone's blue balls and we're going to be doing the octree next week that is a promise if there are no errors there's always an asterisk on there but i'm really hoping that once we clean our code up we can get the octree in there and start doing collision detection i mean we've already written algorithms but like actual collision detection so that's gonna be pretty fun um i have nothing else for you guys today um yeah that's about it uh i'll see you uh whenever you
Info
Channel: Michael Grieco
Views: 778
Rating: undefined out of 5
Keywords: C++, Graphics, OpenGL
Id: enB97Utgpwg
Channel Id: undefined
Length: 88min 0sec (5280 seconds)
Published: Tue Jun 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.