Spaces & Cross Product • Math for Game Devs [Part 2]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
last time we talked about uh scalars or one-dimensional vectors if you want to be esoteric about it uh numbers basically we were talking about the number line um how you got numbers from you know you have zero one two three four five and then up and then negative one negative two and so forth up to positive infinity negative infinity so this is kind of the conceptual number line right um then we extended that to two dimensions so we take that number line and then we kind of like flip it so now we have two axes so now we have two dimensions along which we have some coordinates uh so this allows us to have two dimensional vectors and vectors are incredibly fundamental because it's what we use for almost everything it feels like like we use it for space transformation we use it for the velocities for positions for orientations like we use it for so many different things so it's incredibly fundamental to like have a good grasp of vectors um then we talked about the dot products so maybe it's good to do like a very quick refresher on the dot products uh so the dot product is an operation between two vectors so if we have one vector a and we have another vector actually let's do a longer one b um if a is normalized as in it has a length of one right and this could be any length then the dot product between these two is the projection onto kind of the infinite line created by a here right um yeah so the dot product gives us the um this distance here so this is dot a b uh so it doesn't actually give us a vector uh it doesn't give us like it doesn't give us the whole vector going from from here to here and all it gives us is a scalar value for the length of this one um now it's not exactly the length because the length is pretty much always um the the length is pretty much always positive like in standard context length is always positive distance is always positive uh speed is always positive uh but in some cases it might be useful to talk about negative distances um so usually when you have these like weird negative things that shouldn't be negative you call it signed distance or signed speed uh or signed area and so forth so if you flip b to the other side uh then the projection here is going to be negative instead of positive right uh so someone asked if dots a b and dot b a is different no they give you the same result it doesn't matter what order you do them in the geometric interpretation of the projecting onto the other vector only holds if one of them is normalized at least one of them has to be normalized for this geometric relationship to be true so if whenever you do some sort of projection then pretty much always you want to make sure that one of them is normalized so that you can have the actual distance here in some cases you don't actually want to have it normalized um the effect of not having this normalized is that say say it's twice as long let's say a has the length of two then what's going to happen is that this distance is going to be twice as long uh so then it's no longer a projection like this you know then it's going to be something that goes goes twice as far away right so so then you're going to get this distance there's a very beautiful very beautiful line there you go that distance um however you want to interpret my scribbles um but yeah basically that's what would happen uh serie geometric representation of the tip tip of a being projected onto b um not really uh the problem is that uh it's sort of like a projection but then scaled by the magnitude of this one as in the length of b so so it doesn't really make sense um you would get a vector that sort of goes here right because that would be the the same length as this or not a vector sorry the magnitude here um the same thing as the magnitude here but swapping a and b you get the same results it doesn't matter what order you do them in but the crucial part is that one of them has to be normalized for the 90 degree right angle projection to make sense right but that being said there are a lot of cases where you uh don't use a normalized um vector here but for most cases uh you would have either one of them being normalized or both of them be normalized and if you use it graphically it makes it easier if you project a long one onto the normalized one if both are normalized it doesn't matter if both are normalized both directions uh give you the exact same uh well it's the same result but the geometric interpretation works both ways right now i'm very self-conscious about saying right too often thanks students geez good thing i'm not grading your assignments there we go okay so if we have two vectors we have a we have b in this case both of them are normalized they have a length of one if you do this then we can think about what it means to project each on to the other right so we take this one we can project it there and then the dot product gives us this um distance right if we project this one onto the other one we get the same distance here so it doesn't matter if um if both of them are normalized like in that case like the geometric interpretation works both ways but regardless of the interpretation or the visuals um projecting or like swapping the order the the arguments of the dot product doesn't matter it gives you the same results uh so that was a short recap on the dot products uh it's very important and good to know because like as soon as you know how the dot product works you can sort of work out a lot of the formulas that you otherwise would have to google for like if you're like oh how do i project something onto a plane or whatever but if you know the how the dot product works you can kind of work that out yourself and the more you do that type of math uh the more intuitive it's gonna become after a while and you're just gonna be way more efficient every time you do some gameplay code that involves like space positions directions and so forth three oh so that's the dot products we also talked a lot about vectors in general like how they work how they um add together and so forth i don't think i would need to repeat much of that so i think i'm going to skip to the assignments first assignment was to create the radial trigger that we created um earlier right when we were talking about how do you make a trigger where you're inside or outside and so forth so all we need to figure out is is this point inside a trigger of a given radius that is at some position in the world right so i guess we can just start by making a component for this radial trigger all right we don't need those we're just going to do everything in androgyzma so we don't have to press the play button because that's gross uh okay we're gonna need to use unity um editor android gizmos so first thing whenever i wanna do some sort of like in editor thing where maybe you have a level with a bunch of enemies or some objects where you want to be able to see the you want to be able to see the radius of whatever it is you're doing so so kind of like the first thing that i want to do is to make sure that i can kind of set up all the parameters in order to test my math right if i don't have all the parameters there if i don't have the visualization uh it gets difficult to test and you kind of like blindly write a bunch of code and then if it ends up not working you don't have any way of like verifying it and you have to like start again and like try to do all of the like visualization afterwards when you don't even know what's wrong so usually i like just setting everything up so that you have all the parameters ready um so in our case we we just have one parameter right it's the radius and we want to be able to draw this radius so that we can see what the radius is of this trigger there are various gizmo drawing functions there's gizmos dot draw sphere wire sphere cube and so forth there's also handles.draw um handles is in the unity editor namespace so usually you would have to um compile that out because if you're making builds uh this would just not compile it would scream at you and be like hey handles is not included in builds all right so we need to draw the radius of this object so we can do handles dot i think it's wire disk we have center normal and radius the center is going to be the position of this object right we're going to need to use these variables later so i'm just going to set up some variables so we have the uh center and that's going to be the the position of this transform yeah so so yeah that's the only way we need suffer so we can do center then we need the normal um that that's going to be the normal of the plane in which the disc resides which is a little esoteric right now because we haven't talked about 3d vectors yet but but again the the normal of a surface is a vector pointing directly outwards from that surface so the blue arrow in this case is the normal of my hand right and my hand can sort of define a plane it's a planar surface and specifying the normal tells unity what orientation the disk should have we've given it the position but not the orientation so the orientation is given by passing in this vector and that makes the disk go in around that axis sort of and it's going to be on the um x y plane instead of the z plane or whatever um because we're just doing 2d right now so all we need to pass into this one um is a vector that is pointing into the depth direction and you can do that either using vector3.forward which vector3.4 does exactly the same thing as new vector three zero zero one uh right and then we have the radius so the radius we already have that as a parameter cool anyway let's just verify that this works what a circle and then we can change the radius um oh random useful unity tip uh when tweaking parameters when you click and drag the title of the the parameter if you hold the shift you will increase it faster if you hold alt it will be uh slower and or like increase with with less of a step every time you drag the the mouse so if you hold alt you can make like finer adjustments than uh when you when you aren't holding it all right so we have to have that set up now we can set up the radius it's drawn at the position of the trigger and all of that reads so now now we're good now we can start doing the actual math in this um oh actually we can't do the actual math because we don't have a point to test with so let's set up a transform that we can use as our test point point tf our handle is lesser more performant than gizmos i think it depends on the handle handles have a lot a lot more like advanced utilities uh because the the handles have a lot of interaction stuff like click and drag and whatnot handles are kind of mostly supposed to be used for um editor plugins rather than rather than just using them in like android gizmos so it's a bit of a weird way of using them um but yeah i think handles could be more expensive in some cases gizmo is probably more expensive than others i'm not entirely sure but that being said they aren't free so if you are working on a very big game it can be very useful to make sure that they're only visible when you have things selected so andra gizmo selected is a function you can use to make sure that it's only drawn if we select this trigger right so now it's invisible unless it's selected uh so so there has been issues where uh when we were working at my studio we were making a game called budget cuts and it was kind of this huge game for a very small team and when we ended up with these like very large levels we had a lot of objects you can interact with we were showcasing like we were displaying the radius of interaction radii of stuff we had like boxes to mark things and triggers and like after a while you have so many gizmos that your editor is actually tanking in performance uh because you're visualizing too much right um so so it's not free and in some cases it's like you do need to make sure that you don't always draw the gizmos you can of course always toggle them in the viewport as well um you can turn off what gizmos you want to see here like per component um if you want to um but yeah but that also collapses the components it's a little annoying um but anyway something to keep in mind uh let's give this uh some sort of label let's call it radial trigger is there any way to change the thickness of a gizmo um and making it look good no not really for that you would need a vector graphics library um but um but yeah i know that they're like there is a handle saw draw line and i do believe that one has a thickness but i don't think it looks good um yeah i forget maybe it's the polyline that has thickness yeah this one has a width if you supply a texture you can also supply with here um but it's probably not going to look very good okay also thanks thor throws plugging shapes now we need a point to test with uh some dummy object that we're going to pretend is the um you know a player or some object where we want to activate this trigger right so let's call it as the object it's a great name for an object and then we should give it an icon so the again the first assignment we just need to detect are we inside or outside of this trigger that's what we're going to do so we have the transform of the points so let's let's make an object position dot position so now we have the center of the trigger we have the object position and we have the radius all we need now is the math to do this uh we're probably also going to want to like visualize this somehow so we can tell whether or not it's working um so an easy way of doing it is just coloring the handles based on uh whether or not you're inside right so let's let's make a pool let's call it uh is inside i'll set it to false for now until we do the math and let's do handles dot color equals is inside if it's inside we want to do color.green and otherwise we want to do color dot red so now we're going to be able to see this okay so now we have all the parameters now we can visualize this and now we just need to do the math so now that we have these two points um one thing to always remember whenever you're dealing with vectors or positions or any any vector 2 types or vector 3 types keep in mind like what vectors are and what their data represents the position of these two if you draw them as vectors they would be arrows going from the origin of the world to that position uh for both of these right so what we don't want the the like distance to the origin or anything like that right we want the distance between these two points in order to figure out how close the player is right let's do that so we first first need that distance so float not distance uh distance vector 2 dot distance between the center of the trigger and the object position now we have that distance after that we can then check are we closer or further away than the radius of the trigger so so essentially we are inside if the distance is less than or equal to the radius and that's kind of it but that's enough to to do this little little simple trigger script and then no reference exceptions are also also part of this experience uh so now we can see that it works we should also make sure that we can change the radius and it should still work predictably when changing that and it seems to do um yeah is vector two vector three distance while optimized i mean you can't really optimize it further if you actually want the accurate distance um well you could optimize it further by not using functions uh quite often if you if you if you're in a very very like micro optimization situation sometimes writing out the math yourself using floating point values instead of like calling functions and whatnot sometimes you can get a performance gain out of that but generally don't don't think about that until you have to right because it makes your code like almost unreadable and cluttered and annoying to work with right i wouldn't care about that until you have to but yeah usually if you have like a for loop of like iterating over thousands of objects in an update loop or whatever that's when you kind of that's when you need to start thinking about this type of stuff but otherwise i would just optimize when you need to all right should we do the second one let's make a new script uh what do we call this one this was a look trigger android gizmos so for this one uh we wanted to have a trigger that should should be able to activate when you are looking at it right where you have a player that is looking in some direction and then you have the location of the trigger and if the player is close enough to looking toward it we want it to activate and if it's looking too far away we want it to deactivate there should also be a threshold so you can tweak kind of like how how accurate you need to be do you need to look exactly at it or is there some margin of error there where you can look slightly to the sides if you need to um usually if you were to have that situation of requiring you to look exactly at the object then it would be useless because floating point position kind of dictates that you're pretty much never going to have an exact vector pointing towards an object because it's very hard to look at a point but if you look at something that has a bigger radius or something that has a bit of a margin of error it's easier and you can sort of imagine this being useful for stuff like uh maybe you have a horror game and you want to make something happen if the player looks at the spooky ceiling panel in this house or whatever then you want something to happen well it's like simple use case for um how to um how you could use something like this so let's set up that threshold so let's have a um uh let's have a threshold called strictness or something i don't know um i don't know what you call it but it should go from zero to one um preciseness i don't know um maybe field of view radius uh no because this doesn't work um this one isn't actually using a radius and it's not actually angularly consistent and we're going to get into that but we haven't talked about angles yet we're going to get into angles as soon as we get into trigonometry uh so that's going to be later today okay so we have our preciseness value and now we just need to set up kind of the boilerplate just to to get this up running sort of like the same thing as last time we need the um the uh trigger position so we're just gonna call that center and that's gonna be transformed opposition uh we're gonna need a transform and the object transform let's set up the object position okay let's set up the objects what did i call it zero this is the plural trigger look trigger let's reuse the same object let's just have one one object cool we have our look trigger the yellow one here and we have our player so whenever you need to solve a problem where it's like some geometric problem it's a relationship between objects you have positions and directions the the first thing to solving a problem is always knowing what information you have and what information you need to figure out so right now we don't actually have all information yet we have the positions of these two but we also need the direction that the player is looking right and currently the we we don't really have that we don't have that in code and we're not visualizing it here so the first thing i would do is to visualize the direction that the player is looking also we could also draw and draw a line between the the two just for visualization purposes so um so draw a line from center to object position also we should probably make sure that we have um reset the color so if we want to draw the the direction that the player is looking first we need to decide uh how do we decide like what direction the player is looking well a very useful way of doing it is using the um using the transform of this object because we can rotate this one in unity and we can see that we have the the transform has axes in and of itself right so we can let let's just say the x-axis is the direction that the player is looking i think by convention if you're making a 2d game the x-axis is usually the reference vector and if you're making a 3d game the z-axis is usually the reference vector for look directions so it kind of depends on how you set things up but so i'm going to use the x-axis in this case all right so let's draw the x-axis let's let's actually make it a red because the x-axis is red and then do gizmos dot draw line and now we need to again now we're visualizing something that is a pure direction and things that are just directions don't have positions right it's just the direction so so in this case uh we need to be careful about like if we're drawing a line uh where are we drawing it right in this case we need two end points if we're using draw line we could also use draw ray but i don't like draw rays i never use it because i like explicitly stating things so we need to we want to draw the x-axis but we don't want to draw it at the player right so we're going to do this at the object position should i rename this to player position maybe let's do that so we have the player position and then we want to draw it at the player position again plus the that vector right let's let's define that vector player look direction equals the object transform dot right so right is the x-axis and um up is the y-axis for what is the z-axis so we draw a line from the player to the player plus the look direction so what that means is that there's going to be a line that goes one meter out from the player there we go so now if we rotate this one we have a red line that is now directly aligning with the x-axis of the player okay so now the next thing we need to do is how to like now we need to figure out how to check if you're looking towards something or away from something and this is something we talked about yesterday it's one of the ways we can use the dot products remember how we talked about if you have two normalized vectors then doing the dot product between those two uh can sort of tell you how close they are to being similar versus looking directly away from each other uh so if you have the red vector a here and then you do the dot product between uh a and something that is like exactly at the same position the dot product um is going to be one i don't know why there's a big zero there that's confusing i think i just drew a circle that's on a different layer let's just ignore that big zero look at the one here okay so the dot product between a and the vector that's equivalent uh would just be one as soon as you start giving it a vector that's rotating away from it the value is going to decrease so you would get a value of 0.8 here and so forth um until you hit exactly perpendicular when you are perpendicular it's going to be exactly zero and it doesn't matter what direction you do this in it's the same thing in this direction too it's also zero if it's perpendicular in any direction and then you can continue this if you keep moving this vector over here you're going to start getting negative values until they're exactly opposite that's when you're going to get a negative 1. again this is if you are doing this with normalized vectors um not all of these numbers would match if they're not normalized but regardless of if they're normalized or not the perpendicular case is always zero no matter how long or short they are so that's really useful to remember because sometimes it's a bit of an optimization sometimes you can save a few cycles by not normalizing the vectors if the only thing you want to know is if it's pointing sort of in the same direction or sort of away from some other vector in that case don't bother normalizing unless they're like extreme in which case you might get weird floating point precision issues in the at the border but usually it's fine so so this is useful now because we want a look trigger where if the player is here and they are looking toward the trigger then we want it to activate if they're looking away from the trigger we wanted to deactivate so that's what we're going to use we just need to use the dot products so let's let's set up a float um i don't really know what this is should be called there's not really good term for this because technically it's not how close you are looking at it in terms of angles this is sort of just a weird projection thing but it still works for our purposes uh so i'm just going to call it lookness or something like that it kind of describes what it is and i like using silly names it makes me happy so i'm just going to call it lookness how much we're looking to wear this one right um one thing that's important whenever you do these types of variables if this is called lookness then the higher this value is the more look you have right so make sure that the direction of this um is correct i otherwise would be look awayness in case like uh one is looking away and zero is looking directly at it right so that's something that's a good thing to keep in mind to make sure that your variables are like um kind of consistent and in terms of the the direction that they're sort of hinting at all right so now we have lookness um so how do we figure out the lookness between these vectors well we have the direction that the player is looking uh we don't have the direction to the look trigger thor body okay we don't know the direction to the look trigger we're just drawing a line between them so let's get that direction um so we're not quite ready for to do the lookness yet so we can call this a player to trigger direction yeah so all we need to do is we um we use the the position of the trigger and then we subtract the player position and the way that i think about this is sort of like it kind of looks like this should be center to player but it's always a reverse so keep that in mind in this case it's player two center um which is a little frustrating but that's the way it is and we need to make sure to normalize this if we don't normalize this then the threshold is going to be different depending on how close or far away we are in some cases that might be behavior you want now that i think about it this might actually simulate having a radius of the object um but i'm not sure i would need to do the math to double check anyway but in this case for the for our purposes um let's just normalize this uh so now we have the direction from the player to the trigger and let's draw that one too so let's draw let's replace the old line let's draw it from the player to the player plus uh player to trigger direction so now we're visualizing uh the two directions we have there we go all right we need to i kind of want to change color this one because uh it might be useful to to keep red and green for the state of the trigger like whether or not you're looking at it all right the x-axis is yellow now forget everything i said about the x-axis being red okay so now we have the direction from the player to the look trigger and we have the direction that the player is looking so now we can use these two vectors to figure out how close they are to each other right if you look at these two vectors we have exactly the same case that we had here right we have two directions we need to check how similar they are and the dot product is a very cheap way of checking if two vectors are close to each other in terms of direction and again it's not linear in terms of angle the way that we're checking this uh which is important to know uh but in in many cases when you're just doing a threshold it doesn't matter just like when you're checking distance it doesn't have to be perfectly linear if you're just checking a distance threshold if you're less than or close or or greater than something so it's kind of a similar case with the dot product here we don't need to check the exact angles it actually doesn't matter all we need to know is if we're within or outside of some threshold okay so we have our look trigger we have the the direction of the player and now we need to do the dot product so vector 2 dot dot player to trigger direction and the uh player look direction cool now we have the lookness but what do we do this well we need to use our threshold right for the the preciseness of this and again silly names uh if this is called preciseness that should mean if this value is higher it's more precise if it's lower it's less precise uh so try to be consistent again with the directions of your naming let's use preciseness as our threshold so um that would be a bull again um is looking at at it i don't know or just is looking so all we need to check is if lookness is um greater than or equal to preciseness um and that should be it so now let's color this one based on is looking there we go so now we can rotate this one and we can see that we are getting a green line when we're looking at it and a red line when we're looking away uh let's test the threshold let's make it very precise we're going to set this to 0.98 so now it shouldn't go green until we're very close towards looking at it there we go we can do even more 999. so now it's like way more precise now you have to look almost directly at it right and if we set the preciseness to zero then we only have to be um the angle between here only has to be less than 90 degrees that's the only requirement but if we go outside that's when it goes red so now we've made a very a very simple little look trigger um and one way of like thinking about this is that this could also be used for stuff like if you have a stealth game or something and you have like your enemies have view cones then you could use exactly this type of system where the preciseness would define kind of how wide the view cone is and then you can use that to see whether or not they would see a player given the direction to the player and the direction that some character is looking right um yeah was that clear any questions about that would shapes be useful to make those view cones yes can you also do this in 3d space yes the dot product works in any number of dimensions um the the difference it would make in 3d is that instead of a simple cone like this that goes toward infinity uh it would be a three-dimensional cone right instead of a two-dimensional like wedge like this uh but yes it will still work and i don't know how to draw there we go i'm still working on my drawing skills there we go so in 3d it would it would work just the same way it would also work in 40. uh can you make this code to look inside a circle radius i think that would be something that we can talk about after we talked about trigonometry wouldn't that just be adding a distance check uh no it wouldn't i'm pretty sure the the math might simplify to it uh but that's not how i i would initially uh do it freaking floats my lookness is negative um it could be that you you got the direction flipped um if the the player two trigger direction if you did this the other way around uh then it would be negative when i look away it's green i could just flip the colors i guess well it's probably good to make sure that the variables you have actually represent the things that they say they do right um so finding where things are wrong it's usually pretty important in case people want to reuse any of these variables but if you did any of them wrong just flipping the color or the result is going to make these variables misleading right does not work with three three vectors does plus work for three scalars and well they're not analogous so even though like you say the dot is a two operand operator um the dot takes two vectors but it returns a scalar it doesn't actually return a vector so you can't just do the dot product between something and then use that as one of the parameters for a second dot product right um so you would need to interpret it some way that is not just a pure dot product i mean you could kind of look at the definition of a dot product and just shove in one more argument there for one more vector but then the question is like yes you can do it mathematically but what does it mean like what does that give us is there some interpretation of that that's useful and as far as i know there's not but i could be wrong um how would you translate it to using an angle instead of a preciseness value we're going to get into that as soon as we get into trigonometry uh trigonometry is going to be next up we're going to talk about space like space transformation and matrices and after that we're going to get into trigonometry and angles so we're going to we're going to return to this issue or this this problem at some point and once we're talking about angles a data structure is used in games a lot stake linked list i don't know what the stake thing is um but linked lists yeah they're used a lot um i mean i guess it depends on what you're doing and what data structures you're talking about um yeah linked lists are used a lot arrays are used a lot uh tree structures are used a lot especially in like spatial optimization for like octrees kd trees and that type of stuff yeah lots of data structures oh stacks um yeah i mean you could have a you can have stacks as well uh one example of something that i did was so so in my game that i'm working on i have a level editor and in my level editor you can you can place objects you can manipulate objects they're kind of like beznia curves that you can manipulate and for every action you do i want to be able to undo right so what that means is that every time i do an action let's say i move this there then i basically have two stacks there's the undo stack and the redo stack so if i move an object this action is going to get recorded on the undo stack so now we're going to place that action there and we can move another object that's going to place one more action on the undo stack and so forth the more things we do the more things get added to the undo stack when you press undo what happens is that we pop this off of the undo stack and we place it in the redo stack so that is going to move into the redo stack um if we if we keep undoing it's all going to be popped over to the redo stack if we redo the other way around happens we move it back from the redo stack to the undo stack um so so i've used that for my undo system in uh in my game so so yeah stacks can be useful in some cases i don't use stacks very often this is kind of more of an exception uh but it was really useful for for this type of system uh this android gizmos update when you move objects i'm trying to use if statements operator and it doesn't update um on-draw gizmos is called um every time the editor is updated or every time any of the values of your object changes i think it's like um andra gizmos happens every time the scene view has to repaint and there are like there are different cases where the scene view needs to repaint as in re-render everything that you can see but generally android gizmos sort of kind of function like an update loop um except it doesn't it doesn't update the rendering if it doesn't have to is the redo stack emptied as soon as you add something to the undo stack yes yeah because technically the um technically the the like undo redo action stuff you do um it's kind of like you make an action you you do another action and then you do another action and then if you undo you kind of jump back here right and then what happens is that this becomes part of the redo stack right but if you then do another action um technically if you want to be like neat about it you would kind of branch off and you would create another um undo operation here you do another operation and so forth um so like you could theoretically make a tree structure out of this uh but generally there's the whole like ui side of things of like how do you even navigate this tree right it's a very esoteric system and like explaining this to users is kind of complicated like because if you then undo this again let's say you undo these actions and then now you want to do some other actions then what's going to happen is that uh you have you now have three branches here um and let's say you want to undo back here like what does that process even look like right because you need to have some way of after you've undone this one to go either of these three pads but you only have one hotkey for redoing and then it's like oh when you press redo do should you like get this tree on screen and you can click the one you want to go down like generally this is like very over engineered and most people are not gonna need it um just for like those few cases where you're like oh god damn it i made an action i can't redo the things anymore um usually it's not worth it in terms of like um workload and trade-offs and um indesign right all right i think we're ready to move on then so now we're gonna talk about another very important um very important concept when you're making games so we've talked about the uh the number line right you have the um kind of the x-axis and you have the y-axis and usually uh when you're looking at objects in unity uh all you're seeing is like these two arrows right you don't actually see the infinite lines like spanning all of the observable universe you just see these arrows right and it's the the iris you have when you select an object and what these arrows are showing at least when your gizmo is set to local and your location is at the pivot what these are showing is the position and the uh the space of this object uh so if something is a child object of this one and it's moving along the x-axis it's going to move along this red arrow right so what these two vectors are usually called uh is that they're called basis vectors and basis vectors generally not always have a length of one so these arrows kind of point to um the very first number in the number line and obviously this would continue to two and three and so forth right but as a shorthand for displaying coordinate systems we can use these arrows in order to like think about different spaces the default space whenever you're working in games is called world space generally depending on in what context you are if you are drawing the rendering and then shaders um arguably clip space is default but we're not talking about shaders and rendering um so if you're working in a scene in unity the default space for everything is the world space right and world space is located at zero zero zero in the world and the axes are aligned with um everything you see up here right the top right has the is showing you the orientation of world space and world space origin is always at zero in in the world right and i have the wrong object selected so we can just there we go so so these axes are now aligned with the world space axes okay but where we for now we can just think about uh 2d we don't actually need to go 3d yet okay so now we have these basis vectors here uh in unity they're scaling when you get closer further away um but the space itself the basis vectors of the space space doesn't like care about how close you are in terms of camera distance right so these just scale for convenience uh but in actuality the coordinate system has these um has these vectors kind of inherently in the way that the system is set up so let's say we now have this uh world space actually let's not erase this just yet um maybe we can maybe we can be sneaky about this and then if we want to for completeness we can we can add the the z-axis here to kind of visualize the fact that generally in unity you would have three axes and not just two but right now we can just think about two axes so now we have world space that's great world space is useful we use that to position objects all over the world right but we don't only have world space we also have the space of every single object in the world right so if we look at this object um i guess maybe we should remove the look trigger thing so if we look at this one this one is a different uh set of basis vectors these are not pointing in the same direction so this one kind of depends on the rotation of the objects and they're pointing in different directions but if you make a child object to this one let's make it um blue there we go so if we make a child object and we set the position to 1 1 or actually let's just use the x-axis for now um so now this one is positioned at one on the x-axis and that's it and if we move the parent object this child object stays at the exact same position in local space but not in world space so we can move this one we can rotate this one and the child object has the exact same local space coordinates all the time it doesn't matter where this one is but the local space coordinates is just consistent um it does move in the world but not in local space so what we've essentially created uh or what essentially every transformer every object has a space and again space is kind of just an interpretation of how we think about positions and and orientations and whatnot right so quite often when you're working in games when you're doing math and you're doing like trying to figure out how close two things are to each other a really important thing is always figure out what space is this coordinate in that is super crucial and some of the most confusing bugs come out of using the wrong space especially when you're dealing with rotations and angles um so so like if you use the coordinates here of you know this blue dot has an x coordinate of one and a y and z coordinate of zero then that does not correspond at all to its world space location uh the world space location is like something completely different so you need to keep that in mind it's it's really important to to always consider what space is this vector in what space is this point in what space is this direction in and so forth so that's important so spaces um another way of thinking about these spaces is that we can essentially just take the existing the coordinate system and we can just put it somewhere else with a different orientation right so now we have another coordinate system up here so whenever you're thinking about this if you have a position let's say this one if someone asks where is this point like where is this blue point um it's kind of an ill post question it's kind of like well where in terms of what like relative to what space um if we're talking about local space then we'd be talking about this vector right here in local space we would have an x coordinate of two and a y coordinate of one but in world space it's entirely different it's this vector going all the way from here also that's kind of confusing should probably offset this a little bit in world space it would go all the way from the origin of the world all the way up to that point so that's the world space position of that object and that world space position is definitely not one two uh that is rather uh like three and uh four point something right so it's really important to know whatever like it's really important to know what space you're in um and if you're you're ever mixing up local space and world space when you're doing um vector math you're going to get very weird results um so be careful with this and sometimes it's useful to say you know whether or not a point is relative to another point um if it's relative to another space if it's in local space or world space and so forth let's say this is world space let's do another color okay so we have world space and then this um different applications use different terminology for this um sometimes you'll see object space and local space inter used interchangeably in some cases they mean different things um i think maya has a world space and then this would be object space and local space would be the parent of this object space because sometimes you can have a hierarchy where you have like multiple child object anyway it doesn't matter in unity call it local space object space that's usually what you call it um so this would be the local space of some specific object right so far so good any questions about this because we really really need to like super important that you understand this before we move forward who defines the local space uh local space is relative to every object um every transform has their own local space um and yeah that's basically it so so this is an object with an orientation uh and a position and then um that defines a space in which we can think about coordinates or place objects you essentially just said an object's transform as the origin plus rotation uh pretty much yeah it's just another coordinate system just like we have world space is axiomatically at some position if we go over here we can just kind of if we work in this space we can just ignore world space and then if all the coordinates are in local space we can do everything in local space right um so so this is something that is um so if you're if you're working with shaders for instance um then you kind of have multiple spaces applied in a row it's a very strange hierarchy but basically you go from model model space to view space to projection and then eventually you i forget which one is clip space i think this you can use these transformations to get a coordinating clip space um so like if you are doing things in shaders then there are many spaces that you are juggling and quite often you can optimize things by like not using world space for instance um because in world space sometimes you you're doing like an unnecessary amount amount of like transformations um so so it can be useful sometimes to just do everything in local space and then you're kind of um ignoring the world orientation or whatever because because sometimes you just need local space coordinates and then at the very end of all of your calculations that's when you can transform back to world space if you need it right so you had a you got an assignment assignment number three is very related to the things we are talking about here uh so the assignment was basically uh write a function that can transform between world space and local space and that's essentially what assignment three was and i did say that it was a bit of a curveball because we hadn't talked about spaces um so i'd sort of hope that you would either look it up or have an intuitive understanding of it um but but yeah anyway so that was the thing that we were gonna do so let let's do that let's just think about how we could approach this uh let's erase this one first our old position is stored in world space internally and then it's just local space converted when it's needed um we're going to get into that later once we get to matrices we're going to talk about that the internal storage is a little funky because they use matrices so we're going to talk about that later but in terms of like if the matrices themselves cache the hierarchy of transforms i actually don't know um i i do remember that there is quite a bit of an overhead if you have very deep hierarchies of objects so like sometimes a big optimization you can do especially if you're animating objects and hierarchies is to kind of collapse hierarchies a lot so i don't know if they cache matrices in order to save performance if that's what you were asking okay so the assignment you were given was um make a function that can transform from local space to world space in other words if we have this vector so this is the vector x component 2 y component 1. so we want to write a function that can take this coordinate this local space coordinate and convert that to this vector going all the way from world space to the same point but we want to express that as a world space coordinate which in this case would be like three and four point something okay i did world to local uh the assignment was to do both so now we have um now we have the problem that we need to solve and like i mentioned before we can look at the whenever you want to solve a problem the first thing you need to look at is what information do you have that you can use to solve this problem so what do we have um well we we have the position of this object we just haven't drawn it but we do have this position which is this vector right here then we have the local space coordinates of this vector so now we can try to figure out okay how do we get uh this one in world space uh but we do have these two basis vectors uh like this one right here this is trans form dot up this one right here transform dot right so we have these vectors they they exist and that's information we can use in order to help us figure out how to get this point but in world space so remember that we have the local space position of this object the local space position was the two on the x-axis and one on the y-axis so what we can do is that we can take this vector transform dot right and we can multiply it by the local space x-coordinate and what we're going to end up with is a vector going all the way to this 2 right here and then we do the same thing for the y axis in this case it's a 1 so we're going to get a vector that's exactly the same as as this one and now that we have this long vector here the kind of the scaled x axis and then we have the the scaled y axis if we add these together we're going to end up getting this blue vector in world space so what this means is that all of a sudden we we have this vector and then we have this vector two in world space and then all we need to do is add those up and adding those two together um just like we talked about before vector addition if you have two vectors and you want to add these together uh it's kind of like taking the moving one or the other to the tip or the other one and then you get this diagonal across this one um and that's what we're doing here we literally have arrows one after the other in the same space again that's important um so so using the basis vectors we can convert from a local space position to a world space offset um so that is a way we can get this vector right here and then all we need to do is add the position of the object itself which is this vector okay let's do this in practice because we've done a lot of done a lot of theory so so let's let's implement this presuming you want to see this implemented i'm guessing it might be useful okay um let's see maybe we can start out by visualizing the basis vectors so we're going to use this object itself as our as the the object that has the um as this object so the script resides on this one so transform.position would be this object or that position is it like getting the transforms to get the basis of the vector spaces what if the thing you want is not an object um what do you mean by is it like getting the transforms what if the thing you want is not an object um you can do this math without using a transform like these are pure vectors if you already have these vectors defined in world space um you basically have a coordinate system ready to go frane um i'm not sure if i answered your question why not use pythagorean and get the vector in world space um i'm not sure how that would help we would get the length of the hypotenuse which is not useful for this i think it did answer your question okay great yeah let's just visualize the basis vectors and um and so forth um let's see we're going to use functions now but you know what functions are this is not a problem um let's use draw ray this time uh position the right colored up red um up green it's now a very simple function is just to draw the basis vectors of something you might want to reset the color afterwards um okay now we have a simple function to draw the basis vectors of something so let's draw the basis vectors of this object so position would be transform.position uh then we have transform dot write transform dot up we might actually want to make variables out of this um um i guess we should do this one too [Music] all right cool okay so what we have now is object position is the the blue dot here uh actually maybe we should make this one blue just to match the diagram um there we go and then we have right and up so right and up in this case are that's the basis vectors of this transform and when you do transform dot write and transform that up you get these directions in world space and again whenever you have a vector where the base is not at zero you can discard that the the only thing that matters is the data that underlies this one so we have just visualized this one at this location for convenience but if we were to just draw the raw vector data we would have this direction down here right but we're just drawing it up here because it's easier to know what this direction actually represents right but it is in world space and that's important to know uh local space of this one um that would be zero on the x axis and one on the y axis because that's kind of axiomatically how um what those vectors would be in local space okay so now we should be able to see basis vectors if i recompile uh right so now we have a green line and a red line so these are the basis vectors and this time they actually have the correct length they're supposed to be one unit in length and so we can move this one around and change the the orientation and so forth um let's also let's also draw the world space because it might be useful to see where world space actually is right and world space um the draw functions always have things in world space so we can just say um vector 2.0 because that's the origin in the world um and we could do vector2.write not that one thanks writer and vector2 dot up thanks autocomplete for messing up my cut okay so now we're drawing the basis vectors for world space two so let's recompile and so now we can see world space down there all right neat so now we need a points in local space um let's see trying to figure out if we should just have a number input or if we should have an actual transfer it might be actually less confusing just to have a number input uh or let's call this point there we go local space point so we're gonna start by defining this in local space just like we defined this one as local space uh coordinates two and one right uh so we have the local space points and it might be useful to to draw this one uh so let's do gizmos dot draw sphere and we're gonna draw it um at the local space point with some radius and set color to color dot blue uh that one is now at zero in world space right um right we would actually kind of have to do the the math and that's spoilers i wonder if we should use the transform instead no actually this is good this is exactly what we want um because in order to show this one at the correct location we need to solve this problem right uh so now we have a a coordinate and this is supposed to be local space um but this one is now drawn at zero and it's obviously drawn in in world space because we haven't told it to draw anywhere else also that blue is kind of gross let's use cyan instead uh so how do we how do we transform this to local space because now um now we just have this in world space no wait actually this is the other way around because now we need to trust more from um no never mind sorry i get this mixed up all the time uh we're fine we're good so what we need is a local two world we have a coordinate in local space but we're drawing it in the completely wrong position uh so so let's try to define that function um the function is gonna be uh local to worlds it's a very realistic process of trying to work with local and world space yeah sometimes you just mix them up because like especially when you're drawing them in the wrong space it so easily trips you up um so that's why i'm always like really careful about like be specific whenever you're working in local space or well space about like what space everything is in okay so we have our local space points it is currently drawing at the incorrect location so if we set this to zero it should draw here if we set it to x1 it should draw here if we set y to one it should draw here right but it's not so we need to write this function okay actually let's just make a local function because we have all the variables here so how do we transform something from local to world uh we have some some points and then we want to return a new point that's in world space so this is what we talked about earlier that's everything we went through here so the first thing we want to be we want to want to get is this vector the blue vector right here in world space we have this vector in local space let's actually use the same data x2 and y1 so we have that in um yeah we want to get this vector right here and like i mentioned before the way you can do that is that you can use the basis vectors as in this one if you take the basis vector and multiply this by the local space x coordinate of the local space vector here you will get the world space x axis offset so that gives you this full length vector that goes all the way out to the tip of to the tip of this position in world space and then through vector addition we can do the same thing with the y axis and then we add these two vectors together and what we're going to end up with is this vector right here because vector addition is like taking this vector and putting it right here or because doing a plus b is the same thing as b plus a it's the same thing as taking this vector adding it on top of here and we end up at the same position and the vector we get out of this is this blue one right here in world space yeah so all we need then is uh to get the the blue one here so let's call that the um local world offset or something um so this offset is now going to be the uh basis vector on the x-axis that's the red one right here we multiply that by the local point um x coordinate uh that's this one right here and then we end up with this long vector and then again we want to do the same thing same thing for the y axis and then add them together so we can just add the y axis right after so up multiplied by the local space points dot y because now we want the y axis so now we have the blue vector in in world space um let's call it world offset it's shorter so now this represents this vector in world space which is the space that we want to work with but there's one more thing we need to do because um again whenever we have a vector the vectors don't have a base and a tip they just have the tip in terms of coordinates uh so what this vector really is in world space right now um is like this vector right here uh so this position is incorrect if we just use this value um it would just now work i don't get how you can't just use local point directly when we where do we draw it if we just use local space point directly which is what we're doing here uh it's gonna draw this presuming that this point is in world space uh but it's not right we want this to be a local space point uh but unity wants a world space point for their drawings for for all of their gizmo drawing functions so what's going to happen is that it's going to interpret this coordinate as a world space coordinate which it's doing right this coordinate right here is x 2 and y 1. so it's drawing this in world space but we want this to be drawn here and in order to do that we need to convert our local space position here into world space because unity's drawing functions wants world space um did that make sense um so so basically it's interpreting our local space point as a world space point which is incorrect so we get incorrect values so so basically this is the same thing as we're just saying uh new vector 2 uh 2 1. like there there's not really any way that the drawing function can know what space this is in so it's just defaulting to world space right and that's something that's really important to remember as well vectors don't have the spaces uh vectors are just numbers um so if you have like it's kind of like saying five and you're like five what like is this a coordinate is this an amount of objects uh is this um you know it could be anything so you have to be like clear about like what the actual coordinates mean and what context they're used in uh okay so that's why we need to write this local to world function because this is being interpreted as a world coordinate so we need to convert our local coordinate to world space uh okay so the world offset here we have now calculated um this blue arrow in world space but that again is just this vector um so we need to do something else we need to add this vector and this vector right here is the world space position of the object uh so all we need to do is do world space position plus this offset vector um so we can do return uh transform dot position plus world offset uh and transform opposition is a vector three so it's a little side right now there we go so now we have a function where we can um or we can convert from local space to world space so let's see if this works let's take the um here so uh we want to get the world space point after this um so let's define a variable so point royal space so we do local to worlds and then we take our local coordinates local space points let's be consistent world space points now we have the world space position now we're going to pass that into the drawing function and then when we go back now it's drawing in the correct location so if we rotate this one it's now correctly positioned because we've converted this to world space so that the drawing function knows where to draw this thing right and we can change this local space point here if we want we've set um x to one and y to zero um it's gonna be sitting here exactly like a child object would do if we had it as a child object uh like a transformed child object to this object right did that make sense it gets a little complicated when you need to think about like coordinate spaces like this um which i mean as you noticed i even messed this up so um yeah this is something that's like really good to practice and try to like figure out um yeah how it all works okay we're also going to do the other way around now we just did um local to world but we're also going to do world to local we're quaternions allowed for this because this seemed to work uh nope that's not allowed sorry i forgot to specify that i said you were not allowed to use the transformation functions um the point of this exercise is to make sure you have an understanding of spaces and the dot product so if you're using the quaternion or you're using the internal transformation functions uh then you're kind of like missing the point of the exercise um so i want you to not use the quaternion i don't want you to use the internal transformation functions i want you to like sort of um get an understanding of how the dot product works right and also the vector math right because the thing we did here was is kind of just pure vector math of just adding vectors and scaling vectors in the assignment you also mentioned taking rotation of the object into account what does that mean in this case um there is a naive version you can do where you if you want to convert from local space to world space you can just take one and subtract the other and then you have converted it but this only works if the two coordinate spaces have the exact same rotation um so if these two are aligned we can simplify our code uh in that case uh we we just need to subtract the position or add the position of this object in order to get the to convert from local space to world space um so so the reason we're doing the basis vector multiplied by the local coordinate and the other basis vector multiplied by the coordinate is because we need to make sure that we we take rotation into account uh if we don't do that then it's a simple subtraction uh or an addition in order to figure out local to world um so that would make the exercise pointless and too easy um yeah so that's what i mean by taking rotation into account oh someone's asking what is control id and handles functions so handles are generally quote unquote supposed to be used for editor gizmos that you can click and drag and handle id is used for identification purposes so if you want to like know which component you currently selected handle id is going to be the thing that that returns or if you want to set the keyboard focus or the mouse focus to some control um then you would use that index so it's kind of just a way of identifying uh handles and um yeah you could just do negative one if it's unused or whatever it worked for every rotation around the z-axis okay cool well gratz in that case um yeah i it's a very confusing function but cool i'm glad it works i guess like uh mathematically i guess it boils down to the same operations but math is really weird that way if you like we haven't talked about algebra like almost at all but if you really know algebra very well you can just shuffle things around and have like completely different interpretations of um what is actually happening in order to solve some problem um i personally um i'm not super good at algebra and i don't do it a lot and i'm very like i'm very visually driven uh so anything i can visualize i makes me happy but a lot of algebra is very abstract and hard to visualize uh so i usually don't like uh like when i write code i write it in a way that makes sense geometrically in my head all you did is algebra vectors are an algebraic concept okay what i mean when i say doing algebra is that you are you have an equation and you're shuffling things around using the algebraic rules and whatnot we haven't done that like at all or at least not explicitly so that's what i mean okay new question is how do we visualize this um okay here's what we're gonna do we're going to make a child object and we're going to set the child object's local space position that's how we're going to visualize this because then unity is going to do a lot of the math for us that we haven't gone into yet so okay let's see so now we want to specify a world space coordinate so whoops uh so we want to have a world space point and then we want to convert that into a local space points right um oh we also need the the transform there we go we might want to draw the world space point and now we can just draw it directly because now it's in world space so the gizmo drawing function is already going to draw in the correct position um but the thing we're going to solve now is what local space position do we need to place this object in order for it to match our world space position that's the problem now right uh so now we define coordinates for our world space points uh that's this uh big cyan thing maybe we should use a different color for the local space object it's going to be yellow um okay so now our goal is to place this yellow dot here using local space coordinates because this one is now in world space so how do we figure out what are the local space coordinates that this would have if it was in this space right um so essentially what we need to do is we need to transform this world space point into the local space of this transform all right um so let's make a function for that oil points um okay let's go back to the drawing board like literally not the the figurative version uh i don't know if we can undo a bunch of this because i kind of want the same thing but without the clutter uh it's just some there's some blue goop here we just have to accept that i'm not going to clean that up i'm sorry now we have another problem now we kind of have the the opposite problem where um we have a point and that point is in world space so this is now relative to world space um actually that's a weird example because it's very aligned there we go what a vector cool great so so now let's see so now we have a world space position uh if i have a world space position here then these coordinates are approximately let's see on the x-axis we have around three so we have three and on the y-axis we have like two points something sorry i wanted to be better with colors now two points let's say 2.5 for simplicity's sake okay there we go we have a world space coordinate so so this is very specifically the world space coordinates this is not the the local space coordinates so maybe uh let's position them by this vector so we remember that this is specifically the world space one uh okay so we have the world space position but what we actually want now is the local space position so the local space position uh from the point of view of this transform also very often referred to as frame of reference so whenever someone says transform frame of reference space all of these words are very interchangeable um oh matrix sometimes like transformation matrix um so so now given this frame of reference then we want this vector going from the origin to that one in local space okay so what we need to do to make this transformation is kind of the opposite or like the reverse of what we did with the other one uh so remember how when we transform from local space to world space um the first thing we did was to figure out how do we get the world space direction of this because the local space one is kind of trivial because we have those coordinates already uh we had two and one but then we want to convert this to world space and we did that by multiplying the basis vector with each component so the x basis vector multiplied by the x component y basis vector multiplied by the y components oh and then finally we added the position of the transform itself okay now we want to do the opposite and so so one thing we could do is we can kind of think about this just like in the reverse process so the last thing we did for the previous one was that we added the world space position so if we want to go from world to local the first thing we want to do is to make this point relative to this point and what i mean by making it relative to this point is that um it's still in world space but it's now going to be relative to this point in terms of the vector is the vector between the world space position of this object and the world space position of this object um so that gives us this vector right here i'm going to erase this because this makes it confusing okay so if we take this coordinate and subtract it by this vector we're going to get the relative vector in world space so we have this vector relative to this coordinate but the orientation of this one is still referencing these two so the coordinates are not actually in local space yet all we've done is subtracted the position of this one um so the space we're working in kind of looks like this right now because it's still aligned with world space um but not aligned with local space uh so now we have the world space offset of this one and now if you remember we talked a lot about the dot products and the dot products again if you have normalized vectors which just so happens that these vectors the basis vectors are also normalized because they have the length of one right and if you have a dot product where one of the vectors is normalized and the other one is not then what this essentially is going to do is that it's going to project this onto that axis and then what we get out of it is the technically the signed distance but the distance here is what we get with the dot product between the basis vector and the the relative vector we have over there uh that gives us the um signed distance here or no sorry it gives us this signed distance um very important um not this i'm sorry i messed up it's over you're not going to learn anything now oh geez i hope you didn't write that down uh it's going to be cluttered i hope you see what i mean um there we go so that's going to give us that distance except it should actually be accurate um now that we have this distance um what does this distance actually represent well this is the local space x coordinate right by projecting this we get a scalar value again the dot product does not give us a vector it gives us a scalar and that scalar is this vector projected onto this vector and the length here so what we need to do then is just the same thing but with a y-axis so we we do the same thing we project this onto the y-axis that's the this same equation let's copy that there we go let's make it smaller because it's it's getting very crammed here then we do the same thing but for the y-axis this time so what we're going to get out of this is now the signed distance here and again this is literally the y component of the local space coordinate of this position yeah so that's that's how we can transform between these two spaces um same how we use dot normalized vector for direction linear velocity defined velocity in a specific direction yes and we talked about that on the last stream and the stream is available on my twitch in case you want to check out yesterday's wait two days ago lecture in case you're interested to see how you can use the dot product for velocities and stuff um anyway so this is a way that we can then go from world space to local space all right i guess we should also actually implement this because now we've just written a bunch of diagrams and um it's it's not super practical so so let's write this function okay the first thing we did was to find this blue vector in a world space so we want we want to get this point relative to this other world space point uh so i usually um whenever i do something like this i usually call it the relative points um i don't know if that's good but just my internal terminology um so relative points is then going to be the world point minus the um the object position here in world space so that's object position and now we have the relative point so the relative point here is now this vector in world space okay and then we need to project this into or onto the basis vectors of the um of this transform so we have the the right axis and the up axis and they are right here and then we do the dot product between the um x axis basis vector and this world space relative vector and again these basis vectors are in world space whenever you do transform.write transform.up these are in world space if you want to get the local space basis vectors um that is literally just new vector 2 1 zero because this one is pointing to the right and that's it like there's not much more to it or vector two dot right so in local space the basis vectors are very trivial and doesn't really contain much information um so usually you would use them in world space so this is world space basis vectors of this object okay so we have the relative point and now we need to project them so let's start with the x axis so floats x coordinate or let's just call it x float x equals vector 2 dot dot and we want to project this relative point onto the x axis which is right and that's it so this is now already projected this into local space and it already handles negative values because again um if the dot product arrows if you consider like the green y axis here that one is pointing away from this one so this is going to be a negative value so this distance here is a negative distance which again it's a negative coordinate because it's below the origin on the y axis right sorry this origin cool so we have the x axis then we do the same thing for the y axis uh project the relative points onto the up axis or the upper basis vector uh and that's basically it then we can return new vector 2 x y so that was a very like a lot of theory for a tiny amount of code um so i apologize if it feels like i'm doing a lot of redundancy and repeating stuff too much but this is really important to like have it like baked into your head like exactly how the dot product works exactly how space works and all of that stuff um because even if you've done a lot of um even if you don't have done a lot of like space transformation stuff before you sometimes messes up anyway so might as well learn it properly um okay so we have world to local uh we haven't actually tested this hopefully it'll work unless i mess something up um this yellow object is a child object of this transform that's why it's automatically moving together with this one when we're rotating it and everything um and yes so all we need to do now is um we want to set the local space position of that transform which i believe we have assigned here so that's the local object transform and we have the world space point so all i need to do now is local space object transform dot local position uh equals uh world to local and then we pass our world space point in there so this should now properly transform from world to local there we go so now the now it sits here the child object is now changing position um even if we're moving this object here it's now changing the position of this child object to exactly match the world space position so if we look at the coordinates here it says 0.59 negative 0.89 which looks correct 0.5 is sort of halfway here um negative 0.9 would be down here somewhere on the y-axis um and if we then take this object and rotate it or something move it further away and now look at the look space coordinates uh 2.24 and 2.57 so it does seem to work and it's exactly located at the world space position that we defined here um regardless of where we put this world space position right um thanks there uh okay so let's see i'm trying to figure out like how much um how much i should talk about now um because we are soon going for lunch and thor is currently holding control so that is modifying my actions which makes things difficult all right i think we uh i think we can talk about i think we can talk about matrices let's do matrices uh so thor buddy you're you're kind of in the way matrices in math is a very broad topic and i personally know almost none of it so i'm going to talk about matrices pretty much exclusively in the context of space transformation there are other use cases for matrices uh but primarily matrices are used in a way that is called a transformation matrix um so if we think about what we we just did right we have our x-axis right we have our y-axis and we have our z-axis uh no wait that is incorrect that is uh not in fact how that works uh sorry i want to get this right because i don't want to draw incorrect stuff uh a little side note um the reason that it might be important to get this right is because uh different engines and different like um and well engines or anything where you use coordinates um they can have different coordinate systems um so if you are um looking at something like this um then these two are are using different coordinate systems and they use a different what's called handedness and because these are not equivalent uh and like you need to convert between these two in case you're like working in an application that has a different coordinate system um so yeah so so in addition to the handedness um that like the handedness can be different but on top of that different engines also use different vectors um to be up so for instance the unity is left-handed y up uh unreal is left-handed z up um so in unreal um you would basically tip this one over like that and then the z-axis over here and the y-axis would be here and then you would have the unreal engine uh basis vectors in world space um and this is different in different engines uh blender i think is right-handed uh maya and 3d max is right-handed um it's a mess and everything's a nightmare so you need to keep that in mind sometimes it's important to know the difference okay anyway that was a bit of a side note doesn't really matter in this case um but we'll get into when it matters it starts mattering a lot once we're talking about rotations so we have been talking about this thing called basis vectors right um like i mentioned uh it's the directions that these are pointing uh in world space or more precisely in the parent space of these so so if you are talking about or actually world space sorry so if we think about okay this vector is pointing in some direction uh just like this red vector right here this is pointing in the direction in world space and what is this well it's less than one on the x-axis maybe it's 0.9 and 0.2 or something but it has a length of 1 right so what these are are the basis vectors of this transform um and then of course we have the position of this object so the position of this object would be the vector going from uh world space origin to this object position right okay so hello there we have the position and these three arrows not only do these are these arrows used for um not only are they used for determining what is local space but these also define the rotation of this object if you are doing something in code or like unity has a bunch of objects has a bunch of transforms the actual rotation of the object is not stored anywhere um when you are modifying euler angles or quaternions those are fake they don't exist and they're all they're only there to help you do operations on these vectors um so in actuality when you are doing stuff with rotations the way rotations are stored and the way positions are stored and the way scale is stored is in a single data type called a matrix and this is actually really cool that this is kind of possible to even do this um so so the way that things work in games is that um are usually in games they have a matrix and unity it's called matrix 4x4 and a matrix is just a different way of saying that you have a 2d array pretty much so a matrix 4x4 has 4 items by 4 items did not draw that very well so i'm going to redo this um this is great what a grid isn't that neat so internally when you are talking about a transform in unity including rotation position um and scale all of that is stored in a single data type called matrix and now you might ask okay but how is it stored um so the way that this is stored is that we have talked about the basis vectors right and just like you know the basis factors we had before in the 2d case was something like this right and if you want to know you know what are the components of this basis vector well in world space uh i would guess on the x-axis it would be like oh point 0.9 and on on the y-axis it would be something like 0.2 uh so so these are the the world space coordinates for the direction of this basis vector so these two coordinates or if we are going to 3d which we are now we would also have a z coordinate in this case it would be zero so these three coordinates are stored in the matrix so the matrix contains the directions of each of the basis vectors so if you look at a matrix the x-axis is actually stored here this is where the x-axis basis vector lives in a matrix and otherwise these are just x y and z values you have x you have y you have z and you have some numbers here right um so if you want to define a uh a transformation matrix and you want it to be just the x axis this could be anything so we could use these numbers it might be 0.9 uh and it might have 0.2 for the y-axis or for the y-component of the x-axis sorry things might get confusing uh the zero so what these represent is the world space direction of this basis vector and then you just do the same for the other ones so so the y component would also have numbers here so the y component lives here and the z components lives here so that's basically transform.right yes uh this is transform.right transform.up transform.forward so if you have no rotation at all if your object does not have any rotation as in it's aligned with world space then the x-axis i would point directly along x and then it would be zero on the other two components of this direction and then the y-axis would point directly upwards and the z-axis would point only along the world space z direction and what you are looking at here is called the identity matrix um or we haven't we haven't gone through these yet so you could consider this to be an identity three by three matrix um so an identity matrix means that if we are using this to transform something it's going to be unchanged so this one is just sitting directly at the world space orientation right so when you are rotating an object it doesn't actually store quaternion components it doesn't store euler angles all it's doing is that it's modifying these numbers that's it so internally this is used everywhere for all transformations that happen um from local space to world space um to in rendering it's used everywhere um so this is kind of the kind of the magic construct that kind of handles all space transformation and rotations for us um quaternions are still used to apply these operations uh but when storing data and converting between spaces we're using matrices okay this is not a complete picture so um so now you might ask why is it four by four well it is four by four because we are not actually storing the complete data about this object the only thing we're storing here is the orientation we know where these axes are pointing but we don't know the position of this object so if we want to know the position of this object that is also encoded in here um so uh let me just maybe i should mark these somehow so okay so this specifies the orientation or rotation whatever terminology you want to use so that's the this three by three grid here okay so now the way the position is stored in these matrices uh is this column here so you have the position here so if you want to do the identity matrix then um you would only have ones along the diagonal so if you want to have a position at zero you would have these components right here um and these would then together define the position um okay cool so now we have uh we have a matrix and we are actually able to store the orientation of this objects in other words the world space direction of each of these um axes oh z should not be one sorry um skipping ahead um so so that's the the world space position now is at zero now that i fixed it um sorry for any confusion so now we've encoded the position and the orientation but we haven't done all of it yet uh we are missing scale uh so so what is scale actually let's do the bottom row first because this one is awkward and strange um the bottom row is um kind of vestigial it's sort of unused but for the math to work out it kind of sits there and it just exists um so it's like in 99 of cases uh you're gonna have zero in all of these and you're gonna have one here um in some engines and in some very specific like projection things if you're doing rendering uh you might have values here but for for the mo for the purposes of just linear transformations which is what we're talking about now you will only use this space right here the the extra row is more because the way the matrix multiplication is used or is defined in mathematics um makes use of these even though they might be zero and one here what would those four values represent uh coordinate shenanigans that i have no idea how it works okay so we're almost done so yes you might be asking where is scale so scale does not exist here if you put scale here all the math is going to break and it's not going to work the way that you expect it to so because again matrix multiplication is very rigidly defined in mathematics and it works in a specific way so so scale how does scale work the way that scale works is that you modify the orientation here you can modify the basis vectors and when you do that you automatically bake scale into it depending on what values you shove in here so if we instead pass the value of two we have now scaled this object to be twice as tall or it scaled this coordinate space to be twice as tall and by extension we have now also scaled any objects that happen to be rendering under this coordinate system and so forth so depending on what these values are that would set the scale um so to be more precise the length of this vector is the y scale the length of this vector is the x scale the length of this vector is the z scale yeah so so that's that's how how you define a scale and even non-uniform scale you know where our scale is different on one axis compared to the other ones so it seems kind of ironic that it's actually sometimes kind of computationally expensive just to know what scale you have on one axis because technically you need to calculate the length of this vector right uh will the magnitude of transform that right up forward because with the matrix magnitude i don't think so i'm pretty sure transform dot right up and forward give you directions as in normalized in world space so you won't actually get the scaled vectors there we are running out of time before lunch so i'm going to talk about how you can use this in practice um so let me just add that scale is part of this too so this is scale and orientation is defined in this three by three grid okay so this is how matrices work um any or rather how the data is stored in them we haven't really talked about how they work and how they're applied but we're going to get to that um okay any questions before we go for lunch so the values are multiplied by scale um kinda yes but it's sort of the other way around scale is defined by the length of these it's sort of saying the same thing um but but the the causality is flipped right like scale is defined by the length of the the the y scale is defined by the length of the y vector and so forth what about gimbal lock and matrices versus quaternions uh matrices uh don't have anything to do with gimbal lock they are completely separate um quaternions uh kind of solved the problem of gimbal lock and gimbal locking is a very specific problem when you're defining rotations using euler angles um and no we have not talked a lot about rotations we haven't even talked about angles this is just vector math and matrices so far so ignore bottom row for the most part yes the the if you um unless you're doing something very very specific um the bottom row should always be this um so so the bottom row is if you want to do some very funky coordinate systems that are non-euclidean or whatever what is orientation now again um orientation up here is the well quote unquote the rotation of the object this is a different way of saying rotation right this is defined by each of these components all of these vectors as in the directions that these have in world space they are themselves three values right you have x y and z and these three values are stored inside of this matrix right here and yeah like someone mentioned if you do transform.write you will get this vector which is the same thing as this direction in world space but transform.write etc i'm pretty sure that does not take scale into account so those are normalized uh which these might not be um shouldn't a row major matrices position be in the bottom row the shenanigans will be the rightmost um so there are a bunch of like separate conventions that different like in different contexts if you're doing things in opengl versus in unity then sometimes uh the row versus column is flipped uh so sometimes they might start the x axis here y axis here um and so forth which sucks and um mostly memory memory layout thing like in terms of how you access them in the arrays i would guess rather than how they mathematically are laid out um all of these values are floats yes uh if you're doing shaders these are going to be called more accurately i really like the shaders do this it's called float 4x4 when you are coding in um hlsl or cg it turns out i lied to you all uh you should never listen to me again unsubscribe this was cringe um i'm gonna try to correct my mistake you know you almost never directly go into looking at this actual structure or like getting um individual like cells in this 2d grid um so i'm not too familiar with those i just know approximately how they work and yeah so this is how it actually works uh it doesn't make much of a difference at all in terms of everything i've told you so far it's just that the layout is slightly different the layout is actually not in rows um so the x-axis does not lie here the x-axis lies here so they lie in columns not rows which is important because these should not be part of the axis so if we were to do this using a row layout the position would be down here which in some cases that's the way it is but in mathematics um and in some engines you would have a column layout um so so i'm just gonna i'm just gonna correct that um hopefully by just changing the axes of these there we go so this is the actual layout now we're now we're back i hope unless like these are reversed or something but it's whatever you get the idea all right so essentially the only difference um the this axis is defined in columns here um and and so are the other ones uh so the y-axis is this column z-axis is this column and so forth and then you have the position in this column also sometimes called translation um i just had to double check because i felt like it was a little bit weird that they were part of the directional vectors so i double checked and i was wrong so anyway i've corrected things okay so now you might ask yourself what is the purpose of storing it in this way in particular um you know why does this um this bottom row really exist the short answer is basically that you can do something with matrices where you multiply a matrix with a vector so you can do matrix multiplied by a vector and what you're going to get out of that is another vector um probably shouldn't be called v v1 v2 there we go um so we're going to get out of this as another vector um so if you take this entire matrix multiply it by vector which in matrix notation would be a column like this where you would have x and y z and w um so if you multiply these two together what you are going to get is you're going to transform this from local space to world space that's the magic of how this works um so the way matrix multiplication is defined makes it so that multiplying a vector with this matrix literally does a transformation using that matrix um and it presumes that this is the local to world matrix which it's not always you can have different matrices you can have a world to local matrix but the point is you can use matrices to transform vectors between coordinate spaces it takes rotation position and every all of that into account by just doing that uh so that's really powerful uh so we have been looking at doing this manually so far um but we could do this using matrices we don't actually need to use this of course but what we could do uh is that we could use the matrix to do the exact same thing i don't know if you want to see how you would do that or if it matters that much anyway so you might also be wondering uh what is w like what is what is happening down here uh my coordinates are x y z and what does the w mean so the technically if you want to do a raw matrix vector multiplication let's specify vector if you want to do a matrix vector multiplication then w is generally going to be either zero or one and depending on if w is zero or one you're gonna get different types of transformations uh so if a vector or if w is one you are transforming a point as in that's the stuff that we did here we have a point in world space and then we want to transform that to a point in local space if w is zero you're going to transform the vector and what that means is that it's not going to take position into account position is going to be discarded none of this is going to matter it's only going to take actually this is discarded um and it's only going to take the rotation into account um so if this is zero then you're transforming only the direction so that's only used for like um or not direction sorry only the local vector so that doesn't take position into account but you can use it just to transform directions from one space to another or transform relative vectors um in practice you're almost never gonna have to specify w manually because usually you would use transformation functions in unity um so in unity you would have a local position and then you have a world position and then if you want to transform between these two you would use functions in the transform um and the functions that you would use for that is there is one called um transform point uh so transform points would uh takes a local space position um and then you get a world space position out of that uh if you want to go the other way around then let me just copy this because this is a long word and we don't like long words uh the other way around if you want to go from world to local that is called inverse transform points it's kind of annoying that they're not called local to world and world to local so you kind of have to remember which is which or double check intellisense or the documentation uh to make sure that you're using the correct one in the correct in the correct case um so so these are the two main functions you would use and it's transform dot transform points transform dot inverse transform point so the word point here is is doing a lot of work it's very important to know which one you're using and why so what they mean by points is that it's going to interpret these as points and not relative vectors so that's the w component that we were talking about earlier where if w is 1 it's going to interpret them as points but if w is zero it's going to interpret it as a vector that is just relative where we don't care about the position we just want the same vector but in a different space so those are called transform vector uh there's a third one called transform direction and transform direction makes sure that the length is one uh so that it's always normalized um so this is useful to remember um so if we were to replace our code with that we can comment this out um there we go so our local to world instead of doing it manually um we would do um let's see we would do transform dot uh transform point and then we pass a local point into that uh so this is essentially a local world uh and then the world to local like i mentioned before um sort of the same thing it's just called inverse transform points what you're saying is if you multiply four by four with a vector four you're multiplying each column in the matrix with each row and the vector of w zero you ignore the last column of the matrix pretty much yes um i don't actually i don't know fully how it multiplies them but i would guess that it's equivalent to the stuff that we did when we did it manually as in we take the basis vectors and multiplying them by each component right so it would take the x component multiply it by this column y component multiply it by this column z component by this column and w component multiplied by this one so if that's zero the position is not taken into account then it adds them all up i didn't i'm not entirely sure if that's how it works but i'm i would guess that that's how it works yeah okay so uh most matrices if you just have a context and you do yada yada.matrix um they're going to be a logo to world matrix so that's kind of the default as far as i know um so so sometimes you want to do the other way around you want a world um a world to local instead of local to world in that case you need to get the inverse of the matrix um and i don't know how to calculate that but you can there's a built-in function in in matrices so if you let's say you have a well transform itself has the local world matrix right here and the world's local matrix in case you want to use them manually so if you have a local the world matrix you can do dot inverse if you want the inverse of that matrix um so then you would flip it um yeah so so generally if you want to transform coordinates this is how you would do it and this would automatically take everything into account would take a rotation into account would take uh scale into account everything is there right um yeah whereas if you were to use the matrix manually you would have to do like new vector four and you would need to specify the w component manually to like say which type of transformation you want to do if it's just a vector or if it's a world space position that you want to transform okay any questions about that an inverse matrix is a normal matrix mirrored um i don't think it is but i could be wrong uh no i'm pretty sure you have to calculate the inverse matrix like that's an expensive operation to do but i could be wrong i don't i don't like look at the exact math very often i mostly just use the existing libraries um but it's not just a matter of like flipping it along the diagonal or something i'm pretty sure because that wouldn't actually get you the world's local isn't that a transpose matrix i think so yeah oh was the distinction between transform point vector and direction clear or should i show an example of that actually i can just quickly mention it remember when we were transforming things in from world to local so in this one we were going from world space to local space we wanted to get this um this position in local space so in order to do that we initially subtracted the position and then we projected it onto those and everything like that right and we ended up with this vector down here so that means that we are transforming the point and we are interpreting this as a point that we then want to get as a point in another space if you do transform a vector instead uh then what you're going to get instead of this one is that you're going to get the the same direction like this um but in the local space here so so this would be transform vector whereas this would be transform point um and it's the same thing the other way around so it's mostly like i have a direction in um or not a direction sorry it works for directions too but you have a vector and you want it to be relative uh as in position should not be taken into account uh in that case you are just transforming it to the other space uh if that makes sense um because these two are not the same like if you look at the the coordinates here uh they're vastly different than these two coordinates right um so this would be a transform vector there's another one called transform direction which is pretty much the same thing but unity makes sure that it's normalized so after you've transformed it make sure it has a length of one so direction in unity is sort of a word that kind of means that um it's it's a normalized vector right um so that's the difference between a transform vector points and direction uh so that is like any time you want some direction in some other space you would use transform direction uh or transform vector um but if you want to point in some other space you would use transform points so it really depends on the use case uh so let's see i'm trying to think of an example um so so let's say i have um let's say i have my rocket in my little game you know the one that can like fly around it's got these little wings um and it's got this engine um all right so this rocket has a velocity right uh we haven't really gone into physics yet but uh you can represent velocity as a vector uh so say you're going in some direction um so velocity and unity is always in world space so if you have a velocity in this direction of some rigid body and let's say you want to know what is this velocity in the local space of this rocket because the rocket itself has a local space too right you have an x-axis um you have a y-axis but this velocity um maybe you need that in local space of the rocket so that you can do um i don't know maybe you have like some flags attached to it and you want the flags to animate in some direction based on what the local space velocity is right like that kind of stuff wherever you want to tweak something about this one where you need like how much is this one going to the left or right um in the local space of this rocket so then that's a case where you would use transform vector not transform point because that would mean something completely different because the vector doesn't have it doesn't represent a location it's just a a relative offset and a velocity right cool any questions so far my biggest pet peeve is when people call their velocity variable speed that is a little weird but you know what people are learning and it's a good learning opportunity is this be the magnitude of the velocity vector yes um velocity is a vector speed is the magnitude of the velocity vector so that the speed is just a scalar and in most cases speed can never be negative um because it's the length of a vector and the length of a vector can never be negative there are some cases where you might want to have the concept of assigned speed um but yeah all right we covered a bunch okay we haven't really talked about 3d vectors but i feel like everything we've talked about in terms of 2d vectors generalized to 3d it's exactly the same thing but we add one more axis um so i don't think there's that much more we need to say about 3d vectors unless you have questions about it but yeah like dot products all of that works exactly the same for 3d what's the use case for matrix 4x4 um the use case for matrix 4x4 um it's kind of like having a transform component in unity means that you have the overhead of having game objects and all of that kind of stuff right um but a matrix doesn't require a game object um so if you're doing things like um instanced rendering where you want to like draw meshes from code then you need to supply matrices to say where you want to draw them at what scale and at what orientation um so matrices are kind of the the purest form of a transform um it's not a component it's not like it's completely unrelated to um game objects right um so this is kind of the generic container for everything related to transforming vectors for matrices and so forth um oh i forgot to mention something which is probably kind of important we multiplied a matrix with a vector before right um you can multiply a matrix with a matrix if you multiply a matrix with another matrix that is equivalent to combining those two transforms so if you have two matrices in order then if you have like a hierarchy of objects in unity for instance that's the case where you have a chain of matrices that you then apply in order to end up with a single matrix that is combined that represents the child's child objects transforming two worlds so you can multiply matrices together in order to combine things as if they were child objects so you can even do stuff with hierarchy uh without having a hierarchy of game objects using matrices and you kind of want to code get that for free or at least it's easier you don't have to like do all the transformations yourself you can just multiply the matrices together and everything works um yeah so so this is just a raw data type that can represent transformations yeah and you would you you might use them a lot in one making doing shaders and rendering um whether you know it or not because a lot of the macros in unity use matrices all the time when you're transferring transforming points um and again in shaders you transform points a lot you go a lot between um you know local space to world space to tangent space to clip space to view space you you do that quite a lot in shaders so so that is something that um if you want to do like more advanced type of shaders a lot of vertex transformations those kinds of matrices are kind of ubiquitous and you need to like know how they function or rather how you use them will that get an average position facing for both matrix factors no it will get a combined transformation uh so if you have world space here and you have a child object here and then maybe you have another child object like here you have some some other objects um why is this drawing black there we go so you have another object here um let's say this one is a child of this one um then this matrix probably represents the transformation to go from this to this not to go from world to this or this two worlds rather so when you have this hierarchy of transformations like this if you multiply these two together you get the transformation that goes between these two so you don't have to use the intermediate matrix there so if you combine these two you then have a matrix that represents the full transformation from this space to world space and world space and back um whereas if you just have this matrix being relative to this matrix um then you would have to like apply them in order which can be computationally expensive so sometimes it's good to like cache the matrix that represents the entire transformation so you can like multiply them together to combine them if that makes sense um what is tangent space uh it's a bit of a that's a bit of a tangent uh that goes into more like shaders stuff but um very very uh short explanation if you have a surface this is 3d uh then uh generally we talked earlier about the fact that you have a normal of that surface right and that normal is perpendicular to the surface um right so this is the the normal and then like sometimes you need to construct basis vectors around rendering something on this surface so so for instance you might need to know what is this direction right here um so this direction which is the x-axis this would be the tangent because this one instead of being normal to the surface as in perpendicular to it it is tangent to the surface as in flush with the surface so that's the tangent and then if you do the full coordinate system uh you would get the by tangent here uh and here we have the normal um this is tangent space that's it um so if you are doing something like uh tangent space normal maps which is the most common form of normal maps uh you need tangent space in your matrix um because your your normal maps has a vector in tangent space but when you are in a shader you also need to know what is that vector in world space so what you do is that you use tangent space and from this you construct a a float three by three and this is a matrix uh so this matrix is um is only containing rotation uh sometimes called a rotation matrix where um it's only got these three axes and if you multiply stuff with this one you're only going to get the you can only transform vectors you can never transform positions because the position of this one is not stored it only contains the orientation information but that's all we need so so essentially what the tangent space normal maps contain the texture itself um has a bunch of texels here right and each of these textiles contain a normal pointing in various directions right so depending on where these are pointing uh we're then going to use the uh tangent space in order to transform these uh from tangent space to world space or whatever space we're doing lighting in rather um yeah so so that's what the normal knife contains and in the shader we will use uh tangent space in order to transform that um that's what tangent space is oh right uh this is a good time to talk about the cross products um the cross products that is another way that of multiplying vectors together the cross product is sort of a special case that you can do with 3d vectors there is a 2d equivalent but we're going to get to that later so all right so if you have um actually we can use this one if you have the normal vector and you have the tangent vector um then you might want to calculate this one you might want to know what is the by tangent uh like say you have the normal you know exactly what direction it's pointing you know exactly where tangent is pointing um but you need to know this one so there are a lot of like convoluted ways of getting it uh like maybe you can do something where like okay uh we take the tangent vector uh and then we rotate it 90 degrees around the uh normal and we need to use a matrix to do that and like that is over engineered it's too complicated we don't need to do that so very very simple explanation of the cross product um the way that i sort of visualize the the cross product in my head um is that the cross product of two vectors oh in math it's usually uh a and then an x b so this is how you would write the cross product um so this is cross um and then the dot product would be a dot like this that's why they have the names that they do um so that's the dot product um importantly dot product returns a scalar a single value because it's a scalar projection cross product returns a vector so what the cross product does is if you send uh for instance if you give this one the um the normal and the tangent that we have over there we are going to get the by tangent there we go um so more generally the cross product if you give it two vectors it will always return a vector that is perpendicular to both there is some exception if the if both of your vectors are pointing in the exact same direction like if they're equivalent the cross product will be very sad and it will return a zero vector which doesn't have a direction um but that's a special case so whenever you need a vector that's perpendicular to two other vectors the cross product will do exactly that and it is super useful for many many different things so a good example is for example if you are in a video game you have an fps camera and you want to look around the world quite often you need to use the cross product there in order to figure out what axes are we um like what axes are we rotating around and when we look to the right what actu like what direction do we actually want to look in another example would be if you want to um this is kind of hard to talk about without being like really good at drawing um because it involves perspective but anyway essentially in a lot of cases you have things like normal of a surface and then the direction the player is looking in which might not be axis aligned or might not be perpendicular but let's say you have the normal of the surface and you have some direction that the player is looking in and you want to know what what is the direction to the right and you can use the dot the cross product with these two some of the one of the things that you need to watch out for is that if these two are perpendicular and they are normalized then this one will also be normalized uh but if these two are not perpendicular so if you rotate up the red vector like up there then in that case the returned vector is going to be shorter so if we start rotating this one the output of this one is going to get shorter and shorter the closer these are together so if you want a pure direction you need to normalize this one unless these two vectors are perpendicular so the way that i usually think about this is it's a little bit easier to um to swap the axes around uh so if you consider it's it's sort of the same thing for all of these uh so this is my mental model whenever i think about the cross product um x cross y gives you z if they are perpendicular everything is going to work out the way you want it to um and that's sort of it so so whenever i think about the um whenever i think about the cross product this is what's in my head i always think about this um so i imagine x is the first argument y is the second argument this is the vector i'm gonna get um and that's it so sometimes if i'm like okay i have the i actually did that just now off screen where uh we had the blue and the red one right and i was like oh right what order do we have the blue one and the the red one or the red one on the blue one in order to get the green one well my mental model again i just do x is the first argument y is the second argument and then i get um z axis as the result of the cross product uh so if we're working with um the red and blue of this system then i can just take this one and try to figure out okay how do we get the resulting being the green one so now i'm like okay um this is a little complicated and convoluted i'm sorry so in this case i saw that okay we start with the blue one end with the red one and then we are going to get the blue one of this one as a result which is the the green one which is exact exactly what i did um here because i don't intuitively just know um which order we need to have these two in if you flip the order if you have this one and you take these two vectors um and you flip them so that they are in the other direction uh the this one is going to point in the opposite direction um so depending on what um which order you pass these in the result is going to point in different directions uh so the in the cross product case unlike the dot product uh the order in which you the order in which you pass the vectors in matter because you're going to get things pointing in different directions um yeah so that's how it works what dictates if the green vectors on the right of the red vector compare to the left so that is the handedness of the coordinate system that you're working in um the the cross product is sort of what defines the handedness of your coordinate system the way you implement cross product is your handedness so so quite often you can sometimes have these issues where like you're trying to figure out some orientation of something but it keeps being wrong because it keeps flipping and then you kind of realize that well um you need to define a handedness in order to know how to have a consistent coordinate system um so also an animation for this here's a pro tip if you search for freya homer twitter and then insert any math concept uh so if i i say cross product then you will you will find a tweet generally uh so here is a visualization of the cross products um so it is an animated version uh so you have the uh this is the x or not x axis i guess the red axis uh crossed by the green axis gives you the blue one right here so as you can see as they squeeze together uh the length of the resulting vector of the cross product in this case c uh shrinks right and if they flip direction the c is going to point in the other direction too so that's how it works and if you are if you don't have these like 3d printed gizmos or whatever uh then here's the tip um they're in mathematics there is a thing called the right hand rule and in physics um forget about that in unity we have the left hand rule uh so in unity uh unity is a left-handed coordinate system with a y up so you can use your literal left hand to figure out how this works so you can just go in order of your fingers x y z and you can sort of position your fingers like this so this is the x axis this is the y axis that's the z-axis so you sort of have something resembling a gizmo so this is really useful because now you know that the cross product between this vector and this vector is that vector so that's a way of like kind of visualizing things and trying to figure out um you know what would result in what given your input data um it's also a pretty cool gang sign so if you're left-handed crew or right-hand crew you can you can do your gizmos you know um anyway but both unreal and unity is left-handed so i don't know what that would be like blender maya or something uh source engine is right-handed um but yeah so that's a very useful concept um in addition to that because unity is a left-handed system whenever you rotate something you can also use your left hand to figure out what is a positive rotation around an axis so if you hold your hand like this sort of like a thumbs up your thumb is the axis and the directions that your fingers are curling is a positive rotation if you imagine your fingers being an arrow kind of curling around your thumb so your thumb is essentially the axis and this is a positive rotation um which is really useful because it's kind of annoying to like try it and then it goes the wrong direction and then you have to like change it and then recompile and then try it again so it's it's usually it's very it's a very handy tool get it uh anyway left hand rule uh useful uh use your left hands they're great uh how does cross product work mathematically i have never memorized that one um let's let's just let's just look it up like this there you go here's a bunch of symbols um this looks like it's unnecessarily convoluted though it's a bunch of matrix shenanigans um there you go go to go to wikipedia for that um i've never had to write a cross product function myself this is a right hand rule and they're not even using the thumb and index finger that's gross right handed is standard in math left-handed is standard in unity because everything is inconsistent and it's chaos okay so there's one more uh there's one more useful concept in um how the cross product works i guess we could do an example of something but it requires a bunch of setup which might be a little annoying anyway uh we could do that if you want but we're kind of running low on time and i would like to go through trigonometry before we end the stream today can you give another use case for the cross product um [Music] the thing is it's kind of hard to um hard to give one um oh yeah triangles in a mesh is a pretty good example um although this is a little esoteric as well but if you are making a mesh in in unity or in any other application uh you generally have vertices right and each triangle is a set of three vertices and edges if you have this normal in mesh data uh then generally there's a um there is a like the fixed way that the cross products or where you can use the cross product in order to figure out what's the normal of this surface because the um the mesh data itself does not contain uh which side of this face is pointing up versus pointing down like is this the back face or the front face uh the way that this works is implicitly uh depending on what order the vertices are defined in so if this is vertex zero and this is one and this is two uh then you can use the cross product so if you do the cross product between this vector and this vector uh again remember what the cross product does no matter what vectors we give it it's going to return a vector that is perpendicular to both um so and that's exactly what we want right uh sorry you just need to correct the planar the handles there we go okay so they're going to be orthogonal to each other or rather um the output vector is going to be orthogonal to both of the input vectors so if we uh give this vector um actually why did i not draw this one in green and that's not green i'm messing up i'm sorry so if we pass these two into a cross product the result of that is going to be a vector that is pointing in this direction i'm pretty sure let me double check uh no it's actually not i guess it you would flip one of them in the other direction um anyway the point is the cross product and the winding order is what defines the normal of a of a triangle uh so in this case we can instead of doing this vector i think it might use these two vectors instead um but if the winding order goes in this direction in a triangle it's called winding order which is the the order in which we define the vertices um again we can use the left-hand rule like use your hand the curling of your fingers is the winding order and the thumb is the normal and that way we can then figure out that this is the normal of that surface so so so phase normals are implicitly defined by the order that vertices are defined in meshes another use case for the cross products this is a little difficult to do without having like a um an actual game to do this in and it's kind of annoying to do this but you know what i'm learning how to draw so here we go look at this 3d terrain isn't this beautiful and then goes off into the distance somewhere wow let's see i don't know if you played a lot of uh overwatch or like team fortress 2 um but usually you have uh in these types of games you have someone who can place a turret right you have engineer and tf2 and torbjorn in um in overwatch so so let's say you want to place a turret and your game features uneven terrain um how do you figure out the rotation of the turret so okay so we might think about um so maybe you're standing somewhere uh somewhere here uh and you want to place the turret uh so let's say you want to place it here uh so what is the orientation of this turret now well all right for starters um you point to the terrain so we have a normal so that's a good start right so now we know that uh we have a normal vector which maybe we can use that as the up vector for the turret right um but what about the other vectors like how do we define the other ones uh there's an infinite number of possibilities for where the other vectors could point right uh so currently we just have a normal and that's not enough to define a full rotation so while this will say what's going to be the up vector of the turret it doesn't say what the forward vector is going to be so then you're like okay but well maybe we can use the direction that the player is looking um but the player could be looking like almost downwards right so if we do a side view you know maybe the player is looking down like that and then you have the terrain um bad example uh then you have the terrain and the terrain has a normal and then you have the uh look direction of the player and then you might wonder like okay so we have the look vector of the player but that is not orthogonal to uh to this one right um so what you can then do if you do the cross products between these two vectors um again you will get a vector that is perpendicular to both this is like so so so crucial um so let's say the player is looking towards the the point where they're going to place a turret um and then you use the cross product you use the cross product to figure out another axis so now you will get one that is pointing to the right or left i guess i'm going to ignore handedness now because i just want to do this quickly um so so now you have another vector that should be a little thicker for a clarity um so now you have the right axis here um and now that we have these two all we need to do to get the the last vector is do the cross product between these two and after that we now have a full rotation right and now we know how what orientation to place the turret in um that's another use case so and if you want some terminology for this um this is sort of because we did this as well as creating an x-axis um and sort of flattening this one to go along the terrain um this is called orthonormalization so there there are like built-in functions in various places uh where you can do this type of thing um but yeah so that's that's a useful thing cross product is orthogonal to both input vectors yes the result of the cross product is always orthogonal to the input vectors uh unless the input vectors are zero vectors in that case or if they are actually if the input vectors are parallel then the output vector is always going to be is also going to be a zero vector so the cross product between uh this vector and one pointing in the exact opposite direction is going to be a zero vector because the problem is that if these are pointing in the exact same direction uh there's an infinite number of solutions around this right uh it could point in any of these directions um there is no one solution for where a perpendicular one would point because all of them would be perpendicular um so that's why there's a degenerate case of vectors pointing in the either vectors being entirely parallel uh whether or not they're pointing in the same direction uh so that's a degenerate case of the cross product basically you're defining a plane in space and getting its normal yes um okay anyway i was gonna like do this in unity but it takes a while to like set up a terrain that's useful enough to i don't know um here's another neat use case of the cross product if you do the cross product between let's call this a let's call this one b they're not fully aligned but you know what that's okay um so you have vectors a and b if you do the cross product between these two as in a cross b like i mentioned before this is going to return a vector that is perpendicular to both of these let me check the left hand rule yes it would point in this direction so because again it's orthogonal it's orthogonal to both of these vectors but there's another property of the cross product where if you look at the length of this vector which again if we use the notation we used before a vector length if you take the length of this vector what you're going to end up with is you're going to get the area of the parallelogram that these two form in this region right here uh so the length of this one um actually represents the area of this plane right here uh so if you for instance want to use know the area of this triangle well all you need to do is you can take this and divide it by two because you split the parallelogram exactly in half so you can get the area of a triangle using a cross product only supplying these two vectors a and b so that way you don't have to deal with trigonometry or any of that garbage you can just you can just pass those vectors in uh if you just take a sort of downwards facing vector cross multiply by the normally you get the red vector parallel to the surface yes uh is it just that the red vector is shorter if the blue vector is facing a bit downwards uh yes so um like i mentioned before um if these are perpendicular like exactly perpendicular if a and b is perpendicular uh c is going to have a length of one assuming they're all normalized uh but if they start going close to each other it's going to be shorter um so quite often when you're doing these things you um if you're if you don't know that they are um you don't know that they're orthogonal then you always need to normalize it but it gets you the correct direction even though it's not normalized so you would do the cross product normalize it and then you then you can use those two vectors that were then found the blue and the red one do the cross product between those two and you end up getting the last axis of this one and now you know the full orientation of this object right so incidentally uh unity has a function called look rotation and look rotation has a built-in reference vector so look rotation presumes that it's going to use the world up vector as a reference unless you supply a different vector so this is why if you if you do look rotation with some character and you're looking like in that direction what unity is going to do internally is that implicitly it's going to use the world space up vector to figure out the full rotation that you want for the camera here right so it's going to do the cross product it's going to figure out you know what you want the up vector to be what you want the forward vector to be and what the right vector is going to be um so so internally unity is using the up vector here because again if you think about it quite often when you're defining a rotation it's really important to remember that a single vector can never define a full rotation a single vector is not capable of doing that because if if you think about how vector what information vectors contain they don't contain what rotation you're going to have around that axis and so you can never ever fully define a rotation using only a vector so that's why unity when you do look rotation it presumes that you want the role of the camera to be aligned so that it aligns with world up so that's what it presumes you can of course apply your own up vector um but yeah so if you want to do your own stuff and you want to align this to something else you would supply your own uh rotation there incidentally this is also a very useful way of constructing quaternions um there is something called a quaternion.look rotation uh where all you give it is a forward vector and an up vector and then you can just do the last one manually because it's always the same vector okay uh cross product thing what are we gonna do let's use android gizmos um so okay we wanna let's see um i guess the easiest thing we can do is just use this to raycast into the scene um so i guess let's give this some sort of new so we can see what's happening okay so let's see uh we want to recast so if physics dot breakcast um let's use transformed opposition transform.forward um and out uh all right hit there we go okay cool so we're recasting the scene and i guess for now we can just draw a line so um i guess we need the position so hit position um oh here's a hot tip by the way handles dot draw a a polyline is anti-aliased so if you want to do like a little bit prettier lines you can use draw a polyline so we want to draw it from the position to actually i feel like we should make a variable out of this um because i want to call this head position just to clarify that this is the head of the player right okay draw it from the head to the hip position and let's go back what a beautiful raycast isn't that neat okay just for i kind of want a line at all times even if it misses so so we're gonna we're gonna do another line from head to position to head position uh plus look direction which is going to be transform transform to forward um i'm so used to using my uh using shapes i keep typing draw but that's not how it works um okay there we go so now we can see if it misses at least so that's good um it's a little difficult to see on this one so i'm gonna turn down the lights a little bit it's a little intense why not use shapes um because if you go hey can you send me the code it's not gonna work unless you own shapes um okay so all right so now we just got the basic setup here um so remember that the goal was that we uh this red dot is torbjorn and we want to place a turret right uh and we need to figure out what is the orientation of this turret that we want to place there and like i mentioned before kind of the first go-to for this um is the uh normal of the surface um so uh so so let's visualize that let's visualize the normal uh so let's set handles color to uh blue and let's draw another line um actually sorry i'm just refactoring because it looks like garbage and i don't want to copy my code around too much there we go um [Music] because we're going to draw a bunch of normal ice vectors so why not um okay normal of the surface so they're normal to the surface uh in this case uh we're just gonna do um it's just a hits normal right it's hit dot normal so that's already supplied by the raycast data uh so we got the normal right there and so we go back here just to verify that we got the uh blue line we're drawing it in the wrong location and that's because we should try that hit position and not at the player um there we go that blue line is kind of faint so we're going to go with cyan instead uh cool so now we have the normal of the surface we are recasting against it and we can see that this very much looks like the normal it is orthogonal to the surface it's hitting right so now we were like sort of there because we now know that this is probably going to be the up vector uh of the turret that we want to place on the surface we know that for sure because we the turret has a flat ground and it has a defined up so we want to place the turret you know aligned with the surface but again the problem is what direction should it point after it's been placed on that surface because we can simply make it point the same way the player is looking because the player is looking like down into the ground or they could be looking in any direction right um very likely the player is not going to look in a direction that is aligned with the surface or like orthogonal to the tangent um or normal sorry anyway so we need to solve this somehow uh so again the kind of the first step is to do the cross products um of these two uh so so let's do that so actually let's save the normal over here if the player manually set the characterization though this would be enough right um not really because what is the default rotation if you don't have a default rotation then they're pretty much gonna like flicker around because you're just presuming a bunch of things um so if you were to use something like unity's um look rotation then depending on what part of this one you're placing it the turret would face downhill that would be the that would be the kind of kind of the default of this yeah so so you need to it really depends on like the situation right but you probably want a default rotation even though the player can set it manually right so so now we got the hit position we got the normal and that's just supplied by the raycast um okay actually let's draw these in the colors that we're gonna use for the axes of the turret um so i'm gonna swap around the colors a bit um so so this is gonna be the up vector so let's make it green so let's let's call it up instead of normal because now we're going to start defining the orientation of the turret uh there we go okay so we got the ob vector cool um well what is the the vector pointing to the right that is kind of the first one that we can get from this um so we can go back here and vector three right um and then we want to do the cross product between the direction that the player is looking and the up vector of the um or the normal of the surface which is the up vector in this case so we can do vector dot um cross and then we can pass in the up vector and the look direction uh let's see which ones do we want to pass in um i'm using my gizmos now again player direction and up direction so we want to do look direction and up cool so now we have the right vector so then we should draw that so let's do another one uh color uh this one should be uh run was there a rule yes left hand rule use your left hand um a cross b equals c um that's it x axis cross with the y axis gives you the z axis also no i made these myself uh so there's no place to buy them unless i do something about it because a lot of people are asking me about them um yeah all right so now we should be able to draw this one so from hit position to right so let's go back to unity uh and now it's probably gonna have the incorrect length oh wait i was thinking reverse about this one because it's not the i was thinking in shader terms in which case look direction is usually going in the other direction um but you know what we can just flip these back and everything's gonna be fine there we go okay so now we have something that is pointing to the right um in this orientation however it is not um it's not normalized this one is shorter than the green line right uh so we want to make sure that this one has the same length um and again we can just normalize that so dot normalized go back to unity recompile and now it's normalized so now we have two orthogonal vectors um and the third one now is trivial to calculate because now now we can just do the cross product between those two uh so let's see uh we have trying to be open about my thinking process up vector um and we have the right vector and we want to get the forward vector uh in that case uh it's just straightforward right that just matches perfectly so we don't need to do any complicated stuff it's always just right cross up gives you forward and these two are normalized so and they're normalized and orthogonal already so don't need to normalize the results of this cross product um so let's call this one forward vector3 dot cross um right up and that gives us the forward vector uh so let's draw the forward vector so color dot um cyan and throw it and let's go back to unity and now we have a full orientation so now if you rotate this one uh you can see that the turret is sort of a presuming that you want the turret to look away from the player in terms of its forward direction but that is very likely what the player wants it to do right because intuitively if you are looking down towards the ground and you're placing a turret you probably want it to point kind of forward in the same direction as you're looking right so that's why we're looking we're using the player look direction as a reference to figure out the orientation of the turret that we're placing um yeah when you do the cross rod over the right vector you kind of the player direction is right and normal as up um well what is right and what is up is kind of just an interpretation thing um it's more so that it follows the left-handed rule right or the left-hand rule of this one cross this one gives you this direction um see that's kind of a better way of thinking about it but yeah they just happened to align with the x and y axis for the last uh one we did yeah um was that clear uh do you was there anything any questions about this i apologize for the very thin lines what if you do the opposite do you get a vector pointing in the exact opposite direction if you swap the arguments of a cross product the output reverses yes it points in the opposite direction unity z is away from camera yes is there a stroke with for polyline i think so but you need to supply your own texture um and i think it looks pretty garbage uh let's see if i can remember this yes there you go let's make them five pixels wide i don't know if it's meters or pixels ah there you go uh cross up right equals forward cross right forward equal side cross forward up equals the right and i would have to double check but if you've double checked it with the left hand rule then i presume you're correct yeah oh someone asked about the visualization so i'll just post them in here's the area thing where you can get the area of a of a parallelogram or the area of a triangle using the cross product you know i thought we would cover trigonometry but we are very close to the end how's that area thing work i thought it crossed out return a vector yes you get the length of the result of the cross product oh gosh this is harder than the one before all of my assignment ideas involve trigonometry no i'm not sure did we actually do anything with matrices or did you just tell us they exist um we didn't really directly use them but we did indirectly use them because we um because we were using the transform functions so i just mentioned that that is what unity is doing internally but i mean i could show how to use them directly um if you want to each pixel has a normal that is in tangent's page with space which is relative to the mesh's main normal uh it's relative to the tangent space that the mesh data contains yes mesh data generally contains the normals per vertex normals and per vertex tangents and then you can construct um the by tangent using the cross product and then you have tangent space right anyway i think that's it also like the left side is kind of from the last whole thing so i need to figure out some assignments this is hard i might need some time to figure these out um so i think i'm probably gonna end the stream uh and figure them out after all of this we shall talk about trigonometry next week then thank you all so much for joining i hope this was useful or good or neat or interesting or otherwise entertaining um and uh yeah i think that's that's gonna be it
Info
Channel: Freya Holmér
Views: 118,092
Rating: undefined out of 5
Keywords: Acegikmo, Freya Holmér, Freya, Holmér, Twitch, Unity, Unity3d
Id: XiwEyopOMqg
Channel Id: undefined
Length: 173min 48sec (10428 seconds)
Published: Mon Nov 09 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.