Browse Source

Added new PointWorld types, including a cache

master
Thomas Johnson 2 years ago
parent
commit
7431109808
  1. 49
      src/main/java/t/j/dual/CachedPointWorld.java
  2. 50
      src/main/java/t/j/dual/GridCache.java
  3. 19
      src/main/java/t/j/dual/PointWorld.java
  4. 21
      src/main/java/t/j/dual/RandomPointWorld.java
  5. 39
      src/main/java/t/j/dual/RecelledPointWorld.java
  6. 45
      src/main/java/t/j/dual/ScaledPointWorld.java
  7. 12
      src/main/java/t/j/dual/Utilities.java
  8. 45
      src/main/java/t/j/dual/WorldProviderPeace.java

49
src/main/java/t/j/dual/CachedPointWorld.java

@ -0,0 +1,49 @@
package t.j.dual;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.WeakHashMap;
import net.minecraft.util.math.*;
import t.j.dual.PointWorld;
import t.j.dual.GridCache;
public class CachedPointWorld implements PointWorld {
PointWorld pworld;
GridCache<ArrayList<Vec3d>> cache;
float mean;
Vec3d cellsize;
public CachedPointWorld(PointWorld pworld) {
this.pworld = pworld;
this.cellsize = pworld.getCellSize();
this.cache = new GridCache<ArrayList<Vec3d>>((cell) -> pworld.pointsInCell(cell));
}
public float getMeanPointsPerCell() {
return mean;
}
// TODO: maybe cache?
public Vec3d getCellOrigin(Vec3i cell) {
return pworld.getCellOrigin(cell);
}
public Vec3d getCellSize() {
return cellsize;
}
public ArrayList<Vec3d> cache(Vec3i cell) {
return cache.cache(cell);
}
public void expunge(Vec3i cell) {
cache.expunge(cell);
}
public ArrayList<Vec3d> pointsInCell(Vec3i cell) {
return cache.get(cell);
}
}

50
src/main/java/t/j/dual/GridCache.java

@ -0,0 +1,50 @@
package t.j.dual;
import java.lang.ref.SoftReference;
import java.util.WeakHashMap;
import java.util.function.Function;
import net.minecraft.util.math.*;
import t.j.dual.Utilities;
public class GridCache<T> {
Function<Vec3i, T> source;
WeakHashMap<Vec3i, SoftReference<CacheEntry<T>>> cacheMap;
class CacheEntry<T> {
public Vec3i keyRef;
public T value;
public CacheEntry(Vec3i keyRef, T value) {
this.keyRef = keyRef;
this.value = value;
}
}
public GridCache(Function<Vec3i, T> source) {
this.source = source;
this.cacheMap = new WeakHashMap<Vec3i, SoftReference<CacheEntry<T>>>();
}
public T cache(Vec3i cell) {
T toCache = source.apply(cell);
cacheMap.put(cell, new SoftReference<CacheEntry<T>>(new CacheEntry<T>(cell, toCache)));
return toCache;
}
public void expunge(Vec3i cell) {
cacheMap.remove(cell);
}
public T get(Vec3i cell) {
SoftReference<CacheEntry<T>> softRef = cacheMap.get(cell);
if (softRef != null) {
CacheEntry<T> entry = softRef.get();
if (entry != null) {
return entry.value;
}
}
return cache(cell);
}
}

19
src/main/java/t/j/dual/PointWorld.java

@ -2,20 +2,29 @@ package t.j.dual;
import java.util.Random;
import java.util.ArrayList;
import java.util.stream.Collectors;
import net.minecraft.util.math.*;
import t.j.dual.Utilities;
interface PointWorld {
public Vec3d[] pointsInCell(Vec3i cell);
public ArrayList<Vec3d> pointsInCell(Vec3i cell);
public float getMeanPointsPerCell();
public Vec3d getCellOrigin(Vec3i cell);
public Vec3d getCellSize();
default public ArrayList<Vec3d> pointsInAABB(Vec3d origin, Vec3d remote) {
default public ArrayList<Vec3d> pointsInAABB(Vec3d uOrigin, Vec3d uRemote) {
Vec3d origin = Utilities.ewDiv(uOrigin, this.getCellSize());
Vec3d remote = Utilities.ewDiv(uRemote, this.getCellSize());
ArrayList<Vec3d> points = new ArrayList<Vec3d>();
for (int x = (int) Math.floor(origin.x); x < (int) Math.ceil(remote.x); x++) {
for (int y = (int) Math.floor(origin.y); y < (int) Math.ceil(remote.y); y++) {
for (int z = (int) Math.floor(origin.z); z < (int) Math.ceil(remote.z); z++) {
for (Vec3d point : pointsInCell(new Vec3i(x, y, z))) {
points.add(point);
}
points.addAll(pointsInCell(new Vec3i(x, y, z)).stream().filter((p) -> Utilities.inBoundingBox(p, uOrigin, uRemote)).collect(Collectors.toList()));
}
}
}

21
src/main/java/t/j/dual/RandomPointWorld.java

@ -8,6 +8,7 @@ import t.j.dual.PointWorld;
class RandomPointWorld implements PointWorld {
long seed;
final static float lambda = 1.0f;
Random random;
public RandomPointWorld(Random random, long seed) {
@ -15,14 +16,26 @@ class RandomPointWorld implements PointWorld {
this.random = random;
}
public Vec3d[] pointsInCell(Vec3i cell) {
public float getMeanPointsPerCell() {
return lambda;
}
public Vec3d getCellOrigin(Vec3i cell) {
return new Vec3d(cell);
}
public Vec3d getCellSize() {
return new Vec3d(1.0, 1.0, 1.0);
}
public ArrayList<Vec3d> pointsInCell(Vec3i cell) {
random.setSeed(seed ^ cell.getX());
random.setSeed(random.nextLong() ^ cell.getY());
random.setSeed(random.nextLong() ^ cell.getZ());
int nPoints = Utilities.drawPoisson(random, 1.0f);
Vec3d[] points = new Vec3d[nPoints];
int nPoints = Utilities.drawPoisson(random, lambda);
ArrayList<Vec3d> points = new ArrayList<Vec3d>(nPoints);
for (int i = 0; i < nPoints; i++) {
points[i] = new Vec3d(cell.getX() + random.nextDouble(), cell.getY() + random.nextDouble(), cell.getZ() + random.nextDouble());
points.add(new Vec3d(cell.getX() + random.nextDouble(), cell.getY() + random.nextDouble(), cell.getZ() + random.nextDouble()));
}
return points;
}

39
src/main/java/t/j/dual/RecelledPointWorld.java

@ -0,0 +1,39 @@
package t.j.dual;
import net.minecraft.util.math.*;
import java.util.Random;
import java.util.ArrayList;
import t.j.dual.PointWorld;
class RecelledPointWorld implements PointWorld {
PointWorld pworld;
Vec3d cellsize;
float mean;
public RecelledPointWorld(PointWorld pworld, Vec3d cellsize) {
this.pworld = pworld;
this.cellsize = cellsize;
this.mean = pworld.getMeanPointsPerCell() * (float) (cellsize.x * cellsize.y * cellsize.z);
}
public float getMeanPointsPerCell() {
return mean;
}
public Vec3d getCellOrigin(Vec3i cell) {
return new Vec3d(cell.getX() * cellsize.x, cell.getY() * cellsize.y, cell.getZ() * cellsize.z);
}
public Vec3d getCellSize() {
return cellsize;
}
private Vec3d getCellRemote(Vec3i cell) {
return new Vec3d((cell.getX() + 1) * cellsize.x, (cell.getY() + 1) * cellsize.y, (cell.getZ() + 1) * cellsize.z);
}
public ArrayList<Vec3d> pointsInCell(Vec3i cell) {
return pworld.pointsInAABB(getCellOrigin(cell), getCellRemote(cell));
}
}

45
src/main/java/t/j/dual/ScaledPointWorld.java

@ -0,0 +1,45 @@
package t.j.dual;
import net.minecraft.util.math.*;
import java.util.Random;
import java.util.ArrayList;
import t.j.dual.PointWorld;
import t.j.dual.Utilities;
class ScaledPointWorld implements PointWorld {
PointWorld pworld;
Vec3d scale;
Vec3d iscale;
Vec3d cellsize;
float mean;
public ScaledPointWorld(PointWorld pworld, Vec3d scale) {
this.pworld = pworld;
this.scale = scale;
this.iscale = new Vec3d(1.0 / scale.x, 1.0 / scale.y, 1.0 / scale.z);
this.cellsize = Utilities.ewMult(pworld.getCellSize(), scale);
this.mean = pworld.getMeanPointsPerCell();
}
public float getMeanPointsPerCell() {
return mean;
}
public Vec3d getCellOrigin(Vec3i cell) {
return Utilities.ewMult(pworld.getCellOrigin(cell), scale);
}
public Vec3d getCellSize() {
return cellsize;
}
public ArrayList<Vec3d> pointsInCell(Vec3i cell) {
ArrayList<Vec3d> unscaled = pworld.pointsInCell(cell);
ArrayList<Vec3d> scaled = new ArrayList<Vec3d>(unscaled.size());
for (Vec3d point : unscaled) {
scaled.add(Utilities.ewMult(point, scale));
}
return scaled;
}
}

12
src/main/java/t/j/dual/Utilities.java

@ -25,6 +25,18 @@ class Utilities {
origin.z < point.z && point.z < remote.z;
}
public static Vec3d ewMult(Vec3d a, Vec3d b) {
return new Vec3d(a.x * b.x, a.y * b.y, a.z * b.z);
}
public static Vec3d ewDiv(Vec3d a, Vec3d b) {
return new Vec3d(a.x / b.x, a.y / b.y, a.z / b.z);
}
public static Vec3d ewInv(Vec3d b) {
return new Vec3d(1.0 / b.x, 1.0 / b.y, 1.0 / b.z);
}
public static class LFSRRandom extends Random {
private long seed;

45
src/main/java/t/j/dual/WorldProviderPeace.java

@ -46,39 +46,43 @@ class BedrockChunkGenerator implements IChunkGenerator {
World world;
Random random;
PointWorld pointworld;
static final Vec3d pointScale = new Vec3d(3, 3, 3);
static final Vec3d pointMapFactor = Utilities.ewInv(pointScale).scale(16);
public BedrockChunkGenerator(World w) {
world = w;
this.random = new Utilities.LFSRRandom(0);
this.pointworld = new RandomPointWorld(random, world.getSeed());
this.pointworld = new ScaledPointWorld(new RecelledPointWorld(new CachedPointWorld(new RandomPointWorld(random, world.getSeed())), pointMapFactor), pointScale);
}
public Chunk generateChunk(int X, int Z) {
WorldProviderPeace.logger.info("bedrock: " + X + " " + Z);
ChunkPrimer primer = new ChunkPrimer();
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
primer.setBlockState(x, 0, z, Blocks.BEDROCK.getDefaultState());
}
}
if (((X ^ Z) & 3) >= 0) {
double scale = 8;
double perchunk = 16 / scale;
WorldProviderPeace.logger.info("points:" + X + " " + Z);
List<Vec3d> points = pointworld.pointsInAABB(new Vec3d(perchunk * X, 0, perchunk * Z), new Vec3d(perchunk * X + perchunk, perchunk * 16, perchunk * Z + perchunk));
List<Vec3d> points = pointworld.pointsInAABB(new Vec3d(X * 16, 0, Z * 16), new Vec3d(X * 16 + 16, 256, Z * 16 + 16));
WorldProviderPeace.logger.info("blocks: " + X + " " + Z);
int i = 0;
int totalz = 0;
for (Vec3d point: points) {
i++;
int x = (int) (scale * (point.x - perchunk * X));
int y = (int) (scale * point.y);
int z = (int) (scale * (point.z - perchunk * Z));
totalz += z;
primer.setBlockState(x, y, z, Blocks.STONE.getDefaultState());
IBlockState block;
if (point.y > 250) {
block = Blocks.GRASS.getDefaultState();
} else if (point.y > 240) {
block = Blocks.DIRT.getDefaultState();
} else {
block = Blocks.STONE.getDefaultState();
}
int x = (int) Math.floor(point.x) - X * 16;
int y = (int) Math.floor(point.y);
int z = (int) Math.floor(point.z) - Z * 16;
primer.setBlockState(x, y, z, block);
}
WorldProviderPeace.logger.info("(generated " + i + " blocks): " + X + " " + Z);
WorldProviderPeace.logger.info("mean z: " + totalz / (double) i);
}
WorldProviderPeace.logger.info("bedrock: " + X + " " + Z);
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
primer.setBlockState(x, 0, z, Blocks.BEDROCK.getDefaultState());
}
}
WorldProviderPeace.logger.info("chunk: " + X + " " + Z);
primer.setBlockState(0, 255, 0, Blocks.GOLD_BLOCK.getDefaultState());
@ -92,6 +96,7 @@ class BedrockChunkGenerator implements IChunkGenerator {
}
public boolean generateStructures(Chunk chunkIn, int x, int z) {
WorldProviderPeace.logger.info("generateStructures() called: " + x + " " + z);
return true;
}
@ -108,9 +113,11 @@ class BedrockChunkGenerator implements IChunkGenerator {
}
public void populate(int x, int z) {
WorldProviderPeace.logger.info("populate() called: " + x + " " + z);
}
public void recreateStructures(Chunk chunkIn, int x, int y) {
public void recreateStructures(Chunk chunkIn, int x, int z) {
WorldProviderPeace.logger.info("recreateStructures() called: " + x + " " + z);
}
private float[] verticalWeightMap(int x, int z) {

Loading…
Cancel
Save