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.