Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

The bug

The physics ground represented by a horizontal line. The object is stationary, and seems to be pretending that the ground is lower. This is because the center of the Shape is incorrectly located, or because I am transforming it improperly. The physics ground represented by a horizontal line. The object is stationary, and seems to be pretending that the ground is lower. This is because the center of the Shape is incorrectly located, or because I am transforming it improperly.

This is a cube displayed with the same system, and the center at the center of the object. It acts correctly, but that may just be because of its symmetric nature. This is a cube displayed with the same system, and the center at the center of the object. It acts correctly, but that may just be because of its symmetric nature.

Shapes appear to rotate around points which are not at their center of mass when I view a simulation involving a convex polygon and a static plane. I wrote the draw code myself, as shown below. More specifically, see the render function, which draws all objects in the Box2D world. One possible location for the bug is in the code where I'm transforming the Graphics object, and the other is when I'm creating and transforming the Slick2D Shape I will be drawing.

What is causing my graphics glitch?

Below is the source of the program in question.

IMPORTANT NOTE: This code is fully compilable and self-contained.
If you have jBox2D and Slick2D, you'll be able to compile and run it.

Note that to use jBox2D, you'll have to add some slf4j packages (slf4j-api and slf4j-nop if you just want it quick).

package junk;

import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.collision.shapes.ShapeType;
import org.jbox2d.common.MathUtils;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.Fixture;
import org.jbox2d.dynamics.World;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Polygon;
import org.newdawn.slick.geom.Transform;

public class Junk extends BasicGame
{
    World world;
    int velocityIterations;
    int positionIterations;
    float pixelsPerMeter;

    public Junk()
    {
        super("Hello World");
    }

    @Override
    public void init(GameContainer gc) throws SlickException
    {
        velocityIterations = 10;
        positionIterations = 10;
        pixelsPerMeter = 30.f;

        world = new World(new Vec2(0.f, -9.8f), true);

        {
            BodyDef dground = new BodyDef();
            dground.active = true;
            dground.position = new Vec2(0.f, 0.f);
            dground.type = BodyType.STATIC;
            Body bground = world.createBody(dground);
            PolygonShape sground = new PolygonShape();
            sground.setAsEdge(new Vec2(-30.f, 0.f), new Vec2(30.f, 0.f));
            bground.createFixture(sground, 1000.f);
        }
        {
            BodyDef dbox = new BodyDef();
            dbox.active = true;
            dbox.position = new Vec2(0.f, 10.f);
            dbox.angle = MathUtils.PI / 3.f;
            dbox.type = BodyType.DYNAMIC;
            Body bbox = world.createBody(dbox);
            PolygonShape sbox = new PolygonShape();
            Vec2[] data = 
            {
                new Vec2(-0.3f, -0.7f),
                new Vec2(0.0f, -1.0f),
                new Vec2(0.3f, -0.7f),
                new Vec2(0.5f, 0.5f),
                new Vec2(-0.5f, 0.5f)
            };
            sbox.set(data, 4);
            //sbox.setAsBox(0.5f, 0.5f);
            bbox.createFixture(sbox, 1.f);
            bbox.setAngularVelocity(10.f);
        }
    }

    @Override
    public void update(GameContainer gc, int delta) throws SlickException
    {
        world.step((float)delta / 1000.f, velocityIterations, positionIterations);
    }

    @Override
    public void render(GameContainer gc, Graphics g) throws SlickException
    {
        Body current = world.getBodyList();
        Vec2 center = current.getLocalCenter();
        while(current != null)
        {
            Vec2 pos = current.getPosition();
            g.pushTransform();
            g.translate(pos.x * pixelsPerMeter + (0.5f * gc.getWidth()), 
                       -pos.y * pixelsPerMeter + (0.5f * gc.getHeight()));
            Fixture f = current.getFixtureList();
            while(f != null)
            {
                ShapeType type = f.getType();
                switch(type)
                {
                    case POLYGON:
                    {
                        PolygonShape shape = (PolygonShape)f.getShape();
                        Vec2[] verts = shape.getVertices();
                        int count = shape.getVertexCount();
                        Polygon p = new Polygon();
                        for(int i = 0; i < count; i++)
                        {
                            p.addPoint(verts[i].x, verts[i].y);
                        }
                        p.setCenterX(center.x);
                        p.setCenterY(center.y);
                        p = (Polygon)p.transform(Transform.createRotateTransform(current.getAngle() + MathUtils.PI, center.x, center.y));
                        p = (Polygon)p.transform(Transform.createScaleTransform(pixelsPerMeter, pixelsPerMeter));
                        g.draw(p);
                        break;
                    }
                    case CIRCLE:
                    {
                        CircleShape shape = (CircleShape)f.getShape();
                    }
                    default:
                }

                f = f.getNext();
            }
            g.popTransform();
            current = current.getNext();
        }
    }

    public static void main(String[] args) throws SlickException
    {
        AppGameContainer app = new AppGameContainer(new Junk());

        app.setDisplayMode(800, 600, false);
        //app.setShowFPS(false);
        app.start();
    }
}
share|improve this question

closed as too localized by Byte56, Sean Middleditch, Trevor Powell, Laurent Couvidou, Josh Petrie Jan 29 '13 at 16:22

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

    
You need to make your posts short, to the point and clear otherwise people won't bother to answer your question and will -1 you lol... Trust me, I know. –  Savlon Jan 27 '13 at 4:49
    
I've reworked the question so it will be more useful to people less familiar with Box2D and Slick2D, and hopefully it will be easier to interpret and answer. Also, I added an explicit question to my question (hah!). I hope it's concise enough. I tried to point people to the right place in the code, but the whole thing is needed if it is to remain compilable and runnable. –  Miles Rufat-Latre Jan 27 '13 at 4:58
    
sweet, ok well next problem. There might be people who don't have Box2D or Slick2D so they wont be able to place your self contained code in a compiler and try it out. Can you post a picture of the graphics error you are getting? –  Savlon Jan 27 '13 at 5:00
1  
Thanks for the help. Pictures added. Captions also (no context->no meaning). –  Miles Rufat-Latre Jan 27 '13 at 5:09
    
Added information on common jBox2D issue to prevent chaos. –  Miles Rufat-Latre Jan 27 '13 at 5:17

1 Answer 1

First thing I would look at is how setting the center point of object affects the local coordinate space of your polygon vertices.

Box2d gives you the position of the geometry at its center of mass by default, and the verts will be offset from the center in local space. I would try commenting out the lines:

p.setCenterX(center.x);
p.setCenterY(center.y);

Also to determine if you have a translation or rotation problem, I would drop some polygons into the scene that will rotate when they land, if they roll along the ground correctly but slighly penetrating the surface, you have a translation problem.

If they rotate from a point outside the object itself, you have a rotation problem

share|improve this answer
    
I didn't realize it was still possible to answer the question, since someone voted to close it. I solved the problem though. It did involve removing those lines. (but it also involved getting rid of the second and third parameters to rotate, since the origin of the drawing space was transformed to the correct location anyway). The real key was realizing that the location of the center of mass was NOT the same as the origin of the local coordinate system. –  Miles Rufat-Latre Jan 27 '13 at 15:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.