Elevox (Voxel Project) - Determine which faces to draw efficiently

Hello there!

In my voxel game I store the different in blocks as byte arrays like this:

byte[y * CHUNK_WIDTH * CHUNK_LENGTH + x * CHUNK_LENGTH + z]

Calculating the faces I have to draw is quite easy but I really check each
blocks neighbours (which can take quite a bit if I have to load an unloaded
neighbour chunk which has to generate first).

So is there a way to keep this form but to do it somehow faster?

And the second question: If i switch to Octrees, how can I determine the faces
to draw? Is there a way to do this faster?

This is the important code:


							if(Elevox.world.chunkMap.getBlockAt((int)xShift+x+1, (int)yShift+y, (int)zShift+z).isTransparent() && Elevox.world.chunkMap.getBlockAt((int)xShift+x+1, (int)yShift+y, (int)zShift+z) != Block.blockList[block]) {
								vertexData.put(new float[] {x+1.0f,y+0.0f,z+0.0f, col0r[0],col0r[1],col0r[2],color[3], 1,0,0,
															x+1.0f,y+1.0f,z+0.0f, col0r[0],col0r[1],col0r[2],color[3], 1,0,0,
															x+1.0f,y+1.0f,z+1.0f, col0r[0],col0r[1],col0r[2],color[3], 1,0,0,
															x+1.0f,y+0.0f,z+1.0f, col0r[0],col0r[1],col0r[2],color[3], 1,0,0});
							}
							if(Elevox.world.chunkMap.getBlockAt((int)xShift+x-1, (int)yShift+y, (int)zShift+z).isTransparent() && Elevox.world.chunkMap.getBlockAt((int)xShift+x-1, (int)yShift+y, (int)zShift+z) != Block.blockList[block]) {
								vertexData.put(new float[] {x+0.0f,y+0.0f,z+0.0f, col0r[0],col0r[1],col0r[2],color[3], -1,0,0,
															x+0.0f,y+0.0f,z+1.0f, col0r[0],col0r[1],col0r[2],color[3], -1,0,0,
															x+0.0f,y+1.0f,z+1.0f, col0r[0],col0r[1],col0r[2],color[3], -1,0,0,
															x+0.0f,y+1.0f,z+0.0f, col0r[0],col0r[1],col0r[2],color[3], -1,0,0});
							}
							if(Elevox.world.chunkMap.getBlockAt((int)xShift+x, (int)yShift+y+1, (int)zShift+z).isTransparent() && Elevox.world.chunkMap.getBlockAt((int)xShift+x, (int)yShift+y+1, (int)zShift+z) != Block.blockList[block]) {
								vertexData.put(new float[] {x+0.0f,y+1.0f,z+0.0f, color[0],color[1],color[2],color[3], 0,1,0,
															x+0.0f,y+1.0f,z+1.0f, color[0],color[1],color[2],color[3], 0,1,0,
															x+1.0f,y+1.0f,z+1.0f, color[0],color[1],color[2],color[3], 0,1,0,
															x+1.0f,y+1.0f,z+0.0f, color[0],color[1],color[2],color[3], 0,1,0});
							}
							if(Elevox.world.chunkMap.getBlockAt((int)xShift+x, (int)yShift+y-1, (int)zShift+z).isTransparent() && Elevox.world.chunkMap.getBlockAt((int)xShift+x, (int)yShift+y-1, (int)zShift+z) != Block.blockList[block]) {
								vertexData.put(new float[] {x+0.0f,y+0.0f,z+0.0f, color[0],color[1],color[2],color[3], 0,-1,0,
															x+1.0f,y+0.0f,z+0.0f, color[0],color[1],color[2],color[3], 0,-1,0,
															x+1.0f,y+0.0f,z+1.0f, color[0],color[1],color[2],color[3], 0,-1,0,
															x+0.0f,y+0.0f,z+1.0f, color[0],color[1],color[2],color[3], 0,-1,0});
							}
							if(Elevox.world.chunkMap.getBlockAt((int)xShift+x, (int)yShift+y, (int)zShift+z-1).isTransparent() && Elevox.world.chunkMap.getBlockAt((int)xShift+x, (int)yShift+y, (int)zShift+z-1) != Block.blockList[block]) {
								vertexData.put(new float[] {x+0.0f,y+0.0f,z+0.0f, col0r[0],col0r[1],col0r[2],color[3], 0,0,-1,
															x+0.0f,y+1.0f,z+0.0f, col0r[0],col0r[1],col0r[2],color[3], 0,0,-1,
															x+1.0f,y+1.0f,z+0.0f, col0r[0],col0r[1],col0r[2],color[3], 0,0,-1,
															x+1.0f,y+0.0f,z+0.0f, col0r[0],col0r[1],col0r[2],color[3], 0,0,-1});
							}
							if(Elevox.world.chunkMap.getBlockAt((int)xShift+x, (int)yShift+y, (int)zShift+z+1).isTransparent() && Elevox.world.chunkMap.getBlockAt((int)xShift+x, (int)yShift+y, (int)zShift+z+1) != Block.blockList[block]) {
								vertexData.put(new float[] {x+0.0f,y+0.0f,z+1.0f, col0r[0],col0r[1],col0r[2],color[3], 0,0,1,
															x+1.0f,y+0.0f,z+1.0f, col0r[0],col0r[1],col0r[2],color[3], 0,0,1,
															x+1.0f,y+1.0f,z+1.0f, col0r[0],col0r[1],col0r[2],color[3], 0,0,1,
															x+0.0f,y+1.0f,z+1.0f, col0r[0],col0r[1],col0r[2],color[3], 0,0,1});
							}

Elevox.world.chunkMap.getBlockAt() is a function that can cost quite some time in this critical part.