added /find command & reworked some of the back-end stuff in Core
This commit is contained in:
parent
e853f3d347
commit
446b036414
@ -58,13 +58,13 @@ public abstract class Renderer {
|
||||
if (cell.tag == applet.getCache().getTerrain().coast) {
|
||||
hue = 15;
|
||||
}
|
||||
float modifier = cell.mask;
|
||||
float modifier = cell.mask(0.4F, 0.5F, 0F, 1F);
|
||||
float modAlpha = 0.1F;
|
||||
float mod = (1 - modAlpha) + (modifier * modAlpha);
|
||||
float sat = 70;
|
||||
float bri = 70;
|
||||
applet.fill(hue, 65, 70);
|
||||
return height * el;
|
||||
return cell.regionEdge * el;
|
||||
} else if(applet.controller.getColorMode() == Applet.EROSION) {
|
||||
float change = cell.sediment + cell.erosion;
|
||||
float value = Math.abs(cell.sediment * 250);
|
||||
|
@ -18,9 +18,13 @@ public class Cell<T extends Tag> {
|
||||
|
||||
public float continent;
|
||||
public float continentEdge;
|
||||
public float region;
|
||||
public float regionEdge;
|
||||
public float biome;
|
||||
public float biomeEdge = 1F;
|
||||
public float riverMask = 1F;
|
||||
|
||||
public float value;
|
||||
public float biome;
|
||||
public float biomeMoisture;
|
||||
public float biomeTemperature;
|
||||
public float moisture;
|
||||
@ -28,49 +32,53 @@ public class Cell<T extends Tag> {
|
||||
public float steepness;
|
||||
public float erosion;
|
||||
public float sediment;
|
||||
|
||||
public float mask = 1F;
|
||||
public float biomeMask = 1F;
|
||||
public float biomeTypeMask = 1F;
|
||||
public float regionMask = 1F;
|
||||
public float riverMask = 1F;
|
||||
public BiomeType biomeType = BiomeType.GRASSLAND;
|
||||
|
||||
public T tag = null;
|
||||
|
||||
public void copy(Cell<T> other) {
|
||||
value = other.value;
|
||||
|
||||
continent = other.continent;
|
||||
continentEdge = other.continentEdge;
|
||||
|
||||
value = other.value;
|
||||
biome = other.biome;
|
||||
region = other.region;
|
||||
regionEdge = other.regionEdge;
|
||||
|
||||
biome = other.biome;
|
||||
biomeEdge = other.biomeEdge;
|
||||
|
||||
biomeMask = other.biomeMask;
|
||||
riverMask = other.riverMask;
|
||||
biomeMoisture = other.biomeMoisture;
|
||||
biomeTemperature = other.biomeTemperature;
|
||||
mask = other.mask;
|
||||
regionMask = other.regionMask;
|
||||
|
||||
moisture = other.moisture;
|
||||
temperature = other.temperature;
|
||||
biomeMoisture = other.biomeMoisture;
|
||||
biomeTemperature = other.biomeTemperature;
|
||||
|
||||
steepness = other.steepness;
|
||||
erosion = other.erosion;
|
||||
sediment = other.sediment;
|
||||
biomeType = other.biomeType;
|
||||
biomeTypeMask = other.biomeTypeMask;
|
||||
|
||||
tag = other.tag;
|
||||
}
|
||||
|
||||
public float combinedMask(float clamp) {
|
||||
return NoiseUtil.map(biomeMask * regionMask, 0, clamp, clamp);
|
||||
public float continentMask(float min, float max) {
|
||||
return NoiseUtil.map(continentEdge, min, max, max - min);
|
||||
}
|
||||
|
||||
public float biomeMask(float clamp) {
|
||||
return NoiseUtil.map(biomeMask, 0, clamp, clamp);
|
||||
public float regionMask(float min, float max) {
|
||||
return NoiseUtil.map(regionEdge, min, max, max - min);
|
||||
}
|
||||
|
||||
public float regionMask(float clamp) {
|
||||
return NoiseUtil.map(regionMask, 0, clamp, clamp);
|
||||
public float biomeMask(float min, float max) {
|
||||
return NoiseUtil.map(biomeEdge, min, max, max - min);
|
||||
}
|
||||
|
||||
public float mask(float cmin, float cmax, float rmin, float rmax) {
|
||||
return riverMask * continentMask(cmin, cmax) * regionMask(rmin, rmax);
|
||||
}
|
||||
|
||||
public boolean isAbsent() {
|
||||
|
@ -5,5 +5,5 @@ import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
public interface Decorator {
|
||||
|
||||
void apply(Cell<Terrain> cell, float x, float y);
|
||||
boolean apply(Cell<Terrain> cell, float x, float y);
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
package com.terraforged.core.decorator;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.world.GeneratorContext;
|
||||
import com.terraforged.core.world.heightmap.Levels;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import com.terraforged.core.world.terrain.Terrains;
|
||||
import me.dags.noise.Module;
|
||||
import me.dags.noise.Source;
|
||||
import me.dags.noise.func.CellFunc;
|
||||
|
||||
public class DesertDunes implements Decorator {
|
||||
|
||||
private final Module module;
|
||||
private final float climateMin;
|
||||
private final float climateMax;
|
||||
private final float climateRange;
|
||||
|
||||
private final Levels levels;
|
||||
private final Terrains terrains;
|
||||
private final Terrain dunes = new Terrain("dunes", 100);
|
||||
|
||||
public DesertDunes(GeneratorContext context) {
|
||||
this.climateMin = 0.6F;
|
||||
this.climateMax = 0.85F;
|
||||
this.climateRange = climateMax - climateMin;
|
||||
this.levels = context.levels;
|
||||
this.terrains = context.terrain;
|
||||
this.module = Source.cell(context.seed.next(), 80, CellFunc.DISTANCE)
|
||||
.warp(context.seed.next(), 70, 1, 70)
|
||||
.scale(30 / 255D);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Cell<Terrain> cell, float x, float y) {
|
||||
float temp = cell.temperature;
|
||||
float moisture = 1 - cell.moisture;
|
||||
float climate = temp * moisture;
|
||||
if (climate < climateMin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float duneHeight = module.getValue(x, y);
|
||||
float climateMask = climate > climateMax ? 1F : (climate - climateMin) / climateRange;
|
||||
float regionMask = cell.mask(0.4F, 0.5F, 0,0.8F);
|
||||
|
||||
float height = duneHeight * climateMask * regionMask;
|
||||
cell.value += height;
|
||||
cell.tag = dunes;
|
||||
|
||||
return height >= levels.unit;
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ public class DesertStacks implements Decorator {
|
||||
|
||||
private final float minY;
|
||||
private final float maxY;
|
||||
private final Levels levels;
|
||||
private final Module module;
|
||||
|
||||
public DesertStacks(Seed seed, Levels levels) {
|
||||
@ -35,21 +36,24 @@ public class DesertStacks implements Decorator {
|
||||
|
||||
this.minY = levels.water(0);
|
||||
this.maxY = levels.water(50);
|
||||
this.levels = levels;
|
||||
this.module = stack.scale(scale).mult(mask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
public boolean apply(Cell<Terrain> cell, float x, float y) {
|
||||
if (BiomeType.DESERT != cell.biomeType) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cell.value <= minY || cell.value > maxY) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
float value = module.getValue(x, y);
|
||||
value *= cell.biomeMask;
|
||||
value *= cell.biomeEdge;
|
||||
cell.value += value;
|
||||
|
||||
return value > levels.unit;
|
||||
}
|
||||
}
|
||||
|
@ -30,21 +30,21 @@ public class SwampPools implements Decorator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
public boolean apply(Cell<Terrain> cell, float x, float y) {
|
||||
if (cell.tag == terrains.ocean) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cell.moisture < 0.7 || cell.temperature < 0.3) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cell.value <= minY) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cell.value > blendY) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
float alpha = module.getValue(x, y);
|
||||
@ -55,5 +55,6 @@ public class SwampPools implements Decorator {
|
||||
}
|
||||
|
||||
cell.value = NoiseUtil.lerp(cell.value, minY, alpha);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ public class Blender extends Select implements Populator {
|
||||
private final float midpoint;
|
||||
private final float tagThreshold;
|
||||
|
||||
private boolean mask = false;
|
||||
|
||||
public Blender(Module control, Populator lower, Populator upper, float min, float max, float split) {
|
||||
super(control);
|
||||
this.lower = lower;
|
||||
@ -42,11 +40,6 @@ public class Blender extends Select implements Populator {
|
||||
this.tagThreshold = tagThreshold;
|
||||
}
|
||||
|
||||
public Blender mask() {
|
||||
mask = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float select = getSelect(cell, x, y);
|
||||
@ -74,10 +67,6 @@ public class Blender extends Select implements Populator {
|
||||
if (select < midpoint) {
|
||||
cell.tag = lowerType;
|
||||
}
|
||||
|
||||
if (mask) {
|
||||
cell.mask *= alpha;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,29 +0,0 @@
|
||||
package com.terraforged.core.module;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.world.heightmap.Heightmap;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
public class CellLookup implements Populator {
|
||||
|
||||
private final int scale;
|
||||
private final Heightmap heightmap;
|
||||
|
||||
public CellLookup(Heightmap heightmap, int scale) {
|
||||
this.heightmap = heightmap;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float px = x * scale;
|
||||
float pz = y * scale;
|
||||
heightmap.getValue(px, pz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tag(Cell<Terrain> cell, float x, float y) {
|
||||
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package com.terraforged.core.module;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.world.heightmap.Heightmap;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import me.dags.noise.Module;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
|
||||
public class CellLookupOffset implements Populator {
|
||||
|
||||
private final int scale;
|
||||
private final Module direction;
|
||||
private final Module strength;
|
||||
private final Heightmap heightmap;
|
||||
|
||||
public CellLookupOffset(Heightmap heightmap, Module direction, Module strength, int scale) {
|
||||
this.scale = scale;
|
||||
this.heightmap = heightmap;
|
||||
this.direction = direction;
|
||||
this.strength = strength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float px = x * scale;
|
||||
float pz = y * scale;
|
||||
float str = strength.getValue(x, y);
|
||||
float dir = direction.getValue(x, y) * NoiseUtil.PI2;
|
||||
float dx = NoiseUtil.sin(dir) * str;
|
||||
float dz = NoiseUtil.cos(dir) * str;
|
||||
heightmap.visit(cell, px + dx, pz + dz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tag(Cell<Terrain> cell, float x, float y) {
|
||||
|
||||
}
|
||||
}
|
@ -21,8 +21,6 @@ public class MultiBlender extends Select implements Populator {
|
||||
private final float lowerRange;
|
||||
private final float upperRange;
|
||||
|
||||
private boolean mask = false;
|
||||
|
||||
public MultiBlender(Climate climate, Populator control, Populator lower, Populator middle, Populator upper, float min, float mid, float max) {
|
||||
super(control);
|
||||
this.climate = climate;
|
||||
@ -62,11 +60,6 @@ public class MultiBlender extends Select implements Populator {
|
||||
float upperVal = cell.value;
|
||||
|
||||
cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha);
|
||||
// cell.tag = lowerType;
|
||||
|
||||
if (mask) {
|
||||
cell.mask *= alpha;
|
||||
}
|
||||
} else {
|
||||
float alpha = Interpolation.CURVE3.apply((select - midpoint) / upperRange);
|
||||
|
||||
@ -75,10 +68,6 @@ public class MultiBlender extends Select implements Populator {
|
||||
|
||||
upper.apply(cell, x, y);
|
||||
cell.value = NoiseUtil.lerp(lowerVal, cell.value, alpha);
|
||||
|
||||
if (mask) {
|
||||
cell.mask *= alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,9 @@ public class Region implements Extent {
|
||||
int index = blockSize.indexOf(dx, dz);
|
||||
GenCell cell = blocks[index];
|
||||
for (Decorator decorator : decorators) {
|
||||
decorator.apply(cell, getBlockX() + dx, getBlockZ() + dz);
|
||||
if (decorator.apply(cell, getBlockX() + dx, getBlockZ() + dz)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ public class RegionGenerator implements RegionExtent {
|
||||
if (filter) {
|
||||
generator.getFilters().apply(region);
|
||||
}
|
||||
// region.decorateZoom(generator.getDecorators().getDecorators(), centerX, centerZ, zoom);
|
||||
region.decorateZoom(generator.getDecorators().getDecorators(), centerX, centerZ, zoom);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
|
@ -80,11 +80,11 @@ public class GeneratorSettings {
|
||||
|
||||
@Range(min = 1, max = 200)
|
||||
@Comment("Controls the scale of shape distortion for biomes")
|
||||
public int biomeWarpScale = 30;
|
||||
public int biomeWarpScale = 35;
|
||||
|
||||
@Range(min = 1, max = 200)
|
||||
@Comment("Controls the strength of shape distortion for biomes")
|
||||
public int biomeWarpStrength = 30;
|
||||
public int biomeWarpStrength = 70;
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@ -95,11 +95,11 @@ public class GeneratorSettings {
|
||||
|
||||
@Range(min = 1, max = 100)
|
||||
@Comment("Controls the scale of the noise")
|
||||
public int scale = 4;
|
||||
public int scale = 8;
|
||||
|
||||
@Range(min = 1, max = 5)
|
||||
@Comment("Controls the number of noise octaves")
|
||||
public int octaves = 1;
|
||||
public int octaves = 2;
|
||||
|
||||
@Range(min = 0F, max = 5.5F)
|
||||
@Comment("Controls the gain subsequent noise octaves")
|
||||
@ -107,11 +107,11 @@ public class GeneratorSettings {
|
||||
|
||||
@Range(min = 0F, max = 10.5F)
|
||||
@Comment("Controls the lacunarity of subsequent noise octaves")
|
||||
public float lacunarity = 2F;
|
||||
public float lacunarity = 2.5F;
|
||||
|
||||
@Range(min = 1, max = 100)
|
||||
@Comment("Controls the strength of the noise")
|
||||
public int strength = 12;
|
||||
public int strength = 24;
|
||||
|
||||
public Module build(int seed) {
|
||||
return Source.build(seed, scale, octaves).gain(gain).lacunarity(lacunarity).build(type).bias(-0.5);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.terraforged.core.world;
|
||||
|
||||
import com.terraforged.core.decorator.Decorator;
|
||||
import com.terraforged.core.decorator.DesertDunes;
|
||||
import com.terraforged.core.decorator.DesertStacks;
|
||||
import com.terraforged.core.decorator.SwampPools;
|
||||
|
||||
|
@ -2,8 +2,6 @@ package com.terraforged.core.world.climate;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.world.GeneratorContext;
|
||||
import com.terraforged.core.world.biome.BiomeType;
|
||||
import com.terraforged.core.world.heightmap.WorldHeightmap;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import me.dags.noise.Module;
|
||||
import me.dags.noise.Source;
|
||||
@ -26,7 +24,7 @@ public class Climate {
|
||||
|
||||
private final ClimateModule biomeNoise;
|
||||
|
||||
public Climate(GeneratorContext context, WorldHeightmap heightmap) {
|
||||
public Climate(GeneratorContext context) {
|
||||
this.biomeNoise = new ClimateModule(context.seed, context.settings.generator);
|
||||
|
||||
this.treeLine = Source.perlin(context.seed.next(), context.settings.generator.biome.biomeSize * 2, 1)
|
||||
|
@ -104,10 +104,10 @@ public class ClimateModule {
|
||||
}
|
||||
|
||||
if (mask) {
|
||||
cell.biomeMask = edgeValue(edgeDistance, edgeDistance2);
|
||||
cell.biomeEdge = edgeValue(edgeDistance, edgeDistance2);
|
||||
} else {
|
||||
cell.biome = cellValue(seed, cellX, cellY);
|
||||
cell.biomeMask = edgeValue(edgeDistance, edgeDistance2);
|
||||
cell.biomeEdge = edgeValue(edgeDistance, edgeDistance2);
|
||||
cell.biomeMoisture = moisture.getValue(cellX + vec2f.x, cellY + vec2f.y);
|
||||
cell.biomeTemperature = temperature.getValue(cellX + vec2f.x, cellY + vec2f.y);
|
||||
cell.moisture = moisture.getValue(x, y);
|
||||
|
@ -1,21 +0,0 @@
|
||||
package com.terraforged.core.world.continent;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.module.Blender;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
public class ContinentBlender extends Blender {
|
||||
|
||||
private final Populator control;
|
||||
|
||||
public ContinentBlender(Populator continent, Populator lower, Populator upper, float min, float max, float split, float tagThreshold) {
|
||||
super(continent, lower, upper, min, max, split, tagThreshold);
|
||||
this.control = continent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSelect(Cell<Terrain> cell, float x, float z) {
|
||||
return cell.continentEdge;
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package com.terraforged.core.world.continent;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import me.dags.noise.func.Interpolation;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
|
||||
public class ContinentLerper2 implements Populator {
|
||||
|
||||
private final Populator lower;
|
||||
private final Populator upper;
|
||||
|
||||
private final float blendLower;
|
||||
private final float blendUpper;
|
||||
private final float blendRange;
|
||||
private final float midpoint;
|
||||
private final float tagThreshold;
|
||||
|
||||
public ContinentLerper2(Populator lower, Populator upper, float min, float max, float split, float tagThreshold) {
|
||||
this.lower = lower;
|
||||
this.upper = upper;
|
||||
this.blendLower = min;
|
||||
this.blendUpper = max;
|
||||
this.blendRange = blendUpper - blendLower;
|
||||
this.midpoint = blendLower + (blendRange * split);
|
||||
this.tagThreshold = tagThreshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float select = cell.continentEdge;
|
||||
|
||||
if (select < blendLower) {
|
||||
lower.apply(cell, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (select > blendUpper) {
|
||||
upper.apply(cell, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
float alpha = Interpolation.LINEAR.apply((select - blendLower) / blendRange);
|
||||
lower.apply(cell, x, y);
|
||||
|
||||
float lowerVal = cell.value;
|
||||
Terrain lowerType = cell.tag;
|
||||
|
||||
upper.apply(cell, x, y);
|
||||
float upperVal = cell.value;
|
||||
|
||||
cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha);
|
||||
if (select < midpoint) {
|
||||
cell.tag = lowerType;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tag(Cell<Terrain> cell, float x, float y) {
|
||||
float select = cell.continentEdge;
|
||||
if (select < blendLower) {
|
||||
lower.tag(cell, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (select > blendUpper) {
|
||||
upper.tag(cell, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (select < tagThreshold) {
|
||||
lower.tag(cell, x, y);
|
||||
} else {
|
||||
upper.tag(cell, x, y);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.terraforged.core.world.continent;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.module.MultiBlender;
|
||||
import com.terraforged.core.world.climate.Climate;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import me.dags.noise.func.Interpolation;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
|
||||
public class ContinentLerper3 implements Populator {
|
||||
|
||||
private final Climate climate;
|
||||
private final Populator lower;
|
||||
private final Populator middle;
|
||||
private final Populator upper;
|
||||
private final float midpoint;
|
||||
|
||||
private final float blendLower;
|
||||
private final float blendUpper;
|
||||
|
||||
private final float lowerRange;
|
||||
private final float upperRange;
|
||||
|
||||
public ContinentLerper3(Climate climate, Populator lower, Populator middle, Populator upper, float min, float mid, float max) {
|
||||
this.climate = climate;
|
||||
this.lower = lower;
|
||||
this.upper = upper;
|
||||
this.middle = middle;
|
||||
|
||||
this.midpoint = mid;
|
||||
this.blendLower = min;
|
||||
this.blendUpper = max;
|
||||
|
||||
this.lowerRange = midpoint - blendLower;
|
||||
this.upperRange = blendUpper - midpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float select = cell.continentEdge;
|
||||
if (select < blendLower) {
|
||||
lower.apply(cell, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (select > blendUpper) {
|
||||
upper.apply(cell, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (select < midpoint) {
|
||||
float alpha = Interpolation.CURVE3.apply((select - blendLower) / lowerRange);
|
||||
|
||||
lower.apply(cell, x, y);
|
||||
float lowerVal = cell.value;
|
||||
Terrain lowerType = cell.tag;
|
||||
|
||||
middle.apply(cell, x, y);
|
||||
float upperVal = cell.value;
|
||||
|
||||
cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha);
|
||||
} else {
|
||||
float alpha = Interpolation.CURVE3.apply((select - midpoint) / upperRange);
|
||||
|
||||
middle.apply(cell, x, y);
|
||||
float lowerVal = cell.value;
|
||||
|
||||
upper.apply(cell, x, y);
|
||||
cell.value = NoiseUtil.lerp(lowerVal, cell.value, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tag(Cell<Terrain> cell, float x, float y) {
|
||||
float select = cell.continentEdge;
|
||||
if (select < blendLower) {
|
||||
lower.tag(cell, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (select > blendUpper) {
|
||||
upper.tag(cell, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (select < midpoint) {
|
||||
lower.tag(cell, x, y);
|
||||
if (cell.value > cell.tag.getMax(climate.getRand().getValue(x, y))) {
|
||||
upper.tag(cell, x, y);
|
||||
}
|
||||
} else {
|
||||
upper.tag(cell, x, y);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,141 @@
|
||||
package com.terraforged.core.world.continent;
|
||||
|
||||
import me.dags.noise.Module;
|
||||
import me.dags.noise.Source;
|
||||
import me.dags.noise.domain.Domain;
|
||||
import me.dags.noise.func.DistanceFunc;
|
||||
import me.dags.noise.func.EdgeFunc;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
import me.dags.noise.util.Vec2f;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.settings.GeneratorSettings;
|
||||
import com.terraforged.core.util.Seed;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
public interface ContinentModule extends Populator {
|
||||
public class ContinentModule implements Populator {
|
||||
|
||||
private static final float edgeClampMin = 0.05F;
|
||||
private static final float edgeClampMax = 0.50F;
|
||||
private static final float edgeClampRange = edgeClampMax - edgeClampMin;
|
||||
|
||||
private final int seed;
|
||||
private final float frequency;
|
||||
|
||||
private final float edgeMin;
|
||||
private final float edgeMax;
|
||||
private final float edgeRange;
|
||||
|
||||
private final Domain warp;
|
||||
private final Module shape;
|
||||
|
||||
public ContinentModule(Seed seed, GeneratorSettings settings) {
|
||||
int tectonicScale = settings.land.continentScale * 4;
|
||||
int continentScale = settings.land.continentScale / 2;
|
||||
double oceans = Math.min(Math.max(settings.world.oceanSize, 0.01), 0.99);
|
||||
double shapeMin = 0.15 + (oceans * 0.35);
|
||||
this.seed = seed.next();
|
||||
|
||||
this.frequency = 1F / tectonicScale;
|
||||
this.edgeMin = edgeClampMin;
|
||||
this.edgeMax = (float) oceans;
|
||||
this.edgeRange = edgeMax - edgeMin;
|
||||
|
||||
this.warp = Domain.warp(Source.SIMPLEX, seed.next(), continentScale, 3, continentScale);
|
||||
|
||||
this.shape = Source.perlin(seed.next(), settings.land.continentScale, 2)
|
||||
.clamp(shapeMin, 0.7)
|
||||
.map(0, 1)
|
||||
.warp(Source.SIMPLEX, seed.next(), continentScale / 2, 1, continentScale / 4D)
|
||||
.warp(seed.next(), 50, 1, 20D);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue(float x, float y) {
|
||||
if (true) {
|
||||
throw new RuntimeException("no pls!");
|
||||
} else {
|
||||
Cell<Terrain> cell = new Cell<>();
|
||||
apply(cell, x, y);
|
||||
return cell.continentEdge;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, final float x, final float y) {
|
||||
float ox = warp.getOffsetX(x, y);
|
||||
float oz = warp.getOffsetY(x, y);
|
||||
|
||||
float px = x + ox;
|
||||
float py = y + oz;
|
||||
|
||||
px *= frequency;
|
||||
py *= frequency;
|
||||
|
||||
int cellX = 0;
|
||||
int cellY = 0;
|
||||
|
||||
int xr = NoiseUtil.round(px);
|
||||
int yr = NoiseUtil.round(py);
|
||||
float edgeDistance = 999999.0F;
|
||||
float edgeDistance2 = 999999.0F;
|
||||
float valueDistance = 3.4028235E38F;
|
||||
DistanceFunc dist = DistanceFunc.NATURAL;
|
||||
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
int xi = xr + dx;
|
||||
int yi = yr + dy;
|
||||
Vec2f vec = NoiseUtil.CELL_2D[NoiseUtil.hash2D(seed, xi, yi) & 255];
|
||||
|
||||
float vecX = xi - px + vec.x;
|
||||
float vecY = yi - py + vec.y;
|
||||
float distance = dist.apply(vecX, vecY);
|
||||
|
||||
if (distance < valueDistance) {
|
||||
valueDistance = distance;
|
||||
cellX = xi;
|
||||
cellY = yi;
|
||||
}
|
||||
|
||||
if (distance < edgeDistance2) {
|
||||
edgeDistance2 = Math.max(edgeDistance, distance);
|
||||
} else {
|
||||
edgeDistance2 = Math.max(edgeDistance, edgeDistance2);
|
||||
}
|
||||
|
||||
edgeDistance = Math.min(edgeDistance, distance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float shapeNoise = shape.getValue(x, y);
|
||||
float continentNoise = edgeValue(edgeDistance, edgeDistance2);
|
||||
|
||||
cell.continent = cellValue(seed, cellX, cellY);
|
||||
cell.continentEdge = shapeNoise * continentNoise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tag(Cell<Terrain> cell, float x, float y) {
|
||||
|
||||
}
|
||||
|
||||
private float cellValue(int seed, int cellX, int cellY) {
|
||||
float value = NoiseUtil.valCoord2D(seed, cellX, cellY);
|
||||
return NoiseUtil.map(value, -1, 1, 2);
|
||||
}
|
||||
|
||||
private float edgeValue(float distance, float distance2) {
|
||||
EdgeFunc edge = EdgeFunc.DISTANCE_2_DIV;
|
||||
float value = edge.apply(distance, distance2);
|
||||
float edgeValue = 1 - NoiseUtil.map(value, edge.min(), edge.max(), edge.range());
|
||||
if (edgeValue < edgeMin) {
|
||||
return 0F;
|
||||
}
|
||||
if (edgeValue > edgeMax) {
|
||||
return 1F;
|
||||
}
|
||||
return (edgeValue - edgeMin) / edgeRange;
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
package com.terraforged.core.world.continent;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.module.MultiBlender;
|
||||
import com.terraforged.core.world.climate.Climate;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
public class ContinentMultiBlender extends MultiBlender {
|
||||
|
||||
private final Populator control;
|
||||
|
||||
public ContinentMultiBlender(Climate climate, Populator continent, Populator lower, Populator middle, Populator upper, float min, float mid, float max) {
|
||||
super(climate, continent, lower, middle, upper, min, mid, max);
|
||||
this.control = continent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSelect(Cell<Terrain> cell, float x, float z) {
|
||||
return cell.continentEdge;
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ public class Levels {
|
||||
|
||||
public final int worldHeight;
|
||||
|
||||
public final float unit;
|
||||
|
||||
// y index of the top-most water block
|
||||
public final int waterY;
|
||||
private final int groundY;
|
||||
@ -23,6 +25,7 @@ public class Levels {
|
||||
|
||||
public Levels(GeneratorSettings settings) {
|
||||
worldHeight = Math.max(1, settings.world.worldHeight);
|
||||
unit = NoiseUtil.div(1, worldHeight);
|
||||
|
||||
waterLevel = settings.world.seaLevel;
|
||||
groundLevel = waterLevel + 1;
|
||||
|
@ -3,17 +3,17 @@ package com.terraforged.core.world.heightmap;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.module.Blender;
|
||||
import com.terraforged.core.module.Lerp;
|
||||
import com.terraforged.core.module.MultiBlender;
|
||||
import com.terraforged.core.module.Selector;
|
||||
import com.terraforged.core.settings.GeneratorSettings;
|
||||
import com.terraforged.core.settings.Settings;
|
||||
import com.terraforged.core.util.Seed;
|
||||
import com.terraforged.core.world.GeneratorContext;
|
||||
import com.terraforged.core.world.climate.Climate;
|
||||
import com.terraforged.core.world.continent.ContinentBlender;
|
||||
import com.terraforged.core.world.continent.ContinentMultiBlender;
|
||||
import com.terraforged.core.world.continent.VoronoiContinentModule;
|
||||
import com.terraforged.core.world.continent.ContinentLerper2;
|
||||
import com.terraforged.core.world.continent.ContinentLerper3;
|
||||
import com.terraforged.core.world.continent.ContinentModule;
|
||||
import com.terraforged.core.world.terrain.region.RegionLerper;
|
||||
import com.terraforged.core.world.terrain.region.RegionModule;
|
||||
import com.terraforged.core.world.terrain.region.RegionSelector;
|
||||
import com.terraforged.core.world.river.RiverManager;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import com.terraforged.core.world.terrain.TerrainPopulator;
|
||||
@ -36,9 +36,11 @@ public class WorldHeightmap implements Heightmap {
|
||||
private final Terrains terrain;
|
||||
private final Settings settings;
|
||||
|
||||
private final Populator continentModule;
|
||||
private final Populator regionModule;
|
||||
|
||||
private final Climate climate;
|
||||
private final Populator root;
|
||||
private final Populator continent;
|
||||
private final RiverManager riverManager;
|
||||
private final TerrainProvider terrainProvider;
|
||||
|
||||
@ -48,7 +50,7 @@ public class WorldHeightmap implements Heightmap {
|
||||
this.levels = context.levels;
|
||||
this.terrain = context.terrain;
|
||||
this.settings = context.settings;
|
||||
this.climate = new Climate(context, this);
|
||||
this.climate = new Climate(context);
|
||||
|
||||
Seed seed = context.seed;
|
||||
Levels levels = context.levels;
|
||||
@ -62,11 +64,13 @@ public class WorldHeightmap implements Heightmap {
|
||||
RegionConfig regionConfig = new RegionConfig(
|
||||
regionSeed.get(),
|
||||
context.settings.generator.land.regionSize,
|
||||
Source.simplex(regionWarp.next(), regionWarpScale, 2),
|
||||
Source.simplex(regionWarp.next(), regionWarpScale, 2),
|
||||
Source.simplex(regionWarp.next(), regionWarpScale, 1),
|
||||
Source.simplex(regionWarp.next(), regionWarpScale, 1),
|
||||
regionWarpStrength
|
||||
);
|
||||
|
||||
regionModule = new RegionModule(regionConfig);
|
||||
|
||||
// controls where mountain chains form in the world
|
||||
Module mountainShapeBase = Source.cellEdge(seed.next(), genSettings.land.mountainScale, EdgeFunc.DISTANCE_2_ADD)
|
||||
.add(Source.cubic(seed.next(), genSettings.land.mountainScale, 1).scale(-0.05));
|
||||
@ -77,36 +81,21 @@ public class WorldHeightmap implements Heightmap {
|
||||
.clamp(0, 0.9)
|
||||
.map(0, 1);
|
||||
|
||||
// controls the shape of terrain regions
|
||||
Module regionShape = Source.cell(regionConfig.seed, regionConfig.scale)
|
||||
.warp(regionConfig.warpX, regionConfig.warpZ, regionConfig.warpStrength);
|
||||
|
||||
// the corresponding edges of terrain regions so we can fade out towards borders
|
||||
Module regionEdge = Source.cellEdge(regionConfig.seed, regionConfig.scale, EdgeFunc.DISTANCE_2_DIV).invert()
|
||||
.warp(regionConfig.warpX, regionConfig.warpZ, regionConfig.warpStrength)
|
||||
.pow(1.5)
|
||||
.clamp(0, 0.75)
|
||||
.map(0, 1);
|
||||
|
||||
this.terrainProvider = context.terrainFactory.create(context, regionConfig, this);
|
||||
terrainProvider = context.terrainFactory.create(context, regionConfig, this);
|
||||
|
||||
// the voronoi controlled terrain regions
|
||||
Populator terrainRegions = new Selector(regionShape, terrainProvider.getPopulators());
|
||||
Populator terrainRegions = new RegionSelector(terrainProvider.getPopulators());
|
||||
// the terrain type at region edges
|
||||
Populator terrainRegionBorders = new TerrainPopulator(terrainProvider.getLandforms().plains(seed), context.terrain.steppe);
|
||||
|
||||
// transitions between the unique terrain regions and the common border terrain
|
||||
Populator terrain = new Lerp(
|
||||
regionEdge,
|
||||
terrainRegionBorders,
|
||||
terrainRegions
|
||||
);
|
||||
Populator terrain = new RegionLerper(terrainRegionBorders, terrainRegions);
|
||||
|
||||
// mountain populator
|
||||
Populator mountains = register(terrainProvider.getLandforms().mountains(seed), context.terrain.mountains);
|
||||
|
||||
// controls what's ocean and what's land
|
||||
this.continent = createContinent(context);
|
||||
continentModule = new ContinentModule(seed, settings.generator);
|
||||
|
||||
// blends between normal terrain and mountain chains
|
||||
Populator land = new Blender(
|
||||
@ -119,9 +108,8 @@ public class WorldHeightmap implements Heightmap {
|
||||
);
|
||||
|
||||
// uses the continent noise to blend between deep ocean, to ocean, to coast
|
||||
MultiBlender oceans = new ContinentMultiBlender(
|
||||
ContinentLerper3 oceans = new ContinentLerper3(
|
||||
climate,
|
||||
continent,
|
||||
register(terrainProvider.getLandforms().deepOcean(seed.next()), context.terrain.deepOcean),
|
||||
register(Source.constant(levels.water(-7)), context.terrain.ocean),
|
||||
register(Source.constant(levels.water), context.terrain.coast),
|
||||
@ -131,22 +119,23 @@ public class WorldHeightmap implements Heightmap {
|
||||
);
|
||||
|
||||
// blends between the ocean/coast terrain and land terrains
|
||||
root = new ContinentBlender(
|
||||
continent,
|
||||
root = new ContinentLerper2(
|
||||
oceans,
|
||||
land,
|
||||
OCEAN_VALUE, // below == pure ocean
|
||||
INLAND_VALUE, // above == pure land
|
||||
COAST_VALUE, // split point
|
||||
COAST_VALUE - 0.05F
|
||||
).mask();
|
||||
);
|
||||
|
||||
this.riverManager = new RiverManager(this, context);
|
||||
riverManager = new RiverManager(this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Cell<Terrain> cell, float x, float z) {
|
||||
continent.apply(cell, x, z);
|
||||
continentModule.apply(cell, x, z);
|
||||
regionModule.apply(cell, x, z);
|
||||
|
||||
root.apply(cell, x, z);
|
||||
}
|
||||
|
||||
@ -155,8 +144,9 @@ public class WorldHeightmap implements Heightmap {
|
||||
// initial type
|
||||
cell.tag = terrain.steppe;
|
||||
|
||||
// apply continent value/edge noise
|
||||
continent.apply(cell, x, z);
|
||||
// basic shapes
|
||||
continentModule.apply(cell, x, z);
|
||||
regionModule.apply(cell, x, z);
|
||||
|
||||
// apply actuall heightmap
|
||||
root.apply(cell, x, z);
|
||||
@ -184,7 +174,8 @@ public class WorldHeightmap implements Heightmap {
|
||||
|
||||
@Override
|
||||
public void tag(Cell<Terrain> cell, float x, float z) {
|
||||
continent.apply(cell, x, z);
|
||||
continentModule.apply(cell, x, z);
|
||||
regionModule.apply(cell, x, z);
|
||||
root.tag(cell, x, z);
|
||||
}
|
||||
|
||||
@ -201,8 +192,4 @@ public class WorldHeightmap implements Heightmap {
|
||||
terrainProvider.registerMixable(populator);
|
||||
return populator;
|
||||
}
|
||||
|
||||
private Populator createContinent(GeneratorContext context) {
|
||||
return new VoronoiContinentModule(context.seed, context.settings.generator);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.terraforged.core.world.river;
|
||||
|
||||
import com.terraforged.core.world.heightmap.Heightmap;
|
||||
import me.dags.noise.domain.Domain;
|
||||
import me.dags.noise.util.Vec2i;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.world.heightmap.WorldHeightmap;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
import java.util.Random;
|
||||
@ -21,13 +21,13 @@ public class PosGenerator {
|
||||
private final int padding;
|
||||
private final Domain domain;
|
||||
private final Cell<Terrain> lookup;
|
||||
private final WorldHeightmap heightmap;
|
||||
private final Heightmap heightmap;
|
||||
|
||||
private int i;
|
||||
private int dx;
|
||||
private int dz;
|
||||
|
||||
public PosGenerator(WorldHeightmap heightmap, Domain domain, Cell<Terrain> lookup, int size, int padding) {
|
||||
public PosGenerator(Heightmap heightmap, Domain domain, Cell<Terrain> lookup, int size, int padding) {
|
||||
this.domain = domain;
|
||||
this.lookup = lookup;
|
||||
this.padding = padding;
|
||||
|
@ -1,10 +1,10 @@
|
||||
package com.terraforged.core.world.river;
|
||||
|
||||
import com.terraforged.core.world.heightmap.Heightmap;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.util.Cache;
|
||||
import com.terraforged.core.world.GeneratorContext;
|
||||
import com.terraforged.core.world.heightmap.WorldHeightmap;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -18,11 +18,11 @@ public class RiverManager {
|
||||
private final RiverConfig primary;
|
||||
private final RiverConfig secondary;
|
||||
private final RiverConfig tertiary;
|
||||
private final WorldHeightmap heightmap;
|
||||
private final Heightmap heightmap;
|
||||
private final GeneratorContext context;
|
||||
private final Cache<Long, RiverRegion> cache = new Cache<>(60, 60, TimeUnit.SECONDS, () -> new ConcurrentHashMap<>());
|
||||
|
||||
public RiverManager(WorldHeightmap heightmap, GeneratorContext context) {
|
||||
public RiverManager(Heightmap heightmap, GeneratorContext context) {
|
||||
this.heightmap = heightmap;
|
||||
this.context = context;
|
||||
this.primary = RiverConfig.builder(context.levels)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.terraforged.core.world.river;
|
||||
|
||||
import com.terraforged.core.world.heightmap.Heightmap;
|
||||
import me.dags.noise.domain.Domain;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
import me.dags.noise.util.Vec2f;
|
||||
@ -7,7 +8,6 @@ import me.dags.noise.util.Vec2i;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.util.concurrent.ObjectPool;
|
||||
import com.terraforged.core.world.GeneratorContext;
|
||||
import com.terraforged.core.world.heightmap.WorldHeightmap;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import com.terraforged.core.world.terrain.Terrains;
|
||||
|
||||
@ -35,7 +35,7 @@ public class RiverRegion {
|
||||
private final List<River> rivers;
|
||||
private final List<Lake> lakes = new LinkedList<>();
|
||||
|
||||
public RiverRegion(int regionX, int regionZ, WorldHeightmap heightmap, GeneratorContext context, RiverConfig primary, RiverConfig secondary, RiverConfig tertiary, LakeConfig lake) {
|
||||
public RiverRegion(int regionX, int regionZ, Heightmap heightmap, GeneratorContext context, RiverConfig primary, RiverConfig secondary, RiverConfig tertiary, LakeConfig lake) {
|
||||
int seed = new Random(NoiseUtil.seed(regionX, regionZ)).nextInt();
|
||||
this.lake = lake;
|
||||
this.primary = primary;
|
||||
|
@ -36,7 +36,7 @@ public class VolcanoPopulator extends TerrainPopulator {
|
||||
|
||||
this.cone = Source.cellEdge(region.seed, region.scale, EdgeFunc.DISTANCE_2_DIV).invert()
|
||||
.warp(region.warpX, region.warpZ, region.warpStrength)
|
||||
.powCurve(14)
|
||||
.powCurve(10)
|
||||
.clamp(0.475, 1)
|
||||
.map(0, 1)
|
||||
.grad(0, 0.5, 0.5)
|
||||
@ -47,7 +47,7 @@ public class VolcanoPopulator extends TerrainPopulator {
|
||||
.warp(seed.next(), 30, 1, 30)
|
||||
.scale(0.1);
|
||||
|
||||
this.inversionPoint = 0.95F;
|
||||
this.inversionPoint = 0.93F;
|
||||
this.blendLower = midpoint - (range / 2F);
|
||||
this.blendUpper = blendLower + range;
|
||||
this.blendRange = blendUpper - blendLower;
|
||||
|
@ -1,28 +1,23 @@
|
||||
package com.terraforged.core.module;
|
||||
package com.terraforged.core.world.terrain.region;
|
||||
|
||||
import me.dags.noise.Module;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
|
||||
public class Lerp implements Populator {
|
||||
public class RegionLerper implements Populator {
|
||||
|
||||
private final Module control;
|
||||
private final Populator lower;
|
||||
private final Populator upper;
|
||||
|
||||
public Lerp(Module control, Populator lower, Populator upper) {
|
||||
this.control = control;
|
||||
public RegionLerper(Populator lower, Populator upper) {
|
||||
this.lower = lower;
|
||||
this.upper = upper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float alpha = control.getValue(x, y);
|
||||
cell.regionMask = alpha;
|
||||
|
||||
float alpha = cell.regionEdge;
|
||||
if (alpha == 0) {
|
||||
lower.apply(cell, x, y);
|
||||
return;
|
||||
@ -44,8 +39,7 @@ public class Lerp implements Populator {
|
||||
|
||||
@Override
|
||||
public void tag(Cell<Terrain> cell, float x, float y) {
|
||||
float alpha = control.getValue(x, y);
|
||||
if (alpha == 0) {
|
||||
if (cell.regionEdge == 0) {
|
||||
lower.tag(cell, x, y);
|
||||
return;
|
||||
}
|
@ -1,23 +1,17 @@
|
||||
package com.terraforged.core.world.continent;
|
||||
package com.terraforged.core.world.terrain.region;
|
||||
|
||||
import me.dags.noise.Module;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.world.heightmap.RegionConfig;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import me.dags.noise.Source;
|
||||
import me.dags.noise.domain.Domain;
|
||||
import me.dags.noise.func.DistanceFunc;
|
||||
import me.dags.noise.func.EdgeFunc;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
import me.dags.noise.util.Vec2f;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.settings.GeneratorSettings;
|
||||
import com.terraforged.core.util.Seed;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
public class VoronoiContinentModule implements Populator {
|
||||
|
||||
private static final float edgeClampMin = 0.05F;
|
||||
private static final float edgeClampMax = 0.50F;
|
||||
private static final float edgeClampRange = edgeClampMax - edgeClampMin;
|
||||
public class RegionModule implements Populator {
|
||||
|
||||
private final int seed;
|
||||
private final float frequency;
|
||||
@ -25,44 +19,19 @@ public class VoronoiContinentModule implements Populator {
|
||||
private final float edgeMin;
|
||||
private final float edgeMax;
|
||||
private final float edgeRange;
|
||||
|
||||
private final Domain warp;
|
||||
private final Module shape;
|
||||
|
||||
public VoronoiContinentModule(Seed seed, GeneratorSettings settings) {
|
||||
int tectonicScale = settings.land.continentScale * 4;
|
||||
int continentScale = settings.land.continentScale / 2;
|
||||
double oceans = Math.min(Math.max(settings.world.oceanSize, 0.01), 0.99);
|
||||
double shapeMin = 0.15 + (oceans * 0.35);
|
||||
this.seed = seed.next();
|
||||
|
||||
this.frequency = 1F / tectonicScale;
|
||||
this.edgeMin = edgeClampMin;
|
||||
this.edgeMax = (float) oceans;
|
||||
this.edgeRange = edgeMax - edgeMin;
|
||||
|
||||
this.warp = Domain.warp(Source.SIMPLEX, seed.next(), continentScale, 3, continentScale);
|
||||
|
||||
this.shape = Source.perlin(seed.next(), settings.land.continentScale, 2)
|
||||
.clamp(shapeMin, 0.7)
|
||||
.map(0, 1)
|
||||
.warp(Source.SIMPLEX, seed.next(), continentScale / 2, 1, continentScale / 4D)
|
||||
.warp(seed.next(), 50, 1, 20D);
|
||||
public RegionModule(RegionConfig regionConfig) {
|
||||
seed = regionConfig.seed;
|
||||
edgeMin = 0F;
|
||||
edgeMax = 0.5F;
|
||||
edgeRange = edgeMax - edgeMin;
|
||||
frequency = 1F / regionConfig.scale;
|
||||
warp = Domain.warp(regionConfig.warpX, regionConfig.warpZ, Source.constant(regionConfig.warpStrength));
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue(float x, float y) {
|
||||
if (true) {
|
||||
throw new RuntimeException("no pls!");
|
||||
} else {
|
||||
Cell<Terrain> cell = new Cell<>();
|
||||
apply(cell, x, y);
|
||||
return cell.continentEdge;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, final float x, final float y) {
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float ox = warp.getOffsetX(x, y);
|
||||
float oz = warp.getOffsetY(x, y);
|
||||
|
||||
@ -108,12 +77,8 @@ public class VoronoiContinentModule implements Populator {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float shapeNoise = shape.getValue(x, y);
|
||||
float continentNoise = edgeValue(edgeDistance, edgeDistance2);
|
||||
|
||||
cell.continent = cellValue(seed, cellX, cellY);
|
||||
cell.continentEdge = shapeNoise * continentNoise;
|
||||
cell.region = cellValue(seed, cellX, cellY);
|
||||
cell.regionEdge = edgeValue(edgeDistance, edgeDistance2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -130,12 +95,16 @@ public class VoronoiContinentModule implements Populator {
|
||||
EdgeFunc edge = EdgeFunc.DISTANCE_2_DIV;
|
||||
float value = edge.apply(distance, distance2);
|
||||
float edgeValue = 1 - NoiseUtil.map(value, edge.min(), edge.max(), edge.range());
|
||||
|
||||
edgeValue = NoiseUtil.pow(edgeValue, 1.5F);
|
||||
|
||||
if (edgeValue < edgeMin) {
|
||||
return 0F;
|
||||
}
|
||||
if (edgeValue > edgeMax) {
|
||||
return 1F;
|
||||
}
|
||||
|
||||
return (edgeValue - edgeMin) / edgeRange;
|
||||
}
|
||||
}
|
@ -1,40 +1,36 @@
|
||||
package com.terraforged.core.module;
|
||||
package com.terraforged.core.world.terrain.region;
|
||||
|
||||
import me.dags.noise.Module;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import com.terraforged.core.world.terrain.TerrainPopulator;
|
||||
import me.dags.noise.util.NoiseUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class Selector implements Populator {
|
||||
public class RegionSelector implements Populator {
|
||||
|
||||
private final int maxIndex;
|
||||
private final Module control;
|
||||
private final Populator[] nodes;
|
||||
|
||||
public Selector(Module control, List<Populator> populators) {
|
||||
this.control = control;
|
||||
public RegionSelector(List<Populator> populators) {
|
||||
this.nodes = getWeightedArray(populators);
|
||||
this.maxIndex = nodes.length - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
get(x, y).apply(cell, x, y);
|
||||
get(cell.region).apply(cell, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tag(Cell<Terrain> cell, float x, float y) {
|
||||
get(x, y).tag(cell, x, y);
|
||||
get(cell.region).tag(cell, x, y);
|
||||
}
|
||||
|
||||
public Populator get(float x, float y) {
|
||||
float selector = control.getValue(x, y);
|
||||
int index = NoiseUtil.round(selector * maxIndex);
|
||||
public Populator get(float identity) {
|
||||
int index = NoiseUtil.round(identity * maxIndex);
|
||||
return nodes[index];
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5f7d2c8ec864f6dcd1c977013c3c8377d33c4547
|
||||
Subproject commit 5d1604ab29ae129f133c34fdd72bc207f21364aa
|
Loading…
Reference in New Issue
Block a user