fix single player loading
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
c8ba4c5e5c
commit
ddaab9a2db
1
.gitignore
vendored
1
.gitignore
vendored
@ -36,6 +36,7 @@
|
|||||||
/saves/random_sp_world
|
/saves/random_sp_world
|
||||||
/saves/defaultLevel*
|
/saves/defaultLevel*
|
||||||
/saves/generation_testing
|
/saves/generation_testing
|
||||||
|
/saves/World name*
|
||||||
|
|
||||||
#screenshots
|
#screenshots
|
||||||
/assets/Screenshots
|
/assets/Screenshots
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
#maven.buildNumber.plugin properties file
|
#maven.buildNumber.plugin properties file
|
||||||
#Tue Dec 03 12:29:34 EST 2024
|
#Tue Dec 03 15:14:56 EST 2024
|
||||||
buildNumber=516
|
buildNumber=519
|
||||||
|
|||||||
@ -1229,6 +1229,7 @@ Native code building correctly in jenkins pipeline
|
|||||||
Refactoring native code
|
Refactoring native code
|
||||||
Fix gravity tree not deactivating when body is disabled
|
Fix gravity tree not deactivating when body is disabled
|
||||||
Refactoring world menu generators into dedicated class
|
Refactoring world menu generators into dedicated class
|
||||||
|
Fix single player loading
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -74,7 +74,7 @@ public class BlockDrawCell {
|
|||||||
/**
|
/**
|
||||||
* The cached minimum distance
|
* The cached minimum distance
|
||||||
*/
|
*/
|
||||||
double cachedMinDistance = -1;
|
long cachedMinDistance = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target to notify on generation completion
|
* Target to notify on generation completion
|
||||||
@ -302,11 +302,16 @@ public class BlockDrawCell {
|
|||||||
* @param distCache the lod value under which distance caches are invalidated
|
* @param distCache the lod value under which distance caches are invalidated
|
||||||
* @return the distance
|
* @return the distance
|
||||||
*/
|
*/
|
||||||
public double getMinDistance(Vector3i worldPos, WorldOctTreeNode<BlockDrawCell> node, int distCache){
|
public long getMinDistance(Vector3i worldPos, WorldOctTreeNode<BlockDrawCell> node, int distCache){
|
||||||
if(cachedMinDistance != INVALID_DIST_CACHE && distCache < lod){
|
if(cachedMinDistance != INVALID_DIST_CACHE && distCache < lod){
|
||||||
return cachedMinDistance;
|
return cachedMinDistance;
|
||||||
} else {
|
} else {
|
||||||
this.cachedMinDistance = GeomUtils.getMinSquaredDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
double dist = GeomUtils.approxMinDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
||||||
|
if(Double.isFinite(dist)){
|
||||||
|
this.cachedMinDistance = (long)dist;
|
||||||
|
} else {
|
||||||
|
this.cachedMinDistance = GeomUtils.REALLY_BIG_NUMBER;
|
||||||
|
}
|
||||||
return cachedMinDistance;
|
return cachedMinDistance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,27 +35,27 @@ public class ClientBlockCellManager {
|
|||||||
/**
|
/**
|
||||||
* The distance to draw at full resolution
|
* The distance to draw at full resolution
|
||||||
*/
|
*/
|
||||||
public static final double FULL_RES_DIST = 8 * 8;
|
public static final double FULL_RES_DIST = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for half resolution
|
* The distance for half resolution
|
||||||
*/
|
*/
|
||||||
public static final double HALF_RES_DIST = 16 * 16;
|
public static final double HALF_RES_DIST = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for quarter resolution
|
* The distance for quarter resolution
|
||||||
*/
|
*/
|
||||||
public static final double QUARTER_RES_DIST = 20 * 20;
|
public static final double QUARTER_RES_DIST = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for eighth resolution
|
* The distance for eighth resolution
|
||||||
*/
|
*/
|
||||||
public static final double EIGHTH_RES_DIST = 32 * 32;
|
public static final double EIGHTH_RES_DIST = 32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for sixteenth resolution
|
* The distance for sixteenth resolution
|
||||||
*/
|
*/
|
||||||
public static final double SIXTEENTH_RES_DIST = 64 * 64;
|
public static final double SIXTEENTH_RES_DIST = 64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The octree holding all the chunks to evaluate
|
* The octree holding all the chunks to evaluate
|
||||||
@ -175,7 +175,9 @@ public class ClientBlockCellManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(node.isLeaf()){
|
if(node.isLeaf()){
|
||||||
if(this.shouldSplit(playerPos, node, distCache)){
|
if(this.isMeta(playerPos, node, distCache)){
|
||||||
|
this.flagAsMeta(node);
|
||||||
|
} else if(this.shouldSplit(playerPos, node, distCache)){
|
||||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.split");
|
Globals.profiler.beginCpuSample("ClientDrawCellManager.split");
|
||||||
//perform op
|
//perform op
|
||||||
WorldOctTreeNode<BlockDrawCell> container = chunkTree.split(node);
|
WorldOctTreeNode<BlockDrawCell> container = chunkTree.split(node);
|
||||||
@ -281,12 +283,8 @@ public class ClientBlockCellManager {
|
|||||||
* @param node the node
|
* @param node the node
|
||||||
* @return the distance
|
* @return the distance
|
||||||
*/
|
*/
|
||||||
public double getMinDistance(Vector3i worldPos, WorldOctTreeNode<BlockDrawCell> node, int distCache){
|
public long getMinDistance(Vector3i worldPos, WorldOctTreeNode<BlockDrawCell> node, int distCache){
|
||||||
if(node.getData() == null){
|
return node.getData().getMinDistance(worldPos, node, distCache);
|
||||||
return GeomUtils.getMinSquaredDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
|
||||||
} else {
|
|
||||||
return node.getData().getMinDistance(worldPos, node, distCache);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -429,6 +427,29 @@ public class ClientBlockCellManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this is a meta node
|
||||||
|
* @param pos The position of the player
|
||||||
|
* @param node The node
|
||||||
|
* @param distCache The distance cache
|
||||||
|
* @return true if it is a meta node, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isMeta(Vector3i pos, WorldOctTreeNode<BlockDrawCell> node, int distCache){
|
||||||
|
return
|
||||||
|
node.getLevel() < this.chunkTree.getMaxLevel() - BlockChunkData.LOD_SIXTEENTH_RES &&
|
||||||
|
this.getMinDistance(pos, node, distCache) > SIXTEENTH_RES_DIST
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this node to be a meta node
|
||||||
|
* @param node The node
|
||||||
|
*/
|
||||||
|
private void flagAsMeta(WorldOctTreeNode<BlockDrawCell> node){
|
||||||
|
node.getData().setHasGenerated(true);
|
||||||
|
node.getData().setHomogenous(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether this should be joined or not
|
* Gets whether this should be joined or not
|
||||||
* @param pos the player position
|
* @param pos the player position
|
||||||
@ -818,6 +839,15 @@ public class ClientBlockCellManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of nodes in the tree
|
||||||
|
* @return The number of nodes
|
||||||
|
*/
|
||||||
|
public int getNodeCount(){
|
||||||
|
return this.chunkTree.getNodeCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,8 +33,6 @@ public class ClientWorldData {
|
|||||||
Vector3f worldMinPoint;
|
Vector3f worldMinPoint;
|
||||||
Vector3f worldMaxPoint;
|
Vector3f worldMaxPoint;
|
||||||
|
|
||||||
float randomDampener;
|
|
||||||
|
|
||||||
|
|
||||||
int worldDiscreteSize;
|
int worldDiscreteSize;
|
||||||
|
|
||||||
@ -42,12 +40,10 @@ public class ClientWorldData {
|
|||||||
public ClientWorldData(
|
public ClientWorldData(
|
||||||
Vector3f worldMinPoint,
|
Vector3f worldMinPoint,
|
||||||
Vector3f worldMaxPoint,
|
Vector3f worldMaxPoint,
|
||||||
float randomDampener,
|
|
||||||
int worldDiscreteSize
|
int worldDiscreteSize
|
||||||
) {
|
) {
|
||||||
this.worldMinPoint = worldMinPoint;
|
this.worldMinPoint = worldMinPoint;
|
||||||
this.worldMaxPoint = worldMaxPoint;
|
this.worldMaxPoint = worldMaxPoint;
|
||||||
this.randomDampener = randomDampener;
|
|
||||||
this.worldDiscreteSize = worldDiscreteSize;
|
this.worldDiscreteSize = worldDiscreteSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,10 +58,6 @@ public class ClientWorldData {
|
|||||||
return worldMaxPoint;
|
return worldMaxPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getRandomDampener() {
|
|
||||||
return randomDampener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWorldDiscreteSize() {
|
public int getWorldDiscreteSize() {
|
||||||
return worldDiscreteSize;
|
return worldDiscreteSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,27 +35,27 @@ public class ClientDrawCellManager {
|
|||||||
/**
|
/**
|
||||||
* The distance to draw at full resolution
|
* The distance to draw at full resolution
|
||||||
*/
|
*/
|
||||||
public static final double FULL_RES_DIST = 8 * 8;
|
public static final double FULL_RES_DIST = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for half resolution
|
* The distance for half resolution
|
||||||
*/
|
*/
|
||||||
public static final double HALF_RES_DIST = 16 * 16;
|
public static final double HALF_RES_DIST = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for quarter resolution
|
* The distance for quarter resolution
|
||||||
*/
|
*/
|
||||||
public static final double QUARTER_RES_DIST = 20 * 20;
|
public static final double QUARTER_RES_DIST = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for eighth resolution
|
* The distance for eighth resolution
|
||||||
*/
|
*/
|
||||||
public static final double EIGHTH_RES_DIST = 32 * 32;
|
public static final double EIGHTH_RES_DIST = 32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for sixteenth resolution
|
* The distance for sixteenth resolution
|
||||||
*/
|
*/
|
||||||
public static final double SIXTEENTH_RES_DIST = 128 * 128;
|
public static final double SIXTEENTH_RES_DIST = 128;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lod value for a full res chunk
|
* Lod value for a full res chunk
|
||||||
@ -205,7 +205,9 @@ public class ClientDrawCellManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(node.isLeaf()){
|
if(node.isLeaf()){
|
||||||
if(this.shouldSplit(playerPos, node, distCache)){
|
if(this.isMeta(playerPos, node, distCache)){
|
||||||
|
this.flagAsMeta(node);
|
||||||
|
} else if(this.shouldSplit(playerPos, node, distCache)){
|
||||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.split");
|
Globals.profiler.beginCpuSample("ClientDrawCellManager.split");
|
||||||
//perform op
|
//perform op
|
||||||
WorldOctTreeNode<DrawCell> container = chunkTree.split(node);
|
WorldOctTreeNode<DrawCell> container = chunkTree.split(node);
|
||||||
@ -325,12 +327,8 @@ public class ClientDrawCellManager {
|
|||||||
* @param node the node
|
* @param node the node
|
||||||
* @return the distance
|
* @return the distance
|
||||||
*/
|
*/
|
||||||
public double getMinDistance(Vector3i worldPos, WorldOctTreeNode<DrawCell> node, int distCache){
|
public long getMinDistance(Vector3i worldPos, WorldOctTreeNode<DrawCell> node, int distCache){
|
||||||
if(node.getData() == null){
|
return node.getData().getMinDistance(worldPos, node, distCache);
|
||||||
return GeomUtils.getMinSquaredDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
|
||||||
} else {
|
|
||||||
return node.getData().getMinDistance(worldPos, node, distCache);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -564,6 +562,29 @@ public class ClientDrawCellManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this is a meta node
|
||||||
|
* @param pos The position of the player
|
||||||
|
* @param node The node
|
||||||
|
* @param distCache The distance cache
|
||||||
|
* @return true if it is a meta node, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isMeta(Vector3i pos, WorldOctTreeNode<DrawCell> node, int distCache){
|
||||||
|
return
|
||||||
|
node.getLevel() < this.chunkTree.getMaxLevel() - SIXTEENTH_RES_LOD &&
|
||||||
|
this.getMinDistance(pos, node, distCache) > SIXTEENTH_RES_DIST
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this node to be a meta node
|
||||||
|
* @param node The node
|
||||||
|
*/
|
||||||
|
private void flagAsMeta(WorldOctTreeNode<DrawCell> node){
|
||||||
|
node.getData().setHasGenerated(true);
|
||||||
|
node.getData().setHomogenous(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether this should be joined or not
|
* Gets whether this should be joined or not
|
||||||
* @param pos the player position
|
* @param pos the player position
|
||||||
@ -1001,6 +1022,14 @@ public class ClientDrawCellManager {
|
|||||||
return halfResCount;
|
return halfResCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of nodes in the tree
|
||||||
|
* @return The number of nodes
|
||||||
|
*/
|
||||||
|
public int getNodeCount(){
|
||||||
|
return this.chunkTree.getNodeCount();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets The number of generated chunks
|
* Gets The number of generated chunks
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
@ -91,7 +91,7 @@ public class DrawCell {
|
|||||||
/**
|
/**
|
||||||
* The cached minimum distance
|
* The cached minimum distance
|
||||||
*/
|
*/
|
||||||
double cachedMinDistance = -1;
|
long cachedMinDistance = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target to notify on generation completion
|
* Target to notify on generation completion
|
||||||
@ -579,11 +579,16 @@ public class DrawCell {
|
|||||||
* @param distCache the lod value under which distance caches are invalidated
|
* @param distCache the lod value under which distance caches are invalidated
|
||||||
* @return the distance
|
* @return the distance
|
||||||
*/
|
*/
|
||||||
public double getMinDistance(Vector3i worldPos, WorldOctTreeNode<DrawCell> node, int distCache){
|
public long getMinDistance(Vector3i worldPos, WorldOctTreeNode<DrawCell> node, int distCache){
|
||||||
if(cachedMinDistance != INVALID_DIST_CACHE && distCache < lod){
|
if(cachedMinDistance != INVALID_DIST_CACHE && distCache < lod){
|
||||||
return cachedMinDistance;
|
return cachedMinDistance;
|
||||||
} else {
|
} else {
|
||||||
this.cachedMinDistance = GeomUtils.getMinSquaredDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
double dist = GeomUtils.approxMinDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
||||||
|
if(Double.isFinite(dist)){
|
||||||
|
this.cachedMinDistance = (long)dist;
|
||||||
|
} else {
|
||||||
|
this.cachedMinDistance = GeomUtils.REALLY_BIG_NUMBER;
|
||||||
|
}
|
||||||
return cachedMinDistance;
|
return cachedMinDistance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -190,7 +190,7 @@ public class FoliageCell {
|
|||||||
/**
|
/**
|
||||||
* The cached minimum distance
|
* The cached minimum distance
|
||||||
*/
|
*/
|
||||||
double cachedMinDistance = -1;
|
long cachedMinDistance = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target to notify on generation completion
|
* Target to notify on generation completion
|
||||||
@ -670,11 +670,16 @@ public class FoliageCell {
|
|||||||
* @param distCache the lod value under which distance caches are invalidated
|
* @param distCache the lod value under which distance caches are invalidated
|
||||||
* @return the distance
|
* @return the distance
|
||||||
*/
|
*/
|
||||||
public double getMinDistance(Vector3i worldPos, WorldOctTreeNode<FoliageCell> node, int distCache){
|
public long getMinDistance(Vector3i worldPos, WorldOctTreeNode<FoliageCell> node, int distCache){
|
||||||
if(cachedMinDistance != INVALID_DIST_CACHE && distCache < lod){
|
if(cachedMinDistance != INVALID_DIST_CACHE && distCache < lod){
|
||||||
return cachedMinDistance;
|
return cachedMinDistance;
|
||||||
} else {
|
} else {
|
||||||
this.cachedMinDistance = GeomUtils.getMinSquaredDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
double dist = GeomUtils.approxMinDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
||||||
|
if(Double.isFinite(dist)){
|
||||||
|
this.cachedMinDistance = (long)dist;
|
||||||
|
} else {
|
||||||
|
this.cachedMinDistance = GeomUtils.REALLY_BIG_NUMBER;
|
||||||
|
}
|
||||||
return cachedMinDistance;
|
return cachedMinDistance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,27 +35,27 @@ public class FoliageCellManager {
|
|||||||
/**
|
/**
|
||||||
* The distance to foliage at full resolution
|
* The distance to foliage at full resolution
|
||||||
*/
|
*/
|
||||||
public static final double FULL_RES_DIST = 16 * 16;
|
public static final double FULL_RES_DIST = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for half resolution
|
* The distance for half resolution
|
||||||
*/
|
*/
|
||||||
public static final double HALF_RES_DIST = 20 * 20;
|
public static final double HALF_RES_DIST = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for quarter resolution
|
* The distance for quarter resolution
|
||||||
*/
|
*/
|
||||||
public static final double QUARTER_RES_DIST = 16 * 16;
|
public static final double QUARTER_RES_DIST = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for eighth resolution
|
* The distance for eighth resolution
|
||||||
*/
|
*/
|
||||||
public static final double EIGHTH_RES_DIST = 24 * 24;
|
public static final double EIGHTH_RES_DIST = 24;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distance for sixteenth resolution
|
* The distance for sixteenth resolution
|
||||||
*/
|
*/
|
||||||
public static final double SIXTEENTH_RES_DIST = 64 * 64;
|
public static final double SIXTEENTH_RES_DIST = 64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lod value for a full res chunk
|
* Lod value for a full res chunk
|
||||||
@ -211,7 +211,9 @@ public class FoliageCellManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(node.isLeaf()){
|
if(node.isLeaf()){
|
||||||
if(this.shouldSplit(absVoxelPos, node, distCache)){
|
if(this.isMeta(absVoxelPos, node, distCache)){
|
||||||
|
this.flagAsMeta(node);
|
||||||
|
} else if(this.shouldSplit(absVoxelPos, node, distCache)){
|
||||||
Globals.profiler.beginCpuSample("FoliageCellManager.split");
|
Globals.profiler.beginCpuSample("FoliageCellManager.split");
|
||||||
//perform op
|
//perform op
|
||||||
WorldOctTreeNode<FoliageCell> container = chunkTree.split(node);
|
WorldOctTreeNode<FoliageCell> container = chunkTree.split(node);
|
||||||
@ -338,12 +340,8 @@ public class FoliageCellManager {
|
|||||||
* @param node the node
|
* @param node the node
|
||||||
* @return the distance
|
* @return the distance
|
||||||
*/
|
*/
|
||||||
public double getMinDistance(Vector3i worldPos, WorldOctTreeNode<FoliageCell> node, int distCache){
|
public long getMinDistance(Vector3i worldPos, WorldOctTreeNode<FoliageCell> node, int distCache){
|
||||||
if(node.getData() == null){
|
return node.getData().getMinDistance(worldPos, node, distCache);
|
||||||
return GeomUtils.getMinSquaredDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
|
||||||
} else {
|
|
||||||
return node.getData().getMinDistance(worldPos, node, distCache);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -486,6 +484,29 @@ public class FoliageCellManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this is a meta node
|
||||||
|
* @param pos The position of the player
|
||||||
|
* @param node The node
|
||||||
|
* @param distCache The distance cache
|
||||||
|
* @return true if it is a meta node, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isMeta(Vector3i pos, WorldOctTreeNode<FoliageCell> node, int distCache){
|
||||||
|
return
|
||||||
|
node.getLevel() < this.chunkTree.getMaxLevel() - SIXTEENTH_RES_LOD &&
|
||||||
|
this.getMinDistance(pos, node, distCache) > SIXTEENTH_RES_DIST
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this node to be a meta node
|
||||||
|
* @param node The node
|
||||||
|
*/
|
||||||
|
private void flagAsMeta(WorldOctTreeNode<FoliageCell> node){
|
||||||
|
node.getData().setHasGenerated(true);
|
||||||
|
node.getData().setHomogenous(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether this should be joined or not
|
* Gets whether this should be joined or not
|
||||||
* @param pos the player position
|
* @param pos the player position
|
||||||
@ -865,6 +886,13 @@ public class FoliageCellManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of nodes in the tree
|
||||||
|
* @return The number of nodes
|
||||||
|
*/
|
||||||
|
public int getNodeCount(){
|
||||||
|
return this.chunkTree.getNodeCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,8 +36,17 @@ public class ImGuiChunkMonitor {
|
|||||||
//ui framework text
|
//ui framework text
|
||||||
ImGui.text("Chunk Monitor");
|
ImGui.text("Chunk Monitor");
|
||||||
|
|
||||||
Globals.clientDrawCellManager.updateStatus();
|
if(Globals.clientDrawCellManager != null){
|
||||||
ImGui.text("Full res chunks: " + Globals.clientDrawCellManager.getMaxResCount());
|
Globals.clientDrawCellManager.updateStatus();
|
||||||
|
ImGui.text("Full res chunks: " + Globals.clientDrawCellManager.getMaxResCount());
|
||||||
|
ImGui.text("Terrain node count: " + Globals.clientDrawCellManager.getNodeCount());
|
||||||
|
}
|
||||||
|
if(Globals.clientBlockCellManager != null){
|
||||||
|
ImGui.text("Block node count: " + Globals.clientBlockCellManager.getNodeCount());
|
||||||
|
}
|
||||||
|
if(Globals.foliageCellManager != null){
|
||||||
|
ImGui.text("Foliage node count: " + Globals.foliageCellManager.getNodeCount());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
chunkMonitorWindow.setOpen(false);
|
chunkMonitorWindow.setOpen(false);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import electrosphere.server.terrain.generation.DefaultChunkGenerator;
|
|||||||
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
|
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.server.terrain.models.TerrainModel;
|
||||||
import electrosphere.util.FileUtils;
|
import electrosphere.util.FileUtils;
|
||||||
|
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
@ -21,7 +22,7 @@ public class ServerWorldData {
|
|||||||
/**
|
/**
|
||||||
* The size of the procedural world
|
* The size of the procedural world
|
||||||
*/
|
*/
|
||||||
public static final int PROCEDURAL_WORLD_SIZE = 2000;
|
public static final int PROCEDURAL_WORLD_SIZE = TerrainModel.MAX_WORLD_SIZE_DISCRETE;
|
||||||
|
|
||||||
public static enum WorldType {
|
public static enum WorldType {
|
||||||
GAME_WORLD,
|
GAME_WORLD,
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import electrosphere.engine.Globals;
|
|||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||||
import electrosphere.net.template.ClientProtocolTemplate;
|
import electrosphere.net.template.ClientProtocolTemplate;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The client protocol for handling terrain messages
|
* The client protocol for handling terrain messages
|
||||||
@ -35,15 +34,14 @@ public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
|
|||||||
//Vector3f worldMinPoint, Vector3f worldMaxPoint, int dynamicInterpolationRatio, float randomDampener, int worldDiscreteSize
|
//Vector3f worldMinPoint, Vector3f worldMaxPoint, int dynamicInterpolationRatio, float randomDampener, int worldDiscreteSize
|
||||||
new Vector3f(
|
new Vector3f(
|
||||||
message.getworldMinX(),
|
message.getworldMinX(),
|
||||||
0,
|
message.getworldMinY(),
|
||||||
message.getworldMinY()
|
message.getworldMinZ()
|
||||||
),
|
),
|
||||||
new Vector3f(
|
new Vector3f(
|
||||||
message.getworldMaxX(),
|
message.getworldMaxX(),
|
||||||
(int)(message.getworldSizeDiscrete() * ServerTerrainChunk.CHUNK_DIMENSION),
|
message.getworldMaxY(),
|
||||||
message.getworldMaxY()
|
message.getworldMaxZ()
|
||||||
),
|
),
|
||||||
message.getrandomDampener(),
|
|
||||||
message.getworldSizeDiscrete()
|
message.getworldSizeDiscrete()
|
||||||
);
|
);
|
||||||
Globals.clientSceneWrapper.getCollisionEngine().setCollisionWorldData(new CollisionWorldData(Globals.clientWorldData));
|
Globals.clientSceneWrapper.getCollisionEngine().setCollisionWorldData(new CollisionWorldData(Globals.clientWorldData));
|
||||||
|
|||||||
@ -37,8 +37,10 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
float randomDampener;
|
float randomDampener;
|
||||||
int worldMinX;
|
int worldMinX;
|
||||||
int worldMinY;
|
int worldMinY;
|
||||||
|
int worldMinZ;
|
||||||
int worldMaxX;
|
int worldMaxX;
|
||||||
int worldMaxY;
|
int worldMaxY;
|
||||||
|
int worldMaxZ;
|
||||||
float value;
|
float value;
|
||||||
int worldX;
|
int worldX;
|
||||||
int worldY;
|
int worldY;
|
||||||
@ -138,6 +140,20 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
this.worldMinY = worldMinY;
|
this.worldMinY = worldMinY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets worldMinZ
|
||||||
|
*/
|
||||||
|
public int getworldMinZ() {
|
||||||
|
return worldMinZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets worldMinZ
|
||||||
|
*/
|
||||||
|
public void setworldMinZ(int worldMinZ) {
|
||||||
|
this.worldMinZ = worldMinZ;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets worldMaxX
|
* Gets worldMaxX
|
||||||
*/
|
*/
|
||||||
@ -166,6 +182,20 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
this.worldMaxY = worldMaxY;
|
this.worldMaxY = worldMaxY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets worldMaxZ
|
||||||
|
*/
|
||||||
|
public int getworldMaxZ() {
|
||||||
|
return worldMaxZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets worldMaxZ
|
||||||
|
*/
|
||||||
|
public void setworldMaxZ(int worldMaxZ) {
|
||||||
|
this.worldMaxZ = worldMaxZ;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets value
|
* Gets value
|
||||||
*/
|
*/
|
||||||
@ -491,27 +521,27 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.RESPONSEMETADATA);
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.RESPONSEMETADATA);
|
||||||
stripPacketHeader(byteBuffer);
|
stripPacketHeader(byteBuffer);
|
||||||
rVal.setworldSizeDiscrete(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
rVal.setworldSizeDiscrete(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
rVal.setdynamicInterpolationRatio(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
|
||||||
rVal.setrandomDampener(ByteStreamUtils.popFloatFromByteQueue(byteBuffer));
|
|
||||||
rVal.setworldMinX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
rVal.setworldMinX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
rVal.setworldMinY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
rVal.setworldMinY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setworldMinZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
rVal.setworldMaxX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
rVal.setworldMaxX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
rVal.setworldMaxY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
rVal.setworldMaxY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setworldMaxZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a message of type ResponseMetadata
|
* Constructs a message of type ResponseMetadata
|
||||||
*/
|
*/
|
||||||
public static TerrainMessage constructResponseMetadataMessage(int worldSizeDiscrete,int dynamicInterpolationRatio,float randomDampener,int worldMinX,int worldMinY,int worldMaxX,int worldMaxY){
|
public static TerrainMessage constructResponseMetadataMessage(int worldSizeDiscrete,int worldMinX,int worldMinY,int worldMinZ,int worldMaxX,int worldMaxY,int worldMaxZ){
|
||||||
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.RESPONSEMETADATA);
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.RESPONSEMETADATA);
|
||||||
rVal.setworldSizeDiscrete(worldSizeDiscrete);
|
rVal.setworldSizeDiscrete(worldSizeDiscrete);
|
||||||
rVal.setdynamicInterpolationRatio(dynamicInterpolationRatio);
|
|
||||||
rVal.setrandomDampener(randomDampener);
|
|
||||||
rVal.setworldMinX(worldMinX);
|
rVal.setworldMinX(worldMinX);
|
||||||
rVal.setworldMinY(worldMinY);
|
rVal.setworldMinY(worldMinY);
|
||||||
|
rVal.setworldMinZ(worldMinZ);
|
||||||
rVal.setworldMaxX(worldMaxX);
|
rVal.setworldMaxX(worldMaxX);
|
||||||
rVal.setworldMaxY(worldMaxY);
|
rVal.setworldMaxY(worldMaxY);
|
||||||
|
rVal.setworldMaxZ(worldMaxZ);
|
||||||
rVal.serialize();
|
rVal.serialize();
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
@ -1064,26 +1094,27 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[2+i] = intValues[i];
|
rawBytes[2+i] = intValues[i];
|
||||||
}
|
}
|
||||||
intValues = ByteStreamUtils.serializeIntToBytes(dynamicInterpolationRatio);
|
intValues = ByteStreamUtils.serializeIntToBytes(worldMinX);
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[6+i] = intValues[i];
|
rawBytes[6+i] = intValues[i];
|
||||||
}
|
}
|
||||||
intValues = ByteStreamUtils.serializeFloatToBytes(randomDampener);
|
intValues = ByteStreamUtils.serializeIntToBytes(worldMinY);
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[10+i] = intValues[i];
|
rawBytes[10+i] = intValues[i];
|
||||||
} intValues = ByteStreamUtils.serializeIntToBytes(worldMinX);
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(worldMinZ);
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[14+i] = intValues[i];
|
rawBytes[14+i] = intValues[i];
|
||||||
}
|
}
|
||||||
intValues = ByteStreamUtils.serializeIntToBytes(worldMinY);
|
intValues = ByteStreamUtils.serializeIntToBytes(worldMaxX);
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[18+i] = intValues[i];
|
rawBytes[18+i] = intValues[i];
|
||||||
}
|
}
|
||||||
intValues = ByteStreamUtils.serializeIntToBytes(worldMaxX);
|
intValues = ByteStreamUtils.serializeIntToBytes(worldMaxY);
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[22+i] = intValues[i];
|
rawBytes[22+i] = intValues[i];
|
||||||
}
|
}
|
||||||
intValues = ByteStreamUtils.serializeIntToBytes(worldMaxY);
|
intValues = ByteStreamUtils.serializeIntToBytes(worldMaxZ);
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[26+i] = intValues[i];
|
rawBytes[26+i] = intValues[i];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -359,11 +359,11 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
|
|||||||
connectionHandler.addMessagetoOutgoingQueue(
|
connectionHandler.addMessagetoOutgoingQueue(
|
||||||
TerrainMessage.constructResponseMetadataMessage(
|
TerrainMessage.constructResponseMetadataMessage(
|
||||||
realm.getServerWorldData().getWorldSizeDiscrete(),
|
realm.getServerWorldData().getWorldSizeDiscrete(),
|
||||||
realm.getServerWorldData().getDynamicInterpolationRatio(),
|
|
||||||
0,
|
|
||||||
(int)realm.getServerWorldData().getWorldBoundMin().x,
|
(int)realm.getServerWorldData().getWorldBoundMin().x,
|
||||||
|
(int)realm.getServerWorldData().getWorldBoundMin().y,
|
||||||
(int)realm.getServerWorldData().getWorldBoundMin().z,
|
(int)realm.getServerWorldData().getWorldBoundMin().z,
|
||||||
(int)realm.getServerWorldData().getWorldBoundMax().x,
|
(int)realm.getServerWorldData().getWorldBoundMax().x,
|
||||||
|
(int)realm.getServerWorldData().getWorldBoundMax().y,
|
||||||
(int)realm.getServerWorldData().getWorldBoundMax().z
|
(int)realm.getServerWorldData().getWorldBoundMax().z
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -78,18 +78,19 @@ public class OverworldChunkGenerator implements ChunkGenerator {
|
|||||||
* @return The heightmap array
|
* @return The heightmap array
|
||||||
*/
|
*/
|
||||||
private float[][] getHeightmap(int worldX, int worldZ){
|
private float[][] getHeightmap(int worldX, int worldZ){
|
||||||
String key = worldX + "_" + worldZ;
|
// String key = worldX + "_" + worldZ;
|
||||||
if(heightmapCache.containsKey(key)){
|
// if(heightmapCache.containsKey(key)){
|
||||||
return heightmapCache.get(key);
|
// return heightmapCache.get(key);
|
||||||
} else {
|
// } else {
|
||||||
float[][] macroValues = model.getRad5MacroValuesAtPosition(worldX, worldZ);
|
// float[][] macroValues = model.getRad5MacroValuesAtPosition(worldX, worldZ);
|
||||||
float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
|
// float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
|
||||||
macroValues,
|
// macroValues,
|
||||||
model.getDynamicInterpolationRatio()
|
// model.getDynamicInterpolationRatio()
|
||||||
);
|
// );
|
||||||
heightmapCache.put(key,heightmap);
|
// heightmapCache.put(key,heightmap);
|
||||||
return heightmap;
|
// return heightmap;
|
||||||
}
|
// }
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -162,13 +162,14 @@ public class TerrainGenerator {
|
|||||||
erosionSimulation.simulate();
|
erosionSimulation.simulate();
|
||||||
erosionHeightmap = erosionSimulation.getData();
|
erosionHeightmap = erosionSimulation.getData();
|
||||||
|
|
||||||
rVal = new TerrainModel(
|
// rVal = new TerrainModel(
|
||||||
interpolationPhaseDimension,
|
// interpolationPhaseDimension,
|
||||||
modelInput,
|
// modelInput,
|
||||||
OCEAN_THRESHOLD * verticalInterpolationRatio,
|
// OCEAN_THRESHOLD * verticalInterpolationRatio,
|
||||||
MOUNTAIN_THRESHOLD * verticalInterpolationRatio,
|
// MOUNTAIN_THRESHOLD * verticalInterpolationRatio,
|
||||||
dynamicInterpRatio
|
// dynamicInterpRatio
|
||||||
);
|
// );
|
||||||
|
rVal = TerrainModel.create();
|
||||||
|
|
||||||
|
|
||||||
//create internal renderer
|
//create internal renderer
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
package electrosphere.server.terrain.generation.macro;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default approach to generating macro data
|
||||||
|
*/
|
||||||
|
public class DefaultMacroGenerator implements MacroGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default surface biome
|
||||||
|
*/
|
||||||
|
static final short DEFAULT_SURFACE_BIOME = 1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generate(TerrainModel model) {
|
||||||
|
int DIM = model.getDiscreteArrayDimension();
|
||||||
|
float[][] elevation = model.getElevation();
|
||||||
|
short[][] biome = model.getBiome();
|
||||||
|
|
||||||
|
for(int x = 0; x < DIM; x++){
|
||||||
|
for(int y = 0; y < DIM; y++){
|
||||||
|
elevation[x][y] = 1;
|
||||||
|
biome[x][y] = DEFAULT_SURFACE_BIOME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model.setElevationArray(elevation);
|
||||||
|
model.setBiome(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package electrosphere.server.terrain.generation.macro;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates a terrain model's macro data
|
||||||
|
*/
|
||||||
|
public interface MacroGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the macro data in a terrain model
|
||||||
|
* @param model The terrain model
|
||||||
|
*/
|
||||||
|
public void generate(TerrainModel model);
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,8 +5,8 @@ import electrosphere.engine.Globals;
|
|||||||
import electrosphere.game.server.world.ServerWorldData;
|
import electrosphere.game.server.world.ServerWorldData;
|
||||||
import electrosphere.server.terrain.diskmap.ChunkDiskMap;
|
import electrosphere.server.terrain.diskmap.ChunkDiskMap;
|
||||||
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
|
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
|
||||||
import electrosphere.server.terrain.generation.continentphase.TerrainGenerator;
|
|
||||||
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
||||||
|
import electrosphere.server.terrain.generation.macro.DefaultMacroGenerator;
|
||||||
import electrosphere.server.terrain.models.TerrainModel;
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
import electrosphere.server.terrain.models.TerrainModification;
|
import electrosphere.server.terrain.models.TerrainModification;
|
||||||
import electrosphere.util.FileUtils;
|
import electrosphere.util.FileUtils;
|
||||||
@ -14,6 +14,7 @@ import electrosphere.util.annotation.Exclude;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -99,13 +100,10 @@ public class ServerTerrainManager {
|
|||||||
* Generates a terrain model for the manager
|
* Generates a terrain model for the manager
|
||||||
*/
|
*/
|
||||||
public void generate(){
|
public void generate(){
|
||||||
TerrainGenerator terrainGen = new TerrainGenerator();
|
this.model = TerrainModel.create();
|
||||||
terrainGen.setInterpolationRatio(parent.getWorldSizeDiscrete()/200);
|
DefaultMacroGenerator generator = new DefaultMacroGenerator();
|
||||||
terrainGen.setVerticalInterpolationRatio(parent.getWorldSizeDiscrete());
|
generator.generate(this.model);
|
||||||
terrainGen.setRandomSeed(seed);
|
this.chunkGenerator.setModel(this.model);
|
||||||
model = terrainGen.generateModel();
|
|
||||||
this.chunkGenerator.setModel(model);
|
|
||||||
model.setInterpolationRandomDampener(SERVER_TERRAIN_MANAGER_DAMPENER);
|
|
||||||
this.chunkDiskMap = ChunkDiskMap.init();
|
this.chunkDiskMap = ChunkDiskMap.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,16 +113,38 @@ public class ServerTerrainManager {
|
|||||||
*/
|
*/
|
||||||
public void save(String saveName){
|
public void save(String saveName){
|
||||||
if(model != null){
|
if(model != null){
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(model.getElevation().length * model.getElevation()[0].length * 4);
|
if(model.getDiscreteArrayDimension() < 1){
|
||||||
FloatBuffer floatView = buffer.asFloatBuffer();
|
throw new Error("Invalid terrain macro data size!");
|
||||||
for(int x = 0; x < model.getElevation().length; x++){
|
}
|
||||||
floatView.put(model.getElevation()[x]);
|
|
||||||
|
//save the model itself
|
||||||
|
FileUtils.serializeObjectToSavePath(saveName, "./terrain.json", model);
|
||||||
|
|
||||||
|
//save the elevation array
|
||||||
|
ByteBuffer floatBuff = ByteBuffer.allocate(model.getDiscreteArrayDimension() * model.getDiscreteArrayDimension() * 4);
|
||||||
|
FloatBuffer floatView = floatBuff.asFloatBuffer();
|
||||||
|
for(int x = 0; x < model.getDiscreteArrayDimension(); x++){
|
||||||
|
for(int y = 0; y < model.getDiscreteArrayDimension(); y++){
|
||||||
|
floatView.put(model.getElevation()[x][y]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(floatView.position() > 0){
|
if(floatView.position() > 0){
|
||||||
floatView.flip();
|
floatView.flip();
|
||||||
}
|
}
|
||||||
FileUtils.serializeObjectToSavePath(saveName, "./terrain.json", model);
|
FileUtils.saveBinaryToSavePath(saveName, "./terrain.dat", floatBuff.array());
|
||||||
FileUtils.saveBinaryToSavePath(saveName, "./terrain.dat", buffer.array());
|
|
||||||
|
//save the biome array
|
||||||
|
ByteBuffer shortBuff = ByteBuffer.allocate(model.getDiscreteArrayDimension() * model.getDiscreteArrayDimension() * 2);
|
||||||
|
ShortBuffer shortView = shortBuff.asShortBuffer();
|
||||||
|
for(int x = 0; x < model.getDiscreteArrayDimension(); x++){
|
||||||
|
for(int y = 0; y < model.getDiscreteArrayDimension(); y++){
|
||||||
|
shortView.put(model.getBiome()[x][y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(shortView.position() > 0){
|
||||||
|
shortView.flip();
|
||||||
|
}
|
||||||
|
FileUtils.saveBinaryToSavePath(saveName, "./biome.dat", shortBuff.array());
|
||||||
}
|
}
|
||||||
//for each chunk, save via disk map
|
//for each chunk, save via disk map
|
||||||
for(ServerTerrainChunk chunk : this.chunkCache.getContents()){
|
for(ServerTerrainChunk chunk : this.chunkCache.getContents()){
|
||||||
@ -143,18 +163,41 @@ public class ServerTerrainManager {
|
|||||||
public void load(String saveName){
|
public void load(String saveName){
|
||||||
//load terrain model
|
//load terrain model
|
||||||
if(FileUtils.getSaveFile(saveName, "./terrain.json").exists()){
|
if(FileUtils.getSaveFile(saveName, "./terrain.json").exists()){
|
||||||
|
|
||||||
|
//read the model itself
|
||||||
model = FileUtils.loadObjectFromSavePath(saveName, "./terrain.json", TerrainModel.class);
|
model = FileUtils.loadObjectFromSavePath(saveName, "./terrain.json", TerrainModel.class);
|
||||||
chunkGenerator.setModel(model);
|
chunkGenerator.setModel(model);
|
||||||
byte[] data = FileUtils.loadBinaryFromSavePath(saveName, "./terrain.dat");
|
if(model.getDiscreteArrayDimension() < 1){
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(data);
|
throw new Error("Invalid terrain macro data size!");
|
||||||
FloatBuffer floatView = buffer.asFloatBuffer();
|
}
|
||||||
float[][] elevation = new float[parent.getWorldSizeDiscrete()][parent.getWorldSizeDiscrete()];
|
|
||||||
for(int x = 0; x < parent.getWorldSizeDiscrete(); x++){
|
//read the elevation data
|
||||||
for(int y = 0; y < parent.getWorldSizeDiscrete(); y++){
|
float[][] elevation = new float[model.getDiscreteArrayDimension()][model.getDiscreteArrayDimension()];
|
||||||
elevation[x][y] = floatView.get();
|
if(FileUtils.checkSavePathExists(saveName, "./terrain.dat")){
|
||||||
|
byte[] data = FileUtils.loadBinaryFromSavePath(saveName, "./terrain.dat");
|
||||||
|
ByteBuffer buffer = ByteBuffer.wrap(data);
|
||||||
|
FloatBuffer floatView = buffer.asFloatBuffer();
|
||||||
|
for(int x = 0; x < model.getDiscreteArrayDimension(); x++){
|
||||||
|
for(int y = 0; y < model.getDiscreteArrayDimension(); y++){
|
||||||
|
elevation[x][y] = floatView.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model.setElevationArray(elevation);
|
model.setElevationArray(elevation);
|
||||||
|
|
||||||
|
//read the biome data
|
||||||
|
short[][] biome = new short[model.getDiscreteArrayDimension()][model.getDiscreteArrayDimension()];
|
||||||
|
if(FileUtils.checkSavePathExists(saveName, "./biome.dat")){
|
||||||
|
byte[] data = FileUtils.loadBinaryFromSavePath(saveName, "./biome.dat");
|
||||||
|
ByteBuffer buffer = ByteBuffer.wrap(data);
|
||||||
|
ShortBuffer shortView = buffer.asShortBuffer();
|
||||||
|
for(int x = 0; x < model.getDiscreteArrayDimension(); x++){
|
||||||
|
for(int y = 0; y < model.getDiscreteArrayDimension(); y++){
|
||||||
|
biome[x][y] = shortView.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.setBiome(biome);
|
||||||
}
|
}
|
||||||
//load chunk disk map
|
//load chunk disk map
|
||||||
chunkDiskMap = ChunkDiskMap.init(saveName);
|
chunkDiskMap = ChunkDiskMap.init(saveName);
|
||||||
@ -176,10 +219,6 @@ public class ServerTerrainManager {
|
|||||||
this.chunkCache.clear();
|
this.chunkCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public float[][] getTerrainAtChunk(int x, int y){
|
|
||||||
return model.getElevationForChunk(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getDiscreteValue(int x, int y){
|
public float getDiscreteValue(int x, int y){
|
||||||
if(model != null){
|
if(model != null){
|
||||||
return model.getElevation()[x][y];
|
return model.getElevation()[x][y];
|
||||||
@ -187,26 +226,6 @@ public class ServerTerrainManager {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDynamicInterpolationRatio(){
|
|
||||||
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
|
||||||
if(model != null){
|
|
||||||
return model.getDynamicInterpolationRatio();
|
|
||||||
} else {
|
|
||||||
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getRandomDampener(){
|
|
||||||
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
|
||||||
if(model != null){
|
|
||||||
return model.getRandomDampener();
|
|
||||||
} else {
|
|
||||||
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the terrain model backing this terrain manager
|
* Gets the terrain model backing this terrain manager
|
||||||
|
|||||||
@ -14,29 +14,24 @@ public class TerrainModel {
|
|||||||
/**
|
/**
|
||||||
* Maximum size of the macro data
|
* Maximum size of the macro data
|
||||||
*/
|
*/
|
||||||
public static final int MAX_MACRO_DATA_SIZE = 2000;
|
public static final int MAX_MACRO_DATA_SIZE = 2048;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The scale of the macro data
|
* The scale of the macro data
|
||||||
*/
|
*/
|
||||||
public static final int DEFAULT_MACRO_DATA_SCALE = 32;
|
public static final int DEFAULT_MACRO_DATA_SCALE = 32;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dynamic interpolation ratio
|
* The maximum discrete world size
|
||||||
*/
|
*/
|
||||||
int dynamicInterpolationRatio;
|
public static final int MAX_WORLD_SIZE_DISCRETE = MAX_MACRO_DATA_SIZE * DEFAULT_MACRO_DATA_SCALE;
|
||||||
|
|
||||||
/**
|
|
||||||
* The interpolation dampener
|
|
||||||
*/
|
|
||||||
float interpolationRandomDampener = 0.4f;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The discrete array dimension of the model
|
* The discrete array dimension of the model
|
||||||
*/
|
*/
|
||||||
int discreteArrayDimension;
|
int discreteArrayDimension = MAX_MACRO_DATA_SIZE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The macro level elevation data
|
* The macro level elevation data
|
||||||
@ -78,28 +73,16 @@ public class TerrainModel {
|
|||||||
*/
|
*/
|
||||||
TerrainModel() {
|
TerrainModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Creates the default terrain model
|
||||||
* @param dimension The dimension of the model
|
* @return The default terrain 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 static TerrainModel create(){
|
||||||
int dimension,
|
TerrainModel rVal = new TerrainModel();
|
||||||
float[][] elevation,
|
rVal.elevation = new float[rVal.discreteArrayDimension][rVal.discreteArrayDimension];
|
||||||
float realOceanThreshold,
|
rVal.biome = new short[rVal.discreteArrayDimension][rVal.discreteArrayDimension];
|
||||||
float realMountainThreshold,
|
return rVal;
|
||||||
int dynamicInterpolationRatio
|
|
||||||
){
|
|
||||||
|
|
||||||
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
|
|
||||||
this.discreteArrayDimension = dimension;
|
|
||||||
this.elevation = elevation;
|
|
||||||
this.realMountainThreshold = realMountainThreshold;
|
|
||||||
this.realOceanThreshold = realOceanThreshold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,10 +91,9 @@ public class TerrainModel {
|
|||||||
* @param dynamicInterpolationRatio The dynamic interpolation ratio
|
* @param dynamicInterpolationRatio The dynamic interpolation ratio
|
||||||
* @return The terrain model
|
* @return The terrain model
|
||||||
*/
|
*/
|
||||||
public static TerrainModel constructTerrainModel(int dimension, int dynamicInterpolationRatio){
|
public static TerrainModel constructTerrainModel(int dimension){
|
||||||
TerrainModel rVal = new TerrainModel();
|
TerrainModel rVal = new TerrainModel();
|
||||||
rVal.discreteArrayDimension = dimension;
|
rVal.discreteArrayDimension = dimension;
|
||||||
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
|
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +104,6 @@ public class TerrainModel {
|
|||||||
public static TerrainModel generateTestModel(){
|
public static TerrainModel generateTestModel(){
|
||||||
TerrainModel rVal = new TerrainModel();
|
TerrainModel rVal = new TerrainModel();
|
||||||
rVal.discreteArrayDimension = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
rVal.discreteArrayDimension = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE;
|
||||||
rVal.dynamicInterpolationRatio = 1;
|
|
||||||
int macroDataImageScale = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE / DEFAULT_MACRO_DATA_SCALE + 1;
|
int macroDataImageScale = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE / DEFAULT_MACRO_DATA_SCALE + 1;
|
||||||
rVal.biome = new short[macroDataImageScale][macroDataImageScale];
|
rVal.biome = new short[macroDataImageScale][macroDataImageScale];
|
||||||
for(int x = 0; x < macroDataImageScale; x++){
|
for(int x = 0; x < macroDataImageScale; x++){
|
||||||
@ -149,290 +130,13 @@ public class TerrainModel {
|
|||||||
public short[][] getBiome(){
|
public short[][] getBiome(){
|
||||||
return biome;
|
return biome;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the interpolation random dampener
|
* Sets the biome array
|
||||||
* @param f The interpolation random dampener
|
* @param biome The biome array
|
||||||
*/
|
*/
|
||||||
public void setInterpolationRandomDampener(float f){
|
public void setBiome(short[][] biome){
|
||||||
interpolationRandomDampener = f;
|
this.biome = biome;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dynamically interpolates a chunk of a specific size from the pre-existing elevation map
|
|
||||||
* @param x The x position on the elevation map to get a chunk from
|
|
||||||
* @param y The y position on the elevation map to get a chunk from
|
|
||||||
* @return Dynamically interpolated float array of elevations of chunk
|
|
||||||
*/
|
|
||||||
public float[][] getElevationForChunk(int x, int y){
|
|
||||||
|
|
||||||
//this is what we intend to return from the function
|
|
||||||
float[][] rVal = new float[dynamicInterpolationRatio][dynamicInterpolationRatio];
|
|
||||||
|
|
||||||
/*
|
|
||||||
So we're looking at chunk x,y
|
|
||||||
|
|
||||||
if this is our grid:
|
|
||||||
|
|
||||||
4 0.1 0.2 0.3 0.4
|
|
||||||
^
|
|
||||||
| 3 0.1 0.2 0.3 0.4
|
|
||||||
|
|
|
||||||
| 2 0.1 0.2 0.3 0.4
|
|
||||||
|
|
||||||
x 1 0.1 0.2 0.3 0.4
|
|
||||||
|
|
||||||
0 1 2 3
|
|
||||||
|
|
||||||
y ---- >
|
|
||||||
|
|
||||||
say we're looking at x=2,y=1
|
|
||||||
|
|
||||||
"macroValues" should contain the values for bounds x = [1,3] and y = [0,2]
|
|
||||||
|
|
||||||
the goal is to have the "center" of the output chunk have the value the
|
|
||||||
elevation grid at x=2,y=1
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//set macroValues
|
|
||||||
float[][] macroValues = getMacroValuesAtPosition(x,y);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int halfLength = dynamicInterpolationRatio/2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Four quadrants we're generating
|
|
||||||
|
|
||||||
_____________________
|
|
||||||
|1 |2 |
|
|
||||||
| | |
|
|
||||||
| | |
|
|
||||||
| | |
|
|
||||||
|__________|__________|
|
|
||||||
|3 |4 |
|
|
||||||
| | |
|
|
||||||
| | |
|
|
||||||
|__________|__________|
|
|
||||||
|
|
||||||
First set of loops is quadrant 1
|
|
||||||
then quadrant 2
|
|
||||||
then quadrant 3
|
|
||||||
then quadrant 4
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
int outXOffset = 0;
|
|
||||||
int outYOffset = 0;
|
|
||||||
|
|
||||||
for(int i = 0; i < halfLength; i++){
|
|
||||||
for(int j = 0; j < halfLength; j++){
|
|
||||||
rVal[i+outXOffset][j+outYOffset] =
|
|
||||||
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][0] +
|
|
||||||
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
|
|
||||||
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[0][1] +
|
|
||||||
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][1]
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
outXOffset = halfLength;
|
|
||||||
for(int i = 0; i < halfLength; i++){
|
|
||||||
for(int j = 0; j < halfLength; j++){
|
|
||||||
rVal[i+outXOffset][j+outYOffset] =
|
|
||||||
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
|
|
||||||
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][0] +
|
|
||||||
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][1] +
|
|
||||||
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[2][1]
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
outXOffset = 0;
|
|
||||||
outYOffset = halfLength;
|
|
||||||
for(int i = 0; i < halfLength; i++){
|
|
||||||
for(int j = 0; j < halfLength; j++){
|
|
||||||
rVal[i+outXOffset][j+outYOffset] =
|
|
||||||
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][1] +
|
|
||||||
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
|
|
||||||
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[0][2] +
|
|
||||||
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][2]
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
outXOffset = halfLength;
|
|
||||||
for(int i = 0; i < halfLength; i++){
|
|
||||||
for(int j = 0; j < halfLength; j++){
|
|
||||||
rVal[i+outXOffset][j+outYOffset] =
|
|
||||||
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
|
|
||||||
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][1] +
|
|
||||||
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][2] +
|
|
||||||
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[2][2]
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return rVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
So we're looking at chunk x,y
|
|
||||||
|
|
||||||
if this is our grid:
|
|
||||||
|
|
||||||
4 0.1 0.2 0.3 0.4
|
|
||||||
^
|
|
||||||
| 3 0.1 0.2 0.3 0.4
|
|
||||||
|
|
|
||||||
| 2 0.1 0.2 0.3 0.4
|
|
||||||
|
|
||||||
x 1 0.1 0.2 0.3 0.4
|
|
||||||
|
|
||||||
0 1 2 3
|
|
||||||
|
|
||||||
y ---- >
|
|
||||||
|
|
||||||
say we're looking at x=2,y=1
|
|
||||||
|
|
||||||
"macroValues" should contain the values for x = [1,3] and y = [0,2]
|
|
||||||
|
|
||||||
the goal is to have the "center" of the output chunk have the value the
|
|
||||||
elevation grid at x=2,y=1
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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){
|
|
||||||
|
|
||||||
float[][] rVal = new float[3][3];
|
|
||||||
rVal[1][1] = elevation[x][y];
|
|
||||||
if(x - 1 >= 0){
|
|
||||||
rVal[0][1] = elevation[x-1][y];
|
|
||||||
if(y - 1 >= 0){
|
|
||||||
rVal[0][0] = elevation[x-1][y-1];
|
|
||||||
} else {
|
|
||||||
rVal[0][0] = 0;
|
|
||||||
}
|
|
||||||
if(y + 1 < discreteArrayDimension){
|
|
||||||
rVal[0][2] = elevation[x-1][y+1];
|
|
||||||
} else {
|
|
||||||
rVal[0][2] = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rVal[0][0] = 0;
|
|
||||||
rVal[0][1] = 0;
|
|
||||||
rVal[0][2] = 0;
|
|
||||||
}
|
|
||||||
if(x + 1 < discreteArrayDimension){
|
|
||||||
rVal[2][1] = elevation[x+1][y];
|
|
||||||
if(y - 1 >= 0){
|
|
||||||
rVal[2][0] = elevation[x+1][y-1];
|
|
||||||
} else {
|
|
||||||
rVal[2][0] = 0;
|
|
||||||
}
|
|
||||||
if(y + 1 < discreteArrayDimension){
|
|
||||||
rVal[2][2] = elevation[x+1][y+1];
|
|
||||||
} else {
|
|
||||||
rVal[2][2] = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rVal[2][0] = 0;
|
|
||||||
rVal[2][1] = 0;
|
|
||||||
rVal[2][2] = 0;
|
|
||||||
}
|
|
||||||
if(y - 1 >= 0){
|
|
||||||
rVal[1][0] = elevation[x][y-1];
|
|
||||||
} else {
|
|
||||||
rVal[1][0] = 0;
|
|
||||||
}
|
|
||||||
if(y + 1 < discreteArrayDimension){
|
|
||||||
rVal[1][2] = elevation[x][y+1];
|
|
||||||
} else {
|
|
||||||
rVal[1][2] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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){
|
|
||||||
|
|
||||||
float[][] rVal = new float[5][5];
|
|
||||||
for(int i = -2; i < 3; i++){
|
|
||||||
for(int j = -2; j < 3; j++){
|
|
||||||
if(x + i >= 0 && x + i < discreteArrayDimension && y + j >= 0 && y + j < discreteArrayDimension){
|
|
||||||
rVal[i+2][j+2] = elevation[x+i][y+j];
|
|
||||||
} else {
|
|
||||||
rVal[i+2][j+2] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
So we're looking at chunk x,y
|
|
||||||
|
|
||||||
if this is our grid:
|
|
||||||
|
|
||||||
4 0.1 0.2 0.3 0.4
|
|
||||||
^
|
|
||||||
| 3 0.1 0.2 0.3 0.4
|
|
||||||
|
|
|
||||||
| 2 0.1 0.2 0.3 0.4
|
|
||||||
|
|
||||||
x 1 0.1 0.2 0.3 0.4
|
|
||||||
|
|
||||||
0 1 2 3
|
|
||||||
|
|
||||||
y ---- >
|
|
||||||
|
|
||||||
say we're looking at x=2,y=1
|
|
||||||
|
|
||||||
"macroValues" should contain the values for x = [1,3] and y = [0,2]
|
|
||||||
|
|
||||||
the goal is to have the "center" of the output chunk have the value the
|
|
||||||
elevation grid at x=2,y=1
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the random dampener for the model
|
|
||||||
* @return The random dampener
|
|
||||||
*/
|
|
||||||
public float getRandomDampener(){
|
|
||||||
return interpolationRandomDampener;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the dynamic interpolation ratio
|
|
||||||
* @return The ratio
|
|
||||||
*/
|
|
||||||
public int getDynamicInterpolationRatio(){
|
|
||||||
return dynamicInterpolationRatio;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -532,6 +236,13 @@ public class TerrainModel {
|
|||||||
public double getMacroWidthInRealTerms(){
|
public double getMacroWidthInRealTerms(){
|
||||||
return this.macroDataScale * ServerTerrainChunk.CHUNK_DIMENSION;
|
return this.macroDataScale * ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of the discrete arrays
|
||||||
|
* @return The size of the discrete arrays
|
||||||
|
*/
|
||||||
|
public int getDiscreteArrayDimension(){
|
||||||
|
return discreteArrayDimension;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -270,6 +270,14 @@ public class WorldOctTree <T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of nodes in the tree
|
||||||
|
* @return The number of nodes
|
||||||
|
*/
|
||||||
|
public int getNodeCount(){
|
||||||
|
return nodes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node in a chunk tree
|
* A node in a chunk tree
|
||||||
|
|||||||
@ -8,6 +8,16 @@ import org.joml.Vector3i;
|
|||||||
*/
|
*/
|
||||||
public class GeomUtils {
|
public class GeomUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A really big number
|
||||||
|
*/
|
||||||
|
public static final int REALLY_BIG_NUMBER = 1000000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cutoff after which we just take the distance between the current axis
|
||||||
|
*/
|
||||||
|
public static final int SIMPLIFICATION_CUTOFF = 100000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the minimum distance from a point to an axis aligned cube
|
* Gets the minimum distance from a point to an axis aligned cube
|
||||||
* @param pos the position to check against
|
* @param pos the position to check against
|
||||||
@ -103,6 +113,125 @@ public class GeomUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum squared distance from a point to an axis aligned cube
|
||||||
|
* @param pos the position to check against
|
||||||
|
* @param cubeMin The min position of the cube
|
||||||
|
* @param cubeMax The max position of the cube
|
||||||
|
* @return the distance
|
||||||
|
*/
|
||||||
|
public static double approxMinDistanceAABB(Vector3i pos, Vector3i cubeMin, Vector3i cubeMax){
|
||||||
|
int minX = cubeMin.x;
|
||||||
|
int minY = cubeMin.y;
|
||||||
|
int minZ = cubeMin.z;
|
||||||
|
int maxX = cubeMax.x;
|
||||||
|
int maxY = cubeMax.y;
|
||||||
|
int maxZ = cubeMax.z;
|
||||||
|
if(pos.x > minX && pos.x < maxX){
|
||||||
|
if(pos.y > minY && pos.y < maxY){
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return 0;
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(pos.x,pos.y,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(pos.x,pos.y,maxZ);
|
||||||
|
}
|
||||||
|
} else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){
|
||||||
|
if(Math.abs(pos.y - maxY) > SIMPLIFICATION_CUTOFF){
|
||||||
|
return Math.abs(pos.y - maxY);
|
||||||
|
}
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return pos.distance(pos.x,minY,pos.z);
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(pos.x,minY,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(pos.x,minY,maxZ);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(Math.abs(pos.y - minY) > SIMPLIFICATION_CUTOFF){
|
||||||
|
return Math.abs(pos.y - minY);
|
||||||
|
}
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return pos.distance(pos.x,maxY,pos.z);
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(pos.x,maxY,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(pos.x,maxY,maxZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(Math.abs(pos.x - minX) < Math.abs(pos.x - maxX)){
|
||||||
|
if(Math.abs(pos.x - maxX) > SIMPLIFICATION_CUTOFF){
|
||||||
|
return Math.abs(pos.x - maxX);
|
||||||
|
}
|
||||||
|
if(pos.y > minY && pos.y < maxY){
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return pos.distance(minX,pos.y,pos.z);
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(minX,pos.y,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(minX,pos.y,maxZ);
|
||||||
|
}
|
||||||
|
} else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){
|
||||||
|
if(Math.abs(pos.y - maxY) > SIMPLIFICATION_CUTOFF){
|
||||||
|
return Math.abs(pos.y - maxY);
|
||||||
|
}
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return pos.distance(minX,minY,pos.z);
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(minX,minY,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(minX,minY,maxZ);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(Math.abs(pos.y - minY) > SIMPLIFICATION_CUTOFF){
|
||||||
|
return Math.abs(pos.y - minY);
|
||||||
|
}
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return pos.distance(minX,maxY,pos.z);
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(minX,maxY,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(minX,maxY,maxZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(Math.abs(pos.x - minX) > SIMPLIFICATION_CUTOFF){
|
||||||
|
return Math.abs(pos.x - maxX);
|
||||||
|
}
|
||||||
|
if(pos.y > minY && pos.y < maxY){
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return pos.distance(maxX,pos.y,pos.z);
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(maxX,pos.y,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(maxX,pos.y,maxZ);
|
||||||
|
}
|
||||||
|
} else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){
|
||||||
|
if(Math.abs(pos.y - maxY) > SIMPLIFICATION_CUTOFF){
|
||||||
|
return Math.abs(pos.y - maxY);
|
||||||
|
}
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return pos.distance(maxX,minY,pos.z);
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(maxX,minY,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(maxX,minY,maxZ);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(Math.abs(pos.y - minY) > SIMPLIFICATION_CUTOFF){
|
||||||
|
return Math.abs(pos.y - minY);
|
||||||
|
}
|
||||||
|
if(pos.z > minZ && pos.z < maxZ){
|
||||||
|
return pos.distance(maxX,maxY,pos.z);
|
||||||
|
} else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){
|
||||||
|
return pos.distance(maxX,maxY,minZ);
|
||||||
|
} else {
|
||||||
|
return pos.distance(maxX,maxY,maxZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the minimum squared distance from a point to an axis aligned cube
|
* Gets the minimum squared distance from a point to an axis aligned cube
|
||||||
* @param pos the position to check against
|
* @param pos the position to check against
|
||||||
@ -205,7 +334,7 @@ public class GeomUtils {
|
|||||||
* @param cubeMax The max position of the cube
|
* @param cubeMax The max position of the cube
|
||||||
* @return the distance
|
* @return the distance
|
||||||
*/
|
*/
|
||||||
public static double getMinSquaredDistanceAABB(Vector3i pos, Vector3i cubeMin, Vector3i cubeMax){
|
public static long getMinSquaredDistanceAABB(Vector3i pos, Vector3i cubeMin, Vector3i cubeMax){
|
||||||
int minX = cubeMin.x;
|
int minX = cubeMin.x;
|
||||||
int minY = cubeMin.y;
|
int minY = cubeMin.y;
|
||||||
int minZ = cubeMin.z;
|
int minZ = cubeMin.z;
|
||||||
|
|||||||
@ -25,6 +25,10 @@
|
|||||||
"name" : "worldMinY",
|
"name" : "worldMinY",
|
||||||
"type" : "FIXED_INT"
|
"type" : "FIXED_INT"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name" : "worldMinZ",
|
||||||
|
"type" : "FIXED_INT"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name" : "worldMaxX",
|
"name" : "worldMaxX",
|
||||||
"type" : "FIXED_INT"
|
"type" : "FIXED_INT"
|
||||||
@ -33,6 +37,10 @@
|
|||||||
"name" : "worldMaxY",
|
"name" : "worldMaxY",
|
||||||
"type" : "FIXED_INT"
|
"type" : "FIXED_INT"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name" : "worldMaxZ",
|
||||||
|
"type" : "FIXED_INT"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -120,12 +128,12 @@
|
|||||||
"description" : "Tell the client the terrain metadata",
|
"description" : "Tell the client the terrain metadata",
|
||||||
"data" : [
|
"data" : [
|
||||||
"worldSizeDiscrete",
|
"worldSizeDiscrete",
|
||||||
"dynamicInterpolationRatio",
|
|
||||||
"randomDampener",
|
|
||||||
"worldMinX",
|
"worldMinX",
|
||||||
"worldMinY",
|
"worldMinY",
|
||||||
|
"worldMinZ",
|
||||||
"worldMaxX",
|
"worldMaxX",
|
||||||
"worldMaxY"
|
"worldMaxY",
|
||||||
|
"worldMaxZ"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -35,7 +35,7 @@ public class ClientDrawCellManagerTests {
|
|||||||
public void testJoinCase(){
|
public void testJoinCase(){
|
||||||
|
|
||||||
int worldDiscreteSize = 64;
|
int worldDiscreteSize = 64;
|
||||||
Globals.clientWorldData = new ClientWorldData(new Vector3f(0), new Vector3f(worldDiscreteSize * ServerTerrainChunk.CHUNK_DIMENSION), 0, worldDiscreteSize);
|
Globals.clientWorldData = new ClientWorldData(new Vector3f(0), new Vector3f(worldDiscreteSize * ServerTerrainChunk.CHUNK_DIMENSION), worldDiscreteSize);
|
||||||
ClientDrawCellManager manager = new ClientDrawCellManager(null, 64);
|
ClientDrawCellManager manager = new ClientDrawCellManager(null, 64);
|
||||||
Vector3i playerPos = new Vector3i(0,0,0);
|
Vector3i playerPos = new Vector3i(0,0,0);
|
||||||
WorldOctTreeNode<DrawCell> node = WorldOctTreeNode.constructorForTests(manager.chunkTree, 1, new Vector3i(16,0,0), new Vector3i(32,16,16));
|
WorldOctTreeNode<DrawCell> node = WorldOctTreeNode.constructorForTests(manager.chunkTree, 1, new Vector3i(16,0,0), new Vector3i(32,16,16));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user