diff options
Diffstat (limited to 'Client/ThirdParty/Box2D/docs/hello.md')
-rw-r--r-- | Client/ThirdParty/Box2D/docs/hello.md | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/Client/ThirdParty/Box2D/docs/hello.md b/Client/ThirdParty/Box2D/docs/hello.md new file mode 100644 index 0000000..40d8de6 --- /dev/null +++ b/Client/ThirdParty/Box2D/docs/hello.md @@ -0,0 +1,246 @@ +# Hello Box2D +In the distribution of Box2D is a Hello World project. The program +creates a large ground box and a small dynamic box. This code does not +contain any graphics. All you will see is text output in the console of +the box's position over time. + +This is a good example of how to get up and running with Box2D. + +## Creating a World +Every Box2D program begins with the creation of a b2World object. +b2World is the physics hub that manages memory, objects, and simulation. +You can allocate the physics world on the stack, heap, or data section. + +It is easy to create a Box2D world. First, we define the gravity vector. + +```cpp +b2Vec2 gravity(0.0f, -10.0f); +``` + +Now we create the world object. Note that we are creating the world on +the stack, so the world must remain in scope. + +```cpp +b2World world(gravity); +``` + +So now we have our physics world, let's start adding some stuff to it. + +## Creating a Ground Box +Bodies are built using the following steps: +1. Define a body with position, damping, etc. +2. Use the world object to create the body. +3. Define fixtures with a shape, friction, density, etc. +4. Create fixtures on the body. + +For step 1 we create the ground body. For this we need a body +definition. With the body definition we specify the initial position of +the ground body. + +```cpp +b2BodyDef groundBodyDef; +groundBodyDef.position.Set(0.0f, -10.0f); +``` + +For step 2 the body definition is passed to the world object to create +the ground body. The world object does not keep a reference to the body +definition. Bodies are static by default. Static bodies don't collide +with other static bodies and are immovable. + +```cpp +b2Body* groundBody = world.CreateBody(&groundBodyDef); +``` + +For step 3 we create a ground polygon. We use the SetAsBox shortcut to +form the ground polygon into a box shape, with the box centered on the +origin of the parent body. + +```cpp +b2PolygonShape groundBox; +groundBox.SetAsBox(50.0f, 10.0f); +``` + +The SetAsBox function takes the **half**-**width** and +**half**-**height** (extents). So in this case the ground box is 100 +units wide (x-axis) and 20 units tall (y-axis). Box2D is tuned for +meters, kilograms, and seconds. So you can consider the extents to be in +meters. Box2D generally works best when objects are the size of typical +real world objects. For example, a barrel is about 1 meter tall. Due to +the limitations of floating point arithmetic, using Box2D to model the +movement of glaciers or dust particles is not a good idea. + +We finish the ground body in step 4 by creating the shape fixture. For +this step we have a shortcut. We do not have a need to alter the default +fixture material properties, so we can pass the shape directly to the +body without creating a fixture definition. Later we will see how to use +a fixture definition for customized material properties. The second +parameter is the shape density in kilograms per meter squared. A static +body has zero mass by definition, so the density is not used in this +case. + +```cpp +groundBody->CreateFixture(&groundBox, 0.0f); +``` + +Box2D does not keep a reference to the shape. It clones the data into a +new b2Shape object. + +Note that every fixture must have a parent body, even fixtures that are +static. However, you can attach all static fixtures to a single static +body. + +When you attach a shape to a body using a fixture, the shape's +coordinates become local to the body. So when the body moves, so does +the shape. A fixture's world transform is inherited from the parent +body. A fixture does not have a transform independent of the body. So we +don't move a shape around on the body. Moving or modifying a shape that +is on a body is not supported. The reason is simple: a body with +morphing shapes is not a rigid body, but Box2D is a rigid body engine. +Many of the assumptions made in Box2D are based on the rigid body model. +If this is violated many things will break + +## Creating a Dynamic Body +So now we have a ground body. We can use the same technique to create a +dynamic body. The main difference, besides dimensions, is that we must +establish the dynamic body's mass properties. + +First we create the body using CreateBody. By default bodies are static, +so we should set the b2BodyType at construction time to make the body +dynamic. + +```cpp +b2BodyDef bodyDef; +bodyDef.type = b2_dynamicBody; +bodyDef.position.Set(0.0f, 4.0f); +b2Body* body = world.CreateBody(&bodyDef); +``` + +> **Caution**: +> You must set the body type to b2_dynamicBody if you want the body to +> move in response to forces. + +Next we create and attach a polygon shape using a fixture definition. +First we create a box shape: + +```cpp +b2PolygonShape dynamicBox; +dynamicBox.SetAsBox(1.0f, 1.0f); +``` + +Next we create a fixture definition using the box. Notice that we set +density to 1. The default density is zero. Also, the friction on the +shape is set to 0.3. + +```cpp +b2FixtureDef fixtureDef; +fixtureDef.shape = &dynamicBox; +fixtureDef.density = 1.0f; +fixtureDef.friction = 0.3f; +``` + +> **Caution**: +> A dynamic body should have at least one fixture with a non-zero density. +> Otherwise you will get strange behavior. + +Using the fixture definition we can now create the fixture. This +automatically updates the mass of the body. You can add as many fixtures +as you like to a body. Each one contributes to the total mass. + +```cpp +body->CreateFixture(&fixtureDef); +``` + +That's it for initialization. We are now ready to begin simulating. + +## Simulating the World +So we have initialized the ground box and a dynamic box. Now we are +ready to set Newton loose to do his thing. We just have a couple more +issues to consider. + +Box2D uses a computational algorithm called an integrator. Integrators +simulate the physics equations at discrete points of time. This goes +along with the traditional game loop where we essentially have a flip +book of movement on the screen. So we need to pick a time step for +Box2D. Generally physics engines for games like a time step at least as +fast as 60Hz or 1/60 seconds. You can get away with larger time steps, +but you will have to be more careful about setting up the definitions +for your world. We also don't like the time step to change much. A +variable time step produces variable results, which makes it difficult +to debug. So don't tie the time step to your frame rate (unless you +really, really have to). Without further ado, here is the time step. + +```cpp +float timeStep = 1.0f / 60.0f; +``` + +In addition to the integrator, Box2D also uses a larger bit of code +called a constraint solver. The constraint solver solves all the +constraints in the simulation, one at a time. A single constraint can be +solved perfectly. However, when we solve one constraint, we slightly +disrupt other constraints. To get a good solution, we need to iterate +over all constraints a number of times. + +There are two phases in the constraint solver: a velocity phase and a +position phase. In the velocity phase the solver computes the impulses +necessary for the bodies to move correctly. In the position phase the +solver adjusts the positions of the bodies to reduce overlap and joint +detachment. Each phase has its own iteration count. In addition, the +position phase may exit iterations early if the errors are small. + +The suggested iteration count for Box2D is 8 for velocity and 3 for +position. You can tune this number to your liking, just keep in mind +that this has a trade-off between performance and accuracy. Using fewer +iterations increases performance but accuracy suffers. Likewise, using +more iterations decreases performance but improves the quality of your +simulation. For this simple example, we don't need much iteration. Here +are our chosen iteration counts. + +```cpp +int32 velocityIterations = 6; +int32 positionIterations = 2; +``` + +Note that the time step and the iteration count are completely +unrelated. An iteration is not a sub-step. One solver iteration is a +single pass over all the constraints within a time step. You can have +multiple passes over the constraints within a single time step. + +We are now ready to begin the simulation loop. In your game the +simulation loop can be merged with your game loop. In each pass through +your game loop you call b2World::Step. Just one call is usually enough, +depending on your frame rate and your physics time step. + +The Hello World program was designed to be simple, so it has no +graphical output. The code prints out the position and rotation of the +dynamic body. Here is the simulation loop that simulates 60 time steps +for a total of 1 second of simulated time. + +```cpp +for (int32 i = 0; i < 60; ++i) +{ + world.Step(timeStep, velocityIterations, positionIterations); + b2Vec2 position = body->GetPosition(); + float angle = body->GetAngle(); + printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle); +} +``` + +The output shows the box falling and landing on the ground box. Your +output should look like this: + +``` +0.00 4.00 0.00 +0.00 3.99 0.00 +0.00 3.98 0.00 +... +0.00 1.25 0.00 +0.00 1.13 0.00 +0.00 1.01 0.00 +``` + +## Cleanup +When a world leaves scope or is deleted by calling delete on a pointer, +all the memory reserved for bodies, fixtures, and joints is freed. This +is done to improve performance and make your life easier. However, you +will need to nullify any body, fixture, or joint pointers you have +because they will become invalid. |