Added _UNFINISHED_ water, beaches and mantle

- Refactored terrain generation
- Added PiecewiseLinearFunction
- Added some placeholder content
  - Added Test:Water, the solid, opaque water
  - Added beaches
  - Added Test:Mantle
- Tweaked rock distribution parameters
This commit is contained in:
OLEGSHA 2021-08-31 17:27:08 +03:00
parent 711e4a2bb4
commit a85fc27f8b
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
27 changed files with 741 additions and 74 deletions

View File

@ -0,0 +1,25 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.util.math;
@FunctionalInterface
public interface FloatFunction {
float apply(float x);
}

View File

@ -0,0 +1,24 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.util.math;
public interface FloatFunction2D {
float apply(float x, float y);
}

View File

@ -0,0 +1,24 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.util.math;
public interface FloatFunction3D {
float apply(float x, float y, float z);
}

View File

@ -0,0 +1,124 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.util.math;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import glm.vec._2.Vec2;
public class PiecewiseLinearFunction implements FloatFunction {
public static class Builder {
private final List<Vec2> points = new ArrayList<>();
private float slopeAtNegInf = 0;
private float slopeAtPosInf = 0;
public Builder add(float x, float y) {
points.add(new Vec2(x, y));
return this;
}
public Builder setNegativeSlope(float slope) {
slopeAtNegInf = slope;
return this;
}
public Builder setPositiveSlope(float slope) {
slopeAtPosInf = slope;
return this;
}
public Builder setDefaultUndefined() {
slopeAtPosInf = Float.NaN;
slopeAtNegInf = Float.NaN;
return this;
}
public PiecewiseLinearFunction build() {
float[] pointXs = new float[points.size()];
float[] pointYs = new float[points.size()];
points.sort(Comparator.comparingDouble(v -> v.x));
for (int i = 0; i < points.size(); ++i) {
pointXs[i] = points.get(i).x;
pointYs[i] = points.get(i).y;
}
return new PiecewiseLinearFunction(pointXs, pointYs, slopeAtNegInf, slopeAtPosInf);
}
}
public static Builder builder() {
return new Builder();
}
/**
* The set of the X coordinates of all defining points, sorted in increasing order
*/
private final float[] pointXs;
/**
* The set of the Y coordinates of all defining points, sorted to match the order of {@link #pointXs}
*/
private final float[] pointYs;
/**
* Slope of the segment (-inf; x[0]), or NaN to exclude the segment from the function
*/
private final float slopeAtNegInf;
/**
* Slope of the segment (x[x.length - 1]; +inf), or NaN to exclude the segment from the function
*/
private final float slopeAtPosInf;
protected PiecewiseLinearFunction(float[] pointXs, float[] pointYs, float slopeAtNegInf, float slopeAtPosInf) {
this.pointXs = pointXs;
this.pointYs = pointYs;
this.slopeAtNegInf = slopeAtNegInf;
this.slopeAtPosInf = slopeAtPosInf;
}
@Override
public float apply(float x) {
int index = Arrays.binarySearch(pointXs, x);
if (index >= 0) {
// Wow, exact match, me surprised
return pointYs[index];
}
int bigger = -index - 1;
int smaller = bigger - 1;
if (smaller == -1) {
return pointYs[bigger] + (x - pointXs[bigger]) * slopeAtNegInf;
} else if (bigger == pointXs.length) {
return pointYs[smaller] + (x - pointXs[smaller]) * slopeAtPosInf;
} else {
float t = (x - pointXs[smaller]) / (pointXs[bigger] - pointXs[smaller]);
return pointYs[smaller] * (1 - t) + pointYs[bigger] * t;
}
}
}

View File

@ -24,7 +24,6 @@ import java.util.List;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.FloatRangeMap;
import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
@ -32,7 +31,7 @@ import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator; import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier;
public class PlanetGenerator extends AbstractWorldGenerator<Boolean> { public class PlanetGenerator extends AbstractWorldGenerator<Boolean> {
@ -46,7 +45,7 @@ public class PlanetGenerator extends AbstractWorldGenerator<Boolean> {
Server server, Server server,
Planet planet, Planet planet,
SurfaceFloatField heightMap, SurfaceFloatField heightMap,
FloatRangeMap<TerrainLayer> layers, TerrainSupplier terrain,
List<SurfaceFeature> features List<SurfaceFeature> features
) { ) {
super(id, server, Boolean.class, "Test:PlanetGravityModel"); super(id, server, Boolean.class, "Test:PlanetGravityModel");
@ -56,7 +55,7 @@ public class PlanetGenerator extends AbstractWorldGenerator<Boolean> {
PlanetGravityModel model = (PlanetGravityModel) this.getGravityModel(); PlanetGravityModel model = (PlanetGravityModel) this.getGravityModel();
model.configure(planet.getGravityModelSettings()); model.configure(planet.getGravityModelSettings());
this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, layers); this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, terrain);
this.featureGenerator = new PlanetFeatureGenerator(this, features); this.featureGenerator = new PlanetFeatureGenerator(this, features);
} }

View File

@ -21,7 +21,6 @@ import java.util.Map;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.FloatRangeMap;
import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.Coordinates;
@ -33,7 +32,7 @@ import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.generation.surface.Surface; import ru.windcorp.progressia.server.world.generation.surface.Surface;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceTerrainGenerator; import ru.windcorp.progressia.server.world.generation.surface.SurfaceTerrainGenerator;
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier;
class PlanetTerrainGenerator { class PlanetTerrainGenerator {
@ -43,7 +42,7 @@ class PlanetTerrainGenerator {
public PlanetTerrainGenerator( public PlanetTerrainGenerator(
PlanetGenerator generator, PlanetGenerator generator,
SurfaceFloatField heightMap, SurfaceFloatField heightMap,
FloatRangeMap<TerrainLayer> layers TerrainSupplier terrain
) { ) {
this.parent = generator; this.parent = generator;
@ -53,7 +52,7 @@ class PlanetTerrainGenerator {
face -> new SurfaceTerrainGenerator( face -> new SurfaceTerrainGenerator(
new Surface(face, seaLevel), new Surface(face, seaLevel),
heightMap, heightMap,
layers terrain
) )
); );
} }

View File

@ -19,7 +19,6 @@ package ru.windcorp.progressia.server.world.generation.surface;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.FloatRangeMap;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;
@ -33,12 +32,12 @@ public class SurfaceTerrainGenerator {
private final Surface surface; private final Surface surface;
private final SurfaceFloatField heightMap; private final SurfaceFloatField heightMap;
private final FloatRangeMap<TerrainLayer> layers; private final TerrainSupplier terrain;
public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, FloatRangeMap<TerrainLayer> layers) { public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, TerrainSupplier terrain) {
this.surface = surface; this.surface = surface;
this.heightMap = heightMap; this.heightMap = heightMap;
this.layers = layers; this.terrain = terrain;
} }
public void generateTerrain(Server server, DefaultChunkData chunk) { public void generateTerrain(Server server, DefaultChunkData chunk) {
@ -74,7 +73,7 @@ public class SurfaceTerrainGenerator {
location.set(north, west, altitude); location.set(north, west, altitude);
SurfaceBlockContext blockContext = context.push(location); SurfaceBlockContext blockContext = context.push(location);
BlockData block = layers.get(depth).get(blockContext, depth); BlockData block = terrain.get(blockContext, depth);
blockContext.pop(); blockContext.pop();

View File

@ -21,7 +21,7 @@ import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
@FunctionalInterface @FunctionalInterface
public interface TerrainLayer { public interface TerrainSupplier {
BlockData get(SurfaceBlockContext context, float depth); BlockData get(SurfaceBlockContext context, float depth);

View File

@ -104,6 +104,8 @@ public class TestContent {
registerSimplestBlock("Dirt"); registerSimplestBlock("Dirt");
registerSimplestBlock("Chernozem"); registerSimplestBlock("Chernozem");
registerSimplestBlock("Stone"); registerSimplestBlock("Stone");
registerSimplestBlock("Mantle");
registerSimplestBlock("Water");
registerSimplestBlock("Brick"); registerSimplestBlock("Brick");
registerSimplestBlock("BrickWhite"); registerSimplestBlock("BrickWhite");
registerSimplestBlock("Sand"); registerSimplestBlock("Sand");

View File

@ -24,21 +24,18 @@ import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.Units;
import ru.windcorp.progressia.common.util.ArrayFloatRangeMap;
import ru.windcorp.progressia.common.util.FloatRangeMap;
import ru.windcorp.progressia.common.util.noise.discrete.WorleyProceduralNoise; import ru.windcorp.progressia.common.util.noise.discrete.WorleyProceduralNoise;
import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.generation.WorldGenerator; import ru.windcorp.progressia.server.world.generation.WorldGenerator;
import ru.windcorp.progressia.server.world.generation.planet.Planet; import ru.windcorp.progressia.server.world.generation.planet.Planet;
import ru.windcorp.progressia.server.world.generation.planet.PlanetGenerator; import ru.windcorp.progressia.server.world.generation.planet.PlanetGenerator;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; import ru.windcorp.progressia.test.Rocks.Rock;
import ru.windcorp.progressia.test.Rocks.RockVariant;
import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestContent;
import ru.windcorp.progressia.test.gen.feature.*;
import ru.windcorp.progressia.test.gen.terrain.*;
public class TestGenerationConfig { public class TestGenerationConfig {
@ -62,47 +59,45 @@ public class TestGenerationConfig {
TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS); TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS);
FloatRangeMap<TerrainLayer> layers = new ArrayFloatRangeMap<>(); LayeredTerrain terrain = new LayeredTerrain();
registerTerrainLayers(layers); registerTerrainLayers(terrain);
List<SurfaceFeature> features = new ArrayList<>(); List<SurfaceFeature> features = new ArrayList<>();
registerFeatures(features); registerFeatures(features);
return server -> new PlanetGenerator("Test:PlanetGenerator", server, planet, heightMap, layers, features); return server -> new PlanetGenerator("Test:PlanetGenerator", server, planet, heightMap, terrain, features);
} }
private static void registerTerrainLayers(FloatRangeMap<TerrainLayer> layers) { private static void registerTerrainLayers(LayeredTerrain terrain) {
BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt");
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
SurfaceFloatField cliffs = FIELDS.get("Test:Cliff"); SurfaceFloatField cliffs = FIELDS.get("Test:Cliff");
SurfaceFloatField beaches = FIELDS.register(
"Test:Beach",
f -> multiply(
anti(FIELDS.get("Test:Cliff", f))
)
);
RockStrata rockStrata = createStrata();
WorleyProceduralNoise.Builder<TerrainLayer> builder = WorleyProceduralNoise.builder(); terrain.addLayer(new AirLayer("Test:Air"));
TestContent.ROCKS.getRocks().forEach(rock -> { terrain.addLayer(new MantleLayer("Test:Mantle"));
builder.add((c, d) -> { terrain.addLayer(new CrustLayer("Test:Crust", rockStrata));
if (c.getRandom().nextInt(3) == 0) { terrain.addLayer(new WaterLayer("Test:Water"));
return rock.getBlock(RockVariant.CRACKED); terrain.addLayer(new SoilLayer("Test:Soil"));
} else { terrain.addLayer(new CliffLayer("Test:Cliffs", cliffs, rockStrata));
return rock.getBlock(RockVariant.MONOLITH); terrain.addLayer(new BeachLayer("Test:Beaches", beaches, rockStrata));
} }
}, 1);
}); private static RockStrata createStrata() {
WorleyProceduralNoise.Builder<Rock> builder = WorleyProceduralNoise.builder();
TestContent.ROCKS.getRocks().forEach(rock -> builder.add(rock, 1));
SurfaceFloatField rockDepthOffsets = FIELDS.register( SurfaceFloatField rockDepthOffsets = FIELDS.register(
"Test:RockDepthOffsets", "Test:RockDepthOffsets",
() -> tweak(FIELDS.primitive(), 40, 5) () -> tweak(FIELDS.primitive(), 40, 5)
); );
RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets);
layers.put(Float.NEGATIVE_INFINITY, 0, (c, d) -> air); return new RockStrata(builder.build(SEED), rockDepthOffsets);
layers.put(0, 4, (c, d) -> {
if (cliffs.get(c.getSurface().getUp(), c.getLocation().x, c.getLocation().y) > 0) {
return rockLayer.get(c, d);
} else {
return dirt;
}
});
layers.put(4, Float.POSITIVE_INFINITY, rockLayer);
} }
private static void registerFeatures(List<SurfaceFeature> features) { private static void registerFeatures(List<SurfaceFeature> features) {

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package ru.windcorp.progressia.test.gen; package ru.windcorp.progressia.test.gen.feature;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package ru.windcorp.progressia.test.gen; package ru.windcorp.progressia.test.gen.feature;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package ru.windcorp.progressia.test.gen; package ru.windcorp.progressia.test.gen.feature;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package ru.windcorp.progressia.test.gen; package ru.windcorp.progressia.test.gen.feature;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -104,7 +104,17 @@ public class TestGrassFeature extends SurfaceTopLayerFeature {
} }
private void growGrass(SurfaceBlockContext context, double grassiness) { private void growGrass(SurfaceBlockContext context, double grassiness) {
TileData flatGrass = flatGrasses.get((float) grassiness);
double flatGrassiness = grassiness;
BlockData soil = context.getBlock();
if (soil.getId().endsWith("Sand")) {
flatGrassiness = flatGrassiness / 2 - 0.2;
if (flatGrassiness < 0) {
flatGrassiness = 0;
}
}
TileData flatGrass = flatGrasses.get((float) flatGrassiness);
if (flatGrass != null) { if (flatGrass != null) {
for (RelFace face : RelFace.getFaces()) { for (RelFace face : RelFace.getFaces()) {
if (face == RelFace.DOWN) if (face == RelFace.DOWN)

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package ru.windcorp.progressia.test.gen; package ru.windcorp.progressia.test.gen.feature;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;

View File

@ -0,0 +1,42 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
public class AirLayer extends TerrainLayer {
private final BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
public AirLayer(String id) {
super(id);
}
@Override
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
return air;
}
@Override
public float getIntensity(SurfaceBlockContext context, float depth) {
return depth <= 0 ? 1 : 0;
}
}

View File

@ -0,0 +1,55 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
import ru.windcorp.progressia.test.Rocks.RockVariant;
public class BeachLayer extends TerrainLayer {
private final SurfaceFloatField beachSelector;
private final RockStrata strata;
public BeachLayer(String id, SurfaceFloatField beachSelector, RockStrata strata) {
super(id);
this.beachSelector = beachSelector;
this.strata = strata;
}
@Override
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
return strata.get(context, depth).getBlock(RockVariant.SAND);
}
@Override
public float getIntensity(SurfaceBlockContext context, float depth) {
if (depth < 0 || depth > 3) {
return 0;
}
float altitude = context.getLocation().z;
if (altitude < -5| altitude > 1) {
return 0;
}
return 3 * beachSelector.get(context);
}
}

View File

@ -0,0 +1,64 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
import ru.windcorp.progressia.test.Rocks.RockVariant;
public class CliffLayer extends TerrainLayer {
private final SurfaceFloatField cliffSelector;
private final RockStrata strata;
public CliffLayer(String id, SurfaceFloatField cliffSelector, RockStrata strata) {
super(id);
this.cliffSelector = cliffSelector;
this.strata = strata;
}
@Override
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
RockVariant variant;
switch (context.getRandom().nextInt(4)) {
case 0:
variant = RockVariant.GRAVEL;
break;
case 1:
variant = RockVariant.MONOLITH;
break;
default:
variant = RockVariant.CRACKED;
break;
}
return strata.get(context, depth).getBlock(variant);
}
@Override
public float getIntensity(SurfaceBlockContext context, float depth) {
if (depth < 0 || depth > 7) {
return 0;
}
return 100 * cliffSelector.get(context);
}
}

View File

@ -0,0 +1,69 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.util.ArrayFloatRangeMap;
import ru.windcorp.progressia.common.util.FloatRangeMap;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
import ru.windcorp.progressia.test.Rocks.RockVariant;
public class CrustLayer extends TerrainLayer {
private static final FloatRangeMap<RockVariant> WEAR_TABLE = new ArrayFloatRangeMap<>();
static {
WEAR_TABLE.put(Float.NEGATIVE_INFINITY, 0.25f, RockVariant.MONOLITH);
WEAR_TABLE.put(0.25f, 0.5f, RockVariant.CRACKED);
WEAR_TABLE.put(0.5f, 0.75f, RockVariant.GRAVEL);
WEAR_TABLE.put(0.75f, Float.POSITIVE_INFINITY, RockVariant.SAND);
}
private final RockStrata strata;
public CrustLayer(String id, RockStrata strata) {
super(id);
this.strata = strata;
}
@Override
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
RockVariant variant;
if (depth < 8) {
float wear = 1 - depth / 8;
float offset = (context.getRandom().nextFloat() * 2 - 1) * 0.5f;
variant = WEAR_TABLE.get(wear + offset);
} else {
variant = RockVariant.MONOLITH;
}
return strata.get(context, depth).getBlock(variant);
}
@Override
public float getIntensity(SurfaceBlockContext context, float depth) {
if (depth < 0) {
return 0;
} else if (context.getLocation().z > -100) {
return 1;
} else {
return 0;
}
}
}

View File

@ -0,0 +1,61 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import java.util.ArrayList;
import java.util.List;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
public class LayeredTerrain implements TerrainSupplier {
private final List<TerrainLayer> layers = new ArrayList<>();
public void addLayer(TerrainLayer layer) {
this.layers.add(layer);
}
@Override
public BlockData get(SurfaceBlockContext context, float depth) {
TerrainLayer layer = null;
float intensity = 0;
for (int i = 0; i < layers.size(); ++i) {
TerrainLayer currentLayer = layers.get(i);
float currentIntensity = currentLayer.getIntensity(context, depth);
if (currentIntensity <= 0) {
continue;
}
if (intensity < currentIntensity) {
intensity = currentIntensity;
layer = currentLayer;
}
}
if (layer == null) {
layer = layers.get(0);
}
return layer.generate(context, depth, intensity);
}
}

View File

@ -0,0 +1,42 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
public class MantleLayer extends TerrainLayer {
private final BlockData material = BlockDataRegistry.getInstance().get("Test:Mantle");
public MantleLayer(String id) {
super(id);
}
@Override
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
return material;
}
@Override
public float getIntensity(SurfaceBlockContext context, float depth) {
return context.getLocation().z <= -100 ? 1 : 0;
}
}

View File

@ -15,43 +15,38 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package ru.windcorp.progressia.test.gen; package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.util.noise.discrete.DiscreteNoise; import ru.windcorp.progressia.common.util.noise.discrete.DiscreteNoise;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
import ru.windcorp.progressia.test.Rocks.Rock;
public class RockLayer implements TerrainLayer { public class RockStrata {
private final DiscreteNoise<TerrainLayer> strata; private final DiscreteNoise<Rock> distribution;
private final SurfaceFloatField depthOffsets; private final SurfaceFloatField depthOffsets;
private final double horizontalScale = 200; private final double horizontalScale = 800;
private final double verticalScale = 10; private final double verticalScale = 20;
private final double depthInfluense = 0.1; private final double depthInfluence = 0.1;
public RockLayer(DiscreteNoise<TerrainLayer> strata, SurfaceFloatField depthOffsets) { public RockStrata(DiscreteNoise<Rock> distribution, SurfaceFloatField depthOffsets) {
this.strata = strata; this.distribution = distribution;
this.depthOffsets = depthOffsets; this.depthOffsets = depthOffsets;
} }
@Override public Rock get(SurfaceBlockContext context, float depth) {
public BlockData get(SurfaceBlockContext context, float depth) {
double z = context.getLocation().z; double z = context.getLocation().z;
z -= depth * depthInfluense; z -= depth * depthInfluence;
z += depthOffsets.get(context); z += depthOffsets.get(context);
z /= verticalScale; z /= verticalScale;
return strata return distribution.get(
.get(
context.getLocation().x / horizontalScale, context.getLocation().x / horizontalScale,
context.getLocation().y / horizontalScale, context.getLocation().y / horizontalScale,
z z
) );
.get(context, depth);
} }
} }

View File

@ -0,0 +1,59 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.Units;
import ru.windcorp.progressia.common.util.math.PiecewiseLinearFunction;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
public class SoilLayer extends TerrainLayer {
private static final PiecewiseLinearFunction THICKNESS = PiecewiseLinearFunction.builder()
.add(Units.get("-5 m"), Units.get("1 m"))
.add(Units.get("0 m"), Units.get("4 m"))
.add(Units.get("5 km"), Units.get("0 m"))
.build();
private final BlockData soil = BlockDataRegistry.getInstance().get("Test:Dirt");
public SoilLayer(String id) {
super(id);
}
@Override
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
return soil;
}
@Override
public float getIntensity(SurfaceBlockContext context, float depth) {
if (depth < 0) return 0;
float altitude = context.getLocation().z;
float thickness = THICKNESS.apply(altitude);
if (depth < thickness) {
return 2;
} else {
return 0;
}
}
}

View File

@ -0,0 +1,34 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
public abstract class TerrainLayer extends Namespaced {
public TerrainLayer(String id) {
super(id);
}
public abstract BlockData generate(SurfaceBlockContext context, float depth, float intensity);
public abstract float getIntensity(SurfaceBlockContext context, float depth);
}

View File

@ -0,0 +1,45 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.terrain;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
public class WaterLayer extends TerrainLayer {
private final BlockData water = BlockDataRegistry.getInstance().get("Test:Water");
public WaterLayer(String id) {
super(id);
}
@Override
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
return water;
}
@Override
public float getIntensity(SurfaceBlockContext context, float depth) {
if (depth <= 0 && context.getLocation().z <= 0) {
return 2;
}
return 0;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB