mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-27 06:20:02 +00:00
Added diverse noise styles
- Dune and Strata add dunes and layered bands - Wood and Marble add warped grain and mineral veins - Gabor and Scales add oriented waves and overlapping scallops - Chladni and Kaleidoscope add nodal lines and mirrored motifs - Menger Sponge and Circuit add recursive voids and connected traces - New styles use the shared scale and full seeds - Tests cover tile seams, volume variation, bounds, and octaves
This commit is contained in:
1 parent
645edcff5c
commit
14cfe3ed68
22 files changed
+1183
-3
No files matched your search
@@ -553,6 +553,36 @@ public enum NoiseStyle {
|
||||
|
||||
@Desc("Seeded spiral arms form swirling eddies in 2D and winding funnels in 3D.")
|
||||
VORTEX(rng -> new CNG(rng, NoiseType.VORTEX, 1D, 1), NoiseType.VORTEX),
|
||||
|
||||
@Desc("Seeded crescent dunes with asymmetric slopes and smooth height-dependent drift.")
|
||||
DUNE(rng -> new CNG(rng, NoiseType.DUNE, 1D, 1), NoiseType.DUNE),
|
||||
|
||||
@Desc("Folded sedimentary bands with varying thickness through the volume.")
|
||||
STRATA(rng -> new CNG(rng, NoiseType.STRATA, 1D, 1), NoiseType.STRATA),
|
||||
|
||||
@Desc("Distorted growth rings and knot-like forms with variation through height.")
|
||||
WOOD(rng -> new CNG(rng, NoiseType.WOOD, 1D, 1), NoiseType.WOOD),
|
||||
|
||||
@Desc("Seeded oriented wave packets form a sparse directional ripple texture.")
|
||||
GABOR(rng -> new CNG(rng, NoiseType.GABOR, 1D, 1), NoiseType.GABOR),
|
||||
|
||||
@Desc("Turbulent stone veins separate broad smooth regions.")
|
||||
MARBLE(rng -> new CNG(rng, NoiseType.MARBLE, 1D, 1), NoiseType.MARBLE),
|
||||
|
||||
@Desc("Overlapping scalloped scales form a seeded tiled surface.")
|
||||
SCALES(rng -> new CNG(rng, NoiseType.SCALES, 1D, 1), NoiseType.SCALES),
|
||||
|
||||
@Desc("Standing-wave nodes form plate-like figures that change through height.")
|
||||
CHLADNI(rng -> new CNG(rng, NoiseType.CHLADNI, 1D, 1), NoiseType.CHLADNI),
|
||||
|
||||
@Desc("Mirrored wedge motifs repeat at a local scale with seeded variation.")
|
||||
KALEIDOSCOPE(rng -> new CNG(rng, NoiseType.KALEIDOSCOPE, 1D, 1), NoiseType.KALEIDOSCOPE),
|
||||
|
||||
@Desc("Recursive cubic voids form a three-dimensional sponge with square-hole slices.")
|
||||
MENGER_SPONGE(rng -> new CNG(rng, NoiseType.MENGER_SPONGE, 1D, 1), NoiseType.MENGER_SPONGE),
|
||||
|
||||
@Desc("Orthogonal tracks and ring pads form connected circuits that shift through height.")
|
||||
CIRCUIT(rng -> new CNG(rng, NoiseType.CIRCUIT, 1D, 1), NoiseType.CIRCUIT),
|
||||
;
|
||||
|
||||
private final CNGFactory f;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
public final class ChladniNoise extends PatternNoise {
|
||||
private final int firstMode;
|
||||
private final int secondMode;
|
||||
private final double phase;
|
||||
private final double width;
|
||||
|
||||
public ChladniNoise(long seed) {
|
||||
long hash = mix(seed);
|
||||
firstMode = 2 + (int) (hash & 1L);
|
||||
secondMode = firstMode + 1 + (int) ((hash >>> 1) & 1L);
|
||||
phase = (hash >>> 11) * 0x1.0p-52D;
|
||||
width = 0.22D + ((hash >>> 3) & 255L) * (0.12D / 255D);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
double u = (x + phase) * Math.PI;
|
||||
double v = (z + phase) * Math.PI;
|
||||
double first = Math.cos(firstMode * u) * Math.cos(secondMode * v);
|
||||
double second = Math.cos(secondMode * u) * Math.cos(firstMode * v);
|
||||
double field = first * Math.cos(y * Math.PI * 0.5D)
|
||||
- second * Math.cos(y * Math.PI * 0.75D);
|
||||
double node = Math.max(0D, 1D - Math.abs(field) / width);
|
||||
return node * node * (3D - 2D * node);
|
||||
}
|
||||
|
||||
private static long mix(long value) {
|
||||
value = (value ^ (value >>> 30)) * 0xBF58476D1CE4E5B9L;
|
||||
value = (value ^ (value >>> 27)) * 0x94D049BB133111EBL;
|
||||
return value ^ (value >>> 31);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
public final class CircuitNoise extends PatternNoise {
|
||||
private final long seed;
|
||||
private final double phaseX;
|
||||
private final double phaseZ;
|
||||
|
||||
public CircuitNoise(long seed) {
|
||||
this.seed = seed;
|
||||
phaseX = (mix(seed) >>> 11) * 0x1.0p-53;
|
||||
phaseZ = (mix(seed + 0x9E3779B97F4A7C15L) >>> 11) * 0x1.0p-53;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
x += phaseX;
|
||||
z += phaseZ;
|
||||
if (y != 0D) {
|
||||
x += y * 0.13D + 0.17D * Math.sin(y * Math.PI * 0.5D);
|
||||
z += 0.11D * Math.sin(y * Math.PI * 0.75D);
|
||||
}
|
||||
long cellX = (long) Math.floor(x);
|
||||
long cellZ = (long) Math.floor(z);
|
||||
x -= cellX;
|
||||
z -= cellZ;
|
||||
long hash = mix(seed ^ cellX * 0x9E3779B97F4A7C15L ^ cellZ * 0xD1B54A32D192ED03L);
|
||||
double distance;
|
||||
double padDistance;
|
||||
if ((hash & 3L) == 0L) {
|
||||
distance = Math.min(Math.abs(x - 0.5D), Math.abs(z - 0.5D));
|
||||
double dx = x - 0.5D;
|
||||
double dz = z - 0.5D;
|
||||
padDistance = Math.sqrt(dx * dx + dz * dz);
|
||||
} else {
|
||||
if ((hash & 1L) != 0L) {
|
||||
x = 1D - x;
|
||||
}
|
||||
distance = Math.sqrt(Math.min(routeDistanceSquared(x, z), routeDistanceSquared(1D - x, 1D - z)));
|
||||
double dx = x - 0.75D;
|
||||
double dz = z - 0.25D;
|
||||
double oppositeX = x - 0.25D;
|
||||
double oppositeZ = z - 0.75D;
|
||||
padDistance = Math.sqrt(Math.min(dx * dx + dz * dz, oppositeX * oppositeX + oppositeZ * oppositeZ));
|
||||
}
|
||||
double trace = smooth(1D - distance / 0.045D);
|
||||
double pad = smooth(1D - Math.abs(padDistance - 0.085D) / 0.03D);
|
||||
return Math.max(trace, pad) * smooth(padDistance / 0.045D);
|
||||
}
|
||||
|
||||
private static double routeDistanceSquared(double x, double z) {
|
||||
double top = segmentDistanceSquared(x - 0.5D, z, 0D, 0.25D);
|
||||
double bend = segmentDistanceSquared(z - 0.25D, x, 0.5D, 0.75D);
|
||||
double middle = segmentDistanceSquared(x - 0.75D, z, 0.25D, 0.5D);
|
||||
double right = segmentDistanceSquared(z - 0.5D, x, 0.75D, 1D);
|
||||
return Math.min(Math.min(top, bend), Math.min(middle, right));
|
||||
}
|
||||
|
||||
private static double segmentDistanceSquared(double perpendicular, double along, double start, double end) {
|
||||
double excess = Math.max(start - along, Math.max(along - end, 0D));
|
||||
return perpendicular * perpendicular + excess * excess;
|
||||
}
|
||||
|
||||
private static double smooth(double value) {
|
||||
double bounded = Math.clamp(value, 0D, 1D);
|
||||
return bounded * bounded * (3D - 2D * bounded);
|
||||
}
|
||||
|
||||
private static long mix(long value) {
|
||||
value = (value ^ (value >>> 30)) * 0xBF58476D1CE4E5B9L;
|
||||
value = (value ^ (value >>> 27)) * 0x94D049BB133111EBL;
|
||||
return value ^ (value >>> 31);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
public final class DuneNoise extends PatternNoise {
|
||||
private static final double TAU = Math.PI * 2D;
|
||||
|
||||
private final long seed;
|
||||
private final double cosine;
|
||||
private final double sine;
|
||||
private final double phase;
|
||||
|
||||
public DuneNoise(long seed) {
|
||||
this.seed = seed;
|
||||
phase = unit(mix(seed)) * TAU;
|
||||
cosine = Math.cos(phase);
|
||||
sine = Math.sin(phase);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
double wind = x * cosine + z * sine + y * 0.17D;
|
||||
double across = z * cosine - x * sine + 0.12D * Math.sin(y * 0.7D + phase);
|
||||
long cellWind = (long) Math.floor(wind);
|
||||
long cellAcross = (long) Math.floor(across);
|
||||
double dune = 0D;
|
||||
for (int offsetWind = -1; offsetWind <= 1; offsetWind++) {
|
||||
long gridWind = cellWind + offsetWind;
|
||||
for (int offsetAcross = -1; offsetAcross <= 1; offsetAcross++) {
|
||||
long gridAcross = cellAcross + offsetAcross;
|
||||
long hash = mix(seed ^ gridWind * 0x9E3779B97F4A7C15L ^ gridAcross * 0xD1B54A32D192ED03L);
|
||||
double centerWind = gridWind + 0.2D + (hash & 65535L) * (0.6D / 65535D);
|
||||
double centerAcross = gridAcross + 0.2D + ((hash >>> 16) & 65535L) * (0.6D / 65535D);
|
||||
double width = 0.32D + ((hash >>> 32) & 255L) * (0.16D / 255D);
|
||||
double transverse = (across - centerAcross) / width;
|
||||
double transverseSquared = transverse * transverse;
|
||||
if (transverseSquared >= 1D) {
|
||||
continue;
|
||||
}
|
||||
double crest = centerWind + 0.43D * transverseSquared;
|
||||
double offset = wind - crest;
|
||||
double windward = 0.52D + ((hash >>> 40) & 255L) * (0.14D / 255D);
|
||||
double leeward = 0.1D + ((hash >>> 48) & 255L) * (0.035D / 255D);
|
||||
double slope = Math.max(0D, 1D - Math.abs(offset) / (offset < 0D ? windward : leeward));
|
||||
double horns = 1D - transverseSquared * transverseSquared;
|
||||
double height = 0.62D + (hash >>> 56) * (0.38D / 255D);
|
||||
dune = Math.max(dune, height * horns * horns * slope * slope * (3D - 2D * slope));
|
||||
}
|
||||
}
|
||||
double ripples = 0.04D + 0.035D * Math.cos(wind * TAU * 2D + 0.5D * Math.sin(across * 1.7D + phase));
|
||||
return ripples + (1D - ripples) * dune;
|
||||
}
|
||||
|
||||
private static long mix(long value) {
|
||||
value = (value ^ (value >>> 30)) * 0xBF58476D1CE4E5B9L;
|
||||
value = (value ^ (value >>> 27)) * 0x94D049BB133111EBL;
|
||||
return value ^ (value >>> 31);
|
||||
}
|
||||
|
||||
private static double unit(long value) {
|
||||
return (value >>> 11) * 0x1.0p-53D;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
|
||||
public final class GaborNoise extends PatternNoise {
|
||||
private static final double TAU = Math.PI * 2D;
|
||||
private static final double RADIUS_SQUARED = 0.95D * 0.95D;
|
||||
private static final double SPREAD = 0.6D / 65535D;
|
||||
|
||||
private final long seed;
|
||||
private final double directionX;
|
||||
private final double directionY;
|
||||
private final double directionZ;
|
||||
|
||||
public GaborNoise(long seed) {
|
||||
this.seed = seed;
|
||||
SplittableRandom random = new SplittableRandom(seed);
|
||||
double angle = random.nextDouble(TAU);
|
||||
double elevation = random.nextDouble(-0.55D, 0.55D);
|
||||
double horizontal = Math.sqrt(1D - elevation * elevation);
|
||||
directionX = Math.cos(angle) * horizontal;
|
||||
directionY = elevation;
|
||||
directionZ = Math.sin(angle) * horizontal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
long cellX = (long) Math.floor(x);
|
||||
long cellY = (long) Math.floor(y);
|
||||
long cellZ = (long) Math.floor(z);
|
||||
double sum = 0D;
|
||||
double weights = 0.12D;
|
||||
for (int offsetY = -1; offsetY <= 1; offsetY++) {
|
||||
long pointY = cellY + offsetY;
|
||||
long hashY = pointY * 0xC2B2AE3D27D4EB4FL;
|
||||
for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
|
||||
long pointZ = cellZ + offsetZ;
|
||||
long hashYZ = hashY ^ pointZ * 0x165667B19E3779F9L;
|
||||
for (int offsetX = -1; offsetX <= 1; offsetX++) {
|
||||
long pointX = cellX + offsetX;
|
||||
long hash = mix(seed ^ pointX * 0x9E3779B97F4A7C15L ^ hashYZ);
|
||||
if ((hash & 3L) == 0L) {
|
||||
continue;
|
||||
}
|
||||
double dx = x - (pointX + 0.2D + (hash & 65535L) * SPREAD);
|
||||
double dy = y - (pointY + 0.2D + ((hash >>> 16) & 65535L) * SPREAD);
|
||||
double dz = z - (pointZ + 0.2D + ((hash >>> 32) & 65535L) * SPREAD);
|
||||
double distanceSquared = dx * dx + dy * dy + dz * dz;
|
||||
if (distanceSquared >= RADIUS_SQUARED) {
|
||||
continue;
|
||||
}
|
||||
double envelope = 1D - distanceSquared / RADIUS_SQUARED;
|
||||
double weight = envelope * envelope * envelope;
|
||||
long wave = mix(hash);
|
||||
double waveX = directionX + ((wave & 1023L) / 1023D - 0.5D) * 0.35D;
|
||||
double waveY = directionY + (((wave >>> 10) & 1023L) / 1023D - 0.5D) * 0.35D;
|
||||
double waveZ = directionZ + (((wave >>> 20) & 1023L) / 1023D - 0.5D) * 0.35D;
|
||||
double phase = (wave >>> 32) * (TAU / 4294967296D);
|
||||
sum += weight * Math.cos(TAU * 3D * (waveX * dx + waveY * dy + waveZ * dz) + phase);
|
||||
weights += weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0.5D + 0.5D * sum / weights;
|
||||
}
|
||||
|
||||
private static long mix(long value) {
|
||||
value = (value ^ (value >>> 30)) * 0xBF58476D1CE4E5B9L;
|
||||
value = (value ^ (value >>> 27)) * 0x94D049BB133111EBL;
|
||||
return value ^ (value >>> 31);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
public final class KaleidoscopeNoise extends PatternNoise {
|
||||
private static final double TAU = Math.PI * 2D;
|
||||
|
||||
private final long seed;
|
||||
|
||||
public KaleidoscopeNoise(long seed) {
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
z += 0.5D;
|
||||
long cellX = (long) Math.floor(x);
|
||||
long cellZ = (long) Math.floor(z);
|
||||
double dx = x - cellX - 0.5D;
|
||||
double dz = z - cellZ - 0.5D;
|
||||
double radiusSquared = dx * dx + dz * dz;
|
||||
if (radiusSquared >= 0.25D) {
|
||||
return 0D;
|
||||
}
|
||||
|
||||
long hash = mix(seed ^ cellX * 0x9E3779B97F4A7C15L ^ cellZ * 0xD1B54A32D192ED03L);
|
||||
int wedges = 4 + (int) (hash & 3L);
|
||||
double phase = (hash >>> 11) * 0x1.0p-53D * TAU;
|
||||
double sector = TAU / wedges;
|
||||
double angle = Math.atan2(dz, dx) + phase + y * 0.35D;
|
||||
angle = Math.abs(angle - Math.floor(angle / sector + 0.5D) * sector);
|
||||
double radius = Math.sqrt(radiusSquared);
|
||||
double u = radius * Math.cos(angle);
|
||||
double v = radius * Math.sin(angle);
|
||||
double motif = 0.5D + 0.5D * Math.cos(16D * u + 2.5D * Math.cos(18D * v + phase + y));
|
||||
double envelope = 1D - radiusSquared * 4D;
|
||||
return motif * envelope * envelope;
|
||||
}
|
||||
|
||||
private static long mix(long value) {
|
||||
value = (value ^ (value >>> 30)) * 0xBF58476D1CE4E5B9L;
|
||||
value = (value ^ (value >>> 27)) * 0x94D049BB133111EBL;
|
||||
return value ^ (value >>> 31);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
|
||||
public final class MarbleNoise extends PatternNoise {
|
||||
private static final double TAU = Math.PI * 2D;
|
||||
|
||||
private final FastNoiseDouble distortion;
|
||||
private final double directionX;
|
||||
private final double directionY;
|
||||
private final double directionZ;
|
||||
private final double phase;
|
||||
|
||||
public MarbleNoise(long seed) {
|
||||
SplittableRandom random = new SplittableRandom(seed);
|
||||
distortion = new FastNoiseDouble(random.nextLong());
|
||||
distortion.setFrequency(1D);
|
||||
double angle = random.nextDouble(TAU);
|
||||
directionX = Math.cos(angle);
|
||||
directionY = random.nextDouble(0.25D, 0.65D);
|
||||
directionZ = Math.sin(angle);
|
||||
phase = random.nextDouble(TAU);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
double broad = distortion.GetSimplex(x * 0.45D, y * 0.45D, z * 0.45D);
|
||||
double detail = distortion.GetSimplex(x * 1.3D + 17.3D, y * 1.3D - 11.7D, z * 1.3D + 5.9D);
|
||||
double warp = broad * 1.1D + detail * 0.2D;
|
||||
double position = x * directionX + y * directionY + z * directionZ;
|
||||
double ridge = Math.sin(TAU * (position + warp) + phase);
|
||||
double vein = 1D / (1D + 90D * ridge * ridge);
|
||||
double stone = 0.85D + 0.15D * broad;
|
||||
return Math.clamp(0.1D + 0.84D * stone * (1D - vein), 0D, 1D);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
public final class MengerSpongeNoise extends PatternNoise {
|
||||
private static final int DEPTH = 3;
|
||||
|
||||
private final double phaseX;
|
||||
private final double phaseY;
|
||||
private final double phaseZ;
|
||||
|
||||
public MengerSpongeNoise(long seed) {
|
||||
long hash = mix(seed);
|
||||
phaseX = (hash & 0x1FFFFFL) * 0x1.0p-21D;
|
||||
phaseY = ((hash >>> 21) & 0x1FFFFFL) * (0x1.0p-21D / 3D);
|
||||
phaseZ = (hash >>> 42) * 0x1.0p-22D;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
x += phaseX;
|
||||
y += phaseY;
|
||||
z += phaseZ;
|
||||
x -= Math.floor(x);
|
||||
y -= Math.floor(y);
|
||||
z -= Math.floor(z);
|
||||
for (int level = 0; level < DEPTH; level++) {
|
||||
x *= 3D;
|
||||
y *= 3D;
|
||||
z *= 3D;
|
||||
int cellX = (int) x;
|
||||
int cellY = (int) y;
|
||||
int cellZ = (int) z;
|
||||
int middleAxes = (cellX == 1 ? 1 : 0) + (cellY == 1 ? 1 : 0) + (cellZ == 1 ? 1 : 0);
|
||||
if (middleAxes >= 2) {
|
||||
return 0D;
|
||||
}
|
||||
x -= cellX;
|
||||
y -= cellY;
|
||||
z -= cellZ;
|
||||
}
|
||||
return 1D;
|
||||
}
|
||||
|
||||
private static long mix(long value) {
|
||||
value = (value ^ (value >>> 30)) * 0xBF58476D1CE4E5B9L;
|
||||
value = (value ^ (value >>> 27)) * 0x94D049BB133111EBL;
|
||||
return value ^ (value >>> 31);
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,17 @@ public enum NoiseType {
|
||||
QUASICRYSTAL(QuasicrystalNoise::new, 1D / 64D),
|
||||
TRUCHET(TruchetNoise::new, 1D / 64D),
|
||||
CRATER(CraterNoise::new, 1D / 64D),
|
||||
VORTEX(VortexNoise::new, 1D / 64D);
|
||||
VORTEX(VortexNoise::new, 1D / 64D),
|
||||
DUNE(DuneNoise::new, 1D / 64D),
|
||||
STRATA(StrataNoise::new, 1D / 64D),
|
||||
WOOD(WoodNoise::new, 1D / 64D),
|
||||
GABOR(GaborNoise::new, 1D / 64D),
|
||||
MARBLE(MarbleNoise::new, 1D / 64D),
|
||||
SCALES(ScalesNoise::new, 1D / 64D),
|
||||
CHLADNI(ChladniNoise::new, 1D / 64D),
|
||||
KALEIDOSCOPE(KaleidoscopeNoise::new, 1D / 64D),
|
||||
MENGER_SPONGE(MengerSpongeNoise::new, 1D / 64D),
|
||||
CIRCUIT(CircuitNoise::new, 1D / 64D);
|
||||
|
||||
private final NoiseFactory f;
|
||||
private final double coordinateScale;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
public final class ScalesNoise extends PatternNoise {
|
||||
private static final double TAU = Math.PI * 2D;
|
||||
private static final double RADIUS = 0.5D;
|
||||
private static final double ROW_HEIGHT = 0.5D;
|
||||
private static final double GROOVE_WIDTH = 0.055D;
|
||||
|
||||
private final long seed;
|
||||
private final double phaseX;
|
||||
private final double phaseZ;
|
||||
|
||||
public ScalesNoise(long seed) {
|
||||
this.seed = seed;
|
||||
phaseX = (mix(seed) >>> 11) * 0x1.0p-53D;
|
||||
phaseZ = (mix(seed + 0x9E3779B97F4A7C15L) >>> 11) * 0x1.0p-53D;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
x += phaseX + Math.sin(y * TAU * 0.5D) * 0.22D + y * 0.15D;
|
||||
z += phaseZ + Math.sin(y * TAU * 0.25D) * 0.12D + y * 0.2D;
|
||||
long row = (long) Math.floor(z / ROW_HEIGHT);
|
||||
double groove = 0D;
|
||||
double shade = 0D;
|
||||
for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
|
||||
long pointZ = row + offsetZ;
|
||||
double shift = (pointZ & 1L) * 0.5D;
|
||||
long column = (long) Math.floor(x - shift);
|
||||
double dz = z - pointZ * ROW_HEIGHT;
|
||||
for (int offsetX = -1; offsetX <= 1; offsetX++) {
|
||||
long pointX = column + offsetX;
|
||||
double dx = x - (pointX + shift);
|
||||
double radiusSquared = dx * dx + dz * dz;
|
||||
double distance;
|
||||
if (dz >= 0D) {
|
||||
distance = Math.abs(Math.sqrt(radiusSquared) - RADIUS);
|
||||
} else {
|
||||
double endpoint = Math.abs(dx) - RADIUS;
|
||||
distance = Math.sqrt(endpoint * endpoint + dz * dz);
|
||||
}
|
||||
double rim = Math.max(0D, 1D - distance / GROOVE_WIDTH);
|
||||
if (rim > 0D || radiusSquared < RADIUS * RADIUS && dz > 0D) {
|
||||
long hash = mix(seed ^ pointX * 0x9E3779B97F4A7C15L ^ pointZ * 0xC2B2AE3D27D4EB4FL);
|
||||
double variation = 0.75D + (hash >>> 11) * 0x1.0p-53D * 0.25D;
|
||||
groove = Math.max(groove, rim * rim * (3D - 2D * rim) * variation);
|
||||
double inside = Math.max(0D, 1D - radiusSquared / (RADIUS * RADIUS));
|
||||
double rise = Math.clamp(dz / 0.12D, 0D, 1D);
|
||||
shade = Math.max(shade, inside * rise * rise * (3D - 2D * rise) * variation);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0.72D + 0.22D * shade - 0.65D * groove;
|
||||
}
|
||||
|
||||
private static long mix(long value) {
|
||||
value = (value ^ (value >>> 30)) * 0xBF58476D1CE4E5B9L;
|
||||
value = (value ^ (value >>> 27)) * 0x94D049BB133111EBL;
|
||||
return value ^ (value >>> 31);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
|
||||
public final class StrataNoise extends PatternNoise {
|
||||
private static final double TAU = Math.PI * 2D;
|
||||
|
||||
private final double cosine;
|
||||
private final double sine;
|
||||
private final double phaseA;
|
||||
private final double phaseB;
|
||||
private final double phaseC;
|
||||
|
||||
public StrataNoise(long seed) {
|
||||
SplittableRandom random = new SplittableRandom(seed);
|
||||
double angle = random.nextDouble(TAU);
|
||||
cosine = Math.cos(angle);
|
||||
sine = Math.sin(angle);
|
||||
phaseA = random.nextDouble(TAU);
|
||||
phaseB = random.nextDouble(TAU);
|
||||
phaseC = random.nextDouble(TAU);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
double along = x * cosine + z * sine;
|
||||
double across = z * cosine - x * sine;
|
||||
double fold = 1.1D * Math.sin(along * 1.1D + phaseA)
|
||||
+ 0.35D * Math.sin(along * 2.7D + across * 0.8D + phaseB + y * 0.4D)
|
||||
+ 0.2D * Math.sin(across * 1.7D + y * 0.9D + phaseC);
|
||||
double layer = TAU * (across + y * 0.75D + fold);
|
||||
double thickness = layer + 0.55D * Math.sin(layer * 0.25D + phaseB);
|
||||
double broadBand = 0.5D + 0.5D * Math.sin(thickness);
|
||||
double lamina = 0.5D + 0.5D * Math.sin(thickness * 3D + phaseC);
|
||||
return 0.82D * broadBand + 0.18D * lamina;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package art.arcane.iris.util.project.noise;
|
||||
|
||||
public final class WoodNoise extends PatternNoise {
|
||||
private static final double TAU = Math.PI * 2D;
|
||||
|
||||
private final long seed;
|
||||
private final double cosine;
|
||||
private final double sine;
|
||||
private final double phase;
|
||||
|
||||
public WoodNoise(long seed) {
|
||||
this.seed = seed;
|
||||
phase = (mix(seed) >>> 11) * 0x1.0p-53D * TAU;
|
||||
cosine = Math.cos(phase);
|
||||
sine = Math.sin(phase);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double sample(double x, double y, double z) {
|
||||
double along = (z * cosine - x * sine) * 0.45D + y * 0.17D;
|
||||
double across = x * cosine + z * sine + y * 0.07D + 0.11D * Math.sin(along * 0.85D + phase);
|
||||
double grainPhase = across * TAU * 3D + 0.18D * Math.sin(along * 2.1D + phase);
|
||||
double value = 0.12D * (0.5D + 0.5D * Math.sin(grainPhase));
|
||||
double weightSum = 0.12D;
|
||||
long cellAcross = (long) Math.floor(across);
|
||||
long cellAlong = (long) Math.floor(along);
|
||||
for (int offsetAcross = -1; offsetAcross <= 1; offsetAcross++) {
|
||||
long gridAcross = cellAcross + offsetAcross;
|
||||
for (int offsetAlong = -1; offsetAlong <= 1; offsetAlong++) {
|
||||
long gridAlong = cellAlong + offsetAlong;
|
||||
long hash = mix(seed ^ gridAcross * 0x9E3779B97F4A7C15L ^ gridAlong * 0xD1B54A32D192ED03L);
|
||||
double deltaAcross = across - (gridAcross + 0.3D + (hash & 65535L) * (0.4D / 65535D));
|
||||
double deltaAlong = along - (gridAlong + 0.3D + ((hash >>> 16) & 65535L) * (0.4D / 65535D));
|
||||
double radius = 0.5D + ((hash >>> 32) & 255L) * (0.12D / 255D);
|
||||
double distanceSquared = deltaAcross * deltaAcross + deltaAlong * deltaAlong;
|
||||
double envelope = 1D - distanceSquared / (radius * radius);
|
||||
if (envelope <= 0D) {
|
||||
continue;
|
||||
}
|
||||
double rings = Math.sqrt(distanceSquared + 0.0004D) * TAU * 5D;
|
||||
double ringPhase = ((hash >>> 40) & 65535L) * (TAU / 65535D);
|
||||
double knot = 0.5D + 0.5D * Math.sin(rings + ringPhase);
|
||||
double weight = 3D * envelope * envelope;
|
||||
value += knot * weight;
|
||||
weightSum += weight;
|
||||
}
|
||||
}
|
||||
return value / weightSum;
|
||||
}
|
||||
|
||||
private static long mix(long value) {
|
||||
value = (value ^ (value >>> 30)) * 0xBF58476D1CE4E5B9L;
|
||||
value = (value ^ (value >>> 27)) * 0x94D049BB133111EBL;
|
||||
return value ^ (value >>> 31);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user