Welcome to JigLibX!
With JigLibX, you can add physically based behavior to your XNA Game Studio games. This section will describe briefly how you go about doing so. However, there is no good in-depth documentation yet, so reading the actual code should be the preferred reference for how something works.
Rigid body dynamics is a kind of simulation used in games to give the appearance of "physical" behavior of objects. For each object you want to simulate, one or more bodies are defined, each of which has one or more collision primitives. For something with more than one movable part (say, a fulcrum with a lever), there is one body for each piece, and the bodies are tied together using joints. For a playground see-saw, you would have one body with a collision skin for the base, another body with another collision skin for the part that actually moves, and you would connect them with a hinge joint.
Collision primitives are basic shapes such as boxes, spheres, capsules (a cylinder with round ends, like some kinds of pills), rays/line segments, as well as slightly more advanced shapes, such as planes, heightmaps and triangle meshes. To describe the approximate outline of a given physical body (a car, a swing, a door, etc), you may want to use more than one shape, and put them together. You do that by creating a collision skin and assigning that to the body. Note that all the shapes in a collision skin move together, and move with the body; if you want different parts that move separately (the door on a car, the links in a chain), then you want to create more than one body, each of which has a different collision skin, and hook them together using some form of joint. The fact that each body has a fixed, rigid, shape is why this kind of simulation is called "rigid body dynamics."
Flow of control
In your simulation, you want to create a physics system instance. This system is the part of the code that will simulate the movement of the bodies. You want to create a collision system and assign it to the physics system, so that the physics simulator knows how to take object collisions into effect (so things don't go through walls, fall through the ground, etc). You then create one or more bodies, each of which typically has a collision skin with one or more primitives in it. When you're done, you tell the physics system to "advance time" and figure out what the simulation world will look like after a small amount of time has elapsed. You do this by calling PhysicsSystem.Integrate() and passing it the amount of time to advance by. Typically, your time step will be either the amount of time since the last GameComponent.Update() call (if you're using a variable time step), or a given amount of time (like 1/100th of a second — 0.01f), and you will step the world more than one time to make it "catch up" with the flow of real time.
Once the world is updated, you can extract the transform of each body, and apply that transform to some Model you have loaded separately. This will let you see what's going on in the physics world. Note that it's important to make a CollisionSkin for the Body that approximates the shape of the model, or the model will either appear to be hovering above ground, or it will penetrate surfaces, because the collision skin is used to keep objects apart, not the visual model. The reason for this is that shapes such as spheres, boxes and capsules are a lot cheaper (faster) to collide against each other, than something complex like a full triangle mesh.
In your XNA game, in LoadContent(), create the physics system, the collision system, and populate it with bodies that have collision skins. Remember all the bodies you added, and what model you want to go with each body.
In your XNA game Update(), call PhysicsSystem.Integrate().
In your XNA game Draw(), iterate over each of the bodies, extract the transform for the body and apply it to the model you loaded for that body. Note that JigLibX initially assumes Y is up, so gravity acts in the -Y direction.
If you create a heap of blocks or marbles using boxes and spheres, and a ground using a heightmap or plane, your simulation will show the marbles/boxes falling to the ground, and collide with each other. After a while, the simulation will come to a stop, and nothing more interesting will happen. To get some action, you will want to do two things:
- Add new bodies to the system.
- Affect the already existing bodies.
To add a new body, you do that inside Update(), before you call Integrate(). Create a new Body, give it a CollisionSkin, and add it to the PhysicsSystem. Done! This is a great way of adding, say, a cannon ball that gets shot from out of a cannon (assuming you set the velocity of the cannon ball correctly).
To affect the existing bodies, you want to call the functions AddBodyForce(), AddBodyTorque(), AddWorldForce() and AddWorldTorque(). Those functions will add forces to the bodies that are like "invisible hands" that pull on the objects. However, the accumulated forces are cleared inside PhysicsSystem.Integrate(), so anything you do in Update() won't have any effect. Instead, you need to add a controller subclass to the PhysicsSystem, using the PhysicsSystem.AddController() function.
Each time the physics system integrates, it will call the controllers, and the controllers can add forces and torques to the different objects. For example, to make an object fly upwards, you can call AddWorldForce(Vector3.Up * body.Mass * 11) on the body. Initial default gravity is 10 (newtons per kilo, close to Earth gravity), so this will add enough force to counter-act gravity and slowly accelerate the body upwards. Torques are like forces, except they cause the object to spin around its center of gravity, rather than move (translate) in the world.
The units used are newtons, meters, newton-meters, kilograms and seconds, also known as SI (Systeme Internationale) or metric units. You may be able to scale these units for different measurement systems, but it's easier to just convert everything to metric.
If you want a body to be in the world, but not move, set the Immovable property to true. This is great for the ground, because otherwise gravity would pull the ground downwards along with the rest of the objects.
The time step you use should be small to get good results of the simulation. A value of about 0.01 is about right. Too small, and the simulation will require too much computation and run slowly. Too big, and the simulation will become less stable. Note that the time between frames at 60 Hz is about 0.017, which is somewhat higher than ideal, but will usually work okay.
Look at the Car object in the Vehicles folder to see how a more complex object is put together. Note that this object doesn't use spheres for the wheels; instead it uses some number of rays, cast out in the wheel direction, to detect ground.