Basic terrain generation testing
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
4d6278d21f
commit
604380b31e
@ -1,20 +1,5 @@
|
|||||||
{
|
{
|
||||||
"biomes": [
|
"biomes": [
|
||||||
{
|
|
||||||
"id": "sky",
|
|
||||||
"displayName": "Sky",
|
|
||||||
"isAerial": true,
|
|
||||||
"isSurface": false,
|
|
||||||
"isSubterranean": false,
|
|
||||||
"regions": [
|
|
||||||
{
|
|
||||||
"frequency": 1.0,
|
|
||||||
"baseFloorVoxel": 0,
|
|
||||||
"floorVariants": [],
|
|
||||||
"foliageDescription": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "plains",
|
"id": "plains",
|
||||||
"displayName": "Plains",
|
"displayName": "Plains",
|
||||||
@ -36,7 +21,24 @@
|
|||||||
"foliageDescription": [
|
"foliageDescription": [
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"heightGenerator": "plains"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sky",
|
||||||
|
"displayName": "Sky",
|
||||||
|
"isAerial": true,
|
||||||
|
"isSurface": false,
|
||||||
|
"isSubterranean": false,
|
||||||
|
"regions": [
|
||||||
|
{
|
||||||
|
"frequency": 1.0,
|
||||||
|
"baseFloorVoxel": 0,
|
||||||
|
"floorVariants": [],
|
||||||
|
"foliageDescription": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"heightGenerator": "empty"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
10
pom.xml
10
pom.xml
@ -294,12 +294,20 @@
|
|||||||
<version>${lwjgl.version}</version>
|
<version>${lwjgl.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.lwjgl</groupId>
|
<groupId>org.lwjgl</groupId>
|
||||||
<artifactId>lwjgl-yoga</artifactId>
|
<artifactId>lwjgl-yoga</artifactId>
|
||||||
<version>${lwjgl.version}</version>
|
<version>${lwjgl.version}</version>
|
||||||
<classifier>${lwjgl.natives}</classifier>
|
<classifier>${lwjgl.natives}</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--MathUtils-->
|
||||||
|
<!--License: MIT-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.studiorailgun</groupId>
|
||||||
|
<artifactId>MathUtils</artifactId>
|
||||||
|
<version>1.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,11 @@ public class BiomeData {
|
|||||||
*/
|
*/
|
||||||
Boolean isSubterranean;
|
Boolean isSubterranean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag for the heightmap generator to source from
|
||||||
|
*/
|
||||||
|
String heightGenerator;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,5 +91,13 @@ public class BiomeData {
|
|||||||
public Boolean isSubterranean(){
|
public Boolean isSubterranean(){
|
||||||
return isSubterranean;
|
return isSubterranean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tag for the heightmap generator to source from
|
||||||
|
* @return The tag for the heightmap generator to source from
|
||||||
|
*/
|
||||||
|
public String getHeightGenerator(){
|
||||||
|
return heightGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,11 @@ public class BiomeTypeMap {
|
|||||||
*/
|
*/
|
||||||
Map<String,BiomeData> idBiomeMap = new HashMap<String,BiomeData>();
|
Map<String,BiomeData> idBiomeMap = new HashMap<String,BiomeData>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of index -> biome data
|
||||||
|
*/
|
||||||
|
Map<Integer,BiomeData> indexBiomeMap = new HashMap<Integer,BiomeData>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of surface biomes
|
* The list of surface biomes
|
||||||
*/
|
*/
|
||||||
@ -51,6 +56,7 @@ public class BiomeTypeMap {
|
|||||||
if(biome.isSubterranean()){
|
if(biome.isSubterranean()){
|
||||||
this.subterraneanBiomes.add(biome);
|
this.subterraneanBiomes.add(biome);
|
||||||
}
|
}
|
||||||
|
indexBiomeMap.put(indexBiomeMap.size(),biome);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,4 +144,13 @@ public class BiomeTypeMap {
|
|||||||
return this.subterraneanBiomes;
|
return this.subterraneanBiomes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the biome by its index
|
||||||
|
* @param index The index
|
||||||
|
* @return The biome if the index exists, null otherwise
|
||||||
|
*/
|
||||||
|
public BiomeData getBiomeByIndex(int index){
|
||||||
|
return indexBiomeMap.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,7 +150,13 @@ public class ServerWorldData {
|
|||||||
serverWorldData = ServerWorldData.createFixedWorldData(new Vector3d(0),new Vector3d(16 * 4 * 4));
|
serverWorldData = ServerWorldData.createFixedWorldData(new Vector3d(0),new Vector3d(16 * 4 * 4));
|
||||||
serverWorldData.worldSizeDiscrete = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
serverWorldData.worldSizeDiscrete = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
||||||
serverWorldData.worldSizeDiscreteVertical = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
serverWorldData.worldSizeDiscreteVertical = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
||||||
serverTerrainManager = new ServerTerrainManager(serverWorldData, 0, new TestGenerationChunkGenerator());
|
|
||||||
|
//test terrain gen
|
||||||
|
{
|
||||||
|
TestGenerationChunkGenerator chunkGen = new TestGenerationChunkGenerator(serverWorldData);
|
||||||
|
serverTerrainManager = new ServerTerrainManager(serverWorldData, 0, chunkGen);
|
||||||
|
serverTerrainManager.genTestData(chunkGen);
|
||||||
|
}
|
||||||
serverFluidManager = new ServerFluidManager(serverWorldData, serverTerrainManager, 0, new DefaultFluidGenerator());
|
serverFluidManager = new ServerFluidManager(serverWorldData, serverTerrainManager, 0, new DefaultFluidGenerator());
|
||||||
serverWorldData.setManagers(serverTerrainManager, serverFluidManager);
|
serverWorldData.setManagers(serverTerrainManager, serverFluidManager);
|
||||||
return serverWorldData;
|
return serverWorldData;
|
||||||
@ -184,6 +190,16 @@ public class ServerWorldData {
|
|||||||
public float convertChunkToRealSpace(int chunk){
|
public float convertChunkToRealSpace(int chunk){
|
||||||
return chunk * ServerTerrainChunk.CHUNK_DIMENSION;
|
return chunk * ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a chunk space coordinate to a real space coordinate
|
||||||
|
* @param chunk The position within the chunk
|
||||||
|
* @param worldPos The world pos of the chunk
|
||||||
|
* @return The real pos
|
||||||
|
*/
|
||||||
|
public double convertVoxelToRealSpace(int chunk, int worldPos){
|
||||||
|
return chunk + this.convertWorldToReal(worldPos);
|
||||||
|
}
|
||||||
|
|
||||||
public double getRelativeLocation(double real, int world){
|
public double getRelativeLocation(double real, int world){
|
||||||
return real - (world * dynamicInterpolationRatio);
|
return real - (world * dynamicInterpolationRatio);
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
package electrosphere.server.terrain.generation;
|
package electrosphere.server.terrain.generation;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import electrosphere.game.data.biome.BiomeData;
|
||||||
|
import electrosphere.game.server.world.ServerWorldData;
|
||||||
|
import electrosphere.server.terrain.generation.heightmap.EmptySkyGen;
|
||||||
|
import electrosphere.server.terrain.generation.heightmap.HeightmapGenerator;
|
||||||
|
import electrosphere.server.terrain.generation.heightmap.HillsGen;
|
||||||
|
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
||||||
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
import electrosphere.server.terrain.models.TerrainModel;
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
@ -21,6 +29,35 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
*/
|
*/
|
||||||
TerrainModel terrainModel;
|
TerrainModel terrainModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server world data
|
||||||
|
*/
|
||||||
|
ServerWorldData serverWorldData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of generator tag to the generator
|
||||||
|
*/
|
||||||
|
Map<String,HeightmapGenerator> tagGeneratorMap = new HashMap<String,HeightmapGenerator>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public TestGenerationChunkGenerator(ServerWorldData serverWorldData){
|
||||||
|
this.serverWorldData = serverWorldData;
|
||||||
|
registerGenerator(new EmptySkyGen());
|
||||||
|
registerGenerator(new HillsGen());
|
||||||
|
registerGenerator(new PlainsGen());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a heightmap generator
|
||||||
|
* @param generator The heightmap generator
|
||||||
|
*/
|
||||||
|
private void registerGenerator(HeightmapGenerator generator){
|
||||||
|
tagGeneratorMap.put(generator.getTag(),generator);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ) {
|
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ) {
|
||||||
ServerTerrainChunk rVal = null;
|
ServerTerrainChunk rVal = null;
|
||||||
@ -51,11 +88,15 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
//actual generation algo
|
//actual generation algo
|
||||||
weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
|
weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
|
||||||
values = new int[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
|
values = new int[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
|
||||||
|
|
||||||
|
//biome of the current chunk
|
||||||
|
BiomeData biome = this.terrainModel.getSurfaceBiome(worldX, worldY, worldZ);
|
||||||
|
|
||||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
||||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
||||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
||||||
weights[x][y][z] = this.getChunkWeight(worldX, worldY, worldZ, x, y, z, this.terrainModel);
|
weights[x][y][z] = this.getChunkWeight(worldX, worldY, worldZ, x, y, z, this.terrainModel, biome);
|
||||||
values[x][y][z] = this.getChunkValue(worldX, worldY, worldZ, x, y, z, this.terrainModel);
|
values[x][y][z] = this.getChunkValue(worldX, worldY, worldZ, x, y, z, this.terrainModel, biome);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,10 +121,30 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
* @param chunkY The chunk y pos
|
* @param chunkY The chunk y pos
|
||||||
* @param chunkZ The chunk z pos
|
* @param chunkZ The chunk z pos
|
||||||
* @param terrainModel The terrain model
|
* @param terrainModel The terrain model
|
||||||
|
* @param surfaceBiome The surface biome of the chunk
|
||||||
* @return The value of the chunk
|
* @return The value of the chunk
|
||||||
*/
|
*/
|
||||||
private int getChunkValue(int worldX, int worldY, int worldZ, int chunkX, int chunkY, int chunkZ, TerrainModel terrainModel){
|
private int getChunkValue(
|
||||||
return 1;
|
int worldX, int worldY, int worldZ,
|
||||||
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
TerrainModel terrainModel,
|
||||||
|
BiomeData surfaceBiome
|
||||||
|
){
|
||||||
|
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceBiome.getHeightGenerator());
|
||||||
|
if(heightmapGen == null){
|
||||||
|
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceBiome.getHeightGenerator());
|
||||||
|
}
|
||||||
|
|
||||||
|
double realX = this.serverWorldData.convertVoxelToRealSpace(chunkX,worldX);
|
||||||
|
double realY = this.serverWorldData.convertVoxelToRealSpace(chunkY,worldY);
|
||||||
|
double realZ = this.serverWorldData.convertVoxelToRealSpace(chunkZ,worldZ);
|
||||||
|
|
||||||
|
float surfaceHeight = heightmapGen.getHeight(terrainModel.getSeed(), realX, realZ);
|
||||||
|
if(realY <= surfaceHeight){
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,10 +156,33 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
* @param chunkY The chunk y pos
|
* @param chunkY The chunk y pos
|
||||||
* @param chunkZ The chunk z pos
|
* @param chunkZ The chunk z pos
|
||||||
* @param terrainModel The terrain model
|
* @param terrainModel The terrain model
|
||||||
|
* @param surfaceBiome The surface biome of the chunk
|
||||||
* @return The weight of the chunk
|
* @return The weight of the chunk
|
||||||
*/
|
*/
|
||||||
private float getChunkWeight(int worldX, int worldY, int worldZ, int chunkX, int chunkY, int chunkZ, TerrainModel terrainModel){
|
private float getChunkWeight(
|
||||||
return 0.1f;
|
int worldX, int worldY, int worldZ,
|
||||||
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
TerrainModel terrainModel,
|
||||||
|
BiomeData surfaceBiome
|
||||||
|
){
|
||||||
|
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceBiome.getHeightGenerator());
|
||||||
|
if(heightmapGen == null){
|
||||||
|
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceBiome.getHeightGenerator());
|
||||||
|
}
|
||||||
|
|
||||||
|
double realX = this.serverWorldData.convertVoxelToRealSpace(chunkX,worldX);
|
||||||
|
double realY = this.serverWorldData.convertVoxelToRealSpace(chunkY,worldY);
|
||||||
|
double realZ = this.serverWorldData.convertVoxelToRealSpace(chunkZ,worldZ);
|
||||||
|
|
||||||
|
float surfaceHeight = heightmapGen.getHeight(terrainModel.getSeed(), realX, realZ);
|
||||||
|
double flooredSurfaceHeight = Math.floor(surfaceHeight);
|
||||||
|
if(realY < flooredSurfaceHeight){
|
||||||
|
return 1;
|
||||||
|
} else if(realY > flooredSurfaceHeight) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return (float)(surfaceHeight - flooredSurfaceHeight) * 2 - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,15 @@
|
|||||||
|
package electrosphere.server.terrain.generation.heightmap;
|
||||||
|
|
||||||
|
public class EmptySkyGen implements HeightmapGenerator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getHeight(long SEED, double x, double y) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return "empty";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package electrosphere.server.terrain.generation.heightmap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates height values for terrain
|
||||||
|
*/
|
||||||
|
public interface HeightmapGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the height of a given position, given a SEED value
|
||||||
|
* @param SEED The seed for the terrain
|
||||||
|
* @param x The x value
|
||||||
|
* @param y The y value
|
||||||
|
* @return The height
|
||||||
|
*/
|
||||||
|
public float getHeight(long SEED, double x, double y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tag associated with this generator
|
||||||
|
* @return The tag
|
||||||
|
*/
|
||||||
|
public String getTag();
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
package electrosphere.server.terrain.generation.heightmap;
|
||||||
|
|
||||||
|
import electrosphere.util.noise.OpenSimplex2S;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates hilly heightmaps
|
||||||
|
*/
|
||||||
|
public class HillsGen implements HeightmapGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset from baseline to place the noisemap at
|
||||||
|
*/
|
||||||
|
static final float HEIGHT_OFFSET = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The different scales of noise to sample from
|
||||||
|
*/
|
||||||
|
static final double[][] GRAD_NOISE = new double[][]{
|
||||||
|
{0.01, 2.0},
|
||||||
|
{0.02, 2.0},
|
||||||
|
{0.05, 1.0},
|
||||||
|
{0.1, 1.0},
|
||||||
|
{0.3, 1.0},
|
||||||
|
};
|
||||||
|
|
||||||
|
//distance from origin to sample for gradient calculation
|
||||||
|
public static float GRADIENT_DIST = 0.01f;
|
||||||
|
|
||||||
|
//param for controlling how pointer the initial layers are
|
||||||
|
public static float GRAD_INFLUENCE_DROPOFF = 0.35f;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the height at a given position for this generation approach
|
||||||
|
* @param SEED The seed
|
||||||
|
* @param x The x position
|
||||||
|
* @param y The y position
|
||||||
|
* @return The height
|
||||||
|
*/
|
||||||
|
public float getHeight(long SEED, double x, double y){
|
||||||
|
return gradientHeight(SEED, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a gradient approach to heightfield generation
|
||||||
|
* @param SEED The seed
|
||||||
|
* @param x The x value
|
||||||
|
* @param y The y value
|
||||||
|
* @return The elevation at x,y
|
||||||
|
*/
|
||||||
|
static float gradientHeight(long SEED, double x, double y){
|
||||||
|
float rVal = 0;
|
||||||
|
|
||||||
|
float gradXAccum = 0;
|
||||||
|
float gradYAccum = 0;
|
||||||
|
for(int n = 0; n < GRAD_NOISE.length; n++){
|
||||||
|
//get noise samples
|
||||||
|
float noiseOrigin = (float)(OpenSimplex2S.noise2_ImproveX(SEED, x * GRAD_NOISE[n][0], y * GRAD_NOISE[n][0]) * GRAD_NOISE[n][1]);
|
||||||
|
float noiseX = (float)(OpenSimplex2S.noise2_ImproveX(SEED, x * GRAD_NOISE[n][0] + GRADIENT_DIST, y * GRAD_NOISE[n][0]) * GRAD_NOISE[n][1]);
|
||||||
|
float noiseY = (float)(OpenSimplex2S.noise2_ImproveX(SEED, x * GRAD_NOISE[n][0], y * GRAD_NOISE[n][0] + GRADIENT_DIST) * GRAD_NOISE[n][1]);
|
||||||
|
//calculate gradient accumulation
|
||||||
|
float gradX = (noiseX - noiseOrigin) / GRADIENT_DIST;
|
||||||
|
float gradY = (noiseY - noiseOrigin) / GRADIENT_DIST;
|
||||||
|
gradXAccum = gradXAccum + gradX;
|
||||||
|
gradYAccum = gradYAccum + gradY;
|
||||||
|
//determine current noise's influence based on gradient
|
||||||
|
float gradientMagnitude = (float)Math.sqrt(gradXAccum * gradXAccum + gradYAccum * gradYAccum);
|
||||||
|
float influence = 1.0f / (1.0f + gradientMagnitude * GRAD_INFLUENCE_DROPOFF);
|
||||||
|
|
||||||
|
//add to height
|
||||||
|
rVal = rVal + (float)(OpenSimplex2S.noise2_ImproveX(SEED, x * GRAD_NOISE[n][0], y * GRAD_NOISE[n][0]) * GRAD_NOISE[n][1]) * influence;
|
||||||
|
}
|
||||||
|
rVal = rVal + HEIGHT_OFFSET;
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return "hills";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
package electrosphere.server.terrain.generation.heightmap;
|
||||||
|
|
||||||
|
import electrosphere.util.noise.OpenSimplex2S;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator for plains
|
||||||
|
*/
|
||||||
|
public class PlainsGen implements HeightmapGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset from baseline to place the noisemap at
|
||||||
|
*/
|
||||||
|
static final float HEIGHT_OFFSET = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scale to apply to the coordinates
|
||||||
|
*/
|
||||||
|
static final float GEN_SCALE = 0.2f;
|
||||||
|
|
||||||
|
//the different scales of noise to sample from
|
||||||
|
static final double[][] NOISE_SCALES = new double[][]{
|
||||||
|
{0.01, 3.0},
|
||||||
|
{0.02, 2.0},
|
||||||
|
{0.05, 0.8},
|
||||||
|
{0.1, 0.3},
|
||||||
|
{0.3, 0.2},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the height at a given position for this generation approach
|
||||||
|
* @param SEED The seed
|
||||||
|
* @param x The x position
|
||||||
|
* @param y The y position
|
||||||
|
* @return The height
|
||||||
|
*/
|
||||||
|
public float getHeight(long SEED, double x, double y){
|
||||||
|
return sampleAllNoise(SEED, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Samples all noise values directly
|
||||||
|
* @param SEED The seed
|
||||||
|
* @param x The x value
|
||||||
|
* @param y The y value
|
||||||
|
* @return The elevation at x,y
|
||||||
|
*/
|
||||||
|
static float sampleAllNoise(long SEED, double x, double y){
|
||||||
|
float rVal = 0;
|
||||||
|
double scaledX = x * GEN_SCALE;
|
||||||
|
double scaledY = y * GEN_SCALE;
|
||||||
|
for(int n = 0; n < NOISE_SCALES.length; n++){
|
||||||
|
rVal = rVal + (float)(OpenSimplex2S.noise2_ImproveX(SEED, scaledX * NOISE_SCALES[n][0], scaledY * NOISE_SCALES[n][0]) * NOISE_SCALES[n][1]);
|
||||||
|
}
|
||||||
|
rVal = rVal + HEIGHT_OFFSET;
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return "plains";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package electrosphere.server.terrain.manager;
|
|||||||
|
|
||||||
import electrosphere.game.server.world.ServerWorldData;
|
import electrosphere.game.server.world.ServerWorldData;
|
||||||
import electrosphere.server.terrain.diskmap.ChunkDiskMap;
|
import electrosphere.server.terrain.diskmap.ChunkDiskMap;
|
||||||
|
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
|
||||||
import electrosphere.server.terrain.generation.continentphase.TerrainGenerator;
|
import electrosphere.server.terrain.generation.continentphase.TerrainGenerator;
|
||||||
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
||||||
import electrosphere.server.terrain.models.TerrainModel;
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
@ -151,6 +152,15 @@ public class ServerTerrainManager {
|
|||||||
chunkDiskMap = new ChunkDiskMap();
|
chunkDiskMap = new ChunkDiskMap();
|
||||||
chunkDiskMap.init(saveName);
|
chunkDiskMap.init(saveName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a test terrain model
|
||||||
|
* @param chunkGen The chunk generator
|
||||||
|
*/
|
||||||
|
public void genTestData(TestGenerationChunkGenerator chunkGen){
|
||||||
|
this.model = TerrainModel.generateTestModel();
|
||||||
|
chunkGen.setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
public float[][] getTerrainAtChunk(int x, int y){
|
public float[][] getTerrainAtChunk(int x, int y){
|
||||||
return model.getElevationForChunk(x, y);
|
return model.getElevationForChunk(x, y);
|
||||||
|
|||||||
@ -5,12 +5,19 @@ import java.util.Map;
|
|||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.game.data.biome.BiomeData;
|
import electrosphere.game.data.biome.BiomeData;
|
||||||
|
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
|
||||||
import electrosphere.util.annotation.Exclude;
|
import electrosphere.util.annotation.Exclude;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The model of the terrain
|
* The model of the terrain
|
||||||
*/
|
*/
|
||||||
public class TerrainModel {
|
public class TerrainModel {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scale of the macro data
|
||||||
|
*/
|
||||||
|
static final int MACRO_DATA_SCALE = 32;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,6 +40,12 @@ public class TerrainModel {
|
|||||||
*/
|
*/
|
||||||
@Exclude
|
@Exclude
|
||||||
private float[][] elevation;
|
private float[][] elevation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The macro level biome data
|
||||||
|
*/
|
||||||
|
@Exclude
|
||||||
|
private short[][] biome;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The real coordinate mountain threshold
|
* The real coordinate mountain threshold
|
||||||
@ -48,6 +61,11 @@ public class TerrainModel {
|
|||||||
* The map of modifications applied to the model
|
* The map of modifications applied to the model
|
||||||
*/
|
*/
|
||||||
Map<String,ModificationList> modifications;
|
Map<String,ModificationList> modifications;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The seed of the terrain
|
||||||
|
*/
|
||||||
|
long seed = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor
|
* Private constructor
|
||||||
@ -92,6 +110,18 @@ public class TerrainModel {
|
|||||||
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
|
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a test terrain model
|
||||||
|
* @return The test terrain model
|
||||||
|
*/
|
||||||
|
public static TerrainModel generateTestModel(){
|
||||||
|
TerrainModel rVal = new TerrainModel();
|
||||||
|
rVal.discreteArrayDimension = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
||||||
|
rVal.dynamicInterpolationRatio = 1;
|
||||||
|
rVal.biome = new short[2][2];
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the macro elevation data for the terrain model
|
* Gets the macro elevation data for the terrain model
|
||||||
@ -460,14 +490,26 @@ public class TerrainModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the biome for a given world position
|
* Gets the surface biome for a given world position
|
||||||
* @param worldX The world X
|
* @param worldX The world X
|
||||||
* @param worldY The world Y
|
* @param worldY The world Y
|
||||||
* @param worldZ The world Z
|
* @param worldZ The world Z
|
||||||
* @return The biome
|
* @return The biome
|
||||||
*/
|
*/
|
||||||
public BiomeData getBiome(int worldX, int worldY, int worldZ){
|
public BiomeData getSurfaceBiome(int worldX, int worldY, int worldZ){
|
||||||
return Globals.gameConfigCurrent.getBiomeMap().getTypes().iterator().next();
|
int macroX = worldX / MACRO_DATA_SCALE;
|
||||||
|
int macroZ = worldZ / MACRO_DATA_SCALE;
|
||||||
|
int surfaceBiomeIndex = this.biome[macroX][macroZ];
|
||||||
|
BiomeData biome = Globals.gameConfigCurrent.getBiomeMap().getBiomeByIndex(surfaceBiomeIndex);
|
||||||
|
return biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the seed of the terrain model
|
||||||
|
* @return The seed
|
||||||
|
*/
|
||||||
|
public long getSeed(){
|
||||||
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user