Box2d personal study notes-helloworld

Source: Internet
Author: User

Refer:
The official manual and the corresponding Chinese manual for translation (thanks to the translator ).

The following content is based on the version box2d_v2.2.0.

Hello box2d
1. Description:
The first thing to note is that the box2d source code contains a helloworld example and a testbed unit test example. These two are a lot of learning references. First, understand box2d from the helloworld example.
In addition, rendering itself is not part of box2d, and testbed uses freeglut and glui libraries to render the part. Box2d is only used for calculation and is used to simulate 2D.
2. box2d Unit
To use box2d, you must first understand the unit of box2d. Box2d uses mks (m/kg/s, meter/kg/second) as the unit, angle uses radians. For many rendering engines, the unit is generally pixel, while box2d uses meters. Therefore, when combining box2d with other libraries, pay attention to the unit problem. For OpenGL, you can change the world of box2d to a window by using the viewport transform. Try to use mks as a unit in the game, and only convert the appropriate proportion to pixel during rendering, so that the game logic is clear.
About the coordinate axis, it seems that there is no reference to the coordinate axis of box2d? Maybe this is not important. I searched for it and did not find it to illustrate this problem. Assume that the axis is X to the right and Y to the right, regardless of the following.

2. About the box
The document of the old version generally mentions that "to create a world object, you must first define a world surround box. Box2d uses a box to accelerate collision detection. The size is not critical, but the proper size helps the performance. This box is better than it is too small. When an object reaches the boundary of the box, it is frozen and simulated. ". In the new box2d, creating a world object does not need to use the box as a parameter. However, I believe that the definition of the box is also available in the new version, no matter what, the surrounding box still exists in the new box2d version. If you have the opportunity to study it later. In any case, the following method is still used to create a box:

b2AABB worldAABB;worldAABB.lowerBound.Set(-100.0f, -100.0f);worldAABB.upperBound.Set(100.0f, 100.0f);

The surrounding box b2aabb is a struct, but provides the Member method (equivalent to the class), which is defined in the file b2collision. h. It has only two members, lowerbound and upperbound, which are of the b2vec2 type.

3. Create a world
Each box2d program starts from the creation of a world object. This is a management memory, object and simulated
Center. B2world constructor: b2world (const b2vec2 & gravity, bool dosleep );
Therefore, first define the Gravity Vector and sleep. Gravity Vector is clearly the direction of gravity. In the preceding coordinate axis, if the gravity vector is (0.0f,-10.0f), the gravity is in the negative direction of the Y axis, that is, downward. Whether sleep is used to tell the world that when an object stops moving, it is allowed to sleep. A sleeping object does not need any simulation. The following code creates a world:

b2Vec2 gravity(0.0f, -10.0f);bool doSleep = true;b2World world(gravity, doSleep);

4. Create a ground box
The rigid body bodies is generally created using the following steps:
A. Use Position and damping to define a body (Rigid Body)
B. Create a rigid body using a world object
C. Define a fixture using shape, friction, recovery, etc)
D. Create an accessory (fixtures) on a rigid body)
The world created above is "blank". Next we will first create a ground body. Of course, follow the four steps above.
A. Body definition: defines an object definition. When using object definition, we specify an initialization position.
B. Create a rigid body using a world object and use the above object definition as a parameter. World objects do not save references to object definitions. By default, the rigid body is static. The static rigid body does not conflict with other static rigid bodies and cannot be moved.
C. Create a ground polygon, which defines the shape. You can use the setasbox () method to define a shape as a box shape. The two parameters are half the length of the side of the X axis and Y axis. For example, setasbox (1, 2), a box (rectangle) with a size of 2 × 4 ).
D. Create a shape fitting (shape Fixture ). Use the rigid body created in section B above to create an accessory. The default accessory material attributes are used here, so you can directly use the shape as a parameter. You do not need to create an accessory definition first.
Note: Each accessory requires a parent body, including a static accessory. Of course, you can associate all static accessories with a static rigid body. In addition, the quality of static objects is 0, so the density is useless.

Similar to the above world object, it does not save the reference to the object definition, box2d does not save the reference to the shape, it will copy the data to a new b2shape object.

The code for creating a ground box is as follows:

// 2. create a ground body// a. body definitionb2BodyDef groundBodyDef;groundBodyDef.position.Set(0.0f, -10.0f);// b. creaet bodyb2Body* groundBody = world.CreateBody(&groundBodyDef);// c. create shapeb2PolygonShape groundBox;groundBox.SetAsBox(50.0f, 10.0f);   // size of box is 100m*20m// d. create fixturegroundBody->CreateFixture(&groundBox, 0.0f);    // 0.0f is density, for static body, mass is zero, so density is not used.

5. Create a dynamic object
The method for creating a dynamic object is similar to that for creating a static object. The main difference is that the quality attribute must be set for a dynamic object.

Because the default body is static, we can use b2bodytype to set it as dynamic when defining the rigid body. At the same time, here we create a fixture definition accessory definition, which is used to set its shape, density, friction coefficient, and so on, and then use the accessory definition to create a fixture accessory. (When we create a ground box above, we directly use the shape to create accessories. It is similar. It is not necessary here, but dynamic objects generally need to define density friction .) The following describes how to create a dynamic object:

// 3. create a dynamic body// a. body definiton && create bodyb2BodyDef bodyDef;bodyDef.type = b2_dynamicBody;          // Set it as dynamic body as default is static.bodyDef.position.Set(0.0f, 4.0f);b2Body* body = world.CreateBody(&bodyDef);// b. create shapeb2PolygonShape dynamicBox;dynamicBox.SetAsBox(1.0f, 1.0f); // c. fixture defitionb2FixtureDef fixtureDef;fixtureDef.shape = &dynamicBox;fixtureDef.density = 1.0f;fixtureDef.friction = 0.3f;// d. create fixturebody->CreateFixture(&fixtureDef);

6. Simulate the box2d world

Refer to the following description.

7. Cleanup

When a world object exceeded its scope or is deleted by a pointer, the memory of all objects and joints will be released.

Complete code:

/*    filename: 1.cpp    compile:        gcc -Iinclude -Llib -lBox2D -Wl,-rpath=`pwd`/lib 1.cpp*/#include <Box2D/Box2D.h>#include <stdio.h>int main() {    // 1. create a world    b2Vec2 gravity(0.0f, -10.0f);    bool doSleep = true;    b2World world(gravity, doSleep);    // 2. create a ground body (static body)    // a. body definition    b2BodyDef groundBodyDef;    groundBodyDef.position.Set(0.0f, -10.0f);    // b. creaet body    b2Body* groundBody = world.CreateBody(&groundBodyDef);    // c. create shape    b2PolygonShape groundBox;    groundBox.SetAsBox(50.0f, 10.0f);   // size of box is 100m*20m    // d. create fixture    groundBody->CreateFixture(&groundBox, 0.0f);    // 0.0f is density, for static body, mass is zero, so density is not used.    // 3. create a dynamic body    // a. body definiton && create body    b2BodyDef bodyDef;    bodyDef.type = b2_dynamicBody;          // Set it as dynamic body as default is static.    bodyDef.position.Set(0.0f, 4.0f);    b2Body* body = world.CreateBody(&bodyDef);    // b. create shape    b2PolygonShape dynamicBox;    dynamicBox.SetAsBox(1.0f, 1.0f);     // c. fixture defition    b2FixtureDef fixtureDef;    fixtureDef.shape = &dynamicBox;    fixtureDef.density = 1.0f;    fixtureDef.friction = 0.3f;    // d. create fixture    body->CreateFixture(&fixtureDef);    // 4. simulate the world    float32 timeStep = 1.0f / 60.0f;    int32 velocityIterations = 6;    int32 positionIterations = 2;    for (int32 i = 0; i < 60; ++i)    {        world.Step(timeStep, velocityIterations, positionIterations);        b2Vec2 position = body->GetPosition();        float32 angle = body->GetAngle();        printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);    }    // 5. clean up    return 0;}
0.00 4.00 0.000.00 3.99 0.000.00 3.98 0.000.00 3.97 0.000.00 3.96 0.000.00 3.94 0.000.00 3.92 0.000.00 3.90 0.00......

An understanding of STEP () in the simulated box2d world:

A key function used to simulate box2d is: World. Step (timestep, velocityiterations, positioniterations );

According to the operation in the above example, it is easy to know that this step will change the position of the Dynamic Object Body (in the above example, only the Y coordinate has changed ). So how do we understand the data? How is it calculated? To understand this problem, we need to analyze the impact of each call to a step.

Before analysis, we first explain that the velocityiterations and positioniterations parameters of STEP () do not affect the coordinate changes of the body. Therefore, we ignore the functions of these two parameters, the initial coordinates of the body are (0.0f, 4.0f ).

PS: after a long time, I still haven't understood how to calculate it... Struggling... The following content is updated based on my personal understanding...

1. timestep is understood as a time step or refresh time granularity. This value is not a frame rate. In step, collision detection and speed position update are performed. However, velocityiterations (number of speed update iterations) and positioniterations (number of position update iterations) indicate the number of computations required in each time step. Obviously, more computations are performed, so closer to the real situation, it naturally consumes more time, so the number of iterations is a balance between performance and quality, and cannot be too large or too small. However, these two parameters do not affect the final step result (for example, the above two parameters will not affect the coordinate change of the body ).

2. The understanding of timestep is a bit like a "logical time" in box2d ". Each call indicates that the time is "Pushed" by one unit. Because box2d cannot be simulated using physical time, a time step is provided to indicate time advance. This makes the simulation of box2d not different because of the actual time. For example, in the above example, the body only has gravity, so it is a free falling body movement. If it is a physical time, it is clear that S = g * T/2, so as to update the time, however, in a game engine, T should be controlled by the game. Similarly, the game says that time goes one step forward. Therefore, the world in box2d provides step (). Each call of STEP () indicates that the current world time is one step forward, therefore, it calculates the change of the location speed based on the time step, instead of the actual physical time, so the results will not be different because different machines run at different speeds, but because physical time is different, the game logic is different. To put it simply, box2d has a "Clock", but it does not walk by itself. Every call to step () is equivalent to moving the "Clock" forward to a unit. Personal understanding...

3. If the above 2 is correct... That .. It seems that I still cannot understand how the data in the above example is calculated. I can only explain why the results of each running in the above example are the same and the machines with different configurations are the same, because it does not depend on physical time. After a rough calculation, I found that no matter how timestep is modified, the result after step () is called for the first time can always conform to S = g * T * t (not divided by 2). I think, since this is a logical time, it does not seem important to divide the Unit by not dividing by 2. However, the result of the second call of STEP () does not seem to conform to S = g * T * t, I don't know how much physical time this time step corresponds... The following is the result of timestep = 5.0f/601_f and 10.0f/601_f:

Timestep = 5.0f/60366f

0.00 3.93 0.000.00 3.79 0.000.00 3.58 0.000.00 3.31 0.000.00 2.96 0.000.00 2.54 0.000.00 2.06 0.000.00 1.50 0.000.00 1.01 0.00-0.00 1.01 0.000.00 1.01 0.000.00 1.01 0.000.00 1.01 0.00。。。。。。

Timestep = 10.0f/60366f

0.00 3.72 0.000.00 3.17 0.000.00 2.33 0.000.00 1.22 0.000.00 1.01 0.000.00 1.01 0.000.00 1.01 0.000.00 1.01 0.000.00 1.01 0.00。。。。。。

Note: after calling step () several times, the location is no longer changed (y = 1.01). This is because the location will not "fall" when it hits the ground. Review the previous code. The ground position is (0,-10). It is a box with a size of 100 m * 20 m. The initial position of the dynamic body is: (0, 4), and the size is 2*2. Therefore, the top of the ground is the X axis. When the object is subject to gravity, it will "fall". When Y = 1.01 (y = 1), it will hit the X axis below it, that is, the ground, so it will not fall, which explains that the above 1.01 will not change.

When timestep = 5/60, the displacement of the falling part is H = 4-3.93, and the formula of the free falling body is: S = g * T/2. If the timestep here is the time when the physical time is pushed, in the unit of S, it is found that: S = g * T * t can be interpreted as S = 10 * (5/60) * (5/60) = 0.0694444 = H = 4-3.93, but if the same understanding is used to calculate the result after the second call of STEP (), it is incorrect: S = 10 * (2*5/60) * (2*5/60) = 0.277777, while H = 4-3.79 = 0.21 in the actual result. Similar results can be obtained when timestep is set to 10/60. This is a bit tangled .... For each timestep, how much does t correspond to in the physical formula? (It is impossible for box2d to perform simulation and it does not conform to the physical law... I mean the pressure is very high ...)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.