Okay now’s where things start to get a little twisty… Get it? Twisty? The previous post handles the relatively simple case of motion in a straight line. Now we want to turn (eh? Turn?) our attention to rotations. Simply put, while Linear Motion deals with motion in a straight line, Angular Motion deals with how things spin. The good news is that every formula for rotations has a direct analogue in linear space. The bad news is that it still manages to be confusing. This may have to do with the blatant overuse of Greek symbols. Thankfully for you, I have no idea how to type Greek.
So my goal will be to build up a bunch of equations of Angular Motion by referring directly back to their Linear equivalents. I’m gonna start with the easy ones. First, there’s the Angular version of Position… It’s just Rotation. No surprise here, in Linear space we talk about standing at a specific position, in Angular space we talk about which direction we’re facing. Oh, but I’m not gonna let you get off that easily, I’m gonna throw in Quaternions to make it horrible:
Okay yeah, so the Quaternion makes it mathematically hard, but the concept is simple enough. Are you facing North, South, etc? The reason we’re forced into using a Unit_quaternion is that we will need to take any arbitrary rotation, apply a force, and get some new rotation. If you remember from the Rotations post, this kind of manipulation of a rotation is exactly the problems that Quaternions solve.
So that solves position, but how about velocity? Well in Angular space we simply call this “Angular Velocity” and it just means how fast are you spinning? In Math docs you’ll see this represented with the Greek symbol little omega. In my code it’s called:
Why do I use a Vector and not a Quaternion? This is a great question. I’ve actually been on a bit of quest to try and see how I might use a Quaternion directly, but so far I have not been successful. The math of applying a Quaternion angular velocity to an existing rotation is great, but all of the physics of is just easier to reason about using plain old Vectors. So for now, our angular velocity is a Vector. It works exactly like an Axis and Angle previously described.
So is there an angular version of acceleration? Absolutely, but much like with Linear Acceleration, I don’t really use it so much, aside from as a trick to convert Force to Velocity.
Okay so now for the hard ones. Believe it or not, the first hard one is the Angular equivalent of humble mass, it’s called “moment of inertia.” Why does this need to be hard? Well you may have noticed that when something’s mass is evenly distributed it tends to spin smoothly, think car tire or hula-hoop. But something that weighs a lot more on one end spins very unevenly, think hula-hoop with a five pound weight attached to one side. The Physics of it is that things rotate around the center of mass, the balance point. If the thing has an odd shape, or is made of light stuff on one side, and heavy stuff on the other, it will not spin around it’s physical center. I don’t want to get hung up on the details of this one, the Internet is filled with the math for how this works, for this discussion it’s important to know that things with an uneven mass distribution will spin differently then things with an even mass distribution, even if they both have the same total mass. A Moment of Inertia does the job of storing both an object’s mass, and the distribution of that mass.
And this brings us to the big one, Force, or as we call it in Angular space, Torque. When I was in high school, torque was the hardest part of Physics for the class to understand. I’m not entirely sure why this topic was so complicated for us, but we spent weeks trying to wrap our heads around it. It turns out that torque is really just Force… but it has an extra component, which is where on the object the force is applied. Just like in moment of inertia the distribution of mass is important. Similarly, where the Force is applied is an important part of the Torque. To put this in more concrete terms, imagine a bicycle wheel. If you push the tire it’s pretty simple to get it spinning, but you have to push very fast to make the wheel spin fast. But if you push right next to the hub it’s harder to get it spinning, but you don’t have to push very fast to make the wheel spin fast. It’s the same amount of Torque required to get the wheel spinning to a given angular velocity, but depending on where you push it can feel easier or harder.
You can start to build an equation for Torque by just converting the Linear equation for Force into the Angular one. Let’s start by reminding ourselves what Linear Force looks like:
// Newton's Second Law says: F = m * a;
So the rotation equivalent should be something like:
Torque = (angular mass) * (angular acceleration);
Well as stated above, the angular versions of mass and acceleration are moment of inertia and angular acceleration. So the formula is simply:
Torque = moment_of_inertia * angular_acceleration;
If you’ll remember from my last post, we don’t actually use acceleration, we replace it with the change in velocity in order to find a formula for how velocity changes given an applied force. Let’s do the same thing with torque:
// T = torque // moi = moment of inertia // ra = rotational acceleration // rv = rotational velocity // t = elapsed time T = moi * ra; // Newton's second law (sort of) ra = (rv1 - rv0)/t; // Rotational Acceleration T = moi * (rv1 - rv0)/t; // Newton's second, replace ra T*t = moi*rv1 - moi*rv0; T*t + moi*rv0 = moi*rv1; // rv1 is what we want (T*t + moi*rv0)/moi = rv1; (T*t)/moi + rv0 = rv1; // Eureka! We have rv1
There, that wasn’t so hard… but wait, there’s more. It turns out that moment_of_inertia can’t be represented by a simple scalar. Nope, not a Vector either. How about a Quaternion? Nope, sorry. The moment of inertia is something called a “tensor.” What’s a tensor? Damned if I know, but I do know it’s represented by a matrix. As you may recall, I hate matrices and have made it my life’s work to never use one in a Physics Engine. So what to do? Well if you don’t know by now, it’s time I let you in on a sad truth, Physics Engines are cheaters. Physics Engines for games are blatant, unrepentant cheaters. In the thick of a video game you just don’t need perfect Physics. When you blow up a pile of stacked boxes with some kind of ultra-blaster frag bazooka, you’re not gonna notice if the resulting shrapnel isn’t spinning off around the correct center of mass. So while it turns out that the correct moment of inertia for an object has to do with its shape and mass distribution, the moment of inertia of a uniform sphere is pretty simple, it’s just:
moment_of_inertia_of_uniform_sphere = 2/5 * radius * (mass * mass);
Check it out, it all fits into a simple scalar. Thank goodness for cheating. So the above function for finding the new angular velocity manages to hold up just fine with our
cheating simplified moment of inertia.
Now unfortunately when we go to look at the code there’s a bit of a snag. Remember that I’ve been storing angular velocity as a Vector because it makes the physics easier to reason about. And I’ve been storing the rotation as a Quaternion because it makes rotations smoother. Unfortunately the conversion from one representation to another is a bit of a mystery to me. Luckily for us there are Mathematicians who can show us the way. When you look online you’ll find that most people do something like this:
rotation = rotation + t/2 * angular_velocity * rotation
You won’t find a lot of sites explaining why this works, but this link does have an explanation. Unfortunately I’m not able to fully understand it, so let’s just hope the author never takes down that link.
And there we go, that brings us to the end of Rotational Physics. The code for this is all sitting right next to the code for Linear Physics, here are some links:
- Physics Object – where I store angular velocity, moment of inertia, and torque
- Where I calculate a new Angular Velocity – again I’m using the inverse of the moment of inertia as an optimization
- Where I calculate a new Rotation
|<< Linear Motion||Contents||GJK part 1 >>|