Box2D (C++) triangle shape failing area assert - c++

I'm creating a triangle shaped polygon in Box2D (C++) using this code:
b2FixtureDef fixtureDef;
b2PolygonShape dynamicPolygon;
b2Vec2 vertices[3];
vertices[0].Set(0, -1);
vertices[1].Set(-1, 1);
vertices[2].Set(1, 1);
dynamicPolygon.Set(vertices, 3);
fixtureDef.shape = &dynamicPolygon;
However, upon running this code, I get this error:
a.out: ./Box2D/Collision/Shapes/b2PolygonShape.cpp:127: b2Vec2 ComputeCentroid(const b2Vec2*, int32): Assertion `area > 1.19209289550781250000e-7F' failed.
The area seems to be too small, however, the points should make a correct triangle?
Any ideas?

I needed to swap the values of vertices 1 and 2:
b2FixtureDef fixtureDef;
b2PolygonShape dynamicPolygon;
b2Vec2 vertices[3];
vertices[0].Set(0, -1);
vertices[1].Set(1, 1);
vertices[2].Set(-1, 1);
dynamicPolygon.Set(vertices, 3);
fixtureDef.shape = &dynamicPolygon;
This option puts the vertices in counter-clockwise order works...

Related

The Gravity in Box2D world

When the gravity is very small, the dynamic object will not move after moving for a short distance. When I run this method, the result is The change of dynamic body' position. When the dynamic body moves to a certain position, it will stop. I do not know why. Maybe the precision problem of floating number?
This is the method I run.
void initializeWorld()
{
// Define the gravity vector.
b2Vec2 gravity(0.0f, 0.011f);
// Construct a world object, which will hold and simulate the rigid bodies.
b2World world(gravity);
// Define the up ground body.
b2BodyDef groundBodyDefUp;
groundBodyDefUp.position.Set(0.0f, 8.0f);
// Define the down ground body.
b2BodyDef groundBodyDefDown;
groundBodyDefDown.position.Set(0.0f, -8.0f);
// Define the left ground body
b2BodyDef groundBodyDefLeft;
groundBodyDefLeft.position.Set(-8.0f,0.0f);
// Define the right ground body
b2BodyDef groundBodyDefRight;
groundBodyDefRight.position.Set(8.0f, 0.0f);
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBodyUp = world.CreateBody(&groundBodyDefUp);
b2Body* groundBodyDown = world.CreateBody(&groundBodyDefDown);
b2Body* groundBodyLeft = world.CreateBody(&groundBodyDefLeft);
b2Body* groundBodyRight = world.CreateBody(&groundBodyDefRight);
// Define the ground box shape.
b2PolygonShape groundBoxUp;
// The extents are the half-widths of the box.
groundBoxUp.SetAsBox(5.0f, 3.0f);
// Define the ground box shape.
b2PolygonShape groundBoxDown;
// The extents are the half-widths of the box.
groundBoxDown.SetAsBox(5.0f, 3.0f); // Define the ground box shape.
// Define the ground box shape.
b2PolygonShape groundBoxLeft;
// The extents are the half-widths of the box.
groundBoxLeft.SetAsBox(3.0f, 5.0f); // Define the ground box shape.
// Define the ground box shape.
b2PolygonShape groundBoxRight;
// The extents are the half-widths of the box.
groundBoxRight.SetAsBox(3.0f, 5.0f); // Define the ground box shape.
// Add the ground fixture to the ground body.
groundBodyUp->CreateFixture(&groundBoxUp, 0.0f);
/*groundBodyDown->CreateFixture(&groundBoxDown, 0.0f);
groundBodyLeft->CreateFixture(&groundBoxLeft, 0.0f);
groundBodyRight->CreateFixture(&groundBoxRight, 0.0f);*/
// Define the dynamic body. We set its position and call the body factory.
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(0.0f, 0.0f);
b2Body* body = world.CreateBody(&bodyDef);
// Define another box shape for our dynamic body.
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(0.5f, 0.5f);
// Define the dynamic body fixture.
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
// Set the box density to be non-zero, so it will be dynamic.
fixtureDef.density = 1.0f;
// Override the default friction.
fixtureDef.friction = 0.3f;
// Add the shape to the body.
body->CreateFixture(&fixtureDef);
// Prepare for simulation. Typically we use a time step of 1/60 of a
// second (60Hz) and 10 iterations. This provides a high quality simulation
// in most game scenarios.
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;
bool running = true;
while (running)
{
world.Step(timeStep, velocityIterations, positionIterations);
b2Vec2 position = body->GetPosition();
cout << "(" << position.x << "," << position.y <<")"<< endl;
}
}

TimeStep do not iterate | Box2D

i am getting back to box2d after many years of absence and thought to start from zero. on top of that decided to work with the C++ version this time (in the past worked with the Javascript version)
For a reason the very first program described in box2d.org does not run properly. When i compile it i do not get any errors however the result is wrong.
The result is 0.00 4.00 0.00 and remains as such.
But with each iteration of timestep, the position.y should decrease (position.x and angle should remain the same)
#include "include/box2d/box2d.h"
#include <iostream>
#include <stdio.h>
int main(){
b2Vec2 gravity(0.0f, -10.0f); // define the gravity vector
b2World world(gravity); //create the world object
//Creating static Ground Body
b2BodyDef groundBodyDef; //body definition
groundBodyDef.position.Set(0.0f, -10.0f);
b2Body* groundBody = world.CreateBody(&groundBodyDef); // body definition is passed to the world object to create the ground body
b2PolygonShape groundBox; //create a ground polygon.
groundBox.SetAsBox(50.0f, 10.0f); //We use the SetAsBox shortcut to form the ground polygon into a box shape
groundBody->CreateFixture(&groundBox, 0.0f); //creating the shape fixture
//Creating Dynamic Body
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody; //By default bodies are static, so we should set the b2BodyType at construction time to make the body dynamic
bodyDef.position.Set(0.0f, 4.0f);
b2Body* body = world.CreateBody(&bodyDef);
b2PolygonShape dynamicBox; //create a box shap
dynamicBox.SetAsBox(1.0f, 1.0f);
//A dynamic body should have at least one fixture with a non-zero density. Otherwise you will get strange behavior.
b2FixtureDef fixtureDef; // fixture definition using the box
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
float timeStep = 1.0f / 60.0f; //Integrators simulate the physics equations at discrete points of time -> ie timeStep
int32 velocityIterations = 6;
int32 positionIterations = 2;
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);
}
//return 0;
}
Apologies for the noobie question, but cannot find my mistake. i almost copy paste everything!
I actually forgot to include body->CreateFixture(&fixtureDef);

Assertion failed : area > 1.19209

I'm getting this weird error when I run my program that uses Box2D which is really unexpected because it's in a file which is nowhere related to my project(unbuilt folder not linked to my project). I obtained a copy for Box2D for VS12 and built it for my project and setup-ed the project following a tutorial here:https://www.youtube.com/watch?v=kEClRFKyGkw&list=PLSPw4ASQYyymu3PfG9gxywSPghnSMiOAW&index=53
Here's my code:
void Box::init(b2World* world, const glm::vec2& position, const glm::vec2& dimensions)
{
m_dimensions = dimensions;
b2BodyDef boxDef;
boxDef.type = b2_dynamicBody;
boxDef.position.Set(position.x, position.y);
m_body = world->CreateBody(&boxDef);
b2PolygonShape boxShape;
boxShape.SetAsBox(position.x / 2.0f, position.y / 2.0f);
b2FixtureDef fixtureDef;
fixtureDef.shape = &boxShape;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
m_fixture = m_body->CreateFixture(&fixtureDef);
}
Where I've called the init():
b2Vec2 gravity(0.0f, -9.8f);
m_world = std::make_unique<b2World>(gravity);
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f, -10.0f);
b2Body* groundBody = m_world->CreateBody(&groundBodyDef);
b2PolygonShape groundShape;
groundShape.SetAsBox(50.0f, 10.0f);
groundBody->CreateFixture(&groundShape, 0.0f);
Box newBox;
newBox.init(m_world.get(), glm::vec2(0.0f, 14.0f), glm::vec2(15.0f, 15.0f));
m_boxes.push_back(newBox);
A window pop's up as this:
The error printed on my console:
Assertion failed : area > 1.19209 2896e-07F,
path_to_unbuild_box2d\box2d_v2.3.0\box2d\box2d\collision\shapes\b2
polygonshape.cpp, line 422
Here's where the error occur (when I click Retry) line 336 b2Fixture.h:
inline void b2Fixture::GetMassData(b2MassData* massData) const
{
m_shape->ComputeMass(massData, m_density);
}
Problem 1 fixed
boxShape.SetAsBox(dimensions.x / 2.0f, dimensions.y / 2.0f); ///Instead of position.
The line of code that's failing is (as mentioned in the "Assertion failed" message):
b2Assert(area > b2_epsilon);
It means your polygon has a puny size (look at the assertion, the area is less than 1.192092896e-07F, which is the value 0.0000001192092896, which is tiny).
Likely boxShape has the invalid size. Set a breakpoint on the line:
boxShape.SetAsBox(position.x / 2.0f, position.y / 2.0f);
and inspect the value of position. Make sure you're setting the box's dimensions to a sane value. My bet is that you aren't.

Box2D debug test

I have a problem with Box2d. I created an object (circle) in the center of the screen that rotates to see if I set Box2d well, following the tutorial that I found on internet. The problem is that the circle is created, but I can't rotate despite I followed exactly the tutorial found on internet. This is the code:
file .h:
b2World * _world;
GLESDebugDraw * _debugDraw;
file .mm:
-(void)setupWorld {
b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
bool doSleep = false;
_world = new b2World(gravity, doSleep);
}
-(void)setupDebugDraw {
_debugDraw = new GLESDebugDraw(PTM_RATIO*[[CCDirector sharedDirector] contentScaleFactor]);
_world->SetDebugDraw(_debugDraw);
_debugDraw->SetFlags(b2DebugDraw::e_shapeBit |b2DebugDraw::e_jointBit);
}
-(void)testBox2D {
CGSize winSize = [CCDirector sharedDirector].winSize;
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position = b2Vec2(winSize.width/2/PTM_RATIO,winSize.height/2/PTM_RATIO);
b2Body *body = _world->CreateBody(&bodyDef);
b2CircleShape circleShape;
circleShape.m_radius = 25.0/PTM_RATIO;
b2FixtureDef fixtureDef;
fixtureDef.shape = &circleShape;
fixtureDef.density = 1.0;
body->CreateFixture(&fixtureDef);
body->ApplyAngularImpulse(0.01);
}
-(void)updateBox2D:(ccTime)dt {
_world->Step(dt, 1, 1);
[self updateBox2D:dt];
}
-(void) draw {
glDisable(GL_TEXTURE_2D); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
_world->DrawDebugData();
glEnable(GL_TEXTURE_2D); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

in init:
[self setupWorld];
[self setupDebugDraw];
[self testBox2D];
Two problems:
Are you recursively calling updateBox2D? This looks like an infinite loop to me, and I'm surprised that it's not crashing your application.
Instead, you should only call your world's step once (or a few times depending on how you've setup your time step) during your CCScene tick method.
Your next problem is that you're applying a small impulse to your body, but it is only a one-time impulse... Angular impulses are still affected by damping, so the body will not rotate indefinitely by default. To keep your body rotating, you need to set the angular damping to zero:
bodyDef.angularDamping = 0.0f;

Cocos2d draw a polygon using CCSprite

Can you help. Want to draw a polygon (beams at different angles) and apply box 2d body to it. Can you please let me know how to create a CCSprite with a polygon shape
Any examples would help
Cheers
Create Polygon body.
-(void) createDynamicPoly {
b2BodyDef bodyDefPoly;
bodyDefPoly.type = b2_dynamicBody;
bodyDefPoly.position.Set(3.0f, 10.0f);
b2Body *polyBody = world->CreateBody(&bodyDefPoly);
int count = 8;
b2Vec2 vertices[8];
vertices[0].Set(0.0f / PTM_RATIO,0.0f / PTM_RATIO);
vertices[1].Set(48.0f/PTM_RATIO,0.0f/PTM_RATIO);
vertices[2].Set(48.0f/PTM_RATIO,30.0f/PTM_RATIO);
vertices[3].Set(42.0f/PTM_RATIO,30.0f/PTM_RATIO);
vertices[4].Set(30.0f/PTM_RATIO,18.0f/PTM_RATIO);
vertices[5].Set(18.0f/PTM_RATIO,12.0f/PTM_RATIO);
vertices[6].Set(6.0f/PTM_RATIO,18.0f/PTM_RATIO);
vertices[7].Set(0.0f/PTM_RATIO,30.0f/PTM_RATIO);
b2PolygonShape polygon;
polygon.Set(vertices, count);
b2FixtureDef fixtureDefPoly;
fixtureDefPoly.shape = &polygon;
fixtureDefPoly.density = 1.0f;
fixtureDefPoly.friction = 0.3f;
polyBody->CreateFixture(&fixtureDefPoly);
}
Create your sprite
Attach your sprite to the Polygon body via Fixture and UserData
fixtureDefPoly.SetUserData() = spriteObject;
b2Fixture *fixture;
fixture = circleBody->CreateFixture(&fixtureDefPoly);
fixture->SetUserData(#"spriteObject");
Then Iterate the sprite to the body in your update method.
The easiest way is to open an image editor (such as paint for example or photoshop) and create the image you want. The use it in your program.
Also there is a helloWorld scene when creating an xcode application using cocos2d box2d template. It creates a set of squares with a texture.
CGPoint startPt = edge.start ;
CGPoint endpt = edge.end ;
//length of the stick body
float len = abs(ccpDistance(startPt, endpt))/PTM_RATIO;
//to calculate the angle and position of the body.
float dx = endpt.x-startPt.x;
float dy = endpt.y-startPt.y;
//position of the body
float xPos = startPt.x+dx/2.0f;
float yPos = startPt.y+dy/2.0f;
//width of the body.
float width = 1.0f/PTM_RATIO;
b2BodyDef bodyDef;
bodyDef.position.Set(xPos/PTM_RATIO, yPos/PTM_RATIO);
bodyDef.angle = atan(dy/dx);
NSLog([NSString stringWithFormat:#"Setting angle %f",bodyDef.angle]);
CCSprite *sp = [CCSprite spriteWithFile:#"material-wood.png" rect:CGRectMake(0, 0, 12, 12)];
//TODO: fix shape
[self addChild:sp z:1 ];
bodyDef.userData = sp;
bodyDef.type = b2_dynamicBody;
b2Body* body = world->CreateBody(&bodyDef);
b2PolygonShape shape;
b2Vec2 rectangle1_vertices[4];
rectangle1_vertices[0].Set(-len/2, -width/2);
rectangle1_vertices[1].Set(len/2, -width/2);
rectangle1_vertices[2].Set(len/2, width/2);
rectangle1_vertices[3].Set(-len/2, width/2);
shape.Set(rectangle1_vertices, 4);
b2FixtureDef fd;
fd.shape = &shape;
fd.density = 1.0f;
fd.friction = 0.300000f;
fd.restitution = 0.600000f;
body->CreateFixture(&fd);