Box2D C++ tutorials - Fixtures
Last edited: July 14 2013Chinese version -> 中文
Fixtures
Fixtures are used to describe the size, shape, and material properties of an object in the physics scene. One body can have multiple fixtures attached to it, and the center of mass of the body will be affected by the arrangement of its fixtures. When two bodies collide, their fixtures are used to decide how they will react. The main properties of fixtures are:
- shape - a polygon or circle
- restitution - how bouncy the fixture is
- friction - how slippery it is
- density - how heavy it is in relation to its area
1 2 3 4 5 6 7 | FooTest() { b2BodyDef myBodyDef; myBodyDef.type = b2_dynamicBody; //this will be a dynamic body myBodyDef.position.Set(-10, 20); //a little to the left b2Body* dynamicBody1 = m_world->CreateBody(&myBodyDef); } |
Shapes
Every fixture has a shape which is used to check for collisions with other fixtures as it moves around the scene. A shape can be a circle or a polygon. Let's set up a circle shape...
1 2 3 | b2CircleShape circleShape; circleShape.m_p.Set(0, 0); //position, relative to body position circleShape.m_radius = 1; //radius |
1 2 3 | b2FixtureDef myFixtureDef; myFixtureDef.shape = &circleShape; //this is a pointer to the shape above dynamicBody1->CreateFixture(&myFixtureDef); //add a fixture to the body |

Now let's try a polygon shape. With polygon shapes, you can set each individual vertex of the polygon to create a customized shape, or make use of a couple of convenience functions if you want boxes or lines. Here is a customized polygon with five vertices:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //set each vertex of polygon in an array b2Vec2 vertices[5]; vertices[0].Set(-1, 2); vertices[1].Set(-1, 0); vertices[2].Set( 0, -3); vertices[3].Set( 1, 0); vertices[4].Set( 1, 1); b2PolygonShape polygonShape; polygonShape.Set(vertices, 5); //pass array to the shape myFixtureDef.shape = &polygonShape; //change the shape of the fixture myBodyDef.position.Set(0, 20); //in the middle b2Body* dynamicBody2 = m_world->CreateBody(&myBodyDef); dynamicBody2->CreateFixture(&myFixtureDef); //add a fixture to the body |

There are a few things to be careful of when creating polygon fixtures this way. Firstly there is a limit of 8 vertices per polygon by default. If you need more you can adjust the value b2_maxPolygonVertices in the file b2Settings.h. The vertices must also be specified in counter-clockwise order, and they must describe a convex polygon. A convex polygon is one which, if you were to walk around the edges of it, you always turn the same way at each corner (either always left, or always right).
If you want a rectangular fixture, the easiest way to get one of these is with the SetAsBox function which we used in the last topic:
1 2 3 4 5 | polygonShape.SetAsBox(2, 1); //a 4x2 rectangle myBodyDef.position.Set(10,20); //a bit to the right b2Body* dynamicBody3 = m_world->CreateBody(&myBodyDef); dynamicBody3->CreateFixture(&myFixtureDef); //add a fixture to the body |

Sometimes instead of a solid shape, you want to have a fixture represented by a simple line with zero thickness. This can be done with another convenience function, SetAsEdge. This function takes two points which will be the ends of the line. Let's make a static body with a long flat line fixture, near the bottom of the scene so the dynamic objects can fall onto it.
1 2 3 4 5 6 | myBodyDef.type = b2_staticBody; //change body type myBodyDef.position.Set(0,0); //middle, bottom polygonShape.SetAsEdge( b2Vec2(-15,0), b2Vec2(15,0) ); //ends of the line b2Body* staticBody = m_world->CreateBody(&myBodyDef); staticBody->CreateFixture(&myFixtureDef); //add a fixture to the body |

1 2 3 4 | b2EdgeShape edgeShape; edgeShape.Set( b2Vec2(-15,0), b2Vec2(15,0) ); myFixtureDef.shape = &edgeShape; |
Density
By now you are probably wondering why these bodies don't spin around as expected when you grab them with the mouse cursor. This is because we haven't given any density setting for the fixtures. The density of a fixture multiplied by it's area becomes the mass of that fixture. Go back to where we first declared the fixture definition, and set a density for it:
1 2 3 | b2FixtureDef myFixtureDef; ... myFixtureDef.density = 1; //new code |

Multiple fixtures
We can attach all three of these fixtures onto one body, and it's actually pretty easy - go back to each time you called CreateFixture, and instead of doing it for dynamicBody1, dynamicBody2 and dynamicBody3, change those calls so that all three fixtures get added to dynamicBody1.

1 2 3 4 5 6 7 8 9 10 | //for the custom polygon, add 10 to each x-coord vertices[0].Set(-1 +10, 2); vertices[1].Set(-1 +10, 0); vertices[2].Set( 0 +10, -3); vertices[3].Set( 1 +10, 0); vertices[4].Set( 1 +10, 1); ... //for the box, use an extended version of the SetAsBox function which allows //us to set a location and angle (location is offset from body position) polygonShape.SetAsBox(2, 1, b2Vec2(20,0), 0 ); //moved 20 units right, same angle |

Friction
Now that we know how to set up a body with multiple fixtures, let's start with an empty scene again, and set up a body with four square fixtures on it to use in the next experiments.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | FooTest() { //set up a dynamic body b2BodyDef myBodyDef; myBodyDef.type = b2_dynamicBody; myBodyDef.position.Set(0, 20); //middle b2Body* dynamicBody = m_world->CreateBody(&myBodyDef); //prepare a shape definition b2PolygonShape polygonShape; b2FixtureDef myFixtureDef; myFixtureDef.shape = &polygonShape; myFixtureDef.density = 1; //add four square shaped fixtures around the body center for ( int i = 0; i < 4; i++) { b2Vec2 pos( sinf(i*90*DEGTORAD), cosf(i*90*DEGTORAD) ); //radial placement polygonShape.SetAsBox(1, 1, pos, 0 ); //a 2x2 rectangle dynamicBody->CreateFixture(&myFixtureDef); //add a fixture to the body } //make a static floor to drop things on myBodyDef.type = b2_staticBody; myBodyDef.position.Set(0, 0); //middle, bottom b2Body* staticBody = m_world->CreateBody(&myBodyDef); polygonShape.SetAsEdge( b2Vec2(-15,0), b2Vec2(15,3) ); //slightly sloped staticBody->CreateFixture(&myFixtureDef); //add a fixture to the body } |

Try giving the fixture definition zero friction:
1 2 | myFixtureDef.density = 1; myFixtureDef.friction = 0; //new code |
1 | myFixtureDef.friction = i/4.0; |
* Note: a friction value of 1 does not always guarantee that there will be no sliding.
Restitution
Restitution measures how 'bouncy' a fixture is. Like friction, it is given a value between 0 and 1, where zero means that the fixture will not bounce at all, and one means that all the energy of the bounce will be conserved. When two fixtures collide with each other, the resulting restitution tends toward the higher of their restitution values.
Restitution values can be experimented with in the same way as the friction values above. Try setting a different bounciness for each fixture.
1 2 | myFixtureDef.friction = ...; myFixtureDef.restitution = 0; //new code |
* Note: in reality a tiny amount of energy can be lost in bouncing calculations
Changing fixture attributes at run-time
Sometimes you might want to alter the attributes of a fixture depending on events in the game. You can change the friction, density and restitution by setting these in the fixture using the setter functions. If you already have a reference to the fixture you want to change, this is pretty easy:
1 2 3 | fixture->SetDensity( ... ); fixture->SetRestitution( ... ); fixture->SetFriction( ... ); |
* Setting the density is a special case where one more step is necessary to have the changes take effect. After doing SetDensity() on the fixture, you need to call ResetMassData() on the body that the fixture belongs to.
Iterating over the fixtures in a body
If you have a body and you want to look at all the fixtures attached to it, you can do it as below. The function GetFixureList() returns the first element in a linked list of fixtures.
1 2 3 4 | for (b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext()) { //do something with the fixture 'f' } |
1 2 | b2Fixture* f = body->GetFixtureList(); //do something with the fixture 'f' |
Cleaning up
If you want to remove a fixture from a body, call the body’s DestroyFixture function:
1 2 3 | b2Fixture* myFixture = dynamicBody->CreateFixture(&myFixtureDef); ... dynamicBody->DestroyFixture(myFixture); |
Generally if you know the game logic, and how objects are likely to be destroyed, you can arrange your program to avoid using invalid fixture pointers. However if you are working on a complex project you might find it easier to use the 'destruction listener' feature provided by Box2D. This allows you to receive a notification when any fixture is destroyed so you know not to use it any more. Check out the section on 'Implicit destruction' in the 'Loose Ends' section of the user manual.