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 extends T> objectClass;
+
+ public ResourceLoader(File root, String folderName, String resourceTypeName, Class extends T> 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;
+ }
+}