Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Enable scalable generation #26

Merged
merged 4 commits into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Produces;
import org.terasology.world.generation.Requires;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.facets.ElevationFacet;
import org.terasology.world.generation.facets.SeaLevelFacet;
import org.terasology.world.generation.facets.SurfaceHumidityFacet;
Expand All @@ -40,14 +41,14 @@
@Facet(SurfaceRoughnessFacet.class),
@Facet(SurfaceTemperatureFacet.class),
@Facet(SurfaceHumidityFacet.class)})
public class BiomeProvider implements FacetProvider {
public class BiomeProvider implements ScalableFacetProvider {

@Override
public void setSeed(long seed) {
}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
SeaLevelFacet seaLevelFacet = region.getRegionFacet(SeaLevelFacet.class);
ElevationFacet elevationFacet = region.getRegionFacet(ElevationFacet.class);
SurfaceRoughnessFacet roughnessFacet = region.getRegionFacet(SurfaceRoughnessFacet.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.terasology.world.generation.FacetProvider;
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Requires;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.Updates;
import org.terasology.world.generation.facets.DensityFacet;
import org.terasology.world.generation.facets.SurfacesFacet;
Expand All @@ -29,7 +30,7 @@
@Facet(value = DensityFacet.class, border = @FacetBorder(top = 1)),
@Facet(SurfacesFacet.class)
})
public class DensityNoiseProvider implements FacetProvider {
public class DensityNoiseProvider implements ScalableFacetProvider {
private SubSampledNoise largeNoise;
private SubSampledNoise smallNoise;

Expand All @@ -42,14 +43,14 @@ public void setSeed(long seed) {
}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
SurfaceRoughnessFacet surfaceRoughnessFacet = region.getRegionFacet(SurfaceRoughnessFacet.class);
DensityFacet densityFacet = region.getRegionFacet(DensityFacet.class);
SurfacesFacet surfacesFacet = region.getRegionFacet(SurfacesFacet.class);

BlockRegion densityRegion = densityFacet.getWorldRegion();
float[] smallNoiseValues = smallNoise.noise(densityRegion);
float[] largeNoiseValues = largeNoise.noise(densityRegion);
float[] smallNoiseValues = smallNoise.noise(densityRegion, scale);
float[] largeNoiseValues = largeNoise.noise(densityRegion, scale);
float[] densityValues = densityFacet.getInternal();

int x = densityRegion.minX();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
import org.terasology.world.generation.FacetProvider;
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Produces;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.facets.SeaLevelFacet;

/**
*/
@Produces(SeaLevelFacet.class)
public class SeaLevelProvider implements FacetProvider {
public class SeaLevelProvider implements ScalableFacetProvider {

private int seaLevel;

Expand All @@ -41,7 +42,7 @@ public void setSeed(long seed) {
}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
Border3D border = region.getBorderForFacet(SeaLevelFacet.class);
SeaLevelFacet facet = new SeaLevelFacet(region.getRegion(), border);
facet.setSeaLevel(seaLevel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Produces;
import org.terasology.world.generation.Requires;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.facets.ElevationFacet;
import org.terasology.world.generation.facets.SeaLevelFacet;

/**
*/
@Produces(ElevationFacet.class)
@Requires(@Facet(SeaLevelFacet.class))
public class SimplexBaseSurfaceProvider implements FacetProvider {
public class SimplexBaseSurfaceProvider implements ScalableFacetProvider {
private static final int SAMPLE_RATE = 4;
private static final float BEACH_STEEPNESS = 0.05f;
private static final float OCEAN_FLOOR_CUTOFF = 0.1f;
Expand All @@ -52,12 +53,12 @@ public void setSeed(long seed) {
}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
Border3D border = region.getBorderForFacet(ElevationFacet.class);
ElevationFacet facet = new ElevationFacet(region.getRegion(), border);
SeaLevelFacet seaLevelFacet = region.getRegionFacet(SeaLevelFacet.class);
float seaLevel = seaLevelFacet.getSeaLevel();
float[] noise = surfaceNoise.noise(facet.getWorldArea());
float[] noise = surfaceNoise.noise(facet.getWorldArea(), scale);

for (int i = 0; i < noise.length; ++i) {
if (noise[i] > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@
import org.terasology.world.generation.ConfigurableFacetProvider;
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Produces;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.facets.SurfaceHumidityFacet;

/**
* Defines surface humidity in the range [0..1] based on random noise.
*/
@Produces(SurfaceHumidityFacet.class)
public class SimplexHumidityProvider implements ConfigurableFacetProvider {
public class SimplexHumidityProvider implements ConfigurableFacetProvider, ScalableFacetProvider {
private static final int SAMPLE_RATE = 4;

private SubSampledNoise humidityNoise;
Expand All @@ -59,11 +60,11 @@ public void setSeed(long seed) {
}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
Border3D border = region.getBorderForFacet(SurfaceHumidityFacet.class);
SurfaceHumidityFacet facet = new SurfaceHumidityFacet(region.getRegion(), border);

float[] noise = humidityNoise.noise(facet.getWorldArea());
float[] noise = humidityNoise.noise(facet.getWorldArea(), scale);
for (int i = 0; i < noise.length; ++i) {
noise[i] = TeraMath.clamp((noise[i] * 2.11f + 1f) * 0.5f);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
import org.terasology.world.generation.Facet;
import org.terasology.world.generation.FacetProvider;
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.Updates;
import org.terasology.world.generation.facets.ElevationFacet;

/**
* Applies an amount of the max depth for regions that are rivers
*/
@Updates(@Facet(ElevationFacet.class))
public class SimplexRiverProvider implements FacetProvider, ConfigurableFacetProvider {
public class SimplexRiverProvider implements ScalableFacetProvider, ConfigurableFacetProvider {
private static final int SAMPLE_RATE = 4;

private SubSampledNoise riverNoise;
Expand All @@ -44,9 +45,13 @@ public void setSeed(long seed) {
}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
if (scale > 20) {
// The scale is so large that rivers wouldn't be visible anyway.
return;
}
ElevationFacet facet = region.getRegionFacet(ElevationFacet.class);
float[] noise = riverNoise.noise(facet.getWorldArea());
float[] noise = riverNoise.noise(facet.getWorldArea(), scale);

float[] surfaceHeights = facet.getInternal();
for (int i = 0; i < noise.length; ++i) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Produces;
import org.terasology.world.generation.Requires;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.facets.ElevationFacet;
import org.terasology.world.generation.facets.SeaLevelFacet;

Expand All @@ -23,7 +24,7 @@
@Facet(ElevationFacet.class),
@Facet(SeaLevelFacet.class)
})
public class SimplexRoughnessProvider implements FacetProvider {
public class SimplexRoughnessProvider implements ScalableFacetProvider {
private static final int SAMPLE_RATE = 4;

private Noise noise;
Expand All @@ -34,14 +35,14 @@ public void setSeed(long seed) {
}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
ElevationFacet elevationFacet = region.getRegionFacet(ElevationFacet.class);
SeaLevelFacet seaLevelFacet = region.getRegionFacet(SeaLevelFacet.class);
SurfaceRoughnessFacet facet = new SurfaceRoughnessFacet(region.getRegion(), region.getBorderForFacet(SurfaceRoughnessFacet.class));

for (Vector2ic pos : facet.getWorldArea()) {
float height = elevationFacet.getWorld(pos) - seaLevelFacet.getSeaLevel();
float value = 0.25f + height * 0.007f + noise.noise(pos.x() / 500f, pos.y() / 500f) * 1.5f;
float value = 0.25f + height * 0.007f + noise.noise(pos.x() * scale / 500f, pos.y() * scale / 500f) * 1.5f;
facet.setWorld(pos, value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
import org.terasology.world.generation.FacetProvider;
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Produces;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.facets.SurfaceTemperatureFacet;

/**
*/
@Produces(SurfaceTemperatureFacet.class)
public class SimplexSurfaceTemperatureProvider implements FacetProvider {
public class SimplexSurfaceTemperatureProvider implements ScalableFacetProvider {
private static final int SAMPLE_RATE = 4;

private SubSampledNoise temperatureNoise;
Expand All @@ -39,9 +40,9 @@ public void setSeed(long seed) {
}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
SurfaceTemperatureFacet facet = new SurfaceTemperatureFacet(region.getRegion(), region.getBorderForFacet(SurfaceTemperatureFacet.class));
float[] noise = this.temperatureNoise.noise(facet.getWorldArea());
float[] noise = this.temperatureNoise.noise(facet.getWorldArea(), scale);

for (int i = 0; i < noise.length; ++i) {
noise[i] = TeraMath.clamp((noise[i] * 2.11f + 1f) * 0.5f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Produces;
import org.terasology.world.generation.Requires;
import org.terasology.world.generation.ScalableFacetProvider;
import org.terasology.world.generation.facets.DensityFacet;
import org.terasology.world.generation.facets.ElevationFacet;
import org.terasology.world.generation.facets.SurfacesFacet;
Expand All @@ -33,15 +34,15 @@
*/
@Requires(@Facet(ElevationFacet.class))
@Produces({DensityFacet.class, SurfacesFacet.class})
public class SurfaceToDensityProvider implements FacetProvider {
public class SurfaceToDensityProvider implements ScalableFacetProvider {

@Override
public void setSeed(long seed) {

}

@Override
public void process(GeneratingRegion region) {
public void process(GeneratingRegion region, float scale) {
ElevationFacet elevation = region.getRegionFacet(ElevationFacet.class);
DensityFacet densityFacet = new DensityFacet(region.getRegion(), region.getBorderForFacet(DensityFacet.class));
SurfacesFacet surfacesFacet = new SurfacesFacet(region.getRegion(), region.getBorderForFacet(SurfacesFacet.class));
Expand All @@ -52,7 +53,7 @@ public void process(GeneratingRegion region) {
for (Vector2ic pos : densityRect) {
float height = elevation.get(pos);
for (int y = densityFacet.getRelativeRegion().minY(); y <= densityFacet.getRelativeRegion().maxY(); ++y) {
densityFacet.set(pos.x(), y, pos.y(), height - area.minY() - y);
densityFacet.set(pos.x(), y, pos.y(), height - (area.minY() + y) * scale);
}
}
region.setRegionFacet(DensityFacet.class, densityFacet);
Expand All @@ -61,7 +62,7 @@ public void process(GeneratingRegion region) {
surfacesFacet.getWorldRegion().maxX(), surfacesFacet.getWorldRegion().maxZ());
for (Vector2ic pos : surfaceRect) {
// Round in this odd way because if the elevation is precisely an integer, the block at that level has density 0, so it's air.
int height = (int) Math.ceil(elevation.getWorld(pos)) - 1;
int height = (int) Math.ceil(elevation.getWorld(pos) / scale) - 1;
if (height >= surfacesFacet.getWorldRegion().minY() && height <= surfacesFacet.getWorldRegion().maxY()) {
surfacesFacet.setWorld(pos.x(), height, pos.y(), true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,23 @@
import org.terasology.world.block.BlockManager;
import org.terasology.world.chunks.Chunks;
import org.terasology.world.chunks.CoreChunk;
import org.terasology.world.generation.Facet;
import org.terasology.world.generation.Region;
import org.terasology.world.generation.Requires;
import org.terasology.world.generation.ScalableWorldRasterizer;
import org.terasology.world.generation.WorldRasterizer;
import org.terasology.world.generation.facets.DensityFacet;
import org.terasology.world.generation.facets.SeaLevelFacet;
import org.terasology.world.generation.facets.SurfaceDepthFacet;
import org.terasology.world.generation.facets.SurfacesFacet;

public class SolidRasterizer implements WorldRasterizer {
@Requires({
@Facet(DensityFacet.class),
@Facet(SurfacesFacet.class),
@Facet(BiomeFacet.class),
@Facet(SeaLevelFacet.class)
})
public class SolidRasterizer implements ScalableWorldRasterizer {

private Block water;
private Block ice;
Expand All @@ -58,7 +67,7 @@ public void initialize() {
}

@Override
public void generateChunk(CoreChunk chunk, Region chunkRegion) {
public void generateChunk(CoreChunk chunk, Region chunkRegion, float scale) {
DensityFacet solidityFacet = chunkRegion.getFacet(DensityFacet.class);
SurfacesFacet surfacesFacet = chunkRegion.getFacet(SurfacesFacet.class);
SurfaceDepthFacet surfaceDepthFacet = chunkRegion.getFacet(SurfaceDepthFacet.class);
Expand All @@ -69,7 +78,9 @@ public void generateChunk(CoreChunk chunk, Region chunkRegion) {
Vector2i pos2d = new Vector2i();
for (Vector3ic pos : Chunks.CHUNK_REGION) {
pos2d.set(pos.x(), pos.z());
int posY = pos.y() + chunk.getChunkWorldOffsetY();
float density = solidityFacet.get(pos);
float basePosY = (pos.y() + chunk.getChunkWorldOffsetY()) * scale;
float posY = basePosY + Math.max(0, Math.min(scale, density));

// Check for an optional depth for this layer - if defined stop generating below that level
if (surfaceDepthFacet != null && posY < surfaceDepthFacet.get(pos2d)) {
Expand All @@ -79,24 +90,24 @@ public void generateChunk(CoreChunk chunk, Region chunkRegion) {
Biome biome = biomeFacet.get(pos2d);
biomeRegistry.setBiome(biome, chunk, pos.x(), pos.y(), pos.z());

float density = solidityFacet.get(pos);

if (density > 0 && surfacesFacet.get(pos)) {
if (posY < seaLevel && basePosY + scale > seaLevel && seaLevel < scale) {
// ensure that the ocean is at least 1 block thick.
chunk.setBlock(pos, water);
} else if (density > 0 && surfacesFacet.get(pos)) {
chunk.setBlock(pos, getSurfaceBlock(biome, posY - seaLevel));
} else if (density > 0) {
chunk.setBlock(pos, getBelowSurfaceBlock(density, biome));
} else {
// fill up terrain up to sealevel height with water or ice
if (posY == seaLevel && CoreBiome.SNOW == biome) {
} else if (posY <= seaLevel) { // either OCEAN or SNOW
if (posY + scale > seaLevel && CoreBiome.SNOW == biome) {
chunk.setBlock(pos, ice);
} else if (posY <= seaLevel) { // either OCEAN or SNOW
} else {
chunk.setBlock(pos, water);
}
}
}
}

private Block getSurfaceBlock(Biome type, int heightAboveSea) {
private Block getSurfaceBlock(Biome type, float heightAboveSea) {
if (type instanceof CoreBiome) {
switch ((CoreBiome) type) {
case FOREST:
Expand Down
Loading