Advanced Character Physics: Thomas Jakobsen
Advanced Character Physics: Thomas Jakobsen
Thomas Jakobsen
IO Interactive, Farvergade 2
DK-1463 Copenhagen K
Denmark
Email: tj@ioi.dk, www: www.ioi.dk/~tj
Abstract
This paper explains the basic elements of an approach to physically-based
modeling which is well suited for interactive use. It is simple, fast, and quite
stable, and in its basic version the method does not require knowledge of
advanced mathematical subjects (although it is based on a solid mathematical
foundation). It allows for simulation of both cloth; soft and rigid bodies; and
even articulated or constrained bodies using both forward and inverse
kinematics.
The article also deals with subtleties like penetration test optimization and
friction handling.
1 Introduction
The use of physically-based modeling to produce nice-looking animation has
been considered for some time and many of the existing techniques are fairly
sophisticated. Different approaches have been proposed in the literature
[Baraff, Mirtich, Witkin, and others] and much effort has been put into the
construction of algorithms that are accurate and reliable. Actually, precise
simulation methods for physics and dynamics have been known for quite
some time from engineering. However, for games and interactive use,
accuracy is really not the primary concern (although it’s certainly nice to have)
– rather, here the important goals are believability (the programmer can cheat
as much as he wants if the player still feels immersed) and speed of
execution (only a certain time per frame will be allocated to the physics
engine). In the case of physics simulation, the word believability also covers
stability; a method is no good if objects seem to drift through obstacles or
vibrate when they should be lying still, or if cloth particles tend to “blow up”.
In overview, the success of the method comes from the right combination of
several techniques that all benefit from each other:
• A so-called Verlet integration scheme.
• Handling collisions and penetrations by projection.
• A simple constraint solver using relaxation.
• A nice square root approximation that gives a solid speed-up.
• Modeling rigid bodies as particles with constraints.
• An optimized collision engine with the ability to calculate penetration
depths.
Each of the above subjects will be explained shortly. In writing this document,
the author has tried to make it accessible to the widest possible audience
without losing vital information necessary for implementation. This means that
technical mathematical explanations and notions are kept to a minimum if not
crucial to understanding the subject. The goal is demonstrating the possibility
of implementing quite advanced and stable physics simulations without
dealing with loads of mathematical intricacies.
2 Verlet integration
The heart of the simulation is a particle system. Typically, in implementations
of particle systems, each particle has two main variables: Its position x and its
velocity v. Then in the time-stepping loop, the new position x’ and velocity v’
are often computed by applying the rules
x' = x + v ⋅ ∆t
v ' = v +a ⋅ ∆t ,
where ∆ t is the time step, and a is the acceleration computed using Newton’s
law f=ma (where f is the accumulated force acting on the particle). This is
simple Euler integration.
x' = 2x − x * + a ⋅ ∆t 2
x * = x.
This is called Verlet integration (see [Verlet]) and is used intensely when
simulating molecular dynamics. It is quite stable since the velocity is implicitly
given and consequently it is harder for velocity and position to come out of
sync. (As a side note, the well-known demo effect for creating ripples in water
uses a similar approach.) It works due to the fact that 2x-x*=x+(x-x*) and x-x*
is an approximation of the current velocity (actually, it’s the distance traveled
last time step). It is not always very accurate (energy might leave the system,
i.e., dissipate) but it’s fast and stable. By lowering the value 2 to something
like 1.99 a small amount of drag can also be introduced to the system.
At the end of each step, for each particle the current position x gets stored in
the corresponding variable x*. Note that when manipulating many particles, a
useful optimization is possible by simply swapping array pointers.
The resulting code would look something like this (the Vector3 class should
contain the appropriate member functions and overloaded operators for
manipulation of vectors):
The above code has been written for clarity, not speed. One optimization
would be using arrays of float instead of Vector3 for the state representation.
This might also make it easier to implement the system on a vector processor.
Try setting a=(0,0,1), for example, and use the start condition x=(1,0,0),
x*=(0,0,0), then do a couple of iterations by hand and see what happens.
Here, we use yet another strategy. Offending points are simply projected out
of the obstacle. By projection, loosely speaking, we mean moving the point as
little as possible until it is free of the obstacle. Normally, this means moving
the point perpendicularly out towards the collision surface.
Let’s examine an example. Assume that our world is the inside of the cube
(0,0,0)-(1000,1000,1000) and assume also that the particles’ restitution
coefficient is zero (that is, particles do not bounce off surfaces when colliding).
To keep all positions inside the valid interval, the corresponding projection
code would be:
Try it out – there is no need to directly cancel the velocity in the normal
direction. While the above might seem somewhat trivial when looking at
particles, the strength of the Verlet integration scheme is now beginning to
shine through and should really become apparent when introducing
constraints and coupled rigid bodies in a moment.
In the example, constraints were satisfied (that is, particles are kept inside the
cube) by simply modifying offending positions by projecting the particles onto
the cube surface. To satisfy (C1), we use the following pseudo-code
// Pseudo-code to satisfy (C1)
for i=1,2,3
set xi=min{max{xi, 0}, 1000}
One may think of this process as inserting infinitely stiff springs between the
particle and the penetration surface – springs that are exactly so strong and
suitably damped that instantly they will attain their rest length zero.
Although the particles might be correctly placed initially, after one integration
step the separation distance between them might have become invalid. In
order to obtain the correct distance once again, we move the particles by
projecting them onto the set of solutions described by (C2). This is done by
pushing the particles directly away from each other or by pulling them closer
together (depending on whether the erroneous distance is too small or too
large). See Figure 2.
Really, what we should do is solve for all constraints at once, both (C1) and
(C2). This would be a matter of solving a system of equations. However, we
choose to proceed indirectly by local iteration. We simply repeat the two
pieces of pseudo-code a number of times after each other in the hope that the
result is useful. This yields the following code:
(Initialization of the two particles has been omitted.) While this approach of
pure repetition might appear somewhat naïve, it turns out that it actually
converges to the solution that we are looking for! The method is called
relaxation (or Jacobi or Gauss-Seidel iteration depending on how you do it
exactly, see [Press]). It works by consecutively satisfying various local
constraints and then repeating; if the conditions are right, this will converge to
a global configuration that satisfies all constraints at the same time. It is useful
in many other situations where several interdependent constraints have to be
satisfied at the same time.
Cloth simulation
The fact that a stick constraint can be thought of as a really hard spring
should make apparent its usefulness for cloth simulation as sketched in the
beginning of this section. Assume, for example, that a hexagonal mesh of
triangles describing the cloth has been constructed. For each vertex a particle
is initialized and for each edge a stick constraint between the two
corresponding particles is initialized (with the constraint’s “rest length” simply
being the initial distance between the two vertices).
We now discuss how to get rid of the square root operation. If the constraints
are all satisfied (which they should be at least almost), we already know what
the result of the square root operation in a particular constraint expression
ought to be, namely the rest length r of the corresponding stick. We can use
this fact to approximate the square root function. Mathematically, what we do
is approximate the square root function by its 1st order Taylor-expansion at a
neighborhood of the rest length r (this is equivalent to one Newton-Raphson
iteration with initial guess r). After some rewriting, we obtain the following
pseudo-code:
Notice that if the distance is already correct (that is, if |delta|=restlength), then
one gets delta=(0,0,0) and no change is going to happen.
Per constraint we now use zero square roots, one division only, and the
squared value restlength*restlength can even be precalculated! The usage of
time consuming operations is now down to N divisions per frame (and the
corresponding memory accesses) – it can’t be done much faster than that and
the result even looks quite nice. Actually, in Hitman, the overall speed of the
cloth simulation was limited mostly by how many triangles it was possible to
push through the rendering system.
The constraints are not guaranteed to be satisfied after one iteration only, but
because of the Verlet integration scheme, the system will quickly converge to
the correct state over some frames. In fact, using only one iteration and
approximating the square root removes the stiffness that appears otherwise
when the sticks are perfectly stiff.
The code and the equations covered in this section assume that all particles
have identical mass. Of course, it is possible to model particles with different
masses, the equations only get a little more complex.
To satisfy (C2) while respecting particle masses, use the following code:
// Pseudo-code to satisfy (C2)
delta = x2-x1;
deltalength = sqrt(delta*delta);
diff = (deltalength-restlength)
/(deltalength*(invmass1+invmass2));
x1 -= invmass1*delta*diff;
x2 += invmass2*delta*diff;
Here invmass1 and invmass2 are the numerical inverses of the two masses. If
we want a particle to be immovable, simply set invmass=0 for that particle
(corresponding to an infinite mass). Of course in the above case, the square
root can also be approximated for a speed-up.
5 Rigid bodies
The equations governing motion of rigid bodies were discovered long before
the invention of modern computers. To be able to say anything useful at that
time, mathematicians needed the ability to manipulate expressions
symbolically. In the theory of rigid bodies, this lead to useful notions and tools
such as inertia tensors, angular momentum, torque, quaternions for
representing orientations etc. However, with the current ability to process
huge amounts of data numerically, it has become feasible and in some cases
even advantageous to break down calculations to simpler elements when
running a simulation. In the case of 3D rigid bodies, this could mean modeling
a rigid body by four particles and six constraints (giving the correct amount of
degrees of freedom, 4x3-6 = 6). This simplifies a lot of aspects and it’s exactly
what we will do in the following.
Now clearly, in general rigid bodies do not behave like tetrahedrons collision-
wise (although they might do so kinetically). There is also another problem:
Presently, collision detection between the rigid body and the world exterior is
on a vertex-only basis, that is, if a vertex is
found to be outside the world it is projected
inside again. This works fine as long as the
inside of the world is convex. If the world
were non-convex then the tetrahedron and
the world exterior could actually penetrate
each other without any of the tetrahedron
vertices being in an illegal region (see
Figure 3 where the triangle represents the
2D analogue of the tetrahedron). This Figure 3. A tetrahedron
problem is handled in the following. penetrating the world.
We’ll first consider a simpler version of the problem. Consider the stick
example from earlier and assume that the world exterior has a small bump on
it. The stick can now penetrate the world exterior without any of the two stick
particles leaving the world (see Figure 4). We won’t go into the intricacies of
constructing a collision detection engine since this is a science in itself.
Instead we assume that there is a subsystem available which allows us to
detect the collision. Furthermore we assume that the subsystem can reveal to
us the penetration depth and identify the penetration points on each of the two
colliding objects. (One definition of penetration points and penetration depth
goes like this: The penetration distance dp is the shortest distance that would
prevent the two objects from penetrating if one were to translate one of the
objects by the distance dp in a suitable direction. The penetration points are
the points on each object that just exactly touch the other object after the
aforementioned translation has taken place.)
Take a look again at Figure 4. Here the stick has moved through the bump
after the Verlet step. The collision engine has identified the two points of
penetration, p and q. In Figure 4a, p is actually identical to the position of
particle 1, i.e., p=x1. In Figure 4b, p lies between x1 and x2 at a position ¼ of
the stick length from x1. In both cases, the point p lies on the stick and
consequently it can be expressed as a linear combination of x1 and x2, p=c1
x1+c2 x2 such that c1+c2=1. In the first case, c1=1 and c2=0, in the second
case, c1=0.75 and c2=0.25. These values tell us how much we should move
the corresponding particles.
x2
q x2
x1
p= q p
x1
In the first case, we simply project x1 out of the invalid region like earlier (in
the direction of q) and that’s it (x2 is not touched). In the second case, p is still
nearest to x1 and one might reason that consequently x1 should be moved
more than x2. Actually, since p=0.75 x1 + 0.25 x2, we will choose to move x1
by an amount of 0.75 each time we move x2 by an amount of 0.25. In other
words, the new particle positions x1’ and x2’ are given by the expressions
x1 ' = x1 + 0.75 λ ⋅ Δ
(*)
x2 ' = x2 + 0.25 λ ⋅ Δ
where λ is some unknown value. The new position of p after moving both
particles is p’=c1 x1’+ c2 x2’.
Recall that we want p’=q, i.e., we should choose λ exactly such that p’ ends
up coinciding with q. Since we move the particles only in the direction of ∆ ,
also p moves in the direction of ∆ and consequently the solution to the
equation p’=q can be found by solving
p '⋅Δ = q ⋅ Δ (**)
(q − p) ⋅ Δ
λ= .
(0.75 2 + 0.25 2 ) ⋅ Δ 2
Plugging λ into (*) gives us the new positions of the particles for which p’
coincide with q.
Figure 5 shows the situation after moving the particles. We have no object
penetration but now the stick length constraint has been violated. To fix this,
we do yet another iteration of the relaxation loop (or several) and we’re
finished.
x2
x1 p=q
x2
p=q=x1
The above strategy also works for the tetrahedron in a completely analogous
fashion. First the penetration points p and q are found (they may also be
points interior to a triangle), and p is expressed as a linear combination of the
four particles p=c1 x1+c2 x2+c3 x3+c4 x4 such that c1+c2+c3+c4=1 (this
calls for solving a small system of linear equations). After finding ∆ =q-p, one
computes the value
(q − p) ⋅ Δ
λ=
(c1 + c 2 2 + c3 2 + c 4 2 ) ⋅ Δ 2
2
x1 ' = x1 + c1 ⋅ λ ⋅ Δ
x2 ' = x2 +c2 ⋅ λ⋅ Δ
x3 ' = x3 + c3 ⋅ λ ⋅ Δ
x4 ' = x4 + c 4 ⋅ λ ⋅ Δ.
Here, we have collided a single rigid body with an immovable world. The
above method generalizes to handle collisions of several rigid bodies. The
collisions are processed for one pair of bodies at a time. Instead of moving
only p, in this case both p and q are moved towards each other.
Again, after adjusting the particle positions such that they satisfy the non-
penetration constraints, the six distance constraints that make up the rigid
body should be taken care of and so on. With this method, the tetrahedron
can even be imbedded inside another object that can be used instead of the
tetrahedron itself to handle collisions. In Figure 6, the tetrahedron is
embedded inside a cube.
Usually, 3 to 4 relaxation iterations are enough. The bodies will not behave as
if they were completely rigid since the relaxation iterations are stopped
prematurely. This is mostly a nice feature, actually, as there is no such thing
as perfectly rigid bodies – especially not human bodies. It also makes the
system more stable.
By rearranging the positions of the particles that make up the tetrahedron, the
physical properties can be changed accordingly (mathematically, the inertia
tensor changes as the positions and masses of the particles are changed).
6 Articulated bodies
It is possible to connect multiple rigid bodies by hinges, pin joints, and so on.
Simply let two rigid bodies share a particle, and they will be connected by a
pin joint. Share two particles, and they are connected by a hinge. See Figure
7.
It is also possible to connect two rigid bodies by a stick constraint or any other
kind of constraint – to do this, one simply adds the corresponding ‘fix-up’ code
to the relaxation loop.
Particles can also be restricted to move, for example, in certain planes only.
Once again, particles with positions not satisfying the above-mentioned
constraints should be moved – deciding exactly how is slightly more
complicated that with the stick constraints.
setup the polygonal mesh of the character is forced to orientate the leg, for
instance, such that the knee appears to bend naturally. Since rotation of legs
and arms around the length axis does not comprise the essential motion of a
falling human body, this works out okay and actually optimizes speed by a
great deal.
For collision with the environment, which consists of triangles, each stick is
modeled as a capped cylinder. Somewhere in the collision system, a
subroutine handles collisions between capped cylinders and triangles. When
a collision is found, the penetration depth and points are extracted, and the
collision is then handled for the offending stick in question exactly as
described in the beginning of Section 5.
Naturally, a lot of additional tweaking was necessary to get the result just
right.
7 Comments
This section contains various remarks that didn’t fit anywhere else.
Motion control
To influence the motion of a simulated object, one simply moves the particles
correspondingly. If a person is hit at the shoulder, move the shoulder particle
backwards over a distance proportional to the strength of the blow. The Verlet
integrator will then automatically set the shoulder in motion.
This also makes it easy for the simulation to ‘inherit’ velocities from an
underlying traditional animation system. Simply record the positions of the
particles for two frames and then give them to the Verlet integrator, which
then automatically continues the motion. Bombs can be implemented by
pushing each particle in the system away from the explosion over a distance
inversely proportional to the square distance between the particle and the
bomb center.
Handling friction
Friction has not been taken care of yet. This means that unless we do
something more, particles will slide along the floor as if it were made of ice.
According to the Coulomb friction model, friction force depends on the size of
the normal force between the objects in contact. To implement this, we
measure the penetration depth dp when a penetration has occurred (before
projecting the penetration point out of the obstacle). After projecting the
particle onto the surface, the tangential velocity vt is then reduced by an
amount proportional to dp (the proportion factor being the friction constant).
This is done by appropriately modifying x*. See the Figure 10. Care should be
taken that the tangential velocity does not reverse its direction – in this case
one should simply be set it to zero since this indicates that the penetration
point has seized to move tangentially. Other and better friction models than
this could and should be implemented.
dp v’t
vt
Figure 10. Collision handling with friction (projection and modification of tangential velocity).
Collision detection
One of the bottlenecks in physics simulation as presented here lies in the
collision detection, which is potentially performed several times inside the
relaxation loop. It is possible, however, to iterate a different number of times
over the various constraints and still obtain good results.
In Hitman, the collision system works by culling all triangles inside the
bounding box of the object simulated (this is done using a octtree approach).
For each (static, background) triangle, a structure for fast collision queries
against capped cylinders is then constructed and cached. This strategy gave
quite a speed boost.
To prevent objects that are moving really fast from passing through other
obstacles (because of too large time steps), a simple test if performed.
Imagine the line (or a capped cylinder of proper radius) beginning at the
position of the object’s midpoint last frame and ending at the position of the
object’s midpoint at the current frame. If this line hits anything, then the object
position is set to the point of collision. Though this can theoretically give
problems, in practice it works fine.
Another collision ‘cheat’ is used for dead bodies. If the unusual thing happens
that a fast moving limb ends up being placed with the ends of the capped
cylinder on each side of a wall, the cylinder is projected to the side of the wall
where the cylinder is connected to the torso.
Miscellaneous
The number of relaxation iterations used in Hitman vary between 1 and 10
with the kind of object simulated. Although this is not enough to accurately
solve the global system of constraints, it is sufficient to make motion seem
natural. The nice thing about this scheme is that inaccuracies do not
accumulate or persist visually in the system causing object drift or the like – in
some sense the combination of projection and the Verlet scheme manages to
distribute complex calculations over several frames (other schemes have to
use further stabilization techniques, like Baumgarte stabilization). Fortunately,
the inaccuracies are smallest or even nonexistent when there is little motion
and greatest when there is heavy motion – this is nice since fast or complex
motion somewhat masks small inaccuracies for the human eye.
A kind of soft bodies can also be implemented by using ‘soft’ constraints, i.e.,
constraints that are allowed to have only a certain percentage of the deviation
‘repaired’ each frame (i.e., if the rest length of a stick between two particles is
100 but the actual distance is 60, the relaxation code could first set the
distance to 80 instead of 100, next frame 90, 95, 97.5 etc.).
For the mathematically inclined, however, what we are doing is actually a sort
of time-stepping approach to solving differential inclusions (a variant of
differential equations) using a simple sort of interior-point algorithm (see
[Stewart] where a similar approach is discussed). When trying to satisfy the
constraints, we are actually projecting the system state onto the manifold
described by the constraints. This, in turn, is done by solving a system of
linear equations. The linear equations or code to solve the constraints can be
obtained by deriving the Jacobian of the constraint functions. In this article,
relaxation has been discussed as an implicit way of solving the system.
Although we haven’t touched the subject here, it is sometimes useful to
change the relaxation coefficient or even to use over-relaxation (see [Press]
for an explanation). Since relaxation solvers sometimes converge slowly, one
might also choose to explicitly construct the equation system and use other
methods to solve it (for example a sparse matrix conjugate gradient descent
solver with preconditioning using the results from the previous frame (thereby
utilizing coherence)).
Note that the Verlet integrator scheme exists in a number of variants, e.g., the
Leapfrog integrator and the velocity Verlet integrator. Accuracy might be
improved by using these.
As an optimization, bodies should time out when they have fallen to rest.
To toy with the animation system for dead characters in Hitman: Codename
47, open the Hitman.ini file and add the two lines “enableconsole 1” and
“consolecmd ip_debug 1” at the bottom. Pointing the cursor at an enemy and
pressing shift+F9 will cause a small bomb to explode in his vicinity sending
him flying. Press K to toggle free-cam mode (camera is controlled by cursor
keys, shift, and ctrl).
Note that since all operations basically take place on the particle level, the
algorithms should be very suitable for vector processing (Playstation 2 for
example).
8 Conclusion
This paper has described how a physics system was implemented in Hitman.
The underlying philosophy of combining iterative methods with a stable
integrator has proven to be successful and useful for implementation in
computer games. Most notably, the unified particle-based framework, which
handles both collisions and contact, and the ability to trade off speed vs.
accuracy without accumulating visually obvious errors are powerful features.
Naturally, there are still many specifics that can be improved upon. In
particular, the tetrahedron model for rigid bodies needs some work. This is in
the works.
9 Acknowledgements
The author wishes to thank Jeroen Wagenaar for fruitful discussions and the
entire crew at IO Interactive for cooperation and for producing such a great
working environment.
References
[Baraff] Baraff, David, Dynamic Simulation of Non-Penetrating Rigid
Bodies, Ph.D. thesis, Dept. of Computer Science, Cornell
University, 1992. http://www.cs.cmu.edu/~baraff/papers/index.html
[Mirtich] Mirtich, Brian V., Impulse-base Dynamic Simulation of Rigid Body
Systems, Ph.D. thesis, University of California at Berkeley, 1996.
http://www.merl.com/people/mirtich/papers/thesis/thesis.html
[Press] Press, William H. et al, Numerical Recipes, Cambridge University
Press, 1993. http://www.nr.com/nronline_switcher.html
[Stewart] Stewart, D. E., and J. C. Trinkle, “An Implicit Time-Stepping
Scheme for Rigid Body Dynamics with Inelastic Collisions and
Coulomb Friction”, International Journal of Numerical Methods in
Engineering, to appear.
http://www.cs.tamu.edu/faculty/trink/Papers/ijnmeStewTrink.ps
[Verlet] Verlet, L. "Computer experiments on classical fluids. I.
Thermodynamical properties of Lennard-Jones molecules", Phys.
Rev., 159, 98-103 (1967).
[Witkin] Witkin, Andrew and David Baraff, Physically Based Modeling:
Principles and Practice, Siggraph ’97 course notes, 1997.
http://www.cs.cmu.edu/~baraff/sigcourse/index.html
The author
Thomas Jakobsen is head of research and development at IO Interactive, where he is
developing new technology for the in-house engine, Glacier. He created the physics simulation
and the 3D pathfinder for IO's Hitman: Codename 47. Jakobsen earned his M.Sc. in engineering
from The Technical University of Denmark, where he also obtained his Ph.D. in mathematics. He
spent a number of years in academia and has published several scientific articles on
cryptanalysis. He began programming at age nine with a Sinclair ZX80. In 1986, he co-designed
Vikings for the Commodore 64 and Amstrad CPC. In the late 1980s, he developed tools for the
Amiga classics Hybris and Battle Squadron.