diff --git a/src/main/java/com/volmit/iris/gen/v2/IrisComplex.java b/src/main/java/com/volmit/iris/gen/v2/IrisComplex.java index 2dc187746..6165446e9 100644 --- a/src/main/java/com/volmit/iris/gen/v2/IrisComplex.java +++ b/src/main/java/com/volmit/iris/gen/v2/IrisComplex.java @@ -110,7 +110,7 @@ public class IrisComplex implements DataProvider .convert((v) -> v.getBlockData()); regionStream = dimension.getRegionStyle().create(rng.nextRNG()).stream() .zoom(dimension.getRegionZoom()) - .select(dimension.getRegions()) + .selectRarity(dimension.getRegions()) .convertCached((s) -> data.getRegionLoader().load(s)) .cache2D(1024); caveBiomeStream = regionStream.convertCached((r) @@ -210,7 +210,7 @@ public class IrisComplex implements DataProvider private IrisDecorator decorateFor(IrisBiome b, double x, double z, DecorationPart part) { RNG rngc = chunkRngStream.get(x, z); - + for(IrisDecorator i : b.getDecorators()) { if(!i.getPartOf().equals(part)) @@ -218,11 +218,10 @@ public class IrisComplex implements DataProvider continue; } - FastBlockData block = i.getBlockData(b, rngc, x, z, data); + FastBlockData block = i.getBlockData(b, rngc, x, z, data); if(block != null) { - Iris.info("DECO AT " + x + " " + z); return i; } } @@ -264,7 +263,7 @@ public class IrisComplex implements DataProvider { double sh = region.getShoreHeight(x, z); - if(height >= fluidHeight && height <= fluidHeight + sh && !biome.isShore()) + if(height >= fluidHeight-1 && height <= fluidHeight + sh && !biome.isShore()) { return shoreBiomeStream.get(x, z); } diff --git a/src/main/java/com/volmit/iris/gen/v2/IrisTerrainGenerator.java b/src/main/java/com/volmit/iris/gen/v2/IrisTerrainGenerator.java index 5766e718e..fb523ca0b 100644 --- a/src/main/java/com/volmit/iris/gen/v2/IrisTerrainGenerator.java +++ b/src/main/java/com/volmit/iris/gen/v2/IrisTerrainGenerator.java @@ -12,75 +12,24 @@ import com.volmit.iris.manager.IrisDataManager; import com.volmit.iris.object.IrisBiome; import com.volmit.iris.object.IrisDecorator; import com.volmit.iris.object.IrisDimension; -import com.volmit.iris.util.IO; -import com.volmit.iris.util.KList; import com.volmit.iris.util.PrecisionStopwatch; import com.volmit.iris.util.RNG; public class IrisTerrainGenerator { - public static void main(String[] a) - { - Hunk v = Hunk.newArrayHunk(7, 7, 7); - v.fill(0D); - KList vx = new KList<>(); - v.compute3D((x, y, z, h) -> - { - h.iterate(0, (xx, yy, zz) -> - { - double vv = 0; - synchronized(vx) - { - vv = (double) vx.indexOfAddIfNeeded((double) (IO.hash(x + " " + y + " " + z).hashCode())); - - h.set(xx, yy, zz, vv); - } - }); - }); - - System.out.println("=================== X Z ====================="); - for(int i = 0; i < v.getWidth(); i++) - { - for(int j = 0; j < v.getDepth(); j++) - { - System.out.print(((int) v.get(i, 0, j).doubleValue()) + " "); - } - - System.out.println(); - } - - System.out.println("=================== X Y ====================="); - for(int i = 0; i < v.getHeight(); i++) - { - for(int j = 0; j < v.getWidth(); j++) - { - System.out.print(((int) v.get(j, i, 0).doubleValue()) + " "); - } - - System.out.println(); - } - - System.out.println("=================== Z Y ====================="); - for(int i = 0; i < v.getHeight(); i++) - { - for(int j = 0; j < v.getDepth(); j++) - { - System.out.print(((int) v.get(0, i, j).doubleValue()) + " "); - } - - System.out.println(); - } - } - private long seed; private IrisDataManager data; private IrisDimension dimension; private IrisComplex complex; + private RNG rng; + private int parallelism; private static final Predicate PREDICATE_SOLID = (b) -> b != null && !b.getMaterial().isAir() && !b.getMaterial().equals(Material.WATER) && !b.getMaterial().equals(Material.LAVA); public IrisTerrainGenerator(long seed, IrisDimension dimension, IrisDataManager data) { + parallelism = 8; this.seed = seed; + this.rng = new RNG(seed); complex = new IrisComplex(); this.data = data; this.dimension = dimension; @@ -95,29 +44,28 @@ public class IrisTerrainGenerator private void fill2D(ProceduralStream t, Hunk h, double x, double z, ProceduralStream v) { - t.fill2D(h, x * 16, z * 16, v, 8); + t.fill2D(h, x * 16, z * 16, v, parallelism); } private void fill2DYLock(ProceduralStream t, Hunk h, double x, double z, ProceduralStream v) { - t.fill2DYLocked(h, x * 16, z * 16, v, 8); + t.fill2DYLocked(h, x * 16, z * 16, v, parallelism); } public void generateDecorations(int x, int z, Hunk blocks) { - RNG rng = complex.getRngStream().get(x, z); int bx = (x * 16); int bz = (z * 16); - blocks.iterateSurfaces2D(PREDICATE_SOLID, (xx, zz, top, bottom, lastBottom, h) -> + blocks.iterateSurfaces2D(parallelism, PREDICATE_SOLID, (ax, az, xx, zz, top, bottom, lastBottom, h) -> { - int rx = bx + xx; - int rz = bz + zz; + int rx = bx + xx + ax; + int rz = bz + zz + az; RNG g = rng.nextParallelRNG(rx).nextParallelRNG(rz); IrisBiome b = complex.getTrueBiomeStream().get(rx, rz); boolean surface = lastBottom == -1; int floor = top + 1; - int ceiling = lastBottom == -1 ? blocks.getHeight() : lastBottom - 1; + int ceiling = lastBottom == -1 ? floor < dimension.getFluidHeight() ? dimension.getFluidHeight() : blocks.getHeight() : lastBottom - 1; int height = ceiling - floor; if(height < 2) @@ -135,18 +83,18 @@ public class IrisTerrainGenerator for(int i = 0; i < stack; i++) { - h.set(xx, i + floor, zz, deco.getBlockData100(b, rng, rx - i, rz + i, data).getBlockData()); + h.set(ax, i + floor, az, deco.getBlockData100(b, rng, rx - i, rz + i, data).getBlockData()); } if(deco.getTopPalette().isNotEmpty()) { - h.set(xx, stack + floor - 1, zz, deco.getBlockDataForTop(b, rng, rx - stack, rz + stack, data).getBlockData()); + h.set(ax, stack + floor - 1, az, deco.getBlockDataForTop(b, rng, rx - stack, rz + stack, data).getBlockData()); } } else { - h.set(xx, floor, zz, deco.getBlockData100(b, rng, rx, rz, data).getBlockData()); + h.set(ax, floor, az, deco.getBlockData100(b, rng, rx, rz, data).getBlockData()); } } @@ -162,18 +110,18 @@ public class IrisTerrainGenerator for(int i = 0; i < stack; i++) { - h.set(xx, -i + ceiling, zz, cdeco.getBlockData100(b, rng, rx - i, rz + i, data).getBlockData()); + h.set(ax, -i + ceiling, az, cdeco.getBlockData100(b, rng, rx - i, rz + i, data).getBlockData()); } if(cdeco.getTopPalette().isNotEmpty()) { - h.set(xx, -stack + ceiling - 1, zz, cdeco.getBlockDataForTop(b, rng, rx - stack, rz + stack, data).getBlockData()); + h.set(ax, -stack + ceiling - 1, az, cdeco.getBlockDataForTop(b, rng, rx - stack, rz + stack, data).getBlockData()); } } else { - h.set(xx, ceiling, zz, cdeco.getBlockData100(b, rng, rx, rz, data).getBlockData()); + h.set(ax, ceiling, az, cdeco.getBlockData100(b, rng, rx, rz, data).getBlockData()); } } } diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/AtomicDoubleHunk.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/AtomicDoubleHunk.java index e174075df..54702e94c 100644 --- a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/AtomicDoubleHunk.java +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/AtomicDoubleHunk.java @@ -17,6 +17,12 @@ public class AtomicDoubleHunk extends StorageHunk implements Hunk extends StorageHunk implements Hunk super(w, h, d); data = new AtomicReferenceArray(w * h * d); } + + @Override + public boolean isAtomic() + { + return true; + } @Override public void setRaw(int x, int y, int z, T t) diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/AtomicIntegerHunk.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/AtomicIntegerHunk.java index c6f836363..7dfb93867 100644 --- a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/AtomicIntegerHunk.java +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/AtomicIntegerHunk.java @@ -17,6 +17,12 @@ public class AtomicIntegerHunk extends StorageHunk implements Hunk implements Hunk data = new AtomicLongArray(w * h * d); } + @Override + public boolean isAtomic() + { + return true; + } + @Override public void setRaw(int x, int y, int z, Long t) { diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/DriftHunkView.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/DriftHunkView.java new file mode 100644 index 000000000..b396a1542 --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/DriftHunkView.java @@ -0,0 +1,53 @@ +package com.volmit.iris.gen.v2.scaffold.hunk; + +public class DriftHunkView implements Hunk +{ + private final int ox; + private final int oy; + private final int oz; + private final Hunk src; + + public DriftHunkView(Hunk src, int ox, int oy, int oz) + { + this.src = src; + this.ox = ox; + this.oy = oy; + this.oz = oz; + } + + @Override + public void setRaw(int x, int y, int z, T t) + { + src.setRaw(x + ox, y + oy, z + oz, t); + } + + @Override + public T getRaw(int x, int y, int z) + { + return src.getRaw(x + ox, y + oy, z + oz); + } + + @Override + public int getWidth() + { + return src.getWidth(); + } + + @Override + public int getHeight() + { + return src.getHeight(); + } + + @Override + public int getDepth() + { + return src.getDepth(); + } + + @Override + public Hunk getSource() + { + return src; + } +} diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/Hunk.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/Hunk.java index ef65b747e..a1932efa3 100644 --- a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/Hunk.java +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/Hunk.java @@ -14,7 +14,7 @@ import com.volmit.iris.util.Consumer2; import com.volmit.iris.util.Consumer3; import com.volmit.iris.util.Consumer4; import com.volmit.iris.util.Consumer5; -import com.volmit.iris.util.Consumer6; +import com.volmit.iris.util.Consumer8; import com.volmit.iris.util.Function3; import com.volmit.iris.util.KList; @@ -178,6 +178,11 @@ public interface Hunk return b; } + default boolean isAtomic() + { + return false; + } + default Hunk invertY() { return new InvertedHunkView(this); @@ -270,21 +275,143 @@ public interface Hunk return filterDimension((int) Math.ceil(Math.cbrt(sections))); } - default Hunk iterateSurfaces2D(Predicate p, Consumer6> c) + /** + * Iterate surfaces on 2d. Raytraces with a front and a back which stretches + * through surfaces. Essentially what is returned is the following (in + * order)
+ *
+ * + * The predicate is used to determine if the given block type is solid or not. + * + *
+ *
+ * ================================================
+ * AX, AZ: Hunk Relative X and Z + * + *
+ *
+ * HX, HZ: Hunk Positional X and Z (in its parent hunk) + * + *
+ *
+ * TOP: The top of this surface (top+1 is air above a surface) + * + *
+ *
+ * BOTTOM: The bottom of this surface (bottom is the lowest SOLID surface before + * either air or bedrock going down further) + * + *
+ *
+ * LAST_BOTTOM: The previous bottom. If your surface is the top surface, this + * will be -1 as there is no bottom-of-surface above you. However if you are not + * the top surface, this value is equal to the next solid layer above TOP, such + * that ((LAST_BOTTOM - 1) - (TOP + 1)) is how many air blocks are between your + * surface and the surface above you + * + *
+ *
+ * HUNK: The hunk to set data to.
+ * ================================================
+ *
+ * If we assume your chunk coordinates are x and z, then
+ *
+ * bX = (x * 16)
+ * bZ = (z * 16)
+ *
+ * (ax, az, hx, hz, top, bottom, lastBottom, hunk) {
+ * actualBlockX = ax+hx;
+ * actualBlockZ = az+hz;
+ *
+ * hunkX = ax;
+ * hunkZ = az;
+ *
+ * hunk.set(hunkX, ?, hunkZ, noise(actualBlockX, ?, actualBlockZ));
+ * }
+ * + * @param p + * the predicate + * @param c + * the consumer + * @return this + */ + default Hunk iterateSurfaces2D(Predicate p, Consumer8> c) { return iterateSurfaces2D(getIdeal2DParallelism(), p, c); } - default Hunk iterateSurfaces2D(int parallelism, Predicate p, Consumer6> c) + /** + * Iterate surfaces on 2d. Raytraces with a front and a back which stretches + * through surfaces. Essentially what is returned is the following (in + * order)
+ *
+ * + * The predicate is used to determine if the given block type is solid or not. + * + *
+ *
+ * ================================================
+ * AX, AZ: Hunk Relative X and Z + * + *
+ *
+ * HX, HZ: Hunk Positional X and Z (in its parent hunk) + * + *
+ *
+ * TOP: The top of this surface (top+1 is air above a surface) + * + *
+ *
+ * BOTTOM: The bottom of this surface (bottom is the lowest SOLID surface before + * either air or bedrock going down further) + * + *
+ *
+ * LAST_BOTTOM: The previous bottom. If your surface is the top surface, this + * will be -1 as there is no bottom-of-surface above you. However if you are not + * the top surface, this value is equal to the next solid layer above TOP, such + * that ((LAST_BOTTOM - 1) - (TOP + 1)) is how many air blocks are between your + * surface and the surface above you + * + *
+ *
+ * HUNK: The hunk to set data to.
+ * ================================================
+ *
+ * If we assume your chunk coordinates are x and z, then
+ *
+ * bX = (x * 16)
+ * bZ = (z * 16)
+ *
+ * (ax, az, hx, hz, top, bottom, lastBottom, hunk) {
+ * actualBlockX = ax+hx;
+ * actualBlockZ = az+hz;
+ *
+ * hunkX = ax;
+ * hunkZ = az;
+ *
+ * hunk.set(hunkX, ?, hunkZ, noise(actualBlockX, ?, actualBlockZ));
+ * }
+ * + * @param parallelism + * the ideal threads to use on this + * @param p + * the predicate + * @param c + * the consumer + * @return this + */ + default Hunk iterateSurfaces2D(int parallelism, Predicate p, Consumer8> c) { - iterate2DTop(parallelism, (x, z, h) -> + iterate2DTop(parallelism, (ax, az, hox, hoz, h) -> { int last = -1; int in = getHeight() - 1; boolean hitting = false; for(int i = getHeight() - 1; i >= 0; i--) { - boolean solid = p.test(get(x, i, z)); + boolean solid = p.test(h.get(ax, i, az)); if(!hitting && solid) { @@ -295,26 +422,55 @@ public interface Hunk else if(hitting && !solid) { hitting = false; - c.accept(x, z, in, i - 1, last, h); + c.accept(ax, az, hox, hoz, in, i - 1, last, h); last = i - 1; } } if(hitting) { - c.accept(x, z, in, 0, last, h); + c.accept(ax, az, hox, hoz, in, 0, last, h); } }); return this; } - default Hunk iterate2DTop(Consumer3> c) + /** + * Iterate on the xz top of this hunk. When using this consumer, given + * + * consumer: (ax, az, hx, hz, hunk) + * + * hunk.set(ax, ?, az, NOISE.get(ax+hx, az+hz)); + * + * @param c + * the consumer hunkX, hunkZ, hunkOffsetX, hunkOffsetZ. + * @return this + */ + default Hunk iterate2DTop(Consumer5> c) { return iterate2DTop(getIdeal2DParallelism(), c); } - default Hunk iterate2DTop(int parallelism, Consumer3> c) + default Hunk drift(int x, int y, int z) + { + return new DriftHunkView<>(this, x, y, z); + } + + /** + * Iterate on the xz top of this hunk. When using this consumer, given + * + * consumer: (ax, az, hx, hz, hunk) + * + * hunk.set(ax, ?, az, NOISE.get(ax+hx, az+hz)); + * + * @param parallelism + * the target parallelism value or 0 to disable + * @param c + * the consumer hunkX, hunkZ, hunkOffsetX, hunkOffsetZ. + * @return this + */ + default Hunk iterate2DTop(int parallelism, Consumer5> c) { compute2D(parallelism, (x, y, z, h) -> { @@ -322,7 +478,7 @@ public interface Hunk { for(int k = 0; k < h.getDepth(); k++) { - c.accept(i + x, k + z, h); + c.accept(i, k, x, z, h); } } }); @@ -432,6 +588,7 @@ public interface Hunk getSections2D(parallelism, (xx, yy, zz, h, r) -> e.queue(() -> { v.accept(xx, yy, zz, h); + synchronized(rq) { rq.add(r); @@ -541,11 +698,7 @@ public interface Hunk for(k = 0; k < getDepth(); k += d) { int kk = k; - getSection(ii, jj, kk, - i + w + (i == 0 ? wr : 0), - j + h + (j == 0 ? hr : 0), - k + d + (k == 0 ? dr : 0), - (hh, r) -> v.accept(ii, jj, kk, hh, r), inserter); + getSection(ii, jj, kk, i + w + (i == 0 ? wr : 0), j + h + (j == 0 ? hr : 0), k + d + (k == 0 ? dr : 0), (hh, r) -> v.accept(ii, jj, kk, hh, r), inserter); i = i == 0 ? i + wr : i; j = j == 0 ? j + hr : j; k = k == 0 ? k + dr : k; diff --git a/src/main/java/com/volmit/iris/util/Consumer7.java b/src/main/java/com/volmit/iris/util/Consumer7.java new file mode 100644 index 000000000..a0af81d86 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/Consumer7.java @@ -0,0 +1,8 @@ +package com.volmit.iris.util; + +@SuppressWarnings("hiding") +@FunctionalInterface +public interface Consumer7 +{ + public void accept(A a, B b, C c, D d, E e, F f, G g); +} diff --git a/src/main/java/com/volmit/iris/util/Consumer8.java b/src/main/java/com/volmit/iris/util/Consumer8.java new file mode 100644 index 000000000..43d124a61 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/Consumer8.java @@ -0,0 +1,8 @@ +package com.volmit.iris.util; + +@SuppressWarnings("hiding") +@FunctionalInterface +public interface Consumer8 +{ + public void accept(A a, B b, C c, D d, E e, F f, G g, H h); +}