Decorations!

This commit is contained in:
Daniel Mills 2020-10-27 01:10:19 -04:00
parent a7f8d9126e
commit c4536d789b
10 changed files with 281 additions and 88 deletions

View File

@ -110,7 +110,7 @@ public class IrisComplex implements DataProvider
.convert((v) -> v.getBlockData()); .convert((v) -> v.getBlockData());
regionStream = dimension.getRegionStyle().create(rng.nextRNG()).stream() regionStream = dimension.getRegionStyle().create(rng.nextRNG()).stream()
.zoom(dimension.getRegionZoom()) .zoom(dimension.getRegionZoom())
.select(dimension.getRegions()) .selectRarity(dimension.getRegions())
.convertCached((s) -> data.getRegionLoader().load(s)) .convertCached((s) -> data.getRegionLoader().load(s))
.cache2D(1024); .cache2D(1024);
caveBiomeStream = regionStream.convertCached((r) caveBiomeStream = regionStream.convertCached((r)
@ -222,7 +222,6 @@ public class IrisComplex implements DataProvider
if(block != null) if(block != null)
{ {
Iris.info("DECO AT " + x + " " + z);
return i; return i;
} }
} }
@ -264,7 +263,7 @@ public class IrisComplex implements DataProvider
{ {
double sh = region.getShoreHeight(x, z); 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); return shoreBiomeStream.get(x, z);
} }

View File

@ -12,75 +12,24 @@ import com.volmit.iris.manager.IrisDataManager;
import com.volmit.iris.object.IrisBiome; import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDecorator; import com.volmit.iris.object.IrisDecorator;
import com.volmit.iris.object.IrisDimension; 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.PrecisionStopwatch;
import com.volmit.iris.util.RNG; import com.volmit.iris.util.RNG;
public class IrisTerrainGenerator public class IrisTerrainGenerator
{ {
public static void main(String[] a)
{
Hunk<Double> v = Hunk.newArrayHunk(7, 7, 7);
v.fill(0D);
KList<Double> 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 long seed;
private IrisDataManager data; private IrisDataManager data;
private IrisDimension dimension; private IrisDimension dimension;
private IrisComplex complex; private IrisComplex complex;
private RNG rng;
private int parallelism;
private static final Predicate<BlockData> PREDICATE_SOLID = (b) -> b != null && !b.getMaterial().isAir() && !b.getMaterial().equals(Material.WATER) && !b.getMaterial().equals(Material.LAVA); private static final Predicate<BlockData> 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) public IrisTerrainGenerator(long seed, IrisDimension dimension, IrisDataManager data)
{ {
parallelism = 8;
this.seed = seed; this.seed = seed;
this.rng = new RNG(seed);
complex = new IrisComplex(); complex = new IrisComplex();
this.data = data; this.data = data;
this.dimension = dimension; this.dimension = dimension;
@ -95,29 +44,28 @@ public class IrisTerrainGenerator
private <V, T> void fill2D(ProceduralStream<T> t, Hunk<V> h, double x, double z, ProceduralStream<V> v) private <V, T> void fill2D(ProceduralStream<T> t, Hunk<V> h, double x, double z, ProceduralStream<V> v)
{ {
t.fill2D(h, x * 16, z * 16, v, 8); t.fill2D(h, x * 16, z * 16, v, parallelism);
} }
private <V, T> void fill2DYLock(ProceduralStream<T> t, Hunk<V> h, double x, double z, ProceduralStream<V> v) private <V, T> void fill2DYLock(ProceduralStream<T> t, Hunk<V> h, double x, double z, ProceduralStream<V> 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<BlockData> blocks) public void generateDecorations(int x, int z, Hunk<BlockData> blocks)
{ {
RNG rng = complex.getRngStream().get(x, z);
int bx = (x * 16); int bx = (x * 16);
int bz = (z * 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 rx = bx + xx + ax;
int rz = bz + zz; int rz = bz + zz + az;
RNG g = rng.nextParallelRNG(rx).nextParallelRNG(rz); RNG g = rng.nextParallelRNG(rx).nextParallelRNG(rz);
IrisBiome b = complex.getTrueBiomeStream().get(rx, rz); IrisBiome b = complex.getTrueBiomeStream().get(rx, rz);
boolean surface = lastBottom == -1; boolean surface = lastBottom == -1;
int floor = top + 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; int height = ceiling - floor;
if(height < 2) if(height < 2)
@ -135,18 +83,18 @@ public class IrisTerrainGenerator
for(int i = 0; i < stack; i++) 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()) 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 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++) 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()) 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 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());
} }
} }
} }

View File

@ -17,6 +17,12 @@ public class AtomicDoubleHunk extends StorageHunk<Double> implements Hunk<Double
data = new AtomicDoubleArray(w * h * d); data = new AtomicDoubleArray(w * h * d);
} }
@Override
public boolean isAtomic()
{
return true;
}
@Override @Override
public void setRaw(int x, int y, int z, Double t) public void setRaw(int x, int y, int z, Double t)
{ {

View File

@ -17,6 +17,12 @@ public class AtomicHunk<T> extends StorageHunk<T> implements Hunk<T>
data = new AtomicReferenceArray<T>(w * h * d); data = new AtomicReferenceArray<T>(w * h * d);
} }
@Override
public boolean isAtomic()
{
return true;
}
@Override @Override
public void setRaw(int x, int y, int z, T t) public void setRaw(int x, int y, int z, T t)
{ {

View File

@ -17,6 +17,12 @@ public class AtomicIntegerHunk extends StorageHunk<Integer> implements Hunk<Inte
data = new AtomicIntegerArray(w * h * d); data = new AtomicIntegerArray(w * h * d);
} }
@Override
public boolean isAtomic()
{
return true;
}
@Override @Override
public void setRaw(int x, int y, int z, Integer t) public void setRaw(int x, int y, int z, Integer t)
{ {

View File

@ -17,6 +17,12 @@ public class AtomicLongHunk extends StorageHunk<Long> implements Hunk<Long>
data = new AtomicLongArray(w * h * d); data = new AtomicLongArray(w * h * d);
} }
@Override
public boolean isAtomic()
{
return true;
}
@Override @Override
public void setRaw(int x, int y, int z, Long t) public void setRaw(int x, int y, int z, Long t)
{ {

View File

@ -0,0 +1,53 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
public class DriftHunkView<T> implements Hunk<T>
{
private final int ox;
private final int oy;
private final int oz;
private final Hunk<T> src;
public DriftHunkView(Hunk<T> 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<T> getSource()
{
return src;
}
}

View File

@ -14,7 +14,7 @@ import com.volmit.iris.util.Consumer2;
import com.volmit.iris.util.Consumer3; import com.volmit.iris.util.Consumer3;
import com.volmit.iris.util.Consumer4; import com.volmit.iris.util.Consumer4;
import com.volmit.iris.util.Consumer5; 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.Function3;
import com.volmit.iris.util.KList; import com.volmit.iris.util.KList;
@ -178,6 +178,11 @@ public interface Hunk<T>
return b; return b;
} }
default boolean isAtomic()
{
return false;
}
default Hunk<T> invertY() default Hunk<T> invertY()
{ {
return new InvertedHunkView<T>(this); return new InvertedHunkView<T>(this);
@ -270,21 +275,143 @@ public interface Hunk<T>
return filterDimension((int) Math.ceil(Math.cbrt(sections))); return filterDimension((int) Math.ceil(Math.cbrt(sections)));
} }
default Hunk<T> iterateSurfaces2D(Predicate<T> p, Consumer6<Integer, Integer, Integer, Integer, Integer, Hunk<T>> 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)<br>
* <br>
*
* The predicate is used to determine if the given block type is solid or not.
*
* <br>
* <br>
* ================================================ <br>
* AX, AZ: Hunk Relative X and Z
*
* <br>
* <br>
* HX, HZ: Hunk Positional X and Z (in its parent hunk)
*
* <br>
* <br>
* TOP: The top of this surface (top+1 is air above a surface)
*
* <br>
* <br>
* BOTTOM: The bottom of this surface (bottom is the lowest SOLID surface before
* either air or bedrock going down further)
*
* <br>
* <br>
* 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
*
* <br>
* <br>
* HUNK: The hunk to set data to. <br>
* ================================================ <br>
* <br>
* If we assume your chunk coordinates are x and z, then <br>
* <br>
* bX = (x * 16)<br>
* bZ = (z * 16)<br>
* <br>
* (ax, az, hx, hz, top, bottom, lastBottom, hunk) {<br>
* actualBlockX = ax+hx;<br>
* actualBlockZ = az+hz;<br>
* <br>
* hunkX = ax;<br>
* hunkZ = az;<br>
* <br>
* hunk.set(hunkX, ?, hunkZ, noise(actualBlockX, ?, actualBlockZ));<br>
* }<br>
*
* @param p
* the predicate
* @param c
* the consumer
* @return this
*/
default Hunk<T> iterateSurfaces2D(Predicate<T> p, Consumer8<Integer, Integer, Integer, Integer, Integer, Integer, Integer, Hunk<T>> c)
{ {
return iterateSurfaces2D(getIdeal2DParallelism(), p, c); return iterateSurfaces2D(getIdeal2DParallelism(), p, c);
} }
default Hunk<T> iterateSurfaces2D(int parallelism, Predicate<T> p, Consumer6<Integer, Integer, Integer, Integer, Integer, Hunk<T>> 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)<br>
* <br>
*
* The predicate is used to determine if the given block type is solid or not.
*
* <br>
* <br>
* ================================================ <br>
* AX, AZ: Hunk Relative X and Z
*
* <br>
* <br>
* HX, HZ: Hunk Positional X and Z (in its parent hunk)
*
* <br>
* <br>
* TOP: The top of this surface (top+1 is air above a surface)
*
* <br>
* <br>
* BOTTOM: The bottom of this surface (bottom is the lowest SOLID surface before
* either air or bedrock going down further)
*
* <br>
* <br>
* 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
*
* <br>
* <br>
* HUNK: The hunk to set data to. <br>
* ================================================ <br>
* <br>
* If we assume your chunk coordinates are x and z, then <br>
* <br>
* bX = (x * 16)<br>
* bZ = (z * 16)<br>
* <br>
* (ax, az, hx, hz, top, bottom, lastBottom, hunk) {<br>
* actualBlockX = ax+hx;<br>
* actualBlockZ = az+hz;<br>
* <br>
* hunkX = ax;<br>
* hunkZ = az;<br>
* <br>
* hunk.set(hunkX, ?, hunkZ, noise(actualBlockX, ?, actualBlockZ));<br>
* }<br>
*
* @param parallelism
* the ideal threads to use on this
* @param p
* the predicate
* @param c
* the consumer
* @return this
*/
default Hunk<T> iterateSurfaces2D(int parallelism, Predicate<T> p, Consumer8<Integer, Integer, Integer, Integer, Integer, Integer, Integer, Hunk<T>> c)
{ {
iterate2DTop(parallelism, (x, z, h) -> iterate2DTop(parallelism, (ax, az, hox, hoz, h) ->
{ {
int last = -1; int last = -1;
int in = getHeight() - 1; int in = getHeight() - 1;
boolean hitting = false; boolean hitting = false;
for(int i = getHeight() - 1; i >= 0; i--) 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) if(!hitting && solid)
{ {
@ -295,26 +422,55 @@ public interface Hunk<T>
else if(hitting && !solid) else if(hitting && !solid)
{ {
hitting = false; 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; last = i - 1;
} }
} }
if(hitting) if(hitting)
{ {
c.accept(x, z, in, 0, last, h); c.accept(ax, az, hox, hoz, in, 0, last, h);
} }
}); });
return this; return this;
} }
default Hunk<T> iterate2DTop(Consumer3<Integer, Integer, Hunk<T>> 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<T> iterate2DTop(Consumer5<Integer, Integer, Integer, Integer, Hunk<T>> c)
{ {
return iterate2DTop(getIdeal2DParallelism(), c); return iterate2DTop(getIdeal2DParallelism(), c);
} }
default Hunk<T> iterate2DTop(int parallelism, Consumer3<Integer, Integer, Hunk<T>> c) default Hunk<T> 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<T> iterate2DTop(int parallelism, Consumer5<Integer, Integer, Integer, Integer, Hunk<T>> c)
{ {
compute2D(parallelism, (x, y, z, h) -> compute2D(parallelism, (x, y, z, h) ->
{ {
@ -322,7 +478,7 @@ public interface Hunk<T>
{ {
for(int k = 0; k < h.getDepth(); k++) 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<T>
getSections2D(parallelism, (xx, yy, zz, h, r) -> e.queue(() -> getSections2D(parallelism, (xx, yy, zz, h, r) -> e.queue(() ->
{ {
v.accept(xx, yy, zz, h); v.accept(xx, yy, zz, h);
synchronized(rq) synchronized(rq)
{ {
rq.add(r); rq.add(r);
@ -541,11 +698,7 @@ public interface Hunk<T>
for(k = 0; k < getDepth(); k += d) for(k = 0; k < getDepth(); k += d)
{ {
int kk = k; int kk = k;
getSection(ii, jj, kk, 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 + 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; i = i == 0 ? i + wr : i;
j = j == 0 ? j + hr : j; j = j == 0 ? j + hr : j;
k = k == 0 ? k + dr : k; k = k == 0 ? k + dr : k;

View File

@ -0,0 +1,8 @@
package com.volmit.iris.util;
@SuppressWarnings("hiding")
@FunctionalInterface
public interface Consumer7<A, B, C, D, E, F, G>
{
public void accept(A a, B b, C c, D d, E e, F f, G g);
}

View File

@ -0,0 +1,8 @@
package com.volmit.iris.util;
@SuppressWarnings("hiding")
@FunctionalInterface
public interface Consumer8<A, B, C, D, E, F, G, H>
{
public void accept(A a, B b, C c, D d, E e, F f, G g, H h);
}