From 2fe0db5d68a29305bb7fc132b95a955ac2de8ca5 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 25 Sep 2023 21:25:26 -0700 Subject: [PATCH 1/2] Initial ground plane implementation. --- .../renderer/scene/PreviewRayTracer.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java b/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java index c2446e9c23..0a3841ecde 100644 --- a/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java +++ b/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java @@ -95,6 +95,7 @@ public static boolean nextIntersection(Scene scene, Ray ray) { if (scene.isWaterPlaneEnabled()) { hit = waterPlaneIntersection(scene, ray) || hit; } + hit |= groundPlaneIntersection(scene, ray); if (scene.intersect(ray)) { // Octree tracer handles updating distance. return true; @@ -139,6 +140,30 @@ private static boolean waterPlaneIntersection(Scene scene, Ray ray) { return false; } + private static boolean groundPlaneIntersection(Scene scene, Ray ray) { + double t = (scene.getYClipMin() - ray.o.y - scene.origin.y) / ray.d.y; + if (scene.getWaterPlaneChunkClip()) { + Vector3 pos = new Vector3(ray.o); + pos.scaleAdd(t, ray.d); + if (scene.isChunkLoaded((int)Math.floor(pos.x), (int)Math.floor(pos.y), (int)Math.floor(pos.z))) + return false; + } + if (ray.d.y < 0 && t > 0 && t < ray.t) { + double px = ray.o.x + t * ray.d.x; + double pz = ray.o.z + t * ray.d.z; + + ray.u = px - Math.floor(px); + ray.v = pz - Math.floor(pz); + + ray.t = t; + scene.getPalette().stone.getColor(ray); + ray.setNormal(0, 1, 0); + ray.setCurrentMaterial(scene.getPalette().stone); + return true; + } + return false; + } + // Chunk pattern config private static final double chunkPatternLineWidth = 0.5; // in blocks private static final double chunkPatternLinePosition = 8 - chunkPatternLineWidth / 2; From 75bd12e9aa93dca54115ec641f6b13fcd95e885b Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 25 Sep 2023 21:50:45 -0700 Subject: [PATCH 2/2] Add ground plane settings & controls. --- .../renderer/scene/PreviewRayTracer.java | 8 +-- .../se/llbit/chunky/renderer/scene/Scene.java | 53 +++++++++++++++++++ .../llbit/chunky/ui/render/tabs/WaterTab.java | 32 +++++++++++ .../llbit/chunky/ui/render/tabs/WaterTab.fxml | 14 +++++ 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java b/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java index 0a3841ecde..dc8719837c 100644 --- a/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java +++ b/chunky/src/java/se/llbit/chunky/renderer/scene/PreviewRayTracer.java @@ -95,7 +95,9 @@ public static boolean nextIntersection(Scene scene, Ray ray) { if (scene.isWaterPlaneEnabled()) { hit = waterPlaneIntersection(scene, ray) || hit; } - hit |= groundPlaneIntersection(scene, ray); + if (scene.isGroundPlaneEnabled()) { + hit |= groundPlaneIntersection(scene, ray); + } if (scene.intersect(ray)) { // Octree tracer handles updating distance. return true; @@ -141,8 +143,8 @@ private static boolean waterPlaneIntersection(Scene scene, Ray ray) { } private static boolean groundPlaneIntersection(Scene scene, Ray ray) { - double t = (scene.getYClipMin() - ray.o.y - scene.origin.y) / ray.d.y; - if (scene.getWaterPlaneChunkClip()) { + double t = (scene.getGroundPlaneHeight() - ray.o.y - scene.origin.y) / ray.d.y; + if (scene.getGroundPlaneChunkClip()) { Vector3 pos = new Vector3(ray.o); pos.scaleAdd(t, ray.d); if (scene.isChunkLoaded((int)Math.floor(pos.x), (int)Math.floor(pos.y), (int)Math.floor(pos.z))) diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java b/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java index 32b6b7340a..d561d21b4e 100644 --- a/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java +++ b/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java @@ -228,6 +228,11 @@ public class Scene implements JsonSerializable, Refreshable { protected double waterPlaneHeight = World.SEA_LEVEL; protected boolean waterPlaneOffsetEnabled = true; protected boolean waterPlaneChunkClip = true; + + protected boolean groundPlaneEnabled = false; + protected double groundPlaneHeight = 0; + protected boolean groundPlaneChunkClip = true; + protected WaterShader waterShading = new SimplexWaterShader(); public final Fog fog = new Fog(this); @@ -466,6 +471,11 @@ public synchronized void copyState(Scene other, boolean copyChunks) { waterPlaneHeight = other.waterPlaneHeight; waterPlaneOffsetEnabled = other.waterPlaneOffsetEnabled; waterPlaneChunkClip = other.waterPlaneChunkClip; + + groundPlaneEnabled = other.groundPlaneEnabled; + groundPlaneHeight = other.groundPlaneHeight; + groundPlaneChunkClip = other.groundPlaneChunkClip; + waterShading = other.waterShading.clone(); hideUnknownBlocks = other.hideUnknownBlocks; @@ -1859,6 +1869,39 @@ public boolean getWaterPlaneChunkClip() { return waterPlaneChunkClip; } + public void setGroundPlaneEnabled(boolean enabled) { + if (enabled != groundPlaneEnabled) { + groundPlaneEnabled = enabled; + refresh(); + } + } + + public boolean isGroundPlaneEnabled() { + return groundPlaneEnabled; + } + + public void setGroundPlaneHeight(double height) { + if (height != groundPlaneHeight) { + groundPlaneHeight = height; + refresh(); + } + } + + public double getGroundPlaneHeight() { + return groundPlaneHeight; + } + + public void setGroundPlaneChunkClip(boolean enabled) { + if (enabled != groundPlaneChunkClip) { + groundPlaneChunkClip = enabled; + refresh(); + } + } + + public boolean getGroundPlaneChunkClip() { + return groundPlaneChunkClip; + } + /** * @return the dumpFrequency */ @@ -2663,10 +2706,16 @@ public void setUseCustomWaterColor(boolean value) { json.add("fog", fog.toJson()); json.add("biomeColorsEnabled", biomeColors); json.add("transparentSky", transparentSky); + json.add("waterWorldEnabled", waterPlaneEnabled); json.add("waterWorldHeight", waterPlaneHeight); json.add("waterWorldHeightOffsetEnabled", waterPlaneOffsetEnabled); json.add("waterWorldClipEnabled", waterPlaneChunkClip); + + json.add("groundPlaneEnabled", groundPlaneEnabled); + json.add("groundPlaneHeight", groundPlaneHeight); + json.add("groundPlaneClipEnabled", groundPlaneChunkClip); + json.add("hideUnknownBlocks", hideUnknownBlocks); if (!worldPath.isEmpty()) { @@ -2972,6 +3021,10 @@ else if(waterShader.equals("SIMPLEX")) waterPlaneChunkClip = json.get("waterWorldClipEnabled").boolValue(waterPlaneChunkClip); } + groundPlaneEnabled = json.get("groundPlaneEnabled").boolValue(groundPlaneEnabled); + groundPlaneHeight = json.get("groundPlaneHeight").doubleValue(groundPlaneHeight); + groundPlaneChunkClip = json.get("groundPlaneClipEnabled").boolValue(groundPlaneChunkClip); + hideUnknownBlocks = json.get("hideUnknownBlocks").boolValue(hideUnknownBlocks); materials = json.get("materials").object().copy().toMap(); diff --git a/chunky/src/java/se/llbit/chunky/ui/render/tabs/WaterTab.java b/chunky/src/java/se/llbit/chunky/ui/render/tabs/WaterTab.java index 34f3a440b9..b9c47703a5 100644 --- a/chunky/src/java/se/llbit/chunky/ui/render/tabs/WaterTab.java +++ b/chunky/src/java/se/llbit/chunky/ui/render/tabs/WaterTab.java @@ -52,11 +52,18 @@ public class WaterTab extends ScrollPane implements RenderControlsTab, Initializ @FXML private CheckBox useCustomWaterColor; @FXML private LuxColorPicker waterColor; @FXML private Button saveDefaults; + @FXML private CheckBox waterPlaneEnabled; @FXML private DoubleAdjuster waterPlaneHeight; @FXML private CheckBox waterPlaneOffsetEnabled; @FXML private CheckBox waterPlaneClip; @FXML private TitledPane waterWorldModeDetailsPane; + + @FXML private CheckBox groundPlaneEnabled; + @FXML private DoubleAdjuster groundPlaneHeight; + @FXML private CheckBox groundPlaneClip; + @FXML private TitledPane groundPlaneDetailsPane; + @FXML private CheckBox useProceduralWater; @FXML private IntegerAdjuster proceduralWaterIterations; @FXML private DoubleAdjuster proceduralWaterFrequency; @@ -104,6 +111,11 @@ public void update(Scene scene) { waterPlaneOffsetEnabled.setSelected(scene.isWaterPlaneOffsetEnabled()); waterPlaneClip.setSelected(scene.getWaterPlaneChunkClip()); + groundPlaneEnabled.setSelected(scene.isGroundPlaneEnabled()); + groundPlaneHeight.setRange(scene.yClipMin, scene.yClipMax); + groundPlaneHeight.set(scene.getGroundPlaneHeight()); + groundPlaneClip.setSelected(scene.getGroundPlaneChunkClip()); + if(scene.getWaterShading() instanceof SimplexWaterShader) { useProceduralWater.setSelected(true); SimplexWaterShader simplexWaterShader = (SimplexWaterShader) scene.getWaterShading(); @@ -195,6 +207,26 @@ public void initialize(URL location, ResourceBundle resources) { scene.setWaterPlaneChunkClip(newValue) ); + groundPlaneDetailsPane.setVisible(groundPlaneEnabled.isSelected()); + groundPlaneDetailsPane.setExpanded(groundPlaneEnabled.isSelected()); + groundPlaneDetailsPane.setManaged(groundPlaneEnabled.isSelected()); + + groundPlaneEnabled.setTooltip(new Tooltip("If enabled, an infinite ground fills the scene.")); + groundPlaneEnabled.selectedProperty().addListener((observable, oldValue, newValue) -> { + scene.setGroundPlaneEnabled(newValue); + groundPlaneDetailsPane.setVisible(newValue); + groundPlaneDetailsPane.setExpanded(newValue); + groundPlaneDetailsPane.setManaged(newValue); + }); + + groundPlaneHeight.setName("Ground height"); + groundPlaneHeight.setTooltip("The default ground height is at y=0."); + groundPlaneHeight.onValueChange(value -> scene.setGroundPlaneHeight(value)); + + groundPlaneClip.selectedProperty().addListener((observable, oldValue, newValue) -> + scene.setGroundPlaneChunkClip(newValue) + ); + proceduralWaterDetailsPane.setVisible(useProceduralWater.isSelected()); proceduralWaterDetailsPane.setExpanded(useProceduralWater.isSelected()); proceduralWaterDetailsPane.setManaged(useProceduralWater.isSelected()); diff --git a/chunky/src/res/se/llbit/chunky/ui/render/tabs/WaterTab.fxml b/chunky/src/res/se/llbit/chunky/ui/render/tabs/WaterTab.fxml index 39ff6f2d90..6d39ea1a70 100644 --- a/chunky/src/res/se/llbit/chunky/ui/render/tabs/WaterTab.fxml +++ b/chunky/src/res/se/llbit/chunky/ui/render/tabs/WaterTab.fxml @@ -23,6 +23,7 @@