Refined existing noise

- Hexagon styles produce coherent solid cells with contained subdivisions
- Sierpinski triangles use equilateral recursive geometry
- Noise styles share a 64-block base scale
- Zoom scales the complete pattern with its distortion
- Octaves preserve the base seed and feature scale
- Coordinate dispatch uses the native dimensional sampler
- Classic kernels retain seed precision and bounded output
- Interpolation preserves fractional coordinates and symmetric curves
- Noise caches respect sampling bounds and generation identity
- Clover sampling reuses vertices and cached trigonometry
- Noise and terrain tests cover corrected sampling behavior
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-05 19:32:13 -04:00
1 parent f2887632fe
commit 50894b90ce
47 files changed
+2603 -1542

No files matched your search

@@ -21,6 +21,7 @@ package art.arcane.iris.engine.object;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.engine.data.cache.LazyBoundedCache;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.history.GenerationKernelRegistry;
import art.arcane.iris.engine.object.annotations.Desc;
import art.arcane.iris.engine.object.annotations.MaxNumber;
import art.arcane.iris.engine.object.annotations.MinNumber;
@@ -40,6 +41,7 @@ import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@@ -65,7 +67,7 @@ public class IrisGeneratorStyle {
@Desc("Cell zooms")
private double cellularZoom = 1;
@MinNumber(0.00001)
@Desc("The zoom of this style")
@Desc("Feature size multiplier. Built-in coherent noise uses a 64-block base scale; 2 doubles feature size.")
private double zoom = 1;
@Desc("Instead of using the style property, use a custom expression to represent this style.")
@RegistryListResource(IrisExpression.class)
@@ -97,11 +99,15 @@ public class IrisGeneratorStyle {
}
public CNG createNoCache(RNG rng, IrisData data) {
return createNoCache(rng, data, false, 0, false, resolveEngine(data));
return createNoCache(rng, data, 1, 0, false, resolveEngine(data));
}
public CNG createForLayer(RNG rng, IrisData data, int octaveMultiplier) {
return createNoCache(rng, data, Math.clamp(octaveMultiplier, 1, 16), 0, false, resolveEngine(data));
}
public CNG createForPrebake(RNG rng, IrisData data, int fallbackCacheSize) {
return createNoCache(rng, data, false, Math.max(0, fallbackCacheSize), true, resolveEngine(data));
return createNoCache(rng, data, 1, Math.max(0, fallbackCacheSize), true, resolveEngine(data));
}
@@ -121,16 +127,17 @@ public class IrisGeneratorStyle {
return hash();
}
private String cachePrefix(RNG rng, int effectiveCacheSize, long engineStamp) {
return "style-" + Integer.toUnsignedString(hash())
private String cachePrefix(RNG rng, int effectiveCacheSize, long engineStamp, int octaveMultiplier) {
return "noise-" + NoiseCacheIdentity.FINGERPRINT + "-style-" + Integer.toUnsignedString(hash())
+ "-seed-" + Long.toUnsignedString(rng.getSeed())
+ "-eng-" + Long.toUnsignedString(engineStamp)
+ "-oct-" + octaveMultiplier
+ "-sz-" + effectiveCacheSize
+ "-src-";
}
private String cacheKey(RNG rng, long sourceStamp, int effectiveCacheSize, long engineStamp) {
return cachePrefix(rng, effectiveCacheSize, engineStamp) + Long.toUnsignedString(sourceStamp);
private String cacheKey(RNG rng, long sourceStamp, int effectiveCacheSize, long engineStamp, int octaveMultiplier) {
return cachePrefix(rng, effectiveCacheSize, engineStamp, octaveMultiplier) + Long.toUnsignedString(sourceStamp);
}
private void clearStaleCacheEntries(IrisData data, String prefix, String key) {
@@ -157,12 +164,19 @@ public class IrisGeneratorStyle {
}
}
public CNG createNoCache(RNG rng, IrisData data, boolean actuallyCached) {
return createNoCache(rng, data, actuallyCached, 0, false, resolveEngine(data));
}
private CNG createNoCache(RNG rng, IrisData data, boolean actuallyCached, int fallbackCacheSize,
private CNG createNoCache(RNG rng, IrisData data, int octaveMultiplier, int fallbackCacheSize,
boolean quietCacheLog, Engine engine) {
requirePositiveFinite("zoom", zoom);
requirePositiveFinite("exponent", exponent);
if (!Double.isFinite(cellularFrequency) || cellularFrequency < 0D) {
throw new IllegalArgumentException("cellularFrequency must be finite and nonnegative");
}
if (cellularFrequency > 0D) {
requirePositiveFinite("cellularZoom", cellularZoom);
}
if (fracture != null) {
requirePositiveFinite("fracture.multiplier", fracture.getMultiplier());
}
CNG cng = null;
long sourceStamp = 0L;
if (getExpression() != null) {
@@ -182,10 +196,11 @@ public class IrisGeneratorStyle {
cng = (style != null ? style : NoiseStyle.FLAT).create(rng).bake();
}
cng = cng.scale(1D / zoom).pow(exponent).bake();
cng = cng.oct(Math.clamp((long) cng.getOct() * octaveMultiplier, 1, 16))
.pow(cng.getPower() * exponent);
if (fracture != null) {
cng.fractureWith(fracture.createNoCache(rng.nextParallelRNG(2934), data, false,
cng.fractureWith(fracture.createNoCache(rng.nextParallelRNG(2934), data, 1,
fallbackCacheSize, quietCacheLog, engine), fracture.getMultiplier());
}
@@ -193,11 +208,13 @@ public class IrisGeneratorStyle {
cng = cng.cellularize(rng.nextParallelRNG(884466), cellularFrequency).scale(1D / cellularZoom).bake();
}
cng.zoom(zoom);
int effectiveCacheSize = cacheSize > 0 ? cacheSize : Math.max(0, fallbackCacheSize);
if (effectiveCacheSize > 0) {
long engineStamp = engineStamp(engine);
String key = cacheKey(rng, sourceStamp, effectiveCacheSize, engineStamp);
clearStaleCacheEntries(data, cachePrefix(rng, effectiveCacheSize, engineStamp), key);
String key = cacheKey(rng, sourceStamp, effectiveCacheSize, engineStamp, octaveMultiplier);
clearStaleCacheEntries(data, cachePrefix(rng, effectiveCacheSize, engineStamp, octaveMultiplier), key);
cng = cng.cached(effectiveCacheSize, key, data.getDataFolder(), quietCacheLog);
}
@@ -215,7 +232,7 @@ public class IrisGeneratorStyle {
public CNG create(RNG rng, IrisData data, Engine engine) {
GeneratorCacheKey key = new GeneratorCacheKey(data, engine, rng.getSeed());
return generatorCache.computeIfAbsent(key,
ignored -> createNoCache(rng, data, true, 0, false, engine));
ignored -> createNoCache(rng, data, 1, 0, false, engine));
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
@@ -244,6 +261,25 @@ public class IrisGeneratorStyle {
return data == null ? null : data.getEngine();
}
private static void requirePositiveFinite(String field, double value) {
if (!Double.isFinite(value) || value <= 0D || !Double.isFinite(1D / value)) {
throw new IllegalArgumentException(field + " must be finite and positive");
}
}
private static final class NoiseCacheIdentity {
private static final String FINGERPRINT = fingerprint();
private static String fingerprint() {
GenerationKernelRegistry registry = GenerationKernelRegistry.standard();
try {
return registry.requireSupported(registry.current()).implementationFingerprint();
} catch (IOException failure) {
throw new IllegalStateException("Cannot identify the noise cache implementation", failure);
}
}
}
private static final class GeneratorCacheKey {
private final IrisData data;
private final Engine engine;
@@ -90,7 +90,8 @@ public class IrisNoiseGenerator {
@Desc("The Noise Style")
private IrisGeneratorStyle style = NoiseStyle.IRIS.style();
@MinNumber(1)
@Desc("Multiple octaves for multple generators of changing zooms added together")
@MaxNumber(16)
@Desc("Multiplies the style's octave count, capped at 16. Adds finer detail while preserving the base feature scale.")
private int octaves = 1;
@ArrayType(min = 1, type = IrisNoiseGenerator.class)
@Desc("Apply a child noise generator to fracture the input coordinates of this generator")
@@ -111,7 +112,7 @@ public class IrisNoiseGenerator {
GeneratorKey key = new GeneratorKey(data, engine, generatorSeed);
CNG generator = generators.computeIfAbsent(key,
ignored -> style.createNoCache(new RNG(generatorSeed), data).oct(octaves));
ignored -> style.createForLayer(new RNG(generatorSeed), data, octaves));
if (generator != null) {
recentGenerator.set(new CachedGenerator(key, generator));
}
@@ -146,7 +147,7 @@ public class IrisNoiseGenerator {
double n = cng.noiseFast2D(sampleX, sampleZ) * opacity;
n = negative ? (-n + opacity) : n;
n = (exponent != 1 ? n < 0 ? -Math.pow(-n, exponent) : Math.pow(n, exponent) : n) + offsetY;
n = parametric ? IrisInterpolation.parametric(n, 1) : n;
n = parametric ? IrisInterpolation.parametric(n, 2D) : n;
n = bezier ? IrisInterpolation.bezier(n) : n;
n = sinCentered ? IrisInterpolation.sinCenter(n) : n;
@@ -27,523 +27,529 @@ import art.arcane.iris.util.project.stream.ProceduralStream;
@Desc("Styles of noise")
public enum NoiseStyle {
@Desc("White Noise is like static. Useful for block scattering but not terrain.")
STATIC(rng -> new CNG(rng, NoiseType.WHITE, 1D, 1)),
STATIC(rng -> new CNG(rng, NoiseType.WHITE, 1D, 1), NoiseType.WHITE),
@Desc("White Noise is like static. Useful for block scattering but not terrain.")
STATIC_BILINEAR(rng -> new CNG(rng, NoiseType.WHITE_BILINEAR, 1D, 1)),
STATIC_BILINEAR(rng -> new CNG(rng, NoiseType.WHITE_BILINEAR, 1D, 1), NoiseType.WHITE_BILINEAR),
@Desc("White Noise is like static. Useful for block scattering but not terrain.")
STATIC_BICUBIC(rng -> new CNG(rng, NoiseType.WHITE_BICUBIC, 1D, 1)),
STATIC_BICUBIC(rng -> new CNG(rng, NoiseType.WHITE_BICUBIC, 1D, 1), NoiseType.WHITE_BICUBIC),
@Desc("White Noise is like static. Useful for block scattering but not terrain.")
STATIC_HERMITE(rng -> new CNG(rng, NoiseType.WHITE_HERMITE, 1D, 1)),
STATIC_HERMITE(rng -> new CNG(rng, NoiseType.WHITE_HERMITE, 1D, 1), NoiseType.WHITE_HERMITE),
@Desc("Wispy Perlin-looking simplex noise. The 'iris' style noise.")
IRIS(rng -> CNG.signature(rng).scale(1)),
IRIS(rng -> CNG.signature(rng)),
@Desc("Clover Noise")
CLOVER(rng -> new CNG(rng, NoiseType.CLOVER, 1D, 1).scale(0.06).bake()),
CLOVER(rng -> new CNG(rng, NoiseType.CLOVER, 1D, 1).bake(), NoiseType.CLOVER),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_STARCAST_3(rng -> new CNG(rng, NoiseType.CLOVER_STARCAST_3, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_STARCAST_3(rng -> new CNG(rng, NoiseType.CLOVER_STARCAST_3, 1D, 1), NoiseType.CLOVER_STARCAST_3),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_STARCAST_6(rng -> new CNG(rng, NoiseType.CLOVER_STARCAST_6, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_STARCAST_6(rng -> new CNG(rng, NoiseType.CLOVER_STARCAST_6, 1D, 1), NoiseType.CLOVER_STARCAST_6),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_STARCAST_9(rng -> new CNG(rng, NoiseType.CLOVER_STARCAST_9, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_STARCAST_9(rng -> new CNG(rng, NoiseType.CLOVER_STARCAST_9, 1D, 1), NoiseType.CLOVER_STARCAST_9),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_STARCAST_12(rng -> new CNG(rng, NoiseType.CLOVER_STARCAST_12, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_STARCAST_12(rng -> new CNG(rng, NoiseType.CLOVER_STARCAST_12, 1D, 1), NoiseType.CLOVER_STARCAST_12),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_BILINEAR_STARCAST_3(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR_STARCAST_3, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_BILINEAR_STARCAST_3(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR_STARCAST_3, 1D, 1), NoiseType.CLOVER_BILINEAR_STARCAST_3),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_BILINEAR_STARCAST_6(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR_STARCAST_6, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_BILINEAR_STARCAST_6(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR_STARCAST_6, 1D, 1), NoiseType.CLOVER_BILINEAR_STARCAST_6),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_BILINEAR_STARCAST_9(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR_STARCAST_9, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_BILINEAR_STARCAST_9(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR_STARCAST_9, 1D, 1), NoiseType.CLOVER_BILINEAR_STARCAST_9),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_BILINEAR_STARCAST_12(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR_STARCAST_12, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_BILINEAR_STARCAST_12(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR_STARCAST_12, 1D, 1), NoiseType.CLOVER_BILINEAR_STARCAST_12),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_HERMITE_STARCAST_3(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE_STARCAST_3, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_HERMITE_STARCAST_3(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE_STARCAST_3, 1D, 1), NoiseType.CLOVER_HERMITE_STARCAST_3),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_HERMITE_STARCAST_6(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE_STARCAST_6, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_HERMITE_STARCAST_6(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE_STARCAST_6, 1D, 1), NoiseType.CLOVER_HERMITE_STARCAST_6),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_HERMITE_STARCAST_9(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE_STARCAST_9, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_HERMITE_STARCAST_9(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE_STARCAST_9, 1D, 1), NoiseType.CLOVER_HERMITE_STARCAST_9),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_HERMITE_STARCAST_12(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE_STARCAST_12, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_HERMITE_STARCAST_12(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE_STARCAST_12, 1D, 1), NoiseType.CLOVER_HERMITE_STARCAST_12),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_BILINEAR(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_BILINEAR(rng -> new CNG(rng, NoiseType.CLOVER_BILINEAR, 1D, 1), NoiseType.CLOVER_BILINEAR),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_BICUBIC(rng -> new CNG(rng, NoiseType.CLOVER_BICUBIC, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_BICUBIC(rng -> new CNG(rng, NoiseType.CLOVER_BICUBIC, 1D, 1), NoiseType.CLOVER_BICUBIC),
@Desc("CLOVER noise creates the same noise level for cells, changes noise level on cell borders.")
CLOVER_HERMITE(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE, 1D, 1)),
@Desc("Clover noise smoothed with the selected interpolation kernel.")
CLOVER_HERMITE(rng -> new CNG(rng, NoiseType.CLOVER_HERMITE, 1D, 1), NoiseType.CLOVER_HERMITE),
@Desc("Vascular noise gets higher as the position nears a cell border.")
VASCULAR(rng -> new CNG(rng, NoiseType.VASCULAR, 1D, 1)),
VASCULAR(rng -> new CNG(rng, NoiseType.VASCULAR, 1D, 1), NoiseType.VASCULAR),
@Desc("It always returns 0.5")
FLAT(rng -> new CNG(rng, NoiseType.FLAT, 1D, 1)),
@Desc("It always returns 1.0")
FLAT(rng -> new CNG(rng, NoiseType.FLAT, 1D, 1), NoiseType.FLAT),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR(rng -> new CNG(rng, NoiseType.CELLULAR, 1D, 1)),
CELLULAR(rng -> new CNG(rng, NoiseType.CELLULAR, 1D, 1), NoiseType.CELLULAR),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_STARCAST_3(rng -> new CNG(rng, NoiseType.CELLULAR_STARCAST_3, 1D, 1)),
CELLULAR_STARCAST_3(rng -> new CNG(rng, NoiseType.CELLULAR_STARCAST_3, 1D, 1), NoiseType.CELLULAR_STARCAST_3),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_STARCAST_6(rng -> new CNG(rng, NoiseType.CELLULAR_STARCAST_6, 1D, 1)),
CELLULAR_STARCAST_6(rng -> new CNG(rng, NoiseType.CELLULAR_STARCAST_6, 1D, 1), NoiseType.CELLULAR_STARCAST_6),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_STARCAST_9(rng -> new CNG(rng, NoiseType.CELLULAR_STARCAST_9, 1D, 1)),
CELLULAR_STARCAST_9(rng -> new CNG(rng, NoiseType.CELLULAR_STARCAST_9, 1D, 1), NoiseType.CELLULAR_STARCAST_9),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_STARCAST_12(rng -> new CNG(rng, NoiseType.CELLULAR_STARCAST_12, 1D, 1)),
CELLULAR_STARCAST_12(rng -> new CNG(rng, NoiseType.CELLULAR_STARCAST_12, 1D, 1), NoiseType.CELLULAR_STARCAST_12),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_BILINEAR_STARCAST_3(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR_STARCAST_3, 1D, 1)),
CELLULAR_BILINEAR_STARCAST_3(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR_STARCAST_3, 1D, 1), NoiseType.CELLULAR_BILINEAR_STARCAST_3),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_BILINEAR_STARCAST_6(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR_STARCAST_6, 1D, 1)),
CELLULAR_BILINEAR_STARCAST_6(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR_STARCAST_6, 1D, 1), NoiseType.CELLULAR_BILINEAR_STARCAST_6),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_BILINEAR_STARCAST_9(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR_STARCAST_9, 1D, 1)),
CELLULAR_BILINEAR_STARCAST_9(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR_STARCAST_9, 1D, 1), NoiseType.CELLULAR_BILINEAR_STARCAST_9),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_BILINEAR_STARCAST_12(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR_STARCAST_12, 1D, 1)),
CELLULAR_BILINEAR_STARCAST_12(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR_STARCAST_12, 1D, 1), NoiseType.CELLULAR_BILINEAR_STARCAST_12),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_HERMITE_STARCAST_3(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE_STARCAST_3, 1D, 1)),
CELLULAR_HERMITE_STARCAST_3(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE_STARCAST_3, 1D, 1), NoiseType.CELLULAR_HERMITE_STARCAST_3),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_HERMITE_STARCAST_6(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE_STARCAST_6, 1D, 1)),
CELLULAR_HERMITE_STARCAST_6(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE_STARCAST_6, 1D, 1), NoiseType.CELLULAR_HERMITE_STARCAST_6),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_HERMITE_STARCAST_9(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE_STARCAST_9, 1D, 1)),
CELLULAR_HERMITE_STARCAST_9(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE_STARCAST_9, 1D, 1), NoiseType.CELLULAR_HERMITE_STARCAST_9),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_HERMITE_STARCAST_12(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE_STARCAST_12, 1D, 1)),
CELLULAR_HERMITE_STARCAST_12(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE_STARCAST_12, 1D, 1), NoiseType.CELLULAR_HERMITE_STARCAST_12),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_BILINEAR(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR, 1D, 1)),
CELLULAR_BILINEAR(rng -> new CNG(rng, NoiseType.CELLULAR_BILINEAR, 1D, 1), NoiseType.CELLULAR_BILINEAR),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_BICUBIC(rng -> new CNG(rng, NoiseType.CELLULAR_BICUBIC, 1D, 1)),
CELLULAR_BICUBIC(rng -> new CNG(rng, NoiseType.CELLULAR_BICUBIC, 1D, 1), NoiseType.CELLULAR_BICUBIC),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
CELLULAR_HERMITE(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE, 1D, 1)),
CELLULAR_HERMITE(rng -> new CNG(rng, NoiseType.CELLULAR_HERMITE, 1D, 1), NoiseType.CELLULAR_HERMITE),
@Desc("Hexagonal cells with stable per-cell values.")
HEXAGON(rng -> new CNG(rng, NoiseType.HEXAGON, 1D, 1).scale(1)),
@Desc("Solid regular hexagons colored by a coherent simplex field.")
HEXAGON(rng -> new CNG(rng, NoiseType.HEXAGON, 1D, 1), NoiseType.HEXAGON),
@Desc("Hex James substitution pattern with 3 large and 3 small recursive hex children plus gaps.")
HEX_JAMES(rng -> new CNG(rng, NoiseType.HEX_JAMES, 1D, 1).scale(1)),
@Desc("Recursive contained hexagons with alternating subdivision probabilities and simplex colors.")
HEX_JAMES(rng -> new CNG(rng, NoiseType.HEX_JAMES, 1D, 1), NoiseType.HEX_JAMES),
@Desc("Interlocked solid hex cells with per-cell values from a smooth simplex heatmap.")
HEX_SIMPLEX(rng -> new CNG(rng, NoiseType.HEX_SIMPLEX, 1D, 1).scale(1)),
HEX_SIMPLEX(rng -> new CNG(rng, NoiseType.HEX_SIMPLEX, 1D, 1), NoiseType.HEX_SIMPLEX),
@Desc("Randomized finite-depth Sierpinski-style hex recursion with per-level random 3-large/3-small James substitution.")
HEX_RANDOM_SIZE(rng -> new CNG(rng, NoiseType.HEX_RANDOM_SIZE, 1D, 1).scale(1)),
@Desc("Finite-depth hexagonal subdivision selected by a seeded field, with coherent simplex colors.")
HEX_RANDOM_SIZE(rng -> new CNG(rng, NoiseType.HEX_RANDOM_SIZE, 1D, 1), NoiseType.HEX_RANDOM_SIZE),
@Desc("Sierpinski triangle mask blended with simplex heat.")
SIERPINSKI_TRIANGLE(rng -> new CNG(rng, NoiseType.SIERPINSKI_TRIANGLE, 1D, 1).scale(1)),
@Desc("Finite-depth equilateral Sierpinski triangles colored by simplex heat.")
SIERPINSKI_TRIANGLE(rng -> new CNG(rng, NoiseType.SIERPINSKI_TRIANGLE, 1D, 1), NoiseType.SIERPINSKI_TRIANGLE),
@Desc("Classic German Engineering")
NOWHERE(rng -> CNG.signaturePerlin(rng).scale(0.776).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE(rng -> CNG.signaturePerlin(rng).bake()),
@Desc("Classic German Engineering")
NOWHERE_CELLULAR(rng -> CNG.signaturePerlin(rng, NoiseType.CELLULAR).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_CELLULAR(rng -> CNG.signaturePerlin(rng, NoiseType.CELLULAR).bake(), NoiseType.CELLULAR),
@Desc("Classic German Engineering")
NOWHERE_CLOVER(rng -> CNG.signaturePerlin(rng, NoiseType.CLOVER).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_CLOVER(rng -> CNG.signaturePerlin(rng, NoiseType.CLOVER).bake(), NoiseType.CLOVER),
@Desc("Classic German Engineering")
NOWHERE_HEXAGON(rng -> CNG.signaturePerlin(rng, NoiseType.HEXAGON).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_HEXAGON(rng -> CNG.signaturePerlin(rng, NoiseType.HEXAGON).bake(), NoiseType.HEXAGON),
@Desc("Classic German Engineering")
NOWHERE_HEX_JAMES(rng -> CNG.signaturePerlin(rng, NoiseType.HEX_JAMES).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_HEX_JAMES(rng -> CNG.signaturePerlin(rng, NoiseType.HEX_JAMES).bake(), NoiseType.HEX_JAMES),
@Desc("Classic German Engineering")
NOWHERE_HEX_SIMPLEX(rng -> CNG.signaturePerlin(rng, NoiseType.HEX_SIMPLEX).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_HEX_SIMPLEX(rng -> CNG.signaturePerlin(rng, NoiseType.HEX_SIMPLEX).bake(), NoiseType.HEX_SIMPLEX),
@Desc("Classic German Engineering")
NOWHERE_HEX_RANDOM_SIZE(rng -> CNG.signaturePerlin(rng, NoiseType.HEX_RANDOM_SIZE).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_HEX_RANDOM_SIZE(rng -> CNG.signaturePerlin(rng, NoiseType.HEX_RANDOM_SIZE).bake(), NoiseType.HEX_RANDOM_SIZE),
@Desc("Classic German Engineering")
NOWHERE_SIERPINSKI_TRIANGLE(rng -> CNG.signaturePerlin(rng, NoiseType.SIERPINSKI_TRIANGLE).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_SIERPINSKI_TRIANGLE(rng -> CNG.signaturePerlin(rng, NoiseType.SIERPINSKI_TRIANGLE).bake(), NoiseType.SIERPINSKI_TRIANGLE),
@Desc("Classic German Engineering")
NOWHERE_SIMPLEX(rng -> CNG.signaturePerlin(rng, NoiseType.SIMPLEX).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_SIMPLEX(rng -> CNG.signaturePerlin(rng, NoiseType.SIMPLEX).bake(), NoiseType.SIMPLEX),
@Desc("Classic German Engineering")
NOWHERE_GLOB(rng -> CNG.signaturePerlin(rng, NoiseType.GLOB).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_GLOB(rng -> CNG.signaturePerlin(rng, NoiseType.GLOB).bake(), NoiseType.GLOB),
@Desc("Classic German Engineering")
NOWHERE_VASCULAR(rng -> CNG.signaturePerlin(rng, NoiseType.VASCULAR).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_VASCULAR(rng -> CNG.signaturePerlin(rng, NoiseType.VASCULAR).bake(), NoiseType.VASCULAR),
@Desc("Classic German Engineering")
NOWHERE_CUBIC(rng -> CNG.signaturePerlin(rng, NoiseType.CUBIC).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_CUBIC(rng -> CNG.signaturePerlin(rng, NoiseType.CUBIC).bake(), NoiseType.CUBIC),
@Desc("Classic German Engineering")
NOWHERE_SUPERFRACTAL(rng -> CNG.signaturePerlin(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_SUPERFRACTAL(rng -> CNG.signaturePerlin(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX).bake(), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Classic German Engineering")
NOWHERE_FRACTAL(rng -> CNG.signaturePerlin(rng, NoiseType.FRACTAL_BILLOW_PERLIN).scale(1).bake()),
@Desc("Perlin-warped noise with broad, flowing distortion.")
NOWHERE_FRACTAL(rng -> CNG.signaturePerlin(rng, NoiseType.FRACTAL_BILLOW_PERLIN).bake(), NoiseType.FRACTAL_BILLOW_PERLIN),
@Desc("Wispy Perlin-looking simplex noise. The 'iris' style noise.")
IRIS_DOUBLE(rng -> CNG.signatureDouble(rng).scale(1)),
IRIS_DOUBLE(rng -> CNG.signatureDouble(rng)),
@Desc("Wispy Perlin-looking simplex noise. The 'iris' style noise.")
IRIS_THICK(rng -> CNG.signatureThick(rng).scale(1)),
IRIS_THICK(rng -> CNG.signatureThick(rng)),
@Desc("Wispy Perlin-looking simplex noise. The 'iris' style noise.")
IRIS_HALF(rng -> CNG.signatureHalf(rng).scale(1)),
IRIS_HALF(rng -> CNG.signatureHalf(rng)),
@Desc("Basic, Smooth & Fast Simplex noise.")
SIMPLEX(rng -> new CNG(rng, 1D, 1).scale(1)),
SIMPLEX(rng -> new CNG(rng, 1D, 1)),
@Desc("Very Detailed smoke using simplex fractured with fractal billow simplex at high octaves.")
FRACTAL_SMOKE(rng -> new CNG(rng, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(1), NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 8).scale(0.2), 1000).scale(0.34)),
FRACTAL_SMOKE(rng -> new CNG(rng, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(1), NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 8).scale(0.2), 1000), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("Thinner Veins.")
VASCULAR_THIN(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.VASCULAR, 1D, 1).scale(1).pow(0.65)),
VASCULAR_THIN(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.VASCULAR, 1D, 1).scale(1).pow(1D / 0.65D), NoiseType.VASCULAR),
@Desc("Cells of simplex noise")
SIMPLEX_CELLS(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.SIMPLEX, 1D, 1).scale(1).fractureWith(new CNG(rng.nextParallelRNG(8), NoiseType.CELLULAR, 1D, 1).scale(1), 200)),
SIMPLEX_CELLS(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.SIMPLEX, 1D, 1).scale(1).fractureWith(new CNG(rng.nextParallelRNG(8), NoiseType.CELLULAR, 1D, 1).scale(1), 200), NoiseType.SIMPLEX),
@Desc("Veins of simplex noise")
SIMPLEX_VASCULAR(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.SIMPLEX, 1D, 1).scale(1).fractureWith(new CNG(rng.nextParallelRNG(8), NoiseType.VASCULAR, 1D, 1).scale(1), 200)),
SIMPLEX_VASCULAR(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.SIMPLEX, 1D, 1).scale(1).fractureWith(new CNG(rng.nextParallelRNG(8), NoiseType.VASCULAR, 1D, 1).scale(1), 200), NoiseType.SIMPLEX),
@Desc("Very Detailed fluid using simplex fractured with fractal billow simplex at high octaves.")
FRACTAL_WATER(rng -> new CNG(rng, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(1), NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 9).scale(0.03), 9900).scale(1.14)),
FRACTAL_WATER(rng -> new CNG(rng, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(1), NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 9).scale(0.03), 9900), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Perlin. Like simplex but more natural")
PERLIN(rng -> new CNG(rng, NoiseType.PERLIN, 1D, 1).scale(1.15)),
PERLIN(rng -> new CNG(rng, NoiseType.PERLIN, 1D, 1), NoiseType.PERLIN),
@Desc("Perlin. Like simplex but more natural")
PERLIN_IRIS(rng -> CNG.signature(rng, NoiseType.PERLIN).scale(1.47)),
PERLIN_IRIS(rng -> CNG.signature(rng, NoiseType.PERLIN), NoiseType.PERLIN),
@Desc("Perlin. Like simplex but more natural")
PERLIN_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.PERLIN).scale(1.47)),
PERLIN_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.PERLIN), NoiseType.PERLIN),
@Desc("Perlin. Like simplex but more natural")
PERLIN_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.PERLIN).scale(1.47)),
PERLIN_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.PERLIN), NoiseType.PERLIN),
@Desc("Perlin. Like simplex but more natural")
PERLIN_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.PERLIN).scale(1.47)),
PERLIN_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.PERLIN), NoiseType.PERLIN),
@Desc("Billow Fractal Perlin Noise.")
FRACTAL_BILLOW_PERLIN(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_PERLIN, 1D, 1).scale(1.47)),
FRACTAL_BILLOW_PERLIN(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_PERLIN, 1D, 1), NoiseType.FRACTAL_BILLOW_PERLIN),
@Desc("Billow Fractal Perlin Noise. 2 Octaves")
BIOCTAVE_FRACTAL_BILLOW_PERLIN(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_PERLIN, 1D, 2).scale(1.17)),
BIOCTAVE_FRACTAL_BILLOW_PERLIN(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_PERLIN, 1D, 2), NoiseType.FRACTAL_BILLOW_PERLIN),
@Desc("Billow Fractal Simplex Noise. Single octave.")
FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 1)),
FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 1), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. Single octave.")
FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 1)),
FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 1), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Billow Fractal Iris Noise. Single octave.")
FRACTAL_BILLOW_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX)),
FRACTAL_BILLOW_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Iris Noise. Single octave.")
FRACTAL_FBM_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_FBM_SIMPLEX)),
FRACTAL_FBM_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_FBM_SIMPLEX), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Billow Fractal Iris Noise. Single octave.")
FRACTAL_BILLOW_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX)),
FRACTAL_BILLOW_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Iris Noise. Single octave.")
FRACTAL_FBM_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_FBM_SIMPLEX)),
FRACTAL_FBM_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_FBM_SIMPLEX), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Billow Fractal Iris Noise. Single octave.")
FRACTAL_BILLOW_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX)),
FRACTAL_BILLOW_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Iris Noise. Single octave.")
FRACTAL_FBM_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_FBM_SIMPLEX)),
FRACTAL_FBM_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_FBM_SIMPLEX), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Fractal hexagonal cell noise.")
FRACTAL_HEXAGON(rng -> new CNG(rng, NoiseType.HEXAGON, 1D, 4).scale(1)),
FRACTAL_HEXAGON(rng -> new CNG(rng, NoiseType.HEXAGON, 1D, 4), NoiseType.HEXAGON),
@Desc("Fractal Hex James substitution pattern with recursive 3-large/3-small child hexes and gaps.")
FRACTAL_HEX_JAMES(rng -> new CNG(rng, NoiseType.HEX_JAMES, 1D, 4).scale(1)),
@Desc("Recursive contained hexagons colored by fractal simplex noise.")
FRACTAL_HEX_JAMES(rng -> new CNG(rng, NoiseType.HEX_JAMES, 1D, 4), NoiseType.HEX_JAMES),
@Desc("Interlocked solid hex cells with per-cell fractal simplex heatmap values.")
FRACTAL_HEX_SIMPLEX(rng -> new CNG(rng, NoiseType.HEX_SIMPLEX, 1D, 4).scale(1)),
FRACTAL_HEX_SIMPLEX(rng -> new CNG(rng, NoiseType.HEX_SIMPLEX, 1D, 4), NoiseType.HEX_SIMPLEX),
@Desc("Fractal hexagonal gradient noise with randomized local hex sizes and blended random/simplex heatmaps.")
FRACTAL_HEX_RANDOM_SIZE(rng -> new CNG(rng, NoiseType.HEX_RANDOM_SIZE, 1D, 4).scale(1)),
@Desc("Recursive hexagonal subdivision colored by fractal simplex noise.")
FRACTAL_HEX_RANDOM_SIZE(rng -> new CNG(rng, NoiseType.HEX_RANDOM_SIZE, 1D, 4), NoiseType.HEX_RANDOM_SIZE),
@Desc("Fractal Sierpinski triangle mask blended with simplex heat.")
FRACTAL_SIERPINSKI_TRIANGLE(rng -> new CNG(rng, NoiseType.SIERPINSKI_TRIANGLE, 1D, 4).scale(1)),
@Desc("Finite-depth equilateral Sierpinski triangles colored by fractal simplex heat.")
FRACTAL_SIERPINSKI_TRIANGLE(rng -> new CNG(rng, NoiseType.SIERPINSKI_TRIANGLE, 1D, 4), NoiseType.SIERPINSKI_TRIANGLE),
@Desc("Rigid Multi Fractal Simplex Noise. Single octave.")
FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 1)),
FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 1), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 2 octaves.")
BIOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 2)),
BIOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 2), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 2 octaves.")
BIOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 2)),
BIOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 2), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 2 octaves.")
BIOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 2)),
BIOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 2), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 3 octaves.")
TRIOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 3)),
TRIOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 3), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 3 octaves.")
TRIOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 3)),
TRIOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 3), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 3 octaves.")
TRIOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 3)),
TRIOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 3), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 4 octaves.")
QUADOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 4)),
QUADOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 4), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 4 octaves.")
QUADOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 4)),
QUADOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 4), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 4 octaves.")
QUADOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 4)),
QUADOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 4), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 5 octaves.")
QUINTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 5)),
QUINTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 5), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 5 octaves.")
QUINTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 5)),
QUINTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 5), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 5 octaves.")
QUINTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 5)),
QUINTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 5), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 6 octaves.")
SEXOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 6)),
SEXOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 6), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 6 octaves.")
SEXOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 6)),
SEXOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 6), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 6 octaves.")
SEXOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 6)),
SEXOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 6), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 7 octaves.")
SEPTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 7)),
SEPTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 7), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 7 octaves.")
SEPTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 7)),
SEPTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 7), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 7 octaves.")
SEPTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 7)),
SEPTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 7), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 8 octaves.")
OCTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 8)),
OCTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 8), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 8 octaves.")
OCTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 8)),
OCTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 8), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 8 octaves.")
OCTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 8)),
OCTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 8), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 9 octaves.")
NONOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 9)),
NONOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 9), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 9 octaves.")
NONOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 9)),
NONOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 9), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 9 octaves.")
NONOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 9)),
NONOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 9), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Rigid Multi Fractal Simplex Noise. 10 octaves.")
VIGOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 10)),
VIGOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 10), NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX),
@Desc("Billow Fractal Simplex Noise. 10 octaves.")
VIGOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 10)),
VIGOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 10), NoiseType.FRACTAL_BILLOW_SIMPLEX),
@Desc("FBM Fractal Simplex Noise. 10 octaves.")
VIGOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 10)),
VIGOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 10), NoiseType.FRACTAL_FBM_SIMPLEX),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 2 octaves")
BIOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 2).scale(1D / 2D)),
BIOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 2)),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 3 octaves")
TRIOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 3).scale(1D / 3D)),
TRIOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 3)),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 4 octaves")
QUADOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 4).scale(1D / 4D)),
QUADOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 4)),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 5 octaves")
QUINTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 5).scale(1D / 5D)),
QUINTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 5)),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 6 octaves")
SEXOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 6).scale(1D / 6D)),
SEXOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 6)),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 7 octaves")
SEPTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 7).scale(1D / 12D)),
SEPTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 7)),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 8 octaves")
OCTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 8).scale(1D / 25D)),
OCTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 8)),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 9 octaves")
NONOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 9).scale(1D / 50D)),
NONOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 9)),
@Desc("Basic, Smooth & Fast Simplex noise. Uses 10 octaves")
VIGOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 10).scale(1D / 100D)),
VIGOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 10)),
@Desc("Glob noise is like cellular, but with globs...")
GLOB(rng -> new CNG(rng, NoiseType.GLOB, 1D, 1)),
GLOB(rng -> new CNG(rng, NoiseType.GLOB, 1D, 1), NoiseType.GLOB),
@Desc("Glob noise is like cellular, but with globs...")
GLOB_IRIS(rng -> CNG.signature(rng, NoiseType.GLOB)),
GLOB_IRIS(rng -> CNG.signature(rng, NoiseType.GLOB), NoiseType.GLOB),
@Desc("Glob noise is like cellular, but with globs...")
GLOB_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.GLOB)),
GLOB_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.GLOB), NoiseType.GLOB),
@Desc("Glob noise is like cellular, but with globs...")
GLOB_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.GLOB)),
GLOB_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.GLOB), NoiseType.GLOB),
@Desc("Glob noise is like cellular, but with globs...")
GLOB_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.GLOB)),
GLOB_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.GLOB), NoiseType.GLOB),
@Desc("Cubic Noise")
CUBIC(rng -> new CNG(rng, NoiseType.CUBIC, 1D, 1).scale(256)),
CUBIC(rng -> new CNG(rng, NoiseType.CUBIC, 1D, 1), NoiseType.CUBIC),
@Desc("Fractal Cubic Noise")
FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 1).scale(2)),
FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 1), NoiseType.FRACTAL_CUBIC),
@Desc("Fractal Cubic Noise With Iris Swirls")
FRACTAL_CUBIC_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_CUBIC).scale(2)),
FRACTAL_CUBIC_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_CUBIC), NoiseType.FRACTAL_CUBIC),
@Desc("Fractal Cubic Noise With Iris Swirls")
FRACTAL_CUBIC_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_CUBIC).scale(2)),
FRACTAL_CUBIC_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_CUBIC), NoiseType.FRACTAL_CUBIC),
@Desc("Fractal Cubic Noise With Iris Swirls")
FRACTAL_CUBIC_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_CUBIC).scale(2)),
FRACTAL_CUBIC_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_CUBIC), NoiseType.FRACTAL_CUBIC),
@Desc("Fractal Cubic Noise With Iris Swirls")
FRACTAL_CUBIC_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.FRACTAL_CUBIC).scale(2)),
FRACTAL_CUBIC_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.FRACTAL_CUBIC), NoiseType.FRACTAL_CUBIC),
@Desc("Fractal Cubic Noise, 2 Octaves")
BIOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 2).scale(2)),
BIOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 2), NoiseType.FRACTAL_CUBIC),
@Desc("Fractal Cubic Noise, 3 Octaves")
TRIOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 3).scale(1.5)),
TRIOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 3), NoiseType.FRACTAL_CUBIC),
@Desc("Fractal Cubic Noise, 4 Octaves")
QUADOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 4).scale(1)),
QUADOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 4), NoiseType.FRACTAL_CUBIC),
@Desc("Cubic Noise")
CUBIC_IRIS(rng -> CNG.signature(rng, NoiseType.CUBIC).scale(256)),
CUBIC_IRIS(rng -> CNG.signature(rng, NoiseType.CUBIC), NoiseType.CUBIC),
@Desc("Cubic Noise")
CUBIC_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CUBIC).scale(256)),
CUBIC_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CUBIC), NoiseType.CUBIC),
@Desc("Cubic Noise")
CUBIC_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CUBIC).scale(256)),
CUBIC_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CUBIC), NoiseType.CUBIC),
@Desc("Cubic Noise")
CUBIC_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CUBIC).scale(256)),
CUBIC_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CUBIC), NoiseType.CUBIC),
@Desc("Hexagonal cell noise distorted using Iris styled wispy noise.")
HEXAGON_IRIS(rng -> CNG.signature(rng, NoiseType.HEXAGON).scale(1)),
HEXAGON_IRIS(rng -> CNG.signature(rng, NoiseType.HEXAGON), NoiseType.HEXAGON),
@Desc("Hexagonal cell noise distorted using Iris styled wispy noise.")
HEXAGON_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.HEXAGON).scale(1)),
HEXAGON_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.HEXAGON), NoiseType.HEXAGON),
@Desc("Hexagonal cell noise distorted using Iris styled wispy noise.")
HEXAGON_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.HEXAGON).scale(1)),
HEXAGON_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.HEXAGON), NoiseType.HEXAGON),
@Desc("Hexagonal cell noise distorted using Iris styled wispy noise.")
HEXAGON_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.HEXAGON).scale(1)),
HEXAGON_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.HEXAGON), NoiseType.HEXAGON),
@Desc("Hex James substitution pattern distorted using Iris styled wispy noise.")
HEX_JAMES_IRIS(rng -> CNG.signature(rng, NoiseType.HEX_JAMES).scale(1)),
HEX_JAMES_IRIS(rng -> CNG.signature(rng, NoiseType.HEX_JAMES), NoiseType.HEX_JAMES),
@Desc("Hex James substitution pattern distorted using Iris styled wispy noise.")
HEX_JAMES_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.HEX_JAMES).scale(1)),
HEX_JAMES_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.HEX_JAMES), NoiseType.HEX_JAMES),
@Desc("Hex James substitution pattern distorted using Iris styled wispy noise.")
HEX_JAMES_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.HEX_JAMES).scale(1)),
HEX_JAMES_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.HEX_JAMES), NoiseType.HEX_JAMES),
@Desc("Hex James substitution pattern distorted using Iris styled wispy noise.")
HEX_JAMES_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.HEX_JAMES).scale(1)),
HEX_JAMES_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.HEX_JAMES), NoiseType.HEX_JAMES),
@Desc("Interlocked solid hex-cell simplex heatmap distorted using Iris styled wispy noise.")
HEX_SIMPLEX_IRIS(rng -> CNG.signature(rng, NoiseType.HEX_SIMPLEX).scale(1)),
HEX_SIMPLEX_IRIS(rng -> CNG.signature(rng, NoiseType.HEX_SIMPLEX), NoiseType.HEX_SIMPLEX),
@Desc("Interlocked solid hex-cell simplex heatmap distorted using Iris styled wispy noise.")
HEX_SIMPLEX_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.HEX_SIMPLEX).scale(1)),
HEX_SIMPLEX_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.HEX_SIMPLEX), NoiseType.HEX_SIMPLEX),
@Desc("Interlocked solid hex-cell simplex heatmap distorted using Iris styled wispy noise.")
HEX_SIMPLEX_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.HEX_SIMPLEX).scale(1)),
HEX_SIMPLEX_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.HEX_SIMPLEX), NoiseType.HEX_SIMPLEX),
@Desc("Interlocked solid hex-cell simplex heatmap distorted using Iris styled wispy noise.")
HEX_SIMPLEX_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.HEX_SIMPLEX).scale(1)),
HEX_SIMPLEX_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.HEX_SIMPLEX), NoiseType.HEX_SIMPLEX),
@Desc("Hexagonal random-size gradient noise and distorted using Iris styled wispy noise.")
HEX_RANDOM_SIZE_IRIS(rng -> CNG.signature(rng, NoiseType.HEX_RANDOM_SIZE).scale(1)),
HEX_RANDOM_SIZE_IRIS(rng -> CNG.signature(rng, NoiseType.HEX_RANDOM_SIZE), NoiseType.HEX_RANDOM_SIZE),
@Desc("Hexagonal random-size gradient noise and distorted using Iris styled wispy noise.")
HEX_RANDOM_SIZE_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.HEX_RANDOM_SIZE).scale(1)),
HEX_RANDOM_SIZE_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.HEX_RANDOM_SIZE), NoiseType.HEX_RANDOM_SIZE),
@Desc("Hexagonal random-size gradient noise and distorted using Iris styled wispy noise.")
HEX_RANDOM_SIZE_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.HEX_RANDOM_SIZE).scale(1)),
HEX_RANDOM_SIZE_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.HEX_RANDOM_SIZE), NoiseType.HEX_RANDOM_SIZE),
@Desc("Hexagonal random-size gradient noise and distorted using Iris styled wispy noise.")
HEX_RANDOM_SIZE_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.HEX_RANDOM_SIZE).scale(1)),
HEX_RANDOM_SIZE_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.HEX_RANDOM_SIZE), NoiseType.HEX_RANDOM_SIZE),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders. Cells are distorted using Iris styled wispy noise.")
CELLULAR_IRIS(rng -> CNG.signature(rng, NoiseType.CELLULAR)),
CELLULAR_IRIS(rng -> CNG.signature(rng, NoiseType.CELLULAR), NoiseType.CELLULAR),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders. Cells are distorted using Iris styled wispy noise.")
CELLULAR_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CELLULAR)),
CELLULAR_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CELLULAR), NoiseType.CELLULAR),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders. Cells are distorted using Iris styled wispy noise.")
CELLULAR_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CELLULAR)),
CELLULAR_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CELLULAR), NoiseType.CELLULAR),
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders. Cells are distorted using Iris styled wispy noise.")
CELLULAR_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CELLULAR)),
CELLULAR_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CELLULAR), NoiseType.CELLULAR),
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell")
CELLULAR_HEIGHT(rng -> new CNG(rng, NoiseType.CELLULAR_HEIGHT, 1D, 1)),
CELLULAR_HEIGHT(rng -> new CNG(rng, NoiseType.CELLULAR_HEIGHT, 1D, 1), NoiseType.CELLULAR_HEIGHT),
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell, using the iris style.")
CELLULAR_HEIGHT_IRIS(rng -> CNG.signature(rng, NoiseType.CELLULAR_HEIGHT)),
CELLULAR_HEIGHT_IRIS(rng -> CNG.signature(rng, NoiseType.CELLULAR_HEIGHT), NoiseType.CELLULAR_HEIGHT),
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell, using the iris style.")
CELLULAR_HEIGHT_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CELLULAR_HEIGHT)),
CELLULAR_HEIGHT_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CELLULAR_HEIGHT), NoiseType.CELLULAR_HEIGHT),
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell, using the iris style.")
CELLULAR_HEIGHT_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CELLULAR_HEIGHT)),
CELLULAR_HEIGHT_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CELLULAR_HEIGHT), NoiseType.CELLULAR_HEIGHT),
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell, using the iris style.")
CELLULAR_HEIGHT_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CELLULAR_HEIGHT)),
CELLULAR_HEIGHT_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CELLULAR_HEIGHT), NoiseType.CELLULAR_HEIGHT),
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
VASCULAR_IRIS(rng -> CNG.signature(rng, NoiseType.VASCULAR)),
VASCULAR_IRIS(rng -> CNG.signature(rng, NoiseType.VASCULAR), NoiseType.VASCULAR),
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
VASCULAR_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.VASCULAR)),
VASCULAR_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.VASCULAR), NoiseType.VASCULAR),
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
VASCULAR_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.VASCULAR)),
VASCULAR_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.VASCULAR), NoiseType.VASCULAR),
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
VASCULAR_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.VASCULAR)),
VASCULAR_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.VASCULAR), NoiseType.VASCULAR),
;
private final CNGFactory f;
private final NoiseType type;
NoiseStyle(CNGFactory f) {
this(f, NoiseType.SIMPLEX);
}
NoiseStyle(CNGFactory f, NoiseType type) {
this.f = f;
this.type = type;
}
public ProceduralStream<Double> stream(RNG seed) {
@@ -555,7 +561,7 @@ public enum NoiseStyle {
}
public CNG create(RNG seed) {
CNG cng = f.create(seed).bake();
CNG cng = f.create(seed).bake().scale(type.getCoordinateScale()).bake();
cng.setLeakStyle(this);
return cng;
}
@@ -19,13 +19,13 @@
package art.arcane.iris.util.project.interpolation;
import com.google.common.util.concurrent.AtomicDouble;
import art.arcane.volmlib.util.interpolation.Starcast;
import art.arcane.iris.engine.object.NoiseStyle;
import art.arcane.volmlib.util.function.NoiseProvider;
import art.arcane.volmlib.util.math.RNG;
import art.arcane.iris.util.project.noise.CNG;
public class IrisInterpolation {
private static final double[][] STARCAST_OFFSETS = createStarcastOffsets();
public static CNG cng = NoiseStyle.SIMPLEX.create(new RNG());
private static final ThreadLocal<NoiseSampleCache2D> NOISE_SAMPLE_CACHE_2D = ThreadLocal.withInitial(() -> new NoiseSampleCache2D(64));
private static final ThreadLocal<NoiseBoundsSampleCache2D> NOISE_BOUNDS_SAMPLE_CACHE_2D = ThreadLocal.withInitial(() -> new NoiseBoundsSampleCache2D(64));
@@ -35,8 +35,8 @@ public class IrisInterpolation {
}
public static double parametric(double t, double alpha) {
double sqt = Math.pow(t, alpha);
return sqt / (alpha * (sqt - Math.pow(t, alpha - 1)) + 1.0d);
double forward = Math.pow(t, alpha);
return forward / (forward + Math.pow(1D - t, alpha));
}
public static float lerpf(float a, float b, float f) {
@@ -287,13 +287,17 @@ public class IrisInterpolation {
return (int) Math.floor(coord / radius);
}
public static double getBilinearNoise(int x, int z, double rad, NoiseProvider n) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
public static int getRadiusFactor(double coord, double radius) {
return (int) Math.floor(coord / radius);
}
public static double getBilinearNoise(double x, double z, double rad, NoiseProvider n) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
@@ -307,13 +311,13 @@ public class IrisInterpolation {
//@done
}
public static double getBilinearBezierNoise(int x, int z, double rad, NoiseProvider n) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
public static double getBilinearBezierNoise(double x, double z, double rad, NoiseProvider n) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -326,13 +330,13 @@ public class IrisInterpolation {
//@done
}
public static double getBilinearParametricNoise(int x, int z, double rad, NoiseProvider n, double a) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
public static double getBilinearParametricNoise(double x, double z, double rad, NoiseProvider n, double a) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -345,13 +349,13 @@ public class IrisInterpolation {
//@done
}
public static double getBilinearCenterSineNoise(int x, int z, double rad, NoiseProvider n) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
public static double getBilinearCenterSineNoise(double x, double z, double rad, NoiseProvider n) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -364,17 +368,17 @@ public class IrisInterpolation {
//@done
}
public static double getBicubicNoise(int x, int z, double rad, NoiseProvider n) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x0 = (int) Math.round((fx - 1) * rad);
int z0 = (int) Math.round((fz - 1) * rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
int x3 = (int) Math.round((fx + 2) * rad);
int z3 = (int) Math.round((fz + 2) * rad);
public static double getBicubicNoise(double x, double z, double rad, NoiseProvider n) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x0 = (fx - 1) * rad;
double z0 = (fz - 1) * rad;
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double x3 = (fx + 2) * rad;
double z3 = (fz + 2) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -399,17 +403,17 @@ public class IrisInterpolation {
//@done
}
public static double getBicubicBezierNoise(int x, int z, double rad, NoiseProvider n) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x0 = (int) Math.round((fx - 1) * rad);
int z0 = (int) Math.round((fz - 1) * rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
int x3 = (int) Math.round((fx + 2) * rad);
int z3 = (int) Math.round((fz + 2) * rad);
public static double getBicubicBezierNoise(double x, double z, double rad, NoiseProvider n) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x0 = (fx - 1) * rad;
double z0 = (fz - 1) * rad;
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double x3 = (fx + 2) * rad;
double z3 = (fz + 2) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -434,17 +438,17 @@ public class IrisInterpolation {
//@done
}
public static double getBicubicParametricNoise(int x, int z, double rad, NoiseProvider n, double a) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x0 = (int) Math.round((fx - 1) * rad);
int z0 = (int) Math.round((fz - 1) * rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
int x3 = (int) Math.round((fx + 2) * rad);
int z3 = (int) Math.round((fz + 2) * rad);
public static double getBicubicParametricNoise(double x, double z, double rad, NoiseProvider n, double a) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x0 = (fx - 1) * rad;
double z0 = (fz - 1) * rad;
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double x3 = (fx + 2) * rad;
double z3 = (fz + 2) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -469,29 +473,29 @@ public class IrisInterpolation {
//@done
}
public static double getHermiteNoise(int x, int z, double rad, NoiseProvider n) {
public static double getHermiteNoise(double x, double z, double rad, NoiseProvider n) {
return getHermiteNoise(x, z, rad, n, 0.5, 0);
}
public static double getHermiteBezierNoise(int x, int z, double rad, NoiseProvider n) {
public static double getHermiteBezierNoise(double x, double z, double rad, NoiseProvider n) {
return getHermiteBezierNoise(x, z, rad, n, 0.5, 0);
}
public static double getHermiteParametricNoise(int x, int z, double rad, NoiseProvider n, double a) {
public static double getHermiteParametricNoise(double x, double z, double rad, NoiseProvider n, double a) {
return getHermiteParametricNoise(x, z, rad, n, 0.5, 0, a);
}
public static double getHermiteNoise(int x, int z, double rad, NoiseProvider n, double t, double b) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x0 = (int) Math.round((fx - 1) * rad);
int z0 = (int) Math.round((fz - 1) * rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
int x3 = (int) Math.round((fx + 2) * rad);
int z3 = (int) Math.round((fz + 2) * rad);
public static double getHermiteNoise(double x, double z, double rad, NoiseProvider n, double t, double b) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x0 = (fx - 1) * rad;
double z0 = (fz - 1) * rad;
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double x3 = (fx + 2) * rad;
double z3 = (fz + 2) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -516,17 +520,17 @@ public class IrisInterpolation {
//@done
}
public static double getHermiteBezierNoise(int x, int z, double rad, NoiseProvider n, double t, double b) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x0 = (int) Math.round((fx - 1) * rad);
int z0 = (int) Math.round((fz - 1) * rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
int x3 = (int) Math.round((fx + 2) * rad);
int z3 = (int) Math.round((fz + 2) * rad);
public static double getHermiteBezierNoise(double x, double z, double rad, NoiseProvider n, double t, double b) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x0 = (fx - 1) * rad;
double z0 = (fz - 1) * rad;
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double x3 = (fx + 2) * rad;
double z3 = (fz + 2) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -551,17 +555,17 @@ public class IrisInterpolation {
//@done
}
public static double getHermiteParametricNoise(int x, int z, double rad, NoiseProvider n, double t, double b, double a) {
int fx = getRadiusFactor(x, rad);
int fz = getRadiusFactor(z, rad);
int x0 = (int) Math.round((fx - 1) * rad);
int z0 = (int) Math.round((fz - 1) * rad);
int x1 = (int) Math.round(fx * rad);
int z1 = (int) Math.round(fz * rad);
int x2 = (int) Math.round((fx + 1) * rad);
int z2 = (int) Math.round((fz + 1) * rad);
int x3 = (int) Math.round((fx + 2) * rad);
int z3 = (int) Math.round((fz + 2) * rad);
public static double getHermiteParametricNoise(double x, double z, double rad, NoiseProvider n, double t, double b, double a) {
double fx = Math.floor(x / rad);
double fz = Math.floor(z / rad);
double x0 = (fx - 1) * rad;
double z0 = (fz - 1) * rad;
double x1 = fx * rad;
double z1 = fz * rad;
double x2 = (fx + 1) * rad;
double z2 = (fz + 1) * rad;
double x3 = (fx + 2) * rad;
double z3 = (fz + 2) * rad;
double px = rangeScale(0, 1, x1, x2, x);
double pz = rangeScale(0, 1, z1, z2, z);
//@builder
@@ -601,7 +605,7 @@ public class IrisInterpolation {
return rad.get();
}
public static double getNoise(InterpolationMethod method, int x, int z, double h, NoiseProvider noise) {
public static double getNoise(InterpolationMethod method, double x, double z, double h, NoiseProvider noise) {
if (usesSampleCache(method)) {
NoiseSampleCache2D cache = NOISE_SAMPLE_CACHE_2D.get();
if (!cache.isInUse()) {
@@ -620,37 +624,37 @@ public class IrisInterpolation {
return dispatch(method, x, z, h, noise);
}
private static double dispatch(InterpolationMethod method, int x, int z, double h, NoiseProvider n) {
private static double dispatch(InterpolationMethod method, double x, double z, double h, NoiseProvider n) {
return switch (method) {
case BILINEAR -> getBilinearNoise(x, z, h, n);
case STARCAST_3 -> Starcast.starcast(x, z, h, 3D, n);
case STARCAST_6 -> Starcast.starcast(x, z, h, 6D, n);
case STARCAST_9 -> Starcast.starcast(x, z, h, 9D, n);
case STARCAST_12 -> Starcast.starcast(x, z, h, 12D, n);
case STARCAST_3 -> starcast(x, z, h, 3, n);
case STARCAST_6 -> starcast(x, z, h, 6, n);
case STARCAST_9 -> starcast(x, z, h, 9, n);
case STARCAST_12 -> starcast(x, z, h, 12, n);
case BILINEAR_STARCAST_3 ->
Starcast.starcast(x, z, h, 3D, (xx, zz) -> getBilinearNoise((int) xx, (int) zz, h, n));
starcast(x, z, h, 3, (xx, zz) -> getBilinearNoise(xx, zz, h, n));
case BILINEAR_STARCAST_6 ->
Starcast.starcast(x, z, h, 6D, (xx, zz) -> getBilinearNoise((int) xx, (int) zz, h, n));
starcast(x, z, h, 6, (xx, zz) -> getBilinearNoise(xx, zz, h, n));
case BILINEAR_STARCAST_9 ->
Starcast.starcast(x, z, h, 9D, (xx, zz) -> getBilinearNoise((int) xx, (int) zz, h, n));
starcast(x, z, h, 9, (xx, zz) -> getBilinearNoise(xx, zz, h, n));
case BILINEAR_STARCAST_12 ->
Starcast.starcast(x, z, h, 12D, (xx, zz) -> getBilinearNoise((int) xx, (int) zz, h, n));
starcast(x, z, h, 12, (xx, zz) -> getBilinearNoise(xx, zz, h, n));
case HERMITE_STARCAST_3 ->
Starcast.starcast(x, z, h, 3D, (xx, zz) -> getHermiteNoise((int) xx, (int) zz, h, n, 0D, 0D));
starcast(x, z, h, 3, (xx, zz) -> getHermiteNoise(xx, zz, h, n, 0D, 0D));
case HERMITE_STARCAST_6 ->
Starcast.starcast(x, z, h, 6D, (xx, zz) -> getHermiteNoise((int) xx, (int) zz, h, n, 0D, 0D));
starcast(x, z, h, 6, (xx, zz) -> getHermiteNoise(xx, zz, h, n, 0D, 0D));
case HERMITE_STARCAST_9 ->
Starcast.starcast(x, z, h, 9D, (xx, zz) -> getHermiteNoise((int) xx, (int) zz, h, n, 0D, 0D));
starcast(x, z, h, 9, (xx, zz) -> getHermiteNoise(xx, zz, h, n, 0D, 0D));
case HERMITE_STARCAST_12 ->
Starcast.starcast(x, z, h, 12D, (xx, zz) -> getHermiteNoise((int) xx, (int) zz, h, n, 0D, 0D));
starcast(x, z, h, 12, (xx, zz) -> getHermiteNoise(xx, zz, h, n, 0D, 0D));
case BILINEAR_BEZIER -> getBilinearBezierNoise(x, z, h, n);
case BILINEAR_PARAMETRIC_2 -> getBilinearParametricNoise(x, z, h, n, 2);
case BILINEAR_PARAMETRIC_4 -> getBilinearParametricNoise(x, z, h, n, 4);
case BILINEAR_PARAMETRIC_1_5 -> getBilinearParametricNoise(x, z, h, n, 1.5);
case BICUBIC -> getBilinearNoise(x, z, h, n);
case BICUBIC -> getBicubicNoise(x, z, h, n);
case HERMITE -> getHermiteNoise(x, z, h, n);
case HERMITE_TENSE -> getHermiteNoise(x, z, h, n, 0.8D, 0D);
case CATMULL_ROM_SPLINE -> getHermiteNoise(x, z, h, n, 1D, 0D);
case CATMULL_ROM_SPLINE -> getHermiteNoise(x, z, h, n, 0D, 0D);
case HERMITE_LOOSE -> getHermiteNoise(x, z, h, n, 0D, 0D);
case HERMITE_LOOSE_HALF_NEGATIVE_BIAS -> getHermiteNoise(x, z, h, n, 0D, -0.5D);
case HERMITE_LOOSE_HALF_POSITIVE_BIAS -> getHermiteNoise(x, z, h, n, 0D, 0.5D);
@@ -660,7 +664,7 @@ public class IrisInterpolation {
};
}
public static NoiseBounds getNoiseBounds(InterpolationMethod method, int x, int z, double h, NoiseBoundsProvider noise) {
public static NoiseBounds getNoiseBounds(InterpolationMethod method, double x, double z, double h, NoiseBoundsProvider noise) {
NoiseBoundsSampleCache2D cache = NOISE_BOUNDS_SAMPLE_CACHE_2D.get();
if (cache.isInUse()) {
// Nested bounds interpolation: a fresh table on the rare nested path, never the
@@ -687,6 +691,32 @@ public class IrisInterpolation {
}
}
private static double[][] createStarcastOffsets() {
double[][] offsets = new double[4][];
for (int index = 0; index < offsets.length; index++) {
int checks = (index + 1) * 3;
double[] samples = new double[checks * 2];
for (int sample = 0; sample < checks; sample++) {
double angle = sample * (Math.PI * 2D / checks);
double sin = Math.sin(angle);
double cos = Math.cos(angle);
samples[sample * 2] = cos - sin;
samples[sample * 2 + 1] = sin + cos;
}
offsets[index] = samples;
}
return offsets;
}
private static double starcast(double x, double z, double radius, int checks, NoiseProvider noise) {
double[] offsets = STARCAST_OFFSETS[checks / 3 - 1];
double sum = 0D;
for (int sample = 0; sample < offsets.length; sample += 2) {
sum += noise.noise(x + radius * offsets[sample], z + radius * offsets[sample + 1]);
}
return sum / checks;
}
private static boolean usesSampleCache(InterpolationMethod method) {
return switch (method) {
case BILINEAR_STARCAST_3,
@@ -39,6 +39,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.IdentityHashMap;
import java.util.List;
@Data
@@ -79,6 +80,7 @@ public class CNG {
private transient double signedFractureScale;
private transient boolean fastPathStateDirty = true;
private transient int coordCacheSalt;
private transient Object coordCacheIdentity = new Object();
public CNG(RNG random) {
this(random, 1);
@@ -93,7 +95,7 @@ public class CNG {
}
public CNG(RNG random, NoiseType type, double opacity, int octaves) {
this(random, type.create(random.nextParallelRNG((long) ((1113334944L * opacity) + 12922 + octaves)).lmax()), opacity, octaves);
this(random, type.create(random.nextParallelRNG((long) ((1113334944L * opacity) + 12923)).lmax()), opacity, octaves);
}
public CNG(RNG random, NoiseGenerator generator, double opacity, int octaves) {
@@ -115,8 +117,8 @@ public class CNG {
this.injectorMode = InjectorMode.ADD;
coordCacheSalt = createCoordCacheSalt();
if (generator instanceof OctaveNoise) {
((OctaveNoise) generator).setOctaves(octaves);
if (generator instanceof OctaveNoise octaveNoise) {
octaveNoise.setOctaves(octaves);
}
refreshFastPathState();
@@ -256,7 +258,7 @@ public class CNG {
return this;
}
cache = null;
markFastPathStateDirty();
File f = new File(new File(cacheFolder, ".cache"), key + ".cnm");
FloatCache fbc;
@@ -306,6 +308,7 @@ public class CNG {
}
cache = fbc;
coordCacheIdentity = new Object();
return this;
}
@@ -355,6 +358,16 @@ public class CNG {
return this;
}
public CNG zoom(double factor) {
if (!Double.isFinite(factor) || factor <= 0D || !Double.isFinite(1D / factor)) {
throw new IllegalArgumentException("Zoom must be positive and finite");
}
if (factor != 1D) {
zoom(factor, new IdentityHashMap<>());
}
return this;
}
public CNG patch(double c) {
patch = c;
markFastPathStateDirty();
@@ -650,46 +663,16 @@ public class CNG {
return IrisInterpolation.lerp(min, max, noise);
}
private double getNoise(double... dim) {
ensureFastPathState();
double scale = effectiveScale;
if (fracture == null || noscale) {
return generator.noise(
(dim.length > 0 ? dim[0] : 0D) * scale,
(dim.length > 1 ? dim[1] : 0D) * scale,
(dim.length > 2 ? dim[2] : 0D) * scale) * opacity;
}
double x = dim.length > 0 ? dim[0] : 0D;
double y = dim.length > 1 ? dim[1] : 0D;
double z = dim.length > 2 ? dim[2] : 0D;
if (dim.length > 0) {
x += (fracture.noise(dim) - 0.5) * fscale;
}
if (dim.length > 1) {
y += (fracture.noise(dim[1], dim[0]) - 0.5) * fscale;
}
if (dim.length > 2) {
z += (fracture.noise(dim[2], dim[0], dim[1]) - 0.5) * fscale;
}
return generator.noise(x * scale, y * scale, z * scale) * opacity;
}
private double getNoise(double x) {
ensureFastPathState();
double scl = effectiveScale;
if (fracture == null || noscale) {
return generator.noise(x * scl, 0D, 0D) * opacity;
return generator.noise(x * scl) * opacity;
}
double fx = x + ((fracture.noiseFast1D(x) - 0.5D) * fscale);
return generator.noise(fx * scl, 0D, 0D) * opacity;
return generator.noise(fx * scl) * opacity;
}
private double getNoise(double x, double z) {
@@ -697,12 +680,12 @@ public class CNG {
double scl = effectiveScale;
if (fracture == null || noscale) {
return generator.noise(x * scl, z * scl, 0D) * opacity;
return generator.noise(x * scl, z * scl) * opacity;
}
double fx = x + ((fracture.noiseFast2D(x, z) - 0.5D) * fscale);
double fz = z + ((fracture.noiseFast2D(z, x) - 0.5D) * fscale);
return generator.noise(fx * scl, fz * scl, 0D) * opacity;
return generator.noise(fx * scl, fz * scl) * opacity;
}
private double getNoise(double x, double y, double z) {
@@ -735,8 +718,15 @@ public class CNG {
return (noise(dim) * 2) - 1;
}
private static boolean isWholeCoordinate(double value) {
return value == Math.rint(value);
private boolean isCachedCoordinate(double x, double z) {
return cache != null
&& x >= 0D && x < cache.getWidth()
&& z >= 0D && z < cache.getHeight()
&& x == (int) x && z == (int) z;
}
private double getCachedNoise(double x, double z) {
return cache.get((int) z * cache.getWidth() + (int) x);
}
private double applyPost(double n, double x) {
@@ -860,57 +850,12 @@ public class CNG {
}
public double noise(double... dim) {
if (dim.length == 1) {
return noise(dim[0]);
}
if (dim.length == 2) {
return noise(dim[0], dim[1]);
}
if (dim.length == 3) {
return noise(dim[0], dim[1], dim[2]);
}
double n = getNoise(dim);
n = power != 1D ? (n < 0 ? -Math.pow(Math.abs(n), power) : Math.pow(n, power)) : n;
double m = 1;
if (children == null) {
return (n - down + up) * patch;
}
for (CNG i : children) {
double source = n;
double value = i.noise(dim);
switch (injectorMode) {
case ADD -> {
n = source + value;
m += 1D;
}
case SRC_SUBTRACT -> {
n = source - value < 0D ? 0D : source - value;
m -= 1D;
}
case DST_SUBTRACT -> {
n = value - source < 0D ? 0D : source - value;
m -= 1D;
}
case MULTIPLY -> n = source * value;
case MAX -> n = Math.max(source, value);
case MIN -> n = Math.min(source, value);
case SRC_MOD -> n = source % value;
case SRC_POW -> n = Math.pow(source, value);
case DST_MOD -> n = value % source;
case DST_POW -> n = Math.pow(value, source);
case CUSTOM -> {
double[] combined = injector.combine(source, value);
n = combined[0];
m += combined[1];
}
}
}
return ((n / m) - down + up) * patch;
return switch (dim.length) {
case 1 -> noise(dim[0]);
case 2 -> noise(dim[0], dim[1]);
case 3 -> noise(dim[0], dim[1], dim[2]);
default -> throw new IllegalArgumentException("Noise requires one, two, or three coordinates");
};
}
public double noise(double x) {
@@ -922,16 +867,16 @@ public class CNG {
}
public double noise(double x, double z) {
if (cache != null && isWholeCoordinate(x) && isWholeCoordinate(z)) {
return cache.get((int) x, (int) z);
if (isCachedCoordinate(x, z)) {
return getCachedNoise(x, z);
}
return applyPost(getNoise(x, z), x, z);
}
public double noiseFast2D(double x, double z) {
if (cache != null && isWholeCoordinate(x) && isWholeCoordinate(z)) {
return cache.get((int) x, (int) z);
if (isCachedCoordinate(x, z)) {
return getCachedNoise(x, z);
}
if (isIdentityPostFastPath()) {
@@ -963,12 +908,13 @@ public class CNG {
long kx = Double.doubleToRawLongBits(x);
long kz = Double.doubleToRawLongBits(z);
CoordCache cc = COORD_CACHE_2D.get();
Object identity = coordCacheIdentity();
int slot = coordSlot(kx, kz, coordCacheSalt());
if (cc.owner[slot] == this && cc.kx[slot] == kx && cc.kz[slot] == kz) {
if (cc.owner[slot] == identity && cc.kx[slot] == kx && cc.kz[slot] == kz) {
return cc.value[slot];
}
double computed = computeNoiseFastSigned2D(x, z);
cc.owner[slot] = this;
cc.owner[slot] = identity;
cc.kx[slot] = kx;
cc.kz[slot] = kz;
cc.value[slot] = computed;
@@ -976,8 +922,8 @@ public class CNG {
}
private double computeNoiseFastSigned2D(double x, double z) {
if (cache != null && isWholeCoordinate(x) && isWholeCoordinate(z)) {
return (cache.get((int) x, (int) z) * 2D) - 1D;
if (isCachedCoordinate(x, z)) {
return (getCachedNoise(x, z) * 2D) - 1D;
}
if (hasIdentitySignedFastPath()) {
@@ -1014,12 +960,13 @@ public class CNG {
long ky = Double.doubleToRawLongBits(y);
long kz = Double.doubleToRawLongBits(z);
CoordCache3D cc = COORD_CACHE_3D.get();
Object identity = coordCacheIdentity();
int slot = coordSlot(kx ^ Long.rotateLeft(ky, 21), kz, coordCacheSalt());
if (cc.owner[slot] == this && cc.kx[slot] == kx && cc.ky[slot] == ky && cc.kz[slot] == kz) {
if (cc.owner[slot] == identity && cc.kx[slot] == kx && cc.ky[slot] == ky && cc.kz[slot] == kz) {
return cc.value[slot];
}
double computed = hasIdentitySignedFastPath() ? getSignedNoise(x, y, z) : (noiseFast3D(x, y, z) * 2D) - 1D;
cc.owner[slot] = this;
cc.owner[slot] = identity;
cc.kx[slot] = kx;
cc.ky[slot] = ky;
cc.kz[slot] = kz;
@@ -1034,7 +981,15 @@ public class CNG {
}
public CNG oct(int octaves) {
if (oct == octaves) {
return this;
}
oct = octaves;
if (generator instanceof OctaveNoise octaveNoise) {
octaveNoise.setOctaves(octaves);
}
markFastPathStateDirty();
return this;
}
@@ -1056,6 +1011,23 @@ public class CNG {
return identitySignedFastPath;
}
private void zoom(double factor, IdentityHashMap<CNG, Boolean> visited) {
if (visited.put(this, Boolean.TRUE) != null) {
return;
}
bakedScale /= factor;
fscale *= factor;
if (fracture != null) {
fracture.zoom(factor, visited);
}
if (children != null) {
for (CNG child : children) {
child.zoom(factor, visited);
}
}
markFastPathStateDirty();
}
private void ensureFastPathState() {
if (fastPathStateDirty) {
refreshFastPathState();
@@ -1064,6 +1036,16 @@ public class CNG {
private void markFastPathStateDirty() {
fastPathStateDirty = true;
cache = null;
coordCacheIdentity = new Object();
}
private Object coordCacheIdentity() {
if (coordCacheIdentity == null) {
coordCacheIdentity = new Object();
}
return coordCacheIdentity;
}
private int coordCacheSalt() {
@@ -1112,12 +1094,12 @@ public class CNG {
CNG localFracture = fracture;
if (localFracture == null || noscale) {
return signedWithOpacity(localGenerator.noiseSigned(x * scl, z * scl, 0D));
return signedWithOpacity(localGenerator.noiseSigned(x * scl, z * scl));
}
double fx = x + (localFracture.noiseFastSigned2D(x, z) * signedFractureScale);
double fz = z + (localFracture.noiseFastSigned2D(z, x) * signedFractureScale);
return signedWithOpacity(localGenerator.noiseSigned(fx * scl, fz * scl, 0D));
return signedWithOpacity(localGenerator.noiseSigned(fx * scl, fz * scl));
}
private double getSignedNoise(double x, double y, double z) {
@@ -32,7 +32,7 @@ public class CellHeightNoise implements NoiseGenerator {
}
private double filter(double noise) {
return M.clip(1D - ((noise / 2D) + 0.5D), 0D, 1D);
return M.clip((noise / 2D) + 0.5D, 0D, 1D);
}
@Override
@@ -21,27 +21,27 @@ package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.math.RNG;
public class CellularNoise implements NoiseGenerator {
private final FastNoise n;
private final FastNoiseDouble n;
public CellularNoise(long seed) {
this.n = new FastNoise(new RNG(seed).imax());
n.SetNoiseType(FastNoise.NoiseType.Cellular);
n.SetCellularReturnType(FastNoise.CellularReturnType.CellValue);
n.SetCellularDistanceFunction(FastNoise.CellularDistanceFunction.Natural);
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
n.setCellularReturnType(FastNoiseDouble.CellularReturnType.CellValue);
n.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
}
@Override
public double noise(double x) {
return (n.GetCellular((float) x, 0) / 2D) + 0.5D;
return (n.GetCellular(x, 0) / 2D) + 0.5D;
}
@Override
public double noise(double x, double z) {
return (n.GetCellular((float) x, (float) z) / 2D) + 0.5D;
return (n.GetCellular(x, z) / 2D) + 0.5D;
}
@Override
public double noise(double x, double y, double z) {
return (n.GetCellular((float) x, (float) y, (float) z) / 2D) + 0.5D;
return (n.GetCellular(x, y, z) / 2D) + 0.5D;
}
}
@@ -39,10 +39,6 @@ public class CloverNoise implements NoiseGenerator {
@Override
public double noise(double x, double y, double z) {
if (z == 0) {
return n2.noise(x, y);
}
return n3.noise(x, y, z);
}
@@ -129,8 +125,6 @@ public class CloverNoise implements NoiseGenerator {
Vector2 p_floor = p.floor();
Vector2 c_11 = offset(p_floor);
Vector2 c_10 = offset(p_floor.add(0, -1));
Vector2 c_12 = offset(p_floor.add(0, 1));
Vector2 c_01 = offset(p_floor.add(-1, 0));
Vector2 c_21 = offset(p_floor.add(1, 0));
@@ -143,6 +137,7 @@ public class CloverNoise implements NoiseGenerator {
Vector2 a, c, d;
if (side_nx < 0 && p.x < c_11.x || side_px > 0 && p.x > c_11.x) {
Vector2 c_12 = offset(p_floor.add(0, 1));
double side_py = m_p_c11.sub(d_p_c11.mult(c_12)).ymx();
if (side_py > 0) {
@@ -155,6 +150,7 @@ public class CloverNoise implements NoiseGenerator {
d = new Vector2(1, 1);
}
} else {
Vector2 c_10 = offset(p_floor.add(0, -1));
double side_ny = m_p_c11.sub(d_p_c11.mult(c_10)).ymx();
if (side_ny > 0) {
@@ -235,6 +231,7 @@ public class CloverNoise implements NoiseGenerator {
* @return The value of noise, from 0 to 1.
*/
public double fractalNoise(Vector2 p, int iterations) {
iterations = Math.max(1, Math.min(16, iterations));
double total = 0;
double weight = 1;
double div = 0;
@@ -382,6 +379,18 @@ public class CloverNoise implements NoiseGenerator {
private static final long HASH_M = 0x1000000000000L;
private static final double POINT_SPREAD = 0.2;
private static final double CURL_DX = 0.0001;
private static final double[] HEIGHT_SINES = new double[1000];
private static final double[] HEIGHT_COSINES = new double[1000];
private static final ThreadLocal<Vector3[]> SAMPLE_VERTICES = ThreadLocal.withInitial(Noise3D::createSampleVertices);
static {
for (int index = 0; index < HEIGHT_SINES.length; index++) {
double height = (((index + 0.5D) / 100D) % 1D - 0.5D) * Math.PI / 2D;
HEIGHT_SINES[index] = Math.sin(height);
HEIGHT_COSINES[index] = Math.cos(height);
}
}
private final long seed;
public Noise3D(long seed) {
@@ -392,6 +401,14 @@ public class CloverNoise implements NoiseGenerator {
this(System.currentTimeMillis());
}
private static Vector3[] createSampleVertices() {
Vector3[] vertices = new Vector3[21];
for (int index = 0; index < vertices.length; index++) {
vertices[index] = new Vector3();
}
return vertices;
}
private long doHash(long input, long seed) {
input += seed;
@@ -433,27 +450,23 @@ public class CloverNoise implements NoiseGenerator {
return (double) hash / HASH_M;
}
private Vector3 offset(Vector3 position) {
return offset(position.x, position.y, position.z);
private Vector3 offset(Vector3 destination, Vector3 position, double xOffset, double yOffset, double zOffset) {
return offset(destination, position.x + xOffset, position.y + yOffset, position.z + zOffset);
}
private Vector3 offset(Vector3 position, double xOffset, double yOffset, double zOffset) {
return offset(position.x + xOffset, position.y + yOffset, position.z + zOffset);
}
private Vector3 offset(double positionX, double positionY, double positionZ) {
private Vector3 offset(Vector3 destination, double positionX, double positionY, double positionZ) {
double hash = hash(positionX, positionY, positionZ);
double theta = hash * Math.PI * 2000;
double height = (((Math.floor(hash * 1000) + 0.5) / 100) % 1 - 0.5) * Math.PI / 2;
int heightIndex = (int) (hash * 1000D);
double layer = Math.floor(hash * 10 + 1) / 10;
double cosHeight = Math.cos(height);
double cosHeight = HEIGHT_COSINES[heightIndex];
double offsetX = Math.sin(theta) * cosHeight * layer + 0.5;
double offsetY = Math.sin(height) * layer + 0.5;
double offsetY = HEIGHT_SINES[heightIndex] * layer + 0.5;
double offsetZ = Math.cos(theta) * cosHeight * layer + 0.5;
return new Vector3(
positionX + (offsetX * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD)),
positionY + (offsetY * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD)),
positionZ + (offsetZ * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD)));
destination.x = positionX + (offsetX * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD));
destination.y = positionY + (offsetY * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD));
destination.z = positionZ + (offsetZ * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD));
return destination;
}
private boolean boundary(int permutation, Vector3 p, Vector3 c_00, Vector3 c_10, Vector3 c_20, Vector3 c_01, Vector3 c_11, Vector3 c_21, Vector3 c_02, Vector3 c_12, Vector3 c_22) {
@@ -565,27 +578,34 @@ public class CloverNoise implements NoiseGenerator {
* @return The value of noise, from 0 to 1.
*/
public double noise(Vector3 p) {
Vector3 p_floor = p.floor();
return sample(p, SAMPLE_VERTICES.get());
}
Vector3 c_111 = offset(p_floor);
Vector3 c_100 = offset(p_floor, 0, -1, -1);
Vector3 c_010 = offset(p_floor, -1, 0, -1);
Vector3 c_110 = offset(p_floor, 0, 0, -1);
Vector3 c_210 = offset(p_floor, 1, 0, -1);
Vector3 c_120 = offset(p_floor, 0, 1, -1);
Vector3 c_001 = offset(p_floor, -1, -1, 0);
Vector3 c_101 = offset(p_floor, 0, -1, 0);
Vector3 c_201 = offset(p_floor, 1, -1, 0);
Vector3 c_011 = offset(p_floor, -1, 0, 0);
Vector3 c_211 = offset(p_floor, 1, 0, 0);
Vector3 c_021 = offset(p_floor, -1, 1, 0);
Vector3 c_121 = offset(p_floor, 0, 1, 0);
Vector3 c_221 = offset(p_floor, 1, 1, 0);
Vector3 c_102 = offset(p_floor, 0, -1, 1);
Vector3 c_012 = offset(p_floor, -1, 0, 1);
Vector3 c_112 = offset(p_floor, 0, 0, 1);
Vector3 c_212 = offset(p_floor, 1, 0, 1);
Vector3 c_122 = offset(p_floor, 0, 1, 1);
private double sample(Vector3 p, Vector3[] vertices) {
Vector3 p_floor = vertices[20];
p_floor.x = Math.floor(p.x);
p_floor.y = Math.floor(p.y);
p_floor.z = Math.floor(p.z);
Vector3 c_111 = offset(vertices[0], p_floor.x, p_floor.y, p_floor.z);
Vector3 c_100 = offset(vertices[1], p_floor, 0, -1, -1);
Vector3 c_010 = offset(vertices[2], p_floor, -1, 0, -1);
Vector3 c_110 = offset(vertices[3], p_floor, 0, 0, -1);
Vector3 c_210 = offset(vertices[4], p_floor, 1, 0, -1);
Vector3 c_120 = offset(vertices[5], p_floor, 0, 1, -1);
Vector3 c_001 = offset(vertices[6], p_floor, -1, -1, 0);
Vector3 c_101 = offset(vertices[7], p_floor, 0, -1, 0);
Vector3 c_201 = offset(vertices[8], p_floor, 1, -1, 0);
Vector3 c_011 = offset(vertices[9], p_floor, -1, 0, 0);
Vector3 c_211 = offset(vertices[10], p_floor, 1, 0, 0);
Vector3 c_021 = offset(vertices[11], p_floor, -1, 1, 0);
Vector3 c_121 = offset(vertices[12], p_floor, 0, 1, 0);
Vector3 c_221 = offset(vertices[13], p_floor, 1, 1, 0);
Vector3 c_102 = offset(vertices[14], p_floor, 0, -1, 1);
Vector3 c_012 = offset(vertices[15], p_floor, -1, 0, 1);
Vector3 c_112 = offset(vertices[16], p_floor, 0, 0, 1);
Vector3 c_212 = offset(vertices[17], p_floor, 1, 0, 1);
Vector3 c_122 = offset(vertices[18], p_floor, 0, 1, 1);
boolean x_bound = boundary(1, p, c_100, c_110, c_120, c_101, c_111, c_121, c_102, c_112, c_122);
boolean y_bound = boundary(2, p, c_010, c_110, c_210, c_011, c_111, c_211, c_012, c_112, c_212);
@@ -596,7 +616,7 @@ public class CloverNoise implements NoiseGenerator {
if (x_bound) {
if (y_bound) {
if (z_bound) {
a = offset(p_floor, -1, -1, -1);
a = offset(vertices[19], p_floor, -1, -1, -1);
b = c_001;
c = c_010;
d = c_011;
@@ -606,7 +626,7 @@ public class CloverNoise implements NoiseGenerator {
h = c_111;
} else {
a = c_001;
b = offset(p_floor, -1, -1, 1);
b = offset(vertices[19], p_floor, -1, -1, 1);
c = c_011;
d = c_012;
e = c_101;
@@ -618,7 +638,7 @@ public class CloverNoise implements NoiseGenerator {
if (z_bound) {
a = c_010;
b = c_011;
c = offset(p_floor, -1, 1, -1);
c = offset(vertices[19], p_floor, -1, 1, -1);
d = c_021;
e = c_110;
f = c_111;
@@ -628,7 +648,7 @@ public class CloverNoise implements NoiseGenerator {
a = c_011;
b = c_012;
c = c_021;
d = offset(p_floor, -1, 1, 1);
d = offset(vertices[19], p_floor, -1, 1, 1);
e = c_111;
f = c_112;
g = c_121;
@@ -642,7 +662,7 @@ public class CloverNoise implements NoiseGenerator {
b = c_101;
c = c_110;
d = c_111;
e = offset(p_floor, 1, -1, -1);
e = offset(vertices[19], p_floor, 1, -1, -1);
f = c_201;
g = c_210;
h = c_211;
@@ -652,7 +672,7 @@ public class CloverNoise implements NoiseGenerator {
c = c_111;
d = c_112;
e = c_201;
f = offset(p_floor, 1, -1, 1);
f = offset(vertices[19], p_floor, 1, -1, 1);
g = c_211;
h = c_212;
}
@@ -664,7 +684,7 @@ public class CloverNoise implements NoiseGenerator {
d = c_121;
e = c_210;
f = c_211;
g = offset(p_floor, 1, 1, -1);
g = offset(vertices[19], p_floor, 1, 1, -1);
h = c_221;
} else {
a = c_111;
@@ -674,7 +694,7 @@ public class CloverNoise implements NoiseGenerator {
e = c_211;
f = c_212;
g = c_221;
h = offset(p_floor, 1, 1, 1);
h = offset(vertices[19], p_floor, 1, 1, 1);
}
}
}
@@ -783,6 +803,7 @@ public class CloverNoise implements NoiseGenerator {
* @return The value of noise, from 0 to 1.
*/
public double fractalNoise(Vector3 p, int iterations) {
iterations = Math.max(1, Math.min(16, iterations));
double total = 0;
double weight = 1;
double div = 0;
@@ -980,6 +1001,9 @@ public class CloverNoise implements NoiseGenerator {
public Vector2 normalize() {
double len2 = x * x + y * y;
if (len2 == 0D) {
return new Vector2(0D, 0D);
}
double len = Math.sqrt(len2);
return new Vector2(x / len, y / len);
@@ -1092,6 +1116,9 @@ public class CloverNoise implements NoiseGenerator {
public Vector3 normalize() {
double len2 = x * x + y * y + z * z;
if (len2 == 0D) {
return new Vector3(0D, 0D, 0D);
}
double len = Math.sqrt(len2);
return new Vector3(x / len, y / len, z / len);
@@ -76,7 +76,7 @@ public class FastNoise {
}
private static int FastFloor(float f) {
return (f >= 0 ? (int) f : (int) f - 1);
return (int) Math.floor(f);
}
private static int FastRound(float f) {
@@ -259,7 +259,7 @@ public class FastNoise {
// Sets octave count for all fractal noise types
// Default: 3
public void SetFractalOctaves(int octaves) {
m_octaves = octaves;
m_octaves = Math.max(1, Math.min(16, octaves));
CalculateFractalBounding();
}
@@ -1515,7 +1515,7 @@ public class FastNoise {
x *= m_frequency;
y *= m_frequency;
return SingleCubic(0, x, y);
return SingleCubic(m_seed, x, y);
}
private float SingleCubic(int seed, float x, float y) {
@@ -2194,4 +2194,4 @@ public class FastNoise {
}
}
}
}
@@ -82,7 +82,7 @@ public class FastNoiseDouble {
}
private static long fastFloor(double f) {
return (f >= 0 ? (long) f : (long) f - 1);
return (long) Math.floor(f);
}
private static long fastRound(double f) {
@@ -289,7 +289,7 @@ public class FastNoiseDouble {
// Sets octave count for all fractal noise types
// Default: 3
public void setFractalOctaves(long octaves) {
m_octaves = octaves;
m_octaves = Math.max(1, Math.min(16, octaves));
calculateFractalBounding();
}
@@ -1453,7 +1453,7 @@ public class FastNoiseDouble {
x *= m_frequency;
y *= m_frequency;
return SingleCubic(0, x, y);
return SingleCubic(m_seed, x, y);
}
private double SingleCubic(long seed, double x, double y) {
@@ -1676,14 +1676,11 @@ public class FastNoiseDouble {
break;
}
return switch (m_cellularReturnType) {
case Distance2 -> distance2 - 1;
case Distance2Add -> distance2 + distance - 1;
case Distance2Sub -> distance2 - distance - 1;
case Distance2Mul -> distance2 * distance - 1;
case Distance2Div -> distance / distance2 - 1;
default -> 0;
};
double boundary = 1.55D - Math.max(Math.abs(x - xr), Math.max(Math.abs(y - yr), Math.abs(z - zr)));
if (cellularDistance(boundary, 0D, 0D) < distance2) {
return refineCellular2Edge(x, y, z, xr, yr, zr, distance, distance2);
}
return cellular2EdgeResult(distance, distance2);
}
public double GetCellular(double x, double y) {
@@ -1856,6 +1853,93 @@ public class FastNoiseDouble {
break;
}
double boundary = 1.55D - Math.max(Math.abs(x - xr), Math.abs(y - yr));
if (cellularDistance(boundary, 0D, 0D) < distance2) {
return refineCellular2Edge(x, y, xr, yr, distance, distance2);
}
return cellular2EdgeResult(distance, distance2);
}
private double refineCellular2Edge(double x, double y, long xr, long yr, double distance, double distance2) {
for (int dx = -2; dx <= 2; dx++) {
long xi = xr + dx;
double baseX = xi - x;
double boundX = Math.max(0D, Math.abs(baseX) - 0.45D);
if (cellularDistance(boundX, 0D, 0D) >= distance2) {
continue;
}
for (int dy = -2; dy <= 2; dy++) {
if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {
continue;
}
long yi = yr + dy;
double baseY = yi - y;
double boundY = Math.max(0D, Math.abs(baseY) - 0.45D);
if (cellularDistance(boundX, boundY, 0D) >= distance2) {
continue;
}
int index = (int) hash2D(m_seed, xi, yi) & 255;
double candidate = cellularDistance(baseX + CELL_2D_X[index], baseY + CELL_2D_Y[index], 0D);
if (candidate < distance) {
distance2 = distance;
distance = candidate;
} else if (candidate < distance2) {
distance2 = candidate;
}
}
}
return cellular2EdgeResult(distance, distance2);
}
private double refineCellular2Edge(double x, double y, double z, long xr, long yr, long zr, double distance, double distance2) {
int radius = m_cellularDistanceFunction == CellularDistanceFunction.Manhattan ? 3 : 2;
for (int dx = -radius; dx <= radius; dx++) {
long xi = xr + dx;
double baseX = xi - x;
double boundX = Math.max(0D, Math.abs(baseX) - 0.45D);
if (cellularDistance(boundX, 0D, 0D) >= distance2) {
continue;
}
for (int dy = -radius; dy <= radius; dy++) {
long yi = yr + dy;
double baseY = yi - y;
double boundY = Math.max(0D, Math.abs(baseY) - 0.45D);
if (cellularDistance(boundX, boundY, 0D) >= distance2) {
continue;
}
for (int dz = -radius; dz <= radius; dz++) {
if (Math.abs(dx) < 2 && Math.abs(dy) < 2 && Math.abs(dz) < 2) {
continue;
}
long zi = zr + dz;
double baseZ = zi - z;
double boundZ = Math.max(0D, Math.abs(baseZ) - 0.45D);
if (cellularDistance(boundX, boundY, boundZ) >= distance2) {
continue;
}
int index = (int) hash3D(m_seed, xi, yi, zi) & 255;
double candidate = cellularDistance(baseX + CELL_3D_X[index], baseY + CELL_3D_Y[index], baseZ + CELL_3D_Z[index]);
if (candidate < distance) {
distance2 = distance;
distance = candidate;
} else if (candidate < distance2) {
distance2 = candidate;
}
}
}
}
return cellular2EdgeResult(distance, distance2);
}
private double cellularDistance(double x, double y, double z) {
return switch (m_cellularDistanceFunction) {
case Euclidean -> x * x + y * y + z * z;
case Manhattan -> Math.abs(x) + Math.abs(y) + Math.abs(z);
case Natural -> (Math.abs(x) + Math.abs(y) + Math.abs(z)) + (x * x + y * y + z * z);
};
}
private double cellular2EdgeResult(double distance, double distance2) {
return switch (m_cellularReturnType) {
case Distance2 -> distance2 - 1;
case Distance2Add -> distance2 + distance - 1;
@@ -25,6 +25,7 @@ public class FractalBillowPerlinNoise implements NoiseGenerator, OctaveNoise {
public FractalBillowPerlinNoise(long seed) {
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setLongerp(FastNoiseDouble.Longerp.Qulongic);
n.setFractalOctaves(1);
n.setFractalType(FractalType.Billow);
}
@@ -20,11 +20,12 @@ package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.math.RNG;
import art.arcane.iris.util.project.noise.FastNoiseDouble.FractalType;
public class FractalCubicNoise implements NoiseGenerator {
public class FractalCubicNoise implements NoiseGenerator, OctaveNoise {
private final FastNoiseDouble n;
public FractalCubicNoise(long seed) {
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setFractalOctaves(1);
n.setFractalType(FractalType.Billow);
}
@@ -46,4 +47,9 @@ public class FractalCubicNoise implements NoiseGenerator {
public double noise(double x, double y, double z) {
return f(n.GetCubicFractal(x, y, z));
}
@Override
public void setOctaves(int octaves) {
n.setFractalOctaves(octaves);
}
}
@@ -30,7 +30,7 @@ public class FractalRigidMultiSimplexNoise implements NoiseGenerator, OctaveNois
}
public double f(double v) {
return (v / 2D) + 0.5D;
return 1D + (v - 1D) * n.getFractalBounding();
}
@Override
@@ -2,294 +2,89 @@ package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.math.RNG;
public class HexJamesNoise implements NoiseGenerator, OctaveNoise {
private static final double SQRT_3_OVER_3 = Math.sqrt(3.0) / 3.0;
private static final double TWO_OVER_THREE = 2.0 / 3.0;
private static final double SQRT_3 = Math.sqrt(3.0);
private static final double THREE_OVER_TWO = 1.5D;
private static final double ONE_THIRD = 1D / 3D;
private static final double TWO_THIRDS = 2D / 3D;
public class HexJamesNoise extends HexagonalNoise implements OctaveNoise {
private static final int MAX_DEPTH = 7;
private static final double HEAT_SCALE = 0.31D;
private static final double HEAT_SCALE = 18D;
private static final double LARGE_CONTINUE = 0.26D;
private static final double SMALL_CONTINUE = 0.79D;
private static final double CENTER_CONTINUE = 0.58D;
private static final long CONST_X = 0x9E3779B97F4A7C15L;
private static final long CONST_Z = 0xC2B2AE3D27D4EB4FL;
private static final long[][] CHILD_DIRECTIONS = new long[][]{
{1L, 0L},
{1L, -1L},
{0L, -1L},
{-1L, 0L},
{-1L, 1L},
{0L, 1L}
};
private static final ThreadLocal<HexScratch> SCRATCH = ThreadLocal.withInitial(HexScratch::new);
private final long seed;
private final SimplexNoise heatSimplex;
private int octaves;
private final SimplexNoise heat;
public HexJamesNoise(long seed) {
RNG rng = new RNG(seed);
this.seed = rng.lmax();
this.heatSimplex = new SimplexNoise(rng.nextParallelRNG(877L).lmax());
this.octaves = 1;
this.heat = new SimplexNoise(rng.nextParallelRNG(877L).lmax());
}
private double clip(double value) {
if (value < 0D) {
return 0D;
}
if (value > 1D) {
return 1D;
}
return value;
@Override
public void setOctaves(int octaves) {
heat.setOctaves(octaves);
}
private long mix(long input) {
input = (input ^ (input >>> 33)) * 0xff51afd7ed558ccdL;
input = (input ^ (input >>> 33)) * 0xc4ceb9fe1a85ec53L;
return input ^ (input >>> 33);
}
@Override
protected double sample(double x, double y, double z) {
double qWorld = (SQRT_3_OVER_3 * x) - (z / 3D);
double rWorld = TWO_OVER_THREE * z;
long rootQ = roundQ(qWorld, rWorld);
long rootR = roundR(qWorld, rWorld);
double centerQ = rootQ;
double centerR = rootR;
double radius = 1D;
double localQ = qWorld - centerQ;
double localR = rWorld - centerR;
long nodeHash = mix(seed ^ (rootQ * CONST_X) ^ (rootR * CONST_Z));
int level = 0;
private double hashToUnit(long value) {
long normalized = mix(value) & Long.MAX_VALUE;
return normalized / (double) Long.MAX_VALUE;
}
while (level < MAX_DEPTH) {
int childIndex = pickChildIndex(localQ, localR);
if (childIndex < 0) {
break;
}
private double random01(long nodeHash, int salt) {
long mixed = nodeHash ^ (CONST_X * (salt + 1L)) ^ (CONST_Z * (salt + 7L));
return hashToUnit(mixed);
}
double childQ = CHILD_Q[childIndex];
double childR = CHILD_R[childIndex];
centerQ += childQ * radius;
centerR += childR * radius;
radius *= ONE_THIRD;
localQ = (localQ - childQ) * 3D;
localR = (localR - childR) * 3D;
nodeHash = mix(nodeHash ^ (CONST_X * (childIndex + 11L)) ^ (CONST_Z * (level + 1L)));
level++;
private long nextNodeHash(long nodeHash, int childIndex, int level) {
long mixed = nodeHash ^ (CONST_X * (childIndex + 11L)) ^ (CONST_Z * (level + 1L));
return mix(mixed);
}
private long[] roundAxial(double q, double r) {
double cubeX = q;
double cubeZ = r;
double cubeY = -cubeX - cubeZ;
long roundedX = Math.round(cubeX);
long roundedY = Math.round(cubeY);
long roundedZ = Math.round(cubeZ);
double xDiff = Math.abs(roundedX - cubeX);
double yDiff = Math.abs(roundedY - cubeY);
double zDiff = Math.abs(roundedZ - cubeZ);
if (xDiff > yDiff && xDiff > zDiff) {
roundedX = -roundedY - roundedZ;
} else if (yDiff > zDiff) {
roundedY = -roundedX - roundedZ;
} else {
roundedZ = -roundedX - roundedY;
}
return new long[]{roundedX, roundedZ};
}
private double hexDistance(double q, double r, double centerQ, double centerR) {
double deltaQ = q - centerQ;
double deltaR = r - centerR;
double deltaY = -deltaQ - deltaR;
return Math.max(Math.abs(deltaQ), Math.max(Math.abs(deltaR), Math.abs(deltaY)));
}
private double axialX(double q, double r) {
return SQRT_3 * (q + (r * 0.5D));
}
private double axialZ(double r) {
return THREE_OVER_TWO * r;
}
private double simplexField(double x, double z, double scale) {
if (octaves <= 1) {
return heatSimplex.noise(x * scale, z * scale);
}
double frequency = 1D;
double amplitude = 1D;
double total = 0D;
double max = 0D;
for (int i = 0; i < octaves; i++) {
total += heatSimplex.noise((x * scale) * frequency, (z * scale) * frequency) * amplitude;
max += amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
if (max == 0D) {
return 0.5D;
}
return clip(total / max);
}
private double cellHeat(double centerQ, double centerR, long nodeHash, int level) {
double x = axialX(centerQ, centerR);
double z = axialZ(centerR);
double scale = HEAT_SCALE * (1D + (level * 0.24D));
double simplexValue = simplexField(x, z, scale);
double randomValue = random01(nodeHash, 31 + level);
return clip((simplexValue * 0.82D) + (randomValue * 0.18D));
}
private int rotationForNode(long nodeHash) {
int rotation = (int) Math.floor(random01(nodeHash, 3) * 6D);
if (rotation < 0) {
rotation = 0;
}
if (rotation > 5) {
rotation = 5;
}
return rotation;
}
private int parityForNode(long nodeHash) {
return random01(nodeHash, 5) >= 0.5D ? 1 : 0;
}
private int ringIndexForDirection(int direction, int rotation) {
int ring = direction - rotation;
while (ring < 0) {
ring += 6;
}
while (ring >= 6) {
ring -= 6;
}
return ring;
}
private int pickChildIndex(double localQ, double localR, double[] centersQ, double[] centersR) {
int bestIndex = -1;
double bestDistance = Double.POSITIVE_INFINITY;
centersQ[0] = 0D;
centersR[0] = 0D;
double centerDistance = hexDistance(localQ, localR, 0D, 0D) / ONE_THIRD;
if (centerDistance <= 1D && centerDistance < bestDistance) {
bestDistance = centerDistance;
bestIndex = 0;
}
for (int i = 0; i < 6; i++) {
int index = i + 1;
double centerQ = CHILD_DIRECTIONS[i][0] * TWO_THIRDS;
double centerR = CHILD_DIRECTIONS[i][1] * TWO_THIRDS;
centersQ[index] = centerQ;
centersR[index] = centerR;
double distance = hexDistance(localQ, localR, centerQ, centerR) / ONE_THIRD;
if (distance <= 1D && distance < bestDistance) {
bestDistance = distance;
bestIndex = index;
if (!shouldContinue(childIndex, nodeHash, level - 1)) {
break;
}
}
return bestIndex;
double centerX = SQRT_3 * (centerQ + (centerR * 0.5D));
double centerZ = 1.5D * centerR;
double simplexValue = heat.noise(centerX * HEAT_SCALE, y * HEAT_SCALE, centerZ * HEAT_SCALE);
return (simplexValue * 0.82D) + (random01(nodeHash, 31 + level) * 0.18D);
}
private boolean shouldContinue(int level, int childIndex, long nodeHash) {
private boolean shouldContinue(int childIndex, long nodeHash, int level) {
if (level >= MAX_DEPTH - 1) {
return false;
}
double gate;
if (childIndex == 0) {
gate = CENTER_CONTINUE;
} else {
int rotation = rotationForNode(nodeHash);
int parity = parityForNode(nodeHash);
int ringIndex = ringIndexForDirection(childIndex - 1, rotation);
boolean large = (ringIndex % 2) == parity;
gate = large ? LARGE_CONTINUE : SMALL_CONTINUE;
}
double randomValue = random01(nodeHash, 97 + level);
return randomValue <= gate;
}
private double sample(double x, double z) {
HexScratch scratch = SCRATCH.get();
double[] centersQ = scratch.centersQ;
double[] centersR = scratch.centersR;
double qWorld = (SQRT_3_OVER_3 * x) - (z / 3.0);
double rWorld = TWO_OVER_THREE * z;
long[] rounded = roundAxial(qWorld, rWorld);
double centerQ = rounded[0];
double centerR = rounded[1];
double radius = 0.5D;
double localQ = (qWorld - centerQ) / radius;
double localR = (rWorld - centerR) / radius;
long nodeHash = mix(seed ^ (rounded[0] * CONST_X) ^ (rounded[1] * CONST_Z));
double heat = cellHeat(centerQ, centerR, nodeHash, 0);
for (int level = 0; level < MAX_DEPTH; level++) {
int childIndex = pickChildIndex(localQ, localR, centersQ, centersR);
if (childIndex < 0) {
return heat;
}
double childCenterQ = centersQ[childIndex];
double childCenterR = centersR[childIndex];
centerQ += childCenterQ * radius;
centerR += childCenterR * radius;
radius *= ONE_THIRD;
localQ = (localQ - childCenterQ) / ONE_THIRD;
localR = (localR - childCenterR) / ONE_THIRD;
nodeHash = nextNodeHash(nodeHash, childIndex, level);
heat = cellHeat(centerQ, centerR, nodeHash, level + 1);
if (!shouldContinue(level, childIndex, nodeHash)) {
return heat;
double gate = CENTER_CONTINUE;
if (childIndex != 0) {
int rotation = (int) (random01(nodeHash, 3) * 6D);
int parity = random01(nodeHash, 5) >= 0.5D ? 1 : 0;
int direction = childIndex - 1 - rotation;
if (direction < 0) {
direction += 6;
}
gate = (direction % 2) == parity ? LARGE_CONTINUE : SMALL_CONTINUE;
}
return heat;
return random01(nodeHash, 97 + level) <= gate;
}
@Override
public double noise(double x) {
return sample(x, 0D);
private double random01(long nodeHash, int salt) {
long mixed = nodeHash ^ (CONST_X * (salt + 1L)) ^ (CONST_Z * (salt + 7L));
return (mix(mixed) >>> 11) * 0x1.0p-53;
}
@Override
public double noise(double x, double z) {
return sample(x, z);
}
@Override
public double noise(double x, double y, double z) {
if (z == 0D) {
return sample(x, y);
}
double a = sample(x, z);
double b = sample(y, x);
double c = sample(z, y);
return (a + b + c) / 3D;
}
@Override
public void setOctaves(int o) {
this.octaves = Math.max(1, o);
}
private static final class HexScratch {
private final double[] centersQ = new double[7];
private final double[] centersR = new double[7];
}
}
@@ -2,259 +2,77 @@ package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.math.RNG;
public class HexRandomSizeNoise implements NoiseGenerator, OctaveNoise {
private static final double SQRT_3_OVER_3 = Math.sqrt(3.0) / 3.0;
private static final double TWO_OVER_THREE = 2.0 / 3.0;
private static final double SQRT_3 = Math.sqrt(3.0);
private static final double THREE_OVER_TWO = 1.5D;
private static final double ONE_THIRD = 1D / 3D;
private static final double TWO_THIRDS = 2D / 3D;
public class HexRandomSizeNoise extends HexagonalNoise implements OctaveNoise {
private static final int MAX_DEPTH = 8;
private static final double HEAT_SCALE = 0.24D;
private static final double STRUCTURE_SCALE = 0.36D;
private static final double HEAT_SCALE = 18D;
private static final double STRUCTURE_SCALE = 36D;
private static final double SUBDIVIDE_BASE_THRESHOLD = 0.22D;
private static final double SUBDIVIDE_LEVEL_STEP = 0.11D;
private static final long CONST_X = 0x9E3779B97F4A7C15L;
private static final long CONST_Z = 0xC2B2AE3D27D4EB4FL;
private static final long[][] CHILD_DIRECTIONS = new long[][]{
{1L, 0L},
{1L, -1L},
{0L, -1L},
{-1L, 0L},
{-1L, 1L},
{0L, 1L}
};
private static final ThreadLocal<HexScratch> SCRATCH = ThreadLocal.withInitial(HexScratch::new);
private final long seed;
private final SimplexNoise heatSimplex;
private final SimplexNoise structureSimplex;
private int octaves;
private final SimplexNoise heat;
private final SimplexNoise structure;
public HexRandomSizeNoise(long seed) {
RNG rng = new RNG(seed);
this.seed = rng.lmax();
this.heatSimplex = new SimplexNoise(rng.nextParallelRNG(221L).lmax());
this.structureSimplex = new SimplexNoise(rng.nextParallelRNG(442L).lmax());
this.octaves = 1;
this.heat = new SimplexNoise(rng.nextParallelRNG(221L).lmax());
this.structure = new SimplexNoise(rng.nextParallelRNG(442L).lmax());
}
private double clip(double value) {
if (value < 0D) {
return 0D;
@Override
public void setOctaves(int octaves) {
heat.setOctaves(octaves);
structure.setOctaves(octaves);
}
@Override
protected double sample(double x, double y, double z) {
double qWorld = (SQRT_3_OVER_3 * x) - (z / 3D);
double rWorld = TWO_OVER_THREE * z;
long rootQ = roundQ(qWorld, rWorld);
long rootR = roundR(qWorld, rWorld);
double centerQ = rootQ;
double centerR = rootR;
double radius = 1D;
double localQ = qWorld - centerQ;
double localR = rWorld - centerR;
long nodeHash = mix(seed ^ (rootQ * CONST_X) ^ (rootR * CONST_Z));
int level = 0;
while (level < MAX_DEPTH - 1 && shouldSubdivide(centerQ, centerR, nodeHash, level)) {
int childIndex = pickChildIndex(localQ, localR);
if (childIndex < 0) {
break;
}
double childQ = CHILD_Q[childIndex];
double childR = CHILD_R[childIndex];
centerQ += childQ * radius;
centerR += childR * radius;
radius *= ONE_THIRD;
localQ = (localQ - childQ) * 3D;
localR = (localR - childR) * 3D;
nodeHash = mix(nodeHash ^ (CONST_Z * (childIndex + 1L)) ^ (CONST_X * (level + 1L)));
level++;
}
if (value > 1D) {
return 1D;
}
return value;
double centerX = SQRT_3 * (centerQ + (centerR * 0.5D));
double centerZ = 1.5D * centerR;
double simplexValue = heat.noise(centerX * HEAT_SCALE, y * HEAT_SCALE, centerZ * HEAT_SCALE);
return (simplexValue * 0.74D) + (random01(nodeHash, 11 + level) * 0.26D);
}
private long mix(long input) {
input = (input ^ (input >>> 33)) * 0xff51afd7ed558ccdL;
input = (input ^ (input >>> 33)) * 0xc4ceb9fe1a85ec53L;
return input ^ (input >>> 33);
}
private double hashToUnit(long value) {
long normalized = mix(value) & Long.MAX_VALUE;
return normalized / (double) Long.MAX_VALUE;
private boolean shouldSubdivide(double centerQ, double centerR, long nodeHash, int level) {
double centerX = SQRT_3 * (centerQ + (centerR * 0.5D));
double centerZ = 1.5D * centerR;
double simplexValue = structure.noise(centerX * STRUCTURE_SCALE, centerZ * STRUCTURE_SCALE);
double score = (simplexValue * 0.68D) + (random01(nodeHash, 71 + level) * 0.32D);
return score > SUBDIVIDE_BASE_THRESHOLD + (level * SUBDIVIDE_LEVEL_STEP);
}
private double random01(long nodeHash, int salt) {
long mixed = nodeHash ^ (CONST_X * (salt + 1L)) ^ (CONST_Z * (salt + 31L));
return hashToUnit(mixed);
return (mix(mixed) >>> 11) * 0x1.0p-53;
}
private long nextNodeHash(long nodeHash, int childIndex, int level) {
long mixed = nodeHash ^ (CONST_Z * (childIndex + 1L)) ^ (CONST_X * (level + 1L));
return mix(mixed);
}
private long[] roundAxial(double q, double r) {
double cubeX = q;
double cubeZ = r;
double cubeY = -cubeX - cubeZ;
long roundedX = Math.round(cubeX);
long roundedY = Math.round(cubeY);
long roundedZ = Math.round(cubeZ);
double xDiff = Math.abs(roundedX - cubeX);
double yDiff = Math.abs(roundedY - cubeY);
double zDiff = Math.abs(roundedZ - cubeZ);
if (xDiff > yDiff && xDiff > zDiff) {
roundedX = -roundedY - roundedZ;
} else if (yDiff > zDiff) {
roundedY = -roundedX - roundedZ;
} else {
roundedZ = -roundedX - roundedY;
}
return new long[]{roundedX, roundedZ};
}
private double hexDistance(double q, double r, double centerQ, double centerR) {
double deltaQ = q - centerQ;
double deltaR = r - centerR;
double deltaY = -deltaQ - deltaR;
return Math.max(Math.abs(deltaQ), Math.max(Math.abs(deltaR), Math.abs(deltaY)));
}
private double axialX(double q, double r) {
return SQRT_3 * (q + (r * 0.5D));
}
private double axialZ(double r) {
return THREE_OVER_TWO * r;
}
private double simplexField(SimplexNoise simplex, double x, double z, double scale) {
if (octaves <= 1) {
return simplex.noise(x * scale, z * scale);
}
double frequency = 1D;
double amplitude = 1D;
double total = 0D;
double max = 0D;
for (int i = 0; i < octaves; i++) {
total += simplex.noise((x * scale) * frequency, (z * scale) * frequency) * amplitude;
max += amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
if (max == 0D) {
return 0.5D;
}
return clip(total / max);
}
private double cellHeat(double centerQ, double centerR, long nodeHash, int level) {
double x = axialX(centerQ, centerR);
double z = axialZ(centerR);
double scale = HEAT_SCALE * (1D + (level * 0.2D));
double simplexValue = simplexField(heatSimplex, x, z, scale);
double randomValue = random01(nodeHash, 11 + level);
return clip((simplexValue * 0.74D) + (randomValue * 0.26D));
}
private boolean shouldSubdivide(double centerQ, double centerR, long nodeHash, int level) {
if (level >= MAX_DEPTH - 1) {
return false;
}
double x = axialX(centerQ, centerR);
double z = axialZ(centerR);
double scale = STRUCTURE_SCALE * (1D + (level * 0.31D));
double simplexValue = simplexField(structureSimplex, x, z, scale);
double randomValue = random01(nodeHash, 71 + level);
double score = clip((simplexValue * 0.68D) + (randomValue * 0.32D));
double threshold = SUBDIVIDE_BASE_THRESHOLD + (level * SUBDIVIDE_LEVEL_STEP);
return score > threshold;
}
private int pickChildIndex(double localQ, double localR, double[] centersQ, double[] centersR) {
int bestIndex = -1;
double bestDistance = Double.POSITIVE_INFINITY;
centersQ[0] = 0D;
centersR[0] = 0D;
double centerDistance = hexDistance(localQ, localR, 0D, 0D) / ONE_THIRD;
if (centerDistance <= 1D && centerDistance < bestDistance) {
bestDistance = centerDistance;
bestIndex = 0;
}
for (int i = 0; i < 6; i++) {
int index = i + 1;
double centerQ = CHILD_DIRECTIONS[i][0] * TWO_THIRDS;
double centerR = CHILD_DIRECTIONS[i][1] * TWO_THIRDS;
centersQ[index] = centerQ;
centersR[index] = centerR;
double distance = hexDistance(localQ, localR, centerQ, centerR) / ONE_THIRD;
if (distance <= 1D && distance < bestDistance) {
bestDistance = distance;
bestIndex = index;
}
}
return bestIndex;
}
private double sample(double x, double z) {
HexScratch scratch = SCRATCH.get();
double[] centersQ = scratch.centersQ;
double[] centersR = scratch.centersR;
double qWorld = (SQRT_3_OVER_3 * x) - (z / 3.0);
double rWorld = TWO_OVER_THREE * z;
long[] rounded = roundAxial(qWorld, rWorld);
double centerQ = rounded[0];
double centerR = rounded[1];
double radius = 0.5D;
double localQ = (qWorld - centerQ) / radius;
double localR = (rWorld - centerR) / radius;
long nodeHash = mix(seed ^ (rounded[0] * CONST_X) ^ (rounded[1] * CONST_Z));
double heat = cellHeat(centerQ, centerR, nodeHash, 0);
for (int level = 0; level < MAX_DEPTH; level++) {
if (!shouldSubdivide(centerQ, centerR, nodeHash, level)) {
return heat;
}
int childIndex = pickChildIndex(localQ, localR, centersQ, centersR);
if (childIndex < 0) {
return heat;
}
double childCenterQ = centersQ[childIndex];
double childCenterR = centersR[childIndex];
centerQ += childCenterQ * radius;
centerR += childCenterR * radius;
radius *= ONE_THIRD;
localQ = (localQ - childCenterQ) / ONE_THIRD;
localR = (localR - childCenterR) / ONE_THIRD;
nodeHash = nextNodeHash(nodeHash, childIndex, level);
heat = cellHeat(centerQ, centerR, nodeHash, level + 1);
}
return heat;
}
@Override
public double noise(double x) {
return sample(x, 0D);
}
@Override
public double noise(double x, double z) {
return sample(x, z);
}
@Override
public double noise(double x, double y, double z) {
if (z == 0D) {
return sample(x, y);
}
double a = sample(x, z);
double b = sample(y, x);
double c = sample(z, y);
return (a + b + c) / 3D;
}
@Override
public void setOctaves(int o) {
this.octaves = Math.max(1, o);
}
private static final class HexScratch {
private final double[] centersQ = new double[7];
private final double[] centersR = new double[7];
}
}
@@ -2,124 +2,27 @@ package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.math.RNG;
public class HexSimplexNoise implements NoiseGenerator, OctaveNoise {
private static final double SQRT_3_OVER_3 = Math.sqrt(3.0) / 3.0;
private static final double TWO_OVER_THREE = 2.0 / 3.0;
private static final double SQRT_3 = Math.sqrt(3.0);
private static final double THREE_OVER_TWO = 1.5D;
private static final double CELL_HEAT_SCALE = 2.7D;
private final SimplexNoise cellHeatSimplex;
private int octaves;
public class HexSimplexNoise extends HexagonalNoise implements OctaveNoise {
private static final double HEAT_SCALE = 18D;
private final SimplexNoise heat;
public HexSimplexNoise(long seed) {
RNG rng = new RNG(seed);
this.cellHeatSimplex = new SimplexNoise(rng.nextParallelRNG(811L).lmax());
this.octaves = 1;
this.heat = new SimplexNoise(new RNG(seed).nextParallelRNG(811L).lmax());
}
private double clip(double value) {
if (value < 0D) {
return 0D;
}
if (value > 1D) {
return 1D;
}
return value;
@Override
public void setOctaves(int octaves) {
heat.setOctaves(octaves);
}
private long[] roundAxial(double q, double r) {
double cubeX = q;
double cubeZ = r;
double cubeY = -cubeX - cubeZ;
long roundedX = Math.round(cubeX);
long roundedY = Math.round(cubeY);
long roundedZ = Math.round(cubeZ);
double xDiff = Math.abs(roundedX - cubeX);
double yDiff = Math.abs(roundedY - cubeY);
double zDiff = Math.abs(roundedZ - cubeZ);
if (xDiff > yDiff && xDiff > zDiff) {
roundedX = -roundedY - roundedZ;
} else if (yDiff > zDiff) {
roundedY = -roundedX - roundedZ;
} else {
roundedZ = -roundedX - roundedY;
}
return new long[]{roundedX, roundedZ};
}
private double axialX(long q, long r) {
return SQRT_3 * (q + (r * 0.5D));
}
private double axialZ(long r) {
return THREE_OVER_TWO * r;
}
private double cellHeat(long q, long r, double frequency) {
double x = axialX(q, r);
double z = axialZ(r);
return cellHeatSimplex.noise((x * CELL_HEAT_SCALE) * frequency, (z * CELL_HEAT_SCALE) * frequency);
}
private double sampleCell(long q, long r) {
if (octaves <= 1) {
return cellHeat(q, r, 1D);
}
double frequency = 1D;
double amplitude = 1D;
double total = 0D;
double max = 0D;
for (int i = 0; i < octaves; i++) {
total += cellHeat(q, r, frequency) * amplitude;
max += amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
if (max == 0D) {
return 0.5D;
}
return clip(total / max);
}
private double sample(double x, double z) {
double q = (SQRT_3_OVER_3 * x) - (z / 3.0);
@Override
protected double sample(double x, double y, double z) {
double q = (SQRT_3_OVER_3 * x) - (z / 3D);
double r = TWO_OVER_THREE * z;
long[] rounded = roundAxial(q, r);
return sampleCell(rounded[0], rounded[1]);
}
@Override
public double noise(double x) {
return sample(x, 0D);
}
@Override
public double noise(double x, double z) {
return sample(x, z);
}
@Override
public double noise(double x, double y, double z) {
if (z == 0D) {
return sample(x, y);
}
double a = sample(x, z);
double b = sample(y, x);
double c = sample(z, y);
return (a + b + c) / 3D;
}
@Override
public void setOctaves(int o) {
this.octaves = Math.max(1, o);
long centerQ = roundQ(q, r);
long centerR = roundR(q, r);
double centerX = SQRT_3 * (centerQ + (centerR * 0.5D));
double centerZ = 1.5D * centerR;
return heat.noise(centerX * HEAT_SCALE, y * HEAT_SCALE, centerZ * HEAT_SCALE);
}
}
@@ -2,82 +2,27 @@ package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.math.RNG;
public class HexagonNoise implements NoiseGenerator {
private static final double SQRT_3_OVER_3 = Math.sqrt(3.0) / 3.0;
private static final double TWO_OVER_THREE = 2.0 / 3.0;
private static final long CONST_X = 0x9E3779B97F4A7C15L;
private static final long CONST_Z = 0xC2B2AE3D27D4EB4FL;
private final long seed;
public class HexagonNoise extends HexagonalNoise implements OctaveNoise {
private static final double HEAT_SCALE = 18D;
private final SimplexNoise heat;
public HexagonNoise(long seed) {
this.seed = new RNG(seed).lmax();
this.heat = new SimplexNoise(new RNG(seed).lmax());
}
private long mix(long input) {
input = (input ^ (input >>> 33)) * 0xff51afd7ed558ccdL;
input = (input ^ (input >>> 33)) * 0xc4ceb9fe1a85ec53L;
return input ^ (input >>> 33);
@Override
public void setOctaves(int octaves) {
heat.setOctaves(octaves);
}
private long hash(long q, long r) {
long hash = seed;
hash ^= mix(q + CONST_X);
hash ^= mix(r + CONST_Z);
return mix(hash);
}
private long[] roundAxial(double q, double r) {
double cubeX = q;
double cubeZ = r;
double cubeY = -cubeX - cubeZ;
long rx = Math.round(cubeX);
long ry = Math.round(cubeY);
long rz = Math.round(cubeZ);
double xDiff = Math.abs(rx - cubeX);
double yDiff = Math.abs(ry - cubeY);
double zDiff = Math.abs(rz - cubeZ);
if (xDiff > yDiff && xDiff > zDiff) {
rx = -ry - rz;
} else if (yDiff > zDiff) {
ry = -rx - rz;
} else {
rz = -rx - ry;
}
return new long[]{rx, rz};
}
private double sampleCell(double x, double z) {
double q = (SQRT_3_OVER_3 * x) - (z / 3.0);
@Override
protected double sample(double x, double y, double z) {
double q = (SQRT_3_OVER_3 * x) - (z / 3D);
double r = TWO_OVER_THREE * z;
long[] axial = roundAxial(q, r);
long hashed = hash(axial[0], axial[1]);
long normalized = hashed & Long.MAX_VALUE;
return normalized / (double) Long.MAX_VALUE;
}
@Override
public double noise(double x) {
return sampleCell(x, 0D);
}
@Override
public double noise(double x, double z) {
return sampleCell(x, z);
}
@Override
public double noise(double x, double y, double z) {
if (z == 0D) {
return sampleCell(x, y);
}
double a = sampleCell(x, z);
double b = sampleCell(y, x);
double c = sampleCell(z, y);
return (a + b + c) / 3D;
long centerQ = roundQ(q, r);
long centerR = roundR(q, r);
double centerX = SQRT_3 * (centerQ + (centerR * 0.5D));
double centerZ = 1.5D * centerR;
return heat.noise(centerX * HEAT_SCALE, y * HEAT_SCALE, centerZ * HEAT_SCALE);
}
}
@@ -0,0 +1,71 @@
package art.arcane.iris.util.project.noise;
abstract class HexagonalNoise implements NoiseGenerator {
protected static final double SQRT_3 = Math.sqrt(3D);
protected static final double SQRT_3_OVER_3 = SQRT_3 / 3D;
protected static final double TWO_OVER_THREE = 2D / 3D;
protected static final double ONE_THIRD = 1D / 3D;
protected static final double[] CHILD_Q = {0D, 4D / 9D, 2D / 9D, -2D / 9D, -4D / 9D, -2D / 9D, 2D / 9D};
protected static final double[] CHILD_R = {0D, -2D / 9D, 2D / 9D, 4D / 9D, 2D / 9D, -2D / 9D, -4D / 9D};
protected static final long CONST_X = 0x9E3779B97F4A7C15L;
protected static final long CONST_Z = 0xC2B2AE3D27D4EB4FL;
@Override
public double noise(double x) {
return sample(x, 0D, 0D);
}
@Override
public double noise(double x, double z) {
return sample(x, 0D, z);
}
@Override
public double noise(double x, double y, double z) {
return sample(x, y, z);
}
protected abstract double sample(double x, double y, double z);
protected static long roundQ(double q, double r) {
double cubeY = -q - r;
long roundedQ = Math.round(q);
long roundedR = Math.round(r);
long roundedY = Math.round(cubeY);
double qDiff = Math.abs(roundedQ - q);
double rDiff = Math.abs(roundedR - r);
double yDiff = Math.abs(roundedY - cubeY);
return qDiff > yDiff && qDiff > rDiff ? -roundedY - roundedR : roundedQ;
}
protected static long roundR(double q, double r) {
double cubeY = -q - r;
long roundedQ = Math.round(q);
long roundedR = Math.round(r);
long roundedY = Math.round(cubeY);
double qDiff = Math.abs(roundedQ - q);
double rDiff = Math.abs(roundedR - r);
double yDiff = Math.abs(roundedY - cubeY);
return !(qDiff > yDiff && qDiff > rDiff) && yDiff <= rDiff ? -roundedQ - roundedY : roundedR;
}
protected static long mix(long input) {
input = (input ^ (input >>> 33)) * 0xff51afd7ed558ccdL;
input = (input ^ (input >>> 33)) * 0xc4ceb9fe1a85ec53L;
return input ^ (input >>> 33);
}
protected static int pickChildIndex(double localQ, double localR) {
for (int index = 0; index < CHILD_Q.length; index++) {
double deltaQ = localQ - CHILD_Q[index];
double deltaR = localR - CHILD_R[index];
double distance = Math.max(Math.abs((2D * deltaQ) + deltaR),
Math.max(Math.abs(deltaQ + (2D * deltaR)), Math.abs(deltaQ - deltaR)));
if (distance <= ONE_THIRD) {
return index;
}
}
return -1;
}
}
@@ -21,14 +21,16 @@ package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.function.NoiseProvider;
import art.arcane.iris.util.project.interpolation.InterpolationMethod;
import art.arcane.iris.util.project.interpolation.IrisInterpolation;
public class InterpolatedNoise implements NoiseGenerator {
public class InterpolatedNoise implements NoiseGenerator, OctaveNoise {
private final InterpolationMethod method;
private final NoiseGenerator generator;
private final NoiseProvider p;
public InterpolatedNoise(long seed, NoiseType type, InterpolationMethod method) {
this.method = method;
NoiseGenerator g = type.create(seed);
p = g::noise;
generator = type.create(seed);
double coordinateScale = type.getCoordinateScale();
p = (x, z) -> generator.noise(x * coordinateScale, z * coordinateScale);
}
@Override
@@ -38,15 +40,18 @@ public class InterpolatedNoise implements NoiseGenerator {
@Override
public double noise(double x, double z) {
return IrisInterpolation.getNoise(method, (int) x, (int) z, 32, p);
return Math.max(0D, Math.min(1D, IrisInterpolation.getNoise(method, x, z, 32, p)));
}
@Override
public double noise(double x, double y, double z) {
if (z == 0) {
return noise(x, y);
}
return noise(x, z);
}
return IrisInterpolation.getNoise(method, (int) x, (int) z, 32, p);
@Override
public void setOctaves(int octaves) {
if (generator instanceof OctaveNoise octaveNoise) {
octaveNoise.setOctaves(octaves);
}
}
}
@@ -20,79 +20,89 @@ package art.arcane.iris.util.project.noise;
import art.arcane.iris.util.project.interpolation.InterpolationMethod;
public enum NoiseType {
WHITE(WhiteNoise::new),
WHITE_BILINEAR((s) -> new InterpolatedNoise(s, WHITE, InterpolationMethod.BILINEAR)),
WHITE_BICUBIC((s) -> new InterpolatedNoise(s, WHITE, InterpolationMethod.BICUBIC)),
WHITE_HERMITE((s) -> new InterpolatedNoise(s, WHITE, InterpolationMethod.HERMITE)),
WHITE(WhiteNoise::new, 1D),
WHITE_BILINEAR((s) -> new InterpolatedNoise(s, WHITE, InterpolationMethod.BILINEAR), 1D),
WHITE_BICUBIC((s) -> new InterpolatedNoise(s, WHITE, InterpolationMethod.BICUBIC), 1D),
WHITE_HERMITE((s) -> new InterpolatedNoise(s, WHITE, InterpolationMethod.HERMITE), 1D),
SIMPLEX(SimplexNoise::new),
PERLIN(seed -> new PerlinNoise(seed).hermite()),
PERLIN(PerlinNoise::new),
FRACTAL_BILLOW_SIMPLEX(FractalBillowSimplexNoise::new),
FRACTAL_BILLOW_PERLIN(FractalBillowPerlinNoise::new),
FRACTAL_FBM_SIMPLEX(FractalFBMSimplexNoise::new),
FRACTAL_RIGID_MULTI_SIMPLEX(FractalRigidMultiSimplexNoise::new),
FLAT(FlatNoise::new),
FLAT(FlatNoise::new, 1D),
CELLULAR(CellularNoise::new),
CELLULAR_BILINEAR((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR)),
CELLULAR_BILINEAR_STARCAST_3((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR_STARCAST_3)),
CELLULAR_BILINEAR_STARCAST_6((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR_STARCAST_6)),
CELLULAR_BILINEAR_STARCAST_9((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR_STARCAST_9)),
CELLULAR_BILINEAR_STARCAST_12((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR_STARCAST_12)),
CELLULAR_BICUBIC((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BICUBIC)),
CELLULAR_HERMITE((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE)),
CELLULAR_STARCAST_3((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.STARCAST_3)),
CELLULAR_STARCAST_6((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.STARCAST_6)),
CELLULAR_STARCAST_9((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.STARCAST_9)),
CELLULAR_STARCAST_12((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.STARCAST_12)),
CELLULAR_HERMITE_STARCAST_3((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE_STARCAST_3)),
CELLULAR_HERMITE_STARCAST_6((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE_STARCAST_6)),
CELLULAR_HERMITE_STARCAST_9((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE_STARCAST_9)),
CELLULAR_HERMITE_STARCAST_12((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE_STARCAST_12)),
CELLULAR_BILINEAR((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR), 1D),
CELLULAR_BILINEAR_STARCAST_3((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR_STARCAST_3), 1D),
CELLULAR_BILINEAR_STARCAST_6((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR_STARCAST_6), 1D),
CELLULAR_BILINEAR_STARCAST_9((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR_STARCAST_9), 1D),
CELLULAR_BILINEAR_STARCAST_12((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BILINEAR_STARCAST_12), 1D),
CELLULAR_BICUBIC((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.BICUBIC), 1D),
CELLULAR_HERMITE((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE), 1D),
CELLULAR_STARCAST_3((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.STARCAST_3), 1D),
CELLULAR_STARCAST_6((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.STARCAST_6), 1D),
CELLULAR_STARCAST_9((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.STARCAST_9), 1D),
CELLULAR_STARCAST_12((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.STARCAST_12), 1D),
CELLULAR_HERMITE_STARCAST_3((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE_STARCAST_3), 1D),
CELLULAR_HERMITE_STARCAST_6((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE_STARCAST_6), 1D),
CELLULAR_HERMITE_STARCAST_9((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE_STARCAST_9), 1D),
CELLULAR_HERMITE_STARCAST_12((s) -> new InterpolatedNoise(s, CELLULAR, InterpolationMethod.HERMITE_STARCAST_12), 1D),
GLOB(GlobNoise::new),
CUBIC(CubicNoise::new),
FRACTAL_CUBIC(FractalCubicNoise::new),
CELLULAR_HEIGHT(CellHeightNoise::new),
CLOVER(CloverNoise::new),
CLOVER_BILINEAR((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR)),
CLOVER_BILINEAR_STARCAST_3((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR_STARCAST_3)),
CLOVER_BILINEAR_STARCAST_6((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR_STARCAST_6)),
CLOVER_BILINEAR_STARCAST_9((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR_STARCAST_9)),
CLOVER_BILINEAR_STARCAST_12((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR_STARCAST_12)),
CLOVER_BICUBIC((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BICUBIC)),
CLOVER_HERMITE((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE)),
CLOVER_STARCAST_3((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.STARCAST_3)),
CLOVER_STARCAST_6((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.STARCAST_6)),
CLOVER_STARCAST_9((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.STARCAST_9)),
CLOVER_STARCAST_12((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.STARCAST_12)),
CLOVER_HERMITE_STARCAST_3((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE_STARCAST_3)),
CLOVER_HERMITE_STARCAST_6((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE_STARCAST_6)),
CLOVER_HERMITE_STARCAST_9((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE_STARCAST_9)),
CLOVER_HERMITE_STARCAST_12((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE_STARCAST_12)),
HEXAGON(HexagonNoise::new),
HEXAGON_BILINEAR((s) -> new InterpolatedNoise(s, HEXAGON, InterpolationMethod.BILINEAR)),
HEXAGON_BICUBIC((s) -> new InterpolatedNoise(s, HEXAGON, InterpolationMethod.BICUBIC)),
HEXAGON_HERMITE((s) -> new InterpolatedNoise(s, HEXAGON, InterpolationMethod.HERMITE)),
HEX_JAMES(HexJamesNoise::new),
HEX_JAMES_BILINEAR((s) -> new InterpolatedNoise(s, HEX_JAMES, InterpolationMethod.BILINEAR)),
HEX_JAMES_BICUBIC((s) -> new InterpolatedNoise(s, HEX_JAMES, InterpolationMethod.BICUBIC)),
HEX_JAMES_HERMITE((s) -> new InterpolatedNoise(s, HEX_JAMES, InterpolationMethod.HERMITE)),
HEX_SIMPLEX(HexSimplexNoise::new),
HEX_SIMPLEX_BILINEAR((s) -> new InterpolatedNoise(s, HEX_SIMPLEX, InterpolationMethod.BILINEAR)),
HEX_SIMPLEX_BICUBIC((s) -> new InterpolatedNoise(s, HEX_SIMPLEX, InterpolationMethod.BICUBIC)),
HEX_SIMPLEX_HERMITE((s) -> new InterpolatedNoise(s, HEX_SIMPLEX, InterpolationMethod.HERMITE)),
HEX_RANDOM_SIZE(HexRandomSizeNoise::new),
HEX_RANDOM_SIZE_BILINEAR((s) -> new InterpolatedNoise(s, HEX_RANDOM_SIZE, InterpolationMethod.BILINEAR)),
HEX_RANDOM_SIZE_BICUBIC((s) -> new InterpolatedNoise(s, HEX_RANDOM_SIZE, InterpolationMethod.BICUBIC)),
HEX_RANDOM_SIZE_HERMITE((s) -> new InterpolatedNoise(s, HEX_RANDOM_SIZE, InterpolationMethod.HERMITE)),
SIERPINSKI_TRIANGLE(SierpinskiTriangleNoise::new),
SIERPINSKI_TRIANGLE_BILINEAR((s) -> new InterpolatedNoise(s, SIERPINSKI_TRIANGLE, InterpolationMethod.BILINEAR)),
SIERPINSKI_TRIANGLE_BICUBIC((s) -> new InterpolatedNoise(s, SIERPINSKI_TRIANGLE, InterpolationMethod.BICUBIC)),
SIERPINSKI_TRIANGLE_HERMITE((s) -> new InterpolatedNoise(s, SIERPINSKI_TRIANGLE, InterpolationMethod.HERMITE)),
CLOVER(CloverNoise::new, 1D / 64D),
CLOVER_BILINEAR((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR), 1D),
CLOVER_BILINEAR_STARCAST_3((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR_STARCAST_3), 1D),
CLOVER_BILINEAR_STARCAST_6((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR_STARCAST_6), 1D),
CLOVER_BILINEAR_STARCAST_9((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR_STARCAST_9), 1D),
CLOVER_BILINEAR_STARCAST_12((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BILINEAR_STARCAST_12), 1D),
CLOVER_BICUBIC((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.BICUBIC), 1D),
CLOVER_HERMITE((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE), 1D),
CLOVER_STARCAST_3((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.STARCAST_3), 1D),
CLOVER_STARCAST_6((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.STARCAST_6), 1D),
CLOVER_STARCAST_9((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.STARCAST_9), 1D),
CLOVER_STARCAST_12((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.STARCAST_12), 1D),
CLOVER_HERMITE_STARCAST_3((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE_STARCAST_3), 1D),
CLOVER_HERMITE_STARCAST_6((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE_STARCAST_6), 1D),
CLOVER_HERMITE_STARCAST_9((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE_STARCAST_9), 1D),
CLOVER_HERMITE_STARCAST_12((s) -> new InterpolatedNoise(s, CLOVER, InterpolationMethod.HERMITE_STARCAST_12), 1D),
HEXAGON(HexagonNoise::new, 2D / 64D),
HEXAGON_BILINEAR((s) -> new InterpolatedNoise(s, HEXAGON, InterpolationMethod.BILINEAR), 1D),
HEXAGON_BICUBIC((s) -> new InterpolatedNoise(s, HEXAGON, InterpolationMethod.BICUBIC), 1D),
HEXAGON_HERMITE((s) -> new InterpolatedNoise(s, HEXAGON, InterpolationMethod.HERMITE), 1D),
HEX_JAMES(HexJamesNoise::new, 2D / 64D),
HEX_JAMES_BILINEAR((s) -> new InterpolatedNoise(s, HEX_JAMES, InterpolationMethod.BILINEAR), 1D),
HEX_JAMES_BICUBIC((s) -> new InterpolatedNoise(s, HEX_JAMES, InterpolationMethod.BICUBIC), 1D),
HEX_JAMES_HERMITE((s) -> new InterpolatedNoise(s, HEX_JAMES, InterpolationMethod.HERMITE), 1D),
HEX_SIMPLEX(HexSimplexNoise::new, 2D / 64D),
HEX_SIMPLEX_BILINEAR((s) -> new InterpolatedNoise(s, HEX_SIMPLEX, InterpolationMethod.BILINEAR), 1D),
HEX_SIMPLEX_BICUBIC((s) -> new InterpolatedNoise(s, HEX_SIMPLEX, InterpolationMethod.BICUBIC), 1D),
HEX_SIMPLEX_HERMITE((s) -> new InterpolatedNoise(s, HEX_SIMPLEX, InterpolationMethod.HERMITE), 1D),
HEX_RANDOM_SIZE(HexRandomSizeNoise::new, 2D / 64D),
HEX_RANDOM_SIZE_BILINEAR((s) -> new InterpolatedNoise(s, HEX_RANDOM_SIZE, InterpolationMethod.BILINEAR), 1D),
HEX_RANDOM_SIZE_BICUBIC((s) -> new InterpolatedNoise(s, HEX_RANDOM_SIZE, InterpolationMethod.BICUBIC), 1D),
HEX_RANDOM_SIZE_HERMITE((s) -> new InterpolatedNoise(s, HEX_RANDOM_SIZE, InterpolationMethod.HERMITE), 1D),
SIERPINSKI_TRIANGLE(SierpinskiTriangleNoise::new, 8D / 64D),
SIERPINSKI_TRIANGLE_BILINEAR((s) -> new InterpolatedNoise(s, SIERPINSKI_TRIANGLE, InterpolationMethod.BILINEAR), 1D),
SIERPINSKI_TRIANGLE_BICUBIC((s) -> new InterpolatedNoise(s, SIERPINSKI_TRIANGLE, InterpolationMethod.BICUBIC), 1D),
SIERPINSKI_TRIANGLE_HERMITE((s) -> new InterpolatedNoise(s, SIERPINSKI_TRIANGLE, InterpolationMethod.HERMITE), 1D),
VASCULAR(VascularNoise::new);
private final NoiseFactory f;
private final double coordinateScale;
NoiseType(NoiseFactory f) {
this(f, 100D / 64D);
}
NoiseType(NoiseFactory f, double coordinateScale) {
this.f = f;
this.coordinateScale = coordinateScale;
}
public double getCoordinateScale() {
return coordinateScale;
}
public NoiseGenerator create(long seed) {
@@ -5,7 +5,7 @@ import art.arcane.volmlib.util.math.RNG;
import org.jetbrains.annotations.NotNull;
public class OffsetNoiseGenerator implements NoiseGenerator {
public class OffsetNoiseGenerator implements NoiseGenerator, OctaveNoise {
private static final int GENERIC = 0;
private static final int SIMPLEX = 1;
private static final int PERLIN = 2;
@@ -102,6 +102,13 @@ public class OffsetNoiseGenerator implements NoiseGenerator {
};
}
@Override
public void setOctaves(int octaves) {
if (base instanceof OctaveNoise octaveNoise) {
octaveNoise.setOctaves(octaves);
}
}
@Override
public boolean isNoScale() {
return base.isNoScale();
@@ -23,9 +23,11 @@ import art.arcane.volmlib.util.math.RNG;
public class PerlinNoise implements NoiseGenerator, OctaveNoise {
private final FastNoiseDouble n;
private int octaves;
private double octaveBounding = 1D;
public PerlinNoise(long seed) {
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setLongerp(FastNoiseDouble.Longerp.Qulongic);
octaves = 1;
}
@@ -35,128 +37,74 @@ public class PerlinNoise implements NoiseGenerator, OctaveNoise {
@Override
public double noise(double x) {
if (octaves <= 1) {
return f(n.GetPerlin(x, 0));
}
double f = 1;
double m = 0;
double v = 0;
for (int i = 0; i < octaves; i++) {
v += n.GetPerlin((x * (f == 1 ? f++ : (f *= 2))), 0) * f;
m += f;
}
return f(v / m);
return f(noiseSigned(x));
}
@Override
public double noiseSigned(double x) {
if (octaves <= 1) {
if (octaves == 1) {
return n.GetPerlin(x, 0D);
}
double frequency = 1D;
double magnitude = 0D;
double amplitude = 1D;
double value = 0D;
for (int i = 0; i < octaves; i++) {
double sampleFrequency;
if (frequency == 1D) {
sampleFrequency = frequency;
frequency = 2D;
} else {
frequency *= 2D;
sampleFrequency = frequency;
}
value += n.GetPerlin(x * sampleFrequency, 0D) * frequency;
magnitude += frequency;
value += n.GetPerlin(x * frequency, 0D) * amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
return value / magnitude;
return value * octaveBounding;
}
@Override
public double noise(double x, double z) {
if (octaves <= 1) {
return f(n.GetPerlin(x, z));
}
double f = 1;
double m = 0;
double v = 0;
for (int i = 0; i < octaves; i++) {
f = f == 1 ? f + 1 : f * 2;
v += n.GetPerlin((x * f), (z * f)) * f;
m += f;
}
return f(v / m);
return f(noiseSigned(x, z));
}
@Override
public double noiseSigned(double x, double z) {
if (octaves <= 1) {
if (octaves == 1) {
return n.GetPerlin(x, z);
}
double frequency = 1D;
double magnitude = 0D;
double amplitude = 1D;
double value = 0D;
for (int i = 0; i < octaves; i++) {
double octaveFrequency = frequency == 1D ? frequency + 1D : frequency * 2D;
value += n.GetPerlin(x * octaveFrequency, z * octaveFrequency) * octaveFrequency;
magnitude += octaveFrequency;
frequency = octaveFrequency;
value += n.GetPerlin(x * frequency, z * frequency) * amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
return value / magnitude;
return value * octaveBounding;
}
@Override
public double noise(double x, double y, double z) {
if (octaves <= 1) {
return f(n.GetPerlin(x, y, z));
}
double f = 1;
double m = 0;
double v = 0;
for (int i = 0; i < octaves; i++) {
f = f == 1 ? f + 1 : f * 2;
v += n.GetPerlin((x * f), (y * f), (z * f)) * f;
m += f;
}
return f(v / m);
return f(noiseSigned(x, y, z));
}
@Override
public double noiseSigned(double x, double y, double z) {
if (octaves <= 1) {
if (octaves == 1) {
return n.GetPerlin(x, y, z);
}
double frequency = 1D;
double magnitude = 0D;
double amplitude = 1D;
double value = 0D;
for (int i = 0; i < octaves; i++) {
double octaveFrequency = frequency == 1D ? frequency + 1D : frequency * 2D;
value += n.GetPerlin(x * octaveFrequency, y * octaveFrequency, z * octaveFrequency) * octaveFrequency;
magnitude += octaveFrequency;
frequency = octaveFrequency;
value += n.GetPerlin(x * frequency, y * frequency, z * frequency) * amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
return value / magnitude;
return value * octaveBounding;
}
@Override
public void setOctaves(int o) {
octaves = o;
public void setOctaves(int octaves) {
this.octaves = Math.max(1, Math.min(16, octaves));
octaveBounding = 1D / (2D - Math.scalb(1D, 1 - this.octaves));
}
public NoiseGenerator hermite() {
@@ -3,96 +3,67 @@ package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.math.RNG;
public class SierpinskiTriangleNoise implements NoiseGenerator, OctaveNoise {
private static final double TRI_SCALE = 0.18D;
private static final double TRI_PROJECTION = 0.8660254037844386D;
private static final double HEAT_SCALE = 0.33D;
private final SimplexNoise heatSimplex;
private int octaves;
private static final double TRIANGLE_SIDE = 8D;
private static final double INVERSE_HEIGHT = 2D / (Math.sqrt(3D) * TRIANGLE_SIDE);
private static final double HEAT_SCALE = 6D;
private static final int DEPTH = 4;
private final SimplexNoise heat;
public SierpinskiTriangleNoise(long seed) {
RNG rng = new RNG(seed);
this.heatSimplex = new SimplexNoise(rng.nextParallelRNG(177L).lmax());
this.octaves = 1;
}
private double clip(double value) {
if (value < 0D) {
return 0D;
}
if (value > 1D) {
return 1D;
}
return value;
}
private double heat(double x, double z) {
if (octaves <= 1) {
return heatSimplex.noise(x * HEAT_SCALE, z * HEAT_SCALE);
}
double frequency = 1D;
double amplitude = 1D;
double total = 0D;
double max = 0D;
for (int i = 0; i < octaves; i++) {
total += heatSimplex.noise((x * HEAT_SCALE) * frequency, (z * HEAT_SCALE) * frequency) * amplitude;
max += amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
if (max == 0D) {
return 0.5D;
}
return clip(total / max);
}
private double mask(double x, double z) {
double sx = (x * TRI_SCALE) + ((z * TRI_SCALE) * 0.5D);
double sz = (z * TRI_SCALE) * TRI_PROJECTION;
long ix = (long) Math.floor(Math.abs(sx));
long iz = (long) Math.floor(Math.abs(sz));
return ((ix & iz) == 0L) ? 1D : 0D;
}
private double sample(double x, double z) {
double m = mask(x, z);
double h = heat(x, z);
if (m >= 0.5D) {
return clip((h * 0.65D) + 0.35D);
}
return clip(h * 0.12D);
this.heat = new SimplexNoise(new RNG(seed).nextParallelRNG(177L).lmax());
}
@Override
public double noise(double x) {
return sample(x, 0D);
return sample(x, 0D, 0D);
}
@Override
public double noise(double x, double z) {
return sample(x, z);
return sample(x, 0D, z);
}
@Override
public double noise(double x, double y, double z) {
if (z == 0D) {
return sample(x, y);
}
double a = sample(x, z);
double b = sample(y, x);
double c = sample(z, y);
return (a + b + c) / 3D;
return sample(x, y, z);
}
@Override
public void setOctaves(int o) {
this.octaves = Math.max(1, o);
public void setOctaves(int octaves) {
heat.setOctaves(octaves);
}
private boolean contains(double x, double z) {
double v = z * INVERSE_HEIGHT;
double u = (x / TRIANGLE_SIDE) - (v * 0.5D);
u -= Math.floor(u);
v -= Math.floor(v);
if (u + v > 1D) {
u = 1D - u;
v = 1D - v;
}
for (int depth = 0; depth < DEPTH; depth++) {
if (u >= 0.5D) {
u = (u * 2D) - 1D;
v *= 2D;
} else if (v >= 0.5D) {
u *= 2D;
v = (v * 2D) - 1D;
} else if (u + v <= 0.5D) {
u *= 2D;
v *= 2D;
} else {
return false;
}
}
return true;
}
private double sample(double x, double y, double z) {
double value = heat.noise(x * HEAT_SCALE, y * HEAT_SCALE, z * HEAT_SCALE);
return contains(x, z) ? (value * 0.65D) + 0.35D : value * 0.12D;
}
}
@@ -23,6 +23,7 @@ import art.arcane.volmlib.util.math.RNG;
public class SimplexNoise implements NoiseGenerator, OctaveNoise {
private final FastNoiseDouble n;
private int octaves;
private double octaveBounding = 1D;
public SimplexNoise(long seed) {
this.n = new FastNoiseDouble(new RNG(seed).lmax());
@@ -35,127 +36,74 @@ public class SimplexNoise implements NoiseGenerator, OctaveNoise {
@Override
public double noise(double x) {
if (octaves <= 1) {
return f(n.GetSimplex(x, 0d));
}
double f = 1;
double m = 0;
double v = 0;
for (int i = 0; i < octaves; i++) {
v += n.GetSimplex((x * (f == 1 ? f++ : (f *= 2))), 0d) * f;
m += f;
}
return f(v / m);
return f(noiseSigned(x));
}
@Override
public double noiseSigned(double x) {
if (octaves <= 1) {
if (octaves == 1) {
return n.GetSimplex(x, 0D);
}
double frequency = 1D;
double magnitude = 0D;
double amplitude = 1D;
double value = 0D;
for (int i = 0; i < octaves; i++) {
double sampleFrequency;
if (frequency == 1D) {
sampleFrequency = frequency;
frequency = 2D;
} else {
frequency *= 2D;
sampleFrequency = frequency;
}
value += n.GetSimplex(x * sampleFrequency, 0D) * frequency;
magnitude += frequency;
value += n.GetSimplex(x * frequency, 0D) * amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
return value / magnitude;
return value * octaveBounding;
}
@Override
public double noise(double x, double z) {
if (octaves <= 1) {
return f(n.GetSimplex(x, z));
}
double f = 1;
double m = 0;
double v = 0;
for (int i = 0; i < octaves; i++) {
f = f == 1 ? f + 1 : f * 2;
v += n.GetSimplex((x * f), (z * f)) * f;
m += f;
}
return f(v / m);
return f(noiseSigned(x, z));
}
@Override
public double noiseSigned(double x, double z) {
if (octaves <= 1) {
if (octaves == 1) {
return n.GetSimplex(x, z);
}
double frequency = 1D;
double magnitude = 0D;
double amplitude = 1D;
double value = 0D;
for (int i = 0; i < octaves; i++) {
double octaveFrequency = frequency == 1D ? frequency + 1D : frequency * 2D;
value += n.GetSimplex(x * octaveFrequency, z * octaveFrequency) * octaveFrequency;
magnitude += octaveFrequency;
frequency = octaveFrequency;
value += n.GetSimplex(x * frequency, z * frequency) * amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
return value / magnitude;
return value * octaveBounding;
}
@Override
public double noise(double x, double y, double z) {
if (octaves <= 1) {
return f(n.GetSimplex(x, y, z));
}
double f = 1;
double m = 0;
double v = 0;
for (int i = 0; i < octaves; i++) {
f = f == 1 ? f + 1 : f * 2;
v += n.GetSimplex((x * f), (y * f), (z * f)) * f;
m += f;
}
return f(v / m);
return f(noiseSigned(x, y, z));
}
@Override
public double noiseSigned(double x, double y, double z) {
if (octaves <= 1) {
if (octaves == 1) {
return n.GetSimplex(x, y, z);
}
double frequency = 1D;
double magnitude = 0D;
double amplitude = 1D;
double value = 0D;
for (int i = 0; i < octaves; i++) {
double octaveFrequency = frequency == 1D ? frequency + 1D : frequency * 2D;
value += n.GetSimplex(x * octaveFrequency, y * octaveFrequency, z * octaveFrequency) * octaveFrequency;
magnitude += octaveFrequency;
frequency = octaveFrequency;
value += n.GetSimplex(x * frequency, y * frequency, z * frequency) * amplitude;
frequency *= 2D;
amplitude *= 0.5D;
}
return value / magnitude;
return value * octaveBounding;
}
@Override
public void setOctaves(int o) {
octaves = o;
public void setOctaves(int octaves) {
this.octaves = Math.max(1, Math.min(16, octaves));
octaveBounding = 1D / (2D - Math.scalb(1D, 1 - this.octaves));
}
}
@@ -31,7 +31,7 @@ public class VascularNoise implements NoiseGenerator {
}
private double filter(double noise) {
double normalized = (noise * 0.5D) + 0.5D;
double normalized = 0.5D - noise * 0.5D;
if (normalized < 0D) {
return 0D;
}
@@ -40,6 +40,7 @@ public class VascularNoise implements NoiseGenerator {
}
private double filterSigned(double noise) {
noise = -noise;
if (noise < -1D) {
return -1D;
}
@@ -18,13 +18,11 @@
package art.arcane.iris.util.project.noise;
import art.arcane.volmlib.util.math.RNG;
public class WhiteNoise implements NoiseGenerator {
private final FastNoise n;
private final FastNoiseDouble n;
public WhiteNoise(long seed) {
n = new FastNoise(new RNG(seed).imax());
n = new FastNoiseDouble(seed);
}
public boolean isStatic() {
@@ -35,22 +33,18 @@ public class WhiteNoise implements NoiseGenerator {
return true;
}
private double f(double m) {
return (m % 8192) * 1024;
}
@Override
public double noise(double x) {
return (n.GetWhiteNoise(f(x), 0d) / 2D) + 0.5D;
return (n.GetWhiteNoise(x, 0d) / 2D) + 0.5D;
}
@Override
public double noise(double x, double z) {
return (n.GetWhiteNoise(f(x), f(z)) / 2D) + 0.5D;
return (n.GetWhiteNoise(x, z) / 2D) + 0.5D;
}
@Override
public double noise(double x, double y, double z) {
return (n.GetWhiteNoise(f(x), f(y), f(z)) / 2D) + 0.5D;
return (n.GetWhiteNoise(x, y, z) / 2D) + 0.5D;
}
}