fixes + generator work
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-11-13 15:49:52 -05:00
parent d06d5d4506
commit a32f6200cc
31 changed files with 780 additions and 275 deletions

View File

@ -125,6 +125,12 @@
"path" : "Models/items/weapons/katana1alt.glb"
}
},
"boneGroups" : [
{
"id" : "torso",
"boneNamesThirdPerson" : []
}
],
"collidable": {
"type" : "CUBE",
"dimension1" : 0.04,

View File

@ -102,16 +102,13 @@ export const TestGen: ChunkGenerator = {
engine: Engine
): VoxelFunction => {
const rVal = (
voxel: GeneratedVoxel,
worldX: number, worldY: number, worldZ: number,
chunkX: number, chunkY: number, chunkZ: number,
stride: number,
surfaceHeight: number,
surfaceBiome: BiomeData
): GeneratedVoxel => {
let rVal: GeneratedVoxel = {
type: 0,
weight: -1,
}
): void => {
const realX = voxelToReal(chunkX,worldX)
const realY = voxelToReal(chunkY,worldY)
@ -122,8 +119,8 @@ export const TestGen: ChunkGenerator = {
const surfacePercent = (surfaceHeight - realY) / strideMultiplier
if(heightDiff < -strideMultiplier){
return getSubsurfaceVoxel(
rVal,
getSubsurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,
@ -132,8 +129,8 @@ export const TestGen: ChunkGenerator = {
surfaceBiome
);
} else if(heightDiff > 0) {
return getOverSurfaceVoxel(
rVal,
getOverSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,-
@ -142,8 +139,8 @@ export const TestGen: ChunkGenerator = {
surfaceBiome
);
} else {
return getSurfaceVoxel(
rVal,
getSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,

View File

@ -25,6 +25,7 @@ export interface GeneratedVoxel {
/**
* Gets a voxel for a given position
* @param voxel The voxel to fill with values
* @param worldX The world x coordinate of the chunk
* @param worldY The world y coordinate of the chunk
* @param worldZ The world z coordinate of the chunk
@ -38,12 +39,13 @@ export interface GeneratedVoxel {
* @returns The voxel at the provided position
*/
export type VoxelFunction = (
voxel: GeneratedVoxel,
worldX: number, worldY: number, worldZ: number,
chunkX: number, chunkY: number, chunkZ: number,
stride: number,
surfaceHeight: number,
surfaceBiome: BiomeData
) => GeneratedVoxel;
) => void;

View File

@ -130,7 +130,7 @@ void main(){
vec3 textureColor = getColor(texPlane1, texPlane2, texPlane3, norm, samplerIndexVec, samplerRatioVec, material);
//shadow
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), -norm);
//
//point light calculations
@ -350,5 +350,5 @@ float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
// shadow = currentDepth;
return shadow;
return clamp(1.0 - shadow, 0.0, 0.7);
}

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file
#Sun Nov 10 17:05:45 EST 2024
buildNumber=378
#Wed Nov 13 13:33:32 EST 2024
buildNumber=381

View File

@ -10,4 +10,13 @@ Different cases to consider when working on a biome generation system
- Superstructure biomes (World tree, massive mountains, etc)
- Oceans
- Lakes
- Rivers
- Rivers
- Large scale overhangs
Operations we might want to do
- Placing things on the surface
- Solve navgation at the macro scale

View File

@ -60,3 +60,14 @@ store fire pixels as "good for fire civilization"
when a pixel changes biome, must evict it from all these structures and recalculate which ones it should be within (except maybe zone)
Solve for the heightmap at a given x-z for the surface
Then, have "cells" placed above the surface based on the base height offset of the biome
These cells can be populated with larger structures

View File

@ -1001,6 +1001,18 @@ Passing chunk data between nodes
Fix homogenous value propagating from chunk gen to client cache
Fix homogenous value joining on client
(11/12/2024)
Work to optimize javascript chunk generators
Solve curve SDF
(11/13/2024)
Fix shadows on terrain
Work on an anime-style mountain generator
Work on making chunk reloading less obvious
Fix default chunk generator
Fix unit test
Fix missing data on katana item
# TODO

View File

@ -51,6 +51,11 @@
"data" : [
"data"
]
},
{
"messageName" : "EditorSwap",
"description" : "Swaps between the editor entity and the non-editor entity",
"data" : []
}
]
}

View File

@ -305,7 +305,7 @@
<dependency>
<groupId>io.github.studiorailgun</groupId>
<artifactId>MathUtils</artifactId>
<version>1.1.0</version>
<version>1.3.0</version>
</dependency>
<!--DataStructures-->

View File

@ -184,31 +184,6 @@ public class ClientDrawCellManager {
if(!updatedLastFrame && !this.initialized){
this.initialized = true;
}
// if(!updatedLastFrame){
// Globals.profiler.beginCpuSample("ClientDrawCellManager.update - half res cells");
// updatedLastFrame = this.recursivelyUpdateCells(rootNode, playerWorldPos, evaluationMap, HALF_RES_LOD, distCache);
// Globals.profiler.endCpuSample();
// }
// if(!updatedLastFrame){
// Globals.profiler.beginCpuSample("ClientDrawCellManager.update - half res cells");
// updatedLastFrame = this.recursivelyUpdateCells(rootNode, playerWorldPos, evaluationMap, QUARTER_RES_LOD, distCache);
// Globals.profiler.endCpuSample();
// }
// if(!updatedLastFrame){
// Globals.profiler.beginCpuSample("ClientDrawCellManager.update - quarter res cells");
// updatedLastFrame = this.recursivelyUpdateCells(rootNode, playerWorldPos, evaluationMap, EIGHTH_RES_LOD, distCache);
// Globals.profiler.endCpuSample();
// }
// if(!updatedLastFrame){
// Globals.profiler.beginCpuSample("ClientDrawCellManager.update - eighth res cells");
// updatedLastFrame = this.recursivelyUpdateCells(rootNode, playerWorldPos, evaluationMap, SIXTEENTH_RES_LOD, distCache);
// Globals.profiler.endCpuSample();
// }
// if(!updatedLastFrame){
// Globals.profiler.beginCpuSample("ClientDrawCellManager.update - all res cells");
// updatedLastFrame = this.recursivelyUpdateCells(rootNode, playerPos, evaluationMap, ALL_RES_LOD);
// Globals.profiler.endCpuSample();
// }
}
Globals.profiler.endCpuSample();
}

View File

@ -11,6 +11,7 @@ import electrosphere.collision.CollisionEngine;
import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.types.terrain.TerrainChunk;
import electrosphere.renderer.meshgen.TransvoxelModelGeneration;
import electrosphere.renderer.meshgen.TransvoxelModelGeneration.TransvoxelChunkData;
@ -23,6 +24,11 @@ import electrosphere.util.math.GeomUtils;
*/
public class DrawCell {
/**
* Number of frames to wait before destroying the chunk entity
*/
public static final int FRAMES_TO_WAIT_BEFORE_DESTRUCTION = 15;
/**
* Enum for the different faces of a draw cell -- used when filling in data for higher LOD faces
*/
@ -188,9 +194,19 @@ public class DrawCell {
*/
public void destroy(){
if(modelEntity != null){
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
collisionEngine.destroyPhysics(modelEntity);
ClientEntityUtils.destroyEntity(modelEntity);
Globals.clientScene.registerBehaviorTree(new BehaviorTree(){
int framesSimulated = 0;
public void simulate(float deltaTime) {
if(framesSimulated < FRAMES_TO_WAIT_BEFORE_DESTRUCTION){
framesSimulated++;
} else {
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
collisionEngine.destroyPhysics(modelEntity);
ClientEntityUtils.destroyEntity(modelEntity);
Globals.clientScene.deregisterBehaviorTree(this);
}
}
});
}
}

View File

@ -57,6 +57,9 @@ public class ClientEntityUtils {
if(Globals.clientSceneWrapper != null){
Globals.clientSceneWrapper.getScene().deregisterEntity(entity);
Globals.clientSceneWrapper.deregisterTranslationMapping(entity);
if(Globals.clientSceneWrapper.getCollisionEngine() != null){
Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(entity);
}
}
if(Globals.clientScene != null){
Globals.clientScene.deregisterEntity(entity);

View File

@ -11,7 +11,6 @@ import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
@ -46,7 +45,6 @@ public class ServerPhysicsSyncTree implements BehaviorTree {
Quaterniond rotation = EntityUtils.getRotation(parent);
DBody body = PhysicsEntityUtils.getDBody(parent);
if(body == null){
LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Running physics sync tree on entity that does not have a physics body!"));
} else {
//velocities
Vector3d linearVel = PhysicsUtils.odeVecToJomlVec(body.getLinearVel());

View File

@ -63,7 +63,7 @@ public class TerrainChunk {
}
rVal.putData(EntityDataStrings.HAS_UNIQUE_MODEL, true);
} else {
LoggerInterface.loggerEngine.WARNING("Finished generating terrain polygons; however, entity has already been deleted.");
LoggerInterface.loggerEngine.DEBUG("Finished generating terrain polygons; however, entity has already been deleted.");
}
} catch (Error e){
LoggerInterface.loggerEngine.ERROR(e);

View File

@ -251,7 +251,11 @@ public class Actor {
}
}
} else if(this.boneGroups == null){
LoggerInterface.loggerRenderer.WARNING("Trying to play animation on pose actor that uses bone groups, but the actor's bone group isn't defined!");
LoggerInterface.loggerRenderer.WARNING(
"Trying to play animation on Actor that uses bone groups, but the Actor's bone group isn't defined!\n" +
"Model path: " + modelPath + "\n" +
"Animation name: " + animationName + "\n"
);
}

View File

@ -31,17 +31,22 @@ public class ShadowMapPipeline implements RenderPipeline {
/**
* The eye of the camera that is used to render the shadow map
*/
Vector3d cameraEye = new Vector3d(-1,10,-5.5);
Vector3d cameraEye = new Vector3d(-1,20,-5.5);
/**
* The near plane distance
*/
float nearPlane = 0.1f;
float nearPlane = 1f;
/**
* The far plane
*/
float farPlane = 25f;
float farPlane = 40f;
/**
* Sides of the orthagonal box
*/
float sideLength = 50f;
/**
* Sets whether the far plane should update based on camera location or not
@ -68,9 +73,10 @@ public class ShadowMapPipeline implements RenderPipeline {
float eyeX = (float)cameraEye.x;
float eyeY = (float)cameraEye.y;
float eyeZ = (float)cameraEye.z;
float eyeDist = (float)cameraEye.length();
// float eyeDist = (float)cameraEye.length();
// float farPlane = eyeDist + 10.0f;
float sidesMagnitude = (float)Math.sqrt(eyeDist);
// float sidesMagnitude = (float)Math.sqrt(eyeDist);
float sidesMagnitude = sideLength;
//set matrices for light render
Matrix4f lightProjection = new Matrix4f().setOrtho(-sidesMagnitude, sidesMagnitude, -sidesMagnitude, sidesMagnitude, nearPlane, farPlane);//glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
Matrix4f lightView = new Matrix4f().setLookAt(

View File

@ -48,11 +48,11 @@ public class ServerContentGenerator {
);
}
//setup
Random random = new Random(randomizer);
// //setup
// Random random = new Random(randomizer);
//generate foliage
// //generate foliage
// BiomeData biome = null;
// if(realm.getServerWorldData() != null && realm.getServerWorldData().getServerTerrainManager() != null && realm.getServerWorldData().getServerTerrainManager().getModel() != null){
// biome = realm.getServerWorldData().getServerTerrainManager().getModel().getSurfaceBiome(worldPos.x, worldPos.z);

View File

@ -224,7 +224,11 @@ public class PoseActor {
}
}
} else if(this.boneGroups == null){
LoggerInterface.loggerRenderer.WARNING("Trying to play animation on pose actor that uses bone groups, but the actor's bone group isn't defined!");
LoggerInterface.loggerRenderer.WARNING(
"Trying to play animation on PoseActor that uses bone groups, but the PoseActor's bone group isn't defined!\n" +
"Model path: " + modelPath + "\n" +
"Animation name: " + animationName + "\n"
);
}

View File

@ -26,19 +26,19 @@ public class DefaultChunkGenerator implements ChunkGenerator {
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) {
//Each chunk also needs custody of the next chunk's first values so that they can perfectly overlap.
//Hence, width should actually be chunk dimension + 1
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
int[][][] values = new int[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
for(int inc = 0; inc < ServerTerrainChunk.CHUNK_DIMENSION; inc++){
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
int[][][] values = new int[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
for(int inc = 0; inc < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; inc++){
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightX++){
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightZ++){
weights[weightX][inc][weightZ] = -1;
values[weightX][inc][weightZ] = 0;
}
}
}
if(worldY < 1){
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightX++){
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightZ++){
weights[weightX][0][weightZ] = 0.1f;
values[weightX][0][weightZ] = baseVoxelId;
}

View File

@ -5,7 +5,7 @@ import java.util.Map;
import electrosphere.client.terrain.cache.ChunkData;
// import org.graalvm.polyglot.Value;
import org.graalvm.polyglot.Value;
import electrosphere.engine.Globals;
import electrosphere.game.data.biome.BiomeData;
@ -17,6 +17,10 @@ import electrosphere.server.terrain.generation.heightmap.HillsGen;
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext;
import electrosphere.server.terrain.generation.voxelphase.AnimeMountainsGen;
import electrosphere.server.terrain.generation.voxelphase.HillsVoxelGen;
import electrosphere.server.terrain.generation.voxelphase.VoxelGenerator;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.models.TerrainModel;
@ -61,9 +65,14 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
ServerWorldData serverWorldData;
/**
* Map of generator tag to the generator
* The map of generator tag to the heightmap generator
*/
Map<String,HeightmapGenerator> tagGeneratorMap = new HashMap<String,HeightmapGenerator>();
Map<String,HeightmapGenerator> tagHeightmapMap = new HashMap<String,HeightmapGenerator>();
/**
* The map of generator tag to voxel generator
*/
Map<String,VoxelGenerator> tagVoxelMap = new HashMap<String,VoxelGenerator>();
/**
* Tracks whether to use javascript generation or not
@ -75,9 +84,11 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
*/
public TestGenerationChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
this.serverWorldData = serverWorldData;
registerGenerator(new EmptySkyGen());
registerGenerator(new HillsGen());
registerGenerator(new PlainsGen());
registerHeightmapGenerator(new EmptySkyGen());
registerHeightmapGenerator(new HillsGen());
registerHeightmapGenerator(new PlainsGen());
registerVoxelGenerator(new HillsVoxelGen());
registerVoxelGenerator(new AnimeMountainsGen());
this.useJavascript = useJavascript;
}
@ -85,27 +96,31 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
* Registers a heightmap generator
* @param generator The heightmap generator
*/
private void registerGenerator(HeightmapGenerator generator){
tagGeneratorMap.put(generator.getTag(),generator);
private void registerHeightmapGenerator(HeightmapGenerator generator){
tagHeightmapMap.put(generator.getTag(),generator);
}
/**
* Registers a voxel generator
* @param generator The voxel generator
*/
private void registerVoxelGenerator(VoxelGenerator generator){
tagVoxelMap.put(generator.getTag(),generator);
}
@Override
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) {
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.generateChunk");
ServerTerrainChunk rVal = null;
ServerTerrainChunk rVal = new ServerTerrainChunk(worldX, worldY, worldZ);
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];;
int[][][] values = new int[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
int firstType = -2;
boolean homogenous = true;
try {
//actual generation algo
//biome of the current chunk
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag());
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
if(heightmapGen == null){
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
}
@ -129,39 +144,58 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
}
}
VoxelGenerator voxelGenerator = this.tagVoxelMap.get("hills");
if(this.useJavascript){
// Globals.scriptEngine.executeSynchronously(() -> {
// Value getVoxelFunc = Globals.scriptEngine.invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
// for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
// Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
// for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
// for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
// int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
// int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
// int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
// int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
// int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
// int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
// Value result = getVoxelFunc.execute(
// finalWorldX, finalWorldY, finalWorldZ,
// finalChunkX, finalChunkY, finalChunkZ,
// stride,
// heightfield[x][z],
// surfaceBiome
// );
// if(result != null){
// weights[x][y][z] = result.getMember("weight").asFloat();
// values[x][y][z] = result.getMember("type").asInt();
// }
// }
// }
// Globals.profiler.endCpuSample();
// }
// });
Globals.scriptEngine.executeSynchronously(() -> {
int firstType = -2;
boolean homogenous = true;
GeneratedVoxel voxel = new GeneratedVoxel();
Value getVoxelFunc = Globals.scriptEngine.invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
getVoxelFunc.execute(
voxel,
finalWorldX, finalWorldY, finalWorldZ,
finalChunkX, finalChunkY, finalChunkZ,
stride,
heightfield[x][z],
surfaceBiome
);
weights[x][y][z] = voxel.weight;
values[x][y][z] = voxel.type;
if(firstType == -2){
firstType = values[x][y][z];
} else if(homogenous && firstType != values[x][y][z]){
homogenous = false;
}
}
}
Globals.profiler.endCpuSample();
}
if(homogenous){
rVal.setHomogenousValue(firstType);
} else {
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
}
rVal.setWeights(weights);
rVal.setValues(values);
});
} else {
int firstType = -2;
boolean homogenous = true;
GeneratedVoxel voxel = new GeneratedVoxel();
GenerationContext generationContext = new GenerationContext();
generationContext.setServerWorldData(serverWorldData);
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
@ -170,13 +204,14 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
this.getVoxel(
voxelGenerator.getVoxel(
voxel,
finalWorldX, finalWorldY, finalWorldZ,
finalChunkX, finalChunkY, finalChunkZ,
stride,
heightfield[x][z],
surfaceBiome
surfaceBiome,
generationContext
);
if(voxel != null){
weights[x][y][z] = voxel.weight;
@ -189,13 +224,18 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
}
}
}
Globals.profiler.endCpuSample();
}
if(homogenous){
rVal.setHomogenousValue(firstType);
} else {
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
}
rVal.setWeights(weights);
rVal.setValues(values);
}
} catch(Exception ex){
ex.printStackTrace();
}
rVal = new ServerTerrainChunk(worldX, worldY, worldZ, homogenous ? firstType : ChunkData.NOT_HOMOGENOUS, weights, values);
Globals.profiler.endCpuSample();
return rVal;
}
@ -205,7 +245,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag());
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
if(heightmapGen == null){
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
}
@ -222,140 +262,4 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
this.terrainModel = model;
}
/**
* Gets the value for a chunk
* @param voxel The voxel to fill
* @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 stride The stride of the data
* @param surfaceHeight The height of the surface at x,z
* @param surfaceBiome The surface biome of the chunk
*/
private void getVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
int stride,
float surfaceHeight,
BiomeData surfaceBiome
){
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.getChunkValue");
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag());
if(heightmapGen == null){
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
}
double realX = this.serverWorldData.convertVoxelToRealSpace(chunkX,worldX);
double realY = this.serverWorldData.convertVoxelToRealSpace(chunkY,worldY);
double realZ = this.serverWorldData.convertVoxelToRealSpace(chunkZ,worldZ);
double strideMultiplier = Math.pow(2,stride);
double heightDiff = realY - surfaceHeight;
double surfacePercent = TestGenerationChunkGenerator.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
Globals.profiler.endCpuSample();
if(heightDiff < -strideMultiplier * SURFACE_VOXEL_WIDTH){
getSubsurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,
surfacePercent,
surfaceHeight,
surfaceBiome
);
} else if(heightDiff > 0) {
getOverSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,-
surfacePercent,
surfaceHeight,
surfaceBiome
);
} else {
getSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,
surfacePercent,
surfaceHeight,
surfaceBiome
);
}
}
/**
* Gets the voxel on the surface
* @return The voxel
*/
private void getSurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
voxel.weight = (float)surfacePercent * 2 - 1;
voxel.type = 2;
}
/**
* Gets the voxel below the surface
* @return The voxel
*/
private void getSubsurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
if(realY < surfaceHeight - 5){
voxel.weight = 1;
voxel.type = 6;
} else {
voxel.weight = 1;
voxel.type = 1;
}
}
/**
* Gets the voxel above the service
* @return The voxel
*/
private void getOverSurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
voxel.weight = -1;
voxel.type = 0;
}
/**
* Calculates the weight of a voxel on the surface based on the surface height, the position of the voxel, and the stride multiplier
* @param surfaceHeight The surface height
* @param realPosY The position of the voxel
* @param strideMultiplier The stride multiplier
* @return The weight of the voxel
*/
protected static double getSurfaceWeight(double surfaceHeight, double realPosY, double strideMultiplier){
return ((surfaceHeight - realPosY) / strideMultiplier);
}
}

View File

@ -52,7 +52,7 @@ public class HillsGen implements HeightmapGenerator {
Globals.profiler.beginAggregateCpuSample("HillsGen.getHeight");
double scaledX = x * POSITION_SCALE;
double scaledY = y * POSITION_SCALE;
float rVal = gradientHeight(SEED, scaledX, scaledY) * VERTICAL_SCALE + HEIGHT_OFFSET;
float rVal = HillsGen.gradientHeight(SEED, scaledX, scaledY) * VERTICAL_SCALE + HEIGHT_OFFSET;
Globals.profiler.endCpuSample();
return rVal;
}

View File

@ -0,0 +1,26 @@
package electrosphere.server.terrain.generation.heightmap;
import electrosphere.util.noise.OpenSimplex2S;
/**
* Generates a mild plain that would look like a seafloor
*/
public class SeaFloorGen implements HeightmapGenerator {
/**
* The scale of the noise
*/
float noiseScale = 0.01f;
@Override
public float getHeight(long SEED, double x, double y) {
float noise = (float)OpenSimplex2S.noise2_ImproveX(SEED, x * noiseScale, y * noiseScale);
return noise;
}
@Override
public String getTag() {
return "seafloor";
}
}

View File

@ -0,0 +1,37 @@
package electrosphere.server.terrain.generation.interfaces;
import electrosphere.game.server.world.ServerWorldData;
/**
* The context the generation is happening in. Stores things like biomes to interpolate between.
*/
public class GenerationContext {
/**
* The world data for the realm we're generating for
*/
ServerWorldData serverWorldData;
/**
* Constructor
*/
public GenerationContext(){
}
/**
* Gets the world data for the server
* @return The world data
*/
public ServerWorldData getServerWorldData(){
return serverWorldData;
}
/**
* Sets the world data for the context
* @param serverWorldData The world data
*/
public void setServerWorldData(ServerWorldData serverWorldData){
this.serverWorldData = serverWorldData;
}
}

View File

@ -0,0 +1,259 @@
package electrosphere.server.terrain.generation.voxelphase;
import electrosphere.engine.Globals;
import electrosphere.game.data.biome.BiomeData;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext;
import io.github.studiorailgun.MathUtils;
import io.github.studiorailgun.RandUtils;
/**
* Generates anime-style mountains
*/
public class AnimeMountainsGen implements VoxelGenerator {
/**
* The width of the surface in number of voxels
*/
public static final int SURFACE_VOXEL_WIDTH = 2;
/**
* Size of the large cells that generate mountains
*/
public static final int LARGE_CELL_SIZE = 1024;
/**
* How much to sink the cell into the surface
*/
public static final int CELL_VERTICAL_OFFSET = - (int)((LARGE_CELL_SIZE) * 2.5 / 5.0);
/**
* The variance in scale of mountains
*/
public static final double MOUNTAIN_SCALE_VARIANCE = 0.2;
/**
* The width of the mountain
*/
public static final double MOUNTAIN_WIDTH = 0.4;
/**
* The center x point of the cell
*/
public static final double CELL_CENTER_X = 0.5;
/**
* The center y point of the cell
*/
public static final double CELL_CENTER_Y = 0.5;
/**
* The center z point of the cell
*/
public static final double CELL_CENTER_Z = 0.5;
/**
* Amount the vertical rotation offset can vary
*/
public static final double VERTICAL_ROTATION_OFFSET_VARIANCE = 0.2;
@Override
public String getTag() {
return "animeMountain";
}
@Override
public void getVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
int stride, float surfaceHeight,
BiomeData surfaceBiome,
GenerationContext generationContext
) {
Globals.profiler.beginAggregateCpuSample("AnimeMountainsGen.getVoxel");
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkX,worldX);
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkY,worldY);
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkZ,worldZ);
double strideMultiplier = Math.pow(2,stride);
double heightDiff = realY - surfaceHeight;
double surfacePercent = AnimeMountainsGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
Globals.profiler.endCpuSample();
if(heightDiff < -strideMultiplier * SURFACE_VOXEL_WIDTH){
this.getSubsurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,
surfacePercent,
surfaceHeight,
surfaceBiome
);
} else if(heightDiff > 0) {
this.getOverSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,-
surfacePercent,
surfaceHeight,
surfaceBiome
);
} else {
this.getSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,
surfacePercent,
surfaceHeight,
surfaceBiome
);
}
}
/**
* Gets the voxel on the surface
* @return The voxel
*/
private void getSurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
voxel.weight = (float)surfacePercent * 2 - 1;
voxel.type = 2;
}
/**
* Gets the voxel below the surface
* @return The voxel
*/
private void getSubsurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
if(realY < surfaceHeight - 5){
voxel.weight = 1;
voxel.type = 6;
} else {
voxel.weight = 1;
voxel.type = 1;
}
}
/**
* Gets the voxel above the service
* @return The voxel
*/
private void getOverSurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
//default voxel value
voxel.weight = -1;
voxel.type = 0;
//get the height above the surface
double heightAboveBaseSurface = realY - surfaceBiome.getSurfaceGenerationParams().getHeightOffset();
double offsetHeight = heightAboveBaseSurface - CELL_VERTICAL_OFFSET;
//calculated floored values
double x_i = Math.floor(realX / LARGE_CELL_SIZE);
double y_i = Math.floor(offsetHeight / LARGE_CELL_SIZE);
double z_i = Math.floor(realZ / LARGE_CELL_SIZE);
//only generate if you're on the first cell from the surface
if(y_i < 1){
//calculate values from which cell we're in
double rotationTheta = RandUtils.rand(x_i, z_i, 0) * Math.PI * 2;
// double mountainScale = MathUtils.rand(x_i, z_i, 1) * MOUNTAIN_SCALE_VARIANCE + (1.0 - (MOUNTAIN_SCALE_VARIANCE / 2.0));
// double verticalRotationOffset = MathUtils.rand(x_i, z_i, 2) * VERTICAL_ROTATION_OFFSET_VARIANCE;
//remainders of the point coordinates
double x_r = (realX / LARGE_CELL_SIZE) - x_i;
double y_r = (offsetHeight / LARGE_CELL_SIZE) - y_i;
double z_r = (realZ / LARGE_CELL_SIZE) - z_i;
//get the center of the cell
double cellCenterX = CELL_CENTER_X;
double cellCenterY = CELL_CENTER_Y;
double cellCenterZ = CELL_CENTER_Z;
//delta positions
double deltaX = (x_r - cellCenterX);
double deltaY = (y_r - cellCenterY);
double deltaZ = (z_r - cellCenterZ);
//rotate around the center
double rotX = deltaX * Math.cos(rotationTheta) + deltaZ * Math.sin(rotationTheta);
double rotY = deltaY;
double rotZ = - deltaX * Math.sin(rotationTheta) + deltaZ * Math.cos(rotationTheta);
//roation along the arctre
//ranged [0,2PI]
double rotationAlongArc = Math.atan2(rotY,rotX);
//ranges [0,1]
// double rotationPercent = rotationAlongArc / (Math.PI * 2.0);
//calculate values from where we are WITHIN the cell
// double voxelGamma = Math.atan2(
// x_r - cellCenterX,
// z_r - cellCenterZ
// ) + Math.PI * 2.0;
// double voxelTheta = Math.atan2(y_r - cellCenterY, MathUtils.dist(x_r,z_r,cellCenterX,cellCenterZ));
double distanceFromCenter = MathUtils.dist(rotX,rotY,0,0);
double distanceFromArcCenter = Math.sqrt(rotZ*rotZ);
//target distance from center
double targetDistanceFromArcCenter = Math.sin(rotationAlongArc) * 0.3;
double targetArcRadius = 0.6;
double targetArcRadiusWidth = Math.sin(rotationAlongArc) * 0.03;
if(
// voxelTheta > 0 &&
// (voxelGamma - Math.PI/2) < Math.PI &&
// voxelTheta > Math.max(Math.sin(voxelGamma),0) &&
// voxelTheta > 0.4 * Math.max(Math.sin(voxelGamma),0) &&
distanceFromCenter > targetArcRadius - targetArcRadiusWidth &&
distanceFromCenter < targetArcRadius + targetArcRadiusWidth &&
distanceFromArcCenter < targetDistanceFromArcCenter
){
voxel.weight = 1.0f;
voxel.type = 1;
}
}
}
/**
* Calculates the weight of a voxel on the surface based on the surface height, the position of the voxel, and the stride multiplier
* @param surfaceHeight The surface height
* @param realPosY The position of the voxel
* @param strideMultiplier The stride multiplier
* @return The weight of the voxel
*/
private static double getSurfaceWeight(double surfaceHeight, double realPosY, double strideMultiplier){
return ((surfaceHeight - realPosY) / strideMultiplier);
}
}

View File

@ -0,0 +1,146 @@
package electrosphere.server.terrain.generation.voxelphase;
import electrosphere.engine.Globals;
import electrosphere.game.data.biome.BiomeData;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext;
/**
* Generates voxels for a hill
*/
public class HillsVoxelGen implements VoxelGenerator {
/**
* The width of the surface in number of voxels
*/
public static final int SURFACE_VOXEL_WIDTH = 2;
@Override
public String getTag(){
return "hills";
}
@Override
public void getVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
int stride,
float surfaceHeight,
BiomeData surfaceBiome,
GenerationContext generationContext
){
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkX,worldX);
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkY,worldY);
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkZ,worldZ);
double strideMultiplier = Math.pow(2,stride);
double heightDiff = realY - surfaceHeight;
double surfacePercent = HillsVoxelGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
Globals.profiler.endCpuSample();
if(heightDiff < -strideMultiplier * SURFACE_VOXEL_WIDTH){
this.getSubsurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,
surfacePercent,
surfaceHeight,
surfaceBiome
);
} else if(heightDiff > 0) {
this.getOverSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,-
surfacePercent,
surfaceHeight,
surfaceBiome
);
} else {
this.getSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,
surfacePercent,
surfaceHeight,
surfaceBiome
);
}
}
/**
* Gets the voxel on the surface
* @return The voxel
*/
private void getSurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
voxel.weight = (float)surfacePercent * 2 - 1;
voxel.type = 2;
}
/**
* Gets the voxel below the surface
* @return The voxel
*/
private void getSubsurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
if(realY < surfaceHeight - 5){
voxel.weight = 1;
voxel.type = 6;
} else {
voxel.weight = 1;
voxel.type = 1;
}
}
/**
* Gets the voxel above the service
* @return The voxel
*/
private void getOverSurfaceVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ,
double surfacePercent,
float surfaceHeight,
BiomeData surfaceBiome
){
voxel.weight = -1;
voxel.type = 0;
}
/**
* Calculates the weight of a voxel on the surface based on the surface height, the position of the voxel, and the stride multiplier
* @param surfaceHeight The surface height
* @param realPosY The position of the voxel
* @param strideMultiplier The stride multiplier
* @return The weight of the voxel
*/
protected static double getSurfaceWeight(double surfaceHeight, double realPosY, double strideMultiplier){
return ((surfaceHeight - realPosY) / strideMultiplier);
}
}

View File

@ -0,0 +1,45 @@
package electrosphere.server.terrain.generation.voxelphase;
import electrosphere.game.data.biome.BiomeData;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext;
/**
* Used for generating voxels
*/
public interface VoxelGenerator {
/**
* Gets the tag of the generator
* @return The tag
*/
public String getTag();
/**
* Gets the value for a chunk
* @param voxel The voxel to fill
* @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 stride The stride of the data
* @param surfaceHeight The height of the surface at x,z
* @param surfaceBiome The surface biome of the chunk
* @param generationContext The generation context
*/
public void getVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
int stride,
float surfaceHeight,
BiomeData surfaceBiome,
GenerationContext generationContext
);
}

View File

@ -80,6 +80,18 @@ public class ServerTerrainChunk {
this.values = values;
}
/**
* Constructor
* @param worldX The world position x coordinate
* @param worldY The world position y coordinate
* @param worldZ The world position z coordinate
*/
public ServerTerrainChunk(int worldX, int worldY, int worldZ){
this.worldX = worldX;
this.worldY = worldY;
this.worldZ = worldZ;
}
/**
* Gets the world position x coordinate
* @return The x coordinate
@ -201,5 +213,31 @@ public class ServerTerrainChunk {
public int getHomogenousValue(){
return homogenousValue;
}
/**
* Sets the weights of the chunk
* @param weights The weights
*/
public void setWeights(float[][][] weights) {
this.weights = weights;
}
/**
* Sets the values of the chunk
* @param values The values
*/
public void setValues(int[][][] values) {
this.values = values;
}
/**
* Sets the homogenous value
* @param homogenousValue The homogenous value
*/
public void setHomogenousValue(int homogenousValue) {
this.homogenousValue = homogenousValue;
}
}

View File

@ -40,9 +40,11 @@ public class ClientDrawCellManagerTests {
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));
node.setLeaf(true);
node.setData(DrawCell.generateTerrainCell(new Vector3i(0,0,0),3));
node.setData(DrawCell.generateTerrainCell(new Vector3i(16,0,0),3));
assertTrue(manager.shouldSplit(playerPos, node, 0));
boolean shouldBeTrue = node.getParent() != null;
assertEquals(shouldBeTrue,manager.shouldSplit(playerPos, node, 0));
//cleanup
Main.shutdown();

View File

@ -1,22 +0,0 @@
package electrosphere.server.terrain.generation;
import static org.junit.jupiter.api.Assertions.assertEquals;
import electrosphere.test.annotations.FastTest;
import electrosphere.test.annotations.UnitTest;
/**
* Unit tests for the test generation chunk generator
*/
public class TestGenerationChunkGeneratorTests {
@UnitTest
@FastTest
public void getSurfaceWeight_ValueTests(){
assertEquals(0.5,TestGenerationChunkGenerator.getSurfaceWeight(0.5, 0, 1));
assertEquals(0.1,TestGenerationChunkGenerator.getSurfaceWeight(0.1, 0, 1));
assertEquals(0.9,TestGenerationChunkGenerator.getSurfaceWeight(0.9, 0, 1));
assertEquals(0.95,TestGenerationChunkGenerator.getSurfaceWeight(1.9, 0, 2));
}
}

View File

@ -0,0 +1,22 @@
package electrosphere.server.terrain.generation.voxelphase;
import static org.junit.jupiter.api.Assertions.assertEquals;
import electrosphere.test.annotations.FastTest;
import electrosphere.test.annotations.UnitTest;
/**
* Unit tests for the test generation chunk generator
*/
public class HillsVoxelGenTests {
@UnitTest
@FastTest
public void getSurfaceWeight_ValueTests(){
assertEquals(0.5,HillsVoxelGen.getSurfaceWeight(0.5, 0, 1));
assertEquals(0.1,HillsVoxelGen.getSurfaceWeight(0.1, 0, 1));
assertEquals(0.9,HillsVoxelGen.getSurfaceWeight(0.9, 0, 1));
assertEquals(0.95,HillsVoxelGen.getSurfaceWeight(1.9, 0, 2));
}
}