Search code examples
javaopenglgraphicslibgdx2d-games

Weird, inconsistent and glitchy results when using libgdx's PolygonRegion/PolygonSprite


I've built a destructible terrain in libgdx and box2d and now I want to render the remaining (non destructed) terrain from a texture. Each time a box2d body is affected by an "explosion" (a part of the terrain is removed) the body is removed and remade with the new Polygon(s). I thought libgdx's PolygonSprite would be a perfect fit for this task but I've been having problems with it.

In this example I'm creating a "U" in the terrain with circular "explosions".

This code works perfectly fine:

protected Body createBody(Polygon inputPolygon) {
        ...
        body.setUserData(inputPolygon.getVertices());
        ...
}
//Later in the render method
        sr.setProjectionMatrix(cameraMatrix); //ShapeRenderer sr = new ShapeRenderer();
        sr.begin(ShapeRenderer.ShapeType.Line);
        Array<Body> bodies = new Array<Body>();
        world.getBodies(bodies);
        sr.setColor(Color.BLACK);
        for (Body b : bodies) {
        sr.polygon((float[]) b.getUserData());
        }
        sr.end();

And produces something like this:

When I try to render the "terrain" with a texture through PolygonSprites (or PolygonRegions) like this:

protected Body createBody(Polygon inputPolygon) {
        ...
        //triangulator is a EarClippingTriangulator
        ShortArray indices = triangulator.computeTriangles(inputPolygon.getVertices());
        //The TextureRegion is 100x40 px and the inputPolygon represents a part of this texture (the vertices/coordinates are
        //in the same scale, so an inputPolygon with the vertices (0, 0  100, 0  100, 40,  0, 40) would represent the whole TextureRegion.
        PolygonSprite polygonSprite = new PolygonSprite(new PolygonRegion(terrainTexture, inputPolygon.getVertices(), indices.items));
        polygonSprite.setOrigin(0, 0);
        body.setUserData(polygonSprite);
        ...
}
//Later in the render method
        Array<Body> bodies = new Array<Body>();
        world.getBodies(bodies);
        for (Body b : bodies) {
        //Yes the screen is cleared correctly before, the batch is a
        //PolygonSpriteBatch, the batch is started with begin() and end()
        //and the projection matrix is set correctly.
            ((PolygonSprite) b.getUserData()).draw(batch);
        }

I end up with weird, inconsistent and glitchy results like this: enter image description here ...Or like this: enter image description here

This is how the terrain (the texture) starts out: enter image description here


Solution

  • JavaDoc of EarClippingTriangulator.computeTriangles() says:

    Note the returned array is reused for later calls to the same method.

    So you probably want to copy the indices before passing them to PolygonRegion.