Question

How to apply auto rotation (like in a real world) in Box2D using LibGDX? This doesn't look realistic (see the pic bellow).

Screenshot

In the real world, the blocks would rotate and fall down, but they don't in this simulation.

The World has Y Gravity at -9.81 (so falling and colliding works fine) This is the code, where I create the boxes:

PolygonShape pShape = new PolygonShape();
FixtureDef fDef = new FixtureDef();
BodyDef bDef = new BodyDef();
Body body;

pShape.setAsBox(width, height);
bDef.position.set(x, y);
bDef.type = type;
fDef.shape = pShape;
fDef.density = 1.0f;
fDef.friction = 0.3f;
body = world.createBody(bDef);
body.createFixture(fDef);
body.setUserData(this);
MassData md = new MassData();
md.mass = 5;
body.setMassData(md);

Code for the Main Game class:

public class Game implements ApplicationListener {

public static int WIDTH;
public static int HEIGHT;

World world;
Box2DDebugRenderer dr;
OrthographicCamera cam;
float time;
final float P = 1/60f;
final static int C = 100;

public void create() {
    Gdx.gl.glClearColor(.1f, .1f, .1f, 1.0f);
    WIDTH = Gdx.graphics.getWidth();
    HEIGHT = Gdx.graphics.getHeight();
    world = new World(new Vector2(0, -9.8f), false);

    dr = new Box2DDebugRenderer();
    cam = new OrthographicCamera();
    cam.setToOrtho(false, WIDTH/C, HEIGHT/C);

    new Block(world, BodyType.StaticBody, 2,        HEIGHT,     0,          HEIGHT);
    new Block(world, BodyType.StaticBody, 2,        HEIGHT,     WIDTH-40,   HEIGHT);
    new Block(world, BodyType.StaticBody, WIDTH,    2,          WIDTH,      HEIGHT);
    new Block(world, BodyType.StaticBody, WIDTH,    2,          WIDTH,      0); 
}

public void render() {
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    input();

    dr.render(world, cam.combined);

    time += Gdx.graphics.getDeltaTime();
    while(time >= P) {
        update();
        time -= P;
    }
}

public void update() {
    world.step(P, 5, 5);
}

public void input() {
    if(Gdx.input.isTouched()) {
        new Block(world, BodyType.DynamicBody, 50, 20, Gdx.input.getX(), HEIGHT-Gdx.input.getY());
    }
}

public void dispose() { }
public void pause() { }
public void resize(int arg0, int arg1) { }
public void resume() { }
}

Code for the Block class:

public class Block {

public Block(World world, BodyType type, float width, float height, float x, float y) {

    PolygonShape pShape = new PolygonShape();
    FixtureDef fDef = new FixtureDef();
    BodyDef bDef = new BodyDef();
    Body body;

    pShape.setAsBox(width/Game.C, height/Game.C);
    bDef.position.set(x/Game.C, y/Game.C);
    bDef.type = type;
    fDef.shape = pShape;
    fDef.density = 1.0f;
    fDef.friction = 0.3f;
    body = world.createBody(bDef);
    body.createFixture(fDef);
    body.setUserData(this);
    body.setFixedRotation(false);
    MassData md = new MassData();
    md.mass = 5;
    body.setMassData(md);
}
}
Was it helpful?

Solution

MassData md = new MassData();

gives zero rotational inertia: md.I == 0 so the box doesn't rotate.

If you do

MassData md = body.getMassData();

you will have mass and rotational inertia according to your current density.

The best way to change mass and get the correct rotational inertia - calculate it by yourself according your new mass, like:

float massScale = [newMass] / md.mass;      
md.mass *= massScale;
md.I *= massScale;

In that way you'll save right rotation point and have physically correct inertia.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top