LWJGL Voxel game, glDrawArrays

Posted by user22015 on Game Development See other posts from Game Development or by user22015
Published on 2012-10-18T15:58:49Z Indexed on 2012/10/18 17:26 UTC
Read the original article Hit count: 472

Filed under:
|
|

I've been learning about 3D for a couple days now. I managed to create a chunk (8x8x8). Add optimization so it only renders the active and visible blocks. Then I added so it only draws the faces which don't have a neighbor.

Next what I found from online research was that it is better to use glDrawArrays to increase performance. So I restarted my little project. Render an entire chunck, add optimization so it only renders active and visible blocks.

But now I want to add so it only draws the visible faces while using glDrawArrays. This is giving me some trouble with calling glDrawArrays because I'm passing a wrong count parameter.

    > # A fatal error has been detected by the Java Runtime Environment:
    > #
    > # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000006e31a03, pid=1032, tid=3184
    > #


Stack: [0x00000000023a0000,0x00000000024a0000], sp=0x000000000249ef70, free space=1019k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [ig4icd64.dll+0xa1a03]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.lwjgl.opengl.GL11.nglDrawArrays(IIIJ)V+0
j org.lwjgl.opengl.GL11.glDrawArrays(III)V+20
j com.vox.block.Chunk.render()V+410
j com.vox.ChunkManager.render()V+30
j com.vox.Game.render()V+11
j com.vox.GameHandler.render()V+12
j com.vox.GameHandler.gameLoop()V+15
j com.vox.Main.main([Ljava/lang/StringV+13
v ~StubRoutines::call_stub
public class Chunk {
    public final static int[] DIM = { 8, 8, 8};
    public final static int CHUNK_SIZE = (DIM[0] * DIM[1] * DIM[2]);
    Block[][][] blocks;
    private int index;
    private int vBOVertexHandle;
    private int vBOColorHandle;

    public Chunk(int index) {
        this.index = index;
        vBOColorHandle = GL15.glGenBuffers();
        vBOVertexHandle = GL15.glGenBuffers();
        blocks = new Block[DIM[0]][DIM[1]][DIM[2]];
        for(int x = 0; x < DIM[0]; x++){
            for(int y = 0; y < DIM[1]; y++){
                for(int z = 0; z < DIM[2]; z++){
                    blocks[x][y][z] = new Block();
                }
            }
        }
    }

    public void render(){
        Block curr;
        FloatBuffer vertexPositionData2 = BufferUtils.createFloatBuffer(CHUNK_SIZE * 6 * 12);
        FloatBuffer vertexColorData2 = BufferUtils.createFloatBuffer(CHUNK_SIZE * 6 * 12);
        int counter = 0;
        for(int x = 0; x < DIM[0]; x++){
            for(int y = 0; y < DIM[1]; y++){
                for(int z = 0; z < DIM[2]; z++){
                    curr = blocks[x][y][z];
                    boolean[] neightbours = validateNeightbours(x, y, z);
                    if(curr.isActive() && !neightbours[6]) {
                        float[] arr = curr.createCube((index*DIM[0]*Block.BLOCK_SIZE*2) + x*2, y*2, z*2, neightbours);
                        counter += arr.length;
                        vertexPositionData2.put(arr);
                        vertexColorData2.put(createCubeVertexCol(curr.getCubeColor()));
                    }
                }
            }
        }
        vertexPositionData2.flip();
        vertexPositionData2.flip();
        FloatBuffer vertexPositionData = BufferUtils.createFloatBuffer(vertexColorData2.position());
        FloatBuffer vertexColorData = BufferUtils.createFloatBuffer(vertexColorData2.position());
        for(int i = 0; i < vertexPositionData2.position(); i++)
            vertexPositionData.put(vertexPositionData2.get(i));
        for(int i = 0; i < vertexColorData2.position(); i++)
            vertexColorData.put(vertexColorData2.get(i));

        vertexColorData.flip();
        vertexPositionData.flip();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vBOVertexHandle);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertexPositionData, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vBOColorHandle);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertexColorData, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL11.glPushMatrix();


GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vBOVertexHandle);
    GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vBOColorHandle);
    GL11.glColorPointer(3, GL11.GL_FLOAT, 0, 0L);
    System.out.println("Counter " + counter);
    GL11.glDrawArrays(GL11.GL_LINE_LOOP, 0, counter);
    GL11.glPopMatrix();
    //blocks[r.nextInt(DIM[0])][2][r.nextInt(DIM[2])].setActive(false);
}
//Random r = new Random();

private float[] createCubeVertexCol(float[] CubeColorArray) {
    float[] cubeColors = new float[CubeColorArray.length * 4 * 6];
    for (int i = 0; i < cubeColors.length; i++) {
        cubeColors[i] = CubeColorArray[i % CubeColorArray.length];
    }
    return cubeColors;
}

private boolean[] validateNeightbours(int x, int y, int z) {
    boolean[] bools = new boolean[7];
    bools[6] = true;
    bools[6] = bools[6] && (bools[0] = y > 0 && y < DIM[1]-1 && blocks[x][y+1][z].isActive());//top
    bools[6] = bools[6] && (bools[1] = y > 0 && y < DIM[1]-1 && blocks[x][y-1][z].isActive());//bottom
    bools[6] = bools[6] && (bools[2] = z > 0 && z < DIM[2]-1 && blocks[x][y][z+1].isActive());//front
    bools[6] = bools[6] && (bools[3] = z > 0 && z < DIM[2]-1 && blocks[x][y][z-1].isActive());//back
    bools[6] = bools[6] && (bools[4] = x > 0 && x < DIM[0]-1 && blocks[x+1][y][z].isActive());//left
    bools[6] = bools[6] && (bools[5] = x > 0 && x < DIM[0]-1 && blocks[x-1][y][z].isActive());//right
    return bools;
}

}

public class Block {
    public static final float BLOCK_SIZE = 1f;
    public enum BlockType {
        Default(0),
        Grass(1),
        Dirt(2),
        Water(3),
        Stone(4),
        Wood(5),
        Sand(6),
        LAVA(7);
        int BlockID;
        BlockType(int i) {
            BlockID=i;
        }
    }

    private boolean active;
    private BlockType type;

    public Block() {
        this(BlockType.Default);
    }

    public Block(BlockType type){
        active = true;
        this.type = type;
    }

    public float[] getCubeColor() {
        switch (type.BlockID) {
            case 1:
                return new float[] { 1, 1, 0 };

            case 2:
                return new float[] { 1, 0.5f, 0 };
            case 3:
                return new float[] { 0, 0f, 1f };
            default:
                return new float[] {0.5f, 0.5f, 1f};
        }
    }
    public float[] createCube(float x, float y, float z,  boolean[] neightbours){
        int counter = 0;
        for(boolean b : neightbours)
            if(!b)
                counter++;
        float[] array = new float[counter*12];
        int offset = 0;
        if(!neightbours[0]){//top
            array[offset++] = x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE;
        }
        if(!neightbours[1]){//bottom
            array[offset++] = x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE;
        }
        if(!neightbours[2]){//front
            array[offset++] =  x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE;
        }
        if(!neightbours[3]){//back
            array[offset++] = x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE;
        }
        if(!neightbours[4]){//left
            array[offset++] = x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE;
        }
        if(!neightbours[5]){//right
            array[offset++] = x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE + BLOCK_SIZE; array[offset++] =
            x*BLOCK_SIZE + BLOCK_SIZE; array[offset++] = y*BLOCK_SIZE - BLOCK_SIZE; array[offset++] = z*BLOCK_SIZE - BLOCK_SIZE;
        }
        return Arrays.copyOf(array, offset);
    }
    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public BlockType getType() {
        return type;
    }

    public void setType(BlockType type) {
        this.type = type;
    }

}

I highlighted the code I'm concerned about in this following screenshot: - http://imageshack.us/a/img820/7606/18626782.png - (Not allowed to upload images yet)

I know the code is a mess but I'm just testing stuff so I wasn't really thinking about it.

© Game Development or respective owner

Related posts about opengl

Related posts about java