OptiPass3

This commit is contained in:
Brian Neumann-Fopiano
2026-04-15 15:13:35 -04:00
parent b42d0e4710
commit 6096c39192
6 changed files with 400 additions and 31 deletions
@@ -19,6 +19,7 @@
package art.arcane.iris.engine.framework; package art.arcane.iris.engine.framework;
import art.arcane.iris.core.tools.IrisToolbelt; import art.arcane.iris.core.tools.IrisToolbelt;
import art.arcane.iris.core.gui.PregeneratorJob;
import art.arcane.iris.engine.IrisComplex; import art.arcane.iris.engine.IrisComplex;
import art.arcane.iris.engine.mantle.EngineMantle; import art.arcane.iris.engine.mantle.EngineMantle;
import art.arcane.iris.util.project.context.ChunkContext; import art.arcane.iris.util.project.context.ChunkContext;
@@ -75,7 +76,7 @@ public interface EngineMode extends Staged {
boolean cacheContext = true; boolean cacheContext = true;
if (J.isFolia()) { if (J.isFolia()) {
org.bukkit.World world = getEngine().getWorld().realWorld(); org.bukkit.World world = getEngine().getWorld().realWorld();
if (world != null && IrisToolbelt.isWorldMaintenanceActive(world)) { if (world != null && shouldDisableContextCacheForMaintenance(world)) {
cacheContext = false; cacheContext = false;
} }
} }
@@ -88,4 +89,19 @@ public interface EngineMode extends Staged {
i.generate(x, z, blocks, biomes, multicore, ctx); i.generate(x, z, blocks, biomes, multicore, ctx);
} }
} }
static boolean shouldDisableContextCacheForMaintenance(boolean maintenanceActive, boolean pregeneratorTargetsWorld) {
return maintenanceActive && !pregeneratorTargetsWorld;
}
private boolean shouldDisableContextCacheForMaintenance(org.bukkit.World world) {
boolean maintenanceActive = IrisToolbelt.isWorldMaintenanceActive(world);
if (!maintenanceActive) {
return false;
}
PregeneratorJob pregeneratorJob = PregeneratorJob.getInstance();
boolean pregeneratorTargetsWorld = pregeneratorJob != null && pregeneratorJob.targetsWorld(world);
return shouldDisableContextCacheForMaintenance(maintenanceActive, pregeneratorTargetsWorld);
}
} }
@@ -1049,11 +1049,13 @@ public class IrisCaveCarver3D {
double[] adaptivePlaneDensity = scratch.adaptivePlaneDensity; double[] adaptivePlaneDensity = scratch.adaptivePlaneDensity;
int axisCells = (16 + adaptiveSampleStep - 1) / adaptiveSampleStep; int axisCells = (16 + adaptiveSampleStep - 1) / adaptiveSampleStep;
int axisSamples = axisCells + 1; int axisSamples = axisCells + 1;
for (int sampleXIndex = 0; sampleXIndex < axisSamples; sampleXIndex++) { int[] adaptivePlaneSampleBounds = scratch.adaptivePlaneSampleBounds;
prepareAdaptivePlaneSampleBounds(planeColumnIndices, planeCount, adaptiveSampleStep, adaptivePlaneSampleBounds, axisCells);
for (int sampleXIndex = adaptivePlaneSampleBounds[0]; sampleXIndex <= adaptivePlaneSampleBounds[1]; sampleXIndex++) {
int sampleLocalX = Math.min(sampleXIndex * adaptiveSampleStep, 16); int sampleLocalX = Math.min(sampleXIndex * adaptiveSampleStep, 16);
int x = x0 + sampleLocalX; int x = x0 + sampleLocalX;
int rowOffset = sampleXIndex * axisSamples; int rowOffset = sampleXIndex * axisSamples;
for (int sampleZIndex = 0; sampleZIndex < axisSamples; sampleZIndex++) { for (int sampleZIndex = adaptivePlaneSampleBounds[2]; sampleZIndex <= adaptivePlaneSampleBounds[3]; sampleZIndex++) {
int sampleLocalZ = Math.min(sampleZIndex * adaptiveSampleStep, 16); int sampleLocalZ = Math.min(sampleZIndex * adaptiveSampleStep, 16);
adaptivePlaneDensity[rowOffset + sampleZIndex] = sampleDensityNoWarpNoModules(x, y, z0 + sampleLocalZ); adaptivePlaneDensity[rowOffset + sampleZIndex] = sampleDensityNoWarpNoModules(x, y, z0 + sampleLocalZ);
} }
@@ -1099,11 +1101,13 @@ public class IrisCaveCarver3D {
double[] adaptivePlaneDensity = scratch.adaptivePlaneDensity; double[] adaptivePlaneDensity = scratch.adaptivePlaneDensity;
int axisCells = (16 + adaptiveSampleStep - 1) / adaptiveSampleStep; int axisCells = (16 + adaptiveSampleStep - 1) / adaptiveSampleStep;
int axisSamples = axisCells + 1; int axisSamples = axisCells + 1;
for (int sampleXIndex = 0; sampleXIndex < axisSamples; sampleXIndex++) { int[] adaptivePlaneSampleBounds = scratch.adaptivePlaneSampleBounds;
prepareAdaptivePlaneSampleBounds(planeColumnIndices, planeCount, adaptiveSampleStep, adaptivePlaneSampleBounds, axisCells);
for (int sampleXIndex = adaptivePlaneSampleBounds[0]; sampleXIndex <= adaptivePlaneSampleBounds[1]; sampleXIndex++) {
int sampleLocalX = Math.min(sampleXIndex * adaptiveSampleStep, 16); int sampleLocalX = Math.min(sampleXIndex * adaptiveSampleStep, 16);
int x = x0 + sampleLocalX; int x = x0 + sampleLocalX;
int rowOffset = sampleXIndex * axisSamples; int rowOffset = sampleXIndex * axisSamples;
for (int sampleZIndex = 0; sampleZIndex < axisSamples; sampleZIndex++) { for (int sampleZIndex = adaptivePlaneSampleBounds[2]; sampleZIndex <= adaptivePlaneSampleBounds[3]; sampleZIndex++) {
int sampleLocalZ = Math.min(sampleZIndex * adaptiveSampleStep, 16); int sampleLocalZ = Math.min(sampleZIndex * adaptiveSampleStep, 16);
adaptivePlaneDensity[rowOffset + sampleZIndex] = sampleDensityNoWarpNoModules(x, y, z0 + sampleLocalZ); adaptivePlaneDensity[rowOffset + sampleZIndex] = sampleDensityNoWarpNoModules(x, y, z0 + sampleLocalZ);
} }
@@ -1144,11 +1148,13 @@ public class IrisCaveCarver3D {
double[] adaptivePlaneDensity = scratch.adaptivePlaneDensity; double[] adaptivePlaneDensity = scratch.adaptivePlaneDensity;
int axisCells = (16 + adaptiveSampleStep - 1) / adaptiveSampleStep; int axisCells = (16 + adaptiveSampleStep - 1) / adaptiveSampleStep;
int axisSamples = axisCells + 1; int axisSamples = axisCells + 1;
for (int sampleXIndex = 0; sampleXIndex < axisSamples; sampleXIndex++) { int[] adaptivePlaneSampleBounds = scratch.adaptivePlaneSampleBounds;
prepareAdaptivePlaneSampleBounds(planeColumnIndices, planeCount, adaptiveSampleStep, adaptivePlaneSampleBounds, axisCells);
for (int sampleXIndex = adaptivePlaneSampleBounds[0]; sampleXIndex <= adaptivePlaneSampleBounds[1]; sampleXIndex++) {
int sampleLocalX = Math.min(sampleXIndex * adaptiveSampleStep, 16); int sampleLocalX = Math.min(sampleXIndex * adaptiveSampleStep, 16);
int x = x0 + sampleLocalX; int x = x0 + sampleLocalX;
int rowOffset = sampleXIndex * axisSamples; int rowOffset = sampleXIndex * axisSamples;
for (int sampleZIndex = 0; sampleZIndex < axisSamples; sampleZIndex++) { for (int sampleZIndex = adaptivePlaneSampleBounds[2]; sampleZIndex <= adaptivePlaneSampleBounds[3]; sampleZIndex++) {
int sampleLocalZ = Math.min(sampleZIndex * adaptiveSampleStep, 16); int sampleLocalZ = Math.min(sampleZIndex * adaptiveSampleStep, 16);
adaptivePlaneDensity[rowOffset + sampleZIndex] = sampleDensityWarpOnly(x, y, z0 + sampleLocalZ); adaptivePlaneDensity[rowOffset + sampleZIndex] = sampleDensityWarpOnly(x, y, z0 + sampleLocalZ);
} }
@@ -1194,17 +1200,25 @@ public class IrisCaveCarver3D {
double[] adaptivePlaneDensity = scratch.adaptivePlaneDensity; double[] adaptivePlaneDensity = scratch.adaptivePlaneDensity;
int axisCells = (16 + adaptiveSampleStep - 1) / adaptiveSampleStep; int axisCells = (16 + adaptiveSampleStep - 1) / adaptiveSampleStep;
int axisSamples = axisCells + 1; int axisSamples = axisCells + 1;
for (int sampleXIndex = 0; sampleXIndex < axisSamples; sampleXIndex++) { int[] adaptivePlaneSampleBounds = scratch.adaptivePlaneSampleBounds;
prepareAdaptivePlaneSampleBounds(planeColumnIndices, planeCount, adaptiveSampleStep, adaptivePlaneSampleBounds, axisCells);
for (int sampleXIndex = adaptivePlaneSampleBounds[0]; sampleXIndex <= adaptivePlaneSampleBounds[1]; sampleXIndex++) {
int sampleLocalX = Math.min(sampleXIndex * adaptiveSampleStep, 16); int sampleLocalX = Math.min(sampleXIndex * adaptiveSampleStep, 16);
int x = x0 + sampleLocalX; int x = x0 + sampleLocalX;
int rowOffset = sampleXIndex * axisSamples; int rowOffset = sampleXIndex * axisSamples;
for (int sampleZIndex = 0; sampleZIndex < axisSamples; sampleZIndex++) { for (int sampleZIndex = adaptivePlaneSampleBounds[2]; sampleZIndex <= adaptivePlaneSampleBounds[3]; sampleZIndex++) {
int sampleLocalZ = Math.min(sampleZIndex * adaptiveSampleStep, 16); int sampleLocalZ = Math.min(sampleZIndex * adaptiveSampleStep, 16);
adaptivePlaneDensity[rowOffset + sampleZIndex] = sampleDensityWarpOnly(x, y, z0 + sampleLocalZ); adaptivePlaneDensity[rowOffset + sampleZIndex] = sampleDensityWarpModules(
x,
y,
z0 + sampleLocalZ,
localModules,
activeModuleCount
);
} }
} }
classifyAdaptivePlaneColumnsWarpModules( classifyAdaptivePlaneColumnsWarpModulesSampled(
x0, x0,
z0, z0,
y, y,
@@ -1259,6 +1273,10 @@ public class IrisCaveCarver3D {
double threshold = planeThresholdLimit[planeIndex] * inverseNormalization; double threshold = planeThresholdLimit[planeIndex] * inverseNormalization;
double predictedDensity = adaptivePlanePrediction[planeIndex]; double predictedDensity = adaptivePlanePrediction[planeIndex];
double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex]; double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex];
if (isAdaptivePlaneSampleAligned(localX, localZ, adaptiveSampleStep)) {
planeCarve[planeIndex] = predictedDensity <= threshold;
continue;
}
if (predictedDensity <= threshold - ambiguityMargin) { if (predictedDensity <= threshold - ambiguityMargin) {
planeCarve[planeIndex] = true; planeCarve[planeIndex] = true;
continue; continue;
@@ -1313,6 +1331,20 @@ public class IrisCaveCarver3D {
double threshold = planeThresholdLimit[planeIndex] * inverseNormalization; double threshold = planeThresholdLimit[planeIndex] * inverseNormalization;
double predictedDensity = adaptivePlanePrediction[planeIndex]; double predictedDensity = adaptivePlanePrediction[planeIndex];
double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex]; double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex];
if (isAdaptivePlaneSampleAligned(localX, localZ, adaptiveSampleStep)) {
planeCarve[planeIndex] = classifyDensityPointNoWarpModulesFromExactDensity(
x0 + localX,
y,
z0 + localZ,
threshold,
predictedDensity,
localModules,
activeModuleCount,
remainingMin,
remainingMax
);
continue;
}
if ((predictedDensity + maxRemaining) <= threshold - ambiguityMargin) { if ((predictedDensity + maxRemaining) <= threshold - ambiguityMargin) {
planeCarve[planeIndex] = true; planeCarve[planeIndex] = true;
continue; continue;
@@ -1370,6 +1402,10 @@ public class IrisCaveCarver3D {
double threshold = planeThresholdLimit[planeIndex] * inverseNormalization; double threshold = planeThresholdLimit[planeIndex] * inverseNormalization;
double predictedDensity = adaptivePlanePrediction[planeIndex]; double predictedDensity = adaptivePlanePrediction[planeIndex];
double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex]; double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex];
if (isAdaptivePlaneSampleAligned(localX, localZ, adaptiveSampleStep)) {
planeCarve[planeIndex] = predictedDensity <= threshold;
continue;
}
if (predictedDensity <= threshold - ambiguityMargin) { if (predictedDensity <= threshold - ambiguityMargin) {
planeCarve[planeIndex] = true; planeCarve[planeIndex] = true;
continue; continue;
@@ -1424,6 +1460,20 @@ public class IrisCaveCarver3D {
double threshold = planeThresholdLimit[planeIndex] * inverseNormalization; double threshold = planeThresholdLimit[planeIndex] * inverseNormalization;
double predictedDensity = adaptivePlanePrediction[planeIndex]; double predictedDensity = adaptivePlanePrediction[planeIndex];
double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex]; double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex];
if (isAdaptivePlaneSampleAligned(localX, localZ, adaptiveSampleStep)) {
planeCarve[planeIndex] = classifyDensityPointWarpModulesFromExactDensity(
x0 + localX,
y,
z0 + localZ,
threshold,
predictedDensity,
localModules,
activeModuleCount,
remainingMin,
remainingMax
);
continue;
}
if ((predictedDensity + maxRemaining) <= threshold - ambiguityMargin) { if ((predictedDensity + maxRemaining) <= threshold - ambiguityMargin) {
planeCarve[planeIndex] = true; planeCarve[planeIndex] = true;
continue; continue;
@@ -1446,6 +1496,71 @@ public class IrisCaveCarver3D {
} }
} }
private void classifyAdaptivePlaneColumnsWarpModulesSampled(
int x0,
int z0,
int y,
int[] planeColumnIndices,
double[] planeThresholdLimit,
int planeCount,
boolean[] planeCarve,
int adaptiveSampleStep,
double adaptiveThresholdMargin,
double[] adaptivePlaneDensity,
int axisCells,
int axisSamples,
ModuleState[] localModules,
int activeModuleCount,
double[] remainingMin,
double[] remainingMax
) {
Scratch scratch = SCRATCH.get();
double[] adaptivePlanePrediction = scratch.adaptivePlanePrediction;
double[] adaptivePlaneAmbiguity = scratch.adaptivePlaneAmbiguity;
prepareAdaptivePlaneColumns(
planeColumnIndices,
planeCount,
adaptiveSampleStep,
adaptiveThresholdMargin,
adaptivePlaneDensity,
axisCells,
axisSamples,
adaptivePlanePrediction,
adaptivePlaneAmbiguity
);
for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
int columnIndex = planeColumnIndices[planeIndex];
int localX = PowerOfTwoCoordinates.unpackLocal16X(columnIndex);
int localZ = columnIndex & 15;
double threshold = planeThresholdLimit[planeIndex] * inverseNormalization;
double predictedDensity = adaptivePlanePrediction[planeIndex];
double ambiguityMargin = adaptivePlaneAmbiguity[planeIndex];
if (isAdaptivePlaneSampleAligned(localX, localZ, adaptiveSampleStep)) {
planeCarve[planeIndex] = predictedDensity <= threshold;
continue;
}
if (predictedDensity <= threshold - ambiguityMargin) {
planeCarve[planeIndex] = true;
continue;
}
if (predictedDensity > threshold + ambiguityMargin) {
planeCarve[planeIndex] = false;
continue;
}
planeCarve[planeIndex] = classifyDensityPointWarpModules(
x0 + localX,
y,
z0 + localZ,
planeThresholdLimit[planeIndex],
localModules,
activeModuleCount,
remainingMin,
remainingMax
);
}
}
private boolean classifyDensityPointNoWarpNoModules(int x, int y, int z, double thresholdLimit) { private boolean classifyDensityPointNoWarpNoModules(int x, int y, int z, double thresholdLimit) {
double density = baseDensity.noiseFastSigned3D(x, y, z) * baseWeight; double density = baseDensity.noiseFastSigned3D(x, y, z) * baseWeight;
if ((density + detailMinContribution) > thresholdLimit) { if ((density + detailMinContribution) > thresholdLimit) {
@@ -1568,6 +1683,127 @@ public class IrisCaveCarver3D {
return density <= thresholdLimit; return density <= thresholdLimit;
} }
private boolean classifyDensityPointNoWarpModulesFromExactDensity(
int x,
int y,
int z,
double threshold,
double density,
ModuleState[] localModules,
int activeModuleCount,
double[] remainingMin,
double[] remainingMax
) {
if (activeModuleCount == 0) {
return density <= threshold;
}
double minRemaining = remainingMin[0] * inverseNormalization;
double maxRemaining = remainingMax[0] * inverseNormalization;
if ((density + minRemaining) > threshold) {
return false;
}
if ((density + maxRemaining) <= threshold) {
return true;
}
for (int moduleIndex = 0; moduleIndex < activeModuleCount; moduleIndex++) {
density += localModules[moduleIndex].sample(x, y, z) * inverseNormalization;
if ((density + (remainingMin[moduleIndex + 1] * inverseNormalization)) > threshold) {
return false;
}
if ((density + (remainingMax[moduleIndex + 1] * inverseNormalization)) <= threshold) {
return true;
}
}
return density <= threshold;
}
private boolean classifyDensityPointWarpModulesFromExactDensity(
int x,
int y,
int z,
double threshold,
double density,
ModuleState[] localModules,
int activeModuleCount,
double[] remainingMin,
double[] remainingMax
) {
if (activeModuleCount == 0) {
return density <= threshold;
}
double minRemaining = remainingMin[0] * inverseNormalization;
double maxRemaining = remainingMax[0] * inverseNormalization;
if ((density + minRemaining) > threshold) {
return false;
}
if ((density + maxRemaining) <= threshold) {
return true;
}
double warpA = warpDensity.noiseFastSigned3D(x, y, z);
double warpB = warpDensity.noiseFastSigned3D(x + 31.37D, y - 17.21D, z + 23.91D);
double warpedX = x + (warpA * warpStrength);
double warpedY = y + (warpB * warpStrength);
double warpedZ = z + ((warpA - warpB) * 0.5D * warpStrength);
for (int moduleIndex = 0; moduleIndex < activeModuleCount; moduleIndex++) {
density += localModules[moduleIndex].sample(warpedX, warpedY, warpedZ) * inverseNormalization;
if ((density + (remainingMin[moduleIndex + 1] * inverseNormalization)) > threshold) {
return false;
}
if ((density + (remainingMax[moduleIndex + 1] * inverseNormalization)) <= threshold) {
return true;
}
}
return density <= threshold;
}
private boolean isAdaptivePlaneSampleAligned(int localX, int localZ, int adaptiveSampleStep) {
return localX % adaptiveSampleStep == 0 && localZ % adaptiveSampleStep == 0;
}
private void prepareAdaptivePlaneSampleBounds(
int[] planeColumnIndices,
int planeCount,
int adaptiveSampleStep,
int[] adaptivePlaneSampleBounds,
int axisCells
) {
int minSampleX = axisCells;
int maxSampleX = 0;
int minSampleZ = axisCells;
int maxSampleZ = 0;
for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
int columnIndex = planeColumnIndices[planeIndex];
int localX = PowerOfTwoCoordinates.unpackLocal16X(columnIndex);
int localZ = columnIndex & 15;
int sampleX = Math.min(localX / adaptiveSampleStep, axisCells - 1);
int sampleZ = Math.min(localZ / adaptiveSampleStep, axisCells - 1);
if (sampleX < minSampleX) {
minSampleX = sampleX;
}
if (sampleX + 1 > maxSampleX) {
maxSampleX = sampleX + 1;
}
if (sampleZ < minSampleZ) {
minSampleZ = sampleZ;
}
if (sampleZ + 1 > maxSampleZ) {
maxSampleZ = sampleZ + 1;
}
}
adaptivePlaneSampleBounds[0] = minSampleX;
adaptivePlaneSampleBounds[1] = maxSampleX;
adaptivePlaneSampleBounds[2] = minSampleZ;
adaptivePlaneSampleBounds[3] = maxSampleZ;
}
private void prepareAdaptivePlaneColumns( private void prepareAdaptivePlaneColumns(
int[] planeColumnIndices, int[] planeColumnIndices,
int planeCount, int planeCount,
@@ -1654,6 +1890,10 @@ public class IrisCaveCarver3D {
} }
ModuleState[] localModules = scratch.activeModules; ModuleState[] localModules = scratch.activeModules;
return sampleDensityWarpModules(x, y, z, localModules, activeModuleCount);
}
private double sampleDensityWarpModules(int x, int y, int z, ModuleState[] localModules, int activeModuleCount) {
double warpA = warpDensity.noiseFastSigned3D(x, y, z); double warpA = warpDensity.noiseFastSigned3D(x, y, z);
double warpB = warpDensity.noiseFastSigned3D(x + 31.37D, y - 17.21D, z + 23.91D); double warpB = warpDensity.noiseFastSigned3D(x + 31.37D, y - 17.21D, z + 23.91D);
double warpedX = x + (warpA * warpStrength); double warpedX = x + (warpA * warpStrength);
@@ -1882,6 +2122,7 @@ public class IrisCaveCarver3D {
private final double[] adaptivePlaneDensity = new double[81]; private final double[] adaptivePlaneDensity = new double[81];
private final double[] adaptivePlanePrediction = new double[256]; private final double[] adaptivePlanePrediction = new double[256];
private final double[] adaptivePlaneAmbiguity = new double[256]; private final double[] adaptivePlaneAmbiguity = new double[256];
private final int[] adaptivePlaneSampleBounds = new int[4];
private final int[] tileIndices = new int[4]; private final int[] tileIndices = new int[4];
private final int[] tileLocalX = new int[4]; private final int[] tileLocalX = new int[4];
private final int[] tileLocalZ = new int[4]; private final int[] tileLocalZ = new int[4];
@@ -31,11 +31,12 @@ import art.arcane.iris.engine.object.IrisDimensionCarvingResolver;
import art.arcane.iris.engine.object.IrisRegion; import art.arcane.iris.engine.object.IrisRegion;
import art.arcane.iris.engine.object.IrisRange; import art.arcane.iris.engine.object.IrisRange;
import art.arcane.iris.util.project.context.ChunkContext; import art.arcane.iris.util.project.context.ChunkContext;
import art.arcane.iris.util.project.stream.ProceduralStream;
import art.arcane.iris.util.project.stream.utility.ChunkFillableDoubleStream2D;
import art.arcane.volmlib.util.documentation.ChunkCoordinates; import art.arcane.volmlib.util.documentation.ChunkCoordinates;
import art.arcane.volmlib.util.mantle.flag.ReservedFlag; import art.arcane.volmlib.util.mantle.flag.ReservedFlag;
import art.arcane.volmlib.util.math.PowerOfTwoCoordinates; import art.arcane.volmlib.util.math.PowerOfTwoCoordinates;
import art.arcane.volmlib.util.scheduling.PrecisionStopwatch; import art.arcane.volmlib.util.scheduling.PrecisionStopwatch;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -82,11 +83,10 @@ public class MantleCarvingComponent extends IrisMantleComponent {
public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) { public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) {
IrisComplex complex = context.getComplex(); IrisComplex complex = context.getComplex();
IrisDimensionCarvingResolver.State resolverState = new IrisDimensionCarvingResolver.State(); IrisDimensionCarvingResolver.State resolverState = new IrisDimensionCarvingResolver.State();
Long2ObjectOpenHashMap<IrisBiome> caveBiomeCache = new Long2ObjectOpenHashMap<>(FIELD_SIZE * FIELD_SIZE);
BlendScratch blendScratch = BLEND_SCRATCH.get(); BlendScratch blendScratch = BLEND_SCRATCH.get();
int[] chunkSurfaceHeights = prepareChunkSurfaceHeights(x, z, context, blendScratch.chunkSurfaceHeights); int[] chunkSurfaceHeights = prepareChunkSurfaceHeights(x, z, context, blendScratch.chunkSurfaceHeights);
PrecisionStopwatch resolveStopwatch = PrecisionStopwatch.start(); PrecisionStopwatch resolveStopwatch = PrecisionStopwatch.start();
List<WeightedProfile> weightedProfiles = resolveWeightedProfiles(x, z, complex, resolverState, caveBiomeCache); List<WeightedProfile> weightedProfiles = resolveWeightedProfiles(x, z, complex, resolverState);
getEngineMantle().getEngine().getMetrics().getCarveResolve().put(resolveStopwatch.getMilliseconds()); getEngineMantle().getEngine().getMetrics().getCarveResolve().put(resolveStopwatch.getMilliseconds());
for (WeightedProfile weightedProfile : weightedProfiles) { for (WeightedProfile weightedProfile : weightedProfiles) {
carveProfile(weightedProfile, writer, x, z, chunkSurfaceHeights); carveProfile(weightedProfile, writer, x, z, chunkSurfaceHeights);
@@ -99,7 +99,7 @@ public class MantleCarvingComponent extends IrisMantleComponent {
carver.carve(writer, cx, cz, weightedProfile.columnWeights, MIN_WEIGHT, THRESHOLD_PENALTY, weightedProfile.worldYRange, chunkSurfaceHeights); carver.carve(writer, cx, cz, weightedProfile.columnWeights, MIN_WEIGHT, THRESHOLD_PENALTY, weightedProfile.worldYRange, chunkSurfaceHeights);
} }
private List<WeightedProfile> resolveWeightedProfiles(int chunkX, int chunkZ, IrisComplex complex, IrisDimensionCarvingResolver.State resolverState, Long2ObjectOpenHashMap<IrisBiome> caveBiomeCache) { private List<WeightedProfile> resolveWeightedProfiles(int chunkX, int chunkZ, IrisComplex complex, IrisDimensionCarvingResolver.State resolverState) {
BlendScratch blendScratch = BLEND_SCRATCH.get(); BlendScratch blendScratch = BLEND_SCRATCH.get();
IrisCaveProfile[] profileField = blendScratch.profileField; IrisCaveProfile[] profileField = blendScratch.profileField;
Map<IrisCaveProfile, double[]> columnProfileWeights = blendScratch.columnProfileWeights; Map<IrisCaveProfile, double[]> columnProfileWeights = blendScratch.columnProfileWeights;
@@ -107,7 +107,7 @@ public class MantleCarvingComponent extends IrisMantleComponent {
IrisCaveProfile[] kernelProfiles = blendScratch.kernelProfiles; IrisCaveProfile[] kernelProfiles = blendScratch.kernelProfiles;
double[] kernelProfileWeights = blendScratch.kernelProfileWeights; double[] kernelProfileWeights = blendScratch.kernelProfileWeights;
activeProfiles.clear(); activeProfiles.clear();
fillProfileField(profileField, chunkX, chunkZ, complex, resolverState, caveBiomeCache); fillProfileField(profileField, chunkX, chunkZ, complex, resolverState, blendScratch);
for (int localX = 0; localX < CHUNK_SIZE; localX++) { for (int localX = 0; localX < CHUNK_SIZE; localX++) {
for (int localZ = 0; localZ < CHUNK_SIZE; localZ++) { for (int localZ = 0; localZ < CHUNK_SIZE; localZ++) {
@@ -268,15 +268,25 @@ public class MantleCarvingComponent extends IrisMantleComponent {
} }
} }
private void fillProfileField(IrisCaveProfile[] profileField, int chunkX, int chunkZ, IrisComplex complex, IrisDimensionCarvingResolver.State resolverState, Long2ObjectOpenHashMap<IrisBiome> caveBiomeCache) { private void fillProfileField(IrisCaveProfile[] profileField, int chunkX, int chunkZ, IrisComplex complex, IrisDimensionCarvingResolver.State resolverState, BlendScratch blendScratch) {
int startX = PowerOfTwoCoordinates.chunkToBlock(chunkX) - BLEND_RADIUS; int startX = PowerOfTwoCoordinates.chunkToBlock(chunkX) - BLEND_RADIUS;
int startZ = PowerOfTwoCoordinates.chunkToBlock(chunkZ) - BLEND_RADIUS; int startZ = PowerOfTwoCoordinates.chunkToBlock(chunkZ) - BLEND_RADIUS;
prefillProfileFieldSamples(startX, startZ, complex, blendScratch);
for (int fieldX = 0; fieldX < FIELD_SIZE; fieldX++) { for (int fieldX = 0; fieldX < FIELD_SIZE; fieldX++) {
int worldX = startX + fieldX; int worldX = startX + fieldX;
for (int fieldZ = 0; fieldZ < FIELD_SIZE; fieldZ++) { for (int fieldZ = 0; fieldZ < FIELD_SIZE; fieldZ++) {
int worldZ = startZ + fieldZ; int worldZ = startZ + fieldZ;
profileField[(fieldX * FIELD_SIZE) + fieldZ] = resolveColumnProfile(worldX, worldZ, complex, resolverState, caveBiomeCache); int fieldIndex = (fieldX * FIELD_SIZE) + fieldZ;
profileField[fieldIndex] = resolveColumnProfile(
worldX,
worldZ,
blendScratch.fieldSurfaceHeights[fieldIndex],
blendScratch.fieldRegions[fieldIndex],
blendScratch.fieldSurfaceBiomes[fieldIndex],
blendScratch.fieldCaveBiomes[fieldIndex],
resolverState
);
} }
} }
} }
@@ -291,14 +301,21 @@ public class MantleCarvingComponent extends IrisMantleComponent {
return -1; return -1;
} }
private IrisCaveProfile resolveColumnProfile(int worldX, int worldZ, IrisComplex complex, IrisDimensionCarvingResolver.State resolverState, Long2ObjectOpenHashMap<IrisBiome> caveBiomeCache) { private IrisCaveProfile resolveColumnProfile(
int worldX,
int worldZ,
double surfaceHeight,
IrisRegion region,
IrisBiome surfaceBiome,
IrisBiome caveBiome,
IrisDimensionCarvingResolver.State resolverState
) {
IrisCaveProfile resolved = null; IrisCaveProfile resolved = null;
IrisCaveProfile dimensionProfile = getDimension().getCaveProfile(); IrisCaveProfile dimensionProfile = getDimension().getCaveProfile();
if (isProfileEnabled(dimensionProfile)) { if (isProfileEnabled(dimensionProfile)) {
resolved = dimensionProfile; resolved = dimensionProfile;
} }
IrisRegion region = complex.getRegionStream().get(worldX, worldZ);
if (region != null) { if (region != null) {
IrisCaveProfile regionProfile = region.getCaveProfile(); IrisCaveProfile regionProfile = region.getCaveProfile();
if (isProfileEnabled(regionProfile)) { if (isProfileEnabled(regionProfile)) {
@@ -306,7 +323,6 @@ public class MantleCarvingComponent extends IrisMantleComponent {
} }
} }
IrisBiome surfaceBiome = complex.getTrueBiomeStream().get(worldX, worldZ);
if (surfaceBiome != null) { if (surfaceBiome != null) {
IrisCaveProfile surfaceProfile = surfaceBiome.getCaveProfile(); IrisCaveProfile surfaceProfile = surfaceBiome.getCaveProfile();
if (isProfileEnabled(surfaceProfile)) { if (isProfileEnabled(surfaceProfile)) {
@@ -314,18 +330,36 @@ public class MantleCarvingComponent extends IrisMantleComponent {
} }
} }
int surfaceY = getEngineMantle().getEngine().getHeight(worldX, worldZ, true); int roundedSurfaceY = (int) Math.round(surfaceHeight);
int sampleY = Math.max(1, surfaceY - 56); int sampleY = Math.max(1, roundedSurfaceY - 56);
long cacheKey = Cache.key(worldX, worldZ); int worldY = sampleY + getEngineMantle().getEngine().getWorld().minHeight();
IrisBiome caveBiome = caveBiomeCache.get(cacheKey); IrisDimensionCarvingEntry rootCarvingEntry = IrisDimensionCarvingResolver.resolveRootEntry(getEngineMantle().getEngine(), worldY, resolverState);
if (caveBiome == null) { IrisBiome resolvedCarvingBiome = null;
caveBiome = getEngineMantle().getEngine().getCaveBiome(worldX, sampleY, worldZ, resolverState); if (rootCarvingEntry != null) {
if (caveBiome != null) { IrisDimensionCarvingEntry resolvedCarvingEntry = IrisDimensionCarvingResolver.resolveFromRoot(getEngineMantle().getEngine(), rootCarvingEntry, worldX, worldZ, resolverState);
caveBiomeCache.put(cacheKey, caveBiome); resolvedCarvingBiome = IrisDimensionCarvingResolver.resolveEntryBiome(getEngineMantle().getEngine(), resolvedCarvingEntry, resolverState);
if (resolvedCarvingBiome != null) {
caveBiome = resolvedCarvingBiome;
} }
} }
if (caveBiome != null) { if (caveBiome != null) {
IrisCaveProfile caveProfile = caveBiome.getCaveProfile(); IrisBiome effectiveCaveBiome = caveBiome;
if (resolvedCarvingBiome == null && surfaceBiome != null) {
if (surfaceBiome != null) {
int truncatedSurfaceY = (int) surfaceHeight;
int depthBelowSurface = truncatedSurfaceY - sampleY;
if (depthBelowSurface <= 0) {
effectiveCaveBiome = surfaceBiome;
} else {
int minDepth = Math.max(0, caveBiome.getCaveMinDepthBelowSurface());
if (depthBelowSurface < minDepth) {
effectiveCaveBiome = surfaceBiome;
}
}
}
}
IrisCaveProfile caveProfile = effectiveCaveBiome.getCaveProfile();
if (isProfileEnabled(caveProfile)) { if (isProfileEnabled(caveProfile)) {
resolved = caveProfile; resolved = caveProfile;
} }
@@ -334,6 +368,31 @@ public class MantleCarvingComponent extends IrisMantleComponent {
return resolved; return resolved;
} }
private void prefillProfileFieldSamples(int startX, int startZ, IrisComplex complex, BlendScratch blendScratch) {
fillFieldHeights(complex.getHeightStream(), startX, startZ, blendScratch.fieldSurfaceHeights);
fillFieldObjects(complex.getRegionStream(), startX, startZ, blendScratch.fieldRegions);
fillFieldObjects(complex.getTrueBiomeStream(), startX, startZ, blendScratch.fieldSurfaceBiomes);
fillFieldObjects(complex.getCaveBiomeStream(), startX, startZ, blendScratch.fieldCaveBiomes);
}
private <T> void fillFieldObjects(ProceduralStream<T> stream, int startX, int startZ, T[] target) {
for (int fieldX = 0; fieldX < FIELD_SIZE; fieldX++) {
int worldX = startX + fieldX;
for (int fieldZ = 0; fieldZ < FIELD_SIZE; fieldZ++) {
target[(fieldX * FIELD_SIZE) + fieldZ] = stream.get(worldX, startZ + fieldZ);
}
}
}
private void fillFieldHeights(ProceduralStream<Double> stream, int startX, int startZ, double[] target) {
for (int fieldX = 0; fieldX < FIELD_SIZE; fieldX++) {
int worldX = startX + fieldX;
for (int fieldZ = 0; fieldZ < FIELD_SIZE; fieldZ++) {
target[(fieldX * FIELD_SIZE) + fieldZ] = stream.getDouble(worldX, startZ + fieldZ);
}
}
}
private IrisCaveCarver3D getCarver(IrisCaveProfile profile) { private IrisCaveCarver3D getCarver(IrisCaveProfile profile) {
synchronized (profileCarvers) { synchronized (profileCarvers) {
IrisCaveCarver3D carver = profileCarvers.get(profile); IrisCaveCarver3D carver = profileCarvers.get(profile);
@@ -363,6 +422,14 @@ public class MantleCarvingComponent extends IrisMantleComponent {
&& context.getHeight() != null && context.getHeight() != null
&& context.getX() == baseX && context.getX() == baseX
&& context.getZ() == baseZ; && context.getZ() == baseZ;
double[] cachedChunkHeights = null;
if (!useContextHeight && context != null) {
ProceduralStream<Double> heightStream = context.getComplex().getHeightStream();
if (heightStream instanceof ChunkFillableDoubleStream2D cachedHeightStream) {
cachedChunkHeights = BLEND_SCRATCH.get().chunkSurfaceHeightSamples;
cachedHeightStream.fillChunkDoubles(baseX, baseZ, cachedChunkHeights);
}
}
for (int localX = 0; localX < CHUNK_SIZE; localX++) { for (int localX = 0; localX < CHUNK_SIZE; localX++) {
int worldX = baseX + localX; int worldX = baseX + localX;
for (int localZ = 0; localZ < CHUNK_SIZE; localZ++) { for (int localZ = 0; localZ < CHUNK_SIZE; localZ++) {
@@ -375,6 +442,10 @@ public class MantleCarvingComponent extends IrisMantleComponent {
continue; continue;
} }
} }
if (cachedChunkHeights != null) {
surfaceHeights[columnIndex] = (int) Math.round(cachedChunkHeights[columnIndex]);
continue;
}
surfaceHeights[columnIndex] = getEngineMantle().getEngine().getHeight(worldX, worldZ); surfaceHeights[columnIndex] = getEngineMantle().getEngine().getHeight(worldX, worldZ);
} }
} }
@@ -510,6 +581,11 @@ public class MantleCarvingComponent extends IrisMantleComponent {
private final IdentityHashMap<IrisCaveProfile, double[]> columnProfileWeights = new IdentityHashMap<>(); private final IdentityHashMap<IrisCaveProfile, double[]> columnProfileWeights = new IdentityHashMap<>();
private final IdentityHashMap<IrisDimensionCarvingEntry, IrisDimensionCarvingEntry[]> dimensionColumnPlans = new IdentityHashMap<>(); private final IdentityHashMap<IrisDimensionCarvingEntry, IrisDimensionCarvingEntry[]> dimensionColumnPlans = new IdentityHashMap<>();
private final IdentityHashMap<IrisCaveProfile, Boolean> activeProfiles = new IdentityHashMap<>(); private final IdentityHashMap<IrisCaveProfile, Boolean> activeProfiles = new IdentityHashMap<>();
private final double[] fieldSurfaceHeights = new double[FIELD_SIZE * FIELD_SIZE];
private final IrisRegion[] fieldRegions = new IrisRegion[FIELD_SIZE * FIELD_SIZE];
private final IrisBiome[] fieldSurfaceBiomes = new IrisBiome[FIELD_SIZE * FIELD_SIZE];
private final IrisBiome[] fieldCaveBiomes = new IrisBiome[FIELD_SIZE * FIELD_SIZE];
private final int[] chunkSurfaceHeights = new int[CHUNK_AREA]; private final int[] chunkSurfaceHeights = new int[CHUNK_AREA];
private final double[] chunkSurfaceHeightSamples = new double[CHUNK_AREA];
} }
} }
@@ -9,7 +9,7 @@ import art.arcane.iris.util.project.stream.ProceduralStream;
import art.arcane.volmlib.util.cache.WorldCache2DDouble; import art.arcane.volmlib.util.cache.WorldCache2DDouble;
import art.arcane.volmlib.util.data.KCache; import art.arcane.volmlib.util.data.KCache;
public class CachedDoubleStream2D extends BasicStream<Double> implements ProceduralStream<Double>, MeteredCache, ChunkFillableStream2D { public class CachedDoubleStream2D extends BasicStream<Double> implements ProceduralStream<Double>, MeteredCache, ChunkFillableStream2D, ChunkFillableDoubleStream2D {
private final ProceduralStream<Double> stream; private final ProceduralStream<Double> stream;
private final WorldCache2DDouble cache; private final WorldCache2DDouble cache;
private final Engine engine; private final Engine engine;
@@ -73,4 +73,11 @@ public class CachedDoubleStream2D extends BasicStream<Double> implements Procedu
int chunkZ = worldZ >> 4; int chunkZ = worldZ >> 4;
cache.fillChunk(chunkX, chunkZ, target); cache.fillChunk(chunkX, chunkZ, target);
} }
@Override
public void fillChunkDoubles(int worldX, int worldZ, double[] target) {
int chunkX = worldX >> 4;
int chunkZ = worldZ >> 4;
cache.fillChunk(chunkX, chunkZ, target);
}
} }
@@ -0,0 +1,5 @@
package art.arcane.iris.util.project.stream.utility;
public interface ChunkFillableDoubleStream2D {
void fillChunkDoubles(int worldX, int worldZ, double[] target);
}
@@ -0,0 +1,24 @@
package art.arcane.iris.engine.framework;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class EngineModeMaintenanceTest {
@Test
public void maintenanceDisablesContextCacheWithoutActivePregen() {
assertTrue(EngineMode.shouldDisableContextCacheForMaintenance(true, false));
}
@Test
public void maintenanceKeepsContextCacheForActivePregenWorld() {
assertFalse(EngineMode.shouldDisableContextCacheForMaintenance(true, true));
}
@Test
public void noMaintenanceKeepsContextCacheEnabled() {
assertFalse(EngineMode.shouldDisableContextCacheForMaintenance(false, false));
assertFalse(EngineMode.shouldDisableContextCacheForMaintenance(false, true));
}
}