diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/TerraBiomeHolder.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/TerraBiomeHolder.java index 18ba7a78f..095d94ddf 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/TerraBiomeHolder.java +++ b/common/src/main/java/com/dfsek/terra/biome/pipeline/TerraBiomeHolder.java @@ -30,7 +30,7 @@ public class TerraBiomeHolder implements BiomeHolder { if(z != oldWidth - 1) biomes[x * 2][z * 2 + 1] = expander.getBetween(new Position(x, z + 1), old[x][z], old[x][z + 1]); if(x != oldWidth - 1) biomes[x * 2 + 1][z * 2] = expander.getBetween(new Position(x + 1, z), old[x][z], old[x + 1][z]); if(x != oldWidth - 1 && z != oldWidth - 1) - biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(new Position(x + 1, z + 1), old[x][z], old[x + 1][z + 1]); + biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(new Position(x + 1, z + 1), old[x][z], old[x + 1][z + 1], old[x][z + 1], old[x + 1][z]); } } @@ -38,7 +38,16 @@ public class TerraBiomeHolder implements BiomeHolder { @Override public void mutate(BiomeMutator mutator) { - + for(int x = 0; x < width; x++) { + for(int z = 0; z < width; z++) { + BiomeMutator.ViewPoint viewPoint = new BiomeMutator.ViewPoint(new Biome[][] { + {getBiome(x - 1, z + 1), getBiome(x, z + 1), getBiome(x + 1, z + 1)}, + {getBiome(x - 1, z), getBiome(x, z), getBiome(x + 1, z)}, + {getBiome(x - 1, z - 1), getBiome(x, z - 1), getBiome(x + 1, z - 1)} + }); + biomes[x][z] = mutator.mutate(viewPoint, new Position(x, z)); + } + } } @Override @@ -52,6 +61,7 @@ public class TerraBiomeHolder implements BiomeHolder { @Override public Biome getBiome(int x, int z) { + if(x >= width || z >= width || x < 0 || z < 0) return null; return biomes[x][z]; } } diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BiomeMutator.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BiomeMutator.java index d054a3f05..50fe7a97d 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BiomeMutator.java +++ b/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/BiomeMutator.java @@ -1,4 +1,20 @@ package com.dfsek.terra.biome.pipeline.mutator; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.biome.pipeline.Position; + public interface BiomeMutator { + Biome mutate(ViewPoint viewPoint, Position position); + + class ViewPoint { + private final Biome[][] biomes; + + public ViewPoint(Biome[][] biomes) { + this.biomes = biomes; + } + + public Biome getBiome(int x, int z) { + return biomes[x + 1][z + 1]; + } + } } diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceMutator.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceMutator.java new file mode 100644 index 000000000..7d7f47dfa --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/ReplaceMutator.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.biome.pipeline.mutator; + +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.biome.pipeline.Position; + +import java.util.Set; + +public class ReplaceMutator implements BiomeMutator { + private final Set replaceable; + private final ProbabilityCollection replace; + private final NoiseSampler sampler; + + public ReplaceMutator(Set replaceable, ProbabilityCollection replace, NoiseSampler sampler) { + this.replaceable = replaceable; + this.replace = replace; + this.sampler = sampler; + } + + @Override + public Biome mutate(ViewPoint viewPoint, Position position) { + return replaceable.contains(viewPoint.getBiome(0, 0)) ? replace.get(sampler, position.getX(), position.getY()) : viewPoint.getBiome(0, 0); + } +} diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/SmoothMutator.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/SmoothMutator.java new file mode 100644 index 000000000..4c203d6d9 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/biome/pipeline/mutator/SmoothMutator.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.biome.pipeline.mutator; + +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.biome.pipeline.Position; + +import java.util.Objects; + +public class SmoothMutator implements BiomeMutator { + + private final NoiseSampler sampler; + + public SmoothMutator(NoiseSampler sampler) { + this.sampler = sampler; + } + + @Override + public Biome mutate(ViewPoint viewPoint, Position position) { + Biome top = viewPoint.getBiome(1, 0); + Biome bottom = viewPoint.getBiome(-1, 0); + Biome left = viewPoint.getBiome(0, 1); + Biome right = viewPoint.getBiome(0, -1); + + + boolean vert = Objects.equals(top, bottom) && top != null; + boolean horiz = Objects.equals(left, right) && left != null; + + if(vert && horiz) { + return MathUtil.normalizeIndex(sampler.getNoise(position.getX(), position.getY()), 2) == 0 ? left : top; + } + + if(vert) return top; + if(horiz) return left; + + return viewPoint.getBiome(0, 0); + } +} diff --git a/common/src/test/java/biome/BiomeTest.java b/common/src/test/java/biome/BiomeTest.java index a12fd60e6..d2d7aa3ac 100644 --- a/common/src/test/java/biome/BiomeTest.java +++ b/common/src/test/java/biome/BiomeTest.java @@ -9,6 +9,7 @@ import com.dfsek.terra.api.world.biome.Generator; import com.dfsek.terra.biome.pipeline.Position; import com.dfsek.terra.biome.pipeline.TerraBiomeHolder; import com.dfsek.terra.biome.pipeline.expand.FractalExpander; +import com.dfsek.terra.biome.pipeline.mutator.SmoothMutator; import com.dfsek.terra.biome.pipeline.source.BiomeSource; import com.dfsek.terra.biome.pipeline.source.RandomSource; import org.junit.jupiter.api.Test; @@ -37,15 +38,28 @@ public class BiomeTest { TerraBiomeHolder holder = new TerraBiomeHolder(size, new Position(0, 0)); + long s = System.nanoTime(); holder.fill(source); holder.expand(new FractalExpander(whiteNoise(4))); holder.expand(new FractalExpander(whiteNoise(3))); holder.expand(new FractalExpander(whiteNoise(2))); + + holder.mutate(new SmoothMutator(whiteNoise(34))); + holder.expand(new FractalExpander(whiteNoise(5))); holder.expand(new FractalExpander(whiteNoise(7))); holder.expand(new FractalExpander(whiteNoise(6))); + holder.mutate(new SmoothMutator(whiteNoise(35))); + + long e = System.nanoTime(); + + double time = e - s; + time /= 1000000; + for(int i = 0; i < expand; i++) size = size * 2 - 1; + System.out.println(time + "ms for " + size + "x" + size); + BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);