Now that we have a grounding in the basic Math of a Physics Engine, it’s time we shift our attention to actual Physics. Thankfully, basic Physics is something we’ve all probably had in high school, so this information should be pretty straight forward. Maybe it will help knock off some rust, maybe it will help focus your attention on the specific parts we need for a Physics Engine, or maybe it will introduce you to some of the quirks of Physics in 3D (which I never did in high school). I’m going to split up Linear Motion and Angular Motion into two posts. The Linear part should be a lot simpler, so let’s get started.
Linear Motion is the physics of moving in straight lines. At the base of it all are these humble concepts:
Point position; // where you are float m; // mass float t; // time
No surprises here. The position is a 3D point, which may be a bit different from what you saw in high school, but by now should be easy to grasp. Let’s move it up a notch
Vector distance = pos1 - pos0; Vector velocity = distance/t;
Here’s a nice chance to point out how Vectors are not the same as Points. Recall that subtracting a Point from a Point yields a Vector, in this case a distance. Dividing that by the scalar time will result in velocity. And with Velocity we can move up to the big guy, acceleration:
Vector v0; // the starting velocity Vector v1; // the final velocity Vector acceleration = (v1-v0) / t;
In English, acceleration is the change in velocity divided by time. Or to say it in car analogy: The Tesla Model S does 0 to 60 in 2.28 seconds. To make it painfully obvious, 60 is v1 and 0 is v0, and t is 2.28 seconds.
Consider the basics of what we want to do during a Physics update loop. We will have some kind of object, and it will have a force applied to it (eg. gravity on a falling object, thrust on a rocket ship, brakes on a car, etc), and some amount of time has elapsed since our last trip through the Physics loop. Our goal really comes down to figuring out how far to move the object. Everything else is kind of unimportant, we just want to move the object so users will see it move across the screen. So here’s our list of known things:
Point position; float mass; float time; Vector velocity; Vector force;
From that we want to figure out how far to move the object, a Point
representing the new position would be useful. Notice that force is one of the things we have. When I was in high school I learned exactly one way to convert force to anything useful, it was through Newton’s Second Law, the famous F = ma
. We actually could use that if we had to. We could find the acceleration, and then use that to solve for the new velocity, and then use that to solve for the new distance. But wouldn’t it be nicer to just get the new velocity directly from the force? Here’s the math (in pseudo code):
F = m * a; // Newton's Second law a = (v1 - v0)/t; // Acceleration (see above) F = m * (v1 - v0)/t; // Newton's second, replace a with dv/t F*t = m*v1 - m*v0; F*t + m*v0 = m*v1; // v1 is what we want (F*t + m*v0)/m = v1; (F*t)/m + v0 = v1; // Eureka! We have v1
So here’s the story thus far: we have an object with a known mass, velocity, and applied force. Some amount of time elapses. We enter our Physics loop and combine all of these things to get a brand new velocity. That’s great, but remember that what we want is a new position for our object. How do we take this new velocity and elapsed time and find the position?
V = d / t; // classic velocity formula (see above) d = (p1 - p0); // distance is new position minus old (see above) V = (p1 - p0) / t; // replace d with p1 and p0 V * t = p1 - p0; // p1 is what we want V * t + p0 = p1; // Eureka! We have p1
So yeah, no great magic to all of this. Every time through the Physics loop we take our known velocity, mass, position, force and elapsed time and use those to figure out a new velocity and position. We then update the position on screen, and save these for our next time through the Physics loop.
In my Engine I store the physical properties (velocity, force, mass, etc) in something called a Physics_object. The class which manages all of the Physics_objects and causes them to smash into one another is the Arena:
- Physics object (where I store velocity, force, and inverse mass)
- Where I calculate new Velocity – you’ll notice that instead of dividing Force by Mass I instead store the inverse mass and multiply it by Force each time. This is because multiplication is cheaper then division. It’s an optimization.
- Where I calculate new Position
<< Coordinate Systems | Contents | Angular Motion >> |