terrain generation testing realm
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-10-23 13:07:08 -04:00
parent d10da49140
commit aa70f39eb9
15 changed files with 501 additions and 15 deletions

1
.gitignore vendored
View File

@ -34,6 +34,7 @@
#saves #saves
/saves/random_sp_world /saves/random_sp_world
/saves/defaultLevel* /saves/defaultLevel*
/saves/generation_testing
#screenshots #screenshots
/assets/Screenshots /assets/Screenshots

View File

@ -12,6 +12,17 @@
"SPAWNPOINT" "SPAWNPOINT"
] ]
}, },
{
"id" : "marker",
"graphicsTemplate": {
"model": {
"path" : "Models/gameobj/token.glb"
}
},
"tokens": [
"MARKER"
]
},
{ {
"id" : "flameEmitterTest", "id" : "flameEmitterTest",
"particleEmitter": { "particleEmitter": {

View File

@ -13,8 +13,6 @@
- Old sword item - Old sword item
- Switch that requires being hit - Switch that requires being hit
- Door that can be locked - Door that can be locked
+ Lock third room behind climbing
- Climbing
+ Portal to tutorial hub area + Portal to tutorial hub area
- Portals - Portals
- Switching realms - Switching realms
@ -23,7 +21,6 @@
+ rearchitecture + rearchitecture
+ fix the vibes + fix the vibes
Tooltips for items, hover over with cursor, etc
Ticketed randomizer node for BTs to more heavily weight attacking and waiting Ticketed randomizer node for BTs to more heavily weight attacking and waiting
+ non-feedback requirements + non-feedback requirements

View File

@ -897,6 +897,7 @@ Initial implementation of tooltips
(10/23/2024) (10/23/2024)
Tooltip improvements Tooltip improvements
Terrain generation testing realm
@ -961,6 +962,16 @@ Startup Performance
- Proactively send chunks on player loading in (ie, send all chunks that are all air before its even requested) - Proactively send chunks on player loading in (ie, send all chunks that are all air before its even requested)
- Also send all 'dirt' or 'stone' chunks - Also send all 'dirt' or 'stone' chunks
Scripting enhancements
- setTimeout
- Get marker by entity name/id
- Play/Stop animations on actors
- Apply cameras
- Show/Hide UI
- Enable/disable controls states
- Spawn/Destroy entities
- Ability to define regions in space (ie with entities)
Code Generation Code Generation
- Generate static "hasXComponent", "getXComponent" functions on sync'd components - Generate static "hasXComponent", "getXComponent" functions on sync'd components
@ -977,7 +988,6 @@ Code cleanup
- Rename "ShaderProgram" to "VisualShader" - Rename "ShaderProgram" to "VisualShader"
- Have ComputeShader and VisualShader use same static method for uploading uniforms - Have ComputeShader and VisualShader use same static method for uploading uniforms
Goof off today requirements:
Transvoxel implementation Transvoxel implementation
- Fix draw cell manager requesting far-out chunks - Fix draw cell manager requesting far-out chunks
- Properly update to higher LOD meshes as you get closer - Properly update to higher LOD meshes as you get closer

View File

@ -63,6 +63,14 @@ public class MenuGeneratorsTitleMenu {
Globals.threadManager.start(loadingThread); Globals.threadManager.start(loadingThread);
}).setOnClickAudio(AssetDataStrings.UI_TONE_BUTTON_TITLE)); }).setOnClickAudio(AssetDataStrings.UI_TONE_BUTTON_TITLE));
//button (sp debug)
rVal.addChild(Button.createButtonCentered("Load Test Generation Realm", () -> {
LoadingThread loadingThread = new LoadingThread(LoadingThreadType.CHUNK_GENERATION_REALM);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
Globals.threadManager.start(loadingThread);
}).setOnClickAudio(AssetDataStrings.UI_TONE_BUTTON_TITLE));
//button (ui testing) //button (ui testing)
rVal.addChild(Button.createButtonCentered("UI Testing", () -> { rVal.addChild(Button.createButtonCentered("UI Testing", () -> {
WindowUtils.replaceMainMenuContents(MenuGeneratorsUITesting.createUITestMenu()); WindowUtils.replaceMainMenuContents(MenuGeneratorsUITesting.createUITestMenu());

View File

@ -0,0 +1,104 @@
package electrosphere.engine.loadingthreads;
import java.util.concurrent.TimeUnit;
import electrosphere.auth.AuthenticationManager;
import electrosphere.client.ui.menu.MenuGenerators;
import electrosphere.client.ui.menu.WindowStrings;
import electrosphere.client.ui.menu.WindowUtils;
import electrosphere.engine.Globals;
import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.entity.scene.SceneGenerator;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.renderer.ui.elements.Window;
import electrosphere.server.saves.SaveUtils;
/**
* Loads the chunk generation testing realm
*/
public class ChunkGenerationTestLoading {
/**
* Loads the level editor
*/
protected static void loadChunkGenerationTesting(Object[] params){
//
//Set params we would expect to run with this thread
//
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
Globals.RUN_PHYSICS = false;
Globals.aiManager.setActive(false);
Globals.signalSystem.post(SignalType.UI_MODIFICATION, ()->{
Window loadingWindow = (Window)Globals.elementService.getWindow(WindowStrings.WINDOW_LOADING);
//show loading
WindowUtils.recursiveSetVisible(Globals.elementService.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
loadingWindow.setVisible(true);
});
String saveName = "generation_testing";
if(!SaveUtils.getSaves().contains(saveName)){
//
//the juicy server GENERATION part
//
//init save structure
SaveUtils.createOrOverwriteSave(saveName, SceneGenerator.createGenerationTestingSceneFile(saveName));
}
//load just-created save
SaveUtils.loadSave(saveName, false);
//initialize the "virtual" objects simulation
LoadingUtils.initMacroSimulation();
LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT);
//init authentication
LoadingUtils.initAuthenticationManager(false);
//initialize the local connection
Globals.clientUsername = "leveleditor";
Globals.clientPassword = AuthenticationManager.getHashedString("leveleditor");
ServerConnectionHandler serverPlayerConnection = LoadingUtils.initLocalConnection(true);
//wait for player object creation
while(Globals.playerManager.getPlayers().size() < 1 || !Globals.clientConnection.isInitialized()){
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//initialize the "real" objects simulation
LoadingUtils.initMicroSimulation();
//init game specific stuff (ie different skybox colors)
LoadingUtils.initGameGraphicalEntities();
//set simulations to ready if they exist
LoadingUtils.setSimulationsToReady();
//log
LoggerInterface.loggerEngine.INFO("[Server]Finished loading level editor");
//the less juicy client setup part
while(Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces().size() == 0){
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException ex) {}
}
//spawn player character
LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection, true);
//request terrain data
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
//Run client startup process
ClientLoading.loadClientWorld(params);
}
}

View File

@ -40,6 +40,11 @@ public class LoadingThread extends Thread {
*/ */
DEBUG_RANDOM_SP_WORLD, DEBUG_RANDOM_SP_WORLD,
/**
* Loads a chunk generation testing realm
*/
CHUNK_GENERATION_REALM,
/** /**
* Loads the level editor * Loads the level editor
*/ */
@ -133,6 +138,11 @@ public class LoadingThread extends Thread {
DebugSPWorldLoading.loadDebugSPWorld(params); DebugSPWorldLoading.loadDebugSPWorld(params);
} break; } break;
//Loads a realm used for chunk generation testing
case CHUNK_GENERATION_REALM: {
ChunkGenerationTestLoading.loadChunkGenerationTesting(params);
} break;
//loads the level editor //loads the level editor
case LEVEL_EDITOR: { case LEVEL_EDITOR: {
LevelEditorLoading.loadLevelEditor(params); LevelEditorLoading.loadLevelEditor(params);

View File

@ -10,6 +10,7 @@ public class RealmDescriptor {
*/ */
public static final String REALM_DESCRIPTOR_GRIDDED = "gridded"; public static final String REALM_DESCRIPTOR_GRIDDED = "gridded";
public static final String REALM_DESCRIPTOR_PROCEDURAL = "procedural"; public static final String REALM_DESCRIPTOR_PROCEDURAL = "procedural";
public static final String REALM_DESCRIPTOR_GENERATION_TESTING = "generationTesting";
/** /**
* The dirt voxel type's id * The dirt voxel type's id

View File

@ -1,6 +1,7 @@
package electrosphere.entity.scene; package electrosphere.entity.scene;
import electrosphere.server.datacell.GriddedDataCellManager; import electrosphere.server.datacell.GriddedDataCellManager;
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
/** /**
* Generates scene files where appropriate (ie, if playing the procedurally generated level) * Generates scene files where appropriate (ie, if playing the procedurally generated level)
@ -24,4 +25,21 @@ public class SceneGenerator {
return file; return file;
} }
/**
* Creates a scene file for the generation testing realm
* @param gridSize The size of the terrain grid of the scene
* @return The scene file
*/
public static SceneFile createGenerationTestingSceneFile(String saveName){
//base file stuff
SceneFile file = SceneFile.createSceneFile();
//realm descriptor stuff
file.realmDescriptor.type = RealmDescriptor.REALM_DESCRIPTOR_GENERATION_TESTING;
file.realmDescriptor.griddedRealmSize = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
file.createSaveInstance = true; //won't have a predefined scene to load, so must create one in the save
file.loadAllCells = false; // do not load all cells on init
return file;
}
} }

View File

@ -22,7 +22,9 @@ public class SceneLoader {
/** /**
* Loads a scene file on the server * Loads a scene file on the server
* @param path The name of the save to look for a scene file within * @param saveName The name of the save
* @param serverWorldData the server world data
* @param isLevelEditor true if this is a level editor, false otherwise
*/ */
public static void serverInstantiateSaveSceneFile(String saveName, ServerWorldData serverWorldData, boolean isLevelEditor){ public static void serverInstantiateSaveSceneFile(String saveName, ServerWorldData serverWorldData, boolean isLevelEditor){
//load scene file //load scene file
@ -33,7 +35,9 @@ public class SceneLoader {
/** /**
* Loads a scene file on the server * Loads a scene file on the server
* @param path The name of the scene in the assets/scenes folder * @param sceneName The name of the scene
* @param serverWorldData the server world data
* @param isLevelEditor true if this is a level editor, false otherwise
*/ */
public static void serverInstantiateAssetSceneFile(String sceneName, ServerWorldData serverWorldData, boolean isLevelEditor){ public static void serverInstantiateAssetSceneFile(String sceneName, ServerWorldData serverWorldData, boolean isLevelEditor){
//load scene file //load scene file
@ -80,6 +84,10 @@ public class SceneLoader {
case RealmDescriptor.REALM_DESCRIPTOR_PROCEDURAL: { case RealmDescriptor.REALM_DESCRIPTOR_PROCEDURAL: {
realm = Globals.realmManager.createGriddedRealm(serverWorldData,serverContentManager); realm = Globals.realmManager.createGriddedRealm(serverWorldData,serverContentManager);
} break; } break;
case RealmDescriptor.REALM_DESCRIPTOR_GENERATION_TESTING: {
ServerWorldData newWorldData = ServerWorldData.createGenerationTestWorldData();
realm = Globals.realmManager.createGriddedRealm(newWorldData, serverContentManager);
} break;
default: { default: {
throw new Error("Unhandled case! " + file.realmDescriptor.getType()); throw new Error("Unhandled case! " + file.realmDescriptor.getType());
} }

View File

@ -3,6 +3,7 @@ package electrosphere.game.server.world;
import electrosphere.server.fluid.generation.DefaultFluidGenerator; import electrosphere.server.fluid.generation.DefaultFluidGenerator;
import electrosphere.server.fluid.manager.ServerFluidManager; import electrosphere.server.fluid.manager.ServerFluidManager;
import electrosphere.server.terrain.generation.DefaultChunkGenerator; import electrosphere.server.terrain.generation.DefaultChunkGenerator;
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
import electrosphere.server.terrain.manager.ServerTerrainChunk; import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.manager.ServerTerrainManager; import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.util.FileUtils; import electrosphere.util.FileUtils;
@ -133,6 +134,27 @@ public class ServerWorldData {
serverWorldData.setManagers(serverTerrainManager, serverFluidManager); serverWorldData.setManagers(serverTerrainManager, serverFluidManager);
return serverWorldData; return serverWorldData;
} }
/**
* Creates world data for testing generation
* @return The server world data
*/
public static ServerWorldData createGenerationTestWorldData(){
//
//Read world data if it exists
//
ServerWorldData serverWorldData = null;
ServerTerrainManager serverTerrainManager = null;
ServerFluidManager serverFluidManager = null;
//TODO: Allow loading procedurally generated terrain from disk (the chunk generator is always default currently)
serverWorldData = ServerWorldData.createFixedWorldData(new Vector3d(0),new Vector3d(16 * 4 * 4));
serverWorldData.worldSizeDiscrete = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
serverWorldData.worldSizeDiscreteVertical = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
serverTerrainManager = new ServerTerrainManager(serverWorldData, 0, new TestGenerationChunkGenerator());
serverFluidManager = new ServerFluidManager(serverWorldData, serverTerrainManager, 0, new DefaultFluidGenerator());
serverWorldData.setManagers(serverTerrainManager, serverFluidManager);
return serverWorldData;
}
public Vector3f getWorldBoundMin(){ public Vector3f getWorldBoundMin(){

View File

@ -13,12 +13,20 @@ import java.util.Properties;
*/ */
public class DatabaseController { public class DatabaseController {
/**
* The database connection
*/
Connection conn; Connection conn;
public DatabaseController(){ /**
* Constructor
} */
public DatabaseController(){ }
/**
* Connects to a database
* @param path The path to the database
*/
public void connect(String path){ public void connect(String path){
String dbms = "sqlite"; String dbms = "sqlite";
Properties connectionProps = new Properties(); Properties connectionProps = new Properties();
@ -107,6 +115,10 @@ public class DatabaseController {
return rVal; return rVal;
} }
/**
* Checks of the connection is actually connected
* @return true if connected, false otherwise
*/
public boolean isConnected(){ public boolean isConnected(){
boolean rVal = false; boolean rVal = false;
if(conn == null){ if(conn == null){
@ -120,6 +132,9 @@ public class DatabaseController {
return rVal; return rVal;
} }
/**
* Disconnects from the database
*/
public void disconnect(){ public void disconnect(){
try { try {
conn.close(); conn.close();

View File

@ -0,0 +1,104 @@
package electrosphere.server.terrain.generation;
import java.util.Arrays;
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.models.TerrainModel;
/**
* A generator for testing terrain generation
*/
public class TestGenerationChunkGenerator implements ChunkGenerator {
/**
* The size of the realm for testing generation
*/
public static final int GENERATOR_REALM_SIZE = 10;
/**
* The terreain model for the generator
*/
TerrainModel terrainModel;
@Override
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ) {
ServerTerrainChunk rVal = null;
float[][][] weights;
int[][][] values;
if(worldX == 0 || worldZ == 0){
//generate flat ground for the player to spawn on
weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
values = new int[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
Arrays.fill(weights[x][y],-1f);
}
}
if(worldY == 0){
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
values[x][0][z] = 1;
weights[x][0][z] = 0.1f;
}
}
}
} else {
//actual generation algo
weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
values = new int[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
weights[x][y][z] = this.getChunkWeight(worldX, worldY, worldZ, x, y, z, this.terrainModel);
values[x][y][z] = this.getChunkValue(worldX, worldY, worldZ, x, y, z, this.terrainModel);
}
}
}
}
rVal = new ServerTerrainChunk(worldX, worldY, worldZ, weights, values);
return rVal;
}
@Override
public void setModel(TerrainModel model) {
this.terrainModel = model;
}
/**
* Gets the value for a chunk
* @param worldX The world x pos
* @param worldY The world y pos
* @param worldZ The world z pos
* @param chunkX The chunk x pos
* @param chunkY The chunk y pos
* @param chunkZ The chunk z pos
* @param terrainModel The terrain model
* @return The value of the chunk
*/
private int getChunkValue(int worldX, int worldY, int worldZ, int chunkX, int chunkY, int chunkZ, TerrainModel terrainModel){
return 1;
}
/**
* Gets the weight for a chunk
* @param worldX The world x pos
* @param worldY The world y pos
* @param worldZ The world z pos
* @param chunkX The chunk x pos
* @param chunkY The chunk y pos
* @param chunkZ The chunk z pos
* @param terrainModel The terrain model
* @return The weight of the chunk
*/
private float getChunkWeight(int worldX, int worldY, int worldZ, int chunkX, int chunkY, int chunkZ, TerrainModel terrainModel){
return 0.1f;
}
}

View File

@ -12,16 +12,54 @@ import electrosphere.server.terrain.models.TerrainModification;
*/ */
public class ServerTerrainChunk { public class ServerTerrainChunk {
//all chunks are 16x16x16 /**
* All chunks are 16x16x16
*/
public static final int CHUNK_DIMENSION = 16; public static final int CHUNK_DIMENSION = 16;
//The size of the data passed into marching cubes/transvoxel to generate a fully connected and seamless chunk
/**
* The size of the data passed into marching cubes/transvoxel to generate a fully connected and seamless chunk
*/
public static final int CHUNK_DATA_GENERATOR_SIZE = CHUNK_DIMENSION + 1; public static final int CHUNK_DATA_GENERATOR_SIZE = CHUNK_DIMENSION + 1;
int worldX, worldY, worldZ; /**
* Gets the x coordinate of the world position of the chunk
*/
int worldX;
/**
* Gets the y coordinate of the world position of the chunk
*/
int worldY;
/**
* Gets the z coordinate of the world position of the chunk
*/
int worldZ;
/**
* The list of modifications applied to the chunk
*/
List<TerrainModification> modifications = new LinkedList<TerrainModification>(); List<TerrainModification> modifications = new LinkedList<TerrainModification>();
/**
* The weights of the chunk
*/
float[][][] weights; float[][][] weights;
/**
* The values of the chunk
*/
int[][][] values; int[][][] values;
/**
* Constructor
* @param worldX The world position x coordinate
* @param worldY The world position y coordinate
* @param worldZ The world position z coordinate
* @param weights The weights of the chunk
* @param values The values of the chunk
*/
public ServerTerrainChunk(int worldX, int worldY, int worldZ, float[][][] weights, int[][][] values) { public ServerTerrainChunk(int worldX, int worldY, int worldZ, float[][][] weights, int[][][] values) {
this.worldX = worldX; this.worldX = worldX;
this.worldY = worldY; this.worldY = worldY;
@ -30,18 +68,38 @@ public class ServerTerrainChunk {
this.values = values; this.values = values;
} }
/**
* Gets the world position x coordinate
* @return The x coordinate
*/
public int getWorldX() { public int getWorldX() {
return worldX; return worldX;
} }
/**
* Gets the world position y coordinate
* @return The y coordinate
*/
public int getWorldY() { public int getWorldY() {
return worldY; return worldY;
} }
/**
* Gets the world position z coordinate
* @return The z coordinate
*/
public int getWorldZ() { public int getWorldZ() {
return worldZ; return worldZ;
} }
/**
* Gets the world position of the chunk
* @return The world position
*/
public Vector3i getWorldPos(){
return new Vector3i(worldX,worldY,worldZ);
}
/** /**
* Gets the world position of this terrain chunk as a joml Vector * Gets the world position of this terrain chunk as a joml Vector
* @return The vector * @return The vector
@ -50,18 +108,34 @@ public class ServerTerrainChunk {
return new Vector3i(worldX,worldY,worldZ); return new Vector3i(worldX,worldY,worldZ);
} }
/**
* Gets the list of all modifications applied to the chunk
* @return THe list of all modifications
*/
public List<TerrainModification> getModifications() { public List<TerrainModification> getModifications() {
return modifications; return modifications;
} }
/**
* Gets the weights of the chunk
* @return The weights of the chunk
*/
public float[][][] getWeights() { public float[][][] getWeights() {
return weights; return weights;
} }
/**
* Gets the values of the chunk
* @return The values of the chunk
*/
public int[][][] getValues() { public int[][][] getValues() {
return values; return values;
} }
/**
* Adds a modification to the chunk
* @param modification The modification
*/
public void addModification(TerrainModification modification){ public void addModification(TerrainModification modification){
modifications.add(modification); modifications.add(modification);
values[modification.getVoxelPos().x][modification.getVoxelPos().y][modification.getVoxelPos().z] = modification.getValue(); values[modification.getVoxelPos().x][modification.getVoxelPos().y][modification.getVoxelPos().z] = modification.getValue();

View File

@ -5,25 +5,63 @@ import java.util.Map;
import electrosphere.util.annotation.Exclude; import electrosphere.util.annotation.Exclude;
/**
* The model of the terrain
*/
public class TerrainModel { public class TerrainModel {
/**
* The dynamic interpolation ratio
*/
int dynamicInterpolationRatio; int dynamicInterpolationRatio;
/**
* The interpolation dampener
*/
float interpolationRandomDampener = 0.4f; float interpolationRandomDampener = 0.4f;
/**
* The discrete array dimension of the model
*/
int discreteArrayDimension; int discreteArrayDimension;
/**
* The macro level elevation data
*/
@Exclude @Exclude
private float[][] elevation; private float[][] elevation;
/**
* The real coordinate mountain threshold
*/
float realMountainThreshold; float realMountainThreshold;
/**
* The real coordinate ocean threshold
*/
float realOceanThreshold; float realOceanThreshold;
/**
* The map of modifications applied to the model
*/
Map<String,ModificationList> modifications; Map<String,ModificationList> modifications;
/**
* Private constructor
*/
TerrainModel() { TerrainModel() {
this.modifications = new HashMap<String,ModificationList>(); this.modifications = new HashMap<String,ModificationList>();
} }
/**
* Constructor
* @param dimension The dimension of the model
* @param elevation The macro elevation data
* @param realOceanThreshold The real coordinate ocean threshold
* @param realMountainThreshold The real coordinate mountain threshold
* @param dynamicInterpolationRatio The dynamic interpolation ratio
*/
public TerrainModel( public TerrainModel(
int dimension, int dimension,
float[][] elevation, float[][] elevation,
@ -40,6 +78,12 @@ public class TerrainModel {
this.modifications = new HashMap<String,ModificationList>(); this.modifications = new HashMap<String,ModificationList>();
} }
/**
* Constructs a terrain model
* @param dimension The dimension of the terrain model
* @param dynamicInterpolationRatio The dynamic interpolation ratio
* @return The terrain model
*/
public static TerrainModel constructTerrainModel(int dimension, int dynamicInterpolationRatio){ public static TerrainModel constructTerrainModel(int dimension, int dynamicInterpolationRatio){
TerrainModel rVal = new TerrainModel(); TerrainModel rVal = new TerrainModel();
rVal.discreteArrayDimension = dimension; rVal.discreteArrayDimension = dimension;
@ -47,10 +91,18 @@ public class TerrainModel {
return rVal; return rVal;
} }
/**
* Gets the macro elevation data for the terrain model
* @return The macro elevation data
*/
public float[][] getElevation(){ public float[][] getElevation(){
return elevation; return elevation;
} }
/**
* Gets the interpolation random dampener
* @param f The interpolation random dampener
*/
public void setInterpolationRandomDampener(float f){ public void setInterpolationRandomDampener(float f){
interpolationRandomDampener = f; interpolationRandomDampener = f;
} }
@ -205,6 +257,12 @@ public class TerrainModel {
*/ */
/**
* Gets the macro values at a position
* @param x The world x position
* @param y The world y position
* @return The macro values
*/
public float[][] getMacroValuesAtPosition(int x, int y){ public float[][] getMacroValuesAtPosition(int x, int y){
float[][] rVal = new float[3][3]; float[][] rVal = new float[3][3];
@ -260,7 +318,12 @@ public class TerrainModel {
/**
* Gets the 5-radius macro values at a position
* @param x The x position
* @param y The y position
* @return The macro values
*/
public float[][] getRad5MacroValuesAtPosition(int x, int y){ public float[][] getRad5MacroValuesAtPosition(int x, int y){
float[][] rVal = new float[5][5]; float[][] rVal = new float[5][5];
@ -305,26 +368,53 @@ public class TerrainModel {
*/ */
/**
* Gets the random dampener for the model
* @return The random dampener
*/
public float getRandomDampener(){ public float getRandomDampener(){
return interpolationRandomDampener; return interpolationRandomDampener;
} }
/**
* Gets the dynamic interpolation ratio
* @return The ratio
*/
public int getDynamicInterpolationRatio(){ public int getDynamicInterpolationRatio(){
return dynamicInterpolationRatio; return dynamicInterpolationRatio;
} }
/**
* Gets the real coordinate mountain threshold
* @return The threshold
*/
public float getRealMountainThreshold() { public float getRealMountainThreshold() {
return realMountainThreshold; return realMountainThreshold;
} }
/**
* Gets the real coordinate ocean threshold
* @return The threshold
*/
public float getRealOceanThreshold() { public float getRealOceanThreshold() {
return realOceanThreshold; return realOceanThreshold;
} }
/**
* Gets a modification key
* @param x The world x position
* @param y The world y position
* @param z The world z position
* @return The key
*/
public String getModificationKey(int x, int y, int z){ public String getModificationKey(int x, int y, int z){
return x + "_" + y + "_" + z; return x + "_" + y + "_" + z;
} }
/**
* Adds a terrain modification to the model
* @param modification The modification
*/
public void addModification(TerrainModification modification){ public void addModification(TerrainModification modification){
String key = getModificationKey(modification.getWorldPos().x,modification.getWorldPos().y,modification.getWorldPos().z); String key = getModificationKey(modification.getWorldPos().x,modification.getWorldPos().y,modification.getWorldPos().z);
ModificationList list; ModificationList list;
@ -337,12 +427,25 @@ public class TerrainModel {
list.addModification(modification); list.addModification(modification);
} }
/**
* Checks if a modification has been applied at a world position
* @param worldX The x coordinate of the world position
* @param worldY The y coordinate of the world position
* @param worldZ The z coordinate of the world position
* @return true if there is a modification, false otherwise
*/
public boolean containsModificationsAtCoord(int worldX, int worldY, int worldZ){ public boolean containsModificationsAtCoord(int worldX, int worldY, int worldZ){
return modifications.containsKey(getModificationKey(worldX, worldY, worldZ)); return modifications.containsKey(getModificationKey(worldX, worldY, worldZ));
} }
/**
* Gets the terrain modification at the world position
* @param worldX The x coordinate of the world position
* @param worldY The y coordinate of the world position
* @param worldZ The z coordinate of the world position
* @return The modification if there is one at the position, null otherwise
*/
public ModificationList getModifications(int worldX, int worldY, int worldZ){ public ModificationList getModifications(int worldX, int worldY, int worldZ){
// System.out.println("Got modifications at " + worldX + " " + worldY);
return modifications.get(getModificationKey(worldX, worldY, worldZ)); return modifications.get(getModificationKey(worldX, worldY, worldZ));
} }