From b34e5e76764cf470cabd0fb753e885fcf7762735 Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Wed, 21 Oct 2026 21:09:57 -0400 Subject: [PATCH] Bound slope placement rotation - Use the radial three-dimensional bound whenever rotateTowardsSlope is set, including placements whose configured rotation is disabled - Group the support read margin helper with the other static factories --- .../generation/mantle/PlacementReach.java | 20 ++++++++++--------- .../generation/mantle/PlacementReachTest.java | 9 +++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/art/arcane/iris/generation/mantle/PlacementReach.java b/core/src/main/java/art/arcane/iris/generation/mantle/PlacementReach.java index 255557a96..e7cf808b3 100644 --- a/core/src/main/java/art/arcane/iris/generation/mantle/PlacementReach.java +++ b/core/src/main/java/art/arcane/iris/generation/mantle/PlacementReach.java @@ -61,6 +61,10 @@ public record PlacementReach(int horizontal, int readMargin) { return new Profile(Objects.requireNonNull(placement, "placement")); } + public static int supportReadMargin(int surfaceSupportBuffer) { + return 1 + Math.max(0, surfaceSupportBuffer); + } + public int input() { return saturate((long) horizontal + readMargin); } @@ -75,10 +79,6 @@ public record PlacementReach(int horizontal, int readMargin) { return minimumReadMargin <= readMargin ? this : new PlacementReach(horizontal, minimumReadMargin); } - public static int supportReadMargin(int surfaceSupportBuffer) { - return 1 + Math.max(0, surfaceSupportBuffer); - } - private static int roundedBound(double maximumMagnitude) { return saturate((long) Math.floor(maximumMagnitude + 0.5D + ROUNDING_SLACK)); } @@ -99,6 +99,7 @@ public record PlacementReach(int horizontal, int readMargin) { private final IrisBlockVector translation; private final boolean rotating; private final boolean radial; + private final boolean vertical; private final int[] spinsX; private final int[] spinsY; private final int[] spinsZ; @@ -117,7 +118,9 @@ public record PlacementReach(int horizontal, int readMargin) { this.spinsY = rotating ? distinctSpins(configuredRotation, Axis.Y) : new int[]{0}; this.spinsZ = rotating ? distinctSpins(configuredRotation, Axis.Z) : new int[]{0}; long kernels = (long) spinsX.length * spinsY.length * spinsZ.length; - this.radial = rotating && (placement.isRotateTowardsSlope() || kernels > MAXIMUM_ROTATION_KERNELS); + this.radial = placement.isRotateTowardsSlope() || (rotating && kernels > MAXIMUM_ROTATION_KERNELS); + this.vertical = placement.isRotateTowardsSlope() + || (rotating && (configuredRotation.canRotateX() || configuredRotation.canRotateZ())); this.additive = saturate((long) warpReach(placement.getWarp()) + vacuumReach(placement)); this.readMargin = supportReadMargin(placement.getSurfaceSupportBuffer()); } @@ -134,12 +137,12 @@ public record PlacementReach(int horizontal, int readMargin) { } private int rotatedReach(Extent extent) { - if (!rotating) { - return unrotatedReach(extent); - } if (radial) { return radialReach(extent); } + if (!rotating) { + return unrotatedReach(extent); + } double maximum = 0D; for (int spinX : spinsX) { for (int spinY : spinsY) { @@ -172,7 +175,6 @@ public record PlacementReach(int horizontal, int readMargin) { } private int radialReach(Extent extent) { - boolean vertical = rotation.canRotateX() || rotation.canRotateZ(); double translateX = translation == null ? 0D : translation.getX(); double translateY = translation == null ? 0D : translation.getY(); double translateZ = translation == null ? 0D : translation.getZ(); diff --git a/core/src/test/java/art/arcane/iris/generation/mantle/PlacementReachTest.java b/core/src/test/java/art/arcane/iris/generation/mantle/PlacementReachTest.java index 1cdb89c4a..f32449792 100644 --- a/core/src/test/java/art/arcane/iris/generation/mantle/PlacementReachTest.java +++ b/core/src/test/java/art/arcane/iris/generation/mantle/PlacementReachTest.java @@ -107,6 +107,15 @@ public class PlacementReachTest { assertEquals(14, PlacementReach.of(object, placement, 1D).horizontal()); } + @Test + public void slopeRotationIsBoundedEvenWhenTheConfiguredRotationIsDisabled() { + IrisObject object = singleBlockObject(21, 9, 21); + IrisObjectPlacement placement = new IrisObjectPlacement().setRotation(IrisObjectRotation.of(0D, 0D, 0D)); + + assertEquals(10, PlacementReach.of(object, placement, 1D).horizontal()); + assertEquals(15, PlacementReach.of(object, placement.setRotateTowardsSlope(true), 1D).horizontal()); + } + @Test public void unionKeepsTheLargestReachAndTheLargestInput() { PlacementReach union = new PlacementReach(10, 2).union(new PlacementReach(4, 12));