Chunk physics loading/unloading/radius
This commit is contained in:
parent
c5834a0bca
commit
2ed2ab063a
@ -9,6 +9,15 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "water",
|
||||
"relations" : [
|
||||
{
|
||||
"name" : "fire",
|
||||
"strength" : -1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "water",
|
||||
"relations" : [
|
||||
|
||||
@ -271,13 +271,13 @@ public class LoadingThread extends Thread {
|
||||
Actually initialize the terrain manager
|
||||
*/
|
||||
float[][] elevation;
|
||||
Globals.serverTerrainManager = new ServerTerrainManager(2000,200,100,0.25f,0);
|
||||
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,0.25f,0);
|
||||
if(Globals.RUN_SERVER){
|
||||
if(Globals.LOAD_TERRAIN){
|
||||
Globals.serverTerrainManager.load();
|
||||
} else {
|
||||
Globals.serverTerrainManager.generate();
|
||||
Globals.serverTerrainManager.save();
|
||||
// Globals.serverTerrainManager.save();
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,7 +291,7 @@ public class LoadingThread extends Thread {
|
||||
boolean found = false;
|
||||
for(int x = 0; x < discreteSize; x++){
|
||||
for(int y = 0; y < discreteSize; y++){
|
||||
if(Globals.serverTerrainManager.getDiscreteValue(x, y)>0){
|
||||
if(Globals.serverTerrainManager.getDiscreteValue(x, y)>1000){
|
||||
playerStartX = x;
|
||||
playerStartY = y;
|
||||
found = true;
|
||||
@ -305,7 +305,7 @@ public class LoadingThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
Globals.spawnPoint = new Vector3f(playerStartX * chunkSize,0,playerStartY * chunkSize);
|
||||
Globals.spawnPoint = new Vector3f(playerStartX * chunkSize, Globals.serverTerrainManager.getHeightAtPosition(playerStartX * chunkSize,playerStartY * chunkSize), playerStartY * chunkSize);
|
||||
|
||||
|
||||
|
||||
@ -404,6 +404,13 @@ public class LoadingThread extends Thread {
|
||||
}
|
||||
// System.out.println("undrawable");
|
||||
}
|
||||
|
||||
while(Globals.drawCellManager.containsPhysicsNeedingCell()){
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(10);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package electrosphere.game.client.drawcell;
|
||||
|
||||
import com.bulletphysics.collision.dispatch.CollisionObject;
|
||||
import com.bulletphysics.dynamics.RigidBody;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.game.collision.PhysicsUtils;
|
||||
import electrosphere.game.collision.collidable.Collidable;
|
||||
import electrosphere.game.terrain.processing.TerrainInterpolator;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.main.Globals;
|
||||
@ -29,6 +32,8 @@ public class DrawCell {
|
||||
|
||||
ShaderProgram program;
|
||||
|
||||
CollisionObject physicsObject;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -82,12 +87,21 @@ public class DrawCell {
|
||||
modelEntity = EntityUtils.spawnDrawableEntity(terrainModelPath);
|
||||
LoggerInterface.loggerRenderer.INFO("New cell @ " + cellX * dynamicInterpolationRatio + "," + cellY * dynamicInterpolationRatio);
|
||||
EntityUtils.getPosition(modelEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.0f, cellY * dynamicInterpolationRatio));
|
||||
PhysicsUtils.attachTerrainRigidBody(modelEntity,heightmap);
|
||||
Globals.collisionEngine.registerPhysicsEntity(modelEntity);
|
||||
}
|
||||
|
||||
public void retireCell(){
|
||||
EntityUtils.cleanUpDrawableEntity(modelEntity);
|
||||
}
|
||||
|
||||
public void generatePhysics(){
|
||||
physicsObject = PhysicsUtils.attachTerrainRigidBody(modelEntity,heightmap);
|
||||
Globals.collisionEngine.registerPhysicsEntity(modelEntity);
|
||||
// System.out.println("generate physics");
|
||||
}
|
||||
|
||||
public void destroyPhysics(){
|
||||
Globals.collisionEngine.deregisterCollidableEntity(modelEntity);
|
||||
Globals.collisionEngine.deregisterRigidBody((RigidBody)physicsObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -35,15 +35,19 @@ public class DrawCellManager {
|
||||
boolean[][] drawable;
|
||||
boolean[][] updateable;
|
||||
boolean[][] hasRequested;
|
||||
boolean[][] needsPhysics;
|
||||
boolean[][] hasPhysics;
|
||||
|
||||
|
||||
ShaderProgram program;
|
||||
|
||||
|
||||
|
||||
int drawRadius = 5;
|
||||
int drawRadius = 35;
|
||||
int drawStepdownInterval = 3;
|
||||
int drawStepdownValue = 5;
|
||||
int drawStepdownValue = 25;
|
||||
|
||||
int physicsRadius = 3;
|
||||
|
||||
int worldBoundDiscreteMin = 0;
|
||||
int worldBoundDiscreteMax = 0;
|
||||
@ -70,6 +74,8 @@ public class DrawCellManager {
|
||||
drawable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
|
||||
updateable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
|
||||
hasRequested = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
|
||||
needsPhysics = new boolean[physicsRadius * 2 + 1][physicsRadius * 2 + 1];
|
||||
hasPhysics = new boolean[physicsRadius * 2 + 1][physicsRadius * 2 + 1];
|
||||
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
||||
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
||||
valid[x][y] = false;
|
||||
@ -78,6 +84,12 @@ public class DrawCellManager {
|
||||
hasRequested[x][y] = false;
|
||||
}
|
||||
}
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
for(int y = 0; y < physicsRadius * 2 + 1; y++){
|
||||
needsPhysics[x][y] = true;
|
||||
hasPhysics[x][y] = false;
|
||||
}
|
||||
}
|
||||
cellX = discreteX;
|
||||
cellY = discreteY;
|
||||
|
||||
@ -147,6 +159,9 @@ public class DrawCellManager {
|
||||
drawable[targetX][targetY] = false;
|
||||
updateable[targetX][targetY] = false;
|
||||
hasRequested[targetX][targetY] = false;
|
||||
// if(Math.abs(physicsRadius + 1 - targetX) < physicsRadius && Math.abs(physicsRadius + 1 - targetY) < physicsRadius){
|
||||
// needsPhysics[targetX][targetY] = true;
|
||||
// }
|
||||
} else {
|
||||
if(hasRequested[targetX][targetY] == false){
|
||||
//client should request macro values from server
|
||||
@ -190,6 +205,10 @@ public class DrawCellManager {
|
||||
currentCellY >= 0 &&
|
||||
currentCellY < clientWorldData.getWorldDiscreteSize()
|
||||
){
|
||||
//physics radius calculation
|
||||
// if(Math.abs(physicsRadius + 1 - targetX) < physicsRadius && Math.abs(physicsRadius + 1 - targetY) < physicsRadius){
|
||||
// needsPhysics[targetX][targetY] = true;
|
||||
// }
|
||||
//calculation for stride
|
||||
int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius));//Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
|
||||
int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
|
||||
@ -230,6 +249,9 @@ public class DrawCellManager {
|
||||
currentCellY >= 0 &&
|
||||
currentCellY < clientWorldData.getWorldDiscreteSize()
|
||||
){
|
||||
// if(Math.abs(drawRadius + 1 - targetX) < physicsRadius && Math.abs(drawRadius + 1 - targetY) < physicsRadius){
|
||||
// needsPhysics[targetX][targetY] = true;
|
||||
// }
|
||||
int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius)); //Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
|
||||
int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
|
||||
while(clientWorldData.getDynamicInterpolationRatio() % stride != 0){
|
||||
@ -280,13 +302,74 @@ public class DrawCellManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsPhysicsNeedingCell(){
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
for(int y = 0; y < physicsRadius * 2 + 1; y++){
|
||||
if(needsPhysics[x][y]){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addPhysicsToCell(){
|
||||
int targetX = 0;
|
||||
int targetY = 0;
|
||||
boolean found = false;
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
targetX = x;
|
||||
for(int y = 0; y < physicsRadius * 2 + 1; y++){
|
||||
targetY = y;
|
||||
// System.out.println(x + " <=>w " + y);
|
||||
if(needsPhysics[x][y]){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(found){
|
||||
int currentCellX = cellX - physicsRadius + targetX;
|
||||
int currentCellY = cellY - physicsRadius + targetY;
|
||||
if(
|
||||
currentCellX >= 0 &&
|
||||
currentCellX < clientWorldData.getWorldDiscreteSize() &&
|
||||
currentCellY >= 0 &&
|
||||
currentCellY < clientWorldData.getWorldDiscreteSize()
|
||||
){
|
||||
// if(Math.abs(drawRadius + 1 - targetX) < physicsRadius && Math.abs(drawRadius + 1 - targetY) < physicsRadius){
|
||||
// needsPhysics[targetX][targetY] = true;
|
||||
// }
|
||||
// int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius)); //Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
|
||||
// int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
|
||||
// while(clientWorldData.getDynamicInterpolationRatio() % stride != 0){
|
||||
// stride = stride + 1;
|
||||
// }
|
||||
// if(cells[targetX][targetY + drawRadius] != null){
|
||||
// System.out.println(targetX + " - " + targetY);
|
||||
cells[targetX + drawRadius - physicsRadius][targetY + drawRadius - physicsRadius].generatePhysics();
|
||||
// } else {
|
||||
// System.out.println("Current cell is null: " + currentCellX + " - " + currentCellY);
|
||||
// }
|
||||
}
|
||||
needsPhysics[targetX][targetY] = false;
|
||||
hasPhysics[targetX][targetY] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void shiftChunksNegX(){
|
||||
//retire old graphics
|
||||
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
||||
if(cells[drawRadius * 2][y] != null){
|
||||
cells[drawRadius * 2][y].retireCell();
|
||||
}
|
||||
}
|
||||
//shift draw array
|
||||
for(int x = drawRadius * 2; x > 0; x--){
|
||||
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
||||
cells[x][y] = cells[x-1][y];
|
||||
@ -294,18 +377,39 @@ public class DrawCellManager {
|
||||
hasRequested[x][y] = hasRequested[x-1][y];
|
||||
}
|
||||
}
|
||||
//invalidate edge of draw array
|
||||
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
||||
valid[0][y] = false;
|
||||
hasRequested[0][y] = false;
|
||||
}
|
||||
//retire physics of cells
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
if(hasPhysics[x][physicsRadius * 2]){
|
||||
cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius].destroyPhysics();
|
||||
}
|
||||
}
|
||||
//shift physics array
|
||||
for(int x = physicsRadius * 2; x > 0; x--){
|
||||
for(int y = 0; y < physicsRadius * 2 + 1; y++){
|
||||
needsPhysics[x][y] = needsPhysics[x-1][y];
|
||||
hasPhysics[x][y] = hasPhysics[x-1][y];
|
||||
}
|
||||
}
|
||||
//invalidate edge of physics array
|
||||
for(int y = 0; y < physicsRadius * 2 + 1; y++){
|
||||
needsPhysics[0][y] = true;
|
||||
hasPhysics[0][y] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void shiftChunksPosX(){
|
||||
//retire old graphics
|
||||
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
||||
if(cells[0][y] != null){
|
||||
cells[0][y].retireCell();
|
||||
}
|
||||
}
|
||||
//shift draw array
|
||||
for(int x = 0; x < drawRadius * 2; x++){
|
||||
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
||||
cells[x][y] = cells[x+1][y];
|
||||
@ -313,18 +417,39 @@ public class DrawCellManager {
|
||||
hasRequested[x][y] = hasRequested[x+1][y];
|
||||
}
|
||||
}
|
||||
//invalidate edge of draw array
|
||||
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
||||
valid[drawRadius * 2][y] = false;
|
||||
hasRequested[drawRadius * 2][y] = false;
|
||||
}
|
||||
//retire physics of cells
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
if(hasPhysics[x][physicsRadius * 2]){
|
||||
cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius].destroyPhysics();
|
||||
}
|
||||
}
|
||||
//shift physics array
|
||||
for(int x = 0; x < physicsRadius * 2; x++){
|
||||
for(int y = 0; y < physicsRadius * 2 + 1; y++){
|
||||
needsPhysics[x][y] = needsPhysics[x+1][y];
|
||||
hasPhysics[x][y] = hasPhysics[x+1][y];
|
||||
}
|
||||
}
|
||||
//invalidate edge of physics array
|
||||
for(int y = 0; y < physicsRadius * 2 + 1; y++){
|
||||
needsPhysics[physicsRadius * 2][y] = true;
|
||||
hasPhysics[physicsRadius * 2][y] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void shiftChunksNegY(){
|
||||
//retire cells
|
||||
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
||||
if(cells[x][drawRadius * 2] != null){
|
||||
cells[x][drawRadius * 2].retireCell();
|
||||
}
|
||||
}
|
||||
//shift draw array
|
||||
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
||||
for(int y = drawRadius * 2; y > 0; y--){
|
||||
cells[x][y] = cells[x][y-1];
|
||||
@ -332,18 +457,39 @@ public class DrawCellManager {
|
||||
hasRequested[x][y] = hasRequested[x][y-1];
|
||||
}
|
||||
}
|
||||
//invalidate edge of draw array
|
||||
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
||||
valid[x][0] = false;
|
||||
hasRequested[x][0] = false;
|
||||
}
|
||||
//retire physics of cells
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
if(hasPhysics[x][physicsRadius * 2]){
|
||||
cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius].destroyPhysics();
|
||||
}
|
||||
}
|
||||
//shift physics array
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
for(int y = physicsRadius * 2; y > 0; y--){
|
||||
needsPhysics[x][y] = needsPhysics[x][y-1];
|
||||
hasPhysics[x][y] = hasPhysics[x][y-1];
|
||||
}
|
||||
}
|
||||
//invalidate edge of physics array
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
needsPhysics[x][0] = true;
|
||||
hasPhysics[x][0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void shiftChunksPosY(){
|
||||
//retire old graphics
|
||||
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
||||
if(cells[x][0] != null){
|
||||
cells[x][0].retireCell();
|
||||
}
|
||||
}
|
||||
//shift draw array
|
||||
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
||||
for(int y = 0; y < drawRadius * 2; y++){
|
||||
cells[x][y] = cells[x][y+1];
|
||||
@ -351,10 +497,29 @@ public class DrawCellManager {
|
||||
hasRequested[x][y] = hasRequested[x][y+1];
|
||||
}
|
||||
}
|
||||
//invalidate edge of draw array
|
||||
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
||||
valid[x][drawRadius * 2] = false;
|
||||
hasRequested[x][drawRadius * 2] = false;
|
||||
}
|
||||
//retire physics of cells
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
if(hasPhysics[x][0]){
|
||||
cells[x + drawRadius - physicsRadius][0 + drawRadius - physicsRadius].destroyPhysics();
|
||||
}
|
||||
}
|
||||
//shift physics array
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
for(int y = 0; y < physicsRadius * 2; y++){
|
||||
needsPhysics[x][y] = needsPhysics[x][y+1];
|
||||
hasPhysics[x][y] = hasPhysics[x][y+1];
|
||||
}
|
||||
}
|
||||
//invalidate edge of physics array
|
||||
for(int x = 0; x < physicsRadius * 2 + 1; x++){
|
||||
needsPhysics[x][physicsRadius * 2] = true;
|
||||
hasPhysics[x][physicsRadius * 2] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -404,6 +569,8 @@ public class DrawCellManager {
|
||||
makeCellDrawable();
|
||||
} else if(containsUpdateableCell()){
|
||||
updateCellModel();
|
||||
} else if(containsPhysicsNeedingCell()){
|
||||
addPhysicsToCell();
|
||||
}
|
||||
}
|
||||
// } else if(DRAW_CELL_MANAGER_FLAG_GENERATE_ARENA){
|
||||
|
||||
@ -395,4 +395,36 @@ public class CollisionEngine {
|
||||
}
|
||||
}
|
||||
|
||||
public void deregisterPhysicsObject(CollisionObject object){
|
||||
if(collisionObject.contains(object)){
|
||||
collisionObject.remove(object);
|
||||
}
|
||||
world.removeCollisionObject(object);
|
||||
}
|
||||
|
||||
public void deregisterRigidBody(RigidBody body){
|
||||
if(collisionObject.contains(body)){
|
||||
collisionObject.remove(body);
|
||||
}
|
||||
if((body) != null){
|
||||
body.destroy();
|
||||
// world.removeRigidBody(body);
|
||||
}
|
||||
}
|
||||
|
||||
public void deregisterCollidableEntity(Entity e){
|
||||
if(collisionEntities.contains(e)){
|
||||
collisionEntities.remove(e);
|
||||
}
|
||||
if(physicsEntities.contains(e)){
|
||||
physicsEntities.remove(e);
|
||||
}
|
||||
if(dynamicPhysicsEntities.contains(e)){
|
||||
dynamicPhysicsEntities.remove(e);
|
||||
}
|
||||
if(structurePhysicsEntities.contains(e)){
|
||||
structurePhysicsEntities.remove(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ public class PhysicsUtils {
|
||||
Globals.collisionEngine.registerCollisionObject(terrainRigidBody, new Collidable(terrain,Collidable.TYPE_TERRAIN));
|
||||
|
||||
// terrainRigidBody.getAabb(aabbMin, aabbMax);
|
||||
|
||||
//
|
||||
// System.out.println("aabbMin: " + aabbMin + " aabbMax: " + aabbMax);
|
||||
|
||||
|
||||
|
||||
@ -171,7 +171,7 @@ public class Globals {
|
||||
public static EntityManager serverEntityManager;
|
||||
|
||||
//terrain manager
|
||||
public static boolean LOAD_TERRAIN = true;
|
||||
public static boolean LOAD_TERRAIN = false;
|
||||
public static ServerTerrainManager serverTerrainManager;
|
||||
public static Vector3f spawnPoint = new Vector3f(1000,0,1000);
|
||||
|
||||
|
||||
@ -96,7 +96,7 @@ public class ServerConnectionHandler implements Runnable {
|
||||
//spawn player in world
|
||||
Entity newPlayerCharacter = CreatureUtils.spawnBasicCreature("Human");
|
||||
playerCharacterID = newPlayerCharacter.getId();
|
||||
CreatureUtils.positionCharacter(newPlayerCharacter, new Vector3f(Globals.spawnPoint.x,3,Globals.spawnPoint.z));
|
||||
CreatureUtils.positionCharacter(newPlayerCharacter, new Vector3f(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z));
|
||||
//spawn player sword
|
||||
Entity sword = ItemUtils.spawnBasicItem("Katana");
|
||||
AttachUtils.attachEntityToEntityAtBone(newPlayerCharacter, sword, "Bone.031");
|
||||
|
||||
@ -34,12 +34,12 @@ public class TerrainViewer {
|
||||
|
||||
TerrainModel terrainModel;
|
||||
|
||||
// ServerTerrainManager terrainManager = new ServerTerrainManager(2000, 1000, 100, 0.05f, new Random().nextLong());
|
||||
// terrainManager.generate();
|
||||
// terrainModel = terrainManager.getModel();
|
||||
ServerTerrainManager terrainManager = new ServerTerrainManager(2000, 1000, 100, 0.05f, new Random().nextLong());
|
||||
terrainManager.generate();
|
||||
terrainModel = terrainManager.getModel();
|
||||
|
||||
// Utilities.saveObjectToBakedJsonFile("/Config/testingTerrain.json", terrainModel);
|
||||
terrainModel = FileLoadingUtils.loadObjectFromAssetPath("/Config/testingTerrain.json", TerrainModel.class);
|
||||
// terrainModel = FileLoadingUtils.loadObjectFromAssetPath("/Config/testingTerrain.json", TerrainModel.class);
|
||||
|
||||
MacroSimulation simulation = new MacroSimulation();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user