Iris is 50%-200% faster & now has timings

This commit is contained in:
Daniel Mills 2020-01-21 07:45:20 -05:00
parent 31c2ea888b
commit f6780fcb76
14 changed files with 467 additions and 54 deletions

View File

@ -43,11 +43,21 @@ public class CommandIris implements CommandExecutor
{
if(args[0].equalsIgnoreCase("timings"))
{
double t = Iris.getController(TimingsController.class).getResult("terrain");
double d = Iris.getController(TimingsController.class).getResult("decor");
msg(sender, "Generation: " + ChatColor.BOLD + ChatColor.WHITE + F.duration(t + d, 2));
msg(sender, " \\Terrain: " + ChatColor.BOLD + ChatColor.WHITE + F.duration(t, 2));
msg(sender, " \\Decor: " + ChatColor.BOLD + ChatColor.WHITE + F.duration(d, 2));
if(sender instanceof Player)
{
Player p = (Player) sender;
World w = p.getWorld();
if(w.getGenerator() instanceof IrisGenerator)
{
((IrisGenerator) w.getGenerator()).getMetrics().send(p, (m) -> msg(p, m));
}
else
{
msg(p, "You must be in an iris world for this");
}
}
}
if(args[0].equalsIgnoreCase("info"))

View File

@ -17,6 +17,7 @@ import ninja.bytecode.iris.util.Direction;
import ninja.bytecode.iris.util.IrisController;
import ninja.bytecode.iris.util.IrisControllerSet;
import ninja.bytecode.shuriken.logging.L;
import ninja.bytecode.shuriken.math.CNG;
public class Iris extends JavaPlugin implements Listener
{
@ -24,6 +25,7 @@ public class Iris extends JavaPlugin implements Listener
public static Thread primaryThread;
public static Settings settings;
public static Iris instance;
public static IrisMetrics metrics;
public void onEnable()
{

View File

@ -0,0 +1,236 @@
package ninja.bytecode.iris;
import java.lang.reflect.Executable;
import java.util.function.Consumer;
import org.bukkit.entity.Player;
import com.amazonaws.http.ExecutionContext;
import mortar.compute.math.M;
import mortar.util.text.C;
import ninja.bytecode.iris.controller.ExecutionController;
import ninja.bytecode.shuriken.bench.PrecisionStopwatch;
import ninja.bytecode.shuriken.collections.GList;
import ninja.bytecode.shuriken.collections.GMap;
import ninja.bytecode.shuriken.format.F;
import ninja.bytecode.shuriken.math.RollingSequence;
public class IrisMetrics
{
private int size;
private int generators;
private double scale;
private GMap<String, RollingSequence> sequences;
public IrisMetrics(int generators, int size)
{
scale = 1;
this.size = size;
this.generators = generators;
sequences = new GMap<>();
}
public String avgMS(String s, int dec)
{
return F.duration(get(s).getAverage(), dec);
}
public String avg(String s, int dec)
{
return F.f(get(s).getAverage(), dec);
}
public String maxMS(String s, int dec)
{
return F.duration(get(s).getMax(), dec);
}
public String max(String s, int dec)
{
return F.f(get(s).getMax(), dec);
}
public String minMS(String s, int dec)
{
return F.duration(get(s).getMin(), dec);
}
public String min(String s, int dec)
{
return F.f(get(s).getMin(), dec);
}
public String medianMS(String s, int dec)
{
return F.duration(get(s).getMedian(), dec);
}
public String median(String s, int dec)
{
return F.f(get(s).getMedian(), dec);
}
public RollingSequence get(String s)
{
if(!sequences.containsKey(s))
{
return new RollingSequence(2);
}
return sequences.get(s);
}
public PrecisionStopwatch start()
{
return PrecisionStopwatch.start();
}
public void stop(String f, PrecisionStopwatch g)
{
put(f, g.getMilliseconds());
}
public void put(String f, double t)
{
if(!sequences.containsKey(f))
{
sequences.put(f, new RollingSequence(size));
}
sequences.get(f).put(t);
}
public int getGenerators()
{
return generators;
}
public void setGenerators(int generators)
{
this.generators = generators;
}
public GMap<String, RollingSequence> getSequences()
{
return sequences;
}
public void setSequences(GMap<String, RollingSequence> sequences)
{
this.sequences = sequences;
}
public void send(Player p, Consumer<String> c)
{
send(p, c, null, 0);
}
public void setParScale(double sf)
{
scale = sf;
}
public void send(Player p, Consumer<String> c, String parent, int ind)
{
GMap<String, String> out = new GMap<>();
looking: for(String i : getSequences().k())
{
GList<String> o = new GList<>();
if(i.contains(":"))
{
o.add(i.split("\\Q:\\E"));
}
else
{
o.add(i);
}
String pf = o.get(0);
o.remove(0);
getSequences().get(i).resetExtremes();
double vmin = Math.abs(getSequences().get(i).getMin());
double vmed = Math.abs(getSequences().get(i).getMedian());
double vavg = Math.abs(getSequences().get(i).getAverage());
double vmax = Math.abs(getSequences().get(i).getMax());
for(String k : o)
{
if(k.startsWith("x"))
{
Double mult = Double.valueOf(k.substring(1));
vmin *= mult / (scale * 2D);
vmed *= mult / (scale * 2D);
vavg *= mult / (scale * 2D);
vmax *= mult / (scale * 2D);
}
}
boolean ms = false;
boolean comma = false;
String myparent = null;
int dot = 0;
for(String k : o)
{
if(k.startsWith("/"))
{
myparent = k.substring(1);
}
if(k.startsWith(".") && k.endsWith("."))
{
dot = k.length();
}
else if(k.equals(","))
{
comma = true;
}
if(k.equals("ms"))
{
ms = true;
}
}
if((parent != null) != (myparent != null))
{
continue looking;
}
if(parent != null && !myparent.equals(parent))
{
continue looking;
}
if(dot == 0 && vavg >= 1000 && !comma)
{
comma = true;
}
String af = ms ? F.duration(vmin, dot) : comma ? F.f((int) vmin) : F.f(vmin, dot);
String bf = ms ? F.duration(vmed, dot) : comma ? F.f((int) vmed) : F.f(vmed, dot);
String cf = ms ? F.duration(vavg, dot) : comma ? F.f((int) vavg) : F.f(vavg, dot);
String df = ms ? F.duration(vmax, dot) : comma ? F.f((int) vmax) : F.f(vmax, dot);
out.put(pf, C.DARK_GREEN.toString() + C.ITALIC + cf + C.RESET + C.GRAY + " (" + C.DARK_AQUA + C.ITALIC + af + C.RESET + C.GRAY + " > " + C.GOLD + C.ITALIC + bf + C.RESET + C.GRAY + " < " + C.DARK_RED + C.ITALIC + df + C.RESET + C.GRAY + ")");
}
if(ind == 0)
{
c.accept(C.WHITE.toString() + C.BOLD + "Total Generators: " + C.RESET + C.DARK_AQUA + C.ITALIC + F.f(generators));
c.accept(C.WHITE.toString() + C.BOLD + "Parallelism: " + C.RESET + C.DARK_PURPLE + C.ITALIC + F.pc(scale) + C.WHITE + C.BOLD + " Threads: " + C.RESET + C.BLUE + C.ITALIC + Iris.getController(ExecutionController.class).getTC());
}
for(String i : out.k())
{
String g = F.capitalizeWords(i.replaceAll("\\Q-\\E", " ").toLowerCase());
c.accept(F.repeat(" ", M.iclip(ind, 0, 4)) + C.WHITE + C.BOLD + g + C.RESET + ": " + out.get(i));
send(p, c, i, ind + 1);
}
}
}

View File

@ -1,5 +1,6 @@
package ninja.bytecode.iris;
import ninja.bytecode.iris.util.InterpolationMode;
import ninja.bytecode.iris.util.PerformanceMode;
public class Settings
@ -22,8 +23,9 @@ public class Settings
public static class GeneratorSettings
{
public InterpolationMode interpolationMode = InterpolationMode.BILINEAR;
public int interpolationRadius = 5;
public double objectDensity = 1D;
public int hermiteSampleRadius = 4;
public double horizontalZoom = 2;
public double heightFracture = 155;
public double landScale = 0.25;

View File

@ -33,7 +33,7 @@ public class ExecutionController implements IrisController
return x;
}
private int getTC()
public int getTC()
{
switch(Iris.settings.performance.performanceMode)
{

View File

@ -6,10 +6,13 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.bukkit.util.NumberConversions;
import mortar.util.text.C;
import ninja.bytecode.iris.Iris;
import ninja.bytecode.iris.IrisMetrics;
import ninja.bytecode.iris.controller.PackController;
import ninja.bytecode.iris.generator.atomics.AtomicChunkData;
import ninja.bytecode.iris.generator.genobject.GenObjectDecorator;
@ -25,11 +28,14 @@ import ninja.bytecode.iris.generator.parallax.ParallaxWorldGenerator;
import ninja.bytecode.iris.pack.BiomeType;
import ninja.bytecode.iris.pack.CompiledDimension;
import ninja.bytecode.iris.pack.IrisBiome;
import ninja.bytecode.iris.pack.IrisDimension;
import ninja.bytecode.iris.pack.IrisRegion;
import ninja.bytecode.iris.util.ChunkPlan;
import ninja.bytecode.iris.util.InterpolationMode;
import ninja.bytecode.iris.util.IrisInterpolation;
import ninja.bytecode.iris.util.MB;
import ninja.bytecode.iris.util.SChunkVector;
import ninja.bytecode.shuriken.bench.PrecisionStopwatch;
import ninja.bytecode.shuriken.collections.GList;
import ninja.bytecode.shuriken.logging.L;
import ninja.bytecode.shuriken.math.CNG;
@ -74,14 +80,24 @@ public class IrisGenerator extends ParallaxWorldGenerator
private GenLayerCliffs glCliffs;
private RNG rTerrain;
private CompiledDimension dim;
private IrisMetrics metrics = new IrisMetrics(0, 512);
private int objectHits;
public IrisGenerator()
{
this(Iris.getController(PackController.class).getDimension("overworld"));
}
public void hitObject()
{
objectHits++;
}
public IrisGenerator(CompiledDimension dim)
{
objectHits = 0;
CNG.hits = 0;
CNG.creates = 0;
this.dim = dim;
disposed = false;
L.i("Preparing Dimension: " + dim.getName() + " With " + dim.getBiomes().size() + " Biomes...");
@ -147,6 +163,7 @@ public class IrisGenerator extends ParallaxWorldGenerator
public IrisBiome getBiome(int wxx, int wzx)
{
PrecisionStopwatch c = getMetrics().start();
IrisBiome biome = glBiome.getBiome(wxx, wzx);
IrisBiome real = glBiome.getBiome(wxx, wzx, true);
boolean frozen = getRegion(biome) != null ? getRegion(biome).isFrozen() : false;
@ -157,10 +174,22 @@ public class IrisGenerator extends ParallaxWorldGenerator
biome = height > 61 && height < 65 ? frozen ? biome : getBeach(real) : biome;
biome = height > 63 && biome.getType().equals(BiomeType.FLUID) ? getBeach(real) : biome;
biome = height >= beach && !biome.getType().equals(BiomeType.LAND) ? real : biome;
getMetrics().stop("biome:ms:x256:/terrain:..", c);
return biome;
}
public ChunkData generateChunkData(World world, Random random, int x, int z, BiomeGrid biome)
{
PrecisionStopwatch s = getMetrics().start();
ChunkData d = super.generateChunkData(world, random, x, z, biome);
getMetrics().stop("chunk:ms", s);
getMetrics().put("noise-hits", CNG.hits);
metrics.setGenerators((int) CNG.creates);
CNG.hits = 0;
return d;
}
public IrisBiome biome(String name)
{
return getDimension().getBiomeByName(name);
@ -176,6 +205,11 @@ public class IrisGenerator extends ParallaxWorldGenerator
return Math.round((double) z * (Iris.settings.gen.horizontalZoom / 1.90476190476));
}
public IrisMetrics getMetrics()
{
return metrics;
}
public IrisBiome getOcean(IrisBiome biome, int height)
{
IrisRegion region = glBiome.getRegion(biome.getRegion());
@ -221,9 +255,39 @@ public class IrisGenerator extends ParallaxWorldGenerator
return (int) Math.round(M.clip(getANoise((int) x, (int) z, plan, biome), 0D, 1D) * 253);
}
public double getInterpolation(int x, int z, ChunkPlan plan)
{
PrecisionStopwatch s = getMetrics().start();
double d = 0;
InterpolationMode m = Iris.settings.gen.interpolationMode;
if(m.equals(InterpolationMode.BILINEAR))
{
d = IrisInterpolation.getBilinearNoise(x, z, Iris.settings.gen.interpolationRadius, (xf, zf) -> getBiomedHeight((int) Math.round(xf), (int) Math.round(zf), plan));
}
else if(m.equals(InterpolationMode.BICUBIC))
{
d = IrisInterpolation.getBicubicNoise(x, z, Iris.settings.gen.interpolationRadius, (xf, zf) -> getBiomedHeight((int) Math.round(xf), (int) Math.round(zf), plan));
}
else if(m.equals(InterpolationMode.HERMITE_BICUBIC))
{
d = IrisInterpolation.getHermiteNoise(x, z, Iris.settings.gen.interpolationRadius, (xf, zf) -> getBiomedHeight((int) Math.round(xf), (int) Math.round(zf), plan));
}
else
{
d = getBiomedHeight((int) Math.round(x), (int) Math.round(z), plan);
}
getMetrics().stop("interpolation:ms:x256:/biome:.", s);
return d;
}
public double getANoise(int x, int z, ChunkPlan plan, IrisBiome biome)
{
double hv = !Iris.settings.performance.fastMode ? IrisInterpolation.getNoise(x, z, Iris.settings.gen.hermiteSampleRadius, (xf, zf) -> getBiomedHeight((int) Math.round(xf), (int) Math.round(zf), plan)) : getBiomedHeight((int) Math.round(x), (int) Math.round(z), plan);
double hv = !Iris.settings.performance.fastMode ? getInterpolation(x, z, plan) : getBiomedHeight((int) Math.round(x), (int) Math.round(z), plan);
hv += glLNoise.generateLayer(hv * Iris.settings.gen.roughness * 215, (double) x * Iris.settings.gen.roughness * 0.82, (double) z * Iris.settings.gen.roughness * 0.82) * (1.6918 * (hv * 2.35));
if(biome.hasCliffs())
@ -244,7 +308,10 @@ public class IrisGenerator extends ParallaxWorldGenerator
{
try
{
PrecisionStopwatch s = getMetrics().start();
god.decorateParallax(x, z, random);
String xx = "x" + getParallaxSize().getX() * getParallaxSize().getZ();
getMetrics().stop("object:" + xx + ":.:ms:/parallax", s);
}
catch(Throwable e)
@ -253,9 +320,17 @@ public class IrisGenerator extends ParallaxWorldGenerator
}
}
@Override
public Biome onGenColumn(int wxxf, int wzxf, int x, int z, ChunkPlan plan, AtomicChunkData data)
private double getObjectHits()
{
int hits = objectHits;
objectHits = 0;
return hits;
}
@Override
public Biome onGenColumn(int wxxf, int wzxf, int x, int z, ChunkPlan plan, AtomicChunkData data, boolean surfaceOnly)
{
PrecisionStopwatch s = getMetrics().start();
if(disposed)
{
data.setBlock(x, 0, z, Material.MAGENTA_GLAZED_TERRACOTTA);
@ -274,7 +349,7 @@ public class IrisGenerator extends ParallaxWorldGenerator
int height = computeHeight(wxx, wzx, plan, biome);
int max = Math.max(height, seaLevel);
for(int i = 0; i < max; i++)
for(int i = surfaceOnly ? max > seaLevel ? max - 2 : height - 2 : 0; i < max; i++)
{
MB mb = ROCK.get(scatterInt(wzx, i, wxx, ROCK.size()));
boolean underwater = i >= height && i < seaLevel;
@ -328,9 +403,22 @@ public class IrisGenerator extends ParallaxWorldGenerator
data.setBlock(x, i, z, mb.material, mb.data);
}
glCaves.genCaves(wxx, wzx, x, z, height, this, data);
getMetrics().stop("terrain:ms:x256:/chunk:..", s);
if(!surfaceOnly)
{
PrecisionStopwatch c = getMetrics().start();
glCaves.genCaves(wxx, wzx, x, z, height, this, data);
getMetrics().stop("caves:ms:x256:/terrain:..", c);
PrecisionStopwatch v = getMetrics().start();
glCaverns.genCaverns(wxx, wzx, x, z, height, this, biome, data);
getMetrics().stop("caverns:ms:x256:/terrain:..", v);
}
PrecisionStopwatch c = getMetrics().start();
glCarving.genCarves(wxx, wzx, x, z, height, this, biome, data);
glCaverns.genCaverns(wxx, wzx, x, z, height, this, biome, data);
getMetrics().stop("carving:ms:x256:/terrain:..", c);
int hw = 0;
int hl = 0;
@ -344,6 +432,10 @@ public class IrisGenerator extends ParallaxWorldGenerator
plan.setRealHeight(x, z, hl);
plan.setRealWaterHeight(x, z, hw == 0 ? seaLevel : hw);
plan.setBiome(x, z, biome);
double time = s.getMilliseconds() * 256D;
double atime = getMetrics().get("chunk:ms").getAverage();
getMetrics().setParScale(time / atime);
getMetrics().put("objects:,:/parallax", getObjectHits());
return biome.getRealBiome();
}

View File

@ -123,7 +123,7 @@ public class WorldReactor
{
for(int j = 0; j < 16; j++)
{
gen.onGenColumn((x << 4) + i, (z << 4) + j, i, j, typlan, tydata);
gen.onGenColumn((x << 4) + i, (z << 4) + j, i, j, typlan, tydata, true);
}
}

View File

@ -281,22 +281,25 @@ public class GenObject
if(!Iris.settings.performance.noObjectFail)
{
Material m = placer.get(f.clone().subtract(0, 1, 0)).material;
if(i.getY() == mountHeight && (m.equals(Material.WATER) || m.equals(Material.STATIONARY_WATER) || m.equals(Material.LAVA) || m.equals(Material.STATIONARY_LAVA)))
if(f.getBlockY() == 63 && i.getY() == mountHeight)
{
for(Location j : undo.k())
{
placer.set(j, undo.get(j));
}
Material m = placer.get(f.clone().subtract(0, 1, 0)).material;
if(Iris.settings.performance.verbose)
if(m.equals(Material.WATER) || m.equals(Material.STATIONARY_WATER) || m.equals(Material.LAVA) || m.equals(Material.STATIONARY_LAVA))
{
L.w(C.WHITE + "Object " + C.YELLOW + getName() + C.WHITE + " failed to place in " + C.YELLOW + m.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(f.getBlockX()) + " " + F.f(f.getBlockY()) + " " + F.f(f.getBlockZ()));
}
for(Location j : undo.k())
{
placer.set(j, undo.get(j));
}
failures++;
return null;
if(Iris.settings.performance.verbose)
{
L.w(C.WHITE + "Object " + C.YELLOW + getName() + C.WHITE + " failed to place in " + C.YELLOW + m.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(f.getBlockX()) + " " + F.f(f.getBlockY()) + " " + F.f(f.getBlockZ()));
}
failures++;
return null;
}
}
}

View File

@ -189,6 +189,7 @@ public class GenObjectDecorator
if(start != null)
{
g.hitObject();
if(Iris.settings.performance.verbose)
{
L.v(C.GRAY + "Placed " + C.DARK_GREEN + i.getName() + C.WHITE + "/" + C.DARK_GREEN + go.getName() + C.GRAY + " at " + C.DARK_GREEN + F.f(start.getBlockX()) + " " + F.f(start.getBlockY()) + " " + F.f(start.getBlockZ()));

View File

@ -16,6 +16,7 @@ import org.bukkit.event.world.WorldUnloadEvent;
import mortar.api.nms.NMP;
import ninja.bytecode.iris.Iris;
import ninja.bytecode.iris.controller.TimingsController;
import ninja.bytecode.iris.generator.IrisGenerator;
import ninja.bytecode.iris.generator.atomics.AtomicChunkData;
import ninja.bytecode.iris.util.ChunkPlan;
import ninja.bytecode.iris.util.IrisWorldData;
@ -117,7 +118,7 @@ public abstract class ParallaxWorldGenerator extends ParallelChunkGenerator impl
public ParallaxAnchor computeAnchor(int wx, int wz, ChunkPlan heightBuffer, AtomicChunkData data)
{
onGenColumn(wx, wz, wx & 15, wz & 15, heightBuffer, data);
onGenColumn(wx, wz, wx & 15, wz & 15, heightBuffer, data, false);
return new ParallaxAnchor(heightBuffer.getRealHeight(wx & 15, wz & 15), heightBuffer.getRealWaterHeight(wx & 15, wz & 15), heightBuffer.getBiome(wx & 15, wz & 15), data);
}
@ -125,7 +126,7 @@ public abstract class ParallaxWorldGenerator extends ParallelChunkGenerator impl
public ParallaxAnchor computeAnchor(int wx, int wz)
{
ChunkPlan heightBuffer = new ChunkPlan();
onGenColumn(wx, wz, wx & 15, wz & 15, heightBuffer, buffer);
onGenColumn(wx, wz, wx & 15, wz & 15, heightBuffer, buffer, false);
return new ParallaxAnchor(heightBuffer.getRealHeight(wx & 15, wz & 15), heightBuffer.getRealWaterHeight(wx & 15, wz & 15), heightBuffer.getBiome(wx & 15, wz & 15), buffer);
}
@ -140,35 +141,40 @@ public abstract class ParallaxWorldGenerator extends ParallelChunkGenerator impl
public final ChunkPlan initChunk(World world, int x, int z, Random random)
{
PrecisionStopwatch ps = PrecisionStopwatch.start();
TaskGroup g = startWork();
int gg = 0;
int gx = 0;
for(int ii = Iris.settings.performance.fastMode ? -1 : -(getParallaxSize().getX() / 2) - 1; ii < (Iris.settings.performance.fastMode ? 1 : ((getParallaxSize().getX() / 2) + 1)); ii++)
TaskGroup g = startWork();
if(Iris.settings.gen.genObjects)
{
int i = ii;
for(int jj = Iris.settings.performance.fastMode ? -1 : -(getParallaxSize().getZ() / 2) - 1; jj < (Iris.settings.performance.fastMode ? 1 : ((getParallaxSize().getZ() / 2) + 1)); jj++)
for(int ii = Iris.settings.performance.fastMode ? -1 : -(getParallaxSize().getX() / 2) - 1; ii < (Iris.settings.performance.fastMode ? 1 : ((getParallaxSize().getX() / 2) + 1)); ii++)
{
gx++;
int j = jj;
int cx = x + i;
int cz = z + j;
int i = ii;
if(!getWorldData().exists(cx, cz))
for(int jj = Iris.settings.performance.fastMode ? -1 : -(getParallaxSize().getZ() / 2) - 1; jj < (Iris.settings.performance.fastMode ? 1 : ((getParallaxSize().getZ() / 2) + 1)); jj++)
{
g.queue(() ->
{
onGenParallax(cx, cz, getRMaster(cx, cz, -59328));
getWorldData().getChunk(cx, cz);
});
gx++;
int j = jj;
int cx = x + i;
int cz = z + j;
gg++;
if(!getWorldData().exists(cx, cz))
{
g.queue(() ->
{
onGenParallax(cx, cz, getRMaster(cx, cz, -59328));
getWorldData().getChunk(cx, cz);
});
gg++;
}
}
}
}
double a = ps.getMilliseconds();
double b = g.execute().timeElapsed;
((IrisGenerator) this).getMetrics().put("parallax:ms:/chunk", ps.getMillis());
if(Iris.settings.performance.verbose)
{
@ -186,9 +192,9 @@ public abstract class ParallaxWorldGenerator extends ParallelChunkGenerator impl
}
@Override
public final Biome genColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data)
public final Biome genColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data, boolean surface)
{
return onGenColumn(wx, wz, x, z, plan, data);
return onGenColumn(wx, wz, x, z, plan, data, surface);
}
public World getWorld()
@ -221,7 +227,7 @@ public abstract class ParallaxWorldGenerator extends ParallelChunkGenerator impl
public abstract ChunkPlan onInitChunk(World world, int x, int z, Random random);
public abstract Biome onGenColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data2);
public abstract Biome onGenColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data, boolean surfaceOnly);
public abstract void onPostChunk(World world, int x, int z, Random random, AtomicChunkData data, ChunkPlan plan);
}

View File

@ -48,7 +48,7 @@ public abstract class ParallelChunkGenerator extends ChunkGenerator
public Biome generateFullColumn(int a, int b, int c, int d, ChunkPlan p, AtomicChunkData data)
{
return genColumn(a, b, c, d, p, data);
return genColumn(a, b, c, d, p, data, false);
}
public TaskGroup startParallaxWork()
@ -158,5 +158,5 @@ public abstract class ParallelChunkGenerator extends ChunkGenerator
public abstract void postChunk(World world, int x, int z, Random random, AtomicChunkData data, ChunkPlan plan);
public abstract Biome genColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data);
public abstract Biome genColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data, boolean surfaceOnly);
}

View File

@ -1,3 +1,4 @@
package ninja.bytecode.iris.util;
import org.bukkit.block.BlockFace;

View File

@ -0,0 +1,9 @@
package ninja.bytecode.iris.util;
public enum InterpolationMode
{
NONE,
BILINEAR,
BICUBIC,
HERMITE_BICUBIC
}

View File

@ -112,6 +112,62 @@ public class IrisInterpolation
return cubic(cubic(p00, p01, p02, p03, muy), cubic(p10, p11, p12, p13, muy), cubic(p20, p21, p22, p23, muy), cubic(p30, p31, p32, p33, muy), mux);
}
public static double getBilinearNoise(int x, int z, int rad, NoiseProvider n)
{
int fx = x >> rad;
int fz = z >> rad;
int x1 = (fx << rad);
int z1 = (fz << rad);
int x2 = ((fx + 1) << rad);
int z2 = ((fz + 1) << rad);
double px = M.rangeScale(0, 1, x1, x2, x);
double pz = M.rangeScale(0, 1, z1, z2, z);
//@builder
return blerpBezier(
n.noise(x1, z1),
n.noise(x2, z1),
n.noise(x1, z2),
n.noise(x2, z2),
px, pz);
//@done
}
public static double getBicubicNoise(int x, int z, int rad, NoiseProvider n)
{
int fx = x >> rad;
int fz = z >> rad;
int x0 = ((fx - 1) << rad);
int z0 = ((fz - 1) << rad);
int x1 = (fx << rad);
int z1 = (fz << rad);
int x2 = ((fx + 1) << rad);
int z2 = ((fz + 1) << rad);
int x3 = ((fx + 2) << rad);
int z3 = ((fz + 2) << rad);
double px = M.rangeScale(0, 1, x1, x2, x);
double pz = M.rangeScale(0, 1, z1, z2, z);
//@builder
return bicubic(
n.noise(x0, z0),
n.noise(x0, z1),
n.noise(x0, z2),
n.noise(x0, z3),
n.noise(x1, z0),
n.noise(x1, z1),
n.noise(x1, z2),
n.noise(x1, z3),
n.noise(x2, z0),
n.noise(x2, z1),
n.noise(x2, z2),
n.noise(x2, z3),
n.noise(x3, z0),
n.noise(x3, z1),
n.noise(x3, z2),
n.noise(x3, z3),
px, pz);
//@done
}
public static double getHermiteNoise(int x, int z, int rad, NoiseProvider n)
{
int fx = x >> rad;
@ -147,9 +203,4 @@ public class IrisInterpolation
px, pz, 0.00001, 0.5);
//@done
}
public static double getNoise(int x, int z, int lrad, NoiseProvider n)
{
return getHermiteNoise(x, z, lrad, n);
}
}