Next, you’ll learn how the position of an object is updated, and after that the first physics object the particle will be implemented.. Figure 6.11 shows a graph of how the acceleration,
Trang 1That’s pretty much all you need for a lightweight physics simulation Note that there are light-years between a physics engine like this and a proper engine For example, this “engine” doesn’t handle things like object–object collision, etc Next, you’ll learn how the position of an object is updated, and after that the first physics object (the particle) will be implemented
P OSITION , V ELOCITY , AND A CCELERATION
Next I’ll cover the three most basic physical properties of a rigid body: its position p, its velocity v, and its acceleration a In 3D space, the position of an object is described
with x, y, and z coordinates The velocity of an object is simply how the position
is changing over time In just the same way, the acceleration of an object is how the velocity changes over time The formulas for these behaviors are listed below
p n = p + v • t where p nis the new position
v n = v + a • t where v nis the new velocity
a= f
m
In the case of a 3D object, these are all described as a 3D vector with an x, y, and
z component The following code shows an example class that has the m_position,
m_velocity, and the m_accelerationvector This class implements the formulas above using a constant acceleration:
class OBJECT{
public:
OBJECT() {
m_position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_velocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_acceleration = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
}
void Update(float deltaTime) {
Trang 2
m_velocity += m_acceleration * deltaTime;
m_position += m_velocity * deltaTime;
}
private:
D3DXVECTOR3 m_position;
D3DXVECTOR3 m_velocity;
D3DXVECTOR3 m_acceleration;
};
As you can see, the m_position and the m_velocity vectors are initialized to zero, while the m_accelerationvector is pointing in the Y-direction with a constant magnitude of one Figure 6.11 shows a graph of how the acceleration, velocity, and position of an object like this change over time
In this section you have looked at how an object’s position is affected by velocity, which in turn is affected by its acceleration In the same manner, an object’s orientation is affected by its angular velocity, which in turn is affected by its torque However, since you won’t need the concepts of angular velocity and torque to create a simple ragdoll animation, I won’t dive into the detailed math
of these If you want to look into the specifics of angular velocity and torque, I suggest reading the article “Integrating the Equations of Rigid Body Motion” by Miguel Gomez [Gomez00]
T HE P ARTICLE
These days, physicists use billions of volts to try and accelerate tiny electrically charged particles and collide them with each other What you’re about to engage in
is, thankfully, much simpler than that (and also a lot less expensive) You’ll be looking at the smallest (and simplest) entity you can simulate in a physics engine:
FIGURE 6.11
Acceleration, velocity, and position over time.
Trang 3A particle can have a mass, but it does not have a volume and therefore it doesn’t have an orientation either This makes it a perfect physical entity for us beginners to start with The particle system I am about to cover here is based on the article “Advanced Character Physics” by Thomas Jakobsen [Jakobsen03] Instead of storing the velocity of a particle as a vector, you can also store it
using an object’s current position and its previous position This is called Verlet integration and works like this:
p n = 2p c - p o + a t
po = pc
p n is the new position, p c is the current position, and p ois the previous position of
an object After you calculate the new position of an object, you assign the previous position to the current As you can see, there’s no velocity in this formula since this is always implied using the difference between the current and the old position In code, this can be implemented like this:
D3DXVECTOR3 temp = m_pos;
m_pos += (m_pos - m_oldPos) + m_acceleration * deltaTime * deltaTime; m_oldPos = temp;
In this code snippet, m_posis the current position of the particle, m_oldPosis the old position, and m_accelerationis the acceleration of the particle This Verlet inte-gration also requires that the deltaTimeis fixed (i.e., not changing between updates) Although this method of updating an object may seem more complicated than the one covered previously, it does have some clear advantages Most important of these advantages is that it makes it easier to build a stable physics simulation This is due to the fact that if a particle suddenly were to collide with a wall and stop, its velocity would also become updated (i.e., set to zero), and the particle’s velocity would no longer point in the direction of the wall
The following code shows the PARTICLE class As you can see, it extends the
PHYSICS_OBJECTbase class and can therefore be simulated by the PHYSICS_ENGINEclass
class PARTICLE : public PHYSICS_OBJECT {
public:
PARTICLE();
PARTICLE(D3DXVECTOR3 pos);
void Update(float deltaTime);
void Render();
Trang 4
void AddForces();
void SatisfyConstraints(vector<OBB*> &obstacles);
private:
D3DXVECTOR3 m_pos;
D3DXVECTOR3 m_oldPos;
D3DXVECTOR3 m_forces;
float m_bounce;
};
The m_bouncemember is simply a float between [0, 1] that defines how much
of the energy is lost when the particle bounces against a surface This value is also known as the “coefficient of restitution,” or in other words, “bounciness.” With a high bounciness value, the particle will act like a rubber ball, whereas with a low value it will bounce as well as a rock The next thing you need to figure out is how
a particle behaves when it collides with a plane (remember the world is described with OBBs, which in turn can be described with six planes)
“To describe collision response, we need to partition velocity and force vectors into two orthogonal components, one normal to the collision surface, and the other parallel to it.”
[Witkin01] This same thing is shown more graphically in Figure 6.12
FIGURE 6.12
Particle and forces before collision (left).
Particle and forces after collision (right).
Trang 5VN = (N•V)N
V Nis the current velocity projected onto the normal N of the plane
VT = V – VN
V Tis the velocity parallel to the plane
V' = VT– VN
Finally, V' is the resulting velocity after the collision.
The following code snippet shows you one way to implement this particle-plane collision response using Verlet integration In this code I assume that a collision has occurred and that I know the normal of the plane with which the particle has collided
//Calculate Velocity D3DXVECTOR3 V = m_pos - m_oldPos;
//Normal Velocity D3DXVECTOR3 VN = D3DXVec3Dot(&planeNormal, &V) * planeNormal;
//Tangent Velocity D3DXVECTOR3 VT = V - VN;
//Change the old position (i.e update the particle velocity) m_oldPos = m_pos - (VT - VN * m_bounce);
First, the velocity of the particle was calculated by subtracting the position of the particle with its previous position Next, the normal and tangent velocities were calculated using the formulas above Since Verlet integration is used, you need to change the old position of the particle to make the particle go in a different direc-tion the next update You can also see that I have added the m_bouncevariable to the calculation, and in this way you can simulate particles with different “bounciness.”
Trang 6T HE S PRING
Next I’ll show you how to simulate a spring in a physics simulation In real life you find coiled springs in many different places such as car suspensions, wrist watches, pogo-sticks, etc A spring has a resting length—i.e., the length when it doesn’t try
to expand or contract When you stretch a spring away from this equilibrium length it will “pull back” with a force equivalent to the difference from its resting length This is also known as Hooke’s Law
F = – kx
EXAMPLE 6.2
This example covers the PARTICLE class as well as the particle-OBB inter-section test and response Play around with the different physics parameters
to make the particles behave differently Also try changing the environment and build something more advanced out of the Oriented Bounding Boxes.
Trang 7F is the resulting force, k is the spring constant (how strong/stiff the spring is),
and x is the spring’s current distance away from its resting length Note that if the spring is already in its resting state, the distance will be zero and so will the resulting force If an object is hanging from one end of a spring that has the other end attached
to the roof, it will have an oscillating behavior whenever the object is moved away from the resting length, as shown in Figure 6.13
As you can see in Figure 6.13, the spring makes a nice sinus shaped motion over time Eventually, however, friction will bring this oscillation to a stop (this is, incidentally, what forces us to manually wind up old mechanical clocks) In this book a specific subset of springs are of particular interest: springs with an infinite strength If you connect two particles with a spring like this, the spring will auto-matically pull or push these particles together or apart until they are exactly at the spring’s resting length from each other Using springs with infinite strength can be used to model rigid volumes like tetrahedrons, boxes, and more The following code snippet shows the implementation of the SPRINGclass As you can see, you don’t need anything other than pointers to two particles and a resting length for the spring The SPRINGclass also extends the PHYSICS_OBJECTclass and can therefore also
be simulated by the PHYSICS_ENGINEclass
FIGURE 6.13
The oscillating behavior of a spring.
Trang 8class SPRING : public PHYSICS_OBJECT {
public:
SPRING(PARTICLE *p1, PARTICLE *p2, float restLength);
void Update(float deltaTime){}
void Render();
void AddForces(){}
void SatisfyConstraints(vector<OBB*> &obstacles);
private:
PARTICLE *m_pParticle1;
PARTICLE *m_pParticle2;
float m_restLength;
};
void SPRING::SatisfyConstraints(vector<OBB*> &obstacles) {
D3DXVECTOR3 delta = m_pParticle1->m_pos - m_pParticle2->m_pos; float dist = D3DXVec3Length(&delta);
float diff = (dist-m_restLength)/dist;
m_pParticle1->m_pos -= delta * 0.5f * diff;
m_pParticle2->m_pos += delta * 0.5f * diff;
}
This code shows the SPRINGclass and its most important function, the Satisfy-Constraints() function In it, the two particles are forcibly moved to a distance equal to the resting length of the spring
Trang 9As promised, this chapter contained only the “bare bones” of the knowledge needed to create a physics simulation It is important to note that all the code in this chapter has been written with clarity in mind, not optimization The simplest and most straightforward way to optimize a physics engine like this is to remove all square root calculations Write your own implementation of D3DXVec3Length(),
D3DXVec3Normalize(), etc using an approximate square root calculation For more advanced physics simulations, you’ll also need some form of space partitioning speeding up nearest neighbor queries, etc
In this chapter the game world was described using Oriented Bounding Boxes
A basic particle system was simulated as well as particles connected with springs Although it may seem like a lot more knowledge is needed to create a ragdoll
EXAMPLE 6.3
This example is a small variation of the previous example This time, how-ever, the particles are connected with springs forcing the particles to stay at
a specific distance from each other
Trang 10system, most of it has already been covered All you need to do is start creating a skeleton built of particles connected with springs In Chapter 7, a ragdoll will be created from an existing character using an open source physics engine
CHAPTER 6 EXERCISES
Implement particles with different mass and bounciness values and see how that affects the particles and springs in Example 6.3
Implement springs that don’t have infinite spring strength (use Hooke’s Law) Try to connect particles with springs to form more complex shapes and objects, such as boxes, etc
FURTHER READING
[Eberly99] Eberly, David, “Dynamic Collision Detection Using Oriented Bounding Boxes.” Available online at http://www.geometrictools.com/Documentation/ DynamicCollisionDetection.pdf, 1999
[Gomez99] Gomez, Miguel, “Simple Intersection Tests for Games.” Available online
at http://www.gamasutra.com/features/19991018/Gomez_1.htm, 1999
[Gomez00] Gomez, Miguel, “Integrating the Equations of Rigid Body Motion.” Game Programming Gems, Charles River Media, 2000
[Ibanez01] Ibanez, Luis, “Tutorial on Quaternions.” Available online at http://www itk.org/CourseWare/Training/QuaternionsI.pdf, 2001
[Jakobsen03] Jakobsen, Thomas, “Advanced Character Physics.” Available online
at http://www.gamasutra.com/resource_guide/20030121/jacobson_01.shtml, 2003 [Svarovsky00] Svarovsky, Jan, “Quaternions for Game Programming.” Game Programming Gems, Charles River Media, 2000
[Wikipedia] “Gravitational Constant.” Available online at http://en.wikipedia.org/ wiki/Gravitational_constant
[Witkin01] Witkin, Andrew, “Physically Based Modeling, Particle System Dynamics.” Available online at http://www.pixar.com/companyinfo/research/pbm2001/ pdf/notesc.pdf, 2001
Trang 12Ragdoll Simulation
7
Ragdoll animation is a procedural animation, meaning that it is not created by an artist in a 3D editing program like the animations covered in earlier chapters Instead,
it is created in runtime As its name suggests, ragdoll animation is a technique of sim-ulating a character falling or collapsing in a believable manner It is a very popular technique in first person shooter (FPS) games, where, for example, after an enemy character has been killed, he tumbles down a flight of stairs In the previous chapter you learned the basics of how a physics engine works However, the “engine” created
in the last chapter was far from a commercial engine, completely lacking support for rigid bodies (other than particles) Rigid body physics is something you will need when you implement ragdoll animation So, in this chapter I will race forward a bit
Trang 13and make use of an existing physics engine If you ever work on a commercial game project, you’ll find that they use commercial (and pretty costly) physics engines such
as Havok™, PhysX™, or similar Luckily, there are several good open-source physics engines that are free to download and use In this chapter I’ll use the Bullet physics engine, but there are several other open-source libraries that may suit you better (for example, ODE, Box2D, or Tokamak) This chapter covers the following:
Introduction to the Bullet physics engine Creating the physical ragdoll representation Creating constraints
Applying a mesh to the ragdoll
Before you continue with the rest of this chapter, I recommend that you go to the following site:
http://www.fun-motion.com/physics-games/sumotori-dreams/
Download the amazing 87 kb Sumotori Dreams game and give it a go (free down-load) It is a game where you control a Sumo-wrestling ragdoll This game demo
is not only an excellent example of ragdoll physics, but it is also quite fun! Figure 7.1 shows a screenshot of Sumotori Dreams:
FIGURE 7.1
A screenshot of Sumotori Dreams.