Noise definitions in data files
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
a44255060d
commit
3a9eb0591d
7
assets/Data/game/voxel/test1.json
Normal file
7
assets/Data/game/voxel/test1.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name" : "test1",
|
||||||
|
"sampler" : {
|
||||||
|
"name" : "Invoke",
|
||||||
|
"target" : "test2"
|
||||||
|
}
|
||||||
|
}
|
||||||
36
assets/Data/game/voxel/test2.json
Normal file
36
assets/Data/game/voxel/test2.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name" : "test2",
|
||||||
|
"sampler" :{
|
||||||
|
"name" : "DomainWarp",
|
||||||
|
"x" : {
|
||||||
|
"name" : "Mul",
|
||||||
|
"first" : {
|
||||||
|
"name" : "Const",
|
||||||
|
"value" : 0.02
|
||||||
|
},
|
||||||
|
"second" : {
|
||||||
|
"name" : "OpenSimplex"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"z" : {
|
||||||
|
"name" : "Mul",
|
||||||
|
"first" : {
|
||||||
|
"name" : "Const",
|
||||||
|
"value" : 0.02
|
||||||
|
},
|
||||||
|
"second" : {
|
||||||
|
"name" : "OpenSimplex"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source" : {
|
||||||
|
"name" : "Add",
|
||||||
|
"first" : {
|
||||||
|
"name" : "Const",
|
||||||
|
"value" : 1.0
|
||||||
|
},
|
||||||
|
"second" : {
|
||||||
|
"name" : "OpenSimplex"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1065,6 +1065,16 @@ Fix flickering chunks on unload
|
|||||||
Fix draw cell distance cache busting on far distances
|
Fix draw cell distance cache busting on far distances
|
||||||
Fix skybox not updating position with player entity
|
Fix skybox not updating position with player entity
|
||||||
Add Scene shorthand for registering runnables as behavior trees
|
Add Scene shorthand for registering runnables as behavior trees
|
||||||
|
Re-integrate frame time tracking
|
||||||
|
Solve y last in chunkgen to optimize height calc
|
||||||
|
|
||||||
|
(11/18/2024)
|
||||||
|
Defining noise functions in config files
|
||||||
|
Invoking noise functions from noise functions
|
||||||
|
Voxel and Heightmap generators based on noise functions in files
|
||||||
|
Set all client terrain rigid bodies are kinematic
|
||||||
|
Add caves
|
||||||
|
Tweaking test2 noise definition
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
pom.xml
4
pom.xml
@ -7,8 +7,8 @@
|
|||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
<lwjgl.version>3.3.3</lwjgl.version>
|
<lwjgl.version>3.3.3</lwjgl.version>
|
||||||
<joml.version>1.9.19</joml.version>
|
<joml.version>1.9.19</joml.version>
|
||||||
<recast.version>1.5.7</recast.version>
|
<recast.version>1.5.7</recast.version>
|
||||||
|
|||||||
@ -133,8 +133,8 @@ public class ClientTerrainManager {
|
|||||||
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
|
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
|
||||||
FloatBuffer floatBuffer = buffer.asFloatBuffer();
|
FloatBuffer floatBuffer = buffer.asFloatBuffer();
|
||||||
for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){
|
for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){
|
||||||
for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){
|
for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){
|
||||||
for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){
|
for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){
|
||||||
weights[x][y][z] = floatBuffer.get();
|
weights[x][y][z] = floatBuffer.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,8 +144,8 @@ public class ClientTerrainManager {
|
|||||||
int firstType = -1;
|
int firstType = -1;
|
||||||
boolean homogenous = true;
|
boolean homogenous = true;
|
||||||
for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){
|
for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){
|
||||||
for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){
|
for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){
|
||||||
for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){
|
for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){
|
||||||
values[x][y][z] = intView.get();
|
values[x][y][z] = intView.get();
|
||||||
if(firstType == -1){
|
if(firstType == -1){
|
||||||
firstType = values[x][y][z];
|
firstType = values[x][y][z];
|
||||||
|
|||||||
@ -481,14 +481,12 @@ public class PhysicsEntityUtils {
|
|||||||
* @param data The terrain description
|
* @param data The terrain description
|
||||||
* @return The rigid body created (note, attachment has already been performed)
|
* @return The rigid body created (note, attachment has already been performed)
|
||||||
*/
|
*/
|
||||||
public static DBody clientAttachTerrainChunkRigidBody(Entity terrain, TerrainChunkData data){
|
public static void clientAttachTerrainChunkRigidBody(Entity terrain, TerrainChunkData data){
|
||||||
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT);
|
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT);
|
||||||
|
if(terrainBody != null){
|
||||||
|
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_TERRAIN, false));
|
||||||
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_TERRAIN, false));
|
PhysicsEntityUtils.setDBody(terrain,terrainBody);
|
||||||
PhysicsEntityUtils.setDBody(terrain,terrainBody);
|
}
|
||||||
|
|
||||||
return terrainBody;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -514,6 +512,9 @@ public class PhysicsEntityUtils {
|
|||||||
*/
|
*/
|
||||||
public static void serverRepositionEntities(CollisionEngine collisionEngine){
|
public static void serverRepositionEntities(CollisionEngine collisionEngine){
|
||||||
List<Entity> toReposition = new LinkedList<Entity>();
|
List<Entity> toReposition = new LinkedList<Entity>();
|
||||||
|
if(collisionEngine.getCollidables() == null){
|
||||||
|
throw new Error("Collision engine collidables are null!");
|
||||||
|
}
|
||||||
for(Collidable collidable : collisionEngine.getCollidables()){
|
for(Collidable collidable : collisionEngine.getCollidables()){
|
||||||
Entity entity = collidable.getParent();
|
Entity entity = collidable.getParent();
|
||||||
DBody body = PhysicsEntityUtils.getDBody(entity);
|
DBody body = PhysicsEntityUtils.getDBody(entity);
|
||||||
|
|||||||
@ -428,6 +428,12 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// F R A M E T I M E T R A C K I NG
|
||||||
|
///
|
||||||
|
ImGuiWindowMacros.addGlobalFramerateDatapoint("totalframerate", Globals.timekeeper.getMostRecentRawFrametime());
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// E N D M A I N L O O P
|
/// E N D M A I N L O O P
|
||||||
///
|
///
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import electrosphere.game.data.tutorial.HintDefinition;
|
|||||||
import electrosphere.game.data.units.UnitDefinitionFile;
|
import electrosphere.game.data.units.UnitDefinitionFile;
|
||||||
import electrosphere.game.data.units.UnitLoader;
|
import electrosphere.game.data.units.UnitLoader;
|
||||||
import electrosphere.game.data.voxel.VoxelData;
|
import electrosphere.game.data.voxel.VoxelData;
|
||||||
|
import electrosphere.game.data.voxel.sampler.SamplerFile;
|
||||||
import electrosphere.game.server.race.model.RaceMap;
|
import electrosphere.game.server.race.model.RaceMap;
|
||||||
import electrosphere.game.server.symbolism.model.SymbolMap;
|
import electrosphere.game.server.symbolism.model.SymbolMap;
|
||||||
import electrosphere.util.FileUtils;
|
import electrosphere.util.FileUtils;
|
||||||
@ -66,6 +67,11 @@ public class Config {
|
|||||||
* The biome map
|
* The biome map
|
||||||
*/
|
*/
|
||||||
BiomeTypeMap biomeMap;
|
BiomeTypeMap biomeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of sampler definitions
|
||||||
|
*/
|
||||||
|
List<SamplerFile> samplerDefinitions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the default data
|
* Loads the default data
|
||||||
@ -87,6 +93,7 @@ public class Config {
|
|||||||
config.unitLoader = UnitLoader.create(FileUtils.loadObjectFromAssetPath("Data/game/units/units.json", UnitDefinitionFile.class));
|
config.unitLoader = UnitLoader.create(FileUtils.loadObjectFromAssetPath("Data/game/units/units.json", UnitDefinitionFile.class));
|
||||||
config.recipeMap = RecipeDataMap.loadRecipeFiles("Data/game/recipes.json");
|
config.recipeMap = RecipeDataMap.loadRecipeFiles("Data/game/recipes.json");
|
||||||
config.biomeMap = BiomeTypeMap.loadBiomeFile("Data/game/biomes.json");
|
config.biomeMap = BiomeTypeMap.loadBiomeFile("Data/game/biomes.json");
|
||||||
|
config.samplerDefinitions = SamplerFile.readSamplerDefinitionFiles("Data/game/voxel");
|
||||||
|
|
||||||
//create furniture items
|
//create furniture items
|
||||||
ItemDataMap.loadSpawnItems(config.itemMap, config.objectTypeLoader);
|
ItemDataMap.loadSpawnItems(config.itemMap, config.objectTypeLoader);
|
||||||
@ -282,5 +289,13 @@ public class Config {
|
|||||||
public BiomeTypeMap getBiomeMap(){
|
public BiomeTypeMap getBiomeMap(){
|
||||||
return biomeMap;
|
return biomeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of all sampler files
|
||||||
|
* @return The list of all sampler files
|
||||||
|
*/
|
||||||
|
public List<SamplerFile> getSamplerFiles(){
|
||||||
|
return this.samplerDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,112 @@
|
|||||||
|
package electrosphere.game.data.voxel.sampler;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperoatorInvoke;
|
||||||
|
import electrosphere.util.FileUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sampler definition file
|
||||||
|
*/
|
||||||
|
public class SamplerFile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this sampler type
|
||||||
|
*/
|
||||||
|
String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sample to pull from
|
||||||
|
*/
|
||||||
|
NoiseSampler sampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the file
|
||||||
|
* @return The name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the sampler for this file
|
||||||
|
* @return The sampler
|
||||||
|
*/
|
||||||
|
public NoiseSampler getSampler() {
|
||||||
|
return sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the sampler definition files
|
||||||
|
* @return The list of sampler definition files
|
||||||
|
*/
|
||||||
|
public static List<SamplerFile> readSamplerDefinitionFiles(String initialPath){
|
||||||
|
File initialDirectory = FileUtils.getAssetFile(initialPath);
|
||||||
|
List<SamplerFile> rVal = new LinkedList<SamplerFile>();
|
||||||
|
|
||||||
|
//read the files in
|
||||||
|
SamplerFile.recursivelyReadSamplerDefinitionFiles(initialDirectory, rVal);
|
||||||
|
|
||||||
|
//link invoke targets
|
||||||
|
for(SamplerFile file : rVal){
|
||||||
|
SamplerFile.linkInvokeTargets(rVal, file.getSampler());
|
||||||
|
}
|
||||||
|
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively reads from the root all sampler files
|
||||||
|
* @param rootDir The root dir
|
||||||
|
* @param appendTarget The list to add sampler files to
|
||||||
|
*/
|
||||||
|
private static void recursivelyReadSamplerDefinitionFiles(File rootDir, List<SamplerFile> appendTarget){
|
||||||
|
if(rootDir == null || !rootDir.isDirectory()){
|
||||||
|
throw new Error("Invalid path provided! " + rootDir.getAbsolutePath());
|
||||||
|
}
|
||||||
|
if(rootDir == null || !rootDir.exists() || rootDir.listFiles() == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(File child : rootDir.listFiles()){
|
||||||
|
if(child.isDirectory()){
|
||||||
|
SamplerFile.recursivelyReadSamplerDefinitionFiles(child, appendTarget);
|
||||||
|
} else {
|
||||||
|
SamplerFile file = FileUtils.loadObjectFromFile(child, SamplerFile.class);
|
||||||
|
appendTarget.add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Links all invoke targets to their respective samplers
|
||||||
|
* @param files The list of all sampler files
|
||||||
|
* @param current The current sampler function to evaluate
|
||||||
|
*/
|
||||||
|
private static void linkInvokeTargets(List<SamplerFile> files, NoiseSampler current){
|
||||||
|
if(current instanceof NoiseOperoatorInvoke){
|
||||||
|
NoiseOperoatorInvoke invoker = (NoiseOperoatorInvoke)current;
|
||||||
|
String target = invoker.getTarget();
|
||||||
|
if(target.equals(current.getName())){
|
||||||
|
throw new Error("Invoke module pointing at itself!");
|
||||||
|
}
|
||||||
|
for(SamplerFile file : files){
|
||||||
|
if(file.getName().equals(target)){
|
||||||
|
invoker.setInvokeSampler(file.getSampler());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(invoker.getInvokeSampler() == null){
|
||||||
|
throw new Error("Failed to link " + target);
|
||||||
|
}
|
||||||
|
} else if(current instanceof NoiseContainer){
|
||||||
|
for(NoiseSampler child : ((NoiseContainer)current).getChildren()){
|
||||||
|
SamplerFile.linkInvokeTargets(files, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -229,8 +229,8 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
|
|||||||
FloatBuffer floatView = buffer.asFloatBuffer();
|
FloatBuffer floatView = buffer.asFloatBuffer();
|
||||||
|
|
||||||
for(int x = 0; x < xWidth; x++){
|
for(int x = 0; x < xWidth; x++){
|
||||||
for(int y = 0; y < yWidth; y++){
|
for(int z = 0; z < zWidth; z++){
|
||||||
for(int z = 0; z < zWidth; z++){
|
for(int y = 0; y < yWidth; y++){
|
||||||
floatView.put(chunk.getWeights()[x][y][z]);
|
floatView.put(chunk.getWeights()[x][y][z]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,8 +240,8 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
|
|||||||
intView.position(floatView.position());
|
intView.position(floatView.position());
|
||||||
|
|
||||||
for(int x = 0; x < xWidth; x++){
|
for(int x = 0; x < xWidth; x++){
|
||||||
for(int y = 0; y < yWidth; y++){
|
for(int z = 0; z < zWidth; z++){
|
||||||
for(int z = 0; z < zWidth; z++){
|
for(int y = 0; y < yWidth; y++){
|
||||||
intView.put(chunk.getValues()[x][y][z]);
|
intView.put(chunk.getValues()[x][y][z]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package electrosphere.script;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import org.graalvm.polyglot.Context;
|
import org.graalvm.polyglot.Context;
|
||||||
@ -376,7 +377,15 @@ public class ScriptContext {
|
|||||||
* @param function The function
|
* @param function The function
|
||||||
*/
|
*/
|
||||||
public void executeSynchronously(Runnable function){
|
public void executeSynchronously(Runnable function){
|
||||||
lock.lock();
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
success = lock.tryLock(1, TimeUnit.MICROSECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LoggerInterface.loggerScripts.ERROR(e);
|
||||||
|
}
|
||||||
|
if(!success){
|
||||||
|
throw new Error("Failed to acquire lock!");
|
||||||
|
}
|
||||||
function.run();
|
function.run();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
/**
|
/**
|
||||||
* The number of frames without players that must pass before a server data cell is unloaded
|
* The number of frames without players that must pass before a server data cell is unloaded
|
||||||
*/
|
*/
|
||||||
static final int UNLOAD_FRAME_THRESHOLD = 100;
|
static final int UNLOAD_FRAME_THRESHOLD = 500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks whether this manager has been flagged to unload cells or not
|
* Tracks whether this manager has been flagged to unload cells or not
|
||||||
|
|||||||
@ -0,0 +1,241 @@
|
|||||||
|
package electrosphere.server.terrain.generation;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import electrosphere.client.terrain.cache.ChunkData;
|
||||||
|
|
||||||
|
import org.graalvm.polyglot.Value;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.game.data.biome.BiomeData;
|
||||||
|
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
|
||||||
|
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.MountainGen;
|
||||||
|
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
||||||
|
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
||||||
|
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
|
||||||
|
import electrosphere.server.terrain.generation.voxelphase.AnimeMountainsGen;
|
||||||
|
import electrosphere.server.terrain.generation.voxelphase.HillsVoxelGen;
|
||||||
|
import electrosphere.server.terrain.generation.voxelphase.MountainVoxelGen;
|
||||||
|
import electrosphere.server.terrain.generation.voxelphase.VoxelGenerator;
|
||||||
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedicated script-based chunk generator
|
||||||
|
*/
|
||||||
|
public class JSChunkGenerator implements ChunkGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the realm for testing generation
|
||||||
|
*/
|
||||||
|
public static final int GENERATOR_REALM_SIZE = 512;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default biome index
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_BIOME_INDEX = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The width of the surface in number of voxels
|
||||||
|
*/
|
||||||
|
public static final int SURFACE_VOXEL_WIDTH = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag for the test generator
|
||||||
|
*/
|
||||||
|
public static final String SCRIPT_GEN_TEST_TAG = "test";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls the default setting for whether to use javascript or not
|
||||||
|
*/
|
||||||
|
public static final boolean DEFAULT_USE_JAVASCRIPT = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The terreain model for the generator
|
||||||
|
*/
|
||||||
|
TerrainModel terrainModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server world data
|
||||||
|
*/
|
||||||
|
ServerWorldData serverWorldData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of generator tag to the heightmap generator
|
||||||
|
*/
|
||||||
|
Map<String,HeightmapGenerator> tagHeightmapMap = new HashMap<String,HeightmapGenerator>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of generator tag to voxel generator
|
||||||
|
*/
|
||||||
|
Map<String,VoxelGenerator> tagVoxelMap = new HashMap<String,VoxelGenerator>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks whether to use javascript generation or not
|
||||||
|
*/
|
||||||
|
boolean useJavascript = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public JSChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
|
||||||
|
this.serverWorldData = serverWorldData;
|
||||||
|
this.registerHeightmapGenerator(new EmptySkyGen());
|
||||||
|
this.registerHeightmapGenerator(new HillsGen());
|
||||||
|
this.registerHeightmapGenerator(new PlainsGen());
|
||||||
|
this.registerHeightmapGenerator(new MountainGen());
|
||||||
|
this.registerVoxelGenerator(new HillsVoxelGen());
|
||||||
|
this.registerVoxelGenerator(new AnimeMountainsGen());
|
||||||
|
this.registerVoxelGenerator(new MountainVoxelGen());
|
||||||
|
this.useJavascript = useJavascript;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a heightmap generator
|
||||||
|
* @param generator The heightmap generator
|
||||||
|
*/
|
||||||
|
private void registerHeightmapGenerator(HeightmapGenerator generator){
|
||||||
|
tagHeightmapMap.put(generator.getTag(),generator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a voxel generator
|
||||||
|
* @param generator The voxel generator
|
||||||
|
*/
|
||||||
|
private void registerVoxelGenerator(VoxelGenerator generator){
|
||||||
|
tagVoxelMap.put(generator.getTag(),generator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) {
|
||||||
|
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.generateChunk");
|
||||||
|
ServerTerrainChunk rVal = new ServerTerrainChunk(worldX, worldY, worldZ);
|
||||||
|
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];;
|
||||||
|
int[][][] values = new int[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
|
||||||
|
|
||||||
|
try {
|
||||||
|
//biome of the current chunk
|
||||||
|
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
||||||
|
|
||||||
|
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
||||||
|
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
|
||||||
|
heightmapGen = this.tagHeightmapMap.get("hills");
|
||||||
|
if(heightmapGen == null){
|
||||||
|
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
//stride value
|
||||||
|
int strideValue = (int)Math.pow(2,stride);
|
||||||
|
|
||||||
|
//presolve heightfield
|
||||||
|
float[][] heightfield = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
|
||||||
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||||
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||||
|
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
|
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
|
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
heightfield[x][z] = heightmapGen.getHeight(
|
||||||
|
this.terrainModel.getSeed(),
|
||||||
|
this.serverWorldData.convertVoxelToRealSpace(finalChunkX, finalWorldX),
|
||||||
|
this.serverWorldData.convertVoxelToRealSpace(finalChunkZ, finalWorldZ)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float[][] gradientField = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
|
||||||
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||||
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||||
|
float deltaX = 0;
|
||||||
|
float deltaZ = 0;
|
||||||
|
if(x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1){
|
||||||
|
deltaX = Math.abs(heightfield[x][z] - heightfield[x+1][z]);
|
||||||
|
} else {
|
||||||
|
deltaX = Math.abs(heightfield[x][z] - heightfield[x-1][z]);
|
||||||
|
}
|
||||||
|
if(z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1){
|
||||||
|
deltaX = Math.abs(heightfield[x][z] - heightfield[x][z+1]);
|
||||||
|
} else {
|
||||||
|
deltaX = Math.abs(heightfield[x][z] - heightfield[x][z-1]);
|
||||||
|
}
|
||||||
|
gradientField[x][z] = deltaX * deltaX + deltaZ * deltaZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Globals.scriptEngine.getScriptContext().executeSynchronously(() -> {
|
||||||
|
int firstType = -2;
|
||||||
|
boolean homogenous = true;
|
||||||
|
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||||
|
Value getVoxelFunc = Globals.scriptEngine.getScriptContext().invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
|
||||||
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||||
|
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
||||||
|
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||||
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||||
|
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
|
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
|
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
|
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
getVoxelFunc.execute(
|
||||||
|
voxel,
|
||||||
|
finalWorldX, finalWorldY, finalWorldZ,
|
||||||
|
finalChunkX, finalChunkY, finalChunkZ,
|
||||||
|
stride,
|
||||||
|
heightfield[x][z],
|
||||||
|
surfaceBiome
|
||||||
|
);
|
||||||
|
weights[x][y][z] = voxel.weight;
|
||||||
|
values[x][y][z] = voxel.type;
|
||||||
|
if(firstType == -2){
|
||||||
|
firstType = values[x][y][z];
|
||||||
|
} else if(homogenous && firstType != values[x][y][z]){
|
||||||
|
homogenous = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
}
|
||||||
|
if(homogenous){
|
||||||
|
rVal.setHomogenousValue(firstType);
|
||||||
|
} else {
|
||||||
|
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
|
||||||
|
}
|
||||||
|
rVal.setWeights(weights);
|
||||||
|
rVal.setValues(values);
|
||||||
|
});
|
||||||
|
} catch(Exception ex){
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getElevation(int worldX, int worldZ, int chunkX, int chunkZ){
|
||||||
|
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
||||||
|
|
||||||
|
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
||||||
|
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
|
||||||
|
if(heightmapGen == null){
|
||||||
|
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
|
||||||
|
}
|
||||||
|
double rVal = heightmapGen.getHeight(
|
||||||
|
this.terrainModel.getSeed(),
|
||||||
|
this.serverWorldData.convertVoxelToRealSpace(chunkX, worldX),
|
||||||
|
this.serverWorldData.convertVoxelToRealSpace(chunkZ, worldZ)
|
||||||
|
);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setModel(TerrainModel model) {
|
||||||
|
this.terrainModel = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,14 +5,14 @@ import java.util.Map;
|
|||||||
|
|
||||||
import electrosphere.client.terrain.cache.ChunkData;
|
import electrosphere.client.terrain.cache.ChunkData;
|
||||||
|
|
||||||
import org.graalvm.polyglot.Value;
|
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.game.data.biome.BiomeData;
|
import electrosphere.game.data.biome.BiomeData;
|
||||||
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
|
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
|
||||||
|
import electrosphere.game.data.voxel.sampler.SamplerFile;
|
||||||
import electrosphere.game.server.world.ServerWorldData;
|
import electrosphere.game.server.world.ServerWorldData;
|
||||||
import electrosphere.server.terrain.generation.heightmap.EmptySkyGen;
|
import electrosphere.server.terrain.generation.heightmap.EmptySkyGen;
|
||||||
import electrosphere.server.terrain.generation.heightmap.HeightmapGenerator;
|
import electrosphere.server.terrain.generation.heightmap.HeightmapGenerator;
|
||||||
|
import electrosphere.server.terrain.generation.heightmap.HeightmapNoiseGen;
|
||||||
import electrosphere.server.terrain.generation.heightmap.HillsGen;
|
import electrosphere.server.terrain.generation.heightmap.HillsGen;
|
||||||
import electrosphere.server.terrain.generation.heightmap.MountainGen;
|
import electrosphere.server.terrain.generation.heightmap.MountainGen;
|
||||||
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
||||||
@ -22,6 +22,7 @@ import electrosphere.server.terrain.generation.interfaces.GenerationContext;
|
|||||||
import electrosphere.server.terrain.generation.voxelphase.AnimeMountainsGen;
|
import electrosphere.server.terrain.generation.voxelphase.AnimeMountainsGen;
|
||||||
import electrosphere.server.terrain.generation.voxelphase.HillsVoxelGen;
|
import electrosphere.server.terrain.generation.voxelphase.HillsVoxelGen;
|
||||||
import electrosphere.server.terrain.generation.voxelphase.MountainVoxelGen;
|
import electrosphere.server.terrain.generation.voxelphase.MountainVoxelGen;
|
||||||
|
import electrosphere.server.terrain.generation.voxelphase.NoiseVoxelGen;
|
||||||
import electrosphere.server.terrain.generation.voxelphase.VoxelGenerator;
|
import electrosphere.server.terrain.generation.voxelphase.VoxelGenerator;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
import electrosphere.server.terrain.models.TerrainModel;
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
@ -86,6 +87,16 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
*/
|
*/
|
||||||
public TestGenerationChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
|
public TestGenerationChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
|
||||||
this.serverWorldData = serverWorldData;
|
this.serverWorldData = serverWorldData;
|
||||||
|
this.registerAllGenerators();
|
||||||
|
this.useJavascript = useJavascript;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all generators
|
||||||
|
*/
|
||||||
|
public void registerAllGenerators(){
|
||||||
|
tagHeightmapMap.clear();
|
||||||
|
tagVoxelMap.clear();
|
||||||
this.registerHeightmapGenerator(new EmptySkyGen());
|
this.registerHeightmapGenerator(new EmptySkyGen());
|
||||||
this.registerHeightmapGenerator(new HillsGen());
|
this.registerHeightmapGenerator(new HillsGen());
|
||||||
this.registerHeightmapGenerator(new PlainsGen());
|
this.registerHeightmapGenerator(new PlainsGen());
|
||||||
@ -93,7 +104,10 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
this.registerVoxelGenerator(new HillsVoxelGen());
|
this.registerVoxelGenerator(new HillsVoxelGen());
|
||||||
this.registerVoxelGenerator(new AnimeMountainsGen());
|
this.registerVoxelGenerator(new AnimeMountainsGen());
|
||||||
this.registerVoxelGenerator(new MountainVoxelGen());
|
this.registerVoxelGenerator(new MountainVoxelGen());
|
||||||
this.useJavascript = useJavascript;
|
for(SamplerFile samplerFile : Globals.gameConfigCurrent.getSamplerFiles()){
|
||||||
|
this.registerHeightmapGenerator(new HeightmapNoiseGen(samplerFile));
|
||||||
|
this.registerVoxelGenerator(new NoiseVoxelGen(samplerFile));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,95 +182,60 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelGenerator voxelGenerator = this.tagVoxelMap.get("hills");
|
VoxelGenerator voxelGenerator = this.tagVoxelMap.get("test1");
|
||||||
|
|
||||||
|
int firstType = -2;
|
||||||
|
boolean homogenous = true;
|
||||||
|
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||||
|
GenerationContext generationContext = new GenerationContext();
|
||||||
|
generationContext.setServerWorldData(serverWorldData);
|
||||||
|
|
||||||
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||||
|
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
|
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(finalChunkX,finalWorldX);
|
||||||
|
|
||||||
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||||
|
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
|
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(finalChunkZ,finalWorldZ);
|
||||||
|
float surfaceHeight = heightfield[x][z];
|
||||||
|
float gradient = gradientField[x][z];
|
||||||
|
|
||||||
if(this.useJavascript){
|
|
||||||
Globals.scriptEngine.getScriptContext().executeSynchronously(() -> {
|
|
||||||
int firstType = -2;
|
|
||||||
boolean homogenous = true;
|
|
||||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
|
||||||
Value getVoxelFunc = Globals.scriptEngine.getScriptContext().invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
|
|
||||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
|
||||||
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
|
||||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
|
||||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
|
||||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
|
||||||
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
|
||||||
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
|
||||||
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
|
||||||
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
|
||||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
|
||||||
getVoxelFunc.execute(
|
|
||||||
voxel,
|
|
||||||
finalWorldX, finalWorldY, finalWorldZ,
|
|
||||||
finalChunkX, finalChunkY, finalChunkZ,
|
|
||||||
stride,
|
|
||||||
heightfield[x][z],
|
|
||||||
surfaceBiome
|
|
||||||
);
|
|
||||||
weights[x][y][z] = voxel.weight;
|
|
||||||
values[x][y][z] = voxel.type;
|
|
||||||
if(firstType == -2){
|
|
||||||
firstType = values[x][y][z];
|
|
||||||
} else if(homogenous && firstType != values[x][y][z]){
|
|
||||||
homogenous = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Globals.profiler.endCpuSample();
|
|
||||||
}
|
|
||||||
if(homogenous){
|
|
||||||
rVal.setHomogenousValue(firstType);
|
|
||||||
} else {
|
|
||||||
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
|
|
||||||
}
|
|
||||||
rVal.setWeights(weights);
|
|
||||||
rVal.setValues(values);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
int firstType = -2;
|
|
||||||
boolean homogenous = true;
|
|
||||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
|
||||||
GenerationContext generationContext = new GenerationContext();
|
|
||||||
generationContext.setServerWorldData(serverWorldData);
|
|
||||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
|
||||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(finalChunkY,finalWorldY);
|
||||||
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
|
||||||
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
voxelGenerator.getVoxel(
|
||||||
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
voxel,
|
||||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
finalWorldX, finalWorldY, finalWorldZ,
|
||||||
voxelGenerator.getVoxel(
|
finalChunkX, finalChunkY, finalChunkZ,
|
||||||
voxel,
|
realX, realY, realZ,
|
||||||
finalWorldX, finalWorldY, finalWorldZ,
|
stride,
|
||||||
finalChunkX, finalChunkY, finalChunkZ,
|
surfaceHeight, gradient,
|
||||||
stride,
|
surfaceBiome,
|
||||||
heightfield[x][z], gradientField[x][z],
|
generationContext
|
||||||
surfaceBiome,
|
);
|
||||||
generationContext
|
if(voxel != null){
|
||||||
);
|
weights[x][y][z] = voxel.weight;
|
||||||
if(voxel != null){
|
values[x][y][z] = voxel.type;
|
||||||
weights[x][y][z] = voxel.weight;
|
}
|
||||||
values[x][y][z] = voxel.type;
|
if(firstType == -2){
|
||||||
}
|
firstType = values[x][y][z];
|
||||||
if(firstType == -2){
|
} else if(homogenous && firstType != values[x][y][z]){
|
||||||
firstType = values[x][y][z];
|
homogenous = false;
|
||||||
} else if(homogenous && firstType != values[x][y][z]){
|
|
||||||
homogenous = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(homogenous){
|
|
||||||
rVal.setHomogenousValue(firstType);
|
|
||||||
} else {
|
|
||||||
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
|
|
||||||
}
|
|
||||||
rVal.setWeights(weights);
|
|
||||||
rVal.setValues(values);
|
|
||||||
}
|
}
|
||||||
|
if(homogenous){
|
||||||
|
rVal.setHomogenousValue(firstType);
|
||||||
|
} else {
|
||||||
|
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
|
||||||
|
}
|
||||||
|
rVal.setWeights(weights);
|
||||||
|
rVal.setValues(values);
|
||||||
} catch(Exception ex){
|
} catch(Exception ex){
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
package electrosphere.server.terrain.generation.heightmap;
|
||||||
|
|
||||||
|
import electrosphere.game.data.voxel.sampler.SamplerFile;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a heightmap using a noise definition
|
||||||
|
*/
|
||||||
|
public class HeightmapNoiseGen implements HeightmapGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tag for the noise function that generates
|
||||||
|
*/
|
||||||
|
String tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sampler to pull from when allocating voxels
|
||||||
|
*/
|
||||||
|
NoiseSampler sampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param sampler The sampler to pull from
|
||||||
|
*/
|
||||||
|
public HeightmapNoiseGen(SamplerFile samplerDefinitionFile){
|
||||||
|
this.sampler = samplerDefinitionFile.getSampler();
|
||||||
|
this.tag = samplerDefinitionFile.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getHeight(long SEED, double x, double y) {
|
||||||
|
return (float)sampler.getValue(0, x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A module that contains other modules
|
||||||
|
*/
|
||||||
|
public interface NoiseContainer extends NoiseSampler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all child modules of this one
|
||||||
|
* @return All child modules
|
||||||
|
*/
|
||||||
|
public Collection<NoiseSampler> getChildren();
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorAdd;
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorClamp;
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorConst;
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorDomainWarp;
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorMul;
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorOpenSimplex;
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorVoronoi;
|
||||||
|
import electrosphere.server.terrain.generation.noise.operators.NoiseOperoatorInvoke;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes noise modules
|
||||||
|
*/
|
||||||
|
public class NoiseModuleSerializer implements JsonDeserializer<NoiseSampler> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NoiseSampler deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
switch(json.getAsJsonObject().get("name").getAsString()){
|
||||||
|
|
||||||
|
//meta
|
||||||
|
case NoiseOperoatorInvoke.NAME: {
|
||||||
|
return context.deserialize(json, NoiseOperoatorInvoke.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
//warps
|
||||||
|
case NoiseOperatorDomainWarp.NAME: {
|
||||||
|
return context.deserialize(json, NoiseOperatorDomainWarp.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
//actual noise sampling
|
||||||
|
case NoiseOperatorOpenSimplex.NAME: {
|
||||||
|
return context.deserialize(json, NoiseOperatorOpenSimplex.class);
|
||||||
|
}
|
||||||
|
case NoiseOperatorVoronoi.NAME: {
|
||||||
|
return context.deserialize(json, NoiseOperatorVoronoi.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
//basic ops
|
||||||
|
case NoiseOperatorConst.NAME: {
|
||||||
|
return context.deserialize(json, NoiseOperatorConst.class);
|
||||||
|
}
|
||||||
|
case NoiseOperatorAdd.NAME: {
|
||||||
|
return context.deserialize(json, NoiseOperatorAdd.class);
|
||||||
|
}
|
||||||
|
case NoiseOperatorMul.NAME: {
|
||||||
|
return context.deserialize(json, NoiseOperatorMul.class);
|
||||||
|
}
|
||||||
|
case NoiseOperatorClamp.NAME: {
|
||||||
|
return context.deserialize(json, NoiseOperatorClamp.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A noce function that can be sampled in octaves
|
||||||
|
*/
|
||||||
|
public interface NoiseOctaveSampler extends NoiseSampler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the lacunarity of the sampler
|
||||||
|
* @param lacunarity The lacunarity
|
||||||
|
*/
|
||||||
|
public void setLacunarity(double lacunarity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the lacunarity of the sampler
|
||||||
|
* @return The lacunarity
|
||||||
|
*/
|
||||||
|
public double getLacunarity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the number of octaves to sample
|
||||||
|
* @param octaveCount The number of octaves to sample
|
||||||
|
*/
|
||||||
|
public void setOctaveCount(int octaveCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of octaves to sample
|
||||||
|
* @return The number of octaves to sample
|
||||||
|
*/
|
||||||
|
public int getOctaveCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the frequency to sample at
|
||||||
|
* @param frequency The frequency
|
||||||
|
*/
|
||||||
|
public void setFrequency(double frequency);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the frequency of the function
|
||||||
|
* @return The frequency
|
||||||
|
*/
|
||||||
|
public double getFrequency();
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A noise module that can sample values
|
||||||
|
*/
|
||||||
|
public interface NoiseSampler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of this noise module
|
||||||
|
* @return The name of the module
|
||||||
|
*/
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Samples the noise at a given position with a given seed
|
||||||
|
* @param SEED The seed
|
||||||
|
* @param x The x coordinate
|
||||||
|
* @param y The y coordinate
|
||||||
|
* @param z The z coordinate
|
||||||
|
* @return The value of the noise at that position for the given seed
|
||||||
|
*/
|
||||||
|
public double getValue(double SEED, double x, double y, double z);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise.operators;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
|
||||||
|
public class NoiseOperatorAdd implements NoiseContainer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this module
|
||||||
|
*/
|
||||||
|
public static final String NAME = "Add";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first value to pull from
|
||||||
|
*/
|
||||||
|
protected NoiseSampler first;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The second value to pull from
|
||||||
|
*/
|
||||||
|
protected NoiseSampler second;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(double SEED, double x, double y, double z) {
|
||||||
|
return first.getValue(SEED, x, y, z) + second.getValue(SEED, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<NoiseSampler> getChildren(){
|
||||||
|
return Arrays.asList(new NoiseSampler[]{
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise.operators;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
import io.github.studiorailgun.MathUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clamps a noise value
|
||||||
|
*/
|
||||||
|
public class NoiseOperatorClamp implements NoiseContainer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this module
|
||||||
|
*/
|
||||||
|
public static final String NAME = "Clamp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum value to clamp to
|
||||||
|
*/
|
||||||
|
protected NoiseSampler min;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum value to clamp to
|
||||||
|
*/
|
||||||
|
protected NoiseSampler max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The source to clamp
|
||||||
|
*/
|
||||||
|
protected NoiseSampler source;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(double SEED, double x, double y, double z) {
|
||||||
|
return MathUtils.clamp(source.getValue(SEED, x, y, z), min.getValue(SEED, x, y, z), max.getValue(SEED, x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<NoiseSampler> getChildren(){
|
||||||
|
return Arrays.asList(new NoiseSampler[]{
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
source,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise.operators;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a constant value
|
||||||
|
*/
|
||||||
|
public class NoiseOperatorConst implements NoiseSampler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this module
|
||||||
|
*/
|
||||||
|
public static final String NAME = "Const";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value
|
||||||
|
*/
|
||||||
|
double value;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(double SEED, double x, double y, double z) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise.operators;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The warp operator
|
||||||
|
*/
|
||||||
|
public class NoiseOperatorDomainWarp implements NoiseContainer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this module
|
||||||
|
*/
|
||||||
|
public static final String NAME = "DomainWarp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sampler to pull the x value from
|
||||||
|
*/
|
||||||
|
protected NoiseSampler x;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sampler to pull the y value from
|
||||||
|
*/
|
||||||
|
protected NoiseSampler y;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sampler to pull the z value from
|
||||||
|
*/
|
||||||
|
protected NoiseSampler z;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amplitude of the warp to apply
|
||||||
|
*/
|
||||||
|
protected double amplitude = 1.0f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sampler to pull from for the final emitted value
|
||||||
|
*/
|
||||||
|
protected NoiseSampler source;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(double SEED, double x, double y, double z) {
|
||||||
|
double sampleX = x;
|
||||||
|
if(this.x != null){
|
||||||
|
sampleX = sampleX + this.x.getValue(SEED, x, y, z) * amplitude;
|
||||||
|
}
|
||||||
|
double sampleY = y;
|
||||||
|
if(this.y != null){
|
||||||
|
sampleY = sampleY + this.y.getValue(SEED, x, y, z) * amplitude;
|
||||||
|
}
|
||||||
|
double sampleZ = z;
|
||||||
|
if(this.z != null){
|
||||||
|
sampleZ = sampleZ + this.z.getValue(SEED, x, y, z) * amplitude;
|
||||||
|
}
|
||||||
|
return this.source.getValue(SEED, sampleX, sampleY, sampleZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<NoiseSampler> getChildren(){
|
||||||
|
return Arrays.asList(new NoiseSampler[]{
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z,
|
||||||
|
source,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise.operators;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplies one noise source by another
|
||||||
|
*/
|
||||||
|
public class NoiseOperatorMul implements NoiseContainer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this module
|
||||||
|
*/
|
||||||
|
public static final String NAME = "Mul";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First sample
|
||||||
|
*/
|
||||||
|
protected NoiseSampler first;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Second sample
|
||||||
|
*/
|
||||||
|
protected NoiseSampler second;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(double SEED, double x, double y, double z) {
|
||||||
|
return first.getValue(SEED, x, y, z) * second.getValue(SEED, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<NoiseSampler> getChildren(){
|
||||||
|
return Arrays.asList(new NoiseSampler[]{
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise.operators;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseOctaveSampler;
|
||||||
|
import electrosphere.util.noise.OpenSimplex2S;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Samples open simplex noise
|
||||||
|
*/
|
||||||
|
public class NoiseOperatorOpenSimplex implements NoiseOctaveSampler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this module
|
||||||
|
*/
|
||||||
|
public static final String NAME = "OpenSimplex";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The frequency to sample at
|
||||||
|
*/
|
||||||
|
double frequency = 0.02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lacunarity (the amount to change the frequency each octave)
|
||||||
|
*/
|
||||||
|
double lacunarity = 0.02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of octaves to sample
|
||||||
|
*/
|
||||||
|
int octaveCount = 1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(double SEED, double x, double y, double z) {
|
||||||
|
double rVal = 0;
|
||||||
|
double sampleFreq = frequency;
|
||||||
|
for(int i = 0; i < octaveCount; i++){
|
||||||
|
rVal = rVal + OpenSimplex2S.noise3_ImproveXZ((long)SEED, x * sampleFreq, y * sampleFreq, z * sampleFreq);
|
||||||
|
sampleFreq = sampleFreq + lacunarity;
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLacunarity(double lacunarity) {
|
||||||
|
this.lacunarity = lacunarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLacunarity() {
|
||||||
|
return this.lacunarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOctaveCount(int octaveCount) {
|
||||||
|
this.octaveCount = octaveCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOctaveCount() {
|
||||||
|
return this.octaveCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFrequency(double frequency) {
|
||||||
|
this.frequency = frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getFrequency() {
|
||||||
|
return this.frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise.operators;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseOctaveSampler;
|
||||||
|
import io.github.studiorailgun.NoiseUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Samples voronoi noise
|
||||||
|
*/
|
||||||
|
public class NoiseOperatorVoronoi implements NoiseOctaveSampler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this module
|
||||||
|
*/
|
||||||
|
public static final String NAME = "Voronoi";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The frequency to sample at
|
||||||
|
*/
|
||||||
|
double frequency = 0.02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lacunarity (the amount to change the frequency each octave)
|
||||||
|
*/
|
||||||
|
double lacunarity = 0.02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of octaves to sample
|
||||||
|
*/
|
||||||
|
int octaveCount = 1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(double SEED, double x, double y, double z) {
|
||||||
|
double rVal = 0;
|
||||||
|
double sampleFreq = frequency;
|
||||||
|
for(int i = 0; i < octaveCount; i++){
|
||||||
|
rVal = rVal + NoiseUtils.voronoi(x * sampleFreq, y * sampleFreq, z * sampleFreq);
|
||||||
|
sampleFreq = sampleFreq + lacunarity;
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLacunarity(double lacunarity) {
|
||||||
|
this.lacunarity = lacunarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLacunarity() {
|
||||||
|
return this.lacunarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOctaveCount(int octaveCount) {
|
||||||
|
this.octaveCount = octaveCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOctaveCount() {
|
||||||
|
return this.octaveCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFrequency(double frequency) {
|
||||||
|
this.frequency = frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getFrequency() {
|
||||||
|
return this.frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package electrosphere.server.terrain.generation.noise.operators;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes another sample definition file
|
||||||
|
*/
|
||||||
|
public class NoiseOperoatorInvoke implements NoiseContainer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this module
|
||||||
|
*/
|
||||||
|
public static final String NAME = "Invoke";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sampler to invoke
|
||||||
|
*/
|
||||||
|
NoiseSampler invokeSampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the sampler definition file to invoke
|
||||||
|
*/
|
||||||
|
String target;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(double SEED, double x, double y, double z) {
|
||||||
|
if(invokeSampler != null){
|
||||||
|
return invokeSampler.getValue(SEED, x, y, z);
|
||||||
|
} else {
|
||||||
|
throw new Error("Invoke sampler undefined for " + target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the sampler to invoke
|
||||||
|
* @param invokeSampler The sampler
|
||||||
|
*/
|
||||||
|
public void setInvokeSampler(NoiseSampler invokeSampler){
|
||||||
|
this.invokeSampler = invokeSampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the invoke sampler
|
||||||
|
* @return The sampler
|
||||||
|
*/
|
||||||
|
public NoiseSampler getInvokeSampler(){
|
||||||
|
return invokeSampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the target this operator wants to invoke
|
||||||
|
* @return The target
|
||||||
|
*/
|
||||||
|
public String getTarget(){
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<NoiseSampler> getChildren(){
|
||||||
|
return Arrays.asList(new NoiseSampler[]{
|
||||||
|
invokeSampler
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -67,16 +67,13 @@ public class AnimeMountainsGen implements VoxelGenerator {
|
|||||||
GeneratedVoxel voxel,
|
GeneratedVoxel voxel,
|
||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
int chunkX, int chunkY, int chunkZ,
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
double realX, double realY, double realZ,
|
||||||
int stride, float surfaceHeight, float surfaceGradient,
|
int stride, float surfaceHeight, float surfaceGradient,
|
||||||
BiomeData surfaceBiome,
|
BiomeData surfaceBiome,
|
||||||
GenerationContext generationContext
|
GenerationContext generationContext
|
||||||
) {
|
) {
|
||||||
Globals.profiler.beginAggregateCpuSample("AnimeMountainsGen.getVoxel");
|
Globals.profiler.beginAggregateCpuSample("AnimeMountainsGen.getVoxel");
|
||||||
|
|
||||||
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkX,worldX);
|
|
||||||
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkY,worldY);
|
|
||||||
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkZ,worldZ);
|
|
||||||
|
|
||||||
double strideMultiplier = Math.pow(2,stride);
|
double strideMultiplier = Math.pow(2,stride);
|
||||||
double heightDiff = realY - surfaceHeight;
|
double heightDiff = realY - surfaceHeight;
|
||||||
double surfacePercent = AnimeMountainsGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
double surfacePercent = AnimeMountainsGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
||||||
|
|||||||
@ -26,6 +26,7 @@ public class HillsVoxelGen implements VoxelGenerator {
|
|||||||
GeneratedVoxel voxel,
|
GeneratedVoxel voxel,
|
||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
int chunkX, int chunkY, int chunkZ,
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
double realX, double realY, double realZ,
|
||||||
int stride,
|
int stride,
|
||||||
float surfaceHeight, float surfaceGradient,
|
float surfaceHeight, float surfaceGradient,
|
||||||
BiomeData surfaceBiome,
|
BiomeData surfaceBiome,
|
||||||
@ -33,10 +34,6 @@ public class HillsVoxelGen implements VoxelGenerator {
|
|||||||
){
|
){
|
||||||
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");
|
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");
|
||||||
|
|
||||||
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkX,worldX);
|
|
||||||
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkY,worldY);
|
|
||||||
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkZ,worldZ);
|
|
||||||
|
|
||||||
double strideMultiplier = Math.pow(2,stride);
|
double strideMultiplier = Math.pow(2,stride);
|
||||||
double heightDiff = realY - surfaceHeight;
|
double heightDiff = realY - surfaceHeight;
|
||||||
double surfacePercent = HillsVoxelGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
double surfacePercent = HillsVoxelGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
||||||
|
|||||||
@ -33,6 +33,7 @@ public class MountainVoxelGen implements VoxelGenerator {
|
|||||||
GeneratedVoxel voxel,
|
GeneratedVoxel voxel,
|
||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
int chunkX, int chunkY, int chunkZ,
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
double realX, double realY, double realZ,
|
||||||
int stride,
|
int stride,
|
||||||
float surfaceHeight, float surfaceGradient,
|
float surfaceHeight, float surfaceGradient,
|
||||||
BiomeData surfaceBiome,
|
BiomeData surfaceBiome,
|
||||||
@ -40,10 +41,6 @@ public class MountainVoxelGen implements VoxelGenerator {
|
|||||||
){
|
){
|
||||||
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");
|
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");
|
||||||
|
|
||||||
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkX,worldX);
|
|
||||||
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkY,worldY);
|
|
||||||
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkZ,worldZ);
|
|
||||||
|
|
||||||
double strideMultiplier = Math.pow(2,stride);
|
double strideMultiplier = Math.pow(2,stride);
|
||||||
double heightDiff = realY - surfaceHeight;
|
double heightDiff = realY - surfaceHeight;
|
||||||
double surfacePercent = HillsVoxelGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
double surfacePercent = HillsVoxelGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
||||||
|
|||||||
@ -0,0 +1,109 @@
|
|||||||
|
package electrosphere.server.terrain.generation.voxelphase;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.game.data.biome.BiomeData;
|
||||||
|
import electrosphere.game.data.voxel.sampler.SamplerFile;
|
||||||
|
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
|
||||||
|
import electrosphere.server.terrain.generation.interfaces.GenerationContext;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
|
import io.github.studiorailgun.MathUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates voxels based on a noise config
|
||||||
|
*/
|
||||||
|
public class NoiseVoxelGen implements VoxelGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The width of the surface in number of voxels
|
||||||
|
*/
|
||||||
|
public static final int SURFACE_VOXEL_WIDTH = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tag for the noise function that generates
|
||||||
|
*/
|
||||||
|
String tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sampler to pull from when allocating voxels
|
||||||
|
*/
|
||||||
|
NoiseSampler sampler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param samplerDefinitionFile The file to model this generator off of
|
||||||
|
*/
|
||||||
|
public NoiseVoxelGen(SamplerFile samplerDefinitionFile){
|
||||||
|
this.sampler = samplerDefinitionFile.getSampler();
|
||||||
|
this.tag = samplerDefinitionFile.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getVoxel(
|
||||||
|
GeneratedVoxel voxel,
|
||||||
|
int worldX, int worldY, int worldZ,
|
||||||
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
double realX, double realY, double realZ,
|
||||||
|
int stride, float surfaceHeight, float surfaceGradient,
|
||||||
|
BiomeData surfaceBiome, GenerationContext generationContext
|
||||||
|
) {
|
||||||
|
double strideMultiplier = Math.pow(2,stride);
|
||||||
|
double heightDiff = realY - surfaceHeight;
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
if(heightDiff < -strideMultiplier * SURFACE_VOXEL_WIDTH){
|
||||||
|
//below surface
|
||||||
|
double sample = this.sampler.getValue(0, realX, realY, realZ);
|
||||||
|
if(sample > 0){
|
||||||
|
double finalSurface = MathUtils.clamp(sample,0,1);
|
||||||
|
voxel.weight = (float)finalSurface * 2 - 1;
|
||||||
|
voxel.type = 1;
|
||||||
|
} else {
|
||||||
|
voxel.weight = -1.0f;
|
||||||
|
voxel.type = 0;
|
||||||
|
}
|
||||||
|
} else if(heightDiff > 0) {
|
||||||
|
//above surface
|
||||||
|
voxel.weight = -1.0f;
|
||||||
|
voxel.type = 0;
|
||||||
|
} else if(heightDiff < -strideMultiplier){
|
||||||
|
//generate full-size surface-type voxel
|
||||||
|
double sample = this.sampler.getValue(0, realX, realY, realZ);
|
||||||
|
if(sample > 0){
|
||||||
|
double finalHeight = MathUtils.clamp(sample,0,1);
|
||||||
|
voxel.weight = (float)finalHeight * 2 - 1;
|
||||||
|
voxel.type = 2;
|
||||||
|
} else {
|
||||||
|
voxel.weight = -1.0f;
|
||||||
|
voxel.type = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//surface
|
||||||
|
double sample = this.sampler.getValue(0, realX, realY, realZ);
|
||||||
|
if(sample > 0){
|
||||||
|
double surfacePercent = heightDiff / -strideMultiplier;
|
||||||
|
double finalHeight = MathUtils.clamp(sample,0,1) * MathUtils.clamp(surfacePercent,0,1);
|
||||||
|
voxel.weight = (float)finalHeight * 2 - 1;
|
||||||
|
voxel.type = 2;
|
||||||
|
} else {
|
||||||
|
voxel.weight = -1.0f;
|
||||||
|
voxel.type = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the weight of a voxel on the surface based on the surface height, the position of the voxel, and the stride multiplier
|
||||||
|
* @param surfaceHeight The surface height
|
||||||
|
* @param realPosY The position of the voxel
|
||||||
|
* @param strideMultiplier The stride multiplier
|
||||||
|
* @return The weight of the voxel
|
||||||
|
*/
|
||||||
|
protected static double getSurfaceWeight(double surfaceHeight, double realPosY, double strideMultiplier){
|
||||||
|
return ((surfaceHeight - realPosY) / strideMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -37,6 +37,7 @@ public interface VoxelGenerator {
|
|||||||
GeneratedVoxel voxel,
|
GeneratedVoxel voxel,
|
||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
int chunkX, int chunkY, int chunkZ,
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
double realX, double realY, double realZ,
|
||||||
int stride,
|
int stride,
|
||||||
float surfaceHeight, float surfaceGradient,
|
float surfaceHeight, float surfaceGradient,
|
||||||
BiomeData surfaceBiome,
|
BiomeData surfaceBiome,
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import electrosphere.game.data.creature.type.ai.AITreeDataSerializer;
|
|||||||
import electrosphere.game.data.creature.type.movement.MovementSystem;
|
import electrosphere.game.data.creature.type.movement.MovementSystem;
|
||||||
import electrosphere.game.data.creature.type.movement.MovementSystemSerializer;
|
import electrosphere.game.data.creature.type.movement.MovementSystemSerializer;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseModuleSerializer;
|
||||||
|
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||||
import electrosphere.util.annotation.AnnotationExclusionStrategy;
|
import electrosphere.util.annotation.AnnotationExclusionStrategy;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
@ -43,6 +45,7 @@ public class FileUtils {
|
|||||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
gsonBuilder.registerTypeAdapter(MovementSystem.class, new MovementSystemSerializer());
|
gsonBuilder.registerTypeAdapter(MovementSystem.class, new MovementSystemSerializer());
|
||||||
gsonBuilder.registerTypeAdapter(AITreeData.class, new AITreeDataSerializer());
|
gsonBuilder.registerTypeAdapter(AITreeData.class, new AITreeDataSerializer());
|
||||||
|
gsonBuilder.registerTypeAdapter(NoiseSampler.class, new NoiseModuleSerializer());
|
||||||
gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy());
|
gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy());
|
||||||
gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy());
|
gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy());
|
||||||
gson = gsonBuilder.create();
|
gson = gsonBuilder.create();
|
||||||
@ -248,6 +251,23 @@ public class FileUtils {
|
|||||||
}
|
}
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an object from the assets folder
|
||||||
|
* @param <T> The type of object
|
||||||
|
* @param file The file to load from
|
||||||
|
* @param className The class of the object inside the file
|
||||||
|
* @return The file
|
||||||
|
*/
|
||||||
|
public static <T>T loadObjectFromFile(File file, Class<T> className){
|
||||||
|
T rVal = null;
|
||||||
|
try {
|
||||||
|
rVal = gson.fromJson(Files.newBufferedReader(file.toPath()), className);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LoggerInterface.loggerFileIO.ERROR(ex);
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an sql script file as a string
|
* Gets an sql script file as a string
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user