From 5b1b636539a0dcc7c2d37f8a963366966ee52d56 Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Tue, 1 Sep 2026 19:21:25 -0400 Subject: [PATCH] Point basis samples carry terrain slope Routing, validation and the valley solver sampled basis columns with slope 0; the forward slope now rides on every point sample. --- .../IrisHydrologyRoutingTerrainSampler.java | 4 +++- .../runtime/IrisHydrologyRuntime.java | 4 +--- ...IrisHydrologyRoutingTerrainSamplerTest.java | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRoutingTerrainSampler.java b/core/src/main/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRoutingTerrainSampler.java index 278a5e7fc..7ed8c87b9 100644 --- a/core/src/main/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRoutingTerrainSampler.java +++ b/core/src/main/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRoutingTerrainSampler.java @@ -106,7 +106,9 @@ final class IrisHydrologyRoutingTerrainSampler implements HydrologyNaturalTerrai @Override public HydrologyTerrainSample sampleBasis(int blockX, int blockZ) { - return basis(blockX, blockZ).terrain(); + // Point samples carry the forward slope; the aligned grid derives its own from neighbouring bases. + TerrainBasis basis = basis(blockX, blockZ); + return basis.terrain().withSlope(localSlope(blockX, blockZ, basis.naturalHeight())); } TerrainBasis basis(int blockX, int blockZ) { diff --git a/core/src/main/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRuntime.java b/core/src/main/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRuntime.java index 0e53a6359..4cbab856a 100644 --- a/core/src/main/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRuntime.java +++ b/core/src/main/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRuntime.java @@ -387,9 +387,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable { } private HydrologyTerrainSample createDetailedTerrainSample(int x, int z) { - IrisHydrologyRoutingTerrainSampler.TerrainBasis basis = routingTerrainSampler.basis(x, z); - double slope = routingTerrainSampler.localSlope(x, z, basis.naturalHeight()); - return basis.terrain().withSlope(slope); + return routingTerrainSampler.sampleBasis(x, z); } private IrisHydrologyRoutingTerrainSampler.TerrainBasis createTerrainBasis( diff --git a/core/src/test/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRoutingTerrainSamplerTest.java b/core/src/test/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRoutingTerrainSamplerTest.java index 66c140ab1..3fdbba635 100644 --- a/core/src/test/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRoutingTerrainSamplerTest.java +++ b/core/src/test/java/art/arcane/iris/engine/hydrology/runtime/IrisHydrologyRoutingTerrainSamplerTest.java @@ -93,6 +93,24 @@ public class IrisHydrologyRoutingTerrainSamplerTest { } } + @Test + public void pointBasisSamplesCarryTheForwardSlope() { + IrisHydrologyRoutingTerrainSampler sampler = sampler(64); + int[][] points = {{0, 0}, {-129, -257}, {37, 1024}}; + + for (int[] point : points) { + int x = point[0]; + int z = point[1]; + double expected = IrisHydrologyRoutingTerrainSampler.localSlope( + height(x, z), height(x + 3, z), height(x, z + 3)); + + double actual = sampler.sampleBasis(x, z).slope(); + + assertTrue(expected > 0D); + assertEquals(Double.doubleToRawLongBits(expected), Double.doubleToRawLongBits(actual)); + } + } + @Test public void adjacentGridsShareBasesAndProduceIdenticalOverlap() { AtomicInteger calls = new AtomicInteger();