From b52017625d1c6510faecea11d071fd7008227075 Mon Sep 17 00:00:00 2001 From: cyberpwn Date: Fri, 12 Nov 2021 06:24:47 -0500 Subject: [PATCH] Cellularize things --- .../volmit/iris/engine/object/NoiseStyle.java | 17 ++++ .../iris/util/noise/BiasedCellularNoise.java | 52 ++++++++++ .../com/volmit/iris/util/noise/FastNoise.java | 94 +++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 src/main/java/com/volmit/iris/util/noise/BiasedCellularNoise.java diff --git a/src/main/java/com/volmit/iris/engine/object/NoiseStyle.java b/src/main/java/com/volmit/iris/engine/object/NoiseStyle.java index ec9d75887..508049f16 100644 --- a/src/main/java/com/volmit/iris/engine/object/NoiseStyle.java +++ b/src/main/java/com/volmit/iris/engine/object/NoiseStyle.java @@ -20,6 +20,7 @@ package com.volmit.iris.engine.object; import com.volmit.iris.engine.object.annotations.Desc; import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.BiasedCellularNoise; import com.volmit.iris.util.noise.CNG; import com.volmit.iris.util.noise.CNGFactory; import com.volmit.iris.util.noise.NoiseType; @@ -447,6 +448,22 @@ public enum NoiseStyle { @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)), + @Desc("White Noise is like static. Useful for block scattering but not terrain.") + SIMPLEX_BIASED_CELLULAR(rng -> new CNG(rng, new BiasedCellularNoise(rng.lmax(), + SIMPLEX.stream(rng.nextParallelRNG(-23333666)).zoom(0.158)), 1D, 1)), + + @Desc("White Noise is like static. Useful for block scattering but not terrain.") + NOWHERE_BIASED_CELLULAR(rng -> new CNG(rng, new BiasedCellularNoise(rng.lmax(), + NOWHERE.stream(rng.nextParallelRNG(-23333666)).zoom(0.158)), 1D, 1)), + + @Desc("White Noise is like static. Useful for block scattering but not terrain.") + IRIS_BIASED_CELLULAR(rng -> new CNG(rng, new BiasedCellularNoise(rng.lmax(), + IRIS.stream(rng.nextParallelRNG(-23333666)).zoom(0.158)), 1D, 1)), + + @Desc("White Noise is like static. Useful for block scattering but not terrain.") + VASCULAR_BIASED_CELLULAR(rng -> new CNG(rng, new BiasedCellularNoise(rng.lmax(), + VASCULAR.stream(rng.nextParallelRNG(-23333666)).zoom(0.158)), 1D, 1)), + ; private final CNGFactory f; diff --git a/src/main/java/com/volmit/iris/util/noise/BiasedCellularNoise.java b/src/main/java/com/volmit/iris/util/noise/BiasedCellularNoise.java new file mode 100644 index 000000000..5742bb13b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/noise/BiasedCellularNoise.java @@ -0,0 +1,52 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.noise; + +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.interpolation.IrisInterpolation; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.stream.ProceduralStream; + +public class BiasedCellularNoise implements NoiseGenerator { + private final FastNoise n; + private final ProceduralStream biasShape; + + public BiasedCellularNoise(long seed, ProceduralStream biasShape) { + this.biasShape = biasShape.subtract(0.5).multiply(2); + this.n = new FastNoise(new RNG(seed).imax()); + n.SetNoiseType(FastNoise.NoiseType.Cellular); + n.SetCellularReturnType(FastNoise.CellularReturnType.CellValue); + n.SetCellularDistanceFunction(FastNoise.CellularDistanceFunction.Natural); + } + + @Override + public double noise(double x) { + return (n.GetCellular((float) x, (float) 0, biasShape) / 2D) + 0.5D; + } + + @Override + public double noise(double x, double z) { + return (n.GetCellular((float) x, (float) z, biasShape) / 2D) + 0.5D; + } + + @Override + public double noise(double x, double y, double z) { + return (n.GetCellular((float) x, (float) y, biasShape) / 2D) + 0.5D; + } +} diff --git a/src/main/java/com/volmit/iris/util/noise/FastNoise.java b/src/main/java/com/volmit/iris/util/noise/FastNoise.java index 23e21deb7..548b4720d 100644 --- a/src/main/java/com/volmit/iris/util/noise/FastNoise.java +++ b/src/main/java/com/volmit/iris/util/noise/FastNoise.java @@ -20,6 +20,7 @@ package com.volmit.iris.util.noise; import com.volmit.iris.util.math.Vector2f; import com.volmit.iris.util.math.Vector3f; +import com.volmit.iris.util.stream.ProceduralStream; public class FastNoise { private static final Float2[] GRAD_2D = {new Float2(-1, -1), new Float2(1, -1), new Float2(-1, 1), new Float2(1, 1), new Float2(0, -1), new Float2(-1, 0), new Float2(0, 1), new Float2(1, 0), @@ -1728,6 +1729,19 @@ public class FastNoise { return 0; } } + public float GetCellular(float x, float y, ProceduralStream sourceNoise) { + x *= m_frequency; + y *= m_frequency; + + switch (m_cellularReturnType) { + case CellValue: + case NoiseLookup: + case Distance: + return SingleCellular(x, y, sourceNoise); + default: + return SingleCellular2Edge(x, y); + } + } public float GetCellular(float x, float y) { x *= m_frequency; @@ -1823,6 +1837,86 @@ public class FastNoise { } } + private float SingleCellular(float x, float y, ProceduralStream sourceNoise) { + int xr = FastRound(x); + int yr = FastRound(y); + + float distance = 999999; + int xc = 0, yc = 0; + + switch (m_cellularDistanceFunction) { + default: + case Euclidean: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + + float newDistance = vecX * vecX + vecY * vecY; + + if (newDistance < distance) { + distance = newDistance; + xc = xi; + yc = yi; + } + } + } + break; + case Manhattan: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + + float newDistance = (Math.abs(vecX) + Math.abs(vecY)); + + if (newDistance < distance) { + distance = newDistance; + xc = xi; + yc = yi; + } + } + } + break; + case Natural: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + + float newDistance = (Math.abs(vecX) + Math.abs(vecY)) + (vecX * vecX + vecY * vecY); + + if (newDistance < distance) { + distance = newDistance; + xc = xi; + yc = yi; + } + } + } + break; + } + + switch (m_cellularReturnType) { + case CellValue: + return sourceNoise.get(xc, yc).floatValue(); + + case NoiseLookup: + Float2 vec = CELL_2D[Hash2D(m_seed, xc, yc) & 255]; + return m_cellularNoiseLookup.GetNoise(xc + vec.x, yc + vec.y); + + case Distance: + return distance - 1; + default: + return 0; + } + } + private float SingleCellular2Edge(float x, float y) { int xr = FastRound(x); int yr = FastRound(y);