diff --git a/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction.java b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction.java new file mode 100644 index 0000000..f2438b3 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction.java @@ -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 . + */ +package ru.windcorp.progressia.common.util.math; + +@FunctionalInterface +public interface FloatFunction { + + float apply(float x); + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction2D.java b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction2D.java new file mode 100644 index 0000000..f41ea25 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction2D.java @@ -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 . + */ +package ru.windcorp.progressia.common.util.math; + +public interface FloatFunction2D { + + float apply(float x, float y); + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction3D.java b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction3D.java new file mode 100644 index 0000000..3e5e7a7 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction3D.java @@ -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 . + */ +package ru.windcorp.progressia.common.util.math; + +public interface FloatFunction3D { + + float apply(float x, float y, float z); + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/math/PiecewiseLinearFunction.java b/src/main/java/ru/windcorp/progressia/common/util/math/PiecewiseLinearFunction.java new file mode 100644 index 0000000..051d7f2 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/math/PiecewiseLinearFunction.java @@ -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 . + */ +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 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; + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java index b2c5c8c..dad0435 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java @@ -24,7 +24,6 @@ import java.util.List; import glm.vec._3.Vec3; 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.world.DefaultChunkData; 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.surface.SurfaceFeature; 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 { @@ -46,7 +45,7 @@ public class PlanetGenerator extends AbstractWorldGenerator { Server server, Planet planet, SurfaceFloatField heightMap, - FloatRangeMap layers, + TerrainSupplier terrain, List features ) { super(id, server, Boolean.class, "Test:PlanetGravityModel"); @@ -56,7 +55,7 @@ public class PlanetGenerator extends AbstractWorldGenerator { PlanetGravityModel model = (PlanetGravityModel) this.getGravityModel(); model.configure(planet.getGravityModelSettings()); - this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, layers); + this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, terrain); this.featureGenerator = new PlanetFeatureGenerator(this, features); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java index cb4507c..368a59a 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java @@ -21,7 +21,6 @@ import java.util.Map; import glm.vec._3.Vec3; 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.world.DefaultChunkData; 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.SurfaceFloatField; 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 { @@ -43,7 +42,7 @@ class PlanetTerrainGenerator { public PlanetTerrainGenerator( PlanetGenerator generator, SurfaceFloatField heightMap, - FloatRangeMap layers + TerrainSupplier terrain ) { this.parent = generator; @@ -53,7 +52,7 @@ class PlanetTerrainGenerator { face -> new SurfaceTerrainGenerator( new Surface(face, seaLevel), heightMap, - layers + terrain ) ); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java index ea7cb9b..ead1d47 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java @@ -19,7 +19,6 @@ package ru.windcorp.progressia.server.world.generation.surface; import glm.vec._3.Vec3; 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.world.DefaultChunkData; import ru.windcorp.progressia.common.world.block.BlockData; @@ -33,12 +32,12 @@ public class SurfaceTerrainGenerator { private final Surface surface; private final SurfaceFloatField heightMap; - private final FloatRangeMap layers; + private final TerrainSupplier terrain; - public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, FloatRangeMap layers) { + public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, TerrainSupplier terrain) { this.surface = surface; this.heightMap = heightMap; - this.layers = layers; + this.terrain = terrain; } public void generateTerrain(Server server, DefaultChunkData chunk) { @@ -74,7 +73,7 @@ public class SurfaceTerrainGenerator { location.set(north, west, altitude); SurfaceBlockContext blockContext = context.push(location); - BlockData block = layers.get(depth).get(blockContext, depth); + BlockData block = terrain.get(blockContext, depth); blockContext.pop(); diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainSupplier.java similarity index 96% rename from src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainSupplier.java index 5ec131c..a3a1376 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainSupplier.java @@ -21,7 +21,7 @@ import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; @FunctionalInterface -public interface TerrainLayer { +public interface TerrainSupplier { BlockData get(SurfaceBlockContext context, float depth); diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 8396e21..75e32e4 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -104,6 +104,8 @@ public class TestContent { registerSimplestBlock("Dirt"); registerSimplestBlock("Chernozem"); registerSimplestBlock("Stone"); + registerSimplestBlock("Mantle"); + registerSimplestBlock("Water"); registerSimplestBlock("Brick"); registerSimplestBlock("BrickWhite"); registerSimplestBlock("Sand"); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java index ee0f312..2147889 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -24,21 +24,18 @@ import java.util.List; import java.util.function.Function; 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.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.world.generation.WorldGenerator; 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.surface.SurfaceFeature; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; -import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; -import ru.windcorp.progressia.test.Rocks.RockVariant; +import ru.windcorp.progressia.test.Rocks.Rock; import ru.windcorp.progressia.test.TestContent; +import ru.windcorp.progressia.test.gen.feature.*; +import ru.windcorp.progressia.test.gen.terrain.*; public class TestGenerationConfig { @@ -62,47 +59,45 @@ public class TestGenerationConfig { TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS); - FloatRangeMap layers = new ArrayFloatRangeMap<>(); - registerTerrainLayers(layers); + LayeredTerrain terrain = new LayeredTerrain(); + registerTerrainLayers(terrain); List features = new ArrayList<>(); 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 layers) { - BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); - BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - + private static void registerTerrainLayers(LayeredTerrain terrain) { 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 builder = WorleyProceduralNoise.builder(); - TestContent.ROCKS.getRocks().forEach(rock -> { - builder.add((c, d) -> { - if (c.getRandom().nextInt(3) == 0) { - return rock.getBlock(RockVariant.CRACKED); - } else { - return rock.getBlock(RockVariant.MONOLITH); - } - }, 1); - }); + terrain.addLayer(new AirLayer("Test:Air")); + terrain.addLayer(new MantleLayer("Test:Mantle")); + terrain.addLayer(new CrustLayer("Test:Crust", rockStrata)); + terrain.addLayer(new WaterLayer("Test:Water")); + terrain.addLayer(new SoilLayer("Test:Soil")); + terrain.addLayer(new CliffLayer("Test:Cliffs", cliffs, rockStrata)); + terrain.addLayer(new BeachLayer("Test:Beaches", beaches, rockStrata)); + } + + private static RockStrata createStrata() { + WorleyProceduralNoise.Builder builder = WorleyProceduralNoise.builder(); + TestContent.ROCKS.getRocks().forEach(rock -> builder.add(rock, 1)); + SurfaceFloatField rockDepthOffsets = FIELDS.register( "Test:RockDepthOffsets", () -> tweak(FIELDS.primitive(), 40, 5) ); - RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets); - - layers.put(Float.NEGATIVE_INFINITY, 0, (c, d) -> air); - 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); + + return new RockStrata(builder.build(SEED), rockDepthOffsets); } private static void registerFeatures(List features) { diff --git a/src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/MultiblockVegetationFeature.java similarity index 98% rename from src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/MultiblockVegetationFeature.java index 5cfcc43..ecd738d 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/MultiblockVegetationFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import java.util.Set; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java similarity index 97% rename from src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java index ca2765c..b559582 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestFlowerFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java similarity index 98% rename from src/main/java/ru/windcorp/progressia/test/gen/TestFlowerFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java index 33460a1..19a97aa 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestFlowerFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import java.util.Set; import java.util.function.Function; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java similarity index 93% rename from src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java index 2c564b7..add06ec 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import java.util.List; import java.util.Set; @@ -104,7 +104,17 @@ public class TestGrassFeature extends SurfaceTopLayerFeature { } 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) { for (RelFace face : RelFace.getFaces()) { if (face == RelFace.DOWN) diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java similarity index 98% rename from src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java index d08862e..611ec07 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/AirLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/AirLayer.java new file mode 100644 index 0000000..dbafbd4 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/AirLayer.java @@ -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 . + */ +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; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/BeachLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/BeachLayer.java new file mode 100644 index 0000000..24880ab --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/BeachLayer.java @@ -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 . + */ +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); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/CliffLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/CliffLayer.java new file mode 100644 index 0000000..59f487a --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/CliffLayer.java @@ -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 . + */ +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); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/CrustLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/CrustLayer.java new file mode 100644 index 0000000..2ce53a6 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/CrustLayer.java @@ -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 . + */ +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 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; + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/LayeredTerrain.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/LayeredTerrain.java new file mode 100644 index 0000000..ac802c2 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/LayeredTerrain.java @@ -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 . + */ +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 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); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/MantleLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/MantleLayer.java new file mode 100644 index 0000000..a72f95e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/MantleLayer.java @@ -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 . + */ +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; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/RockLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/RockStrata.java similarity index 64% rename from src/main/java/ru/windcorp/progressia/test/gen/RockLayer.java rename to src/main/java/ru/windcorp/progressia/test/gen/terrain/RockStrata.java index 5b41ef1..218b51a 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/RockLayer.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/RockStrata.java @@ -15,43 +15,38 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -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.world.block.BlockData; 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.test.Rocks.Rock; -public class RockLayer implements TerrainLayer { - - private final DiscreteNoise strata; +public class RockStrata { + + private final DiscreteNoise distribution; private final SurfaceFloatField depthOffsets; - private final double horizontalScale = 200; - private final double verticalScale = 10; - private final double depthInfluense = 0.1; + private final double horizontalScale = 800; + private final double verticalScale = 20; + private final double depthInfluence = 0.1; - public RockLayer(DiscreteNoise strata, SurfaceFloatField depthOffsets) { - this.strata = strata; + public RockStrata(DiscreteNoise distribution, SurfaceFloatField depthOffsets) { + this.distribution = distribution; this.depthOffsets = depthOffsets; } - - @Override - public BlockData get(SurfaceBlockContext context, float depth) { - + + public Rock get(SurfaceBlockContext context, float depth) { double z = context.getLocation().z; - z -= depth * depthInfluense; + z -= depth * depthInfluence; z += depthOffsets.get(context); z /= verticalScale; - return strata - .get( + return distribution.get( context.getLocation().x / horizontalScale, context.getLocation().y / horizontalScale, z - ) - .get(context, depth); + ); } } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/SoilLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/SoilLayer.java new file mode 100644 index 0000000..44875a0 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/SoilLayer.java @@ -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 . + */ +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; + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/TerrainLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/TerrainLayer.java new file mode 100644 index 0000000..e9eeb4b --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/TerrainLayer.java @@ -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 . + */ +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); + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/WaterLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/WaterLayer.java new file mode 100644 index 0000000..3813f68 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/WaterLayer.java @@ -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 . + */ +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; + } + +} diff --git a/src/main/resources/assets/textures/blocks/Mantle.png b/src/main/resources/assets/textures/blocks/Mantle.png new file mode 100644 index 0000000..838daff Binary files /dev/null and b/src/main/resources/assets/textures/blocks/Mantle.png differ diff --git a/src/main/resources/assets/textures/blocks/Water.png b/src/main/resources/assets/textures/blocks/Water.png new file mode 100644 index 0000000..e609712 Binary files /dev/null and b/src/main/resources/assets/textures/blocks/Water.png differ