diff --git a/pom.xml b/pom.xml
index f810c474f..c631d0aad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -83,7 +83,7 @@
org.polydev
gaea
- 1.3.0
+ 1.3.4
diff --git a/src/main/java/com/dfsek/terra/TerraChunkGenerator.java b/src/main/java/com/dfsek/terra/TerraChunkGenerator.java
index 48f9a9c8a..3e53e7f69 100644
--- a/src/main/java/com/dfsek/terra/TerraChunkGenerator.java
+++ b/src/main/java/com/dfsek/terra/TerraChunkGenerator.java
@@ -1,8 +1,11 @@
package com.dfsek.terra;
import com.dfsek.terra.biome.TerraBiomeGrid;
+import com.dfsek.terra.config.WorldConfig;
+import com.dfsek.terra.population.FaunaPopulator;
import org.bukkit.Material;
import org.bukkit.World;
+import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.biome.BiomeGrid;
@@ -11,6 +14,7 @@ import org.polydev.gaea.generation.GenerationPopulator;
import org.polydev.gaea.math.FastNoise;
import org.polydev.gaea.math.InterpolationType;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
@@ -23,10 +27,12 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
@Override
public ChunkData generateBase(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, FastNoise fastNoise) {
ChunkData chunk = createChunkData(world);
+ int sea = WorldConfig.fromWorld(world).seaLevel;
for(byte x = 0; x < 16; x++) {
for(int y = 0; y < 256; y++) {
for(byte z = 0; z < 16; z++) {
if(super.getInterpolatedNoise(x, y, z) > 0) chunk.setBlock(x, y, z, Material.STONE);
+ else if(y < sea) chunk.setBlock(x, y, z, Material.WATER);
}
}
}
@@ -51,4 +57,9 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
public org.polydev.gaea.biome.BiomeGrid getBiomeGrid(World world) {
return TerraBiomeGrid.fromWorld(world);
}
+
+ @Override
+ public @NotNull List getDefaultPopulators(@NotNull World world) {
+ return Arrays.asList(new FaunaPopulator());
+ }
}
diff --git a/src/main/java/com/dfsek/terra/biome/BiomeZone.java b/src/main/java/com/dfsek/terra/biome/BiomeZone.java
index 6ff7956cb..2a5ec3e5d 100644
--- a/src/main/java/com/dfsek/terra/biome/BiomeZone.java
+++ b/src/main/java/com/dfsek/terra/biome/BiomeZone.java
@@ -13,23 +13,26 @@ public class BiomeZone {
private final World w;
private final FastNoise noise;
private static final Map zones = new HashMap<>();
+ private static final double[] normalMap = new double[] {-0.35662081837654114D, -0.30661869049072266D, -0.27095329761505127D, -0.24149227142333984D, -0.21537694334983826D, -0.19166918098926544D, -0.16956785321235657D, -0.14864568412303925D, -0.12845154106616974D, -0.10894706845283508D, -0.08996972441673279D, -0.0715663805603981D, -0.053535036742687225D, -0.03580872714519501D, -0.01817353256046772D, -7.577221258543432E-4D, 0.016616813838481903D, 0.03416096046566963D, 0.05187138542532921D, 0.06989025324583054D, 0.08827653527259827D, 0.10723070055246353D, 0.12675245106220245D, 0.14694781601428986D, 0.16793397068977356D, 0.18999846279621124D, 0.2138010412454605D, 0.24002985656261444D, 0.2696261405944824D, 0.30540621280670166D, 0.35551881790161133D, 0.653269350528717D};
+
public BiomeZone(World w, float freq) {
this.w = w;
this.noise = new FastNoise((int) w.getSeed()+2);
- noise.setNoiseType(FastNoise.NoiseType.Value);
+ noise.setNoiseType(FastNoise.NoiseType.SimplexFractal);
+ noise.setFractalOctaves(5);
noise.setFrequency(freq);
setZones(WorldConfig.fromWorld(w).definedGrids);
zones.put(w, this);
}
public void setZones(BiomeGrid[] grids) {
- if(grids.length != 16) throw new IllegalArgumentException("Illegal number of grids!");
+ if(grids.length != 32) throw new IllegalArgumentException("Illegal number of grids!");
this.grids = grids;
}
public BiomeGrid getGrid(int x, int z) {
- return grids[normalize(noise.getValue(x, z))];
+ return grids[normalize(noise.getSimplexFractal(x, z))];
}
public static BiomeZone fromWorld(World w) {
@@ -38,14 +41,15 @@ public class BiomeZone {
}
/**
- * Takes a noise input and normalizes it to a value between 0 and 15 inclusive.
+ * Takes a noise input and normalizes it to a value between 0 and 31 inclusive.
*
- * @param i - The noise value to normalize.
+ * @param d - The noise value to normalize.
* @return int - The normalized value.
*/
- private static int normalize(double i) {
- if(i > 0) i = Math.pow(i, 0.8125); // Redistribute
- else i = -Math.pow(-i, 0.8125); // Redistribute
- return Math.min((int) Math.floor((i+1)*8), 15);
+ public static int normalize(double d) {
+ for(int i = 0; i < normalMap.length; i++) {
+ if(d < normalMap[i]) return i;
+ }
+ return normalMap.length-1;
}
}
diff --git a/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java b/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java
index 7eb6ad508..afdec9f27 100644
--- a/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java
+++ b/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java
@@ -10,18 +10,30 @@ import org.polydev.gaea.math.parsii.eval.Parser;
import org.polydev.gaea.math.parsii.eval.Scope;
import org.polydev.gaea.math.parsii.tokenizer.ParseException;
import org.polydev.gaea.structures.features.Feature;
+import org.polydev.gaea.world.BlockPalette;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
+import java.util.TreeMap;
public class UserDefinedBiome implements Biome {
private final UserDefinedGenerator gen;
private final BiomeConfig config;
+ private final UserDefinedDecorator decorator;
public UserDefinedBiome(BiomeConfig config) throws ParseException {
this.config = config;
Scope s = Scope.create();
- gen = new UserDefinedGenerator(s, Parser.parse(Objects.requireNonNull(config.getString("noise-equation")), s), Collections.emptyList(), ConfigUtil.getPalette(config.getString("palette")).getPalette());
+ TreeMap paletteMap = new TreeMap<>();
+ for(Map.Entry e : config.getConfigurationSection("palette").getValues(false).entrySet()) {
+ paletteMap.put((Integer) e.getValue(), ConfigUtil.getPalette(e.getKey()).getPalette());
+ }
+
+
+ this.decorator = new UserDefinedDecorator(config);
+
+ gen = new UserDefinedGenerator(s, Parser.parse(Objects.requireNonNull(config.getString("noise-equation")), s), Collections.emptyList(), paletteMap);
}
public BiomeConfig getConfig() {
@@ -35,7 +47,7 @@ public class UserDefinedBiome implements Biome {
*/
@Override
public org.bukkit.block.Biome getVanillaBiome() {
- return org.bukkit.block.Biome.PLAINS;
+ return config.getVanillaBiome();
}
/**
@@ -65,6 +77,6 @@ public class UserDefinedBiome implements Biome {
*/
@Override
public Decorator getDecorator() {
- return null;
+ return decorator;
}
}
diff --git a/src/main/java/com/dfsek/terra/biome/UserDefinedDecorator.java b/src/main/java/com/dfsek/terra/biome/UserDefinedDecorator.java
new file mode 100644
index 000000000..ba5448b8f
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/biome/UserDefinedDecorator.java
@@ -0,0 +1,60 @@
+package com.dfsek.terra.biome;
+
+import com.dfsek.terra.config.BiomeConfig;
+import org.bukkit.block.Biome;
+import org.polydev.gaea.biome.Decorator;
+import org.polydev.gaea.math.ProbabilityCollection;
+import org.polydev.gaea.tree.Tree;
+import org.polydev.gaea.world.Fauna;
+
+import java.util.Map;
+
+public class UserDefinedDecorator extends Decorator {
+
+ private final ProbabilityCollection fauna = new ProbabilityCollection<>();
+ private int faunaChance;
+
+ public UserDefinedDecorator(BiomeConfig config) {
+ if(config.contains("fauna")) {
+ for(Map.Entry e : config.getConfigurationSection("fauna").getValues(false).entrySet()) {
+ fauna.add(Fauna.valueOf(e.getKey()), (Integer) e.getValue());
+ }
+ }
+ faunaChance = config.getInt("fauna-chance", 0);
+ }
+
+ @Override
+ public ProbabilityCollection getTrees() {
+ return null;
+ }
+
+ @Override
+ public int getTreeDensity() {
+ return 0;
+ }
+
+ @Override
+ public boolean overrideStructureChance() {
+ return false;
+ }
+
+ @Override
+ public boolean shouldGenerateSnow() {
+ return false;
+ }
+
+ @Override
+ public Biome getVanillaBiome() {
+ return null;
+ }
+
+ @Override
+ public ProbabilityCollection getFauna() {
+ return fauna;
+ }
+
+ @Override
+ public int getFaunaChance() {
+ return faunaChance;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/biome/UserDefinedGenerator.java b/src/main/java/com/dfsek/terra/biome/UserDefinedGenerator.java
index 3db15a7f9..5e73cf150 100644
--- a/src/main/java/com/dfsek/terra/biome/UserDefinedGenerator.java
+++ b/src/main/java/com/dfsek/terra/biome/UserDefinedGenerator.java
@@ -10,6 +10,8 @@ import org.polydev.gaea.math.parsii.eval.Variable;
import org.polydev.gaea.world.BlockPalette;
import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
public class UserDefinedGenerator extends BiomeTerrain {
private final Expression noiseExp;
@@ -17,13 +19,13 @@ public class UserDefinedGenerator extends BiomeTerrain {
private final Variable xVar;
private final Variable yVar;
private final Variable zVar;
- private final BlockPalette p;
+ private final TreeMap paletteMap;
- public UserDefinedGenerator(Scope s, Expression e, List v, BlockPalette p) {
+ public UserDefinedGenerator(Scope s, Expression e, List v, TreeMap p) {
this.noiseExp = e;
this.vars = v;
- this.p = p;
+ this.paletteMap = p;
this.xVar = s.getVariable("x");
this.yVar = s.getVariable("y");
this.zVar = s.getVariable("z");
@@ -72,6 +74,33 @@ public class UserDefinedGenerator extends BiomeTerrain {
*/
@Override
public BlockPalette getPalette(int y) {
- return p;
+ for(Map.Entry e : paletteMap.entrySet()) {
+ if(e.getKey() >= y ) return e.getValue();
+ }
+ return null;
+ }
+
+ private static class Range {
+ private final int min;
+ private final int max;
+
+ /**
+ * Instantiates a Range object with a minimum value (inclusive) and a maximum value (exclusive).
+ * @param min The minimum value (inclusive).
+ * @param max The maximum value (exclusive).
+ */
+ public Range(int min, int max) {
+ this.min = min;
+ this.max = max;
+ }
+
+ /**
+ * Tests if a value is within range.
+ * @param val The value to test.
+ * @return boolean - Whether the value is within range.
+ */
+ public boolean isInRange(int val) {
+ return val >= min && val < max;
+ }
}
}
diff --git a/src/main/java/com/dfsek/terra/biome/UserDefinedGrid.java b/src/main/java/com/dfsek/terra/biome/UserDefinedGrid.java
index 740bd1ba8..e2553de98 100644
--- a/src/main/java/com/dfsek/terra/biome/UserDefinedGrid.java
+++ b/src/main/java/com/dfsek/terra/biome/UserDefinedGrid.java
@@ -9,4 +9,8 @@ public class UserDefinedGrid extends BiomeGrid {
super(w, freq1, freq2);
super.setGrid(config.getBiomeGrid());
}
+ public UserDefinedGrid(World w, float freq1, float freq2, UserDefinedBiome[][] b) {
+ super(w, freq1, freq2);
+ super.setGrid(b);
+ }
}
diff --git a/src/main/java/com/dfsek/terra/config/BiomeConfig.java b/src/main/java/com/dfsek/terra/config/BiomeConfig.java
index 15b76ac4f..8ceab9707 100644
--- a/src/main/java/com/dfsek/terra/config/BiomeConfig.java
+++ b/src/main/java/com/dfsek/terra/config/BiomeConfig.java
@@ -14,6 +14,7 @@ public class BiomeConfig extends YamlConfiguration {
private UserDefinedBiome biome;
private String biomeID;
private String friendlyName;
+ private org.bukkit.block.Biome vanillaBiome;
private boolean isEnabled = false;
public BiomeConfig(File file) throws InvalidConfigurationException, IOException {
@@ -37,6 +38,12 @@ public class BiomeConfig extends YamlConfiguration {
this.biomeID = getString("id");
if(!contains("name")) throw new InvalidConfigurationException("Biome Name unspecified!");
this.friendlyName = getString("name");
+ if(!contains("vanilla")) throw new InvalidConfigurationException("Vanila Biome unspecified!");
+ try {
+ this.vanillaBiome = org.bukkit.block.Biome.valueOf(getString("vanilla"));
+ } catch(IllegalArgumentException e) {
+ throw new InvalidConfigurationException("Invalid Vanilla biome: " + getString("vanilla"));
+ }
isEnabled = true;
}
@@ -55,4 +62,8 @@ public class BiomeConfig extends YamlConfiguration {
public String getFriendlyName() {
return friendlyName;
}
+
+ public org.bukkit.block.Biome getVanillaBiome() {
+ return vanillaBiome;
+ }
}
diff --git a/src/main/java/com/dfsek/terra/config/PaletteConfig.java b/src/main/java/com/dfsek/terra/config/PaletteConfig.java
index e3a3ebfee..6a4d26612 100644
--- a/src/main/java/com/dfsek/terra/config/PaletteConfig.java
+++ b/src/main/java/com/dfsek/terra/config/PaletteConfig.java
@@ -31,7 +31,7 @@ public class PaletteConfig extends YamlConfiguration {
ProbabilityCollection layer = new ProbabilityCollection<>();
for(Map.Entry type : ((Map) m.get("materials")).entrySet()) {
layer.add(Bukkit.createBlockData(type.getKey()), type.getValue());
- Bukkit.getLogger().info("[Terra] Added" + type.getKey() + " with probability " + type.getValue());
+ Bukkit.getLogger().info("[Terra] Added " + type.getKey() + " with probability " + type.getValue());
}
Bukkit.getLogger().info("[Terra] Added above materials for " + m.get("layers") + " layers.");
palette.addBlockData(layer, (Integer) m.get("layers"));
@@ -61,28 +61,4 @@ public class PaletteConfig extends YamlConfiguration {
public String getPaletteID() {
return paletteID;
}
-
- private static class Range {
- private final int min;
- private final int max;
-
- /**
- * Instantiates a Range object with a minimum value (inclusive) and a maximum value (exclusive).
- * @param min The minimum value (inclusive).
- * @param max The maximum value (exclusive).
- */
- public Range(int min, int max) {
- this.min = min;
- this.max = max;
- }
-
- /**
- * Tests if a value is within range.
- * @param val The value to test.
- * @return boolean - Whether the value is within range.
- */
- public boolean isInRange(int val) {
- return val >= min && val < max;
- }
- }
}
diff --git a/src/main/java/com/dfsek/terra/config/WorldConfig.java b/src/main/java/com/dfsek/terra/config/WorldConfig.java
index d5a2079ed..6bd2e262f 100644
--- a/src/main/java/com/dfsek/terra/config/WorldConfig.java
+++ b/src/main/java/com/dfsek/terra/config/WorldConfig.java
@@ -1,8 +1,7 @@
package com.dfsek.terra.config;
import com.dfsek.terra.Terra;
-import com.dfsek.terra.biome.BiomeZone;
-import com.dfsek.terra.biome.TerraBiomeGrid;
+import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.UserDefinedGrid;
import org.bukkit.World;
import org.bukkit.configuration.InvalidConfigurationException;
@@ -27,7 +26,10 @@ public class WorldConfig {
private static final Map configs = new HashMap<>();
private final Map biomeGrids = new HashMap<>();
public float zoneFreq = 1f/1536;
- public UserDefinedGrid[] definedGrids = new UserDefinedGrid[16];
+ public float freq1 = 1f/256;
+ public float freq2 = 1f/512;
+ public int seaLevel;
+ public UserDefinedGrid[] definedGrids = new UserDefinedGrid[32];
public WorldConfig(World w, JavaPlugin main) {
@@ -63,6 +65,7 @@ public class WorldConfig {
main.getLogger().severe("Unable to load configuration for world " + w + ".");
}
+ seaLevel = config.getInt("sea-level", 63);
try (Stream paths = Files.walk(Paths.get(main.getDataFolder() + File.separator + "grids"))) {
paths
@@ -85,8 +88,19 @@ public class WorldConfig {
- for(int i = 0; i < 16; i++) {
- definedGrids[i] = biomeGrids.get(config.getStringList("grids").get(i)).getGrid();
+ for(int i = 0; i < 32; i++) {
+ String partName = config.getStringList("grids").get(i);
+ if(partName.startsWith("BIOME:")) {
+ UserDefinedBiome[][] temp = new UserDefinedBiome[16][16];
+ UserDefinedBiome b = ConfigUtil.getBiome(partName.substring(6)).getBiome();
+ for(int x = 0; x < 16; x++) {
+ for(int z = 0; z < 16; z++) {
+ temp[x][z] = b;
+ }
+ }
+ definedGrids[i] = new UserDefinedGrid(w, freq1, freq2, temp);
+ main.getLogger().info("Loaded single-biome grid " + partName);
+ } else definedGrids[i] = biomeGrids.get(partName).getGrid();
}
diff --git a/src/main/java/com/dfsek/terra/population/FaunaPopulator.java b/src/main/java/com/dfsek/terra/population/FaunaPopulator.java
new file mode 100644
index 000000000..a7672abee
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/population/FaunaPopulator.java
@@ -0,0 +1,29 @@
+package com.dfsek.terra.population;
+
+import com.dfsek.terra.biome.TerraBiomeGrid;
+import org.bukkit.Chunk;
+import org.bukkit.World;
+import org.bukkit.block.Block;
+import org.bukkit.generator.BlockPopulator;
+import org.jetbrains.annotations.NotNull;
+import org.polydev.gaea.biome.Biome;
+import org.polydev.gaea.world.Fauna;
+
+import java.util.Random;
+
+public class FaunaPopulator extends BlockPopulator {
+ @Override
+ public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
+ for(int x = 0; x < 16; x++) {
+ for(int z = 0; z < 16; z++) {
+ Biome biome = TerraBiomeGrid.fromWorld(world).getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
+ if(biome.getDecorator().getFaunaChance() <= 0 || random.nextInt(100) > biome.getDecorator().getFaunaChance())
+ continue;
+ Block highest = Fauna.getHighestValidSpawnAt(chunk, x, z);
+ try {
+ if(highest != null) biome.getDecorator().getFauna().get(random).plant(highest.getLocation());
+ } catch(NullPointerException ignored) {}
+ }
+ }
+ }
+}
diff --git a/src/test/java/DistributionTest.java b/src/test/java/DistributionTest.java
new file mode 100644
index 000000000..5836c78e7
--- /dev/null
+++ b/src/test/java/DistributionTest.java
@@ -0,0 +1,39 @@
+import com.dfsek.terra.biome.BiomeZone;
+import org.polydev.gaea.math.FastNoise;
+
+import java.util.Random;
+
+public class DistributionTest {
+ public static void main(String[] args) {
+ FastNoise noise = new FastNoise(new Random().nextInt());
+ noise.setFrequency(0.01f);
+ noise.setNoiseType(FastNoise.NoiseType.SimplexFractal);
+ noise.setFractalOctaves(3);
+ int[] numbers = new int[32];
+ double min = Integer.MAX_VALUE;
+ double max = Integer.MIN_VALUE;
+ for(int i = 0; i < 32; i++) {
+ numbers[i] = 0;
+ }
+
+ for(int i = 0; i < 10000000; i++) {
+ double n = noise.getSimplexFractal(0, i);
+ max = Math.max(max, n);
+ min = Math.min(min, n);
+ numbers[BiomeZone.normalize(n)]++;
+ }
+
+ for(int i = 0; i < 32; i++) {
+ System.out.println(i + ": " + numbers[i]);
+ }
+ for(int i = 0; i < 32; i++) {
+ System.out.print(i + " |");
+ for(int j = 0; j < numbers[i]/2500; j++) {
+ System.out.print("-");
+ }
+ System.out.println("|");
+ }
+ System.out.println("max: " + max);
+ System.out.println("min: " + min);
+ }
+}
diff --git a/src/test/java/LookupGenerator.java b/src/test/java/LookupGenerator.java
new file mode 100644
index 000000000..56f7ac5d7
--- /dev/null
+++ b/src/test/java/LookupGenerator.java
@@ -0,0 +1,92 @@
+import com.dfsek.terra.biome.BiomeZone;
+import org.polydev.gaea.math.FastNoise;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+public class LookupGenerator {
+ private static double[] lookup;
+
+ public static void main(String[] args) {
+ int dist = 32;
+
+ List vals = new ArrayList<>();
+ FastNoise noise = new FastNoise(new Random().nextInt());
+ noise.setFrequency(0.01f);
+ noise.setNoiseType(FastNoise.NoiseType.SimplexFractal);
+ noise.setFractalOctaves(5);
+ int[] numbers = new int[dist];
+ double min = Integer.MAX_VALUE;
+ double max = Integer.MIN_VALUE;
+ for(int i = 0; i < dist; i++) {
+ numbers[i] = 0;
+ }
+
+ for(int i = 0; i < 10000000; i++) {
+ double n = noise.getSimplexFractal(0, i);
+ max = Math.max(max, n);
+ min = Math.min(min, n);
+ vals.add(n);
+ numbers[normalize(n, dist)]++;
+ }
+
+ for(int i = 0; i < dist; i++) {
+ System.out.println(i + ": " + numbers[i]);
+ }
+ for(int i = 0; i < dist; i++) {
+ System.out.print(i + (String.valueOf(i).length() ==1 ? " " : "") + " |");
+ for(int j = 0; j < numbers[i]/3000; j++) {
+ System.out.print("-");
+ }
+ System.out.println("|");
+ }
+ System.out.println("max: " + max);
+ System.out.println("min: " + min);
+ Collections.sort(vals);
+
+ lookup = new double[dist];
+ StringBuilder s = new StringBuilder("{");
+ for(int i = 0; i < dist; i++) {
+ int current = vals.size()/dist;
+ System.out.println(i + ", max: " + vals.get(current*(i+1)-1));
+ lookup[i] = vals.get(current*(i+1)-1);
+ s.append(vals.get(current*(i+1)-1) + "D, ");
+ }
+ s.delete(s.length()-2, s.length());
+ s.append("}");
+ numbers = new int[dist];
+ vals = new ArrayList<>();
+ for(int i = 0; i < 10000000; i++) {
+ double n = noise.getSimplexFractal(0, i);
+ vals.add(n);
+ numbers[normalizeNew(n)]++;
+ }
+
+ for(int i = 0; i < dist; i++) {
+ System.out.println(i + ": " + numbers[i]);
+ }
+ for(int i = 0; i < dist; i++) {
+ System.out.print(i + (String.valueOf(i).length() ==1 ? " " : "") + " |");
+ for(int j = 0; j < numbers[i]/3000; j++) {
+ System.out.print("-");
+ }
+ System.out.println("|");
+ }
+ System.out.println(s.toString());
+
+ }
+ public static int normalize(double i, int n) {
+ i*=1.42; // Magic simplex value (sqrt(2) plus a little)
+ i = Math.min(Math.max(i, -1),1);
+ return Math.min((int) Math.floor((i+1)*((double)n/2)), n-1);
+ }
+
+ public static int normalizeNew(double d) {
+ for(int i = 0; i < lookup.length; i++) {
+ if(d < lookup[i]) return i;
+ }
+ return lookup.length-1;
+ }
+}