diff --git a/pom.xml b/pom.xml index ad53524d0..d745c3174 100644 --- a/pom.xml +++ b/pom.xml @@ -150,6 +150,22 @@ 1.15.1-R0.1-SNAPSHOT provided + + javax.vecmath + vecmath + 1.5.2 + + + com.google.code.gson + gson + 2.8.5 + + + org.projectlombok + lombok + 1.18.10 + provided + org.bukkit bukkit diff --git a/src/main/java/ninja/bytecode/iris/Iris.java b/src/main/java/ninja/bytecode/iris/Iris.java index 67e3d4112..08ed6bd3c 100644 --- a/src/main/java/ninja/bytecode/iris/Iris.java +++ b/src/main/java/ninja/bytecode/iris/Iris.java @@ -4,6 +4,7 @@ import java.io.File; import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.World; @@ -18,6 +19,10 @@ import ninja.bytecode.iris.util.IO; public class Iris extends JavaPlugin { + public static Iris instance; + public static IrisDataManager data; + public static IrisHotloadManager hotloader; + public Iris() { IO.delete(new File("iris")); @@ -25,7 +30,9 @@ public class Iris extends JavaPlugin public void onEnable() { - + instance = this; + hotloader = new IrisHotloadManager(); + data = new IrisDataManager(getDataFolder()); Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> { for(World i : Bukkit.getWorlds()) @@ -36,7 +43,7 @@ public class Iris extends JavaPlugin } } - World world = Bukkit.createWorld(new WorldCreator("iris/" + UUID.randomUUID()).generator(new IrisGenerator())); + World world = Bukkit.createWorld(new WorldCreator("iris/" + UUID.randomUUID()).generator(new IrisGenerator("overworld"))); for(Player i : Bukkit.getOnlinePlayers()) { @@ -48,6 +55,7 @@ public class Iris extends JavaPlugin }, 5); } }); + } public void onDisable() @@ -64,6 +72,36 @@ public class Iris extends JavaPlugin @Override public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { - return new IrisGenerator(); + return new IrisGenerator("overworld"); + } + + public static void msg(String string) + { + Bukkit.getConsoleSender().sendMessage(ChatColor.GREEN + "[Iris]: " + ChatColor.GRAY + string); + } + + public static void warn(String string) + { + msg(ChatColor.YELLOW + string); + } + + public static void error(String string) + { + msg(ChatColor.RED + string); + } + + public static void verbose(String string) + { + msg(ChatColor.GRAY + string); + } + + public static void success(String string) + { + msg(ChatColor.GREEN + string); + } + + public static void info(String string) + { + msg(ChatColor.WHITE + string); } } diff --git a/src/main/java/ninja/bytecode/iris/IrisDataManager.java b/src/main/java/ninja/bytecode/iris/IrisDataManager.java new file mode 100644 index 000000000..6037ec298 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/IrisDataManager.java @@ -0,0 +1,104 @@ +package ninja.bytecode.iris; + +import java.io.File; + +import org.bukkit.World.Environment; +import org.bukkit.block.Biome; + +import com.google.gson.Gson; + +import lombok.Getter; +import ninja.bytecode.iris.object.Dispersion; +import ninja.bytecode.iris.object.IrisBiome; +import ninja.bytecode.iris.object.IrisBiomePaletteLayer; +import ninja.bytecode.iris.object.IrisDimension; +import ninja.bytecode.iris.util.IO; +import ninja.bytecode.iris.util.JSONObject; +import ninja.bytecode.iris.util.ResourceLoader; + +public class IrisDataManager +{ + private File dataFolder; + private File packs; + + @Getter + private ResourceLoader biomeLoader; + + @Getter + private ResourceLoader dimensionLoader; + + public void hotloaded() + { + packs.mkdirs(); + this.biomeLoader = new ResourceLoader<>(packs, "biomes", "Biome", IrisBiome.class); + this.dimensionLoader = new ResourceLoader<>(packs, "dimensions", "Dimension", IrisDimension.class); + writeExamples(); + } + + public IrisDataManager(File dataFolder) + { + this.dataFolder = dataFolder; + this.packs = new File(dataFolder, "packs"); + hotloaded(); + } + + private void writeExamples() + { + File examples = new File(dataFolder, "example"); + examples.mkdirs(); + + IrisBiome biome = new IrisBiome(); + biome.getLayers().clear(); + IrisBiomePaletteLayer grass = new IrisBiomePaletteLayer(); + grass.add("GRASS_BLOCK"); + grass.setDispersion(Dispersion.SCATTER); + grass.setMinHeight(1); + grass.setMaxHeight(1); + IrisBiomePaletteLayer dirt = new IrisBiomePaletteLayer(); + grass.add("DIRT"); + grass.setDispersion(Dispersion.SCATTER); + grass.setMinHeight(1); + grass.setMaxHeight(2); + IrisBiomePaletteLayer dirtThick = new IrisBiomePaletteLayer(); + grass.add("DIRT"); + grass.add("COARSE_DIRT"); + grass.setDispersion(Dispersion.WISPY); + grass.setMinHeight(1); + grass.setMaxHeight(3); + + biome.getLayers().add(dirtThick); + biome.getLayers().add(dirt); + biome.getLayers().add(grass); + + IrisDimension dim = new IrisDimension(); + dim.getBiomes().add("a_biome"); + String biomes = ""; + String envs = ""; + + for(Biome i : Biome.values()) + { + biomes += i.name() + "\n"; + } + + for(Environment i : Environment.values()) + { + envs += i.name() + "\n"; + } + + try + { + new File(examples, "example-pack/biomes").mkdirs(); + new File(examples, "example-pack/dimensions").mkdirs(); + IO.writeAll(new File(examples, "biome-list.txt"), biomes); + IO.writeAll(new File(examples, "environment-list.txt"), envs); + IO.writeAll(new File(examples, "example-pack/biomes/a_biome.json"), new JSONObject(new Gson().toJson(biome)).toString(4)); + IO.writeAll(new File(examples, "example-pack/dimensions/a_dimension.json"), new JSONObject(new Gson().toJson(dim)).toString(4)); + } + + catch(Throwable e) + { + + } + + } +} \ No newline at end of file diff --git a/src/main/java/ninja/bytecode/iris/IrisGenerator.java b/src/main/java/ninja/bytecode/iris/IrisGenerator.java index 40cf7b5bd..e457583a2 100644 --- a/src/main/java/ninja/bytecode/iris/IrisGenerator.java +++ b/src/main/java/ninja/bytecode/iris/IrisGenerator.java @@ -2,6 +2,7 @@ package ninja.bytecode.iris; import java.util.List; import java.util.Random; +import java.util.function.Function; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -11,17 +12,34 @@ import org.bukkit.block.data.BlockData; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; +import ninja.bytecode.iris.layer.GenLayerBiome; +import ninja.bytecode.iris.object.IrisBiome; +import ninja.bytecode.iris.object.IrisDimension; +import ninja.bytecode.iris.util.BiomeResult; import ninja.bytecode.iris.util.CNG; -import ninja.bytecode.iris.util.PolygonGenerator.EnumPolygonGenerator; +import ninja.bytecode.iris.util.IrisInterpolation; +import ninja.bytecode.iris.util.KList; import ninja.bytecode.iris.util.RNG; public class IrisGenerator extends ChunkGenerator { + // TODO REMOVE OR FIND A BETTER PLACE + private BlockData STONE = Material.STONE.createBlockData(); + private String dimensionName; + private GenLayerBiome glBiome; + private CNG terrainNoise; + private boolean initialized = false; - private CNG gen; - private EnumPolygonGenerator pog; - private BlockData[] d = {Material.RED_CONCRETE.createBlockData(), Material.GREEN_CONCRETE.createBlockData(), Material.BLUE_CONCRETE.createBlockData(), - }; + + public IrisGenerator(String dimensionName) + { + this.dimensionName = dimensionName; + } + + public IrisDimension getDimension() + { + return Iris.data.getDimensionLoader().load(dimensionName); + } public void onInit(World world, RNG rng) { @@ -31,8 +49,8 @@ public class IrisGenerator extends ChunkGenerator } initialized = true; - gen = CNG.signature(rng.nextParallelRNG(0)); - pog = new EnumPolygonGenerator(rng.nextParallelRNG(1), 0.1, 1, d, (c) -> c); + glBiome = new GenLayerBiome(this, rng.nextParallelRNG(1)); + terrainNoise = CNG.signature(rng.nextParallelRNG(2)); } @Override @@ -42,26 +60,56 @@ public class IrisGenerator extends ChunkGenerator } @Override - public ChunkData generateChunkData(World world, Random no, int x, int z, BiomeGrid biome) + public ChunkData generateChunkData(World world, Random no, int x, int z, BiomeGrid biomeGrid) { + Iris.hotloader.check(); + int i, j, k, height, depth; + double wx, wz, rx, rz, heightLow, heightHigh, heightExponent; + int fluidHeight = getDimension().getFluidHeight(); + BiomeResult biomeResult; + IrisBiome biome; RNG random = new RNG(world.getSeed()); onInit(world, random.nextParallelRNG(0)); ChunkData data = Bukkit.createChunkData(world); - for(int i = 0; i < 16; i++) + for(i = 0; i < 16; i++) { - for(int j = 0; j < 16; j++) + rx = (x * 16) + i; + wx = ((double) (x * 16) + i) / getDimension().getTerrainZoom(); + for(j = 0; j < 16; j++) { - double wx = (x * 16) + i; - double wz = (z * 16) + j; + rz = (z * 16) + j; + wz = ((double) (z * 16) + j) / getDimension().getTerrainZoom(); + depth = 0; + biomeResult = glBiome.generateData(wx, wz); + biome = biomeResult.getBiome(); + heightLow = interpolate(rx, rz, (b) -> b.getLowHeight()); + heightHigh = interpolate(rx, rz, (b) -> b.getHighHeight()); + heightExponent = interpolate(rx, rz, (b) -> b.getHeightExponent()); + height = (int) Math.round(terrainNoise.fitDoubleExponent(heightLow, heightHigh, heightExponent, wx, wz)) + fluidHeight; + KList layers = biome.generateLayers(wx, wz, random, height); - data.setBlock(i, 0, j, pog.getChoice(wx, wz)); + for(k = Math.max(height, fluidHeight); k >= 0; k--) + { + biomeGrid.setBiome(i, k, j, biome.getDerivative()); + data.setBlock(i, k, j, layers.hasIndex(depth) ? layers.get(depth) : STONE); + depth++; + } } } return data; } + public double interpolate(double rx, double rz, Function property) + { + return IrisInterpolation.getNoise(getDimension().getInterpolationFunction(), (int) Math.round(rx), (int) Math.round(rz), getDimension().getInterpolationScale(), (xx, zz) -> + { + BiomeResult neighborResult = glBiome.generateData(xx / getDimension().getTerrainZoom(), zz / getDimension().getTerrainZoom()); + return property.apply(neighborResult.getBiome()); + }); + } + @Override public List getDefaultPopulators(World world) { diff --git a/src/main/java/ninja/bytecode/iris/IrisHotloadManager.java b/src/main/java/ninja/bytecode/iris/IrisHotloadManager.java new file mode 100644 index 000000000..18679d2e7 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/IrisHotloadManager.java @@ -0,0 +1,57 @@ +package ninja.bytecode.iris; + +import java.io.File; + +import org.bukkit.Bukkit; + +import ninja.bytecode.iris.util.ChronoLatch; +import ninja.bytecode.iris.util.FileWatcher; +import ninja.bytecode.iris.util.KList; + +public class IrisHotloadManager +{ + private ChronoLatch latch; + private KList watchers; + + public IrisHotloadManager() + { + watchers = new KList<>(); + latch = new ChronoLatch(3000); + } + + public void check() + { + if(!latch.flip()) + { + return; + } + + Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () -> + { + boolean modified = false; + int c = 0; + + for(FileWatcher i : watchers) + { + if(i.checkModified()) + { + c++; + Iris.info("File Modified: " + i.getFile().getPath()); + modified = true; + } + } + + if(modified) + { + watchers.clear(); + Iris.success("Hotloading Iris (" + c + " File" + (c == 1 ? "" : "s") + " changed)"); + Iris.data.hotloaded(); + } + }); + } + + public void track(File file) + { + watchers.add(new FileWatcher(file)); + } +} diff --git a/src/main/java/ninja/bytecode/iris/layer/GenLayerBiome.java b/src/main/java/ninja/bytecode/iris/layer/GenLayerBiome.java new file mode 100644 index 000000000..d78b03630 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/layer/GenLayerBiome.java @@ -0,0 +1,36 @@ +package ninja.bytecode.iris.layer; + +import ninja.bytecode.iris.IrisGenerator; +import ninja.bytecode.iris.object.IrisBiome; +import ninja.bytecode.iris.util.BiomeResult; +import ninja.bytecode.iris.util.CellGenerator2D; +import ninja.bytecode.iris.util.GenLayer; +import ninja.bytecode.iris.util.KList; +import ninja.bytecode.iris.util.RNG; + +public class GenLayerBiome extends GenLayer +{ + private CellGenerator2D cells; + + public GenLayerBiome(IrisGenerator iris, RNG rng) + { + super(iris, rng); + cells = new CellGenerator2D(rng.nextParallelRNG(2045662)); + } + + public KList getBiomes() + { + return iris.getDimension().buildBiomeList(); + } + + public BiomeResult generateData(double x, double z) + { + return new BiomeResult(getBiomes().get(cells.getIndex(x / iris.getDimension().getBiomeZoom(), z / iris.getDimension().getBiomeZoom(), getBiomes().size())), cells.getDistance(x / iris.getDimension().getBiomeZoom(), z / iris.getDimension().getBiomeZoom())); + } + + @Override + public double generate(double x, double z) + { + return 0; + } +} diff --git a/src/main/java/ninja/bytecode/iris/object/Dispersion.java b/src/main/java/ninja/bytecode/iris/object/Dispersion.java new file mode 100644 index 000000000..35dc195c6 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/object/Dispersion.java @@ -0,0 +1,10 @@ +package ninja.bytecode.iris.object; + +public enum Dispersion +{ + SCATTER, + SIMPLEX, + CELLS, + WISPY, + ZEBRA +} diff --git a/src/main/java/ninja/bytecode/iris/object/InterpolationMethod.java b/src/main/java/ninja/bytecode/iris/object/InterpolationMethod.java new file mode 100644 index 000000000..e7e03bcc6 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/object/InterpolationMethod.java @@ -0,0 +1,9 @@ +package ninja.bytecode.iris.object; + +public enum InterpolationMethod +{ + NONE, + BILINEAR, + BICUBIC, + HERMITE +} diff --git a/src/main/java/ninja/bytecode/iris/object/IrisBiome.java b/src/main/java/ninja/bytecode/iris/object/IrisBiome.java new file mode 100644 index 000000000..f099d1ac7 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/object/IrisBiome.java @@ -0,0 +1,107 @@ +package ninja.bytecode.iris.object; + +import java.util.List; + +import org.bukkit.block.Biome; +import org.bukkit.block.data.BlockData; + +import lombok.Data; +import ninja.bytecode.iris.util.CNG; +import ninja.bytecode.iris.util.KList; +import ninja.bytecode.iris.util.RNG; + +@Data +public class IrisBiome +{ + private String name = "A Biome"; + private Biome derivative = Biome.THE_VOID; + private double highHeight = 7; + private double lowHeight = 1; + private double heightExponent = 1; + private KList layers = new KList().qadd(new IrisBiomePaletteLayer()); + + private transient KList layerHeightGenerators; + private transient KList layerSurfaceGenerators; + + public KList generateLayers(double wx, double wz, RNG random, int maxDepth) + { + KList data = new KList<>(); + + for(int i = 0; i < layers.size(); i++) + { + CNG hgen = getLayerHeightGenerators(random).get(i); + CNG sgen = getLayerSurfaceGenerators(random).get(i); + int d = hgen.fit(layers.get(i).getMinHeight(), layers.get(i).getMaxHeight(), wx / layers.get(i).getTerrainZoom(), wz / layers.get(i).getTerrainZoom()); + + if(d < 0) + { + continue; + } + + List palette = getLayers().get(i).getBlockData(); + + for(int j = 0; j < d; j++) + { + if(data.size() >= maxDepth) + { + break; + } + + data.add(palette.get(sgen.fit(0, palette.size() - 1, (wx + j) / layers.get(i).getTerrainZoom(), (wz - j) / layers.get(i).getTerrainZoom()))); + } + + if(data.size() >= maxDepth) + { + break; + } + } + + return data; + } + + public KList getLayerSurfaceGenerators(RNG rng) + { + synchronized(this) + { + if(layerSurfaceGenerators == null) + { + layerSurfaceGenerators = new KList<>(); + + synchronized(layerSurfaceGenerators) + { + int m = 91235; + + for(IrisBiomePaletteLayer i : getLayers()) + { + layerSurfaceGenerators.add(i.getGenerator(rng.nextParallelRNG((m += 3) * m * m * m))); + } + } + } + } + + return layerSurfaceGenerators; + } + + public KList getLayerHeightGenerators(RNG rng) + { + synchronized(this) + { + if(layerHeightGenerators == null) + { + layerHeightGenerators = new KList<>(); + + synchronized(layerHeightGenerators) + { + int m = 7235; + + for(IrisBiomePaletteLayer i : getLayers()) + { + layerHeightGenerators.add(i.getGenerator(rng.nextParallelRNG((m++) * m * m * m))); + } + } + } + } + + return layerHeightGenerators; + } +} diff --git a/src/main/java/ninja/bytecode/iris/object/IrisBiomePaletteLayer.java b/src/main/java/ninja/bytecode/iris/object/IrisBiomePaletteLayer.java new file mode 100644 index 000000000..a4126cc97 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/object/IrisBiomePaletteLayer.java @@ -0,0 +1,85 @@ +package ninja.bytecode.iris.object; + +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; + +import lombok.Data; +import ninja.bytecode.iris.util.CNG; +import ninja.bytecode.iris.util.KList; +import ninja.bytecode.iris.util.KMap; +import ninja.bytecode.iris.util.RNG; + +@Data +public class IrisBiomePaletteLayer +{ + private Dispersion dispersion = Dispersion.WISPY; + private int minHeight = 1; + private int maxHeight = 1; + private double terrainZoom = 5; + private KList palette = new KList().qadd("GRASS_BLOCK"); + + private transient KMap layerGenerators; + private transient KList blockData; + + public CNG getGenerator(RNG rng) + { + synchronized(this) + { + long key = rng.nextParallelRNG(1).nextLong(); + + if(layerGenerators == null) + { + layerGenerators = new KMap<>(); + } + + if(!layerGenerators.containsKey(key)) + { + synchronized(layerGenerators) + { + layerGenerators.put(key, CNG.signature(rng.nextParallelRNG(minHeight + maxHeight + getBlockData().size()))); + } + } + + return layerGenerators.get(key); + } + } + + public KList add(String b) + { + palette.add(b); + + return palette; + } + + public KList getBlockData() + { + synchronized(this) + { + if(blockData == null) + { + blockData = new KList<>(); + synchronized(blockData) + { + for(String i : palette) + { + try + { + Material m = Material.valueOf(i); + + if(m != null) + { + blockData.add(m.createBlockData()); + } + } + catch(Throwable e) + { + + } + } + } + } + } + + return blockData; + } +} diff --git a/src/main/java/ninja/bytecode/iris/object/IrisDimension.java b/src/main/java/ninja/bytecode/iris/object/IrisDimension.java new file mode 100644 index 000000000..502762380 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/object/IrisDimension.java @@ -0,0 +1,48 @@ +package ninja.bytecode.iris.object; + +import org.bukkit.World.Environment; + +import lombok.Data; +import ninja.bytecode.iris.Iris; +import ninja.bytecode.iris.util.KList; + +@Data +public class IrisDimension +{ + private String name = "A Dimension"; + private InterpolationMethod interpolationFunction = InterpolationMethod.BILINEAR; + private double interpolationScale = 5.6; + private Environment environment = Environment.NORMAL; + private KList biomes = new KList<>(); + private int fluidHeight = 127; + private double biomeZoom = 5D; + private double terrainZoom = 2D; + private double roughnessZoom = 2D; + private int roughnessHeight = 3; + private transient KList biomeCache; + + public KList buildBiomeList() + { + if(biomeCache == null) + { + synchronized(this) + { + biomeCache = new KList<>(); + + synchronized(biomeCache) + { + for(String i : biomes) + { + IrisBiome biome = Iris.data.getBiomeLoader().load(i); + if(biome != null) + { + biomeCache.add(biome); + } + } + } + } + } + + return biomeCache; + } +} diff --git a/src/main/java/ninja/bytecode/iris/util/BiomeResult.java b/src/main/java/ninja/bytecode/iris/util/BiomeResult.java new file mode 100644 index 000000000..91c81e61d --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/BiomeResult.java @@ -0,0 +1,17 @@ +package ninja.bytecode.iris.util; + +import lombok.Data; +import ninja.bytecode.iris.object.IrisBiome; + +@Data +public class BiomeResult +{ + private IrisBiome biome; + private double distance; + + public BiomeResult(IrisBiome biome, double distance) + { + this.biome = biome; + this.distance = distance; + } +} \ No newline at end of file diff --git a/src/main/java/ninja/bytecode/iris/util/CNG.java b/src/main/java/ninja/bytecode/iris/util/CNG.java index a4d8dc576..c41df5b6c 100644 --- a/src/main/java/ninja/bytecode/iris/util/CNG.java +++ b/src/main/java/ninja/bytecode/iris/util/CNG.java @@ -25,6 +25,9 @@ public class CNG private NoiseInjector injector; private RNG rng; private int oct; + private double patch; + private double up; + private double down; private double power; public static CNG signature(RNG rng) @@ -32,14 +35,12 @@ public class CNG //@builder return new CNG(rng.nextParallelRNG(17), 1D, 8) .scale(0.012) - .amp(0.5) - .freq(1.1) .fractureWith(new CNG(rng.nextParallelRNG(18), 1, 5) .scale(0.018) - .child(new CNG(rng.nextParallelRNG(19), 0.745, 2) + .child(new CNG(rng.nextParallelRNG(19), 1, 2) .scale(0.1)) .fractureWith(new CNG(rng.nextParallelRNG(20), 1, 3) - .scale(0.15), 24), 44); + .scale(0.15), 24), 44).down(0.3).patch(2.5); //@done } @@ -62,6 +63,7 @@ public class CNG freq = 1; amp = 1; scale = 1; + patch = 1; fscale = 1; fracture = null; generator = new SNG(random); @@ -116,12 +118,66 @@ public class CNG return this; } + public CNG patch(double c) + { + patch = c; + return this; + } + + public CNG up(double c) + { + up = c; + return this; + } + + public CNG down(double c) + { + down = c; + return this; + } + public CNG injectWith(NoiseInjector i) { injector = i; return this; } + public int fit(int min, int max, double... dim) + { + if(min == max) + { + return min; + } + + double noise = noise(dim); + + return (int) Math.round(IrisInterpolation.lerp(min, max, noise)); + } + + public int fitDouble(double min, double max, double... dim) + { + if(min == max) + { + return (int) Math.round(min); + } + + double noise = noise(dim); + + return (int) Math.round(IrisInterpolation.lerp(min, max, noise)); + } + + public int fitDoubleExponent(double min, double max, double exponent, double... dim) + { + if(min == max) + { + return (int) Math.round(min); + } + + double noise = noise(dim); + + return (int) Math.round(IrisInterpolation.lerp(min, max, exponent == 1 ? noise : Math.pow(noise, exponent))); + } + public double noise(double... dim) { double f = fracture != null ? (fracture.noise(dim) - 0.5) * fscale : 0D; @@ -134,7 +190,7 @@ public class CNG hits += oct; if(children == null) { - return n; + return (n - down + up) * patch; } for(CNG i : children) @@ -144,7 +200,7 @@ public class CNG m += r[1]; } - return n / m; + return ((n / m) - down + up) * patch; } public CNG pow(double power) diff --git a/src/main/java/ninja/bytecode/iris/util/CellGenerator2D.java b/src/main/java/ninja/bytecode/iris/util/CellGenerator2D.java new file mode 100644 index 000000000..0c7b5157e --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/CellGenerator2D.java @@ -0,0 +1,54 @@ +package ninja.bytecode.iris.util; + +import lombok.Getter; +import lombok.Setter; +import ninja.bytecode.iris.util.FastNoise.CellularDistanceFunction; +import ninja.bytecode.iris.util.FastNoise.CellularReturnType; +import ninja.bytecode.iris.util.FastNoise.NoiseType; + +public class CellGenerator2D +{ + private FastNoise fn; + private FastNoise fd; + private CNG cng; + + @Getter + @Setter + private double cellScale; + + @Getter + @Setter + private double shuffle; + + public CellGenerator2D(RNG rng) + { + shuffle = 128; + cellScale = 0.73; + cng = CNG.signature(rng.nextParallelRNG(3204)); + RNG rx = rng.nextParallelRNG(8735652); + int s = rx.nextInt(); + fn = new FastNoise(s); + fn.SetNoiseType(NoiseType.Cellular); + fn.SetCellularReturnType(CellularReturnType.CellValue); + fn.SetCellularDistanceFunction(CellularDistanceFunction.Natural); + fd = new FastNoise(s); + fd.SetNoiseType(NoiseType.Cellular); + fd.SetCellularReturnType(CellularReturnType.Distance2Sub); + fd.SetCellularDistanceFunction(CellularDistanceFunction.Natural); + } + + public float getDistance(double x, double z) + { + return ((fd.GetCellular((float) ((x * cellScale) + (cng.noise(x, z) * shuffle)), (float) ((z * cellScale) + (cng.noise(z, x) * shuffle)))) + 1f) / 2f; + } + + public float getValue(double x, double z, int possibilities) + { + return ((fn.GetCellular((float) ((x * cellScale) + (cng.noise(x, z) * shuffle)), (float) ((z * cellScale) + (cng.noise(z, x) * shuffle))) + 1f) / 2f) * (possibilities - 1); + } + + public int getIndex(double x, double z, int possibilities) + { + return (int) Math.round(getValue(x, z, possibilities)); + } +} diff --git a/src/main/java/ninja/bytecode/iris/util/FastNoise.java b/src/main/java/ninja/bytecode/iris/util/FastNoise.java new file mode 100644 index 000000000..822e99bd0 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/FastNoise.java @@ -0,0 +1,2197 @@ +// FastNoise.java +// +// MIT License +// +// Copyright(c) 2017 Jordan Peck +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// The developer's email is jorzixdan.me2@gzixmail.com (for great email, take +// off every 'zix'.) +// +package ninja.bytecode.iris.util; + +import javax.vecmath.Vector2f; +import javax.vecmath.Vector3f; + +public class FastNoise { + public enum NoiseType {Value, ValueFractal, Perlin, PerlinFractal, Simplex, SimplexFractal, Cellular, WhiteNoise, Cubic, CubicFractal} + public enum Interp {Linear, Hermite, Quintic} + public enum FractalType {FBM, Billow, RigidMulti} + public enum CellularDistanceFunction {Euclidean, Manhattan, Natural} + public enum CellularReturnType {CellValue, NoiseLookup, Distance, Distance2, Distance2Add, Distance2Sub, Distance2Mul, Distance2Div} + + private int m_seed = 1337; + private float m_frequency = (float) 0.01; + private Interp m_interp = Interp.Quintic; + private NoiseType m_noiseType = NoiseType.Simplex; + + private int m_octaves = 3; + private float m_lacunarity = (float) 2.0; + private float m_gain = (float) 0.5; + private FractalType m_fractalType = FractalType.FBM; + + private float m_fractalBounding; + + private CellularDistanceFunction m_cellularDistanceFunction = CellularDistanceFunction.Euclidean; + private CellularReturnType m_cellularReturnType = CellularReturnType.CellValue; + private FastNoise m_cellularNoiseLookup = null; + + private float m_gradientPerturbAmp = (float) (1.0 / 0.45); + + public FastNoise() { + this(1337); + } + + public FastNoise(int seed) { + m_seed = seed; + CalculateFractalBounding(); + } + + // Returns a 0 float/double + public static float GetDecimalType() { + return 0; + } + + // Returns the seed used by this object + public int GetSeed() { + return m_seed; + } + + // Sets seed used for all noise types + // Default: 1337 + public void SetSeed(int seed) { + m_seed = seed; + } + + // Sets frequency for all noise types + // Default: 0.01 + public void SetFrequency(float frequency) { + m_frequency = frequency; + } + + // Changes the interpolation method used to smooth between noise values + // Possible interpolation methods (lowest to highest quality) : + // - Linear + // - Hermite + // - Quintic + // Used in Value, Gradient Noise and Position Perturbing + // Default: Quintic + public void SetInterp(Interp interp) { + m_interp = interp; + } + + // Sets noise return type of GetNoise(...) + // Default: Simplex + public void SetNoiseType(NoiseType noiseType) { + m_noiseType = noiseType; + } + + // Sets octave count for all fractal noise types + // Default: 3 + public void SetFractalOctaves(int octaves) { + m_octaves = octaves; + CalculateFractalBounding(); + } + + // Sets octave lacunarity for all fractal noise types + // Default: 2.0 + public void SetFractalLacunarity(float lacunarity) { + m_lacunarity = lacunarity; + } + + // Sets octave gain for all fractal noise types + // Default: 0.5 + public void SetFractalGain(float gain) { + m_gain = gain; + CalculateFractalBounding(); + } + + // Sets method for combining octaves in all fractal noise types + // Default: FBM + public void SetFractalType(FractalType fractalType) { + m_fractalType = fractalType; + } + + // Sets return type from cellular noise calculations + // Note: NoiseLookup requires another FastNoise object be set with SetCellularNoiseLookup() to function + // Default: CellValue + public void SetCellularDistanceFunction(CellularDistanceFunction cellularDistanceFunction) { + m_cellularDistanceFunction = cellularDistanceFunction; + } + + // Sets distance function used in cellular noise calculations + // Default: Euclidean + public void SetCellularReturnType(CellularReturnType cellularReturnType) { + m_cellularReturnType = cellularReturnType; + } + + // Noise used to calculate a cell value if cellular return type is NoiseLookup + // The lookup value is acquired through GetNoise() so ensure you SetNoiseType() on the noise lookup, value, gradient or simplex is recommended + public void SetCellularNoiseLookup(FastNoise noise) { + m_cellularNoiseLookup = noise; + } + + // Sets the maximum perturb distance from original location when using GradientPerturb{Fractal}(...) + // Default: 1.0 + public void SetGradientPerturbAmp(float gradientPerturbAmp) { + m_gradientPerturbAmp = gradientPerturbAmp / (float) 0.45; + } + + private static class Float2 { + public final float x, y; + + public Float2(float x, float y) { + this.x = x; + this.y = y; + } + } + + private static class Float3 { + public final float x, y, z; + + public Float3(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + } + + 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), + }; + + private static final Float3[] GRAD_3D = { + new Float3(1, 1, 0), new Float3(-1, 1, 0), new Float3(1, -1, 0), new Float3(-1, -1, 0), + new Float3(1, 0, 1), new Float3(-1, 0, 1), new Float3(1, 0, -1), new Float3(-1, 0, -1), + new Float3(0, 1, 1), new Float3(0, -1, 1), new Float3(0, 1, -1), new Float3(0, -1, -1), + new Float3(1, 1, 0), new Float3(0, -1, 1), new Float3(-1, 1, 0), new Float3(0, -1, -1), + }; + + private static final Float2[] CELL_2D = + { + new Float2(-0.4313539279f, 0.1281943404f), new Float2(-0.1733316799f, 0.415278375f), new Float2(-0.2821957395f, -0.3505218461f), new Float2(-0.2806473808f, 0.3517627718f), new Float2(0.3125508975f, -0.3237467165f), new Float2(0.3383018443f, -0.2967353402f), new Float2(-0.4393982022f, -0.09710417025f), new Float2(-0.4460443703f, -0.05953502905f), + new Float2(-0.302223039f, 0.3334085102f), new Float2(-0.212681052f, -0.3965687458f), new Float2(-0.2991156529f, 0.3361990872f), new Float2(0.2293323691f, 0.3871778202f), new Float2(0.4475439151f, -0.04695150755f), new Float2(0.1777518f, 0.41340573f), new Float2(0.1688522499f, -0.4171197882f), new Float2(-0.0976597166f, 0.4392750616f), + new Float2(0.08450188373f, 0.4419948321f), new Float2(-0.4098760448f, -0.1857461384f), new Float2(0.3476585782f, -0.2857157906f), new Float2(-0.3350670039f, -0.30038326f), new Float2(0.2298190031f, -0.3868891648f), new Float2(-0.01069924099f, 0.449872789f), new Float2(-0.4460141246f, -0.05976119672f), new Float2(0.3650293864f, 0.2631606867f), + new Float2(-0.349479423f, 0.2834856838f), new Float2(-0.4122720642f, 0.1803655873f), new Float2(-0.267327811f, 0.3619887311f), new Float2(0.322124041f, -0.3142230135f), new Float2(0.2880445931f, -0.3457315612f), new Float2(0.3892170926f, -0.2258540565f), new Float2(0.4492085018f, -0.02667811596f), new Float2(-0.4497724772f, 0.01430799601f), + new Float2(0.1278175387f, -0.4314657307f), new Float2(-0.03572100503f, 0.4485799926f), new Float2(-0.4297407068f, -0.1335025276f), new Float2(-0.3217817723f, 0.3145735065f), new Float2(-0.3057158873f, 0.3302087162f), new Float2(-0.414503978f, 0.1751754899f), new Float2(-0.3738139881f, 0.2505256519f), new Float2(0.2236891408f, -0.3904653228f), + new Float2(0.002967775577f, -0.4499902136f), new Float2(0.1747128327f, -0.4146991995f), new Float2(-0.4423772489f, -0.08247647938f), new Float2(-0.2763960987f, -0.355112935f), new Float2(-0.4019385906f, -0.2023496216f), new Float2(0.3871414161f, -0.2293938184f), new Float2(-0.430008727f, 0.1326367019f), new Float2(-0.03037574274f, -0.4489736231f), + new Float2(-0.3486181573f, 0.2845441624f), new Float2(0.04553517144f, -0.4476902368f), new Float2(-0.0375802926f, 0.4484280562f), new Float2(0.3266408905f, 0.3095250049f), new Float2(0.06540017593f, -0.4452222108f), new Float2(0.03409025829f, 0.448706869f), new Float2(-0.4449193635f, 0.06742966669f), new Float2(-0.4255936157f, -0.1461850686f), + new Float2(0.449917292f, 0.008627302568f), new Float2(0.05242606404f, 0.4469356864f), new Float2(-0.4495305179f, -0.02055026661f), new Float2(-0.1204775703f, 0.4335725488f), new Float2(-0.341986385f, -0.2924813028f), new Float2(0.3865320182f, 0.2304191809f), new Float2(0.04506097811f, -0.447738214f), new Float2(-0.06283465979f, 0.4455915232f), + new Float2(0.3932600341f, -0.2187385324f), new Float2(0.4472261803f, -0.04988730975f), new Float2(0.3753571011f, -0.2482076684f), new Float2(-0.273662295f, 0.357223947f), new Float2(0.1700461538f, 0.4166344988f), new Float2(0.4102692229f, 0.1848760794f), new Float2(0.323227187f, -0.3130881435f), new Float2(-0.2882310238f, -0.3455761521f), + new Float2(0.2050972664f, 0.4005435199f), new Float2(0.4414085979f, -0.08751256895f), new Float2(-0.1684700334f, 0.4172743077f), new Float2(-0.003978032396f, 0.4499824166f), new Float2(-0.2055133639f, 0.4003301853f), new Float2(-0.006095674897f, -0.4499587123f), new Float2(-0.1196228124f, -0.4338091548f), new Float2(0.3901528491f, -0.2242337048f), + new Float2(0.01723531752f, 0.4496698165f), new Float2(-0.3015070339f, 0.3340561458f), new Float2(-0.01514262423f, -0.4497451511f), new Float2(-0.4142574071f, -0.1757577897f), new Float2(-0.1916377265f, -0.4071547394f), new Float2(0.3749248747f, 0.2488600778f), new Float2(-0.2237774255f, 0.3904147331f), new Float2(-0.4166343106f, -0.1700466149f), + new Float2(0.3619171625f, 0.267424695f), new Float2(0.1891126846f, -0.4083336779f), new Float2(-0.3127425077f, 0.323561623f), new Float2(-0.3281807787f, 0.307891826f), new Float2(-0.2294806661f, 0.3870899429f), new Float2(-0.3445266136f, 0.2894847362f), new Float2(-0.4167095422f, -0.1698621719f), new Float2(-0.257890321f, -0.3687717212f), + new Float2(-0.3612037825f, 0.2683874578f), new Float2(0.2267996491f, 0.3886668486f), new Float2(0.207157062f, 0.3994821043f), new Float2(0.08355176718f, -0.4421754202f), new Float2(-0.4312233307f, 0.1286329626f), new Float2(0.3257055497f, 0.3105090899f), new Float2(0.177701095f, -0.4134275279f), new Float2(-0.445182522f, 0.06566979625f), + new Float2(0.3955143435f, 0.2146355146f), new Float2(-0.4264613988f, 0.1436338239f), new Float2(-0.3793799665f, -0.2420141339f), new Float2(0.04617599081f, -0.4476245948f), new Float2(-0.371405428f, -0.2540826796f), new Float2(0.2563570295f, -0.3698392535f), new Float2(0.03476646309f, 0.4486549822f), new Float2(-0.3065454405f, 0.3294387544f), + new Float2(-0.2256979823f, 0.3893076172f), new Float2(0.4116448463f, -0.1817925206f), new Float2(-0.2907745828f, -0.3434387019f), new Float2(0.2842278468f, -0.348876097f), new Float2(0.3114589359f, -0.3247973695f), new Float2(0.4464155859f, -0.0566844308f), new Float2(-0.3037334033f, -0.3320331606f), new Float2(0.4079607166f, 0.1899159123f), + new Float2(-0.3486948919f, -0.2844501228f), new Float2(0.3264821436f, 0.3096924441f), new Float2(0.3211142406f, 0.3152548881f), new Float2(0.01183382662f, 0.4498443737f), new Float2(0.4333844092f, 0.1211526057f), new Float2(0.3118668416f, 0.324405723f), new Float2(-0.272753471f, 0.3579183483f), new Float2(-0.422228622f, -0.1556373694f), + new Float2(-0.1009700099f, -0.4385260051f), new Float2(-0.2741171231f, -0.3568750521f), new Float2(-0.1465125133f, 0.4254810025f), new Float2(0.2302279044f, -0.3866459777f), new Float2(-0.3699435608f, 0.2562064828f), new Float2(0.105700352f, -0.4374099171f), new Float2(-0.2646713633f, 0.3639355292f), new Float2(0.3521828122f, 0.2801200935f), + new Float2(-0.1864187807f, -0.4095705534f), new Float2(0.1994492955f, -0.4033856449f), new Float2(0.3937065066f, 0.2179339044f), new Float2(-0.3226158377f, 0.3137180602f), new Float2(0.3796235338f, 0.2416318948f), new Float2(0.1482921929f, 0.4248640083f), new Float2(-0.407400394f, 0.1911149365f), new Float2(0.4212853031f, 0.1581729856f), + new Float2(-0.2621297173f, 0.3657704353f), new Float2(-0.2536986953f, -0.3716678248f), new Float2(-0.2100236383f, 0.3979825013f), new Float2(0.3624152444f, 0.2667493029f), new Float2(-0.3645038479f, -0.2638881295f), new Float2(0.2318486784f, 0.3856762766f), new Float2(-0.3260457004f, 0.3101519002f), new Float2(-0.2130045332f, -0.3963950918f), + new Float2(0.3814998766f, -0.2386584257f), new Float2(-0.342977305f, 0.2913186713f), new Float2(-0.4355865605f, 0.1129794154f), new Float2(-0.2104679605f, 0.3977477059f), new Float2(0.3348364681f, -0.3006402163f), new Float2(0.3430468811f, 0.2912367377f), new Float2(-0.2291836801f, -0.3872658529f), new Float2(0.2547707298f, -0.3709337882f), + new Float2(0.4236174945f, -0.151816397f), new Float2(-0.15387742f, 0.4228731957f), new Float2(-0.4407449312f, 0.09079595574f), new Float2(-0.06805276192f, -0.444824484f), new Float2(0.4453517192f, -0.06451237284f), new Float2(0.2562464609f, -0.3699158705f), new Float2(0.3278198355f, -0.3082761026f), new Float2(-0.4122774207f, -0.1803533432f), + new Float2(0.3354090914f, -0.3000012356f), new Float2(0.446632869f, -0.05494615882f), new Float2(-0.1608953296f, 0.4202531296f), new Float2(-0.09463954939f, 0.4399356268f), new Float2(-0.02637688324f, -0.4492262904f), new Float2(0.447102804f, -0.05098119915f), new Float2(-0.4365670908f, 0.1091291678f), new Float2(-0.3959858651f, 0.2137643437f), + new Float2(-0.4240048207f, -0.1507312575f), new Float2(-0.3882794568f, 0.2274622243f), new Float2(-0.4283652566f, -0.1378521198f), new Float2(0.3303888091f, 0.305521251f), new Float2(0.3321434919f, -0.3036127481f), new Float2(-0.413021046f, -0.1786438231f), new Float2(0.08403060337f, -0.4420846725f), new Float2(-0.3822882919f, 0.2373934748f), + new Float2(-0.3712395594f, -0.2543249683f), new Float2(0.4472363971f, -0.04979563372f), new Float2(-0.4466591209f, 0.05473234629f), new Float2(0.0486272539f, -0.4473649407f), new Float2(-0.4203101295f, -0.1607463688f), new Float2(0.2205360833f, 0.39225481f), new Float2(-0.3624900666f, 0.2666476169f), new Float2(-0.4036086833f, -0.1989975647f), + new Float2(0.2152727807f, 0.3951678503f), new Float2(-0.4359392962f, -0.1116106179f), new Float2(0.4178354266f, 0.1670735057f), new Float2(0.2007630161f, 0.4027334247f), new Float2(-0.07278067175f, -0.4440754146f), new Float2(0.3644748615f, -0.2639281632f), new Float2(-0.4317451775f, 0.126870413f), new Float2(-0.297436456f, 0.3376855855f), + new Float2(-0.2998672222f, 0.3355289094f), new Float2(-0.2673674124f, 0.3619594822f), new Float2(0.2808423357f, 0.3516071423f), new Float2(0.3498946567f, 0.2829730186f), new Float2(-0.2229685561f, 0.390877248f), new Float2(0.3305823267f, 0.3053118493f), new Float2(-0.2436681211f, -0.3783197679f), new Float2(-0.03402776529f, 0.4487116125f), + new Float2(-0.319358823f, 0.3170330301f), new Float2(0.4454633477f, -0.06373700535f), new Float2(0.4483504221f, 0.03849544189f), new Float2(-0.4427358436f, -0.08052932871f), new Float2(0.05452298565f, 0.4466847255f), new Float2(-0.2812560807f, 0.3512762688f), new Float2(0.1266696921f, 0.4318041097f), new Float2(-0.3735981243f, 0.2508474468f), + new Float2(0.2959708351f, -0.3389708908f), new Float2(-0.3714377181f, 0.254035473f), new Float2(-0.404467102f, -0.1972469604f), new Float2(0.1636165687f, -0.419201167f), new Float2(0.3289185495f, -0.3071035458f), new Float2(-0.2494824991f, -0.3745109914f), new Float2(0.03283133272f, 0.4488007393f), new Float2(-0.166306057f, -0.4181414777f), + new Float2(-0.106833179f, 0.4371346153f), new Float2(0.06440260376f, -0.4453676062f), new Float2(-0.4483230967f, 0.03881238203f), new Float2(-0.421377757f, -0.1579265206f), new Float2(0.05097920662f, -0.4471030312f), new Float2(0.2050584153f, -0.4005634111f), new Float2(0.4178098529f, -0.167137449f), new Float2(-0.3565189504f, -0.2745801121f), + new Float2(0.4478398129f, 0.04403977727f), new Float2(-0.3399999602f, -0.2947881053f), new Float2(0.3767121994f, 0.2461461331f), new Float2(-0.3138934434f, 0.3224451987f), new Float2(-0.1462001792f, -0.4255884251f), new Float2(0.3970290489f, -0.2118205239f), new Float2(0.4459149305f, -0.06049689889f), new Float2(-0.4104889426f, -0.1843877112f), + new Float2(0.1475103971f, -0.4251360756f), new Float2(0.09258030352f, 0.4403735771f), new Float2(-0.1589664637f, -0.4209865359f), new Float2(0.2482445008f, 0.3753327428f), new Float2(0.4383624232f, -0.1016778537f), new Float2(0.06242802956f, 0.4456486745f), new Float2(0.2846591015f, -0.3485243118f), new Float2(-0.344202744f, -0.2898697484f), + new Float2(0.1198188883f, -0.4337550392f), new Float2(-0.243590703f, 0.3783696201f), new Float2(0.2958191174f, -0.3391033025f), new Float2(-0.1164007991f, 0.4346847754f), new Float2(0.1274037151f, -0.4315881062f), new Float2(0.368047306f, 0.2589231171f), new Float2(0.2451436949f, 0.3773652989f), new Float2(-0.4314509715f, 0.12786735f), + }; + + private static final Float3[] CELL_3D = + { + new Float3(0.1453787434f, -0.4149781685f, -0.0956981749f), new Float3(-0.01242829687f, -0.1457918398f, -0.4255470325f), new Float3(0.2877979582f, -0.02606483451f, -0.3449535616f), new Float3(-0.07732986802f, 0.2377094325f, 0.3741848704f), new Float3(0.1107205875f, -0.3552302079f, -0.2530858567f), new Float3(0.2755209141f, 0.2640521179f, -0.238463215f), new Float3(0.294168941f, 0.1526064594f, 0.3044271714f), new Float3(0.4000921098f, -0.2034056362f, 0.03244149937f), + new Float3(-0.1697304074f, 0.3970864695f, -0.1265461359f), new Float3(-0.1483224484f, -0.3859694688f, 0.1775613147f), new Float3(0.2623596946f, -0.2354852944f, 0.2796677792f), new Float3(-0.2709003183f, 0.3505271138f, -0.07901746678f), new Float3(-0.03516550699f, 0.3885234328f, 0.2243054374f), new Float3(-0.1267712655f, 0.1920044036f, 0.3867342179f), new Float3(0.02952021915f, 0.4409685861f, 0.08470692262f), new Float3(-0.2806854217f, -0.266996757f, 0.2289725438f), + new Float3(-0.171159547f, 0.2141185563f, 0.3568720405f), new Float3(0.2113227183f, 0.3902405947f, -0.07453178509f), new Float3(-0.1024352839f, 0.2128044156f, -0.3830421561f), new Float3(-0.3304249877f, -0.1566986703f, 0.2622305365f), new Float3(0.2091111325f, 0.3133278055f, -0.2461670583f), new Float3(0.344678154f, -0.1944240454f, -0.2142341261f), new Float3(0.1984478035f, -0.3214342325f, -0.2445373252f), new Float3(-0.2929008603f, 0.2262915116f, 0.2559320961f), + new Float3(-0.1617332831f, 0.006314769776f, -0.4198838754f), new Float3(-0.3582060271f, -0.148303178f, -0.2284613961f), new Float3(-0.1852067326f, -0.3454119342f, -0.2211087107f), new Float3(0.3046301062f, 0.1026310383f, 0.314908508f), new Float3(-0.03816768434f, -0.2551766358f, -0.3686842991f), new Float3(-0.4084952196f, 0.1805950793f, 0.05492788837f), new Float3(-0.02687443361f, -0.2749741471f, 0.3551999201f), new Float3(-0.03801098351f, 0.3277859044f, 0.3059600725f), + new Float3(0.2371120802f, 0.2900386767f, -0.2493099024f), new Float3(0.4447660503f, 0.03946930643f, 0.05590469027f), new Float3(0.01985147278f, -0.01503183293f, -0.4493105419f), new Float3(0.4274339143f, 0.03345994256f, -0.1366772882f), new Float3(-0.2072988631f, 0.2871414597f, -0.2776273824f), new Float3(-0.3791240978f, 0.1281177671f, 0.2057929936f), new Float3(-0.2098721267f, -0.1007087278f, -0.3851122467f), new Float3(0.01582798878f, 0.4263894424f, 0.1429738373f), + new Float3(-0.1888129464f, -0.3160996813f, -0.2587096108f), new Float3(0.1612988974f, -0.1974805082f, -0.3707885038f), new Float3(-0.08974491322f, 0.229148752f, -0.3767448739f), new Float3(0.07041229526f, 0.4150230285f, -0.1590534329f), new Float3(-0.1082925611f, -0.1586061639f, 0.4069604477f), new Float3(0.2474100658f, -0.3309414609f, 0.1782302128f), new Float3(-0.1068836661f, -0.2701644537f, -0.3436379634f), new Float3(0.2396452163f, 0.06803600538f, -0.3747549496f), + new Float3(-0.3063886072f, 0.2597428179f, 0.2028785103f), new Float3(0.1593342891f, -0.3114350249f, -0.2830561951f), new Float3(0.2709690528f, 0.1412648683f, -0.3303331794f), new Float3(-0.1519780427f, 0.3623355133f, 0.2193527988f), new Float3(0.1699773681f, 0.3456012883f, 0.2327390037f), new Float3(-0.1986155616f, 0.3836276443f, -0.1260225743f), new Float3(-0.1887482106f, -0.2050154888f, -0.353330953f), new Float3(0.2659103394f, 0.3015631259f, -0.2021172246f), + new Float3(-0.08838976154f, -0.4288819642f, -0.1036702021f), new Float3(-0.04201869311f, 0.3099592485f, 0.3235115047f), new Float3(-0.3230334656f, 0.201549922f, -0.2398478873f), new Float3(0.2612720941f, 0.2759854499f, -0.2409749453f), new Float3(0.385713046f, 0.2193460345f, 0.07491837764f), new Float3(0.07654967953f, 0.3721732183f, 0.241095919f), new Float3(0.4317038818f, -0.02577753072f, 0.1243675091f), new Float3(-0.2890436293f, -0.3418179959f, -0.04598084447f), + new Float3(-0.2201947582f, 0.383023377f, -0.08548310451f), new Float3(0.4161322773f, -0.1669634289f, -0.03817251927f), new Float3(0.2204718095f, 0.02654238946f, -0.391391981f), new Float3(-0.1040307469f, 0.3890079625f, -0.2008741118f), new Float3(-0.1432122615f, 0.371614387f, -0.2095065525f), new Float3(0.3978380468f, -0.06206669342f, 0.2009293758f), new Float3(-0.2599274663f, 0.2616724959f, -0.2578084893f), new Float3(0.4032618332f, -0.1124593585f, 0.1650235939f), + new Float3(-0.08953470255f, -0.3048244735f, 0.3186935478f), new Float3(0.118937202f, -0.2875221847f, 0.325092195f), new Float3(0.02167047076f, -0.03284630549f, -0.4482761547f), new Float3(-0.3411343612f, 0.2500031105f, 0.1537068389f), new Float3(0.3162964612f, 0.3082064153f, -0.08640228117f), new Float3(0.2355138889f, -0.3439334267f, -0.1695376245f), new Float3(-0.02874541518f, -0.3955933019f, 0.2125550295f), new Float3(-0.2461455173f, 0.02020282325f, -0.3761704803f), + new Float3(0.04208029445f, -0.4470439576f, 0.02968078139f), new Float3(0.2727458746f, 0.2288471896f, -0.2752065618f), new Float3(-0.1347522818f, -0.02720848277f, -0.4284874806f), new Float3(0.3829624424f, 0.1231931484f, -0.2016512234f), new Float3(-0.3547613644f, 0.1271702173f, 0.2459107769f), new Float3(0.2305790207f, 0.3063895591f, 0.2354968222f), new Float3(-0.08323845599f, -0.1922245118f, 0.3982726409f), new Float3(0.2993663085f, -0.2619918095f, -0.2103333191f), + new Float3(-0.2154865723f, 0.2706747713f, 0.287751117f), new Float3(0.01683355354f, -0.2680655787f, -0.3610505186f), new Float3(0.05240429123f, 0.4335128183f, -0.1087217856f), new Float3(0.00940104872f, -0.4472890582f, 0.04841609928f), new Float3(0.3465688735f, 0.01141914583f, -0.2868093776f), new Float3(-0.3706867948f, -0.2551104378f, 0.003156692623f), new Float3(0.2741169781f, 0.2139972417f, -0.2855959784f), new Float3(0.06413433865f, 0.1708718512f, 0.4113266307f), + new Float3(-0.388187972f, -0.03973280434f, -0.2241236325f), new Float3(0.06419469312f, -0.2803682491f, 0.3460819069f), new Float3(-0.1986120739f, -0.3391173584f, 0.2192091725f), new Float3(-0.203203009f, -0.3871641506f, 0.1063600375f), new Float3(-0.1389736354f, -0.2775901578f, -0.3257760473f), new Float3(-0.06555641638f, 0.342253257f, -0.2847192729f), new Float3(-0.2529246486f, -0.2904227915f, 0.2327739768f), new Float3(0.1444476522f, 0.1069184044f, 0.4125570634f), + new Float3(-0.3643780054f, -0.2447099973f, -0.09922543227f), new Float3(0.4286142488f, -0.1358496089f, -0.01829506817f), new Float3(0.165872923f, -0.3136808464f, -0.2767498872f), new Float3(0.2219610524f, -0.3658139958f, 0.1393320198f), new Float3(0.04322940318f, -0.3832730794f, 0.2318037215f), new Float3(-0.08481269795f, -0.4404869674f, -0.03574965489f), new Float3(0.1822082075f, -0.3953259299f, 0.1140946023f), new Float3(-0.3269323334f, 0.3036542563f, 0.05838957105f), + new Float3(-0.4080485344f, 0.04227858267f, -0.184956522f), new Float3(0.2676025294f, -0.01299671652f, 0.36155217f), new Float3(0.3024892441f, -0.1009990293f, -0.3174892964f), new Float3(0.1448494052f, 0.425921681f, -0.0104580805f), new Float3(0.4198402157f, 0.08062320474f, 0.1404780841f), new Float3(-0.3008872161f, -0.333040905f, -0.03241355801f), new Float3(0.3639310428f, -0.1291284382f, -0.2310412139f), new Float3(0.3295806598f, 0.0184175994f, -0.3058388149f), + new Float3(0.2776259487f, -0.2974929052f, -0.1921504723f), new Float3(0.4149000507f, -0.144793182f, -0.09691688386f), new Float3(0.145016715f, -0.0398992945f, 0.4241205002f), new Float3(0.09299023471f, -0.299732164f, -0.3225111565f), new Float3(0.1028907093f, -0.361266869f, 0.247789732f), new Float3(0.2683057049f, -0.07076041213f, -0.3542668666f), new Float3(-0.4227307273f, -0.07933161816f, -0.1323073187f), new Float3(-0.1781224702f, 0.1806857196f, -0.3716517945f), + new Float3(0.4390788626f, -0.02841848598f, -0.09435116353f), new Float3(0.2972583585f, 0.2382799621f, -0.2394997452f), new Float3(-0.1707002821f, 0.2215845691f, 0.3525077196f), new Float3(0.3806686614f, 0.1471852559f, -0.1895464869f), new Float3(-0.1751445661f, -0.274887877f, 0.3102596268f), new Float3(-0.2227237566f, -0.2316778837f, 0.3149912482f), new Float3(0.1369633021f, 0.1341343041f, -0.4071228836f), new Float3(-0.3529503428f, -0.2472893463f, -0.129514612f), + new Float3(-0.2590744185f, -0.2985577559f, -0.2150435121f), new Float3(-0.3784019401f, 0.2199816631f, -0.1044989934f), new Float3(-0.05635805671f, 0.1485737441f, 0.4210102279f), new Float3(0.3251428613f, 0.09666046873f, -0.2957006485f), new Float3(-0.4190995804f, 0.1406751354f, -0.08405978803f), new Float3(-0.3253150961f, -0.3080335042f, -0.04225456877f), new Float3(0.2857945863f, -0.05796152095f, 0.3427271751f), new Float3(-0.2733604046f, 0.1973770973f, -0.2980207554f), + new Float3(0.219003657f, 0.2410037886f, -0.3105713639f), new Float3(0.3182767252f, -0.271342949f, 0.1660509868f), new Float3(-0.03222023115f, -0.3331161506f, -0.300824678f), new Float3(-0.3087780231f, 0.1992794134f, -0.2596995338f), new Float3(-0.06487611647f, -0.4311322747f, 0.1114273361f), new Float3(0.3921171432f, -0.06294284106f, -0.2116183942f), new Float3(-0.1606404506f, -0.358928121f, -0.2187812825f), new Float3(-0.03767771199f, -0.2290351443f, 0.3855169162f), + new Float3(0.1394866832f, -0.3602213994f, 0.2308332918f), new Float3(-0.4345093872f, 0.005751117145f, 0.1169124335f), new Float3(-0.1044637494f, 0.4168128432f, -0.1336202785f), new Float3(0.2658727501f, 0.2551943237f, 0.2582393035f), new Float3(0.2051461999f, 0.1975390727f, 0.3484154868f), new Float3(-0.266085566f, 0.23483312f, 0.2766800993f), new Float3(0.07849405464f, -0.3300346342f, -0.2956616708f), new Float3(-0.2160686338f, 0.05376451292f, -0.3910546287f), + new Float3(-0.185779186f, 0.2148499206f, 0.3490352499f), new Float3(0.02492421743f, -0.3229954284f, -0.3123343347f), new Float3(-0.120167831f, 0.4017266681f, 0.1633259825f), new Float3(-0.02160084693f, -0.06885389554f, 0.4441762538f), new Float3(0.2597670064f, 0.3096300784f, 0.1978643903f), new Float3(-0.1611553854f, -0.09823036005f, 0.4085091653f), new Float3(-0.3278896792f, 0.1461670309f, 0.2713366126f), new Float3(0.2822734956f, 0.03754421121f, -0.3484423997f), + new Float3(0.03169341113f, 0.347405252f, -0.2842624114f), new Float3(0.2202613604f, -0.3460788041f, -0.1849713341f), new Float3(0.2933396046f, 0.3031973659f, 0.1565989581f), new Float3(-0.3194922995f, 0.2453752201f, -0.200538455f), new Float3(-0.3441586045f, -0.1698856132f, -0.2349334659f), new Float3(0.2703645948f, -0.3574277231f, 0.04060059933f), new Float3(0.2298568861f, 0.3744156221f, 0.0973588921f), new Float3(0.09326603877f, -0.3170108894f, 0.3054595587f), + new Float3(-0.1116165319f, -0.2985018719f, 0.3177080142f), new Float3(0.2172907365f, -0.3460005203f, -0.1885958001f), new Float3(0.1991339479f, 0.3820341668f, -0.1299829458f), new Float3(-0.0541918155f, -0.2103145071f, 0.39412061f), new Float3(0.08871336998f, 0.2012117383f, 0.3926114802f), new Float3(0.2787673278f, 0.3505404674f, 0.04370535101f), new Float3(-0.322166438f, 0.3067213525f, 0.06804996813f), new Float3(-0.4277366384f, 0.132066775f, 0.04582286686f), + new Float3(0.240131882f, -0.1612516055f, 0.344723946f), new Float3(0.1448607981f, -0.2387819045f, 0.3528435224f), new Float3(-0.3837065682f, -0.2206398454f, 0.08116235683f), new Float3(-0.4382627882f, -0.09082753406f, -0.04664855374f), new Float3(-0.37728353f, 0.05445141085f, 0.2391488697f), new Float3(0.1259579313f, 0.348394558f, 0.2554522098f), new Float3(-0.1406285511f, -0.270877371f, -0.3306796947f), new Float3(-0.1580694418f, 0.4162931958f, -0.06491553533f), + new Float3(0.2477612106f, -0.2927867412f, -0.2353514536f), new Float3(0.2916132853f, 0.3312535401f, 0.08793624968f), new Float3(0.07365265219f, -0.1666159848f, 0.411478311f), new Float3(-0.26126526f, -0.2422237692f, 0.2748965434f), new Float3(-0.3721862032f, 0.252790166f, 0.008634938242f), new Float3(-0.3691191571f, -0.255281188f, 0.03290232422f), new Float3(0.2278441737f, -0.3358364886f, 0.1944244981f), new Float3(0.363398169f, -0.2310190248f, 0.1306597909f), + new Float3(-0.304231482f, -0.2698452035f, 0.1926830856f), new Float3(-0.3199312232f, 0.316332536f, -0.008816977938f), new Float3(0.2874852279f, 0.1642275508f, -0.304764754f), new Float3(-0.1451096801f, 0.3277541114f, -0.2720669462f), new Float3(0.3220090754f, 0.0511344108f, 0.3101538769f), new Float3(-0.1247400865f, -0.04333605335f, -0.4301882115f), new Float3(-0.2829555867f, -0.3056190617f, -0.1703910946f), new Float3(0.1069384374f, 0.3491024667f, -0.2630430352f), + new Float3(-0.1420661144f, -0.3055376754f, -0.2982682484f), new Float3(-0.250548338f, 0.3156466809f, -0.2002316239f), new Float3(0.3265787872f, 0.1871229129f, 0.2466400438f), new Float3(0.07646097258f, -0.3026690852f, 0.324106687f), new Float3(0.3451771584f, 0.2757120714f, -0.0856480183f), new Float3(0.298137964f, 0.2852657134f, 0.179547284f), new Float3(0.2812250376f, 0.3466716415f, 0.05684409612f), new Float3(0.4390345476f, -0.09790429955f, -0.01278335452f), + new Float3(0.2148373234f, 0.1850172527f, 0.3494474791f), new Float3(0.2595421179f, -0.07946825393f, 0.3589187731f), new Float3(0.3182823114f, -0.307355516f, -0.08203022006f), new Float3(-0.4089859285f, -0.04647718411f, 0.1818526372f), new Float3(-0.2826749061f, 0.07417482322f, 0.3421885344f), new Float3(0.3483864637f, 0.225442246f, -0.1740766085f), new Float3(-0.3226415069f, -0.1420585388f, -0.2796816575f), new Float3(0.4330734858f, -0.118868561f, -0.02859407492f), + new Float3(-0.08717822568f, -0.3909896417f, -0.2050050172f), new Float3(-0.2149678299f, 0.3939973956f, -0.03247898316f), new Float3(-0.2687330705f, 0.322686276f, -0.1617284888f), new Float3(0.2105665099f, -0.1961317136f, -0.3459683451f), new Float3(0.4361845915f, -0.1105517485f, 0.004616608544f), new Float3(0.05333333359f, -0.313639498f, -0.3182543336f), new Float3(-0.05986216652f, 0.1361029153f, -0.4247264031f), new Float3(0.3664988455f, 0.2550543014f, -0.05590974511f), + new Float3(-0.2341015558f, -0.182405731f, 0.3382670703f), new Float3(-0.04730947785f, -0.4222150243f, -0.1483114513f), new Float3(-0.2391566239f, -0.2577696514f, -0.2808182972f), new Float3(-0.1242081035f, 0.4256953395f, -0.07652336246f), new Float3(0.2614832715f, -0.3650179274f, 0.02980623099f), new Float3(-0.2728794681f, -0.3499628774f, 0.07458404908f), new Float3(0.007892900508f, -0.1672771315f, 0.4176793787f), new Float3(-0.01730330376f, 0.2978486637f, -0.3368779738f), + new Float3(0.2054835762f, -0.3252600376f, -0.2334146693f), new Float3(-0.3231994983f, 0.1564282844f, -0.2712420987f), new Float3(-0.2669545963f, 0.2599343665f, -0.2523278991f), new Float3(-0.05554372779f, 0.3170813944f, -0.3144428146f), new Float3(-0.2083935713f, -0.310922837f, -0.2497981362f), new Float3(0.06989323478f, -0.3156141536f, 0.3130537363f), new Float3(0.3847566193f, -0.1605309138f, -0.1693876312f), new Float3(-0.3026215288f, -0.3001537679f, -0.1443188342f), + new Float3(0.3450735512f, 0.08611519592f, 0.2756962409f), new Float3(0.1814473292f, -0.2788782453f, -0.3029914042f), new Float3(-0.03855010448f, 0.09795110726f, 0.4375151083f), new Float3(0.3533670318f, 0.2665752752f, 0.08105160988f), new Float3(-0.007945601311f, 0.140359426f, -0.4274764309f), new Float3(0.4063099273f, -0.1491768253f, -0.1231199324f), new Float3(-0.2016773589f, 0.008816271194f, -0.4021797064f), new Float3(-0.07527055435f, -0.425643481f, -0.1251477955f), + }; + + + private static int FastFloor(float f) { + return (f >= 0 ? (int) f : (int) f - 1); + } + + + private static int FastRound(float f) { + return (f >= 0) ? (int) (f + (float) 0.5) : (int) (f - (float) 0.5); + } + + + private static float Lerp(float a, float b, float t) { + return a + t * (b - a); + } + + + private static float InterpHermiteFunc(float t) { + return t * t * (3 - 2 * t); + } + + + private static float InterpQuinticFunc(float t) { + return t * t * t * (t * (t * 6 - 15) + 10); + } + + + private static float CubicLerp(float a, float b, float c, float d, float t) { + float p = (d - c) - (a - b); + return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b; + } + + private void CalculateFractalBounding() { + float amp = m_gain; + float ampFractal = 1; + for (int i = 1; i < m_octaves; i++) { + ampFractal += amp; + amp *= m_gain; + } + m_fractalBounding = 1 / ampFractal; + } + + // Hashing + private final static int X_PRIME = 1619; + private final static int Y_PRIME = 31337; + private final static int Z_PRIME = 6971; + private final static int W_PRIME = 1013; + + private static int Hash2D(int seed, int x, int y) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + return hash; + } + + private static int Hash3D(int seed, int x, int y, int z) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + hash ^= Z_PRIME * z; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + return hash; + } + + public static int Hash4D(int seed, int x, int y, int z, int w) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + hash ^= Z_PRIME * z; + hash ^= W_PRIME * w; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + return hash; + } + + private static float ValCoord2D(int seed, int x, int y) { + int n = seed; + n ^= X_PRIME * x; + n ^= Y_PRIME * y; + + return (n * n * n * 60493) / (float) 2147483648.0; + } + + private static float ValCoord3D(int seed, int x, int y, int z) { + int n = seed; + n ^= X_PRIME * x; + n ^= Y_PRIME * y; + n ^= Z_PRIME * z; + + return (n * n * n * 60493) / (float) 2147483648.0; + } + + private static float ValCoord4D(int seed, int x, int y, int z, int w) { + int n = seed; + n ^= X_PRIME * x; + n ^= Y_PRIME * y; + n ^= Z_PRIME * z; + n ^= W_PRIME * w; + + return (n * n * n * 60493) / (float) 2147483648.0; + } + + private static float GradCoord2D(int seed, int x, int y, float xd, float yd) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + Float2 g = GRAD_2D[hash & 7]; + + return xd * g.x + yd * g.y; + } + + private static float GradCoord3D(int seed, int x, int y, int z, float xd, float yd, float zd) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + hash ^= Z_PRIME * z; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + Float3 g = GRAD_3D[hash & 15]; + + return xd * g.x + yd * g.y + zd * g.z; + } + + private static float GradCoord4D(int seed, int x, int y, int z, int w, float xd, float yd, float zd, float wd) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + hash ^= Z_PRIME * z; + hash ^= W_PRIME * w; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + hash &= 31; + float a = yd, b = zd, c = wd; // X,Y,Z + switch (hash >> 3) { // OR, DEPENDING ON HIGH ORDER 2 BITS: + case 1: + a = wd; + b = xd; + c = yd; + break; // W,X,Y + case 2: + a = zd; + b = wd; + c = xd; + break; // Z,W,X + case 3: + a = yd; + b = zd; + c = wd; + break; // Y,Z,W + } + return ((hash & 4) == 0 ? -a : a) + ((hash & 2) == 0 ? -b : b) + ((hash & 1) == 0 ? -c : c); + } + + public float GetNoise(float x, float y, float z) { + x *= m_frequency; + y *= m_frequency; + z *= m_frequency; + + switch (m_noiseType) { + case Value: + return SingleValue(m_seed, x, y, z); + case ValueFractal: + switch (m_fractalType) { + case FBM: + return SingleValueFractalFBM(x, y, z); + case Billow: + return SingleValueFractalBillow(x, y, z); + case RigidMulti: + return SingleValueFractalRigidMulti(x, y, z); + default: + return 0; + } + case Perlin: + return SinglePerlin(m_seed, x, y, z); + case PerlinFractal: + switch (m_fractalType) { + case FBM: + return SinglePerlinFractalFBM(x, y, z); + case Billow: + return SinglePerlinFractalBillow(x, y, z); + case RigidMulti: + return SinglePerlinFractalRigidMulti(x, y, z); + default: + return 0; + } + case Simplex: + return SingleSimplex(m_seed, x, y, z); + case SimplexFractal: + switch (m_fractalType) { + case FBM: + return SingleSimplexFractalFBM(x, y, z); + case Billow: + return SingleSimplexFractalBillow(x, y, z); + case RigidMulti: + return SingleSimplexFractalRigidMulti(x, y, z); + default: + return 0; + } + case Cellular: + switch (m_cellularReturnType) { + case CellValue: + case NoiseLookup: + case Distance: + return SingleCellular(x, y, z); + default: + return SingleCellular2Edge(x, y, z); + } + case WhiteNoise: + return GetWhiteNoise(x, y, z); + case Cubic: + return SingleCubic(m_seed, x, y, z); + case CubicFractal: + switch (m_fractalType) { + case FBM: + return SingleCubicFractalFBM(x, y, z); + case Billow: + return SingleCubicFractalBillow(x, y, z); + case RigidMulti: + return SingleCubicFractalRigidMulti(x, y, z); + default: + return 0; + } + default: + return 0; + } + } + + public float GetNoise(float x, float y) { + x *= m_frequency; + y *= m_frequency; + + switch (m_noiseType) { + case Value: + return SingleValue(m_seed, x, y); + case ValueFractal: + switch (m_fractalType) { + case FBM: + return SingleValueFractalFBM(x, y); + case Billow: + return SingleValueFractalBillow(x, y); + case RigidMulti: + return SingleValueFractalRigidMulti(x, y); + default: + return 0; + } + case Perlin: + return SinglePerlin(m_seed, x, y); + case PerlinFractal: + switch (m_fractalType) { + case FBM: + return SinglePerlinFractalFBM(x, y); + case Billow: + return SinglePerlinFractalBillow(x, y); + case RigidMulti: + return SinglePerlinFractalRigidMulti(x, y); + default: + return 0; + } + case Simplex: + return SingleSimplex(m_seed, x, y); + case SimplexFractal: + switch (m_fractalType) { + case FBM: + return SingleSimplexFractalFBM(x, y); + case Billow: + return SingleSimplexFractalBillow(x, y); + case RigidMulti: + return SingleSimplexFractalRigidMulti(x, y); + default: + return 0; + } + case Cellular: + switch (m_cellularReturnType) { + case CellValue: + case NoiseLookup: + case Distance: + return SingleCellular(x, y); + default: + return SingleCellular2Edge(x, y); + } + case WhiteNoise: + return GetWhiteNoise(x, y); + case Cubic: + return SingleCubic(m_seed, x, y); + case CubicFractal: + switch (m_fractalType) { + case FBM: + return SingleCubicFractalFBM(x, y); + case Billow: + return SingleCubicFractalBillow(x, y); + case RigidMulti: + return SingleCubicFractalRigidMulti(x, y); + default: + return 0; + } + default: + return 0; + } + } + + // White Noise + + private int FloatCast2Int(float f) { + int i = Float.floatToRawIntBits(f); + + return i ^ (i >> 16); + } + + public float GetWhiteNoise(float x, float y, float z, float w) { + int xi = FloatCast2Int(x); + int yi = FloatCast2Int(y); + int zi = FloatCast2Int(z); + int wi = FloatCast2Int(w); + + return ValCoord4D(m_seed, xi, yi, zi, wi); + } + + public float GetWhiteNoise(float x, float y, float z) { + int xi = FloatCast2Int(x); + int yi = FloatCast2Int(y); + int zi = FloatCast2Int(z); + + return ValCoord3D(m_seed, xi, yi, zi); + } + + public float GetWhiteNoise(float x, float y) { + int xi = FloatCast2Int(x); + int yi = FloatCast2Int(y); + + return ValCoord2D(m_seed, xi, yi); + } + + public float GetWhiteNoiseInt(int x, int y, int z, int w) { + return ValCoord4D(m_seed, x, y, z, w); + } + + public float GetWhiteNoiseInt(int x, int y, int z) { + return ValCoord3D(m_seed, x, y, z); + } + + public float GetWhiteNoiseInt(int x, int y) { + return ValCoord2D(m_seed, x, y); + } + + // Value Noise + public float GetValueFractal(float x, float y, float z) { + x *= m_frequency; + y *= m_frequency; + z *= m_frequency; + + switch (m_fractalType) { + case FBM: + return SingleValueFractalFBM(x, y, z); + case Billow: + return SingleValueFractalBillow(x, y, z); + case RigidMulti: + return SingleValueFractalRigidMulti(x, y, z); + default: + return 0; + } + } + + private float SingleValueFractalFBM(float x, float y, float z) { + int seed = m_seed; + float sum = SingleValue(seed, x, y, z); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum += SingleValue(++seed, x, y, z) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleValueFractalBillow(float x, float y, float z) { + int seed = m_seed; + float sum = Math.abs(SingleValue(seed, x, y, z)) * 2 - 1; + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum += (Math.abs(SingleValue(++seed, x, y, z)) * 2 - 1) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleValueFractalRigidMulti(float x, float y, float z) { + int seed = m_seed; + float sum = 1 - Math.abs(SingleValue(seed, x, y, z)); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum -= (1 - Math.abs(SingleValue(++seed, x, y, z))) * amp; + } + + return sum; + } + + public float GetValue(float x, float y, float z) { + return SingleValue(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); + } + + private float SingleValue(int seed, float x, float y, float z) { + int x0 = FastFloor(x); + int y0 = FastFloor(y); + int z0 = FastFloor(z); + int x1 = x0 + 1; + int y1 = y0 + 1; + int z1 = z0 + 1; + + float xs, ys, zs; + switch (m_interp) { + default: + case Linear: + xs = x - x0; + ys = y - y0; + zs = z - z0; + break; + case Hermite: + xs = InterpHermiteFunc(x - x0); + ys = InterpHermiteFunc(y - y0); + zs = InterpHermiteFunc(z - z0); + break; + case Quintic: + xs = InterpQuinticFunc(x - x0); + ys = InterpQuinticFunc(y - y0); + zs = InterpQuinticFunc(z - z0); + break; + } + + float xf00 = Lerp(ValCoord3D(seed, x0, y0, z0), ValCoord3D(seed, x1, y0, z0), xs); + float xf10 = Lerp(ValCoord3D(seed, x0, y1, z0), ValCoord3D(seed, x1, y1, z0), xs); + float xf01 = Lerp(ValCoord3D(seed, x0, y0, z1), ValCoord3D(seed, x1, y0, z1), xs); + float xf11 = Lerp(ValCoord3D(seed, x0, y1, z1), ValCoord3D(seed, x1, y1, z1), xs); + + float yf0 = Lerp(xf00, xf10, ys); + float yf1 = Lerp(xf01, xf11, ys); + + return Lerp(yf0, yf1, zs); + } + + public float GetValueFractal(float x, float y) { + x *= m_frequency; + y *= m_frequency; + + switch (m_fractalType) { + case FBM: + return SingleValueFractalFBM(x, y); + case Billow: + return SingleValueFractalBillow(x, y); + case RigidMulti: + return SingleValueFractalRigidMulti(x, y); + default: + return 0; + } + } + + private float SingleValueFractalFBM(float x, float y) { + int seed = m_seed; + float sum = SingleValue(seed, x, y); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum += SingleValue(++seed, x, y) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleValueFractalBillow(float x, float y) { + int seed = m_seed; + float sum = Math.abs(SingleValue(seed, x, y)) * 2 - 1; + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + amp *= m_gain; + sum += (Math.abs(SingleValue(++seed, x, y)) * 2 - 1) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleValueFractalRigidMulti(float x, float y) { + int seed = m_seed; + float sum = 1 - Math.abs(SingleValue(seed, x, y)); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum -= (1 - Math.abs(SingleValue(++seed, x, y))) * amp; + } + + return sum; + } + + public float GetValue(float x, float y) { + return SingleValue(m_seed, x * m_frequency, y * m_frequency); + } + + private float SingleValue(int seed, float x, float y) { + int x0 = FastFloor(x); + int y0 = FastFloor(y); + int x1 = x0 + 1; + int y1 = y0 + 1; + + float xs, ys; + switch (m_interp) { + default: + case Linear: + xs = x - x0; + ys = y - y0; + break; + case Hermite: + xs = InterpHermiteFunc(x - x0); + ys = InterpHermiteFunc(y - y0); + break; + case Quintic: + xs = InterpQuinticFunc(x - x0); + ys = InterpQuinticFunc(y - y0); + break; + } + + float xf0 = Lerp(ValCoord2D(seed, x0, y0), ValCoord2D(seed, x1, y0), xs); + float xf1 = Lerp(ValCoord2D(seed, x0, y1), ValCoord2D(seed, x1, y1), xs); + + return Lerp(xf0, xf1, ys); + } + + // Gradient Noise + public float GetPerlinFractal(float x, float y, float z) { + x *= m_frequency; + y *= m_frequency; + z *= m_frequency; + + switch (m_fractalType) { + case FBM: + return SinglePerlinFractalFBM(x, y, z); + case Billow: + return SinglePerlinFractalBillow(x, y, z); + case RigidMulti: + return SinglePerlinFractalRigidMulti(x, y, z); + default: + return 0; + } + } + + private float SinglePerlinFractalFBM(float x, float y, float z) { + int seed = m_seed; + float sum = SinglePerlin(seed, x, y, z); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum += SinglePerlin(++seed, x, y, z) * amp; + } + + return sum * m_fractalBounding; + } + + private float SinglePerlinFractalBillow(float x, float y, float z) { + int seed = m_seed; + float sum = Math.abs(SinglePerlin(seed, x, y, z)) * 2 - 1; + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum += (Math.abs(SinglePerlin(++seed, x, y, z)) * 2 - 1) * amp; + } + + return sum * m_fractalBounding; + } + + private float SinglePerlinFractalRigidMulti(float x, float y, float z) { + int seed = m_seed; + float sum = 1 - Math.abs(SinglePerlin(seed, x, y, z)); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum -= (1 - Math.abs(SinglePerlin(++seed, x, y, z))) * amp; + } + + return sum; + } + + public float GetPerlin(float x, float y, float z) { + return SinglePerlin(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); + } + + private float SinglePerlin(int seed, float x, float y, float z) { + int x0 = FastFloor(x); + int y0 = FastFloor(y); + int z0 = FastFloor(z); + int x1 = x0 + 1; + int y1 = y0 + 1; + int z1 = z0 + 1; + + float xs, ys, zs; + switch (m_interp) { + default: + case Linear: + xs = x - x0; + ys = y - y0; + zs = z - z0; + break; + case Hermite: + xs = InterpHermiteFunc(x - x0); + ys = InterpHermiteFunc(y - y0); + zs = InterpHermiteFunc(z - z0); + break; + case Quintic: + xs = InterpQuinticFunc(x - x0); + ys = InterpQuinticFunc(y - y0); + zs = InterpQuinticFunc(z - z0); + break; + } + + float xd0 = x - x0; + float yd0 = y - y0; + float zd0 = z - z0; + float xd1 = xd0 - 1; + float yd1 = yd0 - 1; + float zd1 = zd0 - 1; + + float xf00 = Lerp(GradCoord3D(seed, x0, y0, z0, xd0, yd0, zd0), GradCoord3D(seed, x1, y0, z0, xd1, yd0, zd0), xs); + float xf10 = Lerp(GradCoord3D(seed, x0, y1, z0, xd0, yd1, zd0), GradCoord3D(seed, x1, y1, z0, xd1, yd1, zd0), xs); + float xf01 = Lerp(GradCoord3D(seed, x0, y0, z1, xd0, yd0, zd1), GradCoord3D(seed, x1, y0, z1, xd1, yd0, zd1), xs); + float xf11 = Lerp(GradCoord3D(seed, x0, y1, z1, xd0, yd1, zd1), GradCoord3D(seed, x1, y1, z1, xd1, yd1, zd1), xs); + + float yf0 = Lerp(xf00, xf10, ys); + float yf1 = Lerp(xf01, xf11, ys); + + return Lerp(yf0, yf1, zs); + } + + public float GetPerlinFractal(float x, float y) { + x *= m_frequency; + y *= m_frequency; + + switch (m_fractalType) { + case FBM: + return SinglePerlinFractalFBM(x, y); + case Billow: + return SinglePerlinFractalBillow(x, y); + case RigidMulti: + return SinglePerlinFractalRigidMulti(x, y); + default: + return 0; + } + } + + private float SinglePerlinFractalFBM(float x, float y) { + int seed = m_seed; + float sum = SinglePerlin(seed, x, y); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum += SinglePerlin(++seed, x, y) * amp; + } + + return sum * m_fractalBounding; + } + + private float SinglePerlinFractalBillow(float x, float y) { + int seed = m_seed; + float sum = Math.abs(SinglePerlin(seed, x, y)) * 2 - 1; + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum += (Math.abs(SinglePerlin(++seed, x, y)) * 2 - 1) * amp; + } + + return sum * m_fractalBounding; + } + + private float SinglePerlinFractalRigidMulti(float x, float y) { + int seed = m_seed; + float sum = 1 - Math.abs(SinglePerlin(seed, x, y)); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum -= (1 - Math.abs(SinglePerlin(++seed, x, y))) * amp; + } + + return sum; + } + + public float GetPerlin(float x, float y) { + return SinglePerlin(m_seed, x * m_frequency, y * m_frequency); + } + + private float SinglePerlin(int seed, float x, float y) { + int x0 = FastFloor(x); + int y0 = FastFloor(y); + int x1 = x0 + 1; + int y1 = y0 + 1; + + float xs, ys; + switch (m_interp) { + default: + case Linear: + xs = x - x0; + ys = y - y0; + break; + case Hermite: + xs = InterpHermiteFunc(x - x0); + ys = InterpHermiteFunc(y - y0); + break; + case Quintic: + xs = InterpQuinticFunc(x - x0); + ys = InterpQuinticFunc(y - y0); + break; + } + + float xd0 = x - x0; + float yd0 = y - y0; + float xd1 = xd0 - 1; + float yd1 = yd0 - 1; + + float xf0 = Lerp(GradCoord2D(seed, x0, y0, xd0, yd0), GradCoord2D(seed, x1, y0, xd1, yd0), xs); + float xf1 = Lerp(GradCoord2D(seed, x0, y1, xd0, yd1), GradCoord2D(seed, x1, y1, xd1, yd1), xs); + + return Lerp(xf0, xf1, ys); + } + + // Simplex Noise + public float GetSimplexFractal(float x, float y, float z) { + x *= m_frequency; + y *= m_frequency; + z *= m_frequency; + + switch (m_fractalType) { + case FBM: + return SingleSimplexFractalFBM(x, y, z); + case Billow: + return SingleSimplexFractalBillow(x, y, z); + case RigidMulti: + return SingleSimplexFractalRigidMulti(x, y, z); + default: + return 0; + } + } + + private float SingleSimplexFractalFBM(float x, float y, float z) { + int seed = m_seed; + float sum = SingleSimplex(seed, x, y, z); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum += SingleSimplex(++seed, x, y, z) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleSimplexFractalBillow(float x, float y, float z) { + int seed = m_seed; + float sum = Math.abs(SingleSimplex(seed, x, y, z)) * 2 - 1; + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum += (Math.abs(SingleSimplex(++seed, x, y, z)) * 2 - 1) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleSimplexFractalRigidMulti(float x, float y, float z) { + int seed = m_seed; + float sum = 1 - Math.abs(SingleSimplex(seed, x, y, z)); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum -= (1 - Math.abs(SingleSimplex(++seed, x, y, z))) * amp; + } + + return sum; + } + + public float GetSimplex(float x, float y, float z) { + return SingleSimplex(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); + } + + private final static float F3 = (float) (1.0 / 3.0); + private final static float G3 = (float) (1.0 / 6.0); + private final static float G33 = G3 * 3 - 1; + + private float SingleSimplex(int seed, float x, float y, float z) { + float t = (x + y + z) * F3; + int i = FastFloor(x + t); + int j = FastFloor(y + t); + int k = FastFloor(z + t); + + t = (i + j + k) * G3; + float x0 = x - (i - t); + float y0 = y - (j - t); + float z0 = z - (k - t); + + int i1, j1, k1; + int i2, j2, k2; + + if (x0 >= y0) { + if (y0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } else if (x0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 0; + k2 = 1; + } else // x0 < z0 + { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 1; + j2 = 0; + k2 = 1; + } + } else // x0 < y0 + { + if (y0 < z0) { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 0; + j2 = 1; + k2 = 1; + } else if (x0 < z0) { + i1 = 0; + j1 = 1; + k1 = 0; + i2 = 0; + j2 = 1; + k2 = 1; + } else // x0 >= z0 + { + i1 = 0; + j1 = 1; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } + } + + float x1 = x0 - i1 + G3; + float y1 = y0 - j1 + G3; + float z1 = z0 - k1 + G3; + float x2 = x0 - i2 + F3; + float y2 = y0 - j2 + F3; + float z2 = z0 - k2 + F3; + float x3 = x0 + G33; + float y3 = y0 + G33; + float z3 = z0 + G33; + + float n0, n1, n2, n3; + + t = (float) 0.6 - x0 * x0 - y0 * y0 - z0 * z0; + if (t < 0) n0 = 0; + else { + t *= t; + n0 = t * t * GradCoord3D(seed, i, j, k, x0, y0, z0); + } + + t = (float) 0.6 - x1 * x1 - y1 * y1 - z1 * z1; + if (t < 0) n1 = 0; + else { + t *= t; + n1 = t * t * GradCoord3D(seed, i + i1, j + j1, k + k1, x1, y1, z1); + } + + t = (float) 0.6 - x2 * x2 - y2 * y2 - z2 * z2; + if (t < 0) n2 = 0; + else { + t *= t; + n2 = t * t * GradCoord3D(seed, i + i2, j + j2, k + k2, x2, y2, z2); + } + + t = (float) 0.6 - x3 * x3 - y3 * y3 - z3 * z3; + if (t < 0) n3 = 0; + else { + t *= t; + n3 = t * t * GradCoord3D(seed, i + 1, j + 1, k + 1, x3, y3, z3); + } + + return 32 * (n0 + n1 + n2 + n3); + } + + public float GetSimplexFractal(float x, float y) { + x *= m_frequency; + y *= m_frequency; + + switch (m_fractalType) { + case FBM: + return SingleSimplexFractalFBM(x, y); + case Billow: + return SingleSimplexFractalBillow(x, y); + case RigidMulti: + return SingleSimplexFractalRigidMulti(x, y); + default: + return 0; + } + } + + private float SingleSimplexFractalFBM(float x, float y) { + int seed = m_seed; + float sum = SingleSimplex(seed, x, y); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum += SingleSimplex(++seed, x, y) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleSimplexFractalBillow(float x, float y) { + int seed = m_seed; + float sum = Math.abs(SingleSimplex(seed, x, y)) * 2 - 1; + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum += (Math.abs(SingleSimplex(++seed, x, y)) * 2 - 1) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleSimplexFractalRigidMulti(float x, float y) { + int seed = m_seed; + float sum = 1 - Math.abs(SingleSimplex(seed, x, y)); + float amp = 1; + + for (int i = 1; i < m_octaves; i++) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum -= (1 - Math.abs(SingleSimplex(++seed, x, y))) * amp; + } + + return sum; + } + + public float GetSimplex(float x, float y) { + return SingleSimplex(m_seed, x * m_frequency, y * m_frequency); + } + + private final static float F2 = (float) (1.0 / 2.0); + private final static float G2 = (float) (1.0 / 4.0); + + private float SingleSimplex(int seed, float x, float y) { + float t = (x + y) * F2; + int i = FastFloor(x + t); + int j = FastFloor(y + t); + + t = (i + j) * G2; + float X0 = i - t; + float Y0 = j - t; + + float x0 = x - X0; + float y0 = y - Y0; + + int i1, j1; + if (x0 > y0) { + i1 = 1; + j1 = 0; + } else { + i1 = 0; + j1 = 1; + } + + float x1 = x0 - i1 + G2; + float y1 = y0 - j1 + G2; + float x2 = x0 - 1 + F2; + float y2 = y0 - 1 + F2; + + float n0, n1, n2; + + t = (float) 0.5 - x0 * x0 - y0 * y0; + if (t < 0) n0 = 0; + else { + t *= t; + n0 = t * t * GradCoord2D(seed, i, j, x0, y0); + } + + t = (float) 0.5 - x1 * x1 - y1 * y1; + if (t < 0) n1 = 0; + else { + t *= t; + n1 = t * t * GradCoord2D(seed, i + i1, j + j1, x1, y1); + } + + t = (float) 0.5 - x2 * x2 - y2 * y2; + if (t < 0) n2 = 0; + else { + t *= t; + n2 = t * t * GradCoord2D(seed, i + 1, j + 1, x2, y2); + } + + return 50 * (n0 + n1 + n2); + } + + public float GetSimplex(float x, float y, float z, float w) { + return SingleSimplex(m_seed, x * m_frequency, y * m_frequency, z * m_frequency, w * m_frequency); + } + + private static final byte[] SIMPLEX_4D = + { + 0, 1, 2, 3, 0, 1, 3, 2, 0, 0, 0, 0, 0, 2, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, + 0, 2, 1, 3, 0, 0, 0, 0, 0, 3, 1, 2, 0, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 3, 0, 0, 0, 0, 1, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 1, 2, 3, 1, 0, + 1, 0, 2, 3, 1, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 1, 0, 0, 0, 0, 2, 1, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 2, 3, 0, 2, 1, 0, 0, 0, 0, 3, 1, 2, 0, + 2, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 2, 0, 0, 0, 0, 3, 2, 0, 1, 3, 2, 1, 0 + }; + + private final static float F4 = (float) ((2.23606797 - 1.0) / 4.0); + private final static float G4 = (float) ((5.0 - 2.23606797) / 20.0); + + private float SingleSimplex(int seed, float x, float y, float z, float w) { + float n0, n1, n2, n3, n4; + float t = (x + y + z + w) * F4; + int i = FastFloor(x + t); + int j = FastFloor(y + t); + int k = FastFloor(z + t); + int l = FastFloor(w + t); + t = (i + j + k + l) * G4; + float X0 = i - t; + float Y0 = j - t; + float Z0 = k - t; + float W0 = l - t; + float x0 = x - X0; + float y0 = y - Y0; + float z0 = z - Z0; + float w0 = w - W0; + + int c = (x0 > y0) ? 32 : 0; + c += (x0 > z0) ? 16 : 0; + c += (y0 > z0) ? 8 : 0; + c += (x0 > w0) ? 4 : 0; + c += (y0 > w0) ? 2 : 0; + c += (z0 > w0) ? 1 : 0; + c <<= 2; + + int i1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; + int i2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; + int i3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; + int j1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; + int j2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; + int j3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; + int k1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; + int k2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; + int k3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; + int l1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; + int l2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; + int l3 = SIMPLEX_4D[c] >= 1 ? 1 : 0; + + float x1 = x0 - i1 + G4; + float y1 = y0 - j1 + G4; + float z1 = z0 - k1 + G4; + float w1 = w0 - l1 + G4; + float x2 = x0 - i2 + 2 * G4; + float y2 = y0 - j2 + 2 * G4; + float z2 = z0 - k2 + 2 * G4; + float w2 = w0 - l2 + 2 * G4; + float x3 = x0 - i3 + 3 * G4; + float y3 = y0 - j3 + 3 * G4; + float z3 = z0 - k3 + 3 * G4; + float w3 = w0 - l3 + 3 * G4; + float x4 = x0 - 1 + 4 * G4; + float y4 = y0 - 1 + 4 * G4; + float z4 = z0 - 1 + 4 * G4; + float w4 = w0 - 1 + 4 * G4; + + t = (float) 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; + if (t < 0) n0 = 0; + else { + t *= t; + n0 = t * t * GradCoord4D(seed, i, j, k, l, x0, y0, z0, w0); + } + t = (float) 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; + if (t < 0) n1 = 0; + else { + t *= t; + n1 = t * t * GradCoord4D(seed, i + i1, j + j1, k + k1, l + l1, x1, y1, z1, w1); + } + t = (float) 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; + if (t < 0) n2 = 0; + else { + t *= t; + n2 = t * t * GradCoord4D(seed, i + i2, j + j2, k + k2, l + l2, x2, y2, z2, w2); + } + t = (float) 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; + if (t < 0) n3 = 0; + else { + t *= t; + n3 = t * t * GradCoord4D(seed, i + i3, j + j3, k + k3, l + l3, x3, y3, z3, w3); + } + t = (float) 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; + if (t < 0) n4 = 0; + else { + t *= t; + n4 = t * t * GradCoord4D(seed, i + 1, j + 1, k + 1, l + 1, x4, y4, z4, w4); + } + + return 27 * (n0 + n1 + n2 + n3 + n4); + } + + // Cubic Noise + public float GetCubicFractal(float x, float y, float z) { + x *= m_frequency; + y *= m_frequency; + z *= m_frequency; + + switch (m_fractalType) { + case FBM: + return SingleCubicFractalFBM(x, y, z); + case Billow: + return SingleCubicFractalBillow(x, y, z); + case RigidMulti: + return SingleCubicFractalRigidMulti(x, y, z); + default: + return 0; + } + } + + private float SingleCubicFractalFBM(float x, float y, float z) { + int seed = m_seed; + float sum = SingleCubic(seed, x, y, z); + float amp = 1; + int i = 0; + + while (++i < m_octaves) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum += SingleCubic(++seed, x, y, z) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleCubicFractalBillow(float x, float y, float z) { + int seed = m_seed; + float sum = Math.abs(SingleCubic(seed, x, y, z)) * 2 - 1; + float amp = 1; + int i = 0; + + while (++i < m_octaves) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum += (Math.abs(SingleCubic(++seed, x, y, z)) * 2 - 1) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleCubicFractalRigidMulti(float x, float y, float z) { + int seed = m_seed; + float sum = 1 - Math.abs(SingleCubic(seed, x, y, z)); + float amp = 1; + int i = 0; + + while (++i < m_octaves) { + x *= m_lacunarity; + y *= m_lacunarity; + z *= m_lacunarity; + + amp *= m_gain; + sum -= (1 - Math.abs(SingleCubic(++seed, x, y, z))) * amp; + } + + return sum; + } + + public float GetCubic(float x, float y, float z) { + return SingleCubic(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); + } + + private final static float CUBIC_3D_BOUNDING = 1 / (float) (1.5 * 1.5 * 1.5); + + private float SingleCubic(int seed, float x, float y, float z) { + int x1 = FastFloor(x); + int y1 = FastFloor(y); + int z1 = FastFloor(z); + + int x0 = x1 - 1; + int y0 = y1 - 1; + int z0 = z1 - 1; + int x2 = x1 + 1; + int y2 = y1 + 1; + int z2 = z1 + 1; + int x3 = x1 + 2; + int y3 = y1 + 2; + int z3 = z1 + 2; + + float xs = x - (float) x1; + float ys = y - (float) y1; + float zs = z - (float) z1; + + return CubicLerp( + CubicLerp( + CubicLerp(ValCoord3D(seed, x0, y0, z0), ValCoord3D(seed, x1, y0, z0), ValCoord3D(seed, x2, y0, z0), ValCoord3D(seed, x3, y0, z0), xs), + CubicLerp(ValCoord3D(seed, x0, y1, z0), ValCoord3D(seed, x1, y1, z0), ValCoord3D(seed, x2, y1, z0), ValCoord3D(seed, x3, y1, z0), xs), + CubicLerp(ValCoord3D(seed, x0, y2, z0), ValCoord3D(seed, x1, y2, z0), ValCoord3D(seed, x2, y2, z0), ValCoord3D(seed, x3, y2, z0), xs), + CubicLerp(ValCoord3D(seed, x0, y3, z0), ValCoord3D(seed, x1, y3, z0), ValCoord3D(seed, x2, y3, z0), ValCoord3D(seed, x3, y3, z0), xs), + ys), + CubicLerp( + CubicLerp(ValCoord3D(seed, x0, y0, z1), ValCoord3D(seed, x1, y0, z1), ValCoord3D(seed, x2, y0, z1), ValCoord3D(seed, x3, y0, z1), xs), + CubicLerp(ValCoord3D(seed, x0, y1, z1), ValCoord3D(seed, x1, y1, z1), ValCoord3D(seed, x2, y1, z1), ValCoord3D(seed, x3, y1, z1), xs), + CubicLerp(ValCoord3D(seed, x0, y2, z1), ValCoord3D(seed, x1, y2, z1), ValCoord3D(seed, x2, y2, z1), ValCoord3D(seed, x3, y2, z1), xs), + CubicLerp(ValCoord3D(seed, x0, y3, z1), ValCoord3D(seed, x1, y3, z1), ValCoord3D(seed, x2, y3, z1), ValCoord3D(seed, x3, y3, z1), xs), + ys), + CubicLerp( + CubicLerp(ValCoord3D(seed, x0, y0, z2), ValCoord3D(seed, x1, y0, z2), ValCoord3D(seed, x2, y0, z2), ValCoord3D(seed, x3, y0, z2), xs), + CubicLerp(ValCoord3D(seed, x0, y1, z2), ValCoord3D(seed, x1, y1, z2), ValCoord3D(seed, x2, y1, z2), ValCoord3D(seed, x3, y1, z2), xs), + CubicLerp(ValCoord3D(seed, x0, y2, z2), ValCoord3D(seed, x1, y2, z2), ValCoord3D(seed, x2, y2, z2), ValCoord3D(seed, x3, y2, z2), xs), + CubicLerp(ValCoord3D(seed, x0, y3, z2), ValCoord3D(seed, x1, y3, z2), ValCoord3D(seed, x2, y3, z2), ValCoord3D(seed, x3, y3, z2), xs), + ys), + CubicLerp( + CubicLerp(ValCoord3D(seed, x0, y0, z3), ValCoord3D(seed, x1, y0, z3), ValCoord3D(seed, x2, y0, z3), ValCoord3D(seed, x3, y0, z3), xs), + CubicLerp(ValCoord3D(seed, x0, y1, z3), ValCoord3D(seed, x1, y1, z3), ValCoord3D(seed, x2, y1, z3), ValCoord3D(seed, x3, y1, z3), xs), + CubicLerp(ValCoord3D(seed, x0, y2, z3), ValCoord3D(seed, x1, y2, z3), ValCoord3D(seed, x2, y2, z3), ValCoord3D(seed, x3, y2, z3), xs), + CubicLerp(ValCoord3D(seed, x0, y3, z3), ValCoord3D(seed, x1, y3, z3), ValCoord3D(seed, x2, y3, z3), ValCoord3D(seed, x3, y3, z3), xs), + ys), + zs) * CUBIC_3D_BOUNDING; + } + + + public float GetCubicFractal(float x, float y) { + x *= m_frequency; + y *= m_frequency; + + switch (m_fractalType) { + case FBM: + return SingleCubicFractalFBM(x, y); + case Billow: + return SingleCubicFractalBillow(x, y); + case RigidMulti: + return SingleCubicFractalRigidMulti(x, y); + default: + return 0; + } + } + + private float SingleCubicFractalFBM(float x, float y) { + int seed = m_seed; + float sum = SingleCubic(seed, x, y); + float amp = 1; + int i = 0; + + while (++i < m_octaves) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum += SingleCubic(++seed, x, y) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleCubicFractalBillow(float x, float y) { + int seed = m_seed; + float sum = Math.abs(SingleCubic(seed, x, y)) * 2 - 1; + float amp = 1; + int i = 0; + + while (++i < m_octaves) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum += (Math.abs(SingleCubic(++seed, x, y)) * 2 - 1) * amp; + } + + return sum * m_fractalBounding; + } + + private float SingleCubicFractalRigidMulti(float x, float y) { + int seed = m_seed; + float sum = 1 - Math.abs(SingleCubic(seed, x, y)); + float amp = 1; + int i = 0; + + while (++i < m_octaves) { + x *= m_lacunarity; + y *= m_lacunarity; + + amp *= m_gain; + sum -= (1 - Math.abs(SingleCubic(++seed, x, y))) * amp; + } + + return sum; + } + + public float GetCubic(float x, float y) { + x *= m_frequency; + y *= m_frequency; + + return SingleCubic(0, x, y); + } + + private final static float CUBIC_2D_BOUNDING = 1 / (float) (1.5 * 1.5); + + private float SingleCubic(int seed, float x, float y) { + int x1 = FastFloor(x); + int y1 = FastFloor(y); + + int x0 = x1 - 1; + int y0 = y1 - 1; + int x2 = x1 + 1; + int y2 = y1 + 1; + int x3 = x1 + 2; + int y3 = y1 + 2; + + float xs = x - (float) x1; + float ys = y - (float) y1; + + return CubicLerp( + CubicLerp(ValCoord2D(seed, x0, y0), ValCoord2D(seed, x1, y0), ValCoord2D(seed, x2, y0), ValCoord2D(seed, x3, y0), + xs), + CubicLerp(ValCoord2D(seed, x0, y1), ValCoord2D(seed, x1, y1), ValCoord2D(seed, x2, y1), ValCoord2D(seed, x3, y1), + xs), + CubicLerp(ValCoord2D(seed, x0, y2), ValCoord2D(seed, x1, y2), ValCoord2D(seed, x2, y2), ValCoord2D(seed, x3, y2), + xs), + CubicLerp(ValCoord2D(seed, x0, y3), ValCoord2D(seed, x1, y3), ValCoord2D(seed, x2, y3), ValCoord2D(seed, x3, y3), + xs), + ys) * CUBIC_2D_BOUNDING; + } + + // Cellular Noise + public float GetCellular(float x, float y, float z) { + x *= m_frequency; + y *= m_frequency; + z *= m_frequency; + + switch (m_cellularReturnType) { + case CellValue: + case NoiseLookup: + case Distance: + return SingleCellular(x, y, z); + default: + return SingleCellular2Edge(x, y, z); + } + } + + private float SingleCellular(float x, float y, float z) { + int xr = FastRound(x); + int yr = FastRound(y); + int zr = FastRound(z); + + float distance = 999999; + int xc = 0, yc = 0, zc = 0; + + switch (m_cellularDistanceFunction) { + case Euclidean: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + for (int zi = zr - 1; zi <= zr + 1; zi++) { + Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + float vecZ = zi - z + vec.z; + + float newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; + + if (newDistance < distance) { + distance = newDistance; + xc = xi; + yc = yi; + zc = zi; + } + } + } + } + break; + case Manhattan: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + for (int zi = zr - 1; zi <= zr + 1; zi++) { + Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + float vecZ = zi - z + vec.z; + + float newDistance = Math.abs(vecX) + Math.abs(vecY) + Math.abs(vecZ); + + if (newDistance < distance) { + distance = newDistance; + xc = xi; + yc = yi; + zc = zi; + } + } + } + } + break; + case Natural: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + for (int zi = zr - 1; zi <= zr + 1; zi++) { + Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + float vecZ = zi - z + vec.z; + + float newDistance = (Math.abs(vecX) + Math.abs(vecY) + Math.abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ); + + if (newDistance < distance) { + distance = newDistance; + xc = xi; + yc = yi; + zc = zi; + } + } + } + } + break; + } + + switch (m_cellularReturnType) { + case CellValue: + return ValCoord3D(0, xc, yc, zc); + + case NoiseLookup: + Float3 vec = CELL_3D[Hash3D(m_seed, xc, yc, zc) & 255]; + return m_cellularNoiseLookup.GetNoise(xc + vec.x, yc + vec.y, zc + vec.z); + + case Distance: + return distance - 1; + default: + return 0; + } + } + + private float SingleCellular2Edge(float x, float y, float z) { + int xr = FastRound(x); + int yr = FastRound(y); + int zr = FastRound(z); + + float distance = 999999; + float distance2 = 999999; + + switch (m_cellularDistanceFunction) { + case Euclidean: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + for (int zi = zr - 1; zi <= zr + 1; zi++) { + Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + float vecZ = zi - z + vec.z; + + float newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; + + distance2 = Math.max(Math.min(distance2, newDistance), distance); + distance = Math.min(distance, newDistance); + } + } + } + break; + case Manhattan: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + for (int zi = zr - 1; zi <= zr + 1; zi++) { + Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + float vecZ = zi - z + vec.z; + + float newDistance = Math.abs(vecX) + Math.abs(vecY) + Math.abs(vecZ); + + distance2 = Math.max(Math.min(distance2, newDistance), distance); + distance = Math.min(distance, newDistance); + } + } + } + break; + case Natural: + for (int xi = xr - 1; xi <= xr + 1; xi++) { + for (int yi = yr - 1; yi <= yr + 1; yi++) { + for (int zi = zr - 1; zi <= zr + 1; zi++) { + Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; + + float vecX = xi - x + vec.x; + float vecY = yi - y + vec.y; + float vecZ = zi - z + vec.z; + + float newDistance = (Math.abs(vecX) + Math.abs(vecY) + Math.abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ); + + distance2 = Math.max(Math.min(distance2, newDistance), distance); + distance = Math.min(distance, newDistance); + } + } + } + break; + default: + break; + } + + switch (m_cellularReturnType) { + case Distance2: + return distance2 - 1; + case Distance2Add: + return distance2 + distance - 1; + case Distance2Sub: + return distance2 - distance - 1; + case Distance2Mul: + return distance2 * distance - 1; + case Distance2Div: + return distance / distance2 - 1; + default: + return 0; + } + } + + public float GetCellular(float x, float y) { + x *= m_frequency; + y *= m_frequency; + + switch (m_cellularReturnType) { + case CellValue: + case NoiseLookup: + case Distance: + return SingleCellular(x, y); + default: + return SingleCellular2Edge(x, y); + } + } + + private float SingleCellular(float x, float y) { + 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 ValCoord2D(0, xc, yc); + + 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); + + float distance = 999999; + float distance2 = 999999; + + 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; + + distance2 = Math.max(Math.min(distance2, newDistance), distance); + distance = Math.min(distance, newDistance); + } + } + 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); + + distance2 = Math.max(Math.min(distance2, newDistance), distance); + distance = Math.min(distance, newDistance); + } + } + 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); + + distance2 = Math.max(Math.min(distance2, newDistance), distance); + distance = Math.min(distance, newDistance); + } + } + break; + } + + switch (m_cellularReturnType) { + case Distance2: + return distance2 - 1; + case Distance2Add: + return distance2 + distance - 1; + case Distance2Sub: + return distance2 - distance - 1; + case Distance2Mul: + return distance2 * distance - 1; + case Distance2Div: + return distance / distance2 - 1; + default: + return 0; + } + } + + public void GradientPerturb(Vector3f v3) { + SingleGradientPerturb(m_seed, m_gradientPerturbAmp, m_frequency, v3); + } + + public void GradientPerturbFractal(Vector3f v3) { + int seed = m_seed; + float amp = m_gradientPerturbAmp * m_fractalBounding; + float freq = m_frequency; + + SingleGradientPerturb(seed, amp, m_frequency, v3); + + for (int i = 1; i < m_octaves; i++) { + freq *= m_lacunarity; + amp *= m_gain; + SingleGradientPerturb(++seed, amp, freq, v3); + } + } + + private void SingleGradientPerturb(int seed, float perturbAmp, float frequency, Vector3f v3) { + float xf = v3.x * frequency; + float yf = v3.y * frequency; + float zf = v3.z * frequency; + + int x0 = FastFloor(xf); + int y0 = FastFloor(yf); + int z0 = FastFloor(zf); + int x1 = x0 + 1; + int y1 = y0 + 1; + int z1 = z0 + 1; + + float xs, ys, zs; + switch (m_interp) { + default: + case Linear: + xs = xf - x0; + ys = yf - y0; + zs = zf - z0; + break; + case Hermite: + xs = InterpHermiteFunc(xf - x0); + ys = InterpHermiteFunc(yf - y0); + zs = InterpHermiteFunc(zf - z0); + break; + case Quintic: + xs = InterpQuinticFunc(xf - x0); + ys = InterpQuinticFunc(yf - y0); + zs = InterpQuinticFunc(zf - z0); + break; + } + + Float3 vec0 = CELL_3D[Hash3D(seed, x0, y0, z0) & 255]; + Float3 vec1 = CELL_3D[Hash3D(seed, x1, y0, z0) & 255]; + + float lx0x = Lerp(vec0.x, vec1.x, xs); + float ly0x = Lerp(vec0.y, vec1.y, xs); + float lz0x = Lerp(vec0.z, vec1.z, xs); + + vec0 = CELL_3D[Hash3D(seed, x0, y1, z0) & 255]; + vec1 = CELL_3D[Hash3D(seed, x1, y1, z0) & 255]; + + float lx1x = Lerp(vec0.x, vec1.x, xs); + float ly1x = Lerp(vec0.y, vec1.y, xs); + float lz1x = Lerp(vec0.z, vec1.z, xs); + + float lx0y = Lerp(lx0x, lx1x, ys); + float ly0y = Lerp(ly0x, ly1x, ys); + float lz0y = Lerp(lz0x, lz1x, ys); + + vec0 = CELL_3D[Hash3D(seed, x0, y0, z1) & 255]; + vec1 = CELL_3D[Hash3D(seed, x1, y0, z1) & 255]; + + lx0x = Lerp(vec0.x, vec1.x, xs); + ly0x = Lerp(vec0.y, vec1.y, xs); + lz0x = Lerp(vec0.z, vec1.z, xs); + + vec0 = CELL_3D[Hash3D(seed, x0, y1, z1) & 255]; + vec1 = CELL_3D[Hash3D(seed, x1, y1, z1) & 255]; + + lx1x = Lerp(vec0.x, vec1.x, xs); + ly1x = Lerp(vec0.y, vec1.y, xs); + lz1x = Lerp(vec0.z, vec1.z, xs); + + v3.x += Lerp(lx0y, Lerp(lx0x, lx1x, ys), zs) * perturbAmp; + v3.y += Lerp(ly0y, Lerp(ly0x, ly1x, ys), zs) * perturbAmp; + v3.z += Lerp(lz0y, Lerp(lz0x, lz1x, ys), zs) * perturbAmp; + } + + public void GradientPerturb(Vector2f v2) { + SingleGradientPerturb(m_seed, m_gradientPerturbAmp, m_frequency, v2); + } + + public void GradientPerturbFractal(Vector2f v2) { + int seed = m_seed; + float amp = m_gradientPerturbAmp * m_fractalBounding; + float freq = m_frequency; + + SingleGradientPerturb(seed, amp, m_frequency, v2); + + for (int i = 1; i < m_octaves; i++) { + freq *= m_lacunarity; + amp *= m_gain; + SingleGradientPerturb(++seed, amp, freq, v2); + } + } + + private void SingleGradientPerturb(int seed, float perturbAmp, float frequency, Vector2f v2) { + float xf = v2.x * frequency; + float yf = v2.y * frequency; + + int x0 = FastFloor(xf); + int y0 = FastFloor(yf); + int x1 = x0 + 1; + int y1 = y0 + 1; + + float xs, ys; + switch (m_interp) { + default: + case Linear: + xs = xf - x0; + ys = yf - y0; + break; + case Hermite: + xs = InterpHermiteFunc(xf - x0); + ys = InterpHermiteFunc(yf - y0); + break; + case Quintic: + xs = InterpQuinticFunc(xf - x0); + ys = InterpQuinticFunc(yf - y0); + break; + } + + Float2 vec0 = CELL_2D[Hash2D(seed, x0, y0) & 255]; + Float2 vec1 = CELL_2D[Hash2D(seed, x1, y0) & 255]; + + float lx0x = Lerp(vec0.x, vec1.x, xs); + float ly0x = Lerp(vec0.y, vec1.y, xs); + + vec0 = CELL_2D[Hash2D(seed, x0, y1) & 255]; + vec1 = CELL_2D[Hash2D(seed, x1, y1) & 255]; + + float lx1x = Lerp(vec0.x, vec1.x, xs); + float ly1x = Lerp(vec0.y, vec1.y, xs); + + v2.x += Lerp(lx0x, lx1x, ys) * perturbAmp; + v2.y += Lerp(ly0x, ly1x, ys) * perturbAmp; + } + +} \ No newline at end of file diff --git a/src/main/java/ninja/bytecode/iris/util/FileWatcher.java b/src/main/java/ninja/bytecode/iris/util/FileWatcher.java new file mode 100644 index 000000000..387576460 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/FileWatcher.java @@ -0,0 +1,42 @@ +package ninja.bytecode.iris.util; + +import java.io.File; + +import lombok.Getter; + +public class FileWatcher +{ + @Getter + private final File file; + private boolean exists; + private long lastModified; + private long size; + + public FileWatcher(File file) + { + this.file = file; + readProperties(); + } + + private void readProperties() + { + exists = file.exists(); + lastModified = exists ? file.lastModified() : -1; + size = exists ? file.length() : -1; + } + + public boolean checkModified() + { + long m = lastModified; + long g = size; + boolean mod = false; + readProperties(); + + if(lastModified != m || g != size) + { + mod = true; + } + + return mod; + } +} diff --git a/src/main/java/ninja/bytecode/iris/util/GenLayer.java b/src/main/java/ninja/bytecode/iris/util/GenLayer.java new file mode 100644 index 000000000..bca1bcc9f --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/GenLayer.java @@ -0,0 +1,17 @@ +package ninja.bytecode.iris.util; + +import ninja.bytecode.iris.IrisGenerator; + +public abstract class GenLayer +{ + protected final RNG rng; + protected final IrisGenerator iris; + + public GenLayer(IrisGenerator iris, RNG rng) + { + this.iris = iris; + this.rng = rng; + } + + public abstract double generate(double x, double z); +} diff --git a/src/main/java/ninja/bytecode/iris/util/IrisInterpolation.java b/src/main/java/ninja/bytecode/iris/util/IrisInterpolation.java index 89e87f0a7..277b53fe8 100644 --- a/src/main/java/ninja/bytecode/iris/util/IrisInterpolation.java +++ b/src/main/java/ninja/bytecode/iris/util/IrisInterpolation.java @@ -1,5 +1,7 @@ package ninja.bytecode.iris.util; +import ninja.bytecode.iris.object.InterpolationMethod; + public class IrisInterpolation { public static double bezier(double t) @@ -18,6 +20,11 @@ public class IrisInterpolation return a + (f * (b - a)); } + public static float lerpf(float a, float b, float f) + { + return a + (f * (b - a)); + } + public static double lerpBezier(double a, double b, double f) { return a + (bezier(f) * (b - a)); @@ -181,6 +188,26 @@ public class IrisInterpolation //@done } + public static double getNoise(InterpolationMethod method, int x, int z, double rad, NoiseProvider n) + { + if(method.equals(InterpolationMethod.BILINEAR)) + { + return getBilinearNoise(x, z, rad, n); + } + + else if(method.equals(InterpolationMethod.BICUBIC)) + { + return getBicubicNoise(x, z, rad, n); + } + + else if(method.equals(InterpolationMethod.HERMITE)) + { + return getHermiteNoise(x, z, rad, n); + } + + return n.noise(x, z); + } + public static double getHermiteNoise(int x, int z, double rad, NoiseProvider n) { int fx = (int) Math.floor(x / rad); diff --git a/src/main/java/ninja/bytecode/iris/util/KList.java b/src/main/java/ninja/bytecode/iris/util/KList.java index 2d06046aa..2778aa750 100644 --- a/src/main/java/ninja/bytecode/iris/util/KList.java +++ b/src/main/java/ninja/bytecode/iris/util/KList.java @@ -639,4 +639,10 @@ public class KList extends ArrayList implements List remove(t); return this; } + + public KList qadd(T t) + { + add(t); + return this; + } } diff --git a/src/main/java/ninja/bytecode/iris/util/M.java b/src/main/java/ninja/bytecode/iris/util/M.java index b832a299f..60d3bfd30 100644 --- a/src/main/java/ninja/bytecode/iris/util/M.java +++ b/src/main/java/ninja/bytecode/iris/util/M.java @@ -151,6 +151,11 @@ public class M return (T) Double.valueOf(Math.min(max.doubleValue(), Math.max(min.doubleValue(), value.doubleValue()))); } + public static int iclip(int value, int min, int max) + { + return Math.min(max, Math.max(min, value)); + } + /** * Get true or false based on random percent * diff --git a/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java b/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java new file mode 100644 index 000000000..65e00e3be --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java @@ -0,0 +1,95 @@ +package ninja.bytecode.iris.util; + +import java.io.File; + +import com.google.gson.Gson; + +import ninja.bytecode.iris.Iris; + +public class ResourceLoader +{ + private File root; + private String folderName; + private String resourceTypeName; + private KMap loadCache; + private KList folderCache; + private Class objectClass; + + public ResourceLoader(File root, String folderName, String resourceTypeName, Class objectClass) + { + this.objectClass = objectClass; + this.resourceTypeName = resourceTypeName; + this.root = root; + this.folderName = folderName; + loadCache = new KMap<>(); + } + + public T load(String name) + { + String key = name + "-" + objectClass.getCanonicalName(); + + if(loadCache.containsKey(key)) + { + return loadCache.get(key); + } + + for(File i : getFolders()) + { + for(File j : i.listFiles()) + { + if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) + { + try + { + T t = new Gson().fromJson(IO.readAll(j), objectClass); + loadCache.put(key, t); + Iris.hotloader.track(j); + Iris.info("Loading " + resourceTypeName + ": " + j.getPath()); + + return t; + } + + catch(Throwable e) + { + Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage()); + } + } + } + } + + Iris.warn("Couldn't find " + resourceTypeName + ": " + name); + + return null; + } + + public KList getFolders() + { + if(folderCache == null) + { + folderCache = new KList<>(); + + for(File i : root.listFiles()) + { + if(i.isDirectory()) + { + for(File j : i.listFiles()) + { + if(j.isDirectory() && j.getName().equals(folderName)) + { + folderCache.add(j); + break; + } + } + } + } + } + + return folderCache; + } + + public void clearCache() + { + loadCache.clear(); + folderCache = null; + } +}