diff --git a/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/GameRenderer.java b/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/GameRenderer.java index 5fb4c44..2677c9b 100644 --- a/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/GameRenderer.java +++ b/modules/io.github.xenfork.freeworld.client/src/main/java/io/github/xenfork/freeworld/client/render/GameRenderer.java @@ -116,7 +116,7 @@ public void render(GLStateMgr gl, double partialTick) { worldRenderer.compileChunks(); worldRenderer.renderChunks(gl); - final HitResult hitResult = worldRenderer.hitResult(); + final HitResult hitResult = worldRenderer.selectBlock(); if (!hitResult.missed()) { final AABBox box = hitResult.blockType().outlineShape().move(hitResult.x(), hitResult.y(), hitResult.z()); final float minX = (float) box.minX(); @@ -125,7 +125,7 @@ public void render(GLStateMgr gl, double partialTick) { final float maxX = (float) box.maxX(); final float maxY = (float) box.maxY(); final float maxZ = (float) box.maxZ(); - final float offset = 0.001f; + final float offset = 0.005f; gl.setTextureBinding2D(0); positionColorProgram.use(gl); positionColorProgram.getUniform(GLProgram.UNIFORM_PROJECTION_VIEW_MATRIX).set(projectionViewMatrix); 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 06db6e5..a2cc36a 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 @@ -19,10 +19,12 @@ import io.github.xenfork.freeworld.core.math.AABBox; import io.github.xenfork.freeworld.world.World; import io.github.xenfork.freeworld.world.block.BlockType; +import io.github.xenfork.freeworld.world.chunk.Chunk; import io.github.xenfork.freeworld.world.chunk.ChunkPos; import org.jetbrains.annotations.NotNull; import org.joml.*; +import java.lang.Math; import java.lang.Runtime; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; @@ -41,9 +43,7 @@ public final class WorldRenderer implements GLResource { private final FrustumRayBuilder frustumRayBuilder = new FrustumRayBuilder(); private final Vector3f frustumRayOrigin = new Vector3f(); private final Vector3f frustumRayDir = new Vector3f(); - private final Vector2f frustumIntersectionResult = new Vector2f(); private final Vector2d blockIntersectionResult = new Vector2d(); - private HitResult hitResult = new HitResult(null, 0, 0, 0, true); public WorldRenderer(GameRenderer gameRenderer, World world) { this.gameRenderer = gameRenderer; @@ -87,14 +87,6 @@ public void compileChunks() { } public void renderChunks(GLStateMgr gl) { - final Matrix4f matrix = gameRenderer.projectionViewMatrix(); - frustumIntersection.set(matrix); - frustumRayBuilder.set(matrix); - frustumRayBuilder.origin(frustumRayOrigin); - frustumRayBuilder.dir(0.5f, 0.5f, frustumRayDir); - frustumIntersectionResult.zero(); - float nearestChunkDistance = Float.POSITIVE_INFINITY; - ClientChunk nearestChunk = null; for (ClientChunk chunk : chunks) { if (frustumIntersection.testAab( chunk.fromX(), @@ -105,37 +97,47 @@ public void renderChunks(GLStateMgr gl) { chunk.toZ() )) { chunk.render(gl); - if (Intersectionf.intersectRayAab( - frustumRayOrigin.x(), - frustumRayOrigin.y(), - frustumRayOrigin.z(), - frustumRayDir.x(), - frustumRayDir.y(), - frustumRayDir.z(), - chunk.fromX(), - chunk.fromY(), - chunk.fromZ(), - chunk.toX(), - chunk.toY(), - chunk.toZ(), - frustumIntersectionResult - ) && frustumIntersectionResult.x() < nearestChunkDistance) { - nearestChunkDistance = frustumIntersectionResult.x(); - nearestChunk = chunk; - } } } - // TODO: 2024/3/24 squid233: This is buggy - if (nearestChunk != null) { - double nearestBlockDistance = Float.POSITIVE_INFINITY; - BlockType nearestBlock = null; - int nearestX = 0; - int nearestY = 0; - int nearestZ = 0; - for (int x = nearestChunk.fromX(); x < nearestChunk.toX(); x++) { - for (int y = nearestChunk.fromY(); y < nearestChunk.toY(); y++) { - for (int z = nearestChunk.fromZ(); z < nearestChunk.toZ(); z++) { - final BlockType blockType = nearestChunk.chunk().getBlockType( + } + + public HitResult selectBlock() { + final Matrix4f matrix = gameRenderer.projectionViewMatrix(); + frustumIntersection.set(matrix); + frustumRayBuilder.set(matrix); + frustumRayBuilder.origin(frustumRayOrigin); + frustumRayBuilder.dir(0.5f, 0.5f, frustumRayDir); + final float ox = frustumRayOrigin.x(); + final float oy = frustumRayOrigin.y(); + final float oz = frustumRayOrigin.z(); + + double nearestBlockDistance = Float.POSITIVE_INFINITY; + BlockType nearestBlock = null; + int nearestX = 0; + int nearestY = 0; + int nearestZ = 0; + + 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()); + for (int x = x0; x <= x1; x++) { + final float xSquared = (x + 0.5f - ox) * (x + 0.5f - ox); + 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 Chunk chunk = world.getChunk( + ChunkPos.absoluteToChunk(x), + ChunkPos.absoluteToChunk(y), + ChunkPos.absoluteToChunk(z) + ); + final BlockType blockType = chunk.getBlockType( ChunkPos.absoluteToRelative(x), ChunkPos.absoluteToRelative(y), ChunkPos.absoluteToRelative(z) @@ -145,9 +147,9 @@ public void renderChunks(GLStateMgr gl) { } final AABBox box = blockType.outlineShape().move(x, y, z); if (Intersectiond.intersectRayAab( - frustumRayOrigin.x(), - frustumRayOrigin.y(), - frustumRayOrigin.z(), + ox, + oy, + oz, frustumRayDir.x(), frustumRayDir.y(), frustumRayDir.z(), @@ -168,18 +170,15 @@ public void renderChunks(GLStateMgr gl) { } } } - hitResult = new HitResult(nearestBlock, nearestX, nearestY, nearestZ, nearestBlock == null); } + + return new HitResult(nearestBlock, nearestX, nearestY, nearestZ, nearestBlock == null); } public VertexBuilderPool vertexBuilderPool() { return vertexBuilderPool; } - public HitResult hitResult() { - return hitResult; - } - @Override public void close(GLStateMgr gl) { executor.close(); diff --git a/modules/io.github.xenfork.freeworld.core/src/main/java/io/github/xenfork/freeworld/world/World.java b/modules/io.github.xenfork.freeworld.core/src/main/java/io/github/xenfork/freeworld/world/World.java index 935ca37..6604499 100644 --- a/modules/io.github.xenfork.freeworld.core/src/main/java/io/github/xenfork/freeworld/world/World.java +++ b/modules/io.github.xenfork.freeworld.core/src/main/java/io/github/xenfork/freeworld/world/World.java @@ -67,4 +67,16 @@ public Chunk getChunk(int x, int y, int z) { public Chunk createChunk(int x, int y, int z) { return new Chunk(this, x, y, z); } + + public int width() { + return width; + } + + public int height() { + return height; + } + + public int depth() { + return depth; + } } diff --git a/modules/io.github.xenfork.freeworld.core/src/main/java/io/github/xenfork/freeworld/world/chunk/ChunkPos.java b/modules/io.github.xenfork.freeworld.core/src/main/java/io/github/xenfork/freeworld/world/chunk/ChunkPos.java index df94ac5..ba7de91 100644 --- a/modules/io.github.xenfork.freeworld.core/src/main/java/io/github/xenfork/freeworld/world/chunk/ChunkPos.java +++ b/modules/io.github.xenfork.freeworld.core/src/main/java/io/github/xenfork/freeworld/world/chunk/ChunkPos.java @@ -22,4 +22,8 @@ public static int relativeToAbsolute(int chunkPos, int relativePos) { public static int absoluteToRelative(int absolutePos) { return Math.floorMod(absolutePos, Chunk.SIZE); } + + public static int absoluteToChunk(int absolutePos) { + return Math.floorDiv(absolutePos, Chunk.SIZE); + } }