10.1201 b11324 Previewpdf PDF
10.1201 b11324 Previewpdf PDF
10.1201 b11324 Previewpdf PDF
game
physics
houses that produce physics software for games on PCs and consoles.
Each article describes not only a specific topic, but provides an in-the-
trenches discussion of the practical problems and solutions when
implementing the algorithms, whether for a physics engine or game
application.
pearls
The chapters cover topics such as collision detection, particle-based
simulations, constraint solving, and soft-body simulation. Several of
the topics are about nonsequential programming, whether multicore
or for game consoles, which is important given the evolution of modern
computing hardware toward multiprocessing and multithreading.
Edited by
Image © Wayne Johnson, 2010.
Gino van den Bergen and Dirk Gregorius
A K Peters, Ltd. Used under license from Shutterstock.com A K PETERS
i i
i i
i i
i i
i i
i i
i i
i i
i i
i i
Edited by
Gino van den Bergen
and
Dirk Gregorius
A K Peters, Ltd.
Natick, Massachusetts
i i
i i
CRC Press
Taylor & Francis Group
6000 Broken Sound Parkway NW, Suite 300
Boca Raton, FL 33487-2742
© 2010 by Taylor & Francis Group, LLC
CRC Press is an imprint of Taylor & Francis Group, an Informa business
This book contains information obtained from authentic and highly regarded sources. Reason-
able efforts have been made to publish reliable data and information, but the author and publisher
cannot assume responsibility for the validity of all materials or the consequences of their use. The
authors and publishers have attempted to trace the copyright holders of all material reproduced in
this publication and apologize to copyright holders if permission to publish in this form has not
been obtained. If any copyright material has not been acknowledged please write and let us know so
we may rectify in any future reprint.
Except as permitted under U.S. Copyright Law, no part of this book may be reprinted, reproduced,
transmitted, or utilized in any form by any electronic, mechanical, or other means, now known or
hereafter invented, including photocopying, microfilming, and recording, or in any information
storage or retrieval system, without written permission from the publishers.
For permission to photocopy or use material electronically from this work, please access www.
copyright.com (http://www.copyright.com/) or contact the Copyright Clearance Center, Inc.
(CCC), 222 Rosewood Drive, Danvers, MA 01923, 978-750-8400. CCC is a not-for-profit organiza-
tion that provides licenses and registration for a variety of users. For organizations that have been
granted a photocopy license by the CCC, a separate system of payment has been arranged.
Trademark Notice: Product or corporate names may be trademarks or registered trademarks, and
are used only for identification and explanation without intent to infringe.
Visit the Taylor & Francis Web site at
http://www.taylorandfrancis.com
and the CRC Press Web site at
http://www.crcpress.com
i i
i i
Contents
Foreword xi
Preface xiii
1 Mathematical Background 3
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Vectors and Points . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Lines and Planes . . . . . . . . . . . . . . . . . . . . . . . . 8
1.4 Matrices and Transformations . . . . . . . . . . . . . . . . . 9
1.5 Quaternions . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.6 Rigid-Body Dynamics . . . . . . . . . . . . . . . . . . . . . 15
1.7 Numerical Integration . . . . . . . . . . . . . . . . . . . . . . 22
1.8 Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . 26
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
II Collision Detection 45
i i
i i
i i
i i
vi Contents
i i
i i
i i
i i
Contents vii
i i
i i
i i
i i
viii Contents
VI Skinning 281
i i
i i
i i
i i
Contents ix
Index 341
i i
i i
i i
i i
i i
i i
i i
i i
Foreword
I am not a fan of gems-style books. Typically, they are assembled and glued
together as a collection of loosely related articles, and no attempt is made to unify
them by emphasizing common themes and ideas. When I was asked to write the
foreword for this book, my initial reaction was to decline politely, thinking this
was yet another such book. However, knowing the editors and their reputations
in the physics engine industry, I agreed to read the book in hopes that there might
be a few articles that make the book a worthwhile purchase.
I am delighted to say that this book is much more than I imagined. Those few
articles I hoped to find interesting turned out to be all the articles! I congratulate
the editors and the authors for producing the finest collection of game physics
articles I have seen to date. The common theme is experience. Each author de-
scribes not only a topic of interest, but provides an in-the-trenches discussion of
the practical problems and solutions when implementing the algorithms, whether
for a physics engine or game application. Moreover, I found it comforting that
the authors were consistent in their findings, giving me hope that writing a fast
and robust physics engine actually can be a scientific process rather than an en-
deavor that combines art, hacks, and voodoo. Also of importance is that several of
the topics are about nonsequential programming, whether multicore or for game
consoles, which is important given the evolution of modern computing hardware
towards multiprocessing and multithreading.
This book is a must-have if you plan on exploring the world of physics pro-
gramming. And I hope the editors and authors have plans on producing more
books of the same great quality.
—Dave Eberly
xi
i i
i i
i i
i i
i i
i i
i i
i i
Preface
It took some time before I considered myself a physics programmer. Like most
game programmers, I started out toying with physics in hobby game projects.
These early attempts at getting physical behavior out of an 8-bit home computer
did involve concepts such as velocity, mass, and force, but in my head they were
far from “real” physics. In the following years at the university I learned how to
program properly and got proficient in linear algebra, geometric algorithms, and
computer graphics. I took courses in theoretical mechanics and numerical anal-
ysis, expecting that after overcoming these hurdles, developing a physics engine
would be easy.
It never did get easy. In the coming years I was struggling to get even the
simplest of rigid body simulations stable on computers that were a thousand times
more powerful than the 8-bit home computer from my junior years. It would take
a considerable number of hacks to stop my “resting” contacts from oscillating and
from bouncing all over the place. And even then, the hacks would work only for
objects within certain ranges of masses and sizes. In the end, most of the hacks
that seemed to work would make Sir Isaac Newton turn in his grave. My inner
physicist was nagging at me, telling me that what I was doing was not “real”
physics. I was failing to truly capture classical mechanics as it was taught to me
in the code of a real-time physics engine. Surely, anyone who needs to resort to
the use of cheap hacks to get things working could never be considered a genuine
physics programmer.
After spending a couple of years in the game industry I learned that an under-
standing of classical mechanics and the ability to apply it in code are not the prime
skills of a physics programmer. Of course, any physics programmer should feel
comfortable with the science and mathematics behind physics, but being too con-
cerned about the science can become a burden as well. Games that involve physics
should primarily be targeted at playability and robustness rather than showcase a
maximum realism level. I had to overcome some hesitation before I willingly
started breaking the laws of physics and came up with hacks that created “un-
natural” behavior that fixed some game design issues. For example, in an arcade
racing game, cars should drift nicely, should rarely tip over, and if they do, should
always land back on their wheels—but most of all, they should never get stuck in
parts of the scenery. A game physics programmer can start with a realistic driving
behavior and then add helper forces and impulses to govern down force, balance,
turn rate, and what not, in order to get just the right behavior. It takes creativity
and a lot of experience to make a game that relies heavily on physics and is fun.
xiii
i i
i i
i i
i i
xiv Preface
My initial contact with game physic programming was totally accidental. I had
just finished my studies of civil engineering and I was sitting in a cafe talking to
an old girlfriend I hadn’t seen for a while. As she asked me what I would do next
I replied that I would be maybe interested in game development. As it turned out
her husband (who just returned from GDC) was a veteran in the game industry,
and he invited me for an interview. In this interview I learned that his company
was working on a release title for the PS3 and was currently looking for a physics
programmer. I had no idea what this meant, but I happily accepted.
When I started my work, I was overwhelmed by the huge amount of books,
papers, and especially rumors that were around. People on public forums had
i i
i i
i i
i i
Preface xv
many ideas and were gladly sharing them, but sadly these ideas often worked
reliably only in very specific situations. I quickly learned that it was very hard
to get accurate information that was actually useable in a game. At this point I
wished for a collection of proven algorithms that actually were used in a shipped
title, but sadly no such source existed at that time.
As Gino mentioned his idea of such a book, I was immediately excited and felt
flattered to support him as editor. It is my very strong belief that game physics pro-
gramming is about choosing the right algorithms rather then inventing everything
yourself. Having a collection of proven techniques is a great help in architecturing
a solution for the specific needs of any game.
It was a great experience editing this book, and I enjoyed every minute work-
ing with every author. They all showed a great enthusiasm for contributing to this
book. I would like to thank all the authors, the staff at A K Peters, all the external
reviewers, the copy editors, the cover designer, and especially Gino for getting
me on board of this project.
—Dirk Gregorius
June 18, 2010
i i
i i
i i
i i
i i
i i
i i
i i
-I-
Game Physics 101
i i
i i
i i
i i
i i
i i
i i
i i
-1-
Mathematical Background
James M. Van Verth
1.1 Introduction
It has been said that, at its core, all physics is mathematics. While that statement
may be debatable, it is certainly true that a background in mathematics is indis-
pensable in studying physics, and game physics is no exception. As such, a single
chapter cannot possibly cover all that is useful in such a broad and interesting
field. However, the following should provide an essential review of the mathe-
matics needed for the remainder of this book. Further references are provided at
the end of the chapter for those who wish to study further.
i i
i i
i i
i i
4 1. Mathematical Background
shows the relationship between points and vectors—in this case, the vector is
acting as the difference between two points. Algebraically, this is
v = x1 − x0
or
x1 = x0 + v.
i i
i i
i i
i i
n−1
n−1
= xn − ai xn + ai xi
i i
n−1
= xn + ai (xi − xn )
i
n−1
= xn + ai vi .
i
Another way to think of this is that we construct a vector and add it to the origin.
This provides a one-to-one mapping between points and vectors.
We can use this to calculate the distance between two points p1 and p2 by taking
p1 − p2 , or
dist(p1 , p2 ) = (x1 − x2 )2 + (y1 − y2 )2 + (z1 − z2 )2 .
i i
i i
i i
i i
6 1. Mathematical Background
a · b = ax b x + ay b y + az b z .
There are two uses of this that are of particular interest to game physics de-
velopers. First of all, it can be used to do simple tests of the angle between two
vectors. If a · b > 0, then θ < π/2; if a · b < 0, then θ > π/2; and if a · b = 0,
then θ = π/2. In the latter case, we also say that the two vectors are orthogonal.
The other main use of the dot product is for projecting one vector onto another.
If we have two vectors a and b, we can break a into two pieces a|| and a⊥ such
that a|| + a⊥ = a and a|| points along the same direction as, or is parallel to, b
(see Figure 1.3). The vector a|| is also known as the scalar projection of a onto b.
From Equation (1.1), if b = 1, then a · b is simply a cos θ, which we
can see from Figure 1.3 is the length of the projection of a onto b. The projected
vector itself can be computed as
a|| = (a · b)b.
a⊥ = a − a|| .
a × b = (ay bz − az by , az bx − ax bz , ax by − ay bx ).
i i
i i
i i
i i
This produces a vector orthogonal to both a and b. The magnitude of the cross
product is
a × b = ab sin θ,
where θ is the angle between a and b. The direction of the cross product is
determined by the right-hand rule: taking your right hand, point the first finger in
the direction of a and the middle finger along b. Your extended thumb will point
along the cross product.
Two useful identities to be aware of are the anticommutativity and bilinearity
of the cross product:
a×b = −b × a,
a × (sb + tc) = s(a × b) + t(a × c).
1.2.6 Derivatives
We mentioned that vectors can act to represent rate of change. In particular, a
vector-valued function is the derivative of a point-valued function. If we take the
standard equation for a derivative of a function as in
x(t + h) − x(t)
x (t) = lim ,
h→0 h
i i
i i
i i
i i
8 1. Mathematical Background
we can see that the result x (t) will be a vector-valued function, as we are sub-
tracting two points and then scaling by 1/h. It can be similarly shown that the
derivative of a vector-valued function is a vector-valued function. Note that we
often write such a time derivative as simply ẋ.
i i
i i
i i
i i
C = A + B,
D = kA.
In the first case, each element cij = aij + bij , and in the second, dij = kaij .
Matrices can be transposed by swapping elements across the diagonal, i.e.,
a matrix G is the transpose of matrix A if for all i and j, gij = aji . This is
represented as
G = AT .
Finally, matrices can be multiplied:
H = AB.
Here, for a given element hij , we take the corresponding row i from A and cor-
responding column j from B, multiply them component-wise, and take the sum,
or
hij = aik bkj .
k
i i
i i
i i
i i
10 1. Mathematical Background
i i
i i
i i
i i
x = A−1 Ax.
z = Ax + y,
where A and y are a matrix and vector, respectively, of the appropriate sizes to
perform the operation. We can also represent this as a matrix calculation:
z A y x
= .
1 0T 1 1
i i
i i
i i
i i
12 1. Mathematical Background
The affine transformation will end up adding the vector y to any point we
apply it to, so y achieves translation for us. Rotation is stored in the matrix A.
Because it is for us convenient to keep them separate, we will use the first form
more often. So in three dimensions, translation will be stored as a 3-vector t and
rotation as a 3 × 3 matrix, which we will call R.
The following equation, also known as the Rodrigues formula, performs a
general rotation of a point p by θ radians around a rotation axis r̂:
where
r̂ = (x, y, z),
c = cos θ,
s = sin θ,
t = 1 − cos θ.
R(a × b) = Ra × Rb.
Note that this does not hold true for all linear transformations.
i i
i i
i i
i i
1.5. Quaternions 13
1.5 Quaternions
1.5.1 Definition
Another useful rotation representation is the quaternion. In their most general
form, quaternions are an extension of complex numbers. Recall that a complex
number can be represented as
c = a + bi,
where i2 = −1.
We can extend this to a quaternion by creating two more imaginary terms, or
q = w + xi + yj + zk,
q = (w, x, y, z).
q = (w, v).
Using the vector form makes manipulating quaternions easier for those who are
familiar with vector operations.
Note that most software packages store a quaternion as (x, y, z, w), which
matches the standard layout for vertex positions in graphics.
aq = (aw, av),
q0 + q1 = (w0 + w1 , q0 + q1 ).
q0 q1 = (w0 w1 − v0 · v1 , w0 v1 + w1 v0 + v0 × v1 ).
i i
i i
i i
i i
14 1. Mathematical Background
1
q−1 = (w, −v).
w2 + x2 + y2 + z 2
which as we see is the same as Equation (1.3) and demonstrates that quaternions
can be used for rotation.
i i
i i
i i
i i
F = ma,
i i
i i
i i
i i
16 1. Mathematical Background
Fspring = −kx,
Fdrag = −mρv.
And as position and velocity will be changing across our time interval, our forces
will as well.
One solution is to try and find a closed analytical solution, but (a) such a
solution may not be possible to find and (b) the solution may be so complex
that it is impractical to compute every frame. In addition, this constrains us to a
single set of forces for that solution, and we would like the flexibility to apply and
remove forces at will.
Instead, we will use a numerical solution. The problem we are trying to solve
is this: we have a physical simulation with a total force dependent generally on
time, position, and velocity, which we will represent as F(t, x, v). We have a
position x(t) = x0 and a starting velocity v(t) = v0 . The question is, what is
x(t + h)?
One solution to this problem is to look at the definition of a derivative. Recall
that
x(t + h) − x(t)
x (t) = lim .
h→0 h
For the moment, we will assume that h is sufficiently small and obtain an approx-
imation by treating h as our time step.
Rearranging terms, we get
.
x(t + h) = x(t) + hx (t),
i i
i i
i i
i i
or
.
x(t + h) = x(t) + hv(t).
This is known as the explicit Euler’s method. Another way of thinking of this
is that the derivative is tangent to the curve of x(t) at time t. By taking a small
enough step in the tangent direction, we should end up close to the actual solution.
Note that since we are taking a new time step each frame, the frame positions
are often represented in terms of a sequence of approximations x0 , x1 , x2 , . . . So
an alternative form for Euler’s method is
xi+1 = xi + hxi .
Including the update for velocity, our full set of simulation equations is
Note that we use the result of the velocity step in our position equation. This is
a variant of the standard Euler known as symplectic Euler, which provides more
stability for position-based forces. We will discuss symplectic Euler and other
integration methods below in more detail.
i i
i i
i i
i i
18 1. Mathematical Background
can determine the linear velocity at a displacement r from the center of rotation
(Figure 1.6) using the following equation:
v = ω × r. (1.5)
If the object is also moving with a linear velocity vl , this becomes
v = vl + ω × r.
The inertial tensor I is the rotational equivalent to mass. Rather than the single
scalar value of mass, the inertial tensor is a 3 × 3 matrix. This is because the
shape and density of an object affects how it rotates. For example, consider a
skater doing a spin. If she draws her arms in, her angular velocity increases. So
by changing her shape, she is changing her rotational dynamics.
Computing the inertial tensor for an object is not always easy. Often, we can
approximate it by using the inertial tensor for a simpler shape. For example, we
could use a box to approximate a car or a cylinder to approximate a statue. If
we want a more accurate representation, we can assume a constant density object
and compute it based on the tessellated geometry. One way to think of this is as
the sum of tetrahedra, where each tetrahedron shares a common vertex with the
others, and the other vertices are one face of the original geometry. As the inertial
tensor for a tetrahedron is a known quantity, this is a relatively straightforward
calculation [Kallay 06]. A quantity that has no linear complement is the center
of mass. This is a point, relative to the object, where applying a force invokes
no rotation. We can think of this as the perfect balance point. The placement of
the center of mass varies with the density or shape of an object. So a uniformly
dense and symmetric steel bar will have its center of mass at its geometric cen-
ter, whereas a hammer, for example, has its center of mass closer to its head.
Placement of the center of mass can be done in a data-driven way by artists or
designers, but more often, it comes out of the same calculation that computes the
inertial tensor.
i i
i i
i i
i i
The final quantity is torque, which is the rotational equivalent to force. Ap-
plying force to an object at any place other than its center of mass will generate
torque. To compute the torque, we take a vector r from the center of mass to the
point where the force is applied and perform a cross product as follows:
τ = r × F.
This will apply the torque counterclockwise around the vector direction, as per
the right-hand rule. We can sum all torques to determine the total torque on an
object:
τtot = rj × Fj .
j
As with force, we can use Newton’s second law to find the relationship be-
tween torque and angular acceleration α:
τ = Iα.
Ri+1 = Ri + hωi .
i i
i i
i i
i i
20 1. Mathematical Background
from that, create a differential rotation matrix. However, there is another way to
do a cross product and that is to use a skew symmetric matrix of the appropriate
form, which is just what [ω]× is. Multiplying rj by the skew symmetric matrix
[ω]× will perform the cross product ω × rj , and multiplying R by [ω]× will
perform the cross product on all the basis vectors as a single operation, giving us
our desired result of dR/dt.
w = (0, ω).
There are a number of proofs for this, though none are as intuitive as the one
for rotation matrices. The most straightforward is from [Hanson 06]. If we take a
quaternion q to the t power, we find that
i i
i i
i i
i i
At t = 0, this is just
dq
= log q
dt
θ
= 0, r̂ .
2
1
Pulling out the 2 term, we get
1 1
(0, θr̂) = w.
2 2
Multiplying this quantity by the quaternion q gives the change relative to q, just
as it did for matrices.
ωi+1 = ωi + hI−1 τ.
However, as
τ = Iω̇ + ω × Iω,
we cannot simply multiply τ by the inverse of I and do the Euler step.
One solution is to ignore the ω ×Iω term and perform the Euler step as written
anyway. This term represents the precession of the system—for example, a tipped,
spinning top will spin about its local axis but will also slowly precess around its
vertical axis as well. Removing this term will not be strictly accurate but can add
some stability.
The alternative is to do the integration in a different way. Consider the angular
momentum L instead, which is Iω. The derivative L̇ = Iω̇ = Iα = τ . Hence we
can do the following:
Li+1 = Li + hτ,
ωi+1 = I−1
i Li+1 .
i i
i i
i i
i i
22 1. Mathematical Background
We can think of this as rotating the angular momentum vector into the object’s
local orientation, applying the inverse inertial tensor, and then rotating back into
world coordinates.
This gives us our final formulas:
τ = rk × Fk ,
k
Li+1 = Li + hτ,
I−1
i = Ri I−1 −1
0 Ri ,
ωi+1 = I−1
i Li+1 ,
Ri+1 = Ri + hωi+1 .
i i
i i
i i
i i
engines do just that for that reason), because of the nature of Euler’s method the
error will still accumulate.
i i
i i
i i
i i
24 1. Mathematical Background
This is known as the implicit Euler method. The distinction between the implicit
and explicit methods is that with the implicit methods, the right side includes
terms that are not yet known. Implicit Euler is a first-order implicit method—it is
possible to create higher-order methods just as we did for explicit methods.
Whereas explicit methods add energy to the system as they drift away from
the actual function, implicit methods remove energy from the system. So while
implicit methods still do not handle oscillating or stiff equations perfectly, they
do not end up oscillating out of control. Instead, the system will damp down
much faster than expected. The solution converges, which is not ideal, but does
maintain stability.
We do have the problem that x (t + h) is unknown. There are three possible
ways to solve this. One is to try to solve for an analytic solution. However,
as before, this is not always possible, and often we do not have an equation for
x (t)—it is a function we call in our simulator that returns a numeric result. That
result could be computed from any number of combinations of other equations.
So, for both reasons, it is usually not practical to compute an explicit solution. In
this case, we have two choices.
The first is to compute x(t + h) using an explicit method and then use the
result to compute our implicit function. This is known as a predictor-corrector
method, as we predict a solution using the explicit equation and then correct for
errors using the implicit solution. An example of this is using the result of an
explicit Euler step in a modified implicit Euler solution:
x̃i+1 = xi + hvi ,
ṽi+1 = vi + hF(ti , xi , vi )/m,
h
xi+1 = xi + (ṽi+1 + vi ),
2
h
vi+1 = vi + (F(t̃i+1 , x̃i+1 , ṽi+1 ) + F(ti , xi , vi ))/m.
2
An alternative method for implicit Euler is to treat it as a linear equation and
solve for it. We can do this for a force dependent on position as follows:
xx+1 = xi + hi xi+1 ,
xi + Δxi = xi + hi F(xi + Δxi ),
Δxi = hi F(xi + Δxi ),
Δxi ≈ hi (F(xi ) + J(xi )Δxi ),
−1
1
Δxi ≈ E − J(xi ) F(xi ),
hi
i i
i i
i i
i i
While standard Verlet is quite stable, it has the disadvantage that it doesn’t
incorporate velocity. This makes it difficult to use with velocity-dependent forces.
One possible solution is to use Leapfrog Verlet:
However, this does not compute the velocity at the current time step, but in-
stead at the half-time step (this is initialized by using a half-interval Euler step).
While we can take an average of these over two time steps for our force calcula-
tion, we still have problems with impulse-based collision systems, which instan-
taneously modify velocity to simulate contact forces. One solution to this is use
the full velocity Verlet:
vi+1/2 = vi + h/2ai ,
xi+1 = xi + hvi+1/2 ,
vi+1 = vi+1/2 + h/2ai+1 .
However, unlike Euler’s method, this does require two force calculations, and we
can get similar stability with the last method we’ll consider.
More information on Verlet methods can be found in Chapter 11.
i i
i i
i i
i i
26 1. Mathematical Background
This takes advantage of the fact that velocity is the derivative of position, and
the end result is that we get a very stable method that only requires one force
calculation. It does have the disadvantage that it is not as accurate with constant
forces, but in those cases, we should consider using Equation (1.4) anyway.
In Figure 1.9, we see the result of using symplectic Euler with one step of our
orbit example. Admittedly this is a bit contrived, but we see that, in principle,
it is extremely stable—neither spiraling outward as explicit Euler would do nor
spiraling inward as implicit Euler would do.
i i
i i
i i
i i
Bibliography 27
Bibliography
[Anton and Rorres 94] Howard Anton and Chris Rorres. Elementary Linear Al-
gebra: Applications Version, Seventh edition. New York: John Wiley and
Sons, 1994.
[Axler 97] Sheldon Axler. Linear Algebra Done Right, Second edition. New
York: Springer, 1997.
[Catto 06] Erin Catto. “Fast and Simple Physics using Sequential Impulses.”
Paper presented at GDC 2006 Tutorial “Physics for Game Programmers,”
San Jose, CA, March, 2006.
[Golub and Van Loan 93] Gene H. Golub and Charles F. Van Loan. Matrix Com-
putations. Baltimore, MD: Johns Hopkins University Press, 1993.
[Hecker 97] Chris Hecker. “Behind the Screen: Physics.” Series published in
Game Developer Magazine, 1996–1997.
[Joy 00a] Kenneth Joy. “On-Line Geometric Modeling Notes: Affine Combina-
tions, Barycentric Coordinates and Convex Combinations.” Technical re-
port, University of California, Davis, 2000.
[Joy 00b] Kenneth Joy. “On-Line Geometric Modeling Notes: Points and Vec-
tors.” Technical report, University of California, Davis, 2000.
[Joy 00c] Kenneth Joy. “On-Line Geometric Modeling Notes: Vector Spaces.”
Technical report, University of California, Davis, 2000.
[Kallay 06] Michael Kallay. “Computing the Moment of Inertia of a Solid De-
fined by a Triangle Mesh.” journal of graphics tools 11:2 (2006), 51–57.
[Press et al. 93] William H. Press, Brian P. Flannery, Saul A. Teukolsky, and
William T. Vetterling. Numerical Recipes in C: The Art of Scientific Com-
puting, Second edition. New York: Cambridge University Press, 1993.
i i
i i
i i
i i
28 Bibliography
[Van Verth and Bishop 08] James M. Van Verth and Lars M. Bishop. Essential
Mathematics for Games and Interactive Applications, Second edition. San
Francisco: Morgan Kaufmann, 2008.
[Witkin and Baraff 01] Andrew Witkin and David Baraff. “Physically Based
Modelling: Principles and Practice.” ACM SIGGRAPH 2001 Course Notes.
Available at http://www.pixar.com/companyinfo/research/pbm2001/, 2001.
i i
i i
i i
i i
-2-
Understanding
Game Physics Artifacts
Dennis Gustafsson
2.1 Introduction
Physics engines are known for being notoriously hard to debug. For most people,
physics artifacts are just a seemingly random stream of weird behavior that makes
no sense. Few components of a game engine cause much frustration and hair
loss. We have all seen ragdolls doing the funky monkey dance and stacks of
“rigid” bodies acting more like a tower of greasy mushrooms, eventually falling
over or taking off into the stratosphere. This chapter will help you understand the
underlying causes of this behavior and common mistakes that lead to it. Some of
them can be fixed, some of them can be worked around, and some of them we will
just have to live with for now. This is mostly written for people writing a physics
engine of their own, but understanding the underlying mechanisms is helpful even
if you are using an off-the-shelf product.
29
i i
i i
i i
i i
1 2 3
Figure 2.1. Discretization can cause fast-moving objects to travel through walls.
Another big source of artifacts is the linearization that most physics engines
employ—the assumption that during the time step everything travels in a linear
motion. For particle physics, this is a pretty good approximation, but as soon as
you introduce rigid bodies and rotation, it falls flat to the ground. Consider the ball
joint illustrated in Figure 2.2. The two bodies are rotating in opposite directions.
At this particular point in time, the two bodies are lined up as shown. Even if
the solver manages to entirely solve the relative velocity at the joint-attachment
point to zero, as soon as time is advanced, no matter how small the amount, the
two attachment points will drift apart. This is the fundamental of linearization,
which makes it impossible to create an accurate physics engine by solving just for
relative linear velocities at discrete points in time.
Even though linearization and discretization are two different approximations,
they are somewhat interconnected. Lowering the step size (increasing the number
of substeps) will always make linearization less problematic, since any nonlinear
motion will appear more and more linear the shorter the time span. The ambitious
reader can make a parallel here to the Heisenberg principle of uncertainty!
The major takeaway here is that as long as a physics engine employs dis-
cretization and linearization, which all modern physics engines and all algorithms
1 2
Figure 2.2. Even if relative linear velocity at the joint attachment is zero, objects can
separate during integration due to rotation.
i i
i i
i i
i i
and examples in this book do, there will always be artifacts. These artifacts are
not results of a problem with the physics engine itself, but the assumptions and
approximations the engine is built upon. This is important to realize, because
once you accept the artifacts and understand their underlying causes, it makes
them easier to deal with and work around.
i i
i i
i i
i i
2.5 Solver
Just to freshen up our memory without getting into technical detail, the solver
is responsible for computing the next valid state of a dynamic system, taking
into account various constraints. Now, since games need to be responsive, this
computation has to be fast, and the most popular way of doing that is using an
iterative method called sequential impulse. The concept is really simple: given a
handful of constraints, satisfy each one of them, one at a time, and when the last
one is done, start over again from the beginning and do another round until it is
“good enough,” where good enough often means, “Sorry man, we are out of time,
let’s just leave it here.”
What is really interesting, from a debugging perspective, is how this early
termination of a sequential impulse solver can affect the energy of the system.
Stopping before we are done will not add energy to the system, it will drain en-
ergy. This means it is really hard to blame the solver itself for energy being added
to the system.
When you implement a sequential impulse solver with early termination,
stacked, resting objects tend to sink into each other. Let’s investigate why this is
happening: at each frame, gravity causes an acceleration that increases an object’s
downward velocity. Contact generation creates a set of points and at each contact,
the solver tries to maintain a zero-relative velocity. However, since greedy game
i i
i i
i i
i i
2.5. Solver 33
programmers want CPU cycles for other things, the solver is terminated before it
is completely done, leaving the objects with a slight downward velocity instead of
zero, which is desired for resting contact. This slight downward velocity causes
objects to sink in, and the process is repeated.
To compensate for this behavior, most physics engines use a geometric mea-
sure for each contact point: either penetration depth or separation distance. As
the penetration depth increases, the desired resulting velocity is biased, so that it
is not zero but is actually negative, causing the objects to separate. This translates
to objects being soft instead of rigid, where the softness is defined by how well
the solver managed to solve the problem. This is why most solvers act springy
or squishy when using fewer iterations. Hence, the best way to get rid of the
mushroom is to increase the number of iterations in the solver!
i i
i i
i i
i i
1 2 3 4
Figure 2.3. A sequential impulse solver can cause an aligned box falling flat to the ground
to bounce off with rotation.
warm starting is being used. Full warm starting can give a springy, oscillating
behavior and prevents stacks from ever falling asleep. Because of this, the cur-
rent frame’s impulses are usually initialized with only a fraction of the previous
frame’s impulses. As we increase this fraction, the solver becomes more springy,
but it can also handle stacking better. It could be worth experimenting with this
to find the sweet spot.
2.5.4 Friction
Friction is usually a little trickier than nonpenetration constraints since the max-
imum applied force depends on the normal force. The more pressure there is on
an object, the better it sticks. This interdependence results in a nonlinear problem
that is very tricky to solve accurately.
i i
i i
i i
i i
2.5. Solver 35
Friction drift. Remember the description above, about early solver termination
causing stacked objects to sink into each other? The exact same thing happens to
friction constraints, so if not compensated for, stacked objects might slide around
slowly on top of each other, eventually causing the whole thing to fall over. Track-
ing friction drift is cumbersome because it involves tracking pairs of objects over
several frames. For penetration depth it is rather straightforward since the desired
configuration is determined by the shape of the objects. For static friction, it is
not quite that easy. Static friction can be seen as a temporary joint holding two
objects together in the contact plane. If the maximum joint force is exceeded,
the objects should actually slide, but as long as the force is within the maximum
friction force, the relative net motion should ideally be zero. Hence, any motion
that actually occurs is due to early solver termination, linearization, or any other
of our artifact friends. Measuring this drift and compensating for it over time can
therefore help maintain stable stacking and natural friction behavior.
i i
i i
i i
i i
problem in such a way so that the solver can find a solution more quickly. Some
engines maintain an explicit graph of how the objects connect, whereas other en-
gines temporarily tweak mass ratios, inertia, or gravity. There is a lot of creativity
in shock propagation, but the artifacts are usually similar.
Large stacks require many iterations because the impulses at the bottom of the
stack are many times bigger than they would be for any pair of objects solved in
isolation. It takes many iterations to build up these large impulses. With shock
propagation, objects at the bottom of a stack will not feel the entire weight of the
objects on top. This can show up as the unnatural behavior of stacks tipping over
and can also be very obvious when observing friction—an object at the bottom of
a stack can be as easily pulled out as one on top.
2.6.1 Phases
Broad phase. Let us start with the broad phase, which has a relatively well-
defined task: report overlaps of bounding volumes, most often axis-aligned bound-
ing boxes. If the bounding box is too small, we might experience weird shootouts
as the broad phase reports nonoverlap until the objects are already in penetration.
Having the bounding boxes too big, on the other hand, has a performance impli-
cation, so we have to be sure to make them just right. Remember that if we use
continuous collision detection or intentional separation distance, these must be
included in the bounding-box computation, so that the bounding box is no longer
tight-fitting around the object. These errors can be hard to spot since it looks right
most of the time.
i i
i i
i i
i i
1 2
Figure 2.4. Compound geometries can cause artifacts when objects get stuck in between
parts.
is no good solution to this, but avoid using many small objects to make up com-
pound bodies. In the case above, a capsule or cylinder would have avoided the
problem.
1 2 3
Figure 2.5. An object sliding over a compound geometry can catch on invisible hooks
due to penetration.
Sliding. A similar problem can occur when an object is sliding over a flat surface
that is made up of multiple parts. Imagine the scene in Figure 2.5. The box
should ideally slide over the seam without any glitches, but they way the object
is constructed, the seam can create invisible “hooks” causing the sliding object to
1 2
Figure 2.6. Making a ramp on each side and letting them overlap is a simple work-around
to avoid objects getting stuck in compound objects.
i i
i i
i i
i i
stop. This is a typical frustrating artifact in certain car racing games where the
car can get trapped on invisible hooks while sliding along the fence. A simple
workaround is to construct the geometry as suggested in Figure 2.6.
Near phase. The near phase is by far the most complex part, where the actual
contact generation occurs. The poor solver is often blamed for unstable and jit-
tering simulations, but surprisingly often, shaking objects, general instability, and
jerkiness can be attributed to inadequate contact generation. A sequential-impulse
solver can be blamed for squishy stacks, improper friction, and many other things,
but it is actually quite hard to make a solver that causes objects to rattle and shake.
Near-phase contact generation often has many special cases and can be prone to
numerical floating-point precision issues. Some engines use contact pruning to
remove excess contact points. Special care should then be taken to make sure the
same contacts are pruned every frame. Remember that keeping the configuration
unchanged is key to stability.
1 2
Figure 2.7. Fast-moving objects are not the only ones taking shortcuts through walls.
Early solver termination can cause objects to get squished even if contacts are detected and
generated.
i i
i i
i i
i i
1 2 3 4
Figure 2.8. Fast-moving objects could potentially get rotated through the floor even if a
contact is generated.
There is also a fairly common case that is a combination of the two. Imagine
a thin rod, slightly inclined, falling onto a flat surface, as illustrated in Figure 2.8.
The initial impact on the left side can cause a rotation so severe that by the next
time step, more than half of the rod has already passed through the floor, and con-
tact generation pushes it out on the other side. This example is a good illustration
of the sometimes complex interaction between linearization and discretization
that can bring a seemingly simple case like this to epic failure, even with con-
tinuous collision detection switched on. Note that some physics engine actually
do have a really sophisticated nonlinear continuous collision detection that does
consider rotation as well, in which case the example mentioned above would have
actually worked.
Sandwich case. The sandwich case can be somewhat worked around by priori-
tizing contacts. It is always the last constraints in a sequential impulse solver that
will be the most powerful and less prone to be violated upon early termination.
Therefore, it is best to rearrange the stream of contacts so that the ones that touch
important game-play mechanisms, such as walls, are solved at the very last. A
good common practice to avoid having objects get pushed through walls or the
floor is to solve all contacts involving a static object after any other contact or do
an extra iteration or two after termination to satisfy only static contacts.
i i
i i
i i
i i
2.7 Joints
Joints are at the most fundamental level simpler than contacts. It is an equality
constraint, keeping the relative velocity between two bodies to zero. No inequal-
ities, no interdependent friction, etc. However, the way we combine constraints,
and add limits, breakable constraints, joint friction, and damping typically make
them fairly complex.
2.7.1 Drift
The most common artifact with joints is drifting, i.e., an unintended separation
between the two jointed objects. It is the joint counterpart to stacked objects
sinking into each other. The solver simply fails to find a valid solution within the
limited number of iterations. However, as described in the introduction to this
chapter, even with an unlimited number of iterations, joints can still drift due to
the linearization of velocities. Most engines cope with drifting in the same way
they cope with penetration or friction drift: simply add a geometric term, acting
as a spring to compensate for the drift.
i i
i i
i i
i i
2.7. Joints 41
1 2 3
Figure 2.9. Hard joint limits might start oscillating due to discretization.
i i
i i
i i
i i
turned off. You will be surprised how good it still looks. You might want to
enable certain collisions, such as hips–lower arms, and calf-calf collisions, but in
general, it is fine to leave most of the other ones, assuming you have a decent
setup of joint limits.
Finally, add a certain amount of damping or friction to all joints. The flesh in
the human body naturally dampens any motion, so some amount of friction will
look more natural, at the same time helping our ragdoll get some sleep.
1 2
Figure 2.10. Compensating for joint drift by moving the objects is usually a really bad
idea.
i i
i i
i i
i i
including using joint motors, to physically drive the object. However, sometimes
we simply want to move an object along an animated path, totally unaffected by
collisions. Animating an object by simply setting its position is never a good
idea. It might still affect objects in its environment, but collisions will be soft and
squishy. This is partly because the velocity of the object is not updated correctly,
so for all the solver knows, there is a collision with penetration, but it is not aware
that any of the objects are moving. To avoid this, make sure to update the velocity
to match the actual motion. Some engines have convenience functions for this.
Even when the velocity is correct, if the animated object is not considerably
heavier than the objects it is colliding with, the collisions will be soft and squishy.
For an animated object to fully affect the environment, its mass and inertia tensor
should be infinite. Only then will other objects fully obey and move out of the
way. Hence, if we animate objects by setting their position, make sure to give
them correct velocity, both linear and angular, and make the mass and inertiaten-
sor temporarily infinite.
• Frame rate gradually slows down to grinding halt. You might have hit
the well of despair, where the physics engine tries to compensate for its
own slow down. Put a cap on the number of physics steps per frame or
implement a more sophisticated time-stepping algorithm.
• Simulation runs in slow motion. Check that the physics step size corre-
sponds to actual time. Keep an eye on simulation scale. A larger scale will
result in slow-motion effects.
• Objects at the bottom of a stack do not feel the weight of the ones on top.
This is caused by a shock-propagation scheme or decoupled friction with
fixed maximum force.
• Highly asymmetric objects act unstable. The low inertia around one of the
axes causes a lot of rotation. Increase inertia tensors, as if the objects were
more symmetric.
i i
i i
i i
i i
• Stacked objects act springy and objects get squashed. The solver iteration
count might be too low. We can also try adding warm starting or a shock-
propagation scheme.
• Stacks are oscillating and tend to never come to rest. Too much warm
starting is being used.
• Stacked objects slide around on each other, eventually falling over. There
is a lack of friction-drift compensation.
• An object penetrate freely and then suddenly shoots out. This can be an
incorrect bounding box or a contact-generation problem.
• Objects are getting pushed through walls by other objects. The contact
stream might not favor static contacts. Rearrange the contact stream so that
static contacts are at the end of the stream.
• Small, fast objects pass through walls. Enable continuous collision detec-
tion or early engage. If the problem still does not go away, it can be due to
rotation. Make the object thicker or increase inertia tensor.
• Falling object stop before hitting the floor and then fall down the last bit.
This is cased by early-engage contact generation. You can add some resti-
tution to hide the problem or implement more sophisticated continuous col-
lision detection.
• Jointed structures drift apart, causing visual separation. This cannot en-
tirely be avoided due to the nature of iterative solvers and linearization.
Use a direct solver to minimize the problem. You can also try a visual joint
displacement, if applicable.
• Ragdolls are shaking and never come to rest. There can be conflicting joint
limits, too many inter-bone collisions, or joint limits that are too hard.
• An animated object does not affect the environment properly. The animated
object might have incorrect velocity, or the mass or inertia is not infinite.
i i
i i
References
[Van Verth and Bishop 08] James M. Van Verth and Lars M.
Bishop. Essential Mathematics for Games and Interactive
Applications, Second edition. San Francisco: Morgan
Kaufmann, 2008.
1 32
motion will appear more and more linear the shorter the
time span. The ambitious
2.5 Solver
to the system.
1 32 4
one corner of the box hit the ground slightly before the
others (see Figure 2.3).
2.5.4 Friction
stack are many times bigger than they would be for any pair
of objects solved in
2.6.1 Phases
Broad phase. Let us start with the broad phase, which has a
relatively well
Near phase. The near phase is by far the most complex part,
where the actual
through walls—how about that! Just enable it, sit back, and
enjoy how everything
Figure 2.7). 1 2
2.7 Joints
2.7.1 Drift
ing point, but using the axes of one of the objects can be
even better, since they
look more natural, at the same time helping our ragdoll get
some sleep.
idea.
i i i i
3 - III - Particles
multiple CPUs.
and each processor (except for the ones at either end) have
two ghost regions, one
on each side. Let the effective radius (particle diameter
in the case of DEM) be
time t+Δt should not be deleted. We can also see that the
particles coming from
particles.
We are now ready to store the data in the grid. The index
of the voxel to
the index of the slice, the first voxel of the slice stored
in the table calculated in
bounding box and the first index of the voxel in each slice
have to be calculated.
putations (we will call them jobs from now on). The ith job
is responsible for particles whose indices are in n/m ≤ a <
(i + 1)n/m. Then the bounding box of the jth slice in the
ith job is B y ij,max = max a∈P ij {b y a }, B y ij,min =
min a∈P ij {b y a }, B z ij,max = max a∈P ij {b z a }, B z
ij,min = min a∈P ij {b z a }, where P ij = {a|b x a = j,
n/m ≤ a < (i + 1)n/m}. One job is processed by a block of
threads on CUDA. Since the bounding values are frequently
read and updated, they can be stored quickly on chip memory
if available. On CUDA, shared memory is used for their
storage. However, the updating of the bounding values has
to be serialized in case of write conflicts among threads.
Therefore, whenever a thread updates a bounding volume, it
has to be locked. This kills the performance when a large
number of threads are running at the same time. To increase
the efficiency of the computation, one job is split into
smaller jobs and threads in a block are also divided into
smaller thread groups. The computation can be much more
efficient because these smaller thread groups calculate
their own bounding volume data by synchronizing fewer
numbers of threads. Figure 7.7 illustrates a three-step
computation of the bounding volumes. We will look more
closely at the implementation of this computation on a
current GPU. Reducing the size of data is a good idea in
most cases because the latency of the memory access is much
higher than are the arithmetic instructions. Also, the chip
resources that can be used in computation are limited. To
maximize the efficiency of the GPU, the register and
shared-memory usage should be kept to a minimum. The size
of the shared memory on an NVIDIA G80 is 16 KB per Particle
Positions Block0 Block1 Block2 1st Step 2nd Step 3rd Step
Figure 7.7. Computation of bounding volumes.
box that reads all the bounding values from the smaller
groups. In short, we have
256 slices, 256 threads run at the merge step, and thread i
assigned to the ith slice
compares all the values of the slices from all the small
groups. Then threads write
particles.
width. Although we can make the kernel the same block size
as the number of real
Now that we have the bounding boxes for all the slices, the
number of voxels
Figure 7.8 shows how much the sliced grid improves the
memory efficiency
1st pass
2nd pass
3rd pass
4th pass
sliced grid (S), and sliced grid with sorting (SS) (see
Color Plate VII).
that total time with sorting does not spike when sorting is
introduced, although
update with sorting does takes some time. 7.5 Data Transfer
Using Grids The sliced grid in which the computation domain
is sliced by the x-axis is used by the acceleration
structure to search for neighboring particles. The data
that have to be sent to an adjacent processor are two
contiguous slices when the side length of voxels equals the
particle diameter. Generally, the data to be sent is
smaller than using a uniform grid although efficiency
depends on the distribution of particles. Sending the data
between GPUs cannot be done directly at the moment.
Therefore, the data have to be sent via main memory in two
steps: first, send the data from a GPU to main memory, then
the second GPU reads the data from main memory. Because the
neighbors of GPUs do not change, the destination of the
memory to which a GPU writes the data and the memory a GPU
reads from is defined at spatial decomposition. Figure 7.13
illustrates how this works when using four GPUs for a
simulation. Each GPU computes a subdomain, and they each
have one or two ghost regions. After the computation of a
time step, all the GPUs send the data to the predefined
location in main memory. GPUs at both ends write particle
data to one buffer and other GPUs write to two buffers. To
make sure that all the data are ready, all of the threads
are synchronized after the send. Then the reading from the
defined memory location finishes the transfer. As you can
see, these threads run completely in parallel except for
one synchronization per time step. Subdomain0 Subdomain0
Processor0 Processor1 Processor2 Processor3 Subdomain1
Subdomain2 Subdomain3 Subdomain1 Subdomain2 Subdomain3 Main
Memory Send Receive Figure 7.13. Overview of a simulation
using four GPUs.
7.6 Results
Our method was implemented using C++ and NVIDIA CUDA 1.1 on
a PC
ing and the other four GPUs for the computation of the
particle-based simulation.
municate with one other GPU when using two GPUs, but
communication with
the time for data transfer, are also shown in Figure 7.14.
These time only ex
ban and Haug 98] and [Haug 89]. I then found results
similar to what is below
this first stage, I assume that both our hinge and CV axes
are aligned along z in
and align the axes and the reference lines so that they
face up. Now, rotate pen 2
between n (1) and n (2) . Now, realign the two pens and
rotate them about their
Let’s get rid of all the indices now. The conclusion from
the experiment above
Therefore, c CV = z · q v = z T Pq = P CV q = 0, (9.6)
tions (9.2) and (9.4) since for a rotation that flips the
axis z by 180 ◦ —q (2) =
the Jacobians have full row rank when the constraints are
satisfied, some of the
now show.
Equation (9.12).
l o
1 0
( 〈 〈
( q
) 〉 〉
l o
1 0
( 〈 〈
( q
) 〉 〉
(bottom). −4 −3 −2 −1 0 l o g 1 0 ( 〈 〈 g ( q ) 〉 〉 ) Hooke
Stabilization θ 0 = 0.45 1 2 3 Time quat: 〈〈c〉〉 quat: q 0
dot: 〈〈c〉〉 dot: q 0 −4 −3 −2 −1 0 l o g 1 0 ( 〈 〈 g ( q ) 〉
〉 ) Hooke Stabilization θ 0 = 0.55 1 2 3 Time quat: 〈〈c〉〉
quat: q 0 dot: 〈〈c〉〉 dot: q 0 Figure 9.6. The CV joint is
used here for the quaternion formulation (top), and the
Hooke joint is used for the dot product one (bottom). −4 −3
−2 −1 0
l o
1 0
( 〈 〈
( q
) 〉 〉
l o
1 0
( 〈 〈
( q
) 〉 〉
0.6
0.8 1
u t
p u
t V
e l
o c
0.6
0.8 1
O
u t
p u
t V
e l
o c
velocity to the driver for the quaternion (top) and the dot
product (bottom) formulations.
11.1.1 Background
reasons.
At some point I remembered the old “demo scene” effect for
simulating rip
details.
can then be calculated on the fly from x(t) and x(t−Δt) (if
needed at all): v(t + Δt) = (x(t + Δt)− x(t))/Δt.
void UpdateLoop() {
VerletTimeStep();
SatisfyBoxConstraints();
VerletTimeStep();
while(notConverged) { SatisfyBoxConstraints()
SatisfyStickConstraints()
void TimeStep()
VerletTimeStep();
// Relaxation step
d ∗= r ∗ r / (dotprod(d, d) + r ∗ r) − 0.5;
x1 += d;
x2 −= d;
can’t be done much faster than that, and the result even
looks quite nice. The con
stiff.
was enough (in fact, the low number gave the plants exactly
the right amount of
bending behavior).
d = x2 − x1;
dlen = sqrt(dotprod(d,d));
x1 += invmass1 ∗ d ∗ f;
below.
tetrahedron: p = c 1 x 1 + c 2 x 2 + c 3 x 3 + c 4 x 4 such
that the weights sum to one:
Simply let two rigid bodies share a particle, and they will
be connected by a pin
11.6 Miscellaneous
for two frames and then give them to the Verlet integrator,
which then automati
eye.
tipliers, etc.
11.7 Conclusion
Vector3 dp = pa−pb;
distance = dp.length();
pa += dp∗0.5∗derr;
pb −= dp∗0.5∗derr;
pa += dp∗0.5∗derr∗relaxationFactor;
Vector3 v = p − pPrevious;
v = v − normal∗dot(v, normal);
pPrevious += v∗mu;
challenge.
that makes sure a given particle can never move more than
halfway through the
will push the particle out to the side it came from. This
can be done with a
12.3.2 Collisions
collision object.
normal.
12.4 Performance
or dying characters.
face.
preserved.
struct Vertex {
real mass;
tem.
simulation.
};
in nature, but there are some bodies that look and behave
as if they were rigid.
ingly well.
any net torque to the system. The basic idea is this: for
each vertex, we calculate
them as new goal positions. For those not familiar with the
topic, this should be
surface mesh will not follow the bone motion very well, and
too much contribu
tion of f rest is needed, which renders the simulation
unrealistic. The model we are
lattice.
graph.
used that mimics the real situation quite well [Shi et al.
08]. We apply yet another
slide freely along the bone. This way, the force tries to
maintain the original
joint.
The link between a joint and its parent is called the bone.
Each vertex is
normalize(axis);
The vector that points from the nearest point on the bone
to the vertex x i is
Here, start defines the first weight and count the number
of weights after the
struct ModelJoint {
char name[64];
int parent;
Vector3 pos;
Quat4 orient;
};
int i;
ModelMesh ∗m = &meshes[mesh];
Vertex ∗v = &m−>finalVertices[vertex];
ModelWeight ∗w = &m−>weights[i];
ModelJoint ∗j = &skeleton[w−>joint];
vecNormalize(axis);
totalWeight += w−>bias;
vecAdd(&totalForce, &result);
vecScale(&totalForce, 1.0f/totalWeight);
return totalForce;
for now. We can simplify our notation for the next few
calculations to (Aq− p) 2 = (Aq− p)(q T A T − p T ).
Now we write out the multiplications component-wise (take
care: u, v, w are
u ( ∑ v A uv q v − p u )( ∑ k A uw q w − p u ) = ∑ u ( ∑ v
A uv q v ) 2 − 2p u ∑ v A uv q v + ∑ u p 2 u . Taking the
derivative ∂/∂A lm to the lm component of the matrix A
yields ∂... ∂A lm = 2A lm q m q m − 2p l q m . Writing this
again in matrix-vector notation, we get 2 ( (Aq)q T − pq T
) , and setting the derivative to zero brings us to Aqq T −
pq T = 0 →A = pq T · (qq T ) −1 . Doing this calculation
with the whole sum and the mass-weights would bring us to A
= ( ∑ i m i p i q T i )( ∑ i m i q i q T i ) −1 . This is
great because this is a quantity we can actually calculate.
The second part we can throw away because it is symmetric
and, thus, cannot contain a rotation. The rest of the
expression we call A pq . Just do the math: A pq =
zeroMatrix(); for each vertex v in v i.neighbors { q =
v.restPos − cm 0; p = v.pos − cm; for all entries j, k { A
pq[j][k] += v.mass ∗ p[k] ∗ q[j]; } } By so-called polar
decomposition, we are now able to decompose the matrix A pq
into a rotation R and a scaling S: A pq = RS. How the
scaling can be obtained can be understood intuitively: if
we apply A pq to a unit vector, the rotational partR will
rotate the vector on the unit sphere, but the scaling S
will displace it from the shell of the unit sphere. Now we
apply A T pq : the rotational part R T will rotate the
vector back to the original position,
while the scaling will displace the vector even more from
the shell. So the com
Acknowledgments
chapter. The MD5 model used was built upon polygonal data
from the Stanford