This commit is contained in:
Daniel Mills 2019-11-01 04:27:47 -04:00
parent 00d4f7640e
commit 373d75609a
6 changed files with 253 additions and 114 deletions

View File

@ -150,7 +150,7 @@ public class Iris extends JavaPlugin implements Listener
else if(p.startsWith("^"))
{
double c = M.percentRange(value, -11, 37);
double c = M.lerpInverse(-11, 37, value);
double f = 32 + (c * (1.8));
v = F.f(c, Integer.valueOf(p.substring(1))) + " \u00B0C / " + F.f(f, Integer.valueOf(p.substring(1))) + " \u00B0F";
}

View File

@ -3,94 +3,144 @@ package ninja.bytecode.iris;
import java.util.List;
import java.util.Random;
import org.bukkit.BlockChangeDelegate;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.TreeType;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.util.Vector;
import ninja.bytecode.iris.biome.CBI;
import ninja.bytecode.iris.gen.GenLayerBase;
import ninja.bytecode.iris.gen.GenLayerBiome;
import ninja.bytecode.iris.gen.IGenLayer;
import ninja.bytecode.iris.util.PolygonGenerator;
import ninja.bytecode.iris.util.MaxingGenerator;
import ninja.bytecode.shuriken.collections.GList;
import ninja.bytecode.shuriken.collections.GMap;
import ninja.bytecode.shuriken.execution.ChronoLatch;
import ninja.bytecode.shuriken.format.F;
import ninja.bytecode.shuriken.logging.L;
import ninja.bytecode.shuriken.math.M;
import ninja.bytecode.shuriken.math.RNG;
public class IrisGenerator extends ParallelChunkGenerator
{
private GMap<Vector, Double> heightCache;
private MB WATER = new MB(Material.STATIONARY_WATER);
private MB BEDROCK = new MB(Material.BEDROCK);
private GList<IGenLayer> genLayers;
private GenLayerBase glBase;
private GenLayerBiome glBiome;
private GMap<Location, TreeType> trees;
private RNG rng;
private World world;
private PolygonGenerator g;
@Override
public void onInit(World world, Random random)
{
this.world = world;
trees = new GMap<>();
genLayers = new GList<>();
heightCache = new GMap<>();
rng = new RNG(world.getSeed());
genLayers.add(glBase = new GenLayerBase(this, world, random, rng.nextRNG()));
genLayers.add(glBiome = new GenLayerBiome(this, world, random, rng.nextRNG()));
g = new PolygonGenerator(rng, 16, 0.01, 1, (c) -> c);
glBase = new GenLayerBase(this, world, random, rng.nextRNG());
glBiome = new GenLayerBiome(this, world, random, rng.nextRNG());
}
public int getHeight(double h)
{
double height = M.clip(h, 0D, 1D);
return (int) (height * 253);
}
public int getHeight(double dx, double dz)
{
double height = M.clip(getRawHeight(dx, dz), 0D, 1D);
return (int) (height * 253);
return getHeight(getRawHeight(dx, dz));
}
public double getRawHeight(double dx, double dz)
{
double noise = 0 + Iris.settings.gen.baseHeight;
for(IGenLayer i : genLayers)
{
noise = i.generateLayer(noise, dx, dz);
}
return M.clip(noise, 0D, 1D);
}
@Override
public Biome genColumn(int wxx, int wzx, int x, int z)
{
if(true)
{
for(int i = 0; i < 1; i++)
{
setBlock(x, i, z, Material.CONCRETE, (byte) g.getIndex(wxx, wzx));
}
return Biome.PLAINS;
}
else
{
return genBaseColumn(wxx, wzx, x, z);
}
return genBaseColumn(wxx, wzx, x, z);
}
private double lerp(double a, double b, double f)
{
return a + (f * (b - a));
}
private double blerp(double a, double b, double c, double d, double tx, double ty)
{
return lerp(lerp(a, b, tx), lerp(c, d, tx), ty);
}
private double getBiomedHeight(int x, int z)
{
Vector v = new Vector(x, z, x * z);
if(heightCache.containsKey(v))
{
return heightCache.get(v);
}
int wx = (int) Math.round((double) x * Iris.settings.gen.horizontalZoom);
int wz = (int) Math.round((double) z * Iris.settings.gen.horizontalZoom);
CBI biome = glBiome.getBiome(wx * Iris.settings.gen.biomeScale, wz * Iris.settings.gen.biomeScale);
double h = Iris.settings.gen.baseHeight + biome.getHeight();
h += (glBase.getHeight(wx, wz) * biome.getAmp()) - (0.33 * biome.getAmp());
heightCache.put(v, h);
return h;
}
private double getBilinearNoise(int x, int z)
{
int h = 3;
int fx = x >> h;
int fz = z >> h;
int xa = (fx << h) - 2;
int za = (fz << h) - 2;
int xb = ((fx + 1) << h) + 2;
int zb = ((fz + 1) << h) + 2;
double na = getBiomedHeight(xa, za);
double nb = getBiomedHeight(xa, zb);
double nc = getBiomedHeight(xb, za);
double nd = getBiomedHeight(xb, zb);
double px = M.rangeScale(0, 1, xa, xb, x);
double pz = M.rangeScale(0, 1, za, zb, z);
return blerp(na, nc, nb, nd, px, pz);
}
private double getBicubicNoise(int x, int z)
{
int h = 3;
int fx = x >> h;
int fz = z >> h;
int xa = (fx << h);
int za = (fz << h);
int xb = ((fx + 1) << h);
int zb = ((fz + 1) << h);
double na = getBilinearNoise(xa, za);
double nb = getBilinearNoise(xa, zb);
double nc = getBilinearNoise(xb, za);
double nd = getBilinearNoise(xb, zb);
double px = M.rangeScale(0, 1, xa, xb, x);
double pz = M.rangeScale(0, 1, za, zb, z);
return blerp(na, nc, nb, nd, px, pz);
}
private Biome genBaseColumn(int wxx, int wzx, int x, int z)
{
int seaLevel = Iris.settings.gen.seaLevel;
int wx = (int) Math.round((double) wxx * Iris.settings.gen.horizontalZoom);
int wz = (int) Math.round((double) wzx * Iris.settings.gen.horizontalZoom);
CBI biome = glBiome.getBiome(wx * Iris.settings.gen.biomeScale, wz * Iris.settings.gen.biomeScale);
int height = getHeight(wx, wz) + 25;
double hv = getBicubicNoise(wxx, wzx);
int height = getHeight(hv);
for(int i = 0; i < Math.max(height, seaLevel); i++)
{
@ -124,17 +174,6 @@ public class IrisGenerator extends ParallelChunkGenerator
}
}
}
if(height < 240 && height >= seaLevel)
{
TreeType s = biome.getTreeChanceSingle();
if(s != null)
{
setBlock(x, i + 1, z, Material.AIR);
trees.put(new Location(world, x, i + 1, z), s);
}
}
}
if(Iris.settings.gen.flatBedrock ? i == 0 : i < glBase.scatterInt(x, i, z, 3))
@ -169,17 +208,12 @@ public class IrisGenerator extends ParallelChunkGenerator
@Override
public void onInitChunk(World world, int x, int z, Random random)
{
heightCache.clear();
}
@Override
public void onPostChunk(World world, int x, int z, Random random)
{
}
public double getBiomeBorder(double dx, double dz)
{
return glBiome.getCenterPercent(dx, dz);
}
}

View File

@ -14,7 +14,7 @@ public class Settings
public static class GeneratorSettings
{
public double horizontalZoom = 1.325; // 1.856 2.556
public double horizontalZoom = 2.225; // 1.856 2.556
public double heightFracture = 155;
public double heightMultiplier = 1.154;
public double heightExponentBase = 1;
@ -22,7 +22,7 @@ public class Settings
public double heightScale = 1;
public double superHeightScale = 0.65;
public double altBiomeScale = 1;
public double baseHeight = 0.3415;
public double baseHeight = 0.22;
public double superSamplerRadius = 32;
public int superSamplerIterations = 14;
public int superSamples = 12;

View File

@ -16,10 +16,15 @@ import ninja.bytecode.shuriken.math.RNG;
public class CBI
{
//@builder
public static final CBI RIVER = new CBI("River", Biome.RIVER)
.surface(MB.of(Material.SAND))
.height(0.085);
public static final CBI OCEAN = new CBI("Ocean", Biome.OCEAN)
.surface(MB.of(Material.SAND));
.surface(MB.of(Material.SAND))
.height(-0.07);
public static final CBI DEEP_OCEAN = new CBI("Deep Ocean", Biome.DEEP_OCEAN)
.surface(MB.of(Material.SAND));
.surface(MB.of(Material.SAND))
.height(-0.07);
public static final CBI DESERT = new CBI("Desert", Biome.DESERT)
.surface(MB.of(Material.SAND))
.scatter(MB.of(Material.DEAD_BUSH, 0), 0.08)
@ -35,6 +40,7 @@ public class CBI
.simplexSurface();
public static final CBI DESERT_HILLS = new CBI("Desert Hills", Biome.DESERT_HILLS)
.surface(MB.of(Material.SAND))
.amp(0.75)
.scatter(MB.of(Material.DEAD_BUSH, 0), 0.08)
.dirt(MB.of(Material.SANDSTONE));
public static final CBI MESA = new CBI("Mesa", Biome.MESA)
@ -46,18 +52,21 @@ public class CBI
.tree(TreeType.ACACIA, 0.2);
public static final CBI SAVANNA_HILLS = new CBI("Savanna Hills", Biome.SAVANNA_ROCK)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.18)
.amp(0.75)
.tree(TreeType.ACACIA, 0.2);
public static final CBI JUNGLE = new CBI("Jungle", Biome.JUNGLE)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.58)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.13);
public static final CBI JUNGLE_HILLS = new CBI("Jungle Hills", Biome.JUNGLE_HILLS)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.58)
.amp(0.75)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.13);
public static final CBI SWAMP = new CBI("Swamp", Biome.SWAMPLAND)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.04)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.03);
public static final CBI PLAINS = new CBI("Plains", Biome.PLAINS)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.38)
.amp(0.4)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.03);
public static final CBI DECAYING_PLAINS = new CBI("Decaying Plains", Biome.PLAINS)
.surface(MB.of(Material.GRASS_PATH), MB.of(Material.GRASS))
@ -68,12 +77,14 @@ public class CBI
.scatter(MB.of(Material.LONG_GRASS, 2), 0.13);
public static final CBI FOREST_HILLS = new CBI("Forest Hills", Biome.FOREST_HILLS)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.23)
.amp(0.75)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.13);
public static final CBI BIRCH_FOREST = new CBI("Birch Forest", Biome.BIRCH_FOREST)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.23)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.13);
public static final CBI BIRCH_FOREST_HILLS = new CBI("Birch Forest Hills", Biome.BIRCH_FOREST_HILLS)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.23)
.amp(0.75)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.13);
public static final CBI ROOFED_FOREST = new CBI("Roofed Forest", Biome.ROOFED_FOREST)
.scatter(MB.of(Material.LONG_GRASS, 1), 0.23)
@ -83,21 +94,25 @@ public class CBI
public static final CBI EXTREME_HILLS = new CBI("Extreme Hills", Biome.EXTREME_HILLS)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.04);
public static final CBI EXTREME_HILLS_TREES = new CBI("Extreme Hills +", Biome.EXTREME_HILLS_WITH_TREES)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.09);
.scatter(MB.of(Material.LONG_GRASS, 2), 0.09)
.amp(1.25);
public static final CBI TAIGA_COLD = new CBI("Taiga Cold", Biome.TAIGA_COLD)
.scatter(MB.of(Material.LONG_GRASS, 2), 0.04);
public static final CBI TAIGA_COLD_HILLS = new CBI("Taiga Cold Hills", Biome.TAIGA_COLD_HILLS);
public static final CBI TAIGA_COLD_HILLS = new CBI("Taiga Cold Hills", Biome.TAIGA_COLD_HILLS)
.amp(0.75);
public static final CBI ICE_FLATS = new CBI("Ice Flats", Biome.ICE_FLATS);
public static final CBI ICE_MOUNTAINS = new CBI("Ice Mountains", Biome.ICE_MOUNTAINS);
public static final CBI ICE_MOUNTAINS = new CBI("Ice Mountains", Biome.ICE_MOUNTAINS)
.amp(1.45);
public static final CBI REDWOOD_TAIGA = new CBI("Redwood Taiga", Biome.REDWOOD_TAIGA)
.surface(MB.of(Material.DIRT, 2), MB.of(Material.DIRT, 1))
.simplexSurface();
public static final CBI REDWOOD_TAIGA_HILLS = new CBI("Redwood Taiga Hills", Biome.REDWOOD_TAIGA_HILLS)
.surface(MB.of(Material.DIRT, 2), MB.of(Material.DIRT, 1))
.amp(0.75)
.simplexSurface();
//@done
private String name;
private Biome realBiome;
private double height;
@ -114,26 +129,26 @@ public class CBI
this.name = name;
this.realBiome = realBiome;
this.height = 0.125;
this.amp = 0;
this.amp = 0.5;
scatterChance = new GMap<>();
treeChance = new GMap<>();
surface(new MB(Material.GRASS)).dirt(new MB(Material.DIRT), new MB(Material.DIRT, 1));
}
public CBI scatter(MB mb, Double chance)
{
scatterChance.put(mb, chance);
return this;
}
public CBI tree(TreeType t, Double chance)
{
treeChance.put(t, chance);
return this;
}
public CBI simplexSurface()
{
simplexScatter = true;
@ -200,17 +215,18 @@ public class CBI
{
if(poly == null)
{
poly = new PolygonGenerator.EnumPolygonGenerator<MB>(rng, 0.05, 12, getSurface().toArray(new MB[getSurface().size()]), (g) -> {
poly = new PolygonGenerator.EnumPolygonGenerator<MB>(rng, 0.05, 12, getSurface().toArray(new MB[getSurface().size()]), (g) ->
{
return g.fractureWith(new CNG(rng.nextRNG(), 1D, 2).scale(0.155), 24);
});
}
return poly.getChoice(wx, wz);
}
return getSurface().getRandom();
}
public MB getDirt(int wx, int wz)
{
return getDirt().getRandom();
@ -230,10 +246,10 @@ public class CBI
return i;
}
}
return MB.of(Material.AIR);
}
public GMap<TreeType, Double> getTreeChance()
{
return treeChance;
@ -248,7 +264,7 @@ public class CBI
return i;
}
}
return null;
}
}

View File

@ -8,35 +8,23 @@ import org.bukkit.World;
import ninja.bytecode.iris.Iris;
import ninja.bytecode.iris.IrisGenerator;
import ninja.bytecode.iris.biome.CBI;
import ninja.bytecode.iris.util.PolygonGenerator;
import ninja.bytecode.iris.util.PolygonGenerator.EnumPolygonGenerator;
import ninja.bytecode.shuriken.collections.GList;
import ninja.bytecode.iris.util.MaxingGenerator.EnumMaxingGenerator;
import ninja.bytecode.shuriken.math.CNG;
import ninja.bytecode.shuriken.math.RNG;
public class GenLayerBiome extends GenLayer
{
private CNG fractures2;
private CNG fractures4;
private PolygonGenerator.EnumPolygonGenerator<CBI> biomeGenerator;
private EnumMaxingGenerator<CBI> biomeGenerator;
private Function<CNG, CNG> factory;
private double closest;
private CNG riverCheck;
public GenLayerBiome(IrisGenerator iris, World world, Random random, RNG rng)
{
//@builder
super(iris, world, random, rng);
double scale = 1.25D;
factory = (g) -> g
.fractureWith(new CNG(g.nextRNG().nextRNG(), 1D, 32)
.scale(0.2112)
.fractureWith(new CNG(g.nextRNG(), 1D, 16)
.scale(0.132),
333), 588);
fractures2 = new CNG(rng.nextRNG(), 1, 32).scale(0.02);
fractures4 = new CNG(rng.nextRNG(), 1, 16).scale(0.12);
biomeGenerator = new PolygonGenerator.EnumPolygonGenerator<CBI>(rng.nextRNG(), 0.00755 * Iris.settings.gen.biomeScale, 1,
factory = (g) -> g.fractureWith(new CNG(rng.nextRNG(), 1D, 4).scale(0.02), 56);
riverCheck = new CNG(rng.nextRNG(), 1D, 2).scale(0.00096);
biomeGenerator = new EnumMaxingGenerator<CBI>(rng.nextRNG(), 0.00755 * Iris.settings.gen.biomeScale, 1,
new CBI[] {
CBI.DESERT,
CBI.DESERT_HILLS,
@ -71,30 +59,20 @@ public class GenLayerBiome extends GenLayer
public CBI getBiome(double x, double z)
{
double scram2 = fractures2.noise(x, z) * 188.35;
double scram4 = fractures4.noise(x, z) * 47;
double a = x - scram2 - scram4;
double b = z + scram2 + scram4;
a += Math.sin(b) * 12;
b += Math.cos(a) * 12;
return biomeGenerator.getChoice(a, b);
}
public double getCenterPercent(double x, double z)
{
double scram2 = fractures2.noise(x, z) * 188.35;
double scram4 = fractures4.noise(x, z) * 47;
double a = x - scram2 - scram4;
double b = z + scram2 + scram4;
a += Math.sin(b) * 12;
b += Math.cos(a) * 12;
return biomeGenerator.getClosestNeighbor(a, b);
if(riverCheck.noise(x, z) > 0.75)
{
if(biomeGenerator.hasBorder(3, 3 + Math.pow(riverCheck.noise(x, z), 1.25) * 16, x, z))
{
return CBI.RIVER;
}
}
return biomeGenerator.getChoice(x, z);
}
@Override
public double generateLayer(double noise, double dx, double dz)
{
CBI biome = getBiome(dx, dz);
return ((1D + (biome.getAmp())) * noise) + (biome.getHeight() / 3D);
return noise;
}
}

View File

@ -0,0 +1,111 @@
package ninja.bytecode.iris.util;
import java.util.function.Function;
import ninja.bytecode.shuriken.math.CNG;
import ninja.bytecode.shuriken.math.RNG;
public class MaxingGenerator
{
private CNG[] gen;
private int possibilities;
public MaxingGenerator(RNG rng, int possibilities, double scale, int octaves, Function<CNG, CNG> factory)
{
this.possibilities = possibilities;
gen = new CNG[possibilities];
for(int i = 0; i < possibilities; i++)
{
gen[i] = new CNG(rng.nextRNG(), 1D, 1).scale(scale);
gen[i] = factory.apply(gen[i]);
}
}
public double getEdge(double... dim)
{
double b = 0;
for(int i = 0; i < gen.length; i++)
{
double g = Math.pow(gen[i].noise(dim), gen.length);
if(g > b)
{
b = g;
}
}
return b;
}
public int getIndex(double... dim)
{
double b = 0;
int index = 0;
for(int i = 0; i < gen.length; i++)
{
double g = Math.pow(gen[i].noise(dim), gen.length);
if(g > b)
{
b = g;
index = i;
}
}
return index % possibilities;
}
public boolean hasBorder(int checks, double distance, double... dims)
{
int current = getIndex(dims);
double ajump = 360D / (double)checks;
if(dims.length == 2)
{
for(int i = 0; i < checks; i++)
{
double dx = Math.sin(Math.toRadians(ajump * i));
double dz = Math.cos(Math.toRadians(ajump * i));
if(current != getIndex((dx * distance) + dims[0], (dz * distance) + dims[1]))
{
return true;
}
}
}
if(dims.length == 3)
{
for(int i = 0; i < checks; i++)
{
double dx = Math.sin(Math.toRadians(ajump * i));
double dz = Math.cos(Math.toRadians(ajump * i));
double dy = Math.tan(Math.toRadians(ajump * i));
if(current != getIndex((dx * distance) + dims[0], (dz * distance) + dims[1], (dy * distance) + dims[2]))
{
return true;
}
}
}
return false;
}
public static class EnumMaxingGenerator<T> extends MaxingGenerator
{
private T[] choices;
public EnumMaxingGenerator(RNG rng, double scale, int octaves, T[] choices, Function<CNG, CNG> factory)
{
super(rng, choices.length, scale / (double) choices.length, octaves, factory);
this.choices = choices;
}
public T getChoice(double... dim)
{
return choices[super.getIndex(dim)];
}
}
}