 When we rotate an object in two-dimensional space, we rotate it around some pivot point, whether that's the origin or some other point in two-dimensional space. But when we rotate an object in three-dimensional space, we're rotating it around some axis, some line. That axis could be one of our three coordinate system axes, but it could just be some arbitrary line in space. In fact, it doesn't even necessarily pass through the origin. Although, it turns out, if you want to rotate something around an axis that doesn't pass through the origin, you first have to need to know how to rotate something around the origin. Because once you've figured that out, once you've figured out how to rotate around an axis passing through the origin, to rotate around some other axis, you temporarily change the frame of reference by translating your object, then do the rotation as if it's around the origin, then change the frame of reference back. So it turns out rotating around some arbitrary axis is a simple problem once you know how to rotate around an axis going through the origin. So that's what we're going to focus on, rotating around an axis going through the origin. So there are a few different ways to represent rotations. I think the simplest is what's called the axis angle scheme, or sometimes the angle axis scheme. And in this scheme, whatever we call it, we define an axis by a vector, a three-dimensional vector. And that implies you have some axis running through the origin. And then we also specify some angle of rotation around that axis. So it requires four numbers to represent a rotation. It requires the three coordinates of our axis vector. And it requires the amount of rotation expressed either as degrees or radians. So here in this demo, we have controls to pitch our axis up and down and to orbit it around our object. Notice, though, it's always going through the origin, which here is at the center of our object. And having defined our axis, we can spin around it, which I can do with my controls Q and W now. So having defined my axis, I then apply some amount of spin around that axis. Somewhat unintuitively, I believe, it turns out that with this scheme, we can apply any possible rotation to an object by defining some axis going through its origin and some amount of rotation around that axis. Given our object starting in the so-called identity orientation, the orientation where no rotation has been applied at all, we can get from that orientation to any other by applying one rotation of some amount of degrees or radians around some axis that runs through the origin. In some cases, though, it's a little unintuitive to see the connection between the numbers and the resulting orientation. So if you have in mind some resulting orientation you want, figuring out then what the axis and the amount of rotation should be can be tricky in some cases. And vice versa, given numbers for an axis and amount of rotation, visualizing what the result of that will be, isn't always easy. So this axis angle scheme, while straightforward, is not necessarily the easiest for humans to work with. Another way of representing rotations is what are called Euler angles, where we're applying not just one rotation around an axis, but around three axes, the perpendicular x, y, and z axes of our coordinate system. And so in this demo with my controls, I'm defining some amount of rotation around the x-axis, some amount of rotation around the y-axis, and some amount of rotation around the z-axis. The question, though, is which order are these rotations being applied in? Because it turns out, this is not always something that's immediately apparent, but it can be proven formally, it turns out when you apply multiple rotations around a single axis, those rotations are cumulative, and it doesn't matter what order you do the rotations in. If I do 30 degrees of rotation around an axis and then 40 degrees around that same axis, those two rotations together just have the effect of doing one rotation of 70 degrees, and it doesn't matter which of the two I do first. If I do 30 degrees and then 40 degrees or 40 degrees and then 30 degrees, we get the same result in the end. But as soon as I do multiple rotations on an object, but the rotations are around different axes, then the order matters. In the general case, if I rotate some amount of degrees around one axis, then some amount of degrees around a different axis, it matters which of those I do first. I get different results if I do A before B or B before A. There are a few special cases where you would get the same result, but as a general rule, you don't get the same result. So, in fact, here with Euler angles, the question is we're doing rotations around these three axes and what order are they applied? Are we first rotating around x than y than z, or z than y than x? Well, we actually have six possible orders. There's x, y, z, x, z, y, y, x, z, y, z, x, z, x, y, and z, y, x. And by default, we're doing z, x, y, because that is, in fact, the order that unity applies. But here we can see what the result is if we did a different order. So, here, x, y, z. Same rotation angles just applied in a different order and we get a very different result. In fact, I'll just go through all the possibilities. And as you can see, all of them are different. So, order of rotations around different axes, that order matters. When we describe rotation in terms of Euler angles, we have to decide which of these six orders we want to use. The choice is, in a sense, arbitrary because any one of these orders does allow us to rotate an object in any way we see fit, just like with Axis angle, we can achieve any possible rotation. But there's a good reason that unity picks z, y, x, because it turns out, in that ordering, here I'll reset everything back to default. It works out that with my controls, when I rotate around y, it's sort of like I'm controlling the yaw, and when I apply rotation on z, it's like I'm controlling the role of my object, and then when I change the x rotation, it's like I'm pitching the object up and down. And this behavior holds no matter what orientation the object is already in. So here I've rolled the object over on its z-axis, but now I changed the x-axis to change the pitch, and it's still pitching up and down in a way that's predictable for me, a human user. Whereas if I chose a different order, like say here y, x, z, and I try and control things with these axes, it gets quite odd, like there are scenarios where the behavior is quite unexpected. Anyway, so z, x, y for Euler angles generally I think gives the most intuitive controls for us, the human users. Though actually we have this option of whether we want intrinsic angles, and what that is referring to is, well, when an object is at the identity orientation it has the three global x, y, z axes, but as soon as we apply some amount of rotation, you can imagine that the object has its own set of local x, y, z axes that have rotated along with it. So it has in a sense its own local x, y, z axes no matter what its current orientation is. We might want to do rotations around these local axes, and doing so is called an intrinsic rotation as opposed to an extrinsic rotation. Extrinsic rotations are rotations around the global x, y, z axes. You're sort of visualized with these markers here, whereas an intrinsic rotation is rotation around the local axes, the axes that have rotated along with the object. And so it works out with Euler angles that not only can we achieve any possible rotation by extrinsically rotating around x, y, and z in one of the six orders, we can also achieve any possible rotation by intrinsically rotating around x, y, and z in one of the six orders. So here when I check on intrinsic, and now we're going to do x, y, and z. So be clear, I'll do some x rotation first, and that has the same effect as extrinsic, because this is the first rotation done. We're starting from the identity orientation, and in the identity orientation, the global axes are the same as the local axes. It's only once we've applied rotation, only then do the intrinsic axes move. So now having rotated on the x-axis, when I then apply a y-axis rotation intrinsically, it's relative from the local coordinate system. So see how it's like yawing relative to its own coordinate system? Here I'll switch back to extrinsic, and you can see a totally different effect, because now we're rotating on the global y-axis, whereas I go back to intrinsic, and we're rotating relative to the local y-axis, not the global. And okay, so finally I'll apply some rotation along z, and now we're spinning the z-axis local to the object itself. So with Euler angles, we have those 12 options. As I said though, in Unity, the system they use, the scheme they use, is extrinsic rotation around z, x, and y in that order. So these Euler angles are what you see in the editor itself when you look at the transform. Here I can take this object and rotate it around x-axis, y-axis, and the z-axis, and I'll just set those all back. This, however, is actually a lie, because internally the way Unity is representing rotations, and in fact really the way all game engines these days represent rotations, is with what are called quaternions. Quaternions are some fairly high level math, and understand they're not really just about rotations. They're more broadly applicable, they're more broadly interesting. In fact, what we use in games for rotations are just a subset of quaternions called unit quaternions. A quaternion boils down to being this thing made up of four values. I believe that's why they're called quaternions, as in four things. And those four values, well, what they actually are in the math is you have some scalar value, you have a coefficient of i, i the imaginary number, another coefficient of j, another imaginary number, and a coefficient of k, a third imaginary number, and we need to really deal with all that. In game terms for rotations, we just think of the values as being called x, y, z, and w. And it boils down to that x, y, and z effectively are describing an axis, just like in the axis angle representation of rotations. And the fourth value, which we call w, that effectively denotes the amount of spin around the axis. But rather than representing it as some amount of degrees or radians, the value is constrained between one and negative one, and one represents no rotation applied on the axis. Zero is the full 180 degrees of rotation, and the positive values between zero and positive one, those are positive rotations, and the values zero to negative one, that's the range of negative rotations. And the way the values are mapped to degrees and radians isn't exactly linear, so 90 degrees, for example, is not 0.5 as you would expect, it's 0.71 something. So the relationship between the w value and the amount of rotation is not exactly linear. The special thing about uniquiturnians is that these four values, as a rule, the square of these four values, they all add up to one. That is a uniquiturnian. x squared plus y squared plus z squared plus w squared must equal one, otherwise it's not a uniquiturnian. For reasons we won't get into, it turns out that uniquiturnians have some useful properties that are conducive to efficiency and also neatly interpolating between rotation values, between quaternion values, because that's often what we want to do with rotations, is smoothly transition from one orientation to another orientation. Again, to understand all this, you would have to get into the math, but we can pretty much get away with using quaternions in unity without really understanding that math. So let's just see this demo here. We have control over axis, just like we did in the first demo, and we can rotate around the axis, but now note that, so this is the amount of spin we're applying the amount of rotating. Here's the axis vector, and it's a normalized vector actually, and here we're seeing the quaternion equivalent, the x, y, z, w values, that is equivalent to this axis angle rotation. And you'll notice, well, first if we have no rotation, w is one and all the other values are zero. But as soon as we add some spin, w starts decreasing, x, y, and z start getting bigger, and here is that x, y, z values, are less than normalized, and notice that the values are exactly the same as our axis. So these x, y, z values are always going to be a point along the same axis vector, and that'll hold true no matter what our w value is. And in the code here, when unity is creating my quaternion values from the axis angle values, it is doing the math to figure out what the x, y, z values should be so that the unit quaternion property holds. x squared plus y squared plus z squared plus w squared all has to equal one. And also here is w changes. We want to still have x, y, z values that are a point along this vector. Thankfully, I don't have to do that math. Unity is doing it for me. But understand that's what's going on. And here I'm displaying the magnitude of this vector. And notice that from no spin, it starts out, well, it's zero, because it's all zero. But as soon as we put a bit of spin, notice it's getting larger so we can get about 180 degrees, yeah. So it maxes out at one. So the x, y, z values imagine as a vector describing our axis of rotation and the closer our spin gets to 180 degrees, either positive or negative, it's getting closer and closer to one. Eventually it tops out at one. And then as we move away from 180 degrees rotation, it shrinks to zero. Also notice there are cases where here the x, y, z, the values are the same for quaternion axis when normalized except the signs have been flipped. Well effectively with quaternions if you want to take your rotation and invert it, if you want to apply the rotation in the opposite direction, there's two ways to do that. You can flip the w value. You can flip its sign from positive to negative or you can flip the sign of all the x, y, z values. You can have the axis point in the opposite direction. And this is actually exactly like with axis angle rotations. If you want to take your axis angle rotation and invert it, you either flip the sign of the spin or you flip the direction of the axis and you get the same effect of you get a rotation in the opposite direction. The reason the signs here aren't agreeing is because the way in my code when I'm taking my axis angle and converting it to a quaternion for whatever reason, the algorithm that generates the quaternion values from the axis angle rotation, it doesn't want to return a negative w. It always returns a positive w. So in some cases the x, y, z values will have flipped signs from the axis angle representation. Be clear though, that's just an artifact of the conversion code. We could have our quaternion with w being negative. It's just that here in this particular example it's never going to be negative. So now in the Unity API, we have a quaternion class because that's how internally all rotations are represented. We don't have an oil or angle class, we don't have an axis angle class, instead we just have quaternions. But as you'll see in a moment, the quaternion class has methods for converting but first off we have in quaternion a static property called identity which is simply the quaternion value where x, y, and z are 0 and w is 1. So this is effectively the identity rotation, the rotation which is no rotation at all. And then the quaternion class overloads the asterisk operator to perform quaternion multiplication which is defined to do this operation. It produces a new quaternion doing these calculations for reasons that we actually don't really need to understand but this is what it does. Notice importantly, if you look at this, you'll see it's not a commutative operation. You would get a different result if you multiplied b times a. So unlike with normal numbers where multiplication is defined to be commutative quaternion multiplication is not commutative and happily it turns out the reason we care about quaternion multiplication is because if you multiply unit quaternion a by unit quaternion b and remember our quaternion values in Unity are always unit quaternions and it turns out that you get the rotation of having extrinsically rotated b by a. So imagine that you have some object which has already been rotated. It's in orientation slash rotation b. That's an important point I kind of glossed over. A rotation and an orientation are really just two sides of the same coin. An orientation is a rotational position and at the same time it represents the rotation it takes to get there. So anyway, we have some object that's already at rotation b and we end up in some third orientation c and that is what this operation produces. Again, for reasons we won't explain that is what this has the effect of doing. So you can think of the quaternion multiplication operator as doing an extrinsic rotation of the first operand extrinsically applied onto the second. You might expect then that there should be some operator or method which will apply an intrinsic rotation but no because again for reasons we won't formally prove here it turns out this is something you can demonstrate quite clearly you can see it empirically. It turns out that when you apply a extrinsically onto b that is the equivalent you get the same result as if you applied b intrinsically onto a. So given any intrinsic rotation you could get the same result by doing an extrinsic rotation with the operands flipped. And vice versa if you have an extrinsic rotation you can get the same result if you did an intrinsic rotation by flipping the operands. If you ever want to intrinsically apply b onto a I can just use a multiplication operator here and I would just write ab and it simultaneously is extrinsically applying a onto b but it's also intrinsically applying b onto a. Either way you think of it you get the same result. So that is the multiplication operator and then we have the Euler angles property which returns a vector 3 representing the Euler angle equivalent of this rotation again that's the Euler angles which are extrinsically done in the order z x y. So that is the result we get back and then we have the two angle axis method where it doesn't return anything but it takes two out parameters angle of float and axis of vector 3 and it'll mutate angle and axis to be the angle axis equivalent of the quaternion rotation. To go the other way around we have the static angle axis method pass in an angle as a float and a vector 3 and we get back to quaternion which is equivalent to that axis angle rotation and likewise if we want to get a quaternion from an Euler angle representation again extrinsically applied in the order z x y. You can do so passing in the x y z values just three separate arguments or pack together in a vector 3 and we get back the equivalent quaternion. We also have the inverse method which I don't know why this is a static method it should have been an instance method to me but whatever you pass in a quaternion and you get back a quaternion representing the inverse of that rotation which would mean simply negating the w value or negating the x y z values. So those are the basic operations and then for fancier stuff we have from two rotation where j and k here are not quaternions they're vector 3's and what we want to get is a rotation that will rotate j so that it ends up at position k and this one's a little tricky to understand it's simplest to picture what it does when j and k both have the same magnitude because then to rotate you would rotate obviously it's like just swinging it around the origin and as you'd expect this method returns a rotation that takes the shortest path but it turns out there's actually an infinite number of possible rotations to swing one point in space to another point in space this is fairly easy to intuit if you imagine a point on a 3D object and the sub rotation applied to get that point in a different position but then the object of that new orientation you can imagine the point to the origin forms a vector which you can spin around 360 degrees and so with the point at that new orientation there's actually an infinite number of orientations our object could have ended up in with that point at that location and so if there's an infinite number of orientations we want to get to there's then an infinite number of rotations so I'm not entirely certain which of those rotations this method will return it'll return one of those and I believe it'll give you the shortest angle of rotation that's what I assume it'll try and do in a sense the shortest path between j to k but I'm not certain about that and to be clear though the magnitude of j and k here matter because if they're not the same magnitude you're not necessarily swinging around the origin it could be rotating around some other pivot point so be careful not to make that assumption it'll give you back rotation which when you apply it to point j will give you back point k no matter what their respective magnitudes are anyway so look rotation we again provide two vectors and well for a 3D object you can imagine it has sort of the front facing of the object this is easiest to imagine if you imagine a 3D object like say a human head or some animal head is at the front facing of the object and then there's also the upward direction there's a vector which is coming out of the front of your object and there's another vector going straight up going out of the top and what we commonly want to do with objects is rotate it so that it faces a particular direction but that facing then is effectively an axis we can spin around and so we also need to decide well relative from that axis that forward facing axis which way is up and so plugging in those two vectors here is the rotation we complied her object such that it would be facing in direction j with k pointing up and in the case where k is not perpendicular to j it'll use the vector 3 orthonormalize method we looked at last time where it'll take j as being forward and then find the plane between j and k and swing k until it is on a plane perpendicular with j so what actually matters is the plane formed by j and k that's what determines what the direction is so liquidation is a very useful method and then we have the dot method which of course computes the dot product and the dot product in quaternions is defined just like with vector 2s and vector 3s you're taking the corresponding elements of the two quaternions multiplying them together and then summing it all as one result so we take the x and the x, multiply them together the y and the y, multiply those together as z and z, w and w and then sum that all together into one value and it turns out we definitely won't prove this but it turns out that this formula just like we saw with vector 2s applies to quaternions you take the magnitude of the two quaternions multiply them together multiply them by the cosine of the angle between the quaternions that is for the rotation that we could apply to get from a to b that's a particular angle you take the cosine of that and multiply it by the magnitudes and compute the angle between the two quaternions and happily with unit quaternions it turns out the magnitude we won't go into how magnitude is defined for quaternions but no matter because with unit quaternions it's always going to be equal to one so we can just ignore this part of the equation and so when it comes time to compute the angle between two quaternions again what this means effectively is that we're finding the rotation from a to b and we want to figure out what the angle of that rotation is and well it turns out actually for reasons I don't entirely understand that the formula is not really accurate with rotations where b is not the identity there are cases where you get not quite right results I don't know why but the fix for that is that you get the rotation from a to b which is computed like this you get the inverse of a and then you extrinsically apply b onto it and you get some third rotation c and that is the rotation that you would apply to a to get to b so with some quaternion we then well okay here we need to get the dot product between c and the identity rotation but it turns out the dot product of some quaternion with the identity quaternion well if you just plug into the formula here you'll see very quickly well then the x, y, z of the identity are all zeroes so this part we can just immediately ignore and then the identity that this boils down to is really just the w of c so this is just c dot w and we get the r cosine of that and for reasons I don't understand you multiply it by 2 and that gets you a value which is in radians b we want degrees so we multiply it by the constant rad to degrees that gets us the equivalent in degrees so that's our angle and then lastly for whatever reason this should always return an angle that's less than 100 degrees and never negative so 100 degrees we're going to subtract 360 and if it's less than zero after that then we're going to flip the sign so it's positive so it's really giving you the absolute angle rather than the signed angle and lastly we have lurp and slurp for interpolating between quaternions and these behave very similar to the equivalent methods for vectors I believe the way lurp is defined for quaternion is it just simply takes the two quaternion values and interpolates the respective components so for example here we're interpolating 40% of the way from a to b then for the x component for example that's just figuring out what is 40% of the way from a.x to b.x and it does the same thing for all the respective components of these two quaternions and so that's a cheap operation to do and you have the unclamped variant where you're not necessarily constrained to the range of 0 to 1 which is sometimes useful but then other times you're going to want to do slurp which is it's not exactly analogous to the slurp of vectors but it's kind of the same effect where it's really interpolating the angles of change rather than just linearly interpolating between respective component values it's a more expensive operation but it does give us in a sense a more accurate interpolation and in some cases that will be noticeable particularly for cases where the rotation between a and b is large but again keep in mind it is more expensive so you may want to start off with slurps but then if you have performance problems you may want to look into in some cases bumping back down to slurps and in many cases the difference really won't be noticeable to human players in any case, last day we have rotate towards which is like slurp but instead of expressing the amount we want to interpolate by in terms of some percentage we just say that well we want to go from a to b we want to get the rotation between them and travel some distance along the way but the amount we want to travel we express in terms of degrees rather than percentage so say for example if the rotation from a to b were 120 degrees if we rotate towards 60 degrees that'd be equivalent of slurping with 0.5 it's like slurping half of the way there it's just in this case we express the amount we want to rotate in terms of actual degrees rather than percentage between and in the case where the rotation from a to b is actually smaller than this value we're just going to get back b whatever this value is we're not going to rotate past b just in case you're not entirely clear what this interpolation looks like here I have a demo where we have our object the capsule so-called and there's actually three copies right on top of each other and one of them has a green tip and another one has a red tip for the one with the green tip I'm using slurp to interpolate from the starting rotation to the end rotation for red I'm using lurp and for the blue one I'm doing my own solution which is finding the rotation from the starting position to the end expressing that rotation in terms of axis angle and then linearly interpolating the angle so at the starting point we're applying no rotation around that axis and by the end we're applying the full rotation and halfway between we're applying half of it so here let me put these back reset the position reset position and now we're going to play and if these solutions were all equivalent of they interpolated exactly the same way we should see them all move together and let's see so it's just randomly picked two angles the starting end and then rotate between them and then stop and wait for a second and then do it again for another start and end and what you're seeing here is that the green and the blue that's the slurp and my manual axis angle solution my manual interpolation those are staying on top of each other those are always doing exactly the same thing and you just get a bit of z-fighting where one can't decide which to draw on top of each other but then the lurp one the red that sometimes doesn't follow exactly the same speed it's following the same path of rotation but at first it's going slower at a halfway point it's going a bit faster and so you don't get exactly the same interpolation with lurp as you would with slurp or with my custom solution which is effectively I think the same thing though I'm sure the slurp implementation is more efficient I assume so I hope that gives you an idea of the difference notice that the distinction is pretty damn small for larger rotations it's more noticeable the difference but in most cases it's not something a human user would notice so those are the essentials of what you really need to understand about rotations in unity and I'm sure it's not entirely clear at this point in particular you're probably wondering why we use quaternions rather than Euler angles or just ordinary axis angle rotations this wikipedia article sums up pretty well in this section advantages of quaternions one reason is as we just demonstrated you can get efficiently get nice interpolations between rotations that's one good reason and Euler angles also have this problem of so called gimbal lock which let's see maybe I can quickly demonstrate that so we'll go into the demo here and I'm going to pick the x, y, z rotation order and I'm going to put y at 90 degrees we would seem to have some effect at negative 90 but anyway with y at 90 degrees now I can't get it exactly but close enough so now I'm going to do some x axis rotations okay nothing too surprising there but now I'm going to do z axis rotations and wait a minute with y at 90 degrees now when I'm doing z axis rotations it has like the same effect as doing x well actually it's opposite so I'm going to do a positive z axis rotation and now do some positive x axis rotation so positive x and positive z right now are having opposite effects so this is so called gimbal lock where in a sense we've lost the degree of freedom where we're getting some strange results and it's just very unintuitive it's difficult for artists and environment designers to work with it's just an awkward consequence of the oil angles it's not a huge deal arguably but it is strange so that's something we avoid with well axis angle avoids that but then quaternions avoid it as well though I would say the real reason we use quaternions the primary motivation is we just get smooth interpolation even when you do a simple lurp with quaternions you get quite accurate results just linearly interpolate between respective x, y and z components of two rotations you get some very odd behaviors the rotation doesn't seem to take the most direct path from one orientation to the next it often will take this weird elliptical path where it seems like veer off and then head back which is almost always not what we want so oil angles particularly in the order of z, x, y as I explained particularly in that extrinsic application order they're more intuitive to work with for humans they're more intuitive at least than quaternions but they're not good when we do our interpolation calculations very last thing if you really do want to understand the math of quaternions as I've said you don't actually really need to for most practical purposes at least in games but if you really want to understand the math can't hurt unfortunately most resources like actually most of the wikipedia articles are quite unreadable and bad explanations of what the hell quaternions are about so instead I would look elsewhere as I found is this page here it's reasonably readable and clear and also relatively comprehensive about the essentials so if you really want to understand the math this is probably one of the better places to start