diff --git a/src/main/java/ninja/bytecode/iris/CommandIris.java b/src/main/java/ninja/bytecode/iris/CommandIris.java index 3938ed0da..bb029c309 100644 --- a/src/main/java/ninja/bytecode/iris/CommandIris.java +++ b/src/main/java/ninja/bytecode/iris/CommandIris.java @@ -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")) diff --git a/src/main/java/ninja/bytecode/iris/Iris.java b/src/main/java/ninja/bytecode/iris/Iris.java index 25c4f3b96..cd613f623 100644 --- a/src/main/java/ninja/bytecode/iris/Iris.java +++ b/src/main/java/ninja/bytecode/iris/Iris.java @@ -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() { diff --git a/src/main/java/ninja/bytecode/iris/IrisMetrics.java b/src/main/java/ninja/bytecode/iris/IrisMetrics.java new file mode 100644 index 000000000..85417c11a --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/IrisMetrics.java @@ -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 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 getSequences() + { + return sequences; + } + + public void setSequences(GMap sequences) + { + this.sequences = sequences; + } + + public void send(Player p, Consumer c) + { + send(p, c, null, 0); + } + + public void setParScale(double sf) + { + scale = sf; + } + + public void send(Player p, Consumer c, String parent, int ind) + { + GMap out = new GMap<>(); + + looking: for(String i : getSequences().k()) + { + GList 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); + } + } +} diff --git a/src/main/java/ninja/bytecode/iris/Settings.java b/src/main/java/ninja/bytecode/iris/Settings.java index bfe4c5f59..07ae139c2 100644 --- a/src/main/java/ninja/bytecode/iris/Settings.java +++ b/src/main/java/ninja/bytecode/iris/Settings.java @@ -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; diff --git a/src/main/java/ninja/bytecode/iris/controller/ExecutionController.java b/src/main/java/ninja/bytecode/iris/controller/ExecutionController.java index b40c9d903..88f8ef4ef 100644 --- a/src/main/java/ninja/bytecode/iris/controller/ExecutionController.java +++ b/src/main/java/ninja/bytecode/iris/controller/ExecutionController.java @@ -33,7 +33,7 @@ public class ExecutionController implements IrisController return x; } - private int getTC() + public int getTC() { switch(Iris.settings.performance.performanceMode) { diff --git a/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java b/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java index 1fddc9151..6ee92802c 100644 --- a/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java @@ -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(); } diff --git a/src/main/java/ninja/bytecode/iris/generator/WorldReactor.java b/src/main/java/ninja/bytecode/iris/generator/WorldReactor.java index c71c1fc6b..ef5652615 100644 --- a/src/main/java/ninja/bytecode/iris/generator/WorldReactor.java +++ b/src/main/java/ninja/bytecode/iris/generator/WorldReactor.java @@ -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); } } diff --git a/src/main/java/ninja/bytecode/iris/generator/genobject/GenObject.java b/src/main/java/ninja/bytecode/iris/generator/genobject/GenObject.java index 14aa1ce3b..fd5051971 100644 --- a/src/main/java/ninja/bytecode/iris/generator/genobject/GenObject.java +++ b/src/main/java/ninja/bytecode/iris/generator/genobject/GenObject.java @@ -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; + } } } diff --git a/src/main/java/ninja/bytecode/iris/generator/genobject/GenObjectDecorator.java b/src/main/java/ninja/bytecode/iris/generator/genobject/GenObjectDecorator.java index d99bc0348..743e4c6fb 100644 --- a/src/main/java/ninja/bytecode/iris/generator/genobject/GenObjectDecorator.java +++ b/src/main/java/ninja/bytecode/iris/generator/genobject/GenObjectDecorator.java @@ -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())); diff --git a/src/main/java/ninja/bytecode/iris/generator/parallax/ParallaxWorldGenerator.java b/src/main/java/ninja/bytecode/iris/generator/parallax/ParallaxWorldGenerator.java index 0af842718..d6480610b 100644 --- a/src/main/java/ninja/bytecode/iris/generator/parallax/ParallaxWorldGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/parallax/ParallaxWorldGenerator.java @@ -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); } diff --git a/src/main/java/ninja/bytecode/iris/generator/parallax/ParallelChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/parallax/ParallelChunkGenerator.java index 14f84552e..bdc25fe99 100644 --- a/src/main/java/ninja/bytecode/iris/generator/parallax/ParallelChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/parallax/ParallelChunkGenerator.java @@ -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); } \ No newline at end of file diff --git a/src/main/java/ninja/bytecode/iris/util/Direction.java b/src/main/java/ninja/bytecode/iris/util/Direction.java index c125585da..855355147 100644 --- a/src/main/java/ninja/bytecode/iris/util/Direction.java +++ b/src/main/java/ninja/bytecode/iris/util/Direction.java @@ -1,3 +1,4 @@ + package ninja.bytecode.iris.util; import org.bukkit.block.BlockFace; diff --git a/src/main/java/ninja/bytecode/iris/util/InterpolationMode.java b/src/main/java/ninja/bytecode/iris/util/InterpolationMode.java new file mode 100644 index 000000000..d9204fd08 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/InterpolationMode.java @@ -0,0 +1,9 @@ +package ninja.bytecode.iris.util; + +public enum InterpolationMode +{ + NONE, + BILINEAR, + BICUBIC, + HERMITE_BICUBIC +} diff --git a/src/main/java/ninja/bytecode/iris/util/IrisInterpolation.java b/src/main/java/ninja/bytecode/iris/util/IrisInterpolation.java index caccb3098..a8ad5bc1c 100644 --- a/src/main/java/ninja/bytecode/iris/util/IrisInterpolation.java +++ b/src/main/java/ninja/bytecode/iris/util/IrisInterpolation.java @@ -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); - } }