0
votes

Since rendering with triangles is faster than rendering with quads, i decided to split my 6 quad faces into 12 total triangles. The part that I'm stuck at is that I have no idea how to apply a quad texture to a triangle surface. The picture below is my attempt at it, but it's rather odd looking. Can anyone explain what is happening, and show me how I'd go about fixing this issue?

Screenshot: http://i.snag.gy/2ZenI.jpg

BlockFace class:

public class BlockFace {
    private final int amountOfVertices = 3;
    private final int vertexSize = 3;
    private final int textureSize = 2;
    private final int amountOfFaces = 2;

    private int vbo; // vertices
    private int tbo; // texture coordinates

    public BlockFace(float[] vertices) {
        FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize * amountOfFaces);
        vertexData.put(vertices);
        vertexData.flip();

        FloatBuffer textureData = BufferUtils.createFloatBuffer(4 * textureSize * amountOfFaces);
        textureData.put(new float[] {
                0, 0,
                1, 0,
                1, 1,
                0, 1,

                0, 0,
                1, 0,
                1, 1,
                0, 1
        });
        textureData.flip();

        vbo = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        tbo = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, tbo);
        glBufferData(GL_ARRAY_BUFFER, textureData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    public void draw(Texture texture) {
        texture.bind();

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);

        glBindBuffer(GL_ARRAY_BUFFER, tbo);
        glTexCoordPointer(textureSize, GL_FLOAT, 0, 0L);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glDrawArrays(GL_TRIANGLES, 0, amountOfVertices * 2);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }
}

BlockRenderer class:

public class BlockRenderer {
    private BlockFace topBlockFace;
    private BlockFace bottomBlockFace;
    private BlockFace frontBlockFace;
    private BlockFace backBlockFace;
    private BlockFace leftBlockFace;
    private BlockFace rightBlockFace;

    public BlockRenderer() {
        topBlockFace = new BlockFace(new float[] {
            0, 1, 0,
            1, 1, 0,
            0, 1, 1,

            1, 1, 1,
            1, 1, 0,
            0, 1, 1
        });
        bottomBlockFace = new BlockFace(new float[] {
            0, 0, 0,
            1, 0, 0,
            0, 0, 1,

            1, 0, 1,
            1, 0, 0,
            0, 0, 1
        });
        frontBlockFace = new BlockFace(new float[] {
            0, 0, 1,
            0, 1, 1,
            1, 1, 1,

            0, 0, 1,
            1, 0, 1,
            1, 1, 1
        });
        backBlockFace = new BlockFace(new float[] {
            0, 0, 0,
            0, 1, 0,
            1, 1, 0,

            0, 0, 0,
            1, 0, 0,
            1, 1, 0
        });
        leftBlockFace = new BlockFace(new float[] {
            0, 1, 0,
            0, 1, 1,
            0, 0, 1,

            0, 1, 0,
            0, 0, 0,
            0, 0, 1
        });
        rightBlockFace = new BlockFace(new float[] {
            1, 1, 0,
            1, 1, 1,
            1, 0, 1,

            1, 1, 0,
            1, 0, 0,
            1, 0, 1
        });
    }

    public void renderBlock(Block block, float x, float y, float z) {
        glPushMatrix();
        glTranslatef(x, y, z);

        topBlockFace.draw(block.getTexture());
        bottomBlockFace.draw(block.getTexture());
        frontBlockFace.draw(block.getTexture());
        backBlockFace.draw(block.getTexture());
        leftBlockFace.draw(block.getTexture());
        rightBlockFace.draw(block.getTexture());

        glPopMatrix();
    }
}
1

1 Answers

0
votes

If you divide your vertices into triangles, you have to divide the texture coordinates into triangles too. That means, you need 6 texture coordinates per face like you have 6 vertices per face.

For your example you need to change to:

FloatBuffer textureData = BufferUtils.createFloatBuffer(amountOfVertices * textureSize * amountOfFaces);
for(int i = 0; i < amountOfFaces; i++) {
    textureData.put(new float[] {
            0, 0,
            1, 0,
            0, 1,

            1, 1,
            1, 0,
            0, 1
    });
}
textureData.flip();

I furthermore saw, that one of your triangles per quad is defined clockwise whereas the other one is defined counter clockwise. If you use cull-face, you will only see one of the triangles.