The Skeleton of a Physics Engine
Keeping Boxes from Sinking
In one line
Fixing only the velocity does not make an overlap that has already penetrated go away. You have to push the position separately, but pushing too hard makes it jitter, so you need to leave a margin (slop) and push a little at a time. When there are several contacts, you solve them repeatedly several times within the same step.
Why this was needed
The impulse from the previous module fixes velocity. If you make the downward velocity of a box touching the floor 0, it does not go any lower. But that box has already penetrated a little. This is because the moment you notice the overlap is already after it has overlapped.
The velocity has become 0, so the box stays put in the spot where it penetrated. In the next step gravity gives it velocity again, the position goes a little lower, and it becomes 0 again. It sinks little by little. If you stack several boxes, the lower ones are squashed and set while penetrating each other.
How it works
Position correction pushes both sides out by the overlap amount, divided in proportion to the inverse masses.
보정량 = max(깊이 - slop, 0) / (inv_m1 + inv_m2) * percent
물체1 을 -n 방향으로 보정량 * inv_m1 만큼
물체2 을 +n 방향으로 보정량 * inv_m2 만큼
There are two knobs here. percent is how much of the overlap to undo per step. If you set it to 1.0, it pushes everything out at once, and then the object is thrown out and hits again in the next step, producing an oscillation. Usually you use between 0.2 and 0.8.
slop is the margin of overlap to ignore. You usually leave about 0.005 to 0.01, and without it, a correction that tries to make the overlap 0 keeps happening at every step with a tiny value and the object jitters slightly. Rather than trying to make the overlap exactly 0, leaving it in a very thinly overlapped state is actually more stable.
It is also important that position correction does not touch velocity. It only moves the position, so it does not create energy. If you change velocity too, the correction becomes a force that pushes the objects and the pile bounces up by itself.
The number of iterations is needed when there are several contacts. If three boxes are stacked, there are three contacts (floor-1, 1-2, 2-3), and they are entangled with each other. If you push the top box, the middle is squashed, and if you fix the middle, the bottom is squashed. If you solve the contacts one at a time in order, the one solved later ruins the one solved earlier.
The exact solution is to solve all the contacts as one system of simultaneous equations, but that is expensive. So engines repeat the same pass several times. The more you repeat, the closer you get to the right answer, and the point where you stop repeating is the trade-off between accuracy and cost. This is called sequential impulse, and it became practically the standard after Erin Catto laid it out in Box2D. How solid a pile of boxes looks depends almost directly on this number of iterations.
There is another way besides position correction. Baumgarte stabilization is a method that mixes part of the overlap into the velocity target. If you change the target from "make the relative velocity 0" to "make the relative velocity beta * 깊이 / dt" (the placeholder is the depth), the overlap is pushed out as well within the velocity solver. It was widely used because it is simple to implement, but it has the side effect of putting energy into the system, which can also cause a pile to jitter slightly.
That is why modern engines use split impulse. You keep the impulse that fixes velocity and the impulse that fixes position separate, and the position impulse is not reflected in the actual velocity. The overlap is pushed out while no energy comes in, so only the advantages of both methods remain. The position correction in this lab is the most simplified form of that idea.
What it looks like in the field
A pile that slowly gets lower as time passes means too few iterations. The step ends before the lower contacts are fully solved, so it is squashed a little at every step. Increasing the iterations improves it noticeably, but the cost grows by the same amount.
Another is sleeping. Once a pile is stable, the computation keeps running but the result hardly changes. An engine takes an object out of the computation when its velocity stays below a threshold for a certain time, and wakes it when something touches it. This is why a scene with 1,000 stacked boxes can actually run.
Finally, it is good to decide what you use to measure the stability of a pile. Saying that it does not wobble when you look at it is not a criterion. There are two methods used in the lab. One is whether the maximum penetration depth of the contacts stays near the slop, and the other is whether the difference between the pictures of two consecutive frames converges to 0. The latter is especially useful because it measures the same thing a person sees — even if the numbers move a little, if the pixels on screen are the same, it has stopped as far as a person is concerned.
And remember one rule of this layer — not wobbling comes before being exact. An attempt to make the overlap exactly 0 creates jitter, and an attempt to undo everything in one step creates bouncing. A pile that stands quietly with a slight overlap is better than a pile that touches exactly but vibrates slightly.
What you will do in the next lab
You build the position correction function, and compare in numbers a box run without correction setting while penetrated with the box returning to the slop when correction is on. Next, you change the number of iterations to 1, 4 and 10 on three boxes and confirm that the penetration depth shrinks, and finally you leave the process of five boxes falling, stacking and settling in twelve pictures.