1
\$\begingroup\$

I have a hexagon-shaped polygon. I want to put a part of a rectangular image onto it (a part because it's a hexagon, not a rectangle). I tried to do this using PolygonRegion, but it gives a weird and flipped result. Also when I have multiple hexagons, the texture is only on the first hexagon, and on the others, only the weird lines are visible. I use libGDX with the Game and Screen classes. I'd also like to know what this error/effect is called.

My questions:

  1. How do I make the texture scale to the size of the hexagon?
  2. How do I not flip the texture?

My (altered) code "GameScreen":

class GameScreen implements Screen {

private OrthographicCamera cam;
private PolygonSpriteBatch pSB;
private Hexagon hexagon1, hexagon2;
public final int HEXAGON_WIDTH = 100;
public final int HEXAGON_HEIGHT = (int) (HEXAGON_WIDTH / (Math.sqrt(3) / 2)); 
//Ratio of width and height of a regular hexagon.

GameScreen() {
    this.cam = new OrthographicCamera(800, 800);
    cam.setToOrtho(true); 
    cam.position.set(cam.viewportWidth / 2f, cam.viewportHeight / 2f, 0);
    cam.update();

    hexagon1 = new Hexagon(new Vector2(0, 0));
    hexagon2 = new Hexagon(new Vector2(HEXAGON_WIDTH + 2, 0));

    pSB = new PolygonSpriteBatch();
}

@Override
public void render(float delta) {
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    Gdx.gl.glClearColor(1, 1, 1, 1);

    cam.update();
    pSB.setProjectionMatrix(cam.combined);

    pSB.begin();
    hexagon1.draw(pSB);
    hexagon2.draw(pSB);
    pSB.end();
}
}

Class Hexagon

class Hexagon {

    private PolygonSprite sprite;
    private Vector2 pos;

    Hexagon(Vector2 pos) {
        this.pos = pos;
        this.sprite = createPolygonSprite();
    }

    private PolygonSprite createPolygonSprite() {

        int hexWidth = GameScreen.HEXAGON_WIDTH;
        int hexHeight = GameScreen.HEXAGON_HEIGHT;

        float[] vertices = {
            pos.x + hexWidth / 2, pos.y,
            pos.x + hexWidth, pos.y + hexHeight * .25f,
            pos.x + hexWidth, pos.y + hexHeight * .75f,
            pos.x + hexWidth / 2, pos.y + hexHeight,
            pos.x, pos.y + hexHeight * .75f,
            pos.x, pos.y + hexHeight * .25f
        };

        PolygonRegion polygonRegion = new PolygonRegion(
            new TextureRegion(new Texture(Gdx.files.internal("badlogic.jpg")), 
            vertices, 
            new EarClippingTriangulator().computeTriangles(vertices).toArray());
        PolygonSprite polygonSprite = new PolygonSprite(polygonRegion);
        polygonSprite.setOrigin(pos.x + width / 2, pos.y + height / 2);
        return polygonSprite;
    }

    void draw(PolygonSpriteBatch pSB) {
        this.sprite.draw(pSB);
    }
}

The result (using similar code as written above but with more hexagons and other things): Weird lines and flipped texture

What I expected to see (instead of the above picture): I expected to see the image not flipped and on every hexagon. The image should have been of such a size that all the hexagon space is filled (that of course means you can't see the corners of the image, but that's what I want). The image should be displayed on each hexagon, so it should start drawing on each hexagon. The image should scale to the size of the hexagon.

\$\endgroup\$
  • \$\begingroup\$ What is startPos? \$\endgroup\$ – Bálint Dec 29 '16 at 19:31
  • \$\begingroup\$ should just be "pos" I think, I edited it. \$\endgroup\$ – The Coding Wombat Dec 29 '16 at 19:42
1
\$\begingroup\$

You need to set the texture's TextureWrap to Repeat

setWrap(Repeat, Repeat);
\$\endgroup\$
  • \$\begingroup\$ Okay, that looks prettier, but doesn't really do what I want. That makes the image repeat next to each other and under each other. But that means that each hexagon looks different (the texture repeats so on the second hexagon, the texture is already halfway on the first hexagon). I just want to start drawing the texture on the top left of each hexagon. \$\endgroup\$ – The Coding Wombat Dec 29 '16 at 17:58
  • \$\begingroup\$ I fixed my above concern by not adding the start position to every float in the vertices float[] but instead using sprite.setPosition(start.x, start.y). \$\endgroup\$ – The Coding Wombat Dec 29 '16 at 18:03
  • \$\begingroup\$ @TheCodingWombat could you mark this as an answer? \$\endgroup\$ – Bálint Dec 29 '16 at 18:45
  • \$\begingroup\$ No, it does not really do what I require or asked for. It was helpful, but what I want is that the texture scales to the size of the hexagon and that it starts drawing the texture at the start of each hexagon. I'll edit my question. I already fixed the not starting to draw at each texture with my previous comment. \$\endgroup\$ – The Coding Wombat Dec 29 '16 at 18:49
0
\$\begingroup\$

I figured all three problems out after some time: flipping the texture, putting the texture on every hexagon, and scaling the texture to the size of the hexagon.

To flip the "texture":

Texture texture = new Texture(Gdx.files.internal("badlogic.jpg");
TextureRegion textureRegion = new TextureRegion(texture);`
textureRegion.flip(false, true); //Flipping the texture region around the y axis
PolygonRegion polyRegion = new PolygonRegion(
    textureRegion, 
    vertices,
    new EarClippingTriangulator().computeTriangles(vertices).toArray()
);`

Even though multiple hexagons are present, the texture only seemed to be drawn once. That is because you shouldn't add the starting position to every vertex, but instead set the position of the whole sprite using. (example is shown further down).

To make the texture "scale" to the size of the hexagon, you have to scale the PolygonRegion down to the size of the texture by changing the vertices. After that, set the width and height of the hexagon using sprite.setBounds(x, y, width, height); So for this case that would be:

float texHeight = texture.getHeight();
float texDrawWidth = texHeight * ((float) Math.sqrt(3) / 2); 
  //Ratio between width and height of regular hexagon

float[] vertices = {
        texDrawWidth / 2, 0,
        texDrawWidth , texHeight * .25f,
        texDrawWidth , texHeight * .75f,
        texDrawWidth / 2, texHeight,
        0, texHeight * .75f,
        0, texHeight * .25f};

Then after creating the PolygonSprite use

sprite.setBounds(pos.x, pos.y, hexHeight, hexHeight);

Result: What the tiles now look like

I do not understand why setting the width and height of the sprite both equal to the desired height of the hexagon is correct, but it is the only thing that works.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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