fixes + generator work
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
d06d5d4506
commit
a32f6200cc
@ -125,6 +125,12 @@
|
|||||||
"path" : "Models/items/weapons/katana1alt.glb"
|
"path" : "Models/items/weapons/katana1alt.glb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"boneGroups" : [
|
||||||
|
{
|
||||||
|
"id" : "torso",
|
||||||
|
"boneNamesThirdPerson" : []
|
||||||
|
}
|
||||||
|
],
|
||||||
"collidable": {
|
"collidable": {
|
||||||
"type" : "CUBE",
|
"type" : "CUBE",
|
||||||
"dimension1" : 0.04,
|
"dimension1" : 0.04,
|
||||||
|
|||||||
@ -102,16 +102,13 @@ export const TestGen: ChunkGenerator = {
|
|||||||
engine: Engine
|
engine: Engine
|
||||||
): VoxelFunction => {
|
): VoxelFunction => {
|
||||||
const rVal = (
|
const rVal = (
|
||||||
|
voxel: GeneratedVoxel,
|
||||||
worldX: number, worldY: number, worldZ: number,
|
worldX: number, worldY: number, worldZ: number,
|
||||||
chunkX: number, chunkY: number, chunkZ: number,
|
chunkX: number, chunkY: number, chunkZ: number,
|
||||||
stride: number,
|
stride: number,
|
||||||
surfaceHeight: number,
|
surfaceHeight: number,
|
||||||
surfaceBiome: BiomeData
|
surfaceBiome: BiomeData
|
||||||
): GeneratedVoxel => {
|
): void => {
|
||||||
let rVal: GeneratedVoxel = {
|
|
||||||
type: 0,
|
|
||||||
weight: -1,
|
|
||||||
}
|
|
||||||
|
|
||||||
const realX = voxelToReal(chunkX,worldX)
|
const realX = voxelToReal(chunkX,worldX)
|
||||||
const realY = voxelToReal(chunkY,worldY)
|
const realY = voxelToReal(chunkY,worldY)
|
||||||
@ -122,8 +119,8 @@ export const TestGen: ChunkGenerator = {
|
|||||||
const surfacePercent = (surfaceHeight - realY) / strideMultiplier
|
const surfacePercent = (surfaceHeight - realY) / strideMultiplier
|
||||||
|
|
||||||
if(heightDiff < -strideMultiplier){
|
if(heightDiff < -strideMultiplier){
|
||||||
return getSubsurfaceVoxel(
|
getSubsurfaceVoxel(
|
||||||
rVal,
|
voxel,
|
||||||
worldX, worldY, worldZ,
|
worldX, worldY, worldZ,
|
||||||
chunkX, chunkY, chunkZ,
|
chunkX, chunkY, chunkZ,
|
||||||
realX, realY, realZ,
|
realX, realY, realZ,
|
||||||
@ -132,8 +129,8 @@ export const TestGen: ChunkGenerator = {
|
|||||||
surfaceBiome
|
surfaceBiome
|
||||||
);
|
);
|
||||||
} else if(heightDiff > 0) {
|
} else if(heightDiff > 0) {
|
||||||
return getOverSurfaceVoxel(
|
getOverSurfaceVoxel(
|
||||||
rVal,
|
voxel,
|
||||||
worldX, worldY, worldZ,
|
worldX, worldY, worldZ,
|
||||||
chunkX, chunkY, chunkZ,
|
chunkX, chunkY, chunkZ,
|
||||||
realX, realY, realZ,-
|
realX, realY, realZ,-
|
||||||
@ -142,8 +139,8 @@ export const TestGen: ChunkGenerator = {
|
|||||||
surfaceBiome
|
surfaceBiome
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return getSurfaceVoxel(
|
getSurfaceVoxel(
|
||||||
rVal,
|
voxel,
|
||||||
worldX, worldY, worldZ,
|
worldX, worldY, worldZ,
|
||||||
chunkX, chunkY, chunkZ,
|
chunkX, chunkY, chunkZ,
|
||||||
realX, realY, realZ,
|
realX, realY, realZ,
|
||||||
|
|||||||
@ -25,6 +25,7 @@ export interface GeneratedVoxel {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a voxel for a given position
|
* 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 worldX The world x coordinate of the chunk
|
||||||
* @param worldY The world y coordinate of the chunk
|
* @param worldY The world y coordinate of the chunk
|
||||||
* @param worldZ The world z 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
|
* @returns The voxel at the provided position
|
||||||
*/
|
*/
|
||||||
export type VoxelFunction = (
|
export type VoxelFunction = (
|
||||||
|
voxel: GeneratedVoxel,
|
||||||
worldX: number, worldY: number, worldZ: number,
|
worldX: number, worldY: number, worldZ: number,
|
||||||
chunkX: number, chunkY: number, chunkZ: number,
|
chunkX: number, chunkY: number, chunkZ: number,
|
||||||
stride: number,
|
stride: number,
|
||||||
surfaceHeight: number,
|
surfaceHeight: number,
|
||||||
surfaceBiome: BiomeData
|
surfaceBiome: BiomeData
|
||||||
) => GeneratedVoxel;
|
) => void;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -130,7 +130,7 @@ void main(){
|
|||||||
vec3 textureColor = getColor(texPlane1, texPlane2, texPlane3, norm, samplerIndexVec, samplerRatioVec, material);
|
vec3 textureColor = getColor(texPlane1, texPlane2, texPlane3, norm, samplerIndexVec, samplerRatioVec, material);
|
||||||
|
|
||||||
//shadow
|
//shadow
|
||||||
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
|
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), -norm);
|
||||||
|
|
||||||
//
|
//
|
||||||
//point light calculations
|
//point light calculations
|
||||||
@ -350,5 +350,5 @@ float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
|||||||
|
|
||||||
// shadow = currentDepth;
|
// shadow = currentDepth;
|
||||||
|
|
||||||
return shadow;
|
return clamp(1.0 - shadow, 0.0, 0.7);
|
||||||
}
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
#maven.buildNumber.plugin properties file
|
#maven.buildNumber.plugin properties file
|
||||||
#Sun Nov 10 17:05:45 EST 2024
|
#Wed Nov 13 13:33:32 EST 2024
|
||||||
buildNumber=378
|
buildNumber=381
|
||||||
|
|||||||
@ -10,4 +10,13 @@ Different cases to consider when working on a biome generation system
|
|||||||
- Superstructure biomes (World tree, massive mountains, etc)
|
- Superstructure biomes (World tree, massive mountains, etc)
|
||||||
- Oceans
|
- Oceans
|
||||||
- Lakes
|
- Lakes
|
||||||
- Rivers
|
- Rivers
|
||||||
|
- Large scale overhangs
|
||||||
|
|
||||||
|
|
||||||
|
Operations we might want to do
|
||||||
|
- Placing things on the surface
|
||||||
|
- Solve navgation at the macro scale
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1001,6 +1001,18 @@ Passing chunk data between nodes
|
|||||||
Fix homogenous value propagating from chunk gen to client cache
|
Fix homogenous value propagating from chunk gen to client cache
|
||||||
Fix homogenous value joining on client
|
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
|
# TODO
|
||||||
|
|||||||
@ -51,6 +51,11 @@
|
|||||||
"data" : [
|
"data" : [
|
||||||
"data"
|
"data"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"messageName" : "EditorSwap",
|
||||||
|
"description" : "Swaps between the editor entity and the non-editor entity",
|
||||||
|
"data" : []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@ -305,7 +305,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.github.studiorailgun</groupId>
|
<groupId>io.github.studiorailgun</groupId>
|
||||||
<artifactId>MathUtils</artifactId>
|
<artifactId>MathUtils</artifactId>
|
||||||
<version>1.1.0</version>
|
<version>1.3.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--DataStructures-->
|
<!--DataStructures-->
|
||||||
|
|||||||
@ -184,31 +184,6 @@ public class ClientDrawCellManager {
|
|||||||
if(!updatedLastFrame && !this.initialized){
|
if(!updatedLastFrame && !this.initialized){
|
||||||
this.initialized = true;
|
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();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import electrosphere.collision.CollisionEngine;
|
|||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.ClientEntityUtils;
|
import electrosphere.entity.ClientEntityUtils;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.btree.BehaviorTree;
|
||||||
import electrosphere.entity.types.terrain.TerrainChunk;
|
import electrosphere.entity.types.terrain.TerrainChunk;
|
||||||
import electrosphere.renderer.meshgen.TransvoxelModelGeneration;
|
import electrosphere.renderer.meshgen.TransvoxelModelGeneration;
|
||||||
import electrosphere.renderer.meshgen.TransvoxelModelGeneration.TransvoxelChunkData;
|
import electrosphere.renderer.meshgen.TransvoxelModelGeneration.TransvoxelChunkData;
|
||||||
@ -23,6 +24,11 @@ import electrosphere.util.math.GeomUtils;
|
|||||||
*/
|
*/
|
||||||
public class DrawCell {
|
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
|
* 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(){
|
public void destroy(){
|
||||||
if(modelEntity != null){
|
if(modelEntity != null){
|
||||||
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
|
Globals.clientScene.registerBehaviorTree(new BehaviorTree(){
|
||||||
collisionEngine.destroyPhysics(modelEntity);
|
int framesSimulated = 0;
|
||||||
ClientEntityUtils.destroyEntity(modelEntity);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,9 @@ public class ClientEntityUtils {
|
|||||||
if(Globals.clientSceneWrapper != null){
|
if(Globals.clientSceneWrapper != null){
|
||||||
Globals.clientSceneWrapper.getScene().deregisterEntity(entity);
|
Globals.clientSceneWrapper.getScene().deregisterEntity(entity);
|
||||||
Globals.clientSceneWrapper.deregisterTranslationMapping(entity);
|
Globals.clientSceneWrapper.deregisterTranslationMapping(entity);
|
||||||
|
if(Globals.clientSceneWrapper.getCollisionEngine() != null){
|
||||||
|
Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(Globals.clientScene != null){
|
if(Globals.clientScene != null){
|
||||||
Globals.clientScene.deregisterEntity(entity);
|
Globals.clientScene.deregisterEntity(entity);
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import electrosphere.entity.Entity;
|
|||||||
import electrosphere.entity.EntityDataStrings;
|
import electrosphere.entity.EntityDataStrings;
|
||||||
import electrosphere.entity.EntityUtils;
|
import electrosphere.entity.EntityUtils;
|
||||||
import electrosphere.entity.btree.BehaviorTree;
|
import electrosphere.entity.btree.BehaviorTree;
|
||||||
import electrosphere.logger.LoggerInterface;
|
|
||||||
import electrosphere.net.parser.net.message.EntityMessage;
|
import electrosphere.net.parser.net.message.EntityMessage;
|
||||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||||
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||||
@ -46,7 +45,6 @@ public class ServerPhysicsSyncTree implements BehaviorTree {
|
|||||||
Quaterniond rotation = EntityUtils.getRotation(parent);
|
Quaterniond rotation = EntityUtils.getRotation(parent);
|
||||||
DBody body = PhysicsEntityUtils.getDBody(parent);
|
DBody body = PhysicsEntityUtils.getDBody(parent);
|
||||||
if(body == null){
|
if(body == null){
|
||||||
LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Running physics sync tree on entity that does not have a physics body!"));
|
|
||||||
} else {
|
} else {
|
||||||
//velocities
|
//velocities
|
||||||
Vector3d linearVel = PhysicsUtils.odeVecToJomlVec(body.getLinearVel());
|
Vector3d linearVel = PhysicsUtils.odeVecToJomlVec(body.getLinearVel());
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public class TerrainChunk {
|
|||||||
}
|
}
|
||||||
rVal.putData(EntityDataStrings.HAS_UNIQUE_MODEL, true);
|
rVal.putData(EntityDataStrings.HAS_UNIQUE_MODEL, true);
|
||||||
} else {
|
} 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){
|
} catch (Error e){
|
||||||
LoggerInterface.loggerEngine.ERROR(e);
|
LoggerInterface.loggerEngine.ERROR(e);
|
||||||
|
|||||||
@ -251,7 +251,11 @@ public class Actor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(this.boneGroups == null){
|
} 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"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -31,17 +31,22 @@ public class ShadowMapPipeline implements RenderPipeline {
|
|||||||
/**
|
/**
|
||||||
* The eye of the camera that is used to render the shadow map
|
* 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
|
* The near plane distance
|
||||||
*/
|
*/
|
||||||
float nearPlane = 0.1f;
|
float nearPlane = 1f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The far plane
|
* 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
|
* 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 eyeX = (float)cameraEye.x;
|
||||||
float eyeY = (float)cameraEye.y;
|
float eyeY = (float)cameraEye.y;
|
||||||
float eyeZ = (float)cameraEye.z;
|
float eyeZ = (float)cameraEye.z;
|
||||||
float eyeDist = (float)cameraEye.length();
|
// float eyeDist = (float)cameraEye.length();
|
||||||
// float farPlane = eyeDist + 10.0f;
|
// 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
|
//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 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(
|
Matrix4f lightView = new Matrix4f().setLookAt(
|
||||||
|
|||||||
@ -48,11 +48,11 @@ public class ServerContentGenerator {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup
|
// //setup
|
||||||
Random random = new Random(randomizer);
|
// Random random = new Random(randomizer);
|
||||||
|
|
||||||
|
|
||||||
//generate foliage
|
// //generate foliage
|
||||||
// BiomeData biome = null;
|
// BiomeData biome = null;
|
||||||
// if(realm.getServerWorldData() != null && realm.getServerWorldData().getServerTerrainManager() != null && realm.getServerWorldData().getServerTerrainManager().getModel() != null){
|
// if(realm.getServerWorldData() != null && realm.getServerWorldData().getServerTerrainManager() != null && realm.getServerWorldData().getServerTerrainManager().getModel() != null){
|
||||||
// biome = realm.getServerWorldData().getServerTerrainManager().getModel().getSurfaceBiome(worldPos.x, worldPos.z);
|
// biome = realm.getServerWorldData().getServerTerrainManager().getModel().getSurfaceBiome(worldPos.x, worldPos.z);
|
||||||
|
|||||||
@ -224,7 +224,11 @@ public class PoseActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(this.boneGroups == null){
|
} 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"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -26,19 +26,19 @@ public class DefaultChunkGenerator implements ChunkGenerator {
|
|||||||
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) {
|
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.
|
//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
|
//Hence, width should actually be chunk dimension + 1
|
||||||
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
|
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_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
|
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_DIMENSION; inc++){
|
for(int inc = 0; inc < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; inc++){
|
||||||
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
|
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightX++){
|
||||||
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
|
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightZ++){
|
||||||
weights[weightX][inc][weightZ] = -1;
|
weights[weightX][inc][weightZ] = -1;
|
||||||
values[weightX][inc][weightZ] = 0;
|
values[weightX][inc][weightZ] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(worldY < 1){
|
if(worldY < 1){
|
||||||
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
|
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightX++){
|
||||||
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
|
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightZ++){
|
||||||
weights[weightX][0][weightZ] = 0.1f;
|
weights[weightX][0][weightZ] = 0.1f;
|
||||||
values[weightX][0][weightZ] = baseVoxelId;
|
values[weightX][0][weightZ] = baseVoxelId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import electrosphere.client.terrain.cache.ChunkData;
|
import electrosphere.client.terrain.cache.ChunkData;
|
||||||
|
|
||||||
// import org.graalvm.polyglot.Value;
|
import org.graalvm.polyglot.Value;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.game.data.biome.BiomeData;
|
import electrosphere.game.data.biome.BiomeData;
|
||||||
@ -17,6 +17,10 @@ import electrosphere.server.terrain.generation.heightmap.HillsGen;
|
|||||||
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
||||||
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
||||||
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
|
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.manager.ServerTerrainChunk;
|
||||||
import electrosphere.server.terrain.models.TerrainModel;
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
|
|
||||||
@ -61,9 +65,14 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
ServerWorldData serverWorldData;
|
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
|
* Tracks whether to use javascript generation or not
|
||||||
@ -75,9 +84,11 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
*/
|
*/
|
||||||
public TestGenerationChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
|
public TestGenerationChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
|
||||||
this.serverWorldData = serverWorldData;
|
this.serverWorldData = serverWorldData;
|
||||||
registerGenerator(new EmptySkyGen());
|
registerHeightmapGenerator(new EmptySkyGen());
|
||||||
registerGenerator(new HillsGen());
|
registerHeightmapGenerator(new HillsGen());
|
||||||
registerGenerator(new PlainsGen());
|
registerHeightmapGenerator(new PlainsGen());
|
||||||
|
registerVoxelGenerator(new HillsVoxelGen());
|
||||||
|
registerVoxelGenerator(new AnimeMountainsGen());
|
||||||
this.useJavascript = useJavascript;
|
this.useJavascript = useJavascript;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,27 +96,31 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
* Registers a heightmap generator
|
* Registers a heightmap generator
|
||||||
* @param generator The heightmap generator
|
* @param generator The heightmap generator
|
||||||
*/
|
*/
|
||||||
private void registerGenerator(HeightmapGenerator generator){
|
private void registerHeightmapGenerator(HeightmapGenerator generator){
|
||||||
tagGeneratorMap.put(generator.getTag(),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
|
@Override
|
||||||
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) {
|
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) {
|
||||||
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.generateChunk");
|
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];;
|
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[][][] 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 {
|
try {
|
||||||
//actual generation algo
|
|
||||||
|
|
||||||
//biome of the current chunk
|
//biome of the current chunk
|
||||||
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
||||||
|
|
||||||
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
||||||
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag());
|
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
|
||||||
if(heightmapGen == null){
|
if(heightmapGen == null){
|
||||||
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
|
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){
|
if(this.useJavascript){
|
||||||
// Globals.scriptEngine.executeSynchronously(() -> {
|
Globals.scriptEngine.executeSynchronously(() -> {
|
||||||
// Value getVoxelFunc = Globals.scriptEngine.invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
|
int firstType = -2;
|
||||||
// for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
boolean homogenous = true;
|
||||||
// Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||||
// for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
Value getVoxelFunc = Globals.scriptEngine.invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
|
||||||
// for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||||
// int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
||||||
// int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||||
// int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||||
// int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
// int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
// int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
// Value result = getVoxelFunc.execute(
|
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
// finalWorldX, finalWorldY, finalWorldZ,
|
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
// finalChunkX, finalChunkY, finalChunkZ,
|
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
// stride,
|
getVoxelFunc.execute(
|
||||||
// heightfield[x][z],
|
voxel,
|
||||||
// surfaceBiome
|
finalWorldX, finalWorldY, finalWorldZ,
|
||||||
// );
|
finalChunkX, finalChunkY, finalChunkZ,
|
||||||
// if(result != null){
|
stride,
|
||||||
// weights[x][y][z] = result.getMember("weight").asFloat();
|
heightfield[x][z],
|
||||||
// values[x][y][z] = result.getMember("type").asInt();
|
surfaceBiome
|
||||||
// }
|
);
|
||||||
// }
|
weights[x][y][z] = voxel.weight;
|
||||||
// }
|
values[x][y][z] = voxel.type;
|
||||||
// Globals.profiler.endCpuSample();
|
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 {
|
} else {
|
||||||
|
int firstType = -2;
|
||||||
|
boolean homogenous = true;
|
||||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||||
|
GenerationContext generationContext = new GenerationContext();
|
||||||
|
generationContext.setServerWorldData(serverWorldData);
|
||||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
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 y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
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 finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
this.getVoxel(
|
voxelGenerator.getVoxel(
|
||||||
voxel,
|
voxel,
|
||||||
finalWorldX, finalWorldY, finalWorldZ,
|
finalWorldX, finalWorldY, finalWorldZ,
|
||||||
finalChunkX, finalChunkY, finalChunkZ,
|
finalChunkX, finalChunkY, finalChunkZ,
|
||||||
stride,
|
stride,
|
||||||
heightfield[x][z],
|
heightfield[x][z],
|
||||||
surfaceBiome
|
surfaceBiome,
|
||||||
|
generationContext
|
||||||
);
|
);
|
||||||
if(voxel != null){
|
if(voxel != null){
|
||||||
weights[x][y][z] = voxel.weight;
|
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){
|
} catch(Exception ex){
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
rVal = new ServerTerrainChunk(worldX, worldY, worldZ, homogenous ? firstType : ChunkData.NOT_HOMOGENOUS, weights, values);
|
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
@ -205,7 +245,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
||||||
|
|
||||||
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
||||||
HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag());
|
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
|
||||||
if(heightmapGen == null){
|
if(heightmapGen == null){
|
||||||
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
|
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;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,7 @@ public class HillsGen implements HeightmapGenerator {
|
|||||||
Globals.profiler.beginAggregateCpuSample("HillsGen.getHeight");
|
Globals.profiler.beginAggregateCpuSample("HillsGen.getHeight");
|
||||||
double scaledX = x * POSITION_SCALE;
|
double scaledX = x * POSITION_SCALE;
|
||||||
double scaledY = y * 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();
|
Globals.profiler.endCpuSample();
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
@ -80,6 +80,18 @@ public class ServerTerrainChunk {
|
|||||||
this.values = values;
|
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
|
* Gets the world position x coordinate
|
||||||
* @return The x coordinate
|
* @return The x coordinate
|
||||||
@ -201,5 +213,31 @@ public class ServerTerrainChunk {
|
|||||||
public int getHomogenousValue(){
|
public int getHomogenousValue(){
|
||||||
return homogenousValue;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,9 +40,11 @@ public class ClientDrawCellManagerTests {
|
|||||||
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));
|
||||||
node.setLeaf(true);
|
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
|
//cleanup
|
||||||
Main.shutdown();
|
Main.shutdown();
|
||||||
|
|||||||
@ -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));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user