diff --git a/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/world/ChunkCompileTask.java b/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/world/ChunkCompileTask.java index 8b73784..f83e955 100644 --- a/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/world/ChunkCompileTask.java +++ b/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/world/ChunkCompileTask.java @@ -12,7 +12,7 @@ import io.github.xenfork.freeworld.client.render.GameRenderer; import io.github.xenfork.freeworld.client.render.builder.DefaultVertexBuilder; -import io.github.xenfork.freeworld.client.render.builder.VertexBuilder; +import io.github.xenfork.freeworld.client.world.chunk.ClientChunk; import io.github.xenfork.freeworld.util.Direction; import io.github.xenfork.freeworld.world.chunk.Chunk; import io.github.xenfork.freeworld.world.chunk.ChunkPos; @@ -29,40 +29,20 @@ public final class ChunkCompileTask implements Callable { private final GameRenderer gameRenderer; private final WorldRenderer worldRenderer; - private final Chunk chunk; + private final ClientChunk chunk; - public ChunkCompileTask(GameRenderer gameRenderer, WorldRenderer worldRenderer, Chunk chunk) { + public ChunkCompileTask(GameRenderer gameRenderer, WorldRenderer worldRenderer, ClientChunk chunk) { this.gameRenderer = gameRenderer; this.worldRenderer = worldRenderer; this.chunk = chunk; } - private record DelegateArena( - Arena arena, - VertexBuilderPool pool, - T builder - ) implements Arena { - @Override - public MemorySegment allocate(long byteSize, long byteAlignment) { - return arena.allocate(byteSize, byteAlignment); - } - - @Override - public MemorySegment.Scope scope() { - return arena.scope(); - } - - @Override - public void close() { - arena.close(); - pool.release(builder); - } - } - @Override public ChunkVertexData call() { final var pool = worldRenderer.vertexBuilderPool(); final DefaultVertexBuilder builder = pool.acquire(); + builder.reset(); + final Chunk chunk = this.chunk.chunk(); final int cx = chunk.x(); final int cy = chunk.y(); final int cz = chunk.z(); @@ -80,17 +60,18 @@ public ChunkVertexData call() { ChunkPos.relativeToAbsolute(cx, x), ChunkPos.relativeToAbsolute(cy, y), ChunkPos.relativeToAbsolute(cz, z), - direction); + direction + ); } } } } } - final Arena arena = new DelegateArena<>(Arena.ofShared(), pool, builder); + final Arena arena = Arena.ofShared(); final MemorySegment vertexDataSlice = builder.vertexDataSlice(); final MemorySegment indexDataSlice = builder.indexDataSlice(); - return new ChunkVertexData( + final ChunkVertexData data = new ChunkVertexData( builder.vertexLayout(), builder.indexCount(), arena, @@ -99,5 +80,7 @@ public ChunkVertexData call() { builder.shouldReallocateVertexData(), builder.shouldReallocateIndexData() ); + pool.release(builder); + return data; } } diff --git a/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/world/WorldRenderer.java b/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/world/WorldRenderer.java index a2cc36a..33dbddc 100644 --- a/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/world/WorldRenderer.java +++ b/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/world/WorldRenderer.java @@ -74,19 +74,20 @@ public Thread newThread(@NotNull Runnable r) { } private static DefaultVertexBuilder createVertexBuilder() { - return new DefaultVertexBuilder(VertexLayouts.POSITION_COLOR_TEX, 30000, 60000); + return new DefaultVertexBuilder(VertexLayouts.POSITION_COLOR_TEX, 30000, 45000); } public void compileChunks() { for (ClientChunk chunk : chunks) { if (chunk.shouldRecompile.get() && !chunk.submitted.get()) { - chunk.future.set(executor.submit(new ChunkCompileTask(gameRenderer, this, chunk.chunk()))); + chunk.future.set(executor.submit(new ChunkCompileTask(gameRenderer, this, chunk))); chunk.submitted.set(true); } } } public void renderChunks(GLStateMgr gl) { + frustumIntersection.set(gameRenderer.projectionViewMatrix()); for (ClientChunk chunk : chunks) { if (frustumIntersection.testAab( chunk.fromX(), @@ -102,9 +103,7 @@ public void renderChunks(GLStateMgr gl) { } public HitResult selectBlock() { - final Matrix4f matrix = gameRenderer.projectionViewMatrix(); - frustumIntersection.set(matrix); - frustumRayBuilder.set(matrix); + frustumRayBuilder.set(gameRenderer.projectionViewMatrix()); frustumRayBuilder.origin(frustumRayOrigin); frustumRayBuilder.dir(0.5f, 0.5f, frustumRayDir); final float ox = frustumRayOrigin.x(); @@ -119,19 +118,20 @@ public HitResult selectBlock() { final float radius = 5.0f; final float radiusSquared = radius * radius; - final int x0 = Math.clamp((int) Math.floor(ox - radius), 0, world.width()); - final int y0 = Math.clamp((int) Math.floor(oy - radius), 0, world.height()); - final int z0 = Math.clamp((int) Math.floor(oz - radius), 0, world.depth()); - final int x1 = Math.clamp((int) Math.ceil(ox + radius), 0, world.width()); - final int y1 = Math.clamp((int) Math.ceil(oy + radius), 0, world.height()); - final int z1 = Math.clamp((int) Math.ceil(oz + radius), 0, world.depth()); + final int x0 = Math.clamp((int) Math.floor(ox - radius) - 1, 0, world.width()); + final int y0 = Math.clamp((int) Math.floor(oy - radius) - 1, 0, world.height()); + final int z0 = Math.clamp((int) Math.floor(oz - radius) - 1, 0, world.depth()); + final int x1 = Math.clamp((int) Math.ceil(ox + radius) + 1, 0, world.width()); + final int y1 = Math.clamp((int) Math.ceil(oy + radius) + 1, 0, world.height()); + final int z1 = Math.clamp((int) Math.ceil(oz + radius) + 1, 0, world.depth()); for (int x = x0; x <= x1; x++) { - final float xSquared = (x + 0.5f - ox) * (x + 0.5f - ox); + final float vx = x + 0.5f - ox; + final float xSquared = vx * vx; for (int y = y0; y <= y1; y++) { - final float ySquared = (y + 0.5f - oy) * (y + 0.5f - oy); for (int z = z0; z <= z1; z++) { - final float zSquared = (z + 0.5f - oz) * (z + 0.5f - oz); - if ((xSquared + ySquared + zSquared) <= radiusSquared) { + final float vz = z + 0.5f - oz; + final float zSquared = vz * vz; + if ((xSquared + zSquared) <= radiusSquared) { final Chunk chunk = world.getChunk( ChunkPos.absoluteToChunk(x), ChunkPos.absoluteToChunk(y), diff --git a/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/world/chunk/ClientChunk.java b/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/world/chunk/ClientChunk.java index 1a0a4e3..d1dd18f 100644 --- a/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/world/chunk/ClientChunk.java +++ b/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/world/chunk/ClientChunk.java @@ -18,7 +18,6 @@ import io.github.xenfork.freeworld.world.chunk.Chunk; import overrungl.opengl.GL15C; -import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -47,34 +46,39 @@ public ClientChunk(World world, int x, int y, int z, Chunk chunk) { public void render(GLStateMgr gl) { if (shouldRecompile.get() && submitted.get()) { try { - final ChunkVertexData data = future.get().get(); - try (Arena _ = data.arena()) { - final MemorySegment vertexData = data.vertexData(); - final MemorySegment indexData = data.indexData(); - indexCount = data.indexCount(); - if (vao == 0) vao = gl.genVertexArrays(); - if (vbo == 0) vbo = gl.genBuffers(); - if (ebo == 0) ebo = gl.genBuffers(); - gl.setVertexArrayBinding(vao); - gl.setArrayBufferBinding(vbo); - if (data.shouldReallocateVertexData()) { - gl.bufferData(GL15C.ARRAY_BUFFER, vertexData, GL15C.DYNAMIC_DRAW); - final VertexLayout layout = data.vertexLayout(); - layout.enableAttribs(gl); - layout.specifyAttribPointers(gl); - } else { - gl.bufferSubData(GL15C.ARRAY_BUFFER, 0L, vertexData); - } - gl.bindBuffer(GL15C.ELEMENT_ARRAY_BUFFER, ebo); - if (data.shouldReallocateIndexData()) { - gl.bufferData(GL15C.ELEMENT_ARRAY_BUFFER, indexData, GL15C.DYNAMIC_DRAW); - } else { - gl.bufferSubData(GL15C.ELEMENT_ARRAY_BUFFER, 0L, indexData); + final Future dataFuture = future.get(); + if (dataFuture.isDone()) { + final ChunkVertexData data = dataFuture.get(); + try { + final MemorySegment vertexData = data.vertexData(); + final MemorySegment indexData = data.indexData(); + indexCount = data.indexCount(); + if (vao == 0) vao = gl.genVertexArrays(); + if (vbo == 0) vbo = gl.genBuffers(); + if (ebo == 0) ebo = gl.genBuffers(); + gl.setVertexArrayBinding(vao); + gl.setArrayBufferBinding(vbo); + if (data.shouldReallocateVertexData()) { + gl.bufferData(GL15C.ARRAY_BUFFER, vertexData, GL15C.DYNAMIC_DRAW); + final VertexLayout layout = data.vertexLayout(); + layout.enableAttribs(gl); + layout.specifyAttribPointers(gl); + } else { + gl.bufferSubData(GL15C.ARRAY_BUFFER, 0L, vertexData); + } + gl.bindBuffer(GL15C.ELEMENT_ARRAY_BUFFER, ebo); + if (data.shouldReallocateIndexData()) { + gl.bufferData(GL15C.ELEMENT_ARRAY_BUFFER, indexData, GL15C.DYNAMIC_DRAW); + } else { + gl.bufferSubData(GL15C.ELEMENT_ARRAY_BUFFER, 0L, indexData); + } + } finally { + data.arena().close(); } + shouldRecompile.set(false); + submitted.set(false); + future.set(null); } - shouldRecompile.set(false); - submitted.set(false); - future.set(null); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); }