hitbox fix + mountain gen
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-11-17 14:32:18 -05:00
parent d65efefc92
commit 596b0f6624
16 changed files with 477 additions and 48 deletions

View File

@ -70,7 +70,8 @@
"rotW": 1,
"offsetX" : 0.0,
"offsetY" : 0.5,
"offsetZ" : 0.0
"offsetZ" : 0.0,
"kinematic" : true
},
"interaction" : {
"onInteract" : "menu",

View File

@ -1056,6 +1056,11 @@ Update visuals on pine tree
Mountain generation work
Implement crafting
Fix image panel test
Add explicit kinematic flag in data
Fix hitbox destruction logic to not double-delete
(11/17/2024)
Mountain generation work

View File

@ -110,6 +110,9 @@ public class PhysicsEntityUtils {
if(physicsTemplate.isAngularlyStatic()){
Globals.clientSceneWrapper.getCollisionEngine().setAngularlyStatic(rigidBody, true);
}
if(physicsTemplate.getKinematic()){
Globals.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
}
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
@ -170,6 +173,9 @@ public class PhysicsEntityUtils {
if(physicsTemplate.isAngularlyStatic()){
Globals.clientSceneWrapper.getCollisionEngine().setAngularlyStatic(rigidBody, true);
}
if(physicsTemplate.getKinematic()){
Globals.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
}
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
@ -232,6 +238,9 @@ public class PhysicsEntityUtils {
if(physicsTemplate.isAngularlyStatic()){
Globals.clientSceneWrapper.getCollisionEngine().setAngularlyStatic(rigidBody, true);
}
if(physicsTemplate.getKinematic()){
Globals.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
}
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
@ -317,6 +326,9 @@ public class PhysicsEntityUtils {
if(physicsTemplate.isAngularlyStatic()){
realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
}
if(physicsTemplate.getKinematic()){
Globals.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
}
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
@ -377,6 +389,9 @@ public class PhysicsEntityUtils {
if(physicsTemplate.isAngularlyStatic()){
realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
}
if(physicsTemplate.getKinematic()){
Globals.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
}
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
@ -439,6 +454,9 @@ public class PhysicsEntityUtils {
if(physicsTemplate.isAngularlyStatic()){
realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
}
if(physicsTemplate.getKinematic()){
Globals.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
}
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);

View File

@ -18,6 +18,12 @@ public class AssetDataStrings {
public static final String MODEL_PARTICLE = "particleModel";
public static final String TEXTURE_PARTICLE = "particleTexture";
/**
* UI textures
*/
public static final String UI_FRAME_TEXTURE_DEFAULT_1 = "Textures/ui/uiFrame1.png";
public static final String UI_FRAME_TEXTURE_DEFAULT_2 = "Textures/ui/uiFrame2.png";
/**
* UI generic audio
*/

View File

@ -529,6 +529,7 @@ public class HitboxCollectionState {
state = HitboxCollectionState.getHitboxState(entity);
state.manager.deregisterHitbox(state);
state.destroy(isServer);
entity.removeData(EntityDataStrings.HITBOX_DATA);
}
return state;
}

View File

@ -517,8 +517,6 @@ public class ItemUtils {
//destroy physics
//this deregisters from all four & unhooks rigid bodies from the physics runtime
Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(item);
//destroy hitboxes
HitboxCollectionState.destroyHitboxState(item,false);
//destroy graphics
ClientEntityUtils.destroyEntity(item);
}

View File

@ -10,17 +10,54 @@ public class CollidableTemplate {
*/
String type;
/**
* The first dimension of the rigid body
*/
float dimension1;
/**
* The second dimension of the rigid body
*/
float dimension2;
/**
* The third dimension of the rigid body
*/
float dimension3;
/**
* The x component of the quaternion controlling the offset rotation of the body
*/
float rotX;
/**
* The y component of the quaternion controlling the offset rotation of the body
*/
float rotY;
/**
* The z component of the quaternion controlling the offset rotation of the body
*/
float rotZ;
/**
* The w component of the quaternion controlling the offset rotation of the body
*/
float rotW;
/**
* The x component of the vector controlling the offset position of the body
*/
float offsetX;
/**
* The y component of the vector controlling the offset position of the body
*/
float offsetY;
/**
* The z component of the vector controlling the offset position of the body
*/
float offsetZ;
/**
@ -43,6 +80,11 @@ public class CollidableTemplate {
*/
boolean angularlyStatic;
/**
* Controls whether the body is kinematic (infinite mass) or not
*/
boolean kinematic;
/**
* The primitive shape type
* @return The primitive shape
@ -51,42 +93,82 @@ public class CollidableTemplate {
return type;
}
/**
* Gets the first dimension of the rigid body
* @return The first dimension of the rigid body
*/
public float getDimension1() {
return dimension1;
}
/**
* Gets the second dimension of the rigid body
* @return The second dimension of the rigid body
*/
public float getDimension2() {
return dimension2;
}
/**
* Gets the third dimension of the rigid body
* @return The third dimension of the rigid body
*/
public float getDimension3() {
return dimension3;
}
/**
* Gets the x component of the quaternion controlling the offset rotation of the body
* @return The x component of the quaternion controlling the offset rotation of the body
*/
public float getRotX(){
return rotX;
}
/**
* Gets the y component of the quaternion controlling the offset rotation of the body
* @return The y component of the quaternion controlling the offset rotation of the body
*/
public float getRotY(){
return rotY;
}
/**
* Gets the z component of the quaternion controlling the offset rotation of the body
* @return The z component of the quaternion controlling the offset rotation of the body
*/
public float getRotZ(){
return rotZ;
}
/**
* Gets the w component of the quaternion controlling the offset rotation of the body
* @return The w component of the quaternion controlling the offset rotation of the body
*/
public float getRotW(){
return rotW;
}
/**
* Gets the x component of the vector controlling the offset position of the body
* @return The x component of the vector controlling the offset position of the body
*/
public float getOffsetX() {
return offsetX;
}
/**
* Gets the y component of the vector controlling the offset position of the body
* @return The y component of the vector controlling the offset position of the body
*/
public float getOffsetY() {
return offsetY;
}
/**
* Gets the z component of the vector controlling the offset position of the body
* @return The z component of the vector controlling the offset position of the body
*/
public float getOffsetZ() {
return offsetZ;
}
@ -123,30 +205,70 @@ public class CollidableTemplate {
return this.angularlyStatic;
}
/**
* Sets the first dimension of the rigid body
* @return The first dimension of the rigid body
*/
public void setDimension1(float dimension1) {
this.dimension1 = dimension1;
}
/**
* Sets the second dimension of the rigid body
* @return The second dimension of the rigid body
*/
public void setDimension2(float dimension2) {
this.dimension2 = dimension2;
}
/**
* Sets the third dimension of the rigid body
* @return The third dimension of the rigid body
*/
public void setDimension3(float dimension3) {
this.dimension3 = dimension3;
}
/**
* Sets the x component of the vector controlling the offset position of the body
* @return The x component of the vector controlling the offset position of the body
*/
public void setOffsetX(float offsetX) {
this.offsetX = offsetX;
}
/**
* Sets the y component of the vector controlling the offset position of the body
* @return The y component of the vector controlling the offset position of the body
*/
public void setOffsetY(float offsetY) {
this.offsetY = offsetY;
}
/**
* Sets the z component of the vector controlling the offset position of the body
* @return The z component of the vector controlling the offset position of the body
*/
public void setOffsetZ(float offsetZ) {
this.offsetZ = offsetZ;
}
/**
* Gets whether the body is kinematic (infinite mass) or not
* @return true if the body is kinematic, false otherwise
*/
public boolean getKinematic() {
return kinematic;
}
/**
* Sets whether the body is kinematic (infinite mass) or not
* @param kinematic true if the body is kinematic, false otherwise
*/
public void setKinematic(boolean kinematic) {
this.kinematic = kinematic;
}

View File

@ -3,7 +3,6 @@ package electrosphere.net.synchronization.transport;
import electrosphere.entity.state.movement.editor.ServerEditorMovementTree;
import electrosphere.entity.state.movement.editor.ClientEditorMovementTree;
import electrosphere.util.Utilities;
import electrosphere.entity.state.equip.ServerToolbarState;
import electrosphere.entity.state.equip.ClientToolbarState;
import electrosphere.entity.state.stance.ServerStanceComponent;

View File

@ -1,19 +1,16 @@
package electrosphere.renderer.ui.elements;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import java.util.LinkedList;
import java.util.List;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL40;
import org.lwjgl.util.yoga.YGLayout;
import org.lwjgl.util.yoga.YGNode;
import org.lwjgl.util.yoga.Yoga;
import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState;
@ -35,38 +32,70 @@ import electrosphere.renderer.ui.events.NavigationEvent;
*/
public class Window implements DrawableElement, ContainerElement, NavigableElement {
static Vector3f color = new Vector3f(1.0f);
/**
* The color of the window
*/
Vector3f color = new Vector3f(1.0f);
/**
* The child elements of this window
*/
List<Element> childList = new LinkedList<Element>();
/**
* The buffer to draw the contents of the window to
*/
Framebuffer widgetBuffer;
/**
* The material for the window
*/
Material customMat = new Material();
/**
* The position of buffer texture within the render call for the window itself
*/
Vector3f texPosition = new Vector3f(0,0,0);
/**
* The scale of buffer texture within the render call for the window itself
*/
Vector3f texScale = new Vector3f(1,1,0);
/**
* The navigation callback for the window
*/
NavigationEventCallback navCallback;
static final Vector3f windowDrawDebugColor = new Vector3f(1.0f,0.0f,0.0f);
/**
* Default width of popups
*/
static final int DEFAULT_POPUP_WIDTH = 1000;
/**
* Default height of popups
*/
static final int DEFAULT_POPUP_HEIGHT = 1000;
//controls whether to show window decorations (ie the frame)
/**
* Controls whether the decorations for the window draw or not
*/
boolean showDecorations = true;
//Yoga node for controlling placement of the window on the screen
//IE, if you want to place a window in the upper right hand side of the screen,
//this node can be used to control placement alignment to accomplish that
//NOTE: It should always be set to the current size of the window (width, height)
//NOTE: It is updated every time the applyYoga function is called
/**
* Yoga node for controlling placement of the window on the screen
* IE, if you want to place a window in the upper right hand side of the screen,
* this node can be used to control placement alignment to accomplish that
* NOTE: It should always be set to the current size of the window (width, height)
* NOTE: It is updated every time the applyYoga function is called
*/
long parentWindowYogaNode = -1;
/**
* The frame decoration texture path
*/
String frameDecoration = AssetDataStrings.UI_FRAME_TEXTURE_DEFAULT_1;
/**
* Constructor
* @param showDecorations
@ -186,12 +215,12 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
widgetBuffer.bind(openGLState);
openGLState.glViewport(width, height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GL40.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL40.glClear(GL40.GL_COLOR_BUFFER_BIT | GL40.GL_DEPTH_BUFFER_BIT);
//grab assets required to render window
Model planeModel = Globals.assetManager.fetchModel(Globals.imagePlaneModelID);
Texture windowFrame = Globals.assetManager.fetchTexture("Textures/ui/uiFrame1.png");
Texture windowFrame = Globals.assetManager.fetchTexture(AssetDataStrings.UI_FRAME_TEXTURE_DEFAULT_1);
for(Element child : childList){
if(child instanceof DrawableElement){
@ -227,7 +256,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions);
planeModel.pushUniformToMesh("plane", "tPosition", texPosition);
planeModel.pushUniformToMesh("plane", "tDimension", texScale);
planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", color);
planeModel.pushUniformToMesh(planeModel.getMeshes().get(0).getMeshName(), "color", new Vector3f(1.0f));
customMat.setTexturePointer(widgetBuffer.getTexture().getTexturePointer());
planeModel.getMeshes().get(0).setMaterial(customMat);
planeModel.drawUI();
@ -239,7 +268,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
*/
public void destroy(){
this.yogaNode = Element.NULL_YOGA_ELEMENT;
for(Element el : getChildren()){
for(Element el : this.getChildren()){
Globals.signalSystem.post(SignalType.YOGA_DESTROY, el);
}
this.clearChildren();
@ -252,7 +281,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
* clears all children
*/
public void clear(){
for(Element el : getChildren()){
for(Element el : this.getChildren()){
Globals.signalSystem.post(SignalType.YOGA_DESTROY, el);
}
this.clearChildren();
@ -836,4 +865,38 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
Yoga.YGNodeStyleSetPadding(this.yogaNode, Yoga.YGEdgeLeft, paddingLeft);
}
/**
* Gets the frame decoration texture path
* @return The frame decoration texture path
*/
public String getFrameDecoration() {
return frameDecoration;
}
/**
* Sets the frame decoration texture path
* @param frameDecoration The frame decoration texture path
*/
public void setFrameDecoration(String frameDecoration) {
this.frameDecoration = frameDecoration;
}
/**
* Gets the color of the window decorations
* @return The color of the decorations
*/
public Vector3f getColor() {
return color;
}
/**
* Sets the color of the window decorations
* @param color The color of the decorations
*/
public void setColor(Vector3f color) {
this.color = color;
}
}

View File

@ -19,7 +19,6 @@ import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.EntityMessage;
@ -384,27 +383,36 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
}
}
for(ServerDataCell cell : toCleanQueue){
boolean containsPlayerEntity = false;
//clear all entities in cell
for(Entity entity : cell.getScene().getEntityList()){
if(ServerPlayerViewDirTree.hasTree(entity)){
containsPlayerEntity = true;
break;
// int playerId = CreatureUtils.getControllerPlayerId(entity);
// Player player = Globals.playerManager.getPlayerFromId(playerId);
// throw new Error(
// "Trying to unload a player's entity! " +
// "entity: " + entity + "\n" +
// "entity pos (real): " + EntityUtils.getPosition(entity) + "\n" +
// "entity pos (world): " + serverWorldData.convertRealToWorldSpace(EntityUtils.getPosition(entity)) + "\n" +
// "chunk pos (world): " + worldPos + "\n" +
// "player pos (world): " + player.getWorldPos() + "\n" +
// "Number of players in cell: " + cell.getPlayers().size()
// );
}
// ServerEntityUtils.destroyEntity(entity);
}
if(containsPlayerEntity){
continue;
}
parent.deregisterCell(cell);
Vector3i worldPos = getCellWorldPosition(cell);
Long key = getServerDataCellKey(worldPos);
groundDataCells.remove(key);
//offload all entities in cell to chunk file
serverContentManager.saveContentToDisk(key, cell.getScene().getEntityList());
//clear all entities in cell
for(Entity entity : cell.getScene().getEntityList()){
if(ServerPlayerViewDirTree.hasTree(entity)){
int playerId = CreatureUtils.getControllerPlayerId(entity);
Player player = Globals.playerManager.getPlayerFromId(playerId);
throw new Error(
"Trying to unload a player's entity! " +
"entity: " + entity + "\n" +
"entity pos (real): " + EntityUtils.getPosition(entity) + "\n" +
"entity pos (world): " + serverWorldData.convertRealToWorldSpace(EntityUtils.getPosition(entity)) + "\n" +
"chunk pos (world): " + worldPos + "\n" +
"player pos (world): " + player.getWorldPos() + "\n" +
"Number of players in cell: " + cell.getPlayers().size()
);
}
ServerEntityUtils.destroyEntity(entity);
}
//save terrain to disk

View File

@ -21,6 +21,7 @@ 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.MountainVoxelGen;
import electrosphere.server.terrain.generation.voxelphase.VoxelGenerator;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.models.TerrainModel;
@ -91,6 +92,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
this.registerHeightmapGenerator(new MountainGen());
this.registerVoxelGenerator(new HillsVoxelGen());
this.registerVoxelGenerator(new AnimeMountainsGen());
this.registerVoxelGenerator(new MountainVoxelGen());
this.useJavascript = useJavascript;
}
@ -123,7 +125,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
heightmapGen = this.tagHeightmapMap.get("mountains");
heightmapGen = this.tagHeightmapMap.get("hills");
if(heightmapGen == null){
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
}
@ -147,6 +149,25 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
}
}
float[][] gradientField = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
float deltaX = 0;
float deltaZ = 0;
if(x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1){
deltaX = Math.abs(heightfield[x][z] - heightfield[x+1][z]);
} else {
deltaX = Math.abs(heightfield[x][z] - heightfield[x-1][z]);
}
if(z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1){
deltaX = Math.abs(heightfield[x][z] - heightfield[x][z+1]);
} else {
deltaX = Math.abs(heightfield[x][z] - heightfield[x][z-1]);
}
gradientField[x][z] = deltaX * deltaX + deltaZ * deltaZ;
}
}
VoxelGenerator voxelGenerator = this.tagVoxelMap.get("hills");
if(this.useJavascript){
@ -212,7 +233,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
finalWorldX, finalWorldY, finalWorldZ,
finalChunkX, finalChunkY, finalChunkZ,
stride,
heightfield[x][z],
heightfield[x][z], gradientField[x][z],
surfaceBiome,
generationContext
);

View File

@ -1,5 +1,6 @@
package electrosphere.server.terrain.generation.heightmap;
import electrosphere.util.noise.OpenSimplex2S;
import io.github.studiorailgun.NoiseUtils;
public class MountainGen implements HeightmapGenerator {
@ -17,18 +18,20 @@ public class MountainGen implements HeightmapGenerator {
/**
* Vertical scale of the noise
*/
static final float VERTICAL_SCALE = 1024.0f;
static final float VERTICAL_SCALE = 512.0f;
/**
* Horizontal scale of the noise
*/
static final float HORIZONTAL_SCALE = 1024.0f;
static final float HORIZONTAL_SCALE = 512.0f;
/**
* The power applied to the noise
*/
static final float POWER_SCALE = 2;
static final float RELAXATION_FACTOR = 0.13f;
/**
* The scale to apply to the coordinates
*/
@ -52,15 +55,40 @@ public class MountainGen implements HeightmapGenerator {
* @return The height
*/
public float getHeight(long SEED, double x, double y){
return this.getHeight1(SEED, x, y);
}
/**
* Gets the height at a given position for this generation approach
* @param SEED The seed
* @param x The x position
* @param y The y position
* @return The height
*/
public float getHeight1(long SEED, double x, double y){
float rVal = 0.0f;
double smoothVoronoiSample = NoiseUtils.smoothVoronoi(x * GEN_SCALE, y * GEN_SCALE, (double)SEED, FALLOFF_FACTOR);
double inverted = 1.0 - smoothVoronoiSample;
double minClamped = Math.max(inverted,0.0f);
double noisy = inverted +
0.02 * OpenSimplex2S.noise2(SEED, x * GEN_SCALE * 3, y * GEN_SCALE * 3) +
0.005 * OpenSimplex2S.noise2(SEED, x * GEN_SCALE * 5, y * GEN_SCALE * 5)
;
double minClamped = Math.max(noisy,0.0f);
double powered = Math.pow(minClamped,POWER_SCALE);
rVal = (float)powered * VERTICAL_SCALE;
return rVal;
}
public float getHeight2(long SEED, double x, double y){
double invertedMinDist = (
1.0 * (NoiseUtils.voronoiRelaxed(x * GEN_SCALE, y * GEN_SCALE, RELAXATION_FACTOR)) +
0.5 * (NoiseUtils.voronoiRelaxed(x * 1.2 * GEN_SCALE, y * 1.2 * GEN_SCALE, RELAXATION_FACTOR)) +
0.3 * (NoiseUtils.voronoiRelaxed(x * 2 * GEN_SCALE, y * 2 * GEN_SCALE, RELAXATION_FACTOR))
);
return (float)(Math.max(invertedMinDist - 0.6,0) / 1.6 * VERTICAL_SCALE);
}
@Override
public String getTag() {

View File

@ -67,7 +67,7 @@ public class AnimeMountainsGen implements VoxelGenerator {
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
int stride, float surfaceHeight,
int stride, float surfaceHeight, float surfaceGradient,
BiomeData surfaceBiome,
GenerationContext generationContext
) {

View File

@ -27,7 +27,7 @@ public class HillsVoxelGen implements VoxelGenerator {
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
int stride,
float surfaceHeight,
float surfaceHeight, float surfaceGradient,
BiomeData surfaceBiome,
GenerationContext generationContext
){

View File

@ -0,0 +1,158 @@
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;
public class MountainVoxelGen implements VoxelGenerator {
/**
* The width of the surface in number of voxels
*/
public static final int SURFACE_VOXEL_WIDTH = 2;
/**
* Cutoff after which snow is placed
*/
public static final int SNOW_CUTOFF = 150;
/**
* Gradient cutoff after which dirt is placed
*/
public static final float GRADIENT_DIRT_CUTOFF = 0.1f;
@Override
public String getTag(){
return "mountains";
}
@Override
public void getVoxel(
GeneratedVoxel voxel,
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
int stride,
float surfaceHeight, float surfaceGradient,
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, surfaceGradient,
surfaceBiome
);
} else if(heightDiff > 0) {
this.getOverSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,-
surfacePercent,
surfaceHeight, surfaceGradient,
surfaceBiome
);
} else {
this.getSurfaceVoxel(
voxel,
worldX, worldY, worldZ,
chunkX, chunkY, chunkZ,
realX, realY, realZ,
surfacePercent,
surfaceHeight, surfaceGradient,
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, float surfaceGradient,
BiomeData surfaceBiome
){
voxel.weight = (float)surfacePercent * 2 - 1;
voxel.type = 2;
if(realY > SNOW_CUTOFF){
voxel.type = 5;
} else {
if(surfaceGradient > GRADIENT_DIRT_CUTOFF){
voxel.type = 1;
}
}
}
/**
* 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, float surfaceGradient,
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, float surfaceGradient,
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

@ -29,6 +29,7 @@ public interface VoxelGenerator {
* @param chunkZ The chunk z pos
* @param stride The stride of the data
* @param surfaceHeight The height of the surface at x,z
* @param surfaceGradient The rate of change in the surface at this point
* @param surfaceBiome The surface biome of the chunk
* @param generationContext The generation context
*/
@ -37,7 +38,7 @@ public interface VoxelGenerator {
int worldX, int worldY, int worldZ,
int chunkX, int chunkY, int chunkZ,
int stride,
float surfaceHeight,
float surfaceHeight, float surfaceGradient,
BiomeData surfaceBiome,
GenerationContext generationContext
);