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.
Related
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;
}
}
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);
I am trying to detect a collision between a static body and a kinematic body using the b2ContactListener class but my code is not detecting a collision between my two fixtures. I placed an EdgeShape at the top of my kinematic body and made it a fixture to detect a collision with my static body fixture. I am using SFML to draw to the screen and detect keyboard events.
Here is my main function:
int main()
{
Vector2f resolution;
resolution.x = VideoMode::getDesktopMode().width;
resolution.y = VideoMode::getDesktopMode().height;
RenderWindow window(VideoMode(resolution.x, resolution.y),
"Box2D Test", Style::Fullscreen);
Vector2f staticRectSize(100.0f, 20.0f);
Vector2f kinematicRectSize(40.0f, 20.0f);
Event keyBoardEvent;
b2Vec2 gravity(0.0f, 0.0f);
b2World world(gravity);
// Creating static body and fixture
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(100.0f, 150.0f);
b2Body* groundBody = world.CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
groundBox.SetAsBox(50.0f, 10.0f);
groundBody->CreateFixture(&groundBox, 0.0f);
// Creating kinematic body and fixture
b2BodyDef bodyDef;
bodyDef.type = b2_kinematicBody;
bodyDef.position.Set(125.0f, 700.0f);
b2Body* body = world.CreateBody(&bodyDef);
b2PolygonShape kinematicBox;
kinematicBox.SetAsBox(20.0f, 10.0f);
b2FixtureDef fixtureDef;
fixtureDef.shape = &kinematicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
body->CreateFixture(&fixtureDef);
// world.Step inputs
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;
RectangleShape staticRect(staticRectSize);
RectangleShape dynamicRect(kinematicRectSize);
b2Vec2 staticPosition = groundBody->GetPosition();
staticRect.setPosition(staticPosition.x, staticPosition.y);
b2Vec2 dynamicPosition = body->GetPosition();
// Creating EdgeShape
b2EdgeShape top;
top.Set(b2Vec2(dynamicPosition.x, dynamicPosition.y), b2Vec2(dynamicPosition.x + 40.0, dynamicPosition.y));
fixtureDef.shape = ⊤
fixtureDef.isSensor = true;
body->CreateFixture(&fixtureDef)->SetUserData("top collision");
// Creating an instance of myContactListener class
myContactListener contactListener;
world.SetContactListener(&contactListener);
while (window.isOpen())
{
world.Step(timeStep, velocityIterations, positionIterations);
dynamicPosition = body->GetPosition();
dynamicRect.setPosition(dynamicPosition.x, dynamicPosition.y);
while (window.pollEvent(keyBoardEvent))
{
if (keyBoardEvent.type == Event::KeyPressed)
{
if (keyBoardEvent.key.code == Keyboard::W)
{
body->SetLinearVelocity(b2Vec2(0, -10));
}
...
window.clear();
window.draw(staticRect);
window.draw(dynamicRect);
window.draw(line);
window.display();
if (Keyboard::isKeyPressed(Keyboard::Escape))
{
break;
}
}
return 0;
}
And here is my MyContactListiner.cpp:
void myContactListener::BeginContact(b2Contact* contact)
{
b2Fixture *fa = contact->GetFixtureA();
b2Fixture *fb = contact->GetFixtureB();
if (fa == NULL || fb == NULL) { return; }
while (1)
{
printf("Collision occurred");
if (Keyboard::isKeyPressed(Keyboard::Escape))
{
break;
}
}
}
Box2D doesn't do collision handling for static bodies directly against other static or kinematic bodies. They're both theoretically of infinite mass for which laws of motion don't seem to make much sense anymore (at least not to me in terms of collisions).
Probably easiest to make the kinematic body a dynamic one instead.
You could alternatively surround one of the bodies with dynamic ones to get the contact listener to fire up. The dynamic bodies can't be made to drive the kinematic or static one it surrounds however in the substep phases without more effort than I think it'd be worth.
Hope this answer helps!
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...
Edit
*Solved. Source code updated to working version!*
I'm trying to make a simple game engine for my next game using OpenGL and Box2D.
Problem is I can't get working these two well. If i turn OpenGL rotation off, everything looks as I'd except it in real worl. Problem is with rotation on.
http://cl.ly/image/0I0M3C3K1c3c - rotation off
http://cl.ly/image/421v321t201D - rotation on
I don't know if it's Box2D or OpenGL problem but I think right box shouldn't be rotated if it's on a flat ground in calm state or it's clearly violates law of physics. This is not only one problem but this one is clearly visible with picture only. I personally blame OpenGL for this :)
Here's my rendering code
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
GLuint texture_handle;
/* texture load logic */
...
...
glTranslatef(this->xPos + this->width / 2, this->yPos + this->height / 2, 0.0f);
glRotatef(this->angle, 0.0f, 0.0f, 1.0f);
glTranslatef(-this->width / 2, -this->height / 2 , 0);
/* Creates 3D cube */
glBegin(GL_QUADS);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(this->GetWidth(), 0);
glTexCoord2f(1, 1);
glVertex2f(this->GetWidth(), this->GetHeight());
glTexCoord2f(0, 1);
glVertex2f(0, this->GetHeight());
glTexCoord2f(0, 0);
glEnd();
glDeleteTextures(1, &texture_handle);
glPopMatrix();
glFlush();
For completion, here's Box2D part
/* define body for box */
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(this->xPos / RATIO, this->yPos / RATIO);
bodyDef.angle = this->angle * (M_PI / 180);
body = this->world->CreateBody(&bodyDef);
b2PolygonShape box;
box.SetAsBox((this->width / 2) / RATIO, (this->height / 2) / RATIO);
b2FixtureDef shapeDef;
shapeDef.shape = &box;
shapeDef.density = 1f;
shapeDef.friction = 0.8f;
body->CreateFixture(&shapeDef);
this->body = body;
/* apply physics */
b2Vec2 position = this->body->GetPosition();
this->angle = this->body->GetAngle() / (M_PI / 180);
this->xPos = (position.x * RATIO);
this->yPos = (position.y * RATIO);