Skip to content

Commit

Permalink
Fix fluids shape on octree edge (#1579)
Browse files Browse the repository at this point in the history
  • Loading branch information
NotStirred authored Oct 27, 2024
1 parent c4b66a6 commit d91e484
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 24 deletions.
58 changes: 35 additions & 23 deletions chunky/src/java/se/llbit/chunky/renderer/scene/OctreeFinalizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import se.llbit.math.Octree;
import se.llbit.math.Vector3i;

import java.util.Set;

/**
* Processes the Octree after it has been loaded and updates block states for blocks that depend on
* neighbor blocks. Octree finalization is be done after all chunks have been loaded because before
Expand All @@ -41,7 +43,7 @@ public class OctreeFinalizer {
* @param cp Position of the chunk to finalize
*/
public static void finalizeChunk(Octree worldTree, Octree waterTree, BlockPalette palette,
Vector3i origin, ChunkPosition cp, int yMin, int yMax) {
Set<ChunkPosition> loadedChunks, Vector3i origin, ChunkPosition cp, int yMin, int yMax) {
for (int cy = yMin; cy < yMax; ++cy) {
for (int cz = 0; cz < 16; ++cz) {
int z = cz + cp.z * 16 - origin.z;
Expand All @@ -50,7 +52,7 @@ public static void finalizeChunk(Octree worldTree, Octree waterTree, BlockPalett
// process blocks that are at the edge of the chunk, the other should have be taken care of during the loading
if (cy == yMin || cy == yMax - 1 || cz == 0 || cz == 15 || cx == 0 || cx == 15) {
hideBlocks(worldTree, palette, x, cy, z, yMin, yMax, origin);
processBlock(worldTree, waterTree, palette, x, cy, z, origin);
processBlock(worldTree, waterTree, palette, loadedChunks, x, cy, z, origin);
}
}
}
Expand All @@ -75,8 +77,8 @@ private static void hideBlocks(Octree worldTree, BlockPalette palette, int x,
}
}

private static void processBlock(Octree worldTree, Octree waterTree, BlockPalette palette, int x,
int cy, int z, Vector3i origin) {
private static void processBlock(Octree worldTree, Octree waterTree, BlockPalette palette,
Set<ChunkPosition> loadedChunks, int x, int cy, int z, Vector3i origin) {
int y = cy - origin.y;
Material mat = worldTree.getMaterial(x, y, z, palette);
Material wmat = waterTree.getMaterial(x, y, z, palette);
Expand All @@ -91,32 +93,32 @@ private static void processBlock(Octree worldTree, Octree waterTree, BlockPalett
int corner2 = level0;
int corner3 = level0;

int level = waterLevelAt(worldTree, waterTree, palette, x - 1, y, z, level0);
int level = waterLevelAt(worldTree, waterTree, palette, loadedChunks, x - 1, y, z, level0);
corner3 += level;
corner0 += level;

level = waterLevelAt(worldTree, waterTree, palette, x - 1, y, z + 1, level0);
level = waterLevelAt(worldTree, waterTree, palette, loadedChunks, x - 1, y, z + 1, level0);
corner0 += level;

level = waterLevelAt(worldTree, waterTree, palette, x, y, z + 1, level0);
level = waterLevelAt(worldTree, waterTree, palette, loadedChunks, x, y, z + 1, level0);
corner0 += level;
corner1 += level;

level = waterLevelAt(worldTree, waterTree, palette, x + 1, y, z + 1, level0);
level = waterLevelAt(worldTree, waterTree, palette, loadedChunks, x + 1, y, z + 1, level0);
corner1 += level;

level = waterLevelAt(worldTree, waterTree, palette, x + 1, y, z, level0);
level = waterLevelAt(worldTree, waterTree, palette, loadedChunks, x + 1, y, z, level0);
corner1 += level;
corner2 += level;

level = waterLevelAt(worldTree, waterTree, palette, x + 1, y, z - 1, level0);
level = waterLevelAt(worldTree, waterTree, palette, loadedChunks, x + 1, y, z - 1, level0);
corner2 += level;

level = waterLevelAt(worldTree, waterTree, palette, x, y, z - 1, level0);
level = waterLevelAt(worldTree, waterTree, palette, loadedChunks, x, y, z - 1, level0);
corner2 += level;
corner3 += level;

level = waterLevelAt(worldTree, waterTree, palette, x - 1, y, z - 1, level0);
level = waterLevelAt(worldTree, waterTree, palette, loadedChunks, x - 1, y, z - 1, level0);
corner3 += level;

corner0 = Math.min(7, 8 - (corner0 / 4));
Expand All @@ -142,32 +144,32 @@ private static void processBlock(Octree worldTree, Octree waterTree, BlockPalett
int corner2 = level0;
int corner3 = level0;

int level = lavaLevelAt(worldTree, palette, x - 1, y, z, level0);
int level = lavaLevelAt(worldTree, palette, loadedChunks, x - 1, y, z, level0);
corner3 += level;
corner0 += level;

level = lavaLevelAt(worldTree, palette, x - 1, y, z + 1, level0);
level = lavaLevelAt(worldTree, palette, loadedChunks, x - 1, y, z + 1, level0);
corner0 += level;

level = lavaLevelAt(worldTree, palette, x, y, z + 1, level0);
level = lavaLevelAt(worldTree, palette, loadedChunks, x, y, z + 1, level0);
corner0 += level;
corner1 += level;

level = lavaLevelAt(worldTree, palette, x + 1, y, z + 1, level0);
level = lavaLevelAt(worldTree, palette, loadedChunks, x + 1, y, z + 1, level0);
corner1 += level;

level = lavaLevelAt(worldTree, palette, x + 1, y, z, level0);
level = lavaLevelAt(worldTree, palette, loadedChunks, x + 1, y, z, level0);
corner1 += level;
corner2 += level;

level = lavaLevelAt(worldTree, palette, x + 1, y, z - 1, level0);
level = lavaLevelAt(worldTree, palette, loadedChunks, x + 1, y, z - 1, level0);
corner2 += level;

level = lavaLevelAt(worldTree, palette, x, y, z - 1, level0);
level = lavaLevelAt(worldTree, palette, loadedChunks, x, y, z - 1, level0);
corner2 += level;
corner3 += level;

level = lavaLevelAt(worldTree, palette, x - 1, y, z - 1, level0);
level = lavaLevelAt(worldTree, palette, loadedChunks, x - 1, y, z - 1, level0);
corner3 += level;

corner0 = Math.min(7, 8 - (corner0 / 4));
Expand All @@ -185,8 +187,13 @@ private static void processBlock(Octree worldTree, Octree waterTree, BlockPalett
}
}

private static int waterLevelAt(Octree worldTree, Octree waterTree,
BlockPalette palette, int x, int cy, int z, int baseLevel) {
private static int waterLevelAt(Octree worldTree, Octree waterTree, BlockPalette palette,
Set<ChunkPosition> loadedChunks, int x, int cy, int z, int baseLevel) {
// If the position isn't in a loaded chunk, return the baseLevel to make the edge-of-world water flat
if (!loadedChunks.contains(new ChunkPosition(x >> 4, z >> 4))) {
return baseLevel;
}

Material corner = waterTree.getMaterial(x, cy, z, palette);
if (corner instanceof Water) {
Material above = waterTree.getMaterial(x, cy + 1, z, palette);
Expand All @@ -201,7 +208,12 @@ private static int waterLevelAt(Octree worldTree, Octree waterTree,
}

private static int lavaLevelAt(Octree octree, BlockPalette palette,
int x, int cy, int z, int baseLevel) {
Set<ChunkPosition> loadedChunks, int x, int cy, int z, int baseLevel) {
// If the position isn't in a loaded chunk, return the baseLevel to make the edge-of-world water flat
if (!loadedChunks.contains(new ChunkPosition(x >> 4, z >> 4))) {
return baseLevel;
}

Material corner = octree.getMaterial(x, cy, z, palette);
if (corner instanceof Lava) {
Material above = octree.getMaterial(x, cy + 1, z, palette);
Expand Down
2 changes: 1 addition & 1 deletion chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ public synchronized void loadChunks(TaskTracker taskTracker, World world, Collec
}
}
}
OctreeFinalizer.finalizeChunk(worldOctree, waterOctree, palette, origin, cp, yMin, yMax);
OctreeFinalizer.finalizeChunk(worldOctree, waterOctree, palette, loadedChunks, origin, cp, yMin, yMax);
if (legacyChunks.contains(cp)) {
LegacyBlocksFinalizer
.finalizeChunk(worldOctree, waterOctree, palette, origin, cp, yMin, yMax);
Expand Down

0 comments on commit d91e484

Please sign in to comment.