Networked terrain editing
This commit is contained in:
parent
01fb472585
commit
a8941c5de7
@ -54,6 +54,19 @@
|
|||||||
"type" : "FIXED_INT"
|
"type" : "FIXED_INT"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name" : "voxelX",
|
||||||
|
"type" : "FIXED_INT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "voxelY",
|
||||||
|
"type" : "FIXED_INT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "voxelZ",
|
||||||
|
"type" : "FIXED_INT"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -111,11 +124,40 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"messageName" : "Update",
|
"messageName" : "RequestEditVoxel",
|
||||||
"data" : [
|
"data" : [
|
||||||
"worldX",
|
"worldX",
|
||||||
"worldY",
|
"worldY",
|
||||||
"worldZ"
|
"worldZ",
|
||||||
|
"voxelX",
|
||||||
|
"voxelY",
|
||||||
|
"voxelZ",
|
||||||
|
"terrainWeight",
|
||||||
|
"terrainValue"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"messageName" : "UpdateVoxel",
|
||||||
|
"data" : [
|
||||||
|
"worldX",
|
||||||
|
"worldY",
|
||||||
|
"worldZ",
|
||||||
|
"voxelX",
|
||||||
|
"voxelY",
|
||||||
|
"voxelZ",
|
||||||
|
"terrainWeight",
|
||||||
|
"terrainValue"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"messageName" : "RequestUseTerrainPalette",
|
||||||
|
"data" : [
|
||||||
|
"realLocationX",
|
||||||
|
"realLocationY",
|
||||||
|
"realLocationZ",
|
||||||
|
"value",
|
||||||
|
"terrainWeight",
|
||||||
|
"terrainValue"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -141,7 +141,7 @@ public class ClientFoliageManager {
|
|||||||
modelMatrix.rotate(new Quaterniond(grassRotation));
|
modelMatrix.rotate(new Quaterniond(grassRotation));
|
||||||
modelMatrix.scale(new Vector3d(EntityUtils.getScale(grassEntity)));
|
modelMatrix.scale(new Vector3d(EntityUtils.getScale(grassEntity)));
|
||||||
|
|
||||||
instancedActor.setAttribute(modelMatrixAttribute, modelMatrix);
|
instancedActor.setAttribute(modelMatrixAttribute, new Matrix4f(modelMatrix));
|
||||||
|
|
||||||
//draw
|
//draw
|
||||||
// instancedActor.draw(Globals.renderingEngine.getRenderPipelineState());
|
// instancedActor.draw(Globals.renderingEngine.getRenderPipelineState());
|
||||||
|
|||||||
@ -7,8 +7,10 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
|||||||
*/
|
*/
|
||||||
public class ChunkData {
|
public class ChunkData {
|
||||||
|
|
||||||
//The size of a chunk
|
//The size of a chunk in virtual data
|
||||||
public static final int CHUNK_SIZE = ServerTerrainChunk.CHUNK_DIMENSION;
|
public static final int CHUNK_SIZE = ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
//The size of the data passed into marching cubes/transvoxel algorithm to get a fully connected and seamless chunk
|
||||||
|
public static final int CHUNK_DATA_GENERATOR_SIZE = ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE;
|
||||||
|
|
||||||
//What type of terrain is in this voxel, eg stone vs dirt vs grass, etc
|
//What type of terrain is in this voxel, eg stone vs dirt vs grass, etc
|
||||||
int[][][] voxelType;
|
int[][][] voxelType;
|
||||||
|
|||||||
@ -72,7 +72,7 @@ public class DrawCell {
|
|||||||
if(modelEntity != null){
|
if(modelEntity != null){
|
||||||
Globals.clientScene.deregisterEntity(modelEntity);
|
Globals.clientScene.deregisterEntity(modelEntity);
|
||||||
}
|
}
|
||||||
modelEntity = TerrainChunk.clientCreateTerrainChunkEntity(data.getVoxelWeight(), data.getVoxelType());
|
modelEntity = TerrainChunk.clientCreateTerrainChunkEntity(data.getVoxelWeight(), data.getVoxelType(), 0);
|
||||||
// TerrainChunk.createTerrainChunkEntity();
|
// TerrainChunk.createTerrainChunkEntity();
|
||||||
// Model terrainModel = RenderUtils.createMinimizedTerrainModelPrecomputedShader(heightmap, texturemap, program, stride);
|
// Model terrainModel = RenderUtils.createMinimizedTerrainModelPrecomputedShader(heightmap, texturemap, program, stride);
|
||||||
// Mesh terrainMesh = terrainModel.meshes.get(0);
|
// Mesh terrainMesh = terrainModel.meshes.get(0);
|
||||||
@ -97,10 +97,6 @@ public class DrawCell {
|
|||||||
ClientEntityUtils.initiallyPositionEntity(modelEntity, getRealPos());
|
ClientEntityUtils.initiallyPositionEntity(modelEntity, getRealPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void retireCell(){
|
|
||||||
EntityUtils.cleanUpEntity(modelEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Vector3d getRealPos(){
|
protected Vector3d getRealPos(){
|
||||||
return new Vector3d(
|
return new Vector3d(
|
||||||
worldPos.x * ChunkData.CHUNK_SIZE,
|
worldPos.x * ChunkData.CHUNK_SIZE,
|
||||||
@ -122,12 +118,12 @@ public class DrawCell {
|
|||||||
// // System.out.println("generate physics");
|
// // System.out.println("generate physics");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys a drawcell including its physics
|
||||||
|
*/
|
||||||
public void destroy(){
|
public void destroy(){
|
||||||
Realm realm = Globals.realmManager.getEntityRealm(modelEntity);
|
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
|
||||||
if(realm != null){
|
|
||||||
CollisionEngine collisionEngine = Globals.realmManager.getEntityRealm(modelEntity).getCollisionEngine();
|
|
||||||
collisionEngine.destroyEntityThatHasPhysics(modelEntity);
|
collisionEngine.destroyEntityThatHasPhysics(modelEntity);
|
||||||
}
|
|
||||||
EntityUtils.cleanUpEntity(modelEntity);
|
EntityUtils.cleanUpEntity(modelEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,71 @@
|
|||||||
|
package electrosphere.client.terrain.editing;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
import org.joml.Vector3i;
|
||||||
|
|
||||||
|
import electrosphere.client.terrain.cache.ChunkData;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for editing terrain from client side of things
|
||||||
|
*/
|
||||||
|
public class TerrainEditing {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a terrain chunk edit. Basically has a sphere around the provided position that it attempts to add value to.
|
||||||
|
* @param position The position to perform the edit
|
||||||
|
* @param editMagnitude The magnitude of the edit to perform
|
||||||
|
* @param type The type of block to make all edited blocks
|
||||||
|
* @param weight The weight of the sphere to apply the edit to
|
||||||
|
*/
|
||||||
|
public static void editTerrain(Vector3d position, float editMagnitude, int type, float weight){
|
||||||
|
if(position != null){
|
||||||
|
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestUseTerrainPaletteMessage(position.x, position.y, position.z, editMagnitude, weight, type));
|
||||||
|
//calculate kernel size
|
||||||
|
// int numPlacesToCheck = (int)((editMagnitude * 2 + 1) * (editMagnitude * 2 + 1) * (editMagnitude * 2 + 1));
|
||||||
|
// //create and fill in kernel of positions to check
|
||||||
|
// int[] xOffsetSet = new int[numPlacesToCheck];
|
||||||
|
// int[] yOffsetSet = new int[numPlacesToCheck];
|
||||||
|
// int[] zOffsetSet = new int[numPlacesToCheck];
|
||||||
|
// int i = 0;
|
||||||
|
// for(int x = -(int)editMagnitude; x <= (int)editMagnitude; x++){
|
||||||
|
// for(int y = -(int)editMagnitude; y <= (int)editMagnitude; y++){
|
||||||
|
// for(int z = -(int)editMagnitude; z <= (int)editMagnitude; z++){
|
||||||
|
// xOffsetSet[i] = x;
|
||||||
|
// yOffsetSet[i] = y;
|
||||||
|
// zOffsetSet[i] = z;
|
||||||
|
// i++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for(i = 0; i < numPlacesToCheck; i++){
|
||||||
|
// //calculate position of edit
|
||||||
|
// Vector3d offsetPos = new Vector3d(position).add(xOffsetSet[i],yOffsetSet[i],zOffsetSet[i]);
|
||||||
|
// Vector3i chunkPos = Globals.clientWorldData.convertRealToChunkSpace(offsetPos);
|
||||||
|
// Vector3i voxelPos = Globals.clientWorldData.convertRealToVoxelSpace(offsetPos);
|
||||||
|
// //get distance from true center point of sphere to current voxel position in world space
|
||||||
|
// float distance = (float)new Vector3d(Math.floor(offsetPos.x),Math.floor(offsetPos.y),Math.floor(offsetPos.z)).distance(position);
|
||||||
|
// float currentPositionMagnitude = editMagnitude - distance;
|
||||||
|
// ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(chunkPos.x, chunkPos.y, chunkPos.z);
|
||||||
|
// if(
|
||||||
|
// voxelPos.x < ChunkData.CHUNK_SIZE &&
|
||||||
|
// voxelPos.y < ChunkData.CHUNK_SIZE &&
|
||||||
|
// voxelPos.z < ChunkData.CHUNK_SIZE &&
|
||||||
|
// currentPositionMagnitude > 0 &&
|
||||||
|
// data != null
|
||||||
|
// ){
|
||||||
|
// float current = data.getVoxelWeight()[voxelPos.x][voxelPos.y][voxelPos.z];
|
||||||
|
// //hard clamp so it doesn't go over 1
|
||||||
|
// float finalValue = Math.max(Math.min(current + weight,1),-1);
|
||||||
|
// Globals.clientTerrainManager.updateChunk(
|
||||||
|
// chunkPos.x, chunkPos.y, chunkPos.z,
|
||||||
|
// voxelPos.x, voxelPos.y, voxelPos.z,
|
||||||
|
// finalValue, 1
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -56,22 +56,22 @@ public class ClientTerrainManager {
|
|||||||
messageQueue.remove(message);
|
messageQueue.remove(message);
|
||||||
switch(message.getMessageSubtype()){
|
switch(message.getMessageSubtype()){
|
||||||
case SENDCHUNKDATA: {
|
case SENDCHUNKDATA: {
|
||||||
int[][][] values = new int[ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE];
|
int[][][] values = new int[ChunkData.CHUNK_DATA_GENERATOR_SIZE][ChunkData.CHUNK_DATA_GENERATOR_SIZE][ChunkData.CHUNK_DATA_GENERATOR_SIZE];
|
||||||
float[][][] weights = new float[ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE];
|
float[][][] weights = new float[ChunkData.CHUNK_DATA_GENERATOR_SIZE][ChunkData.CHUNK_DATA_GENERATOR_SIZE][ChunkData.CHUNK_DATA_GENERATOR_SIZE];
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
|
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
|
||||||
FloatBuffer floatBuffer = buffer.asFloatBuffer();
|
FloatBuffer floatBuffer = buffer.asFloatBuffer();
|
||||||
for(int x = 0; x < ChunkData.CHUNK_SIZE; x++){
|
for(int x = 0; x < ChunkData.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||||
for(int y = 0; y < ChunkData.CHUNK_SIZE; y++){
|
for(int y = 0; y < ChunkData.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||||
for(int z = 0; z < ChunkData.CHUNK_SIZE; z++){
|
for(int z = 0; z < ChunkData.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||||
weights[x][y][z] = floatBuffer.get();
|
weights[x][y][z] = floatBuffer.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IntBuffer intView = buffer.asIntBuffer();
|
IntBuffer intView = buffer.asIntBuffer();
|
||||||
intView.position(floatBuffer.position());
|
intView.position(floatBuffer.position());
|
||||||
for(int x = 0; x < ChunkData.CHUNK_SIZE; x++){
|
for(int x = 0; x < ChunkData.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||||
for(int y = 0; y < ChunkData.CHUNK_SIZE; y++){
|
for(int y = 0; y < ChunkData.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||||
for(int z = 0; z < ChunkData.CHUNK_SIZE; z++){
|
for(int z = 0; z < ChunkData.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||||
values[x][y][z] = intView.get();
|
values[x][y][z] = intView.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import static org.ode4j.ode.internal.Common.dRecip;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
@ -469,130 +471,6 @@ public class CollisionEngine {
|
|||||||
// return entityHeight > worldHeight + 0.1f;
|
// return entityHeight > worldHeight + 0.1f;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public float sweepTest(DBody body, Vector3f startPos, Vector3f endPos){
|
|
||||||
// space.collide2(body.getFirstGeom(), endPos, nearCallback);
|
|
||||||
// SphereShape sphere = new SphereShape(0.1f);
|
|
||||||
// // CollisionObject collider = new CollisionObject();
|
|
||||||
// // collider.setCollisionShape(sphere);
|
|
||||||
// ClosestConvexResultCallbackImpl callback = new ClosestConvexResultCallbackImpl(startPos,endPos,object,dispatcher,world.getPairCache());
|
|
||||||
// callback.collisionFilterGroup = 1;
|
|
||||||
// callback.collisionFilterMask = 1;
|
|
||||||
// world.convexSweepTest(sphere, PhysicsUtils.jomlVecToTransform(startPos), PhysicsUtils.jomlVecToTransform(endPos), callback);
|
|
||||||
// // callback.hasHit()
|
|
||||||
// if(callback.hasHit()){
|
|
||||||
// return callback.closestHitFraction;
|
|
||||||
// } else {
|
|
||||||
// return -1.0f;
|
|
||||||
// }
|
|
||||||
return -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean RaycastQuery(DSpace space, DVector3 start, DVector3 end) {
|
|
||||||
|
|
||||||
// Calculate direction
|
|
||||||
DVector3 direction = new DVector3();
|
|
||||||
dSubtractVectors3(direction, end, start);
|
|
||||||
|
|
||||||
// Get length
|
|
||||||
double length = dCalcVectorLengthSquare3(direction);
|
|
||||||
double inverseLength = dRecip(length);
|
|
||||||
|
|
||||||
// Normalize
|
|
||||||
direction.scale(inverseLength);
|
|
||||||
|
|
||||||
// Create ray
|
|
||||||
DRay ray = OdeHelper.createRay(space, length);
|
|
||||||
ray.set(start.get0(), start.get1(), start.get2(), direction.get0(), direction.get1(), direction.get2());
|
|
||||||
|
|
||||||
// Check collisions
|
|
||||||
DVector4 hitPosition = new DVector4();
|
|
||||||
hitPosition.set3(dInfinity);
|
|
||||||
space.collide2(ray, null, nearCallback);
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
ray.destroy();
|
|
||||||
|
|
||||||
// Check for hit
|
|
||||||
if(hitPosition.get3() != dInfinity) {
|
|
||||||
end.set0(hitPosition.get0());
|
|
||||||
end.set1(hitPosition.get1());
|
|
||||||
end.set2(hitPosition.get2());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// private static class ClosestConvexResultCallbackImpl extends ClosestConvexResultCallback {
|
|
||||||
|
|
||||||
// CollisionObject me;
|
|
||||||
// private OverlappingPairCache pairCache;
|
|
||||||
// private Dispatcher dispatcher;
|
|
||||||
|
|
||||||
// public ClosestConvexResultCallbackImpl(Vector3f startPos, Vector3f endPos, CollisionObject me, Dispatcher dispatcher, OverlappingPairCache pairCache){
|
|
||||||
// super(PhysicsUtils.jomlToVecmathVector3f(startPos),PhysicsUtils.jomlToVecmathVector3f(endPos));
|
|
||||||
// this.me = me;
|
|
||||||
// this.pairCache = pairCache;
|
|
||||||
// this.dispatcher = dispatcher;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public float addSingleResult(LocalConvexResult convexResult, boolean normalInWorldSpace) {
|
|
||||||
// if (convexResult.hitCollisionObject == me) {
|
|
||||||
// return 1f;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Vector3f linVelA = new Vector3f(), linVelB = new Vector3f();
|
|
||||||
// linVelA.sub(PhysicsUtils.vecmathToJomlVector3f(convexToWorld), PhysicsUtils.vecmathToJomlVector3f(convexFromWorld));
|
|
||||||
// linVelB.set(0f, 0f, 0f);//toB.getOrigin()-fromB.getOrigin();
|
|
||||||
|
|
||||||
// Vector3f relativeVelocity = new Vector3f();
|
|
||||||
// relativeVelocity.sub(linVelA, linVelB);
|
|
||||||
// // don't report time of impact for motion away from the contact normal (or causes minor penetration)
|
|
||||||
// if (convexResult.hitNormalLocal.dot(PhysicsUtils.jomlToVecmathVector3f(relativeVelocity)) >= -0f) {
|
|
||||||
// return 1f;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return super.addSingleResult(convexResult, normalInWorldSpace);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public boolean needsCollision(BroadphaseProxy proxy0) {
|
|
||||||
// // don't collide with itself
|
|
||||||
// if (proxy0.clientObject == me) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // don't do CCD when the collision filters are not matching
|
|
||||||
// if (!super.needsCollision(proxy0)) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// CollisionObject otherObj = (CollisionObject)proxy0.clientObject;
|
|
||||||
|
|
||||||
// // call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
|
|
||||||
// if (dispatcher.needsResponse(me, otherObj)) {
|
|
||||||
// // don't do CCD when there are already contact points (touching contact/penetration)
|
|
||||||
// ObjectArrayList<PersistentManifold> manifoldArray = new ObjectArrayList<PersistentManifold>();
|
|
||||||
// BroadphasePair collisionPair = pairCache.findPair(me.getBroadphaseHandle(), proxy0);
|
|
||||||
// if (collisionPair != null) {
|
|
||||||
// if (collisionPair.algorithm != null) {
|
|
||||||
// //manifoldArray.resize(0);
|
|
||||||
// collisionPair.algorithm.getAllContactManifolds(manifoldArray);
|
|
||||||
// for (int j=0; j<manifoldArray.size(); j++) {
|
|
||||||
// PersistentManifold manifold = manifoldArray.getQuick(j);
|
|
||||||
// if (manifold.getNumContacts() > 0) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Casts a ray into the scene and returns the first entity that the ray collides with.
|
* Casts a ray into the scene and returns the first entity that the ray collides with.
|
||||||
@ -654,6 +532,29 @@ public class CollisionEngine {
|
|||||||
return data.collisionPosition;
|
return data.collisionPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ray casts into the scene and gets the position of the closest collision's position in world space.
|
||||||
|
* @param start The start position of the ray to cast
|
||||||
|
* @param direction The direction of the ray to cast
|
||||||
|
* @param length The length of the ray to cast
|
||||||
|
* @param typeMask The mask of types to collide the ray with
|
||||||
|
* @return The position, in world coordinates, of the closest collision of the way, or null if it did not collide with anything.
|
||||||
|
*/
|
||||||
|
public Vector3d rayCastPositionMasked(Vector3d start, Vector3d direction, double length, List<String> typeMask){
|
||||||
|
spaceLock.acquireUninterruptibly();
|
||||||
|
//create the ray
|
||||||
|
DRay ray = OdeHelper.createRay(space, length);
|
||||||
|
ray.set(start.x, start.y, start.z, direction.x, direction.y, direction.z);
|
||||||
|
//collide
|
||||||
|
RayCastCallbackData data = new RayCastCallbackData(bodyPointerMap, typeMask);
|
||||||
|
rayCastCallback.setLength(length);
|
||||||
|
space.collide2(ray, data, rayCastCallback);
|
||||||
|
//destroy ray
|
||||||
|
ray.destroy();
|
||||||
|
spaceLock.release();
|
||||||
|
return data.collisionPosition;
|
||||||
|
}
|
||||||
|
|
||||||
public void registerPhysicsObject(DBody body){
|
public void registerPhysicsObject(DBody body){
|
||||||
if(!bodies.contains(body)){
|
if(!bodies.contains(body)){
|
||||||
bodies.add(body);
|
bodies.add(body);
|
||||||
@ -661,11 +562,23 @@ public class CollisionEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys a body and all geometry under the body
|
||||||
|
* @param body The DBody to destroy
|
||||||
|
*/
|
||||||
public void deregisterPhysicsObject(DBody body){
|
public void deregisterPhysicsObject(DBody body){
|
||||||
|
spaceLock.acquireUninterruptibly();
|
||||||
if(bodies.contains(body)){
|
if(bodies.contains(body)){
|
||||||
bodies.remove(body);
|
bodies.remove(body);
|
||||||
}
|
}
|
||||||
|
Iterator<DGeom> geomIterator = body.getGeomIterator();
|
||||||
|
while(geomIterator.hasNext()){
|
||||||
|
DGeom geom = geomIterator.next();
|
||||||
|
space.remove(geom);
|
||||||
|
geom.destroy();
|
||||||
|
}
|
||||||
body.destroy();
|
body.destroy();
|
||||||
|
spaceLock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deregisterRigidBody(DBody body){
|
public void deregisterRigidBody(DBody body){
|
||||||
@ -695,7 +608,7 @@ public class CollisionEngine {
|
|||||||
|
|
||||||
public void destroyEntityThatHasPhysics(Entity e){
|
public void destroyEntityThatHasPhysics(Entity e){
|
||||||
//make uncollidable
|
//make uncollidable
|
||||||
if(e.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && e.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){
|
if(e.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY)){
|
||||||
DBody rigidBody = (DBody)e.getData(EntityDataStrings.PHYSICS_COLLISION_BODY);
|
DBody rigidBody = (DBody)e.getData(EntityDataStrings.PHYSICS_COLLISION_BODY);
|
||||||
deregisterPhysicsObject(rigidBody);
|
deregisterPhysicsObject(rigidBody);
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/main/java/electrosphere/collision/CollisionMasks.java
Normal file
24
src/main/java/electrosphere/collision/CollisionMasks.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package electrosphere.collision;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import electrosphere.collision.collidable.Collidable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains masks for different collision engine functions
|
||||||
|
*/
|
||||||
|
public class CollisionMasks {
|
||||||
|
|
||||||
|
//Only terrain
|
||||||
|
public static final LinkedList<String> terrainMask = new LinkedList<String>();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills in all the collision engine masks
|
||||||
|
*/
|
||||||
|
public static void initMasks(){
|
||||||
|
//terrain mask
|
||||||
|
terrainMask.add(Collidable.TYPE_TERRAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -69,12 +69,11 @@ import java.util.List;
|
|||||||
import org.joml.Vector2f;
|
import org.joml.Vector2f;
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
import org.joml.Vector3i;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import electrosphere.audio.AudioUtils;
|
import electrosphere.audio.AudioUtils;
|
||||||
import electrosphere.client.targeting.crosshair.Crosshair;
|
import electrosphere.client.targeting.crosshair.Crosshair;
|
||||||
import electrosphere.client.terrain.cache.ChunkData;
|
import electrosphere.client.terrain.editing.TerrainEditing;
|
||||||
import electrosphere.collision.CollisionEngine;
|
import electrosphere.collision.CollisionEngine;
|
||||||
import electrosphere.controls.Control.ControlMethod;
|
import electrosphere.controls.Control.ControlMethod;
|
||||||
import electrosphere.controls.Control.ControlType;
|
import electrosphere.controls.Control.ControlType;
|
||||||
@ -134,6 +133,7 @@ public class ControlHandler {
|
|||||||
public static final String INPUT_CODE_CHARACTER_OPEN = "characterOpen";
|
public static final String INPUT_CODE_CHARACTER_OPEN = "characterOpen";
|
||||||
public static final String INPUT_CODE_IRON_SIGHT = "ironSight";
|
public static final String INPUT_CODE_IRON_SIGHT = "ironSight";
|
||||||
public static final String INPUT_CODE_PLACE_TERRAIN = "placeTerrain";
|
public static final String INPUT_CODE_PLACE_TERRAIN = "placeTerrain";
|
||||||
|
public static final String INPUT_CODE_REMOVE_TERRAIN = "removeTerrain";
|
||||||
|
|
||||||
public static final String DATA_STRING_INPUT_CODE_MENU_NAVIGATE_FORWARD = "menuNavigateForward";
|
public static final String DATA_STRING_INPUT_CODE_MENU_NAVIGATE_FORWARD = "menuNavigateForward";
|
||||||
public static final String DATA_STRING_INPUT_CODE_MENU_NAVIGATE_BACKWARDS = "menuNavigateBackwards";
|
public static final String DATA_STRING_INPUT_CODE_MENU_NAVIGATE_BACKWARDS = "menuNavigateBackwards";
|
||||||
@ -328,6 +328,7 @@ public class ControlHandler {
|
|||||||
Terrain controls
|
Terrain controls
|
||||||
*/
|
*/
|
||||||
handler.addControl(INPUT_CODE_PLACE_TERRAIN, new Control(ControlType.KEY,GLFW_KEY_T));
|
handler.addControl(INPUT_CODE_PLACE_TERRAIN, new Control(ControlType.KEY,GLFW_KEY_T));
|
||||||
|
handler.addControl(INPUT_CODE_REMOVE_TERRAIN, new Control(ControlType.KEY,GLFW_KEY_Y));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
framestep controls
|
framestep controls
|
||||||
@ -942,50 +943,52 @@ public class ControlHandler {
|
|||||||
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera));
|
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera));
|
||||||
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
|
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
|
||||||
Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0);
|
Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0);
|
||||||
int[] xOffsetSet = new int[]{
|
TerrainEditing.editTerrain(cursorPos, 1.1f, 1, 0.01f);
|
||||||
0,1,0,1,0,1,0,1,
|
|
||||||
};
|
|
||||||
int[] yOffsetSet = new int[]{
|
|
||||||
0,0,0,0,1,1,1,1,
|
|
||||||
};
|
|
||||||
int[] zOffsetSet = new int[]{
|
|
||||||
0,0,1,1,0,0,1,1,
|
|
||||||
};
|
|
||||||
if(cursorPos != null){
|
|
||||||
Vector3i chunkPos = Globals.clientWorldData.convertRealToChunkSpace(cursorPos);
|
|
||||||
Vector3i voxelPos = Globals.clientWorldData.convertRealToVoxelSpace(cursorPos);
|
|
||||||
for(int i = 0; i < 8; i++){
|
|
||||||
Vector3i actualPos = new Vector3i(
|
|
||||||
voxelPos.x + xOffsetSet[i],
|
|
||||||
voxelPos.y + yOffsetSet[i],
|
|
||||||
voxelPos.z + zOffsetSet[i]
|
|
||||||
);
|
|
||||||
if(
|
|
||||||
actualPos.x < ChunkData.CHUNK_SIZE &&
|
|
||||||
actualPos.y < ChunkData.CHUNK_SIZE &&
|
|
||||||
actualPos.z < ChunkData.CHUNK_SIZE
|
|
||||||
){
|
|
||||||
Globals.clientTerrainManager.updateChunk(
|
|
||||||
chunkPos.x, chunkPos.y, chunkPos.z,
|
|
||||||
actualPos.x, actualPos.y, actualPos.z,
|
|
||||||
1.0f, 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Globals.clientTerrainManager.getChunkDataAtWorldPoint(chunkPos.x, chunkPos.y, chunkPos.z)
|
|
||||||
// .updatePosition(voxelPos.x, voxelPos.y, voxelPos.z, 1.0f, 1);
|
|
||||||
// Globals.clientTerrainManager.updateChunk(
|
|
||||||
// chunkPos.x, chunkPos.y, chunkPos.z,
|
|
||||||
// voxelPos.x, voxelPos.y, voxelPos.z,
|
|
||||||
// 1.0f, 1
|
|
||||||
// );
|
|
||||||
// System.out.println("Terrain");
|
|
||||||
// System.out.println(Globals.clientWorldData.convertRealToChunkSpace(cursorPos));
|
|
||||||
// System.out.println(Globals.clientWorldData.convertRealToVoxelSpace(cursorPos));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
controls.get(INPUT_CODE_PLACE_TERRAIN).setRepeatTimeout(0.5f * Main.targetFrameRate);
|
controls.get(INPUT_CODE_PLACE_TERRAIN).setOnRepeat(new ControlMethod(){public void execute(){
|
||||||
|
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
|
||||||
|
Entity camera = Globals.playerCamera;
|
||||||
|
if(
|
||||||
|
collisionEngine != null &&
|
||||||
|
camera != null
|
||||||
|
){
|
||||||
|
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera));
|
||||||
|
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
|
||||||
|
Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0);
|
||||||
|
TerrainEditing.editTerrain(cursorPos, 1.1f, 1, 0.01f);
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
controls.get(INPUT_CODE_PLACE_TERRAIN).setRepeatTimeout(0.2f * Main.targetFrameRate);
|
||||||
|
|
||||||
|
mainGameControlList.add(controls.get(INPUT_CODE_REMOVE_TERRAIN));
|
||||||
|
controls.get(INPUT_CODE_REMOVE_TERRAIN).setOnPress(new ControlMethod(){public void execute(){
|
||||||
|
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
|
||||||
|
Entity camera = Globals.playerCamera;
|
||||||
|
if(
|
||||||
|
collisionEngine != null &&
|
||||||
|
camera != null
|
||||||
|
){
|
||||||
|
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera));
|
||||||
|
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
|
||||||
|
Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0);
|
||||||
|
TerrainEditing.editTerrain(cursorPos, 1.1f, 1, -0.01f);
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
controls.get(INPUT_CODE_REMOVE_TERRAIN).setOnRepeat(new ControlMethod(){public void execute(){
|
||||||
|
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
|
||||||
|
Entity camera = Globals.playerCamera;
|
||||||
|
if(
|
||||||
|
collisionEngine != null &&
|
||||||
|
camera != null
|
||||||
|
){
|
||||||
|
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera));
|
||||||
|
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
|
||||||
|
Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0);
|
||||||
|
TerrainEditing.editTerrain(cursorPos, 1.1f, 1, -0.01f);
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
controls.get(INPUT_CODE_REMOVE_TERRAIN).setRepeatTimeout(0.2f * Main.targetFrameRate);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import electrosphere.client.sim.ClientSimulation;
|
|||||||
import electrosphere.client.terrain.cells.DrawCellManager;
|
import electrosphere.client.terrain.cells.DrawCellManager;
|
||||||
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
||||||
import electrosphere.collision.CollisionEngine;
|
import electrosphere.collision.CollisionEngine;
|
||||||
|
import electrosphere.collision.CollisionMasks;
|
||||||
import electrosphere.collision.CollisionWorldData;
|
import electrosphere.collision.CollisionWorldData;
|
||||||
import electrosphere.controls.CameraHandler;
|
import electrosphere.controls.CameraHandler;
|
||||||
import electrosphere.controls.ControlCallback;
|
import electrosphere.controls.ControlCallback;
|
||||||
@ -396,6 +397,8 @@ public class Globals {
|
|||||||
if(Globals.userSettings.getNetRunNetMonitor()){
|
if(Globals.userSettings.getNetRunNetMonitor()){
|
||||||
netMonitor = new NetMonitor();
|
netMonitor = new NetMonitor();
|
||||||
}
|
}
|
||||||
|
//init collision masks
|
||||||
|
CollisionMasks.initMasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initDefaultAudioResources(){
|
public static void initDefaultAudioResources(){
|
||||||
|
|||||||
@ -225,6 +225,8 @@ public class ClientLoading {
|
|||||||
Vector3d cursorPos = collisionEngine.rayCastPosition(centerPos, new Vector3d(eyePos).mul(-1.0), 5.0);
|
Vector3d cursorPos = collisionEngine.rayCastPosition(centerPos, new Vector3d(eyePos).mul(-1.0), 5.0);
|
||||||
if(cursorPos != null){
|
if(cursorPos != null){
|
||||||
EntityUtils.getPosition(cursorTracker).set(cursorPos);
|
EntityUtils.getPosition(cursorTracker).set(cursorPos);
|
||||||
|
} else {
|
||||||
|
EntityUtils.getPosition(cursorTracker).set(new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-5.0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import electrosphere.logger.LoggerInterface;
|
|||||||
import electrosphere.menu.MenuGenerators;
|
import electrosphere.menu.MenuGenerators;
|
||||||
import electrosphere.menu.WindowStrings;
|
import electrosphere.menu.WindowStrings;
|
||||||
import electrosphere.menu.WindowUtils;
|
import electrosphere.menu.WindowUtils;
|
||||||
|
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||||
import electrosphere.renderer.ui.Window;
|
import electrosphere.renderer.ui.Window;
|
||||||
import electrosphere.server.saves.SaveUtils;
|
import electrosphere.server.saves.SaveUtils;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
||||||
@ -53,14 +54,20 @@ public class DebugSPWorldLoading {
|
|||||||
|
|
||||||
|
|
||||||
LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT);
|
LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT);
|
||||||
//init the data of the world
|
|
||||||
// LoadingUtils.initTerrainDataCellManager();
|
|
||||||
//init authentication
|
//init authentication
|
||||||
LoadingUtils.initAuthenticationManager();
|
LoadingUtils.initAuthenticationManager();
|
||||||
//initialize the local connection
|
//initialize the local connection
|
||||||
Globals.clientUsername = "testuser";
|
Globals.clientUsername = "testuser";
|
||||||
Globals.clientPassword = AuthenticationManager.getHashedString("testpass");
|
Globals.clientPassword = AuthenticationManager.getHashedString("testpass");
|
||||||
LoadingUtils.initLocalConnection();
|
LoadingUtils.initLocalConnection();
|
||||||
|
//wait for player object creation
|
||||||
|
while(Globals.playerManager.getPlayers().size() < 1){
|
||||||
|
try {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(10);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
//initialize the "real" objects simulation
|
//initialize the "real" objects simulation
|
||||||
LoadingUtils.initMicroSimulation();
|
LoadingUtils.initMicroSimulation();
|
||||||
//init game specific stuff (ie different skybox colors)
|
//init game specific stuff (ie different skybox colors)
|
||||||
@ -77,29 +84,14 @@ public class DebugSPWorldLoading {
|
|||||||
} catch (InterruptedException ex) {}
|
} catch (InterruptedException ex) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//spawn player character
|
||||||
LoadingUtils.spawnLocalPlayerTestEntity();
|
LoadingUtils.spawnLocalPlayerTestEntity();
|
||||||
|
|
||||||
initWorldBaseGraphicalEntities();
|
//request terrain data
|
||||||
|
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
|
||||||
|
|
||||||
// SeekTown.attachToCreature(Globals.playerEntity);
|
//Run client startup process
|
||||||
|
ClientLoading.loadClientWorld();
|
||||||
//hide cursor
|
|
||||||
Globals.controlHandler.hideMouse();
|
|
||||||
//make loading window disappear
|
|
||||||
loadingWindow.setVisible(false);
|
|
||||||
//recapture screen
|
|
||||||
Globals.controlHandler.setShouldRecapture(true);
|
|
||||||
//set rendering flags to main game mode
|
|
||||||
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
|
|
||||||
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = true;
|
|
||||||
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = true;
|
|
||||||
Globals.RENDER_FLAG_RENDER_UI = true;
|
|
||||||
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
|
|
||||||
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
|
||||||
LoggerInterface.loggerEngine.INFO("[Client]Finished loading main game");
|
|
||||||
//set controls state
|
|
||||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.MAIN_GAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -239,6 +239,7 @@ public class LoadingUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
||||||
|
//create player
|
||||||
//spawn entity
|
//spawn entity
|
||||||
Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,Globals.spawnPoint,template.getCreatureType(),template);
|
Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,Globals.spawnPoint,template.getCreatureType(),template);
|
||||||
Globals.playerEntity = newPlayerEntity;
|
Globals.playerEntity = newPlayerEntity;
|
||||||
|
|||||||
@ -142,32 +142,32 @@ public class ClientCollidableTree implements BehaviorTree {
|
|||||||
// System.out.println(cumulativeTorque);
|
// System.out.println(cumulativeTorque);
|
||||||
// }
|
// }
|
||||||
//friction
|
//friction
|
||||||
if(angularVelocity.lengthSquared() > 0.001){
|
// if(angularVelocity.lengthSquared() > 0.001){
|
||||||
angularVelocity.slerp(new Quaterniond(0,0,0,1), 0.03);
|
// angularVelocity.slerp(new Quaterniond(0,0,0,1), 0.03);
|
||||||
// angularVelocity.scale((float)(Math.sqrt(angularVelocity.lengthSquared()) * 0.9));
|
// // angularVelocity.scale((float)(Math.sqrt(angularVelocity.lengthSquared()) * 0.9));
|
||||||
// System.out.println(angularVelocity);
|
// // System.out.println(angularVelocity);
|
||||||
}
|
|
||||||
// if(cumulativeTorque.w > 0.001){
|
|
||||||
// Vector4f holder = inverseInertiaTensor.transform(new Vector4f((float)cumulativeTorque.x,(float)cumulativeTorque.y,(float)cumulativeTorque.z,(float)cumulativeTorque.w));
|
|
||||||
// cumulativeTorque = new Vector4d(holder.x,holder.y,holder.z,holder.w);
|
|
||||||
// angularVelocity = angularVelocity.add(cumulativeTorque).normalize();
|
|
||||||
// cumulativeTorque.set(0,0,0,0);
|
|
||||||
// // Vector3d normalizedTorqueDir = new Vector3d(cumulativeTorque.x,cumulativeTorque.y,cumulativeTorque.z).normalize();
|
|
||||||
// // double newMag = cumulativeTorque.w * 0.9;
|
|
||||||
// // cumulativeTorque.set(normalizedTorqueDir.x,normalizedTorqueDir.y,normalizedTorqueDir.z,newMag);
|
|
||||||
// }
|
// }
|
||||||
if(angularVelocity.lengthSquared() > 0.001){
|
// // if(cumulativeTorque.w > 0.001){
|
||||||
// System.out.println("-" + rotation);
|
// // Vector4f holder = inverseInertiaTensor.transform(new Vector4f((float)cumulativeTorque.x,(float)cumulativeTorque.y,(float)cumulativeTorque.z,(float)cumulativeTorque.w));
|
||||||
Quaterniond newRotation = new Quaterniond(rotation).mul(angularVelocity).normalize();
|
// // cumulativeTorque = new Vector4d(holder.x,holder.y,holder.z,holder.w);
|
||||||
// if(new Quaternionf(newRotation).add(new Quaternionf(rotation).conjugate()).lengthSquared() > 0.2){
|
// // angularVelocity = angularVelocity.add(cumulativeTorque).normalize();
|
||||||
// newRotation.w = Math.copySign(newRotation.w, rotation.w);
|
// // cumulativeTorque.set(0,0,0,0);
|
||||||
// newRotation.x = Math.copySign(newRotation.x, rotation.x);
|
// // // Vector3d normalizedTorqueDir = new Vector3d(cumulativeTorque.x,cumulativeTorque.y,cumulativeTorque.z).normalize();
|
||||||
// newRotation.y = Math.copySign(newRotation.y, rotation.y);
|
// // // double newMag = cumulativeTorque.w * 0.9;
|
||||||
// newRotation.z = Math.copySign(newRotation.z, rotation.z);
|
// // // cumulativeTorque.set(normalizedTorqueDir.x,normalizedTorqueDir.y,normalizedTorqueDir.z,newMag);
|
||||||
|
// // }
|
||||||
|
// if(angularVelocity.lengthSquared() > 0.001){
|
||||||
|
// // System.out.println("-" + rotation);
|
||||||
|
// Quaterniond newRotation = new Quaterniond(rotation).mul(angularVelocity).normalize();
|
||||||
|
// // if(new Quaternionf(newRotation).add(new Quaternionf(rotation).conjugate()).lengthSquared() > 0.2){
|
||||||
|
// // newRotation.w = Math.copySign(newRotation.w, rotation.w);
|
||||||
|
// // newRotation.x = Math.copySign(newRotation.x, rotation.x);
|
||||||
|
// // newRotation.y = Math.copySign(newRotation.y, rotation.y);
|
||||||
|
// // newRotation.z = Math.copySign(newRotation.z, rotation.z);
|
||||||
|
// // }
|
||||||
|
// rotation.set(newRotation);
|
||||||
|
// // System.out.println("=" + rotation);
|
||||||
// }
|
// }
|
||||||
rotation.set(newRotation);
|
|
||||||
// System.out.println("=" + rotation);
|
|
||||||
}
|
|
||||||
// if(inverseInertiaTensor != null && angularVelocity.w > 0.01){
|
// if(inverseInertiaTensor != null && angularVelocity.w > 0.01){
|
||||||
// // Vector4f angularMomentum = inverseInertiaTensor.transform(new Vector4f((float)cumulativeTorque.x,(float)cumulativeTorque.x,(float)cumulativeTorque.x,(float)cumulativeTorque.w));
|
// // Vector4f angularMomentum = inverseInertiaTensor.transform(new Vector4f((float)cumulativeTorque.x,(float)cumulativeTorque.x,(float)cumulativeTorque.x,(float)cumulativeTorque.w));
|
||||||
// // Quaternionf nextRotation = new Quaternionf(rotation).mul(new Quaternionf(angularMomentum.x,angularMomentum.y,angularMomentum.z,angularMomentum.w).scale(0.001f)).normalize();
|
// // Quaternionf nextRotation = new Quaternionf(rotation).mul(new Quaternionf(angularMomentum.x,angularMomentum.y,angularMomentum.z,angularMomentum.w).scale(0.001f)).normalize();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package electrosphere.entity.state.gravity;
|
package electrosphere.entity.state.gravity;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ import org.joml.Vector3d;
|
|||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
import org.ode4j.ode.DBody;
|
import org.ode4j.ode.DBody;
|
||||||
|
|
||||||
|
import electrosphere.collision.CollisionMasks;
|
||||||
import electrosphere.collision.collidable.Collidable;
|
import electrosphere.collision.collidable.Collidable;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
@ -161,18 +163,24 @@ public class ClientGravityTree implements BehaviorTree {
|
|||||||
gravityVelocity = gravityConstant;
|
gravityVelocity = gravityConstant;
|
||||||
}
|
}
|
||||||
float gravityDif = gravityVelocity * (float)Math.pow(1.0f - linearDamping,deltaTime * 2);
|
float gravityDif = gravityVelocity * (float)Math.pow(1.0f - linearDamping,deltaTime * 2);
|
||||||
Vector3d newGravityPos = new Vector3d(position.x,position.y - gravityDif,position.z);
|
// Vector3d newGravityPos = new Vector3d(position.x,position.y - gravityDif,position.z);
|
||||||
float hitFraction = Globals.clientSceneWrapper.getCollisionEngine().sweepTest(body, new Vector3f((float)position.x,(float)position.y,(float)position.z), new Vector3f((float)newGravityPos.x,(float)newGravityPos.y,(float)newGravityPos.z));
|
// Entity terrainHit = Globals.clientSceneWrapper.getCollisionEngine().rayCast(
|
||||||
|
// position,
|
||||||
|
// new Vector3d(0,-1,0),
|
||||||
|
// gravityDif,
|
||||||
|
// CollisionMasks.terrainMask
|
||||||
|
// );
|
||||||
|
// float hitFraction = Globals.clientSceneWrapper.getCollisionEngine().sweepTest(body, new Vector3f((float)position.x,(float)position.y,(float)position.z), new Vector3f((float)newGravityPos.x,(float)newGravityPos.y,(float)newGravityPos.z));
|
||||||
// if(hitFraction >= 0){
|
// if(hitFraction >= 0){
|
||||||
// collidable.addImpulse(new Impulse(new Vector3d(0,-1,0),gravityDif * hitFraction,"gravity"));
|
// collidable.addImpulse(new Impulse(new Vector3d(0,-1,0),gravityDif * hitFraction,"gravity"));
|
||||||
// position.set(new Vector3d(position.x,position.y - gravityDif * hitFraction,position.z));
|
// position.set(new Vector3d(position.x,position.y - gravityDif * hitFraction,position.z));
|
||||||
// } else {
|
// } else {
|
||||||
// position.set(new Vector3d(position.x,position.y - gravityDif,position.z));
|
// position.set(new Vector3d(position.x,position.y - gravityDif,position.z));
|
||||||
// }
|
// }
|
||||||
if(hitFraction < 0){
|
// if(hitFraction < 0){
|
||||||
hitFraction = 1;
|
// hitFraction = 1;
|
||||||
}
|
// }
|
||||||
collidable.addImpulse(new Impulse(new Vector3d(0,-1,0), new Vector3d(0,0,0), new Vector3d(position), gravityDif * hitFraction,"gravity"));
|
collidable.addImpulse(new Impulse(new Vector3d(0,-1,0), new Vector3d(0,0,0), new Vector3d(position), gravityDif,"gravity"));
|
||||||
// System.out.println(hitFraction);
|
// System.out.println(hitFraction);
|
||||||
// bodyTransformMatrix = new javax.vecmath.Matrix4f(PhysicsUtils.jomlToVecmathQuaternionf(rotation),PhysicsUtils.jomlToVecmathVector3f(new Vector3f((float)position.x,(float)position.y,(float)position.z)),1.0f);
|
// bodyTransformMatrix = new javax.vecmath.Matrix4f(PhysicsUtils.jomlToVecmathQuaternionf(rotation),PhysicsUtils.jomlToVecmathVector3f(new Vector3f((float)position.x,(float)position.y,(float)position.z)),1.0f);
|
||||||
// body.setWorldTransform(new electrosphere.linearmath.Transform(bodyTransformMatrix));
|
// body.setWorldTransform(new electrosphere.linearmath.Transform(bodyTransformMatrix));
|
||||||
|
|||||||
@ -162,19 +162,19 @@ public class ServerGravityTree implements BehaviorTree {
|
|||||||
gravityVelocity = gravityConstant;
|
gravityVelocity = gravityConstant;
|
||||||
}
|
}
|
||||||
float gravityDif = gravityVelocity * (float)Math.pow(1.0f - linearDamping,deltaTime * 2);
|
float gravityDif = gravityVelocity * (float)Math.pow(1.0f - linearDamping,deltaTime * 2);
|
||||||
Vector3d newGravityPos = new Vector3d(position.x,position.y - gravityDif,position.z);
|
// Vector3d newGravityPos = new Vector3d(position.x,position.y - gravityDif,position.z);
|
||||||
Realm parentRealm = Globals.realmManager.getEntityRealm(parent);
|
// Realm parentRealm = Globals.realmManager.getEntityRealm(parent);
|
||||||
float hitFraction = parentRealm.getCollisionEngine().sweepTest(body, new Vector3f((float)position.x,(float)position.y,(float)position.z), new Vector3f((float)newGravityPos.x,(float)newGravityPos.y,(float)newGravityPos.z));
|
// float hitFraction = parentRealm.getCollisionEngine().sweepTest(body, new Vector3f((float)position.x,(float)position.y,(float)position.z), new Vector3f((float)newGravityPos.x,(float)newGravityPos.y,(float)newGravityPos.z));
|
||||||
// if(hitFraction >= 0){
|
// if(hitFraction >= 0){
|
||||||
// collidable.addImpulse(new Impulse(new Vector3d(0,-1,0),gravityDif * hitFraction,"gravity"));
|
// collidable.addImpulse(new Impulse(new Vector3d(0,-1,0),gravityDif * hitFraction,"gravity"));
|
||||||
// position.set(new Vector3d(position.x,position.y - gravityDif * hitFraction,position.z));
|
// position.set(new Vector3d(position.x,position.y - gravityDif * hitFraction,position.z));
|
||||||
// } else {
|
// } else {
|
||||||
// position.set(new Vector3d(position.x,position.y - gravityDif,position.z));
|
// position.set(new Vector3d(position.x,position.y - gravityDif,position.z));
|
||||||
// }
|
// }
|
||||||
if(hitFraction < 0){
|
// if(hitFraction < 0){
|
||||||
hitFraction = 1;
|
// hitFraction = 1;
|
||||||
}
|
// }
|
||||||
collidable.addImpulse(new Impulse(new Vector3d(0,-1,0), new Vector3d(0,0,0), new Vector3d(position), gravityDif * hitFraction,"gravity"));
|
collidable.addImpulse(new Impulse(new Vector3d(0,-1,0), new Vector3d(0,0,0), new Vector3d(position), gravityDif,"gravity"));
|
||||||
// System.out.println(hitFraction);
|
// System.out.println(hitFraction);
|
||||||
// bodyTransformMatrix = new javax.vecmath.Matrix4f(PhysicsUtils.jomlToVecmathQuaternionf(rotation),PhysicsUtils.jomlToVecmathVector3f(new Vector3f((float)position.x,(float)position.y,(float)position.z)),1.0f);
|
// bodyTransformMatrix = new javax.vecmath.Matrix4f(PhysicsUtils.jomlToVecmathQuaternionf(rotation),PhysicsUtils.jomlToVecmathVector3f(new Vector3f((float)position.x,(float)position.y,(float)position.z)),1.0f);
|
||||||
// body.setWorldTransform(new electrosphere.linearmath.Transform(bodyTransformMatrix));
|
// body.setWorldTransform(new electrosphere.linearmath.Transform(bodyTransformMatrix));
|
||||||
|
|||||||
@ -21,16 +21,17 @@ public class TerrainChunk {
|
|||||||
* Creates a client terrain chunk based on weights and values provided
|
* Creates a client terrain chunk based on weights and values provided
|
||||||
* @param weights The terrain weights
|
* @param weights The terrain weights
|
||||||
* @param values The values (block types)
|
* @param values The values (block types)
|
||||||
|
* @param levelOfDetail Increasing value that increments level of detail. 0 would be full resolution, 1 would be half resolution and so on. Only generates physics if levelOfDetail is 0
|
||||||
* @return The terrain chunk entity
|
* @return The terrain chunk entity
|
||||||
*/
|
*/
|
||||||
public static Entity clientCreateTerrainChunkEntity(float[][][] weights, int[][][] values){
|
public static Entity clientCreateTerrainChunkEntity(float[][][] weights, int[][][] values, int levelOfDetail){
|
||||||
|
|
||||||
TerrainChunkData data = TerrainChunkModelGeneration.generateTerrainChunkData(weights, values);
|
TerrainChunkData data = TerrainChunkModelGeneration.generateTerrainChunkData(weights, values);
|
||||||
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data);
|
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data);
|
||||||
|
|
||||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||||
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
|
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
|
||||||
if(data.vertices.size() > 0){
|
if(data.vertices.size() > 0 && levelOfDetail < 1){
|
||||||
PhysicsUtils.clientAttachTerrainChunkRigidBody(rVal, data);
|
PhysicsUtils.clientAttachTerrainChunkRigidBody(rVal, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,10 @@ import electrosphere.server.datacell.ServerDataCell;
|
|||||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
import org.joml.Vector3i;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -112,6 +115,30 @@ public class ServerWorldData {
|
|||||||
return isArena;
|
return isArena;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a real coordinate to a world space coordinate
|
||||||
|
* @param position The real coordinate
|
||||||
|
* @return The world space coordinate
|
||||||
|
*/
|
||||||
|
public Vector3i convertRealToWorldSpace(Vector3d position){
|
||||||
|
return new Vector3i(
|
||||||
|
convertRealToChunkSpace(position.x),
|
||||||
|
convertRealToChunkSpace(position.y),
|
||||||
|
convertRealToChunkSpace(position.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a real coordinate to a voxel space coordinate, relative to the containing chunk of the real coordinate
|
||||||
|
* @param position The real coordinate
|
||||||
|
* @return The voxel space coordinate
|
||||||
|
*/
|
||||||
|
public Vector3i convertRealToVoxelSpace(Vector3d position){
|
||||||
|
return new Vector3i(
|
||||||
|
(int)Math.floor(position.x - convertChunkToRealSpace(convertRealToChunkSpace(position.x))),
|
||||||
|
(int)Math.floor(position.y - convertChunkToRealSpace(convertRealToChunkSpace(position.y))),
|
||||||
|
(int)Math.floor(position.z - convertChunkToRealSpace(convertRealToChunkSpace(position.z)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,21 @@ public class TerrainProtocol {
|
|||||||
case SENDCHUNKDATA:
|
case SENDCHUNKDATA:
|
||||||
Globals.clientTerrainManager.attachTerrainMessage(message);
|
Globals.clientTerrainManager.attachTerrainMessage(message);
|
||||||
break;
|
break;
|
||||||
|
case UPDATEVOXEL: {
|
||||||
|
if(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(message.getworldX(), message.getworldY(), message.getworldZ())){
|
||||||
|
ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(message.getworldX(), message.getworldY(), message.getworldZ());
|
||||||
|
if(data != null){
|
||||||
|
data.updatePosition(
|
||||||
|
message.getvoxelX(),
|
||||||
|
message.getvoxelY(),
|
||||||
|
message.getvoxelZ(),
|
||||||
|
message.getterrainWeight(),
|
||||||
|
message.getterrainValue()
|
||||||
|
);
|
||||||
|
Globals.drawCellManager.markUpdateable(message.getworldX(), message.getworldY(), message.getworldZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
LoggerInterface.loggerNetworking.WARNING("Client networking: Unhandled message of type: " + message.getMessageSubtype());
|
LoggerInterface.loggerNetworking.WARNING("Client networking: Unhandled message of type: " + message.getMessageSubtype());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -200,9 +200,19 @@ INVENTORY_MESSAGE,
|
|||||||
rVal = TerrainMessage.parseRequestChunkMessage(byteBuffer);
|
rVal = TerrainMessage.parseRequestChunkMessage(byteBuffer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATE:
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTEDITVOXEL:
|
||||||
if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
|
if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
|
||||||
rVal = TerrainMessage.parseUpdateMessage(byteBuffer);
|
rVal = TerrainMessage.parseRequestEditVoxelMessage(byteBuffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEVOXEL:
|
||||||
|
if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
|
||||||
|
rVal = TerrainMessage.parseUpdateVoxelMessage(byteBuffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTUSETERRAINPALETTE:
|
||||||
|
if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
|
||||||
|
rVal = TerrainMessage.parseRequestUseTerrainPaletteMessage(byteBuffer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TypeBytes.TERRAIN_MESSAGE_TYPE_SPAWNPOSITION:
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_SPAWNPOSITION:
|
||||||
|
|||||||
@ -11,7 +11,9 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
REQUESTMETADATA,
|
REQUESTMETADATA,
|
||||||
RESPONSEMETADATA,
|
RESPONSEMETADATA,
|
||||||
REQUESTCHUNK,
|
REQUESTCHUNK,
|
||||||
UPDATE,
|
REQUESTEDITVOXEL,
|
||||||
|
UPDATEVOXEL,
|
||||||
|
REQUESTUSETERRAINPALETTE,
|
||||||
SPAWNPOSITION,
|
SPAWNPOSITION,
|
||||||
REQUESTCHUNKDATA,
|
REQUESTCHUNKDATA,
|
||||||
SENDCHUNKDATA,
|
SENDCHUNKDATA,
|
||||||
@ -29,6 +31,9 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
int worldX;
|
int worldX;
|
||||||
int worldY;
|
int worldY;
|
||||||
int worldZ;
|
int worldZ;
|
||||||
|
int voxelX;
|
||||||
|
int voxelY;
|
||||||
|
int voxelZ;
|
||||||
double realLocationX;
|
double realLocationX;
|
||||||
double realLocationY;
|
double realLocationY;
|
||||||
double realLocationZ;
|
double realLocationZ;
|
||||||
@ -133,6 +138,30 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
this.worldZ = worldZ;
|
this.worldZ = worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getvoxelX() {
|
||||||
|
return voxelX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setvoxelX(int voxelX) {
|
||||||
|
this.voxelX = voxelX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getvoxelY() {
|
||||||
|
return voxelY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setvoxelY(int voxelY) {
|
||||||
|
this.voxelY = voxelY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getvoxelZ() {
|
||||||
|
return voxelZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setvoxelZ(int voxelZ) {
|
||||||
|
this.voxelZ = voxelZ;
|
||||||
|
}
|
||||||
|
|
||||||
public double getrealLocationX() {
|
public double getrealLocationX() {
|
||||||
return realLocationX;
|
return realLocationX;
|
||||||
}
|
}
|
||||||
@ -205,8 +234,20 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATE:
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTEDITVOXEL:
|
||||||
if(byteBuffer.getRemaining() >= TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATE_SIZE){
|
if(byteBuffer.getRemaining() >= TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTEDITVOXEL_SIZE){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEVOXEL:
|
||||||
|
if(byteBuffer.getRemaining() >= TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEVOXEL_SIZE){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTUSETERRAINPALETTE:
|
||||||
|
if(byteBuffer.getRemaining() >= TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTUSETERRAINPALETTE_SIZE){
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -283,20 +324,82 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TerrainMessage parseUpdateMessage(CircularByteBuffer byteBuffer){
|
public static TerrainMessage parseRequestEditVoxelMessage(CircularByteBuffer byteBuffer){
|
||||||
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.UPDATE);
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.REQUESTEDITVOXEL);
|
||||||
stripPacketHeader(byteBuffer);
|
stripPacketHeader(byteBuffer);
|
||||||
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
rVal.setworldY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
rVal.setworldY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
rVal.setworldZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
rVal.setworldZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setvoxelX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setvoxelY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setvoxelZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setterrainWeight(ByteStreamUtils.popFloatFromByteQueue(byteBuffer));
|
||||||
|
rVal.setterrainValue(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TerrainMessage constructUpdateMessage(int worldX,int worldY,int worldZ){
|
public static TerrainMessage constructRequestEditVoxelMessage(int worldX,int worldY,int worldZ,int voxelX,int voxelY,int voxelZ,float terrainWeight,int terrainValue){
|
||||||
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.UPDATE);
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.REQUESTEDITVOXEL);
|
||||||
rVal.setworldX(worldX);
|
rVal.setworldX(worldX);
|
||||||
rVal.setworldY(worldY);
|
rVal.setworldY(worldY);
|
||||||
rVal.setworldZ(worldZ);
|
rVal.setworldZ(worldZ);
|
||||||
|
rVal.setvoxelX(voxelX);
|
||||||
|
rVal.setvoxelY(voxelY);
|
||||||
|
rVal.setvoxelZ(voxelZ);
|
||||||
|
rVal.setterrainWeight(terrainWeight);
|
||||||
|
rVal.setterrainValue(terrainValue);
|
||||||
|
rVal.serialize();
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TerrainMessage parseUpdateVoxelMessage(CircularByteBuffer byteBuffer){
|
||||||
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.UPDATEVOXEL);
|
||||||
|
stripPacketHeader(byteBuffer);
|
||||||
|
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setworldY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setworldZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setvoxelX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setvoxelY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setvoxelZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setterrainWeight(ByteStreamUtils.popFloatFromByteQueue(byteBuffer));
|
||||||
|
rVal.setterrainValue(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TerrainMessage constructUpdateVoxelMessage(int worldX,int worldY,int worldZ,int voxelX,int voxelY,int voxelZ,float terrainWeight,int terrainValue){
|
||||||
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.UPDATEVOXEL);
|
||||||
|
rVal.setworldX(worldX);
|
||||||
|
rVal.setworldY(worldY);
|
||||||
|
rVal.setworldZ(worldZ);
|
||||||
|
rVal.setvoxelX(voxelX);
|
||||||
|
rVal.setvoxelY(voxelY);
|
||||||
|
rVal.setvoxelZ(voxelZ);
|
||||||
|
rVal.setterrainWeight(terrainWeight);
|
||||||
|
rVal.setterrainValue(terrainValue);
|
||||||
|
rVal.serialize();
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TerrainMessage parseRequestUseTerrainPaletteMessage(CircularByteBuffer byteBuffer){
|
||||||
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.REQUESTUSETERRAINPALETTE);
|
||||||
|
stripPacketHeader(byteBuffer);
|
||||||
|
rVal.setrealLocationX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
|
||||||
|
rVal.setrealLocationY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
|
||||||
|
rVal.setrealLocationZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
|
||||||
|
rVal.setvalue(ByteStreamUtils.popFloatFromByteQueue(byteBuffer));
|
||||||
|
rVal.setterrainWeight(ByteStreamUtils.popFloatFromByteQueue(byteBuffer));
|
||||||
|
rVal.setterrainValue(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TerrainMessage constructRequestUseTerrainPaletteMessage(double realLocationX,double realLocationY,double realLocationZ,float value,float terrainWeight,int terrainValue){
|
||||||
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.REQUESTUSETERRAINPALETTE);
|
||||||
|
rVal.setrealLocationX(realLocationX);
|
||||||
|
rVal.setrealLocationY(realLocationY);
|
||||||
|
rVal.setrealLocationZ(realLocationZ);
|
||||||
|
rVal.setvalue(value);
|
||||||
|
rVal.setterrainWeight(terrainWeight);
|
||||||
|
rVal.setterrainValue(terrainValue);
|
||||||
rVal.serialize();
|
rVal.serialize();
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
@ -446,12 +549,12 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
rawBytes[6+i] = intValues[i];
|
rawBytes[6+i] = intValues[i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UPDATE:
|
case REQUESTEDITVOXEL:
|
||||||
rawBytes = new byte[2+4+4+4];
|
rawBytes = new byte[2+4+4+4+4+4+4+4+4];
|
||||||
//message header
|
//message header
|
||||||
rawBytes[0] = TypeBytes.MESSAGE_TYPE_TERRAIN;
|
rawBytes[0] = TypeBytes.MESSAGE_TYPE_TERRAIN;
|
||||||
//entity messaage header
|
//entity messaage header
|
||||||
rawBytes[1] = TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATE;
|
rawBytes[1] = TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTEDITVOXEL;
|
||||||
intValues = ByteStreamUtils.serializeIntToBytes(worldX);
|
intValues = ByteStreamUtils.serializeIntToBytes(worldX);
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[2+i] = intValues[i];
|
rawBytes[2+i] = intValues[i];
|
||||||
@ -464,6 +567,92 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
rawBytes[10+i] = intValues[i];
|
rawBytes[10+i] = intValues[i];
|
||||||
}
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(voxelX);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[14+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(voxelY);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[18+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(voxelZ);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[22+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeFloatToBytes(terrainWeight);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[26+i] = intValues[i];
|
||||||
|
} intValues = ByteStreamUtils.serializeIntToBytes(terrainValue);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[30+i] = intValues[i];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UPDATEVOXEL:
|
||||||
|
rawBytes = new byte[2+4+4+4+4+4+4+4+4];
|
||||||
|
//message header
|
||||||
|
rawBytes[0] = TypeBytes.MESSAGE_TYPE_TERRAIN;
|
||||||
|
//entity messaage header
|
||||||
|
rawBytes[1] = TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEVOXEL;
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(worldX);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[2+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(worldY);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[6+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(worldZ);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[10+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(voxelX);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[14+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(voxelY);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[18+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(voxelZ);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[22+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeFloatToBytes(terrainWeight);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[26+i] = intValues[i];
|
||||||
|
} intValues = ByteStreamUtils.serializeIntToBytes(terrainValue);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[30+i] = intValues[i];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REQUESTUSETERRAINPALETTE:
|
||||||
|
rawBytes = new byte[2+8+8+8+4+4+4];
|
||||||
|
//message header
|
||||||
|
rawBytes[0] = TypeBytes.MESSAGE_TYPE_TERRAIN;
|
||||||
|
//entity messaage header
|
||||||
|
rawBytes[1] = TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTUSETERRAINPALETTE;
|
||||||
|
intValues = ByteStreamUtils.serializeDoubleToBytes(realLocationX);
|
||||||
|
for(int i = 0; i < 8; i++){
|
||||||
|
rawBytes[2+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeDoubleToBytes(realLocationY);
|
||||||
|
for(int i = 0; i < 8; i++){
|
||||||
|
rawBytes[10+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeDoubleToBytes(realLocationZ);
|
||||||
|
for(int i = 0; i < 8; i++){
|
||||||
|
rawBytes[18+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeFloatToBytes(value);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[26+i] = intValues[i];
|
||||||
|
} intValues = ByteStreamUtils.serializeFloatToBytes(terrainWeight);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[30+i] = intValues[i];
|
||||||
|
} intValues = ByteStreamUtils.serializeIntToBytes(terrainValue);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[34+i] = intValues[i];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPAWNPOSITION:
|
case SPAWNPOSITION:
|
||||||
rawBytes = new byte[2+8+8+8];
|
rawBytes = new byte[2+8+8+8];
|
||||||
|
|||||||
@ -80,17 +80,21 @@ Message categories
|
|||||||
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTMETADATA = 0;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTMETADATA = 0;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA = 1;
|
public static final byte TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA = 1;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNK = 2;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNK = 2;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_UPDATE = 3;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTEDITVOXEL = 3;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION = 4;
|
public static final byte TERRAIN_MESSAGE_TYPE_UPDATEVOXEL = 4;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA = 5;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTUSETERRAINPALETTE = 5;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA = 6;
|
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION = 6;
|
||||||
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA = 7;
|
||||||
|
public static final byte TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA = 8;
|
||||||
/*
|
/*
|
||||||
Terrain packet sizes
|
Terrain packet sizes
|
||||||
*/
|
*/
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTMETADATA_SIZE = 2;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTMETADATA_SIZE = 2;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA_SIZE = 30;
|
public static final byte TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA_SIZE = 30;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNK_SIZE = 10;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNK_SIZE = 10;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_UPDATE_SIZE = 14;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTEDITVOXEL_SIZE = 34;
|
||||||
|
public static final byte TERRAIN_MESSAGE_TYPE_UPDATEVOXEL_SIZE = 34;
|
||||||
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTUSETERRAINPALETTE_SIZE = 38;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION_SIZE = 26;
|
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION_SIZE = 26;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA_SIZE = 14;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA_SIZE = 14;
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -4,11 +4,16 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
import electrosphere.client.terrain.cache.ChunkData;
|
import electrosphere.client.terrain.cache.ChunkData;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||||
import electrosphere.net.server.Server;
|
import electrosphere.net.server.Server;
|
||||||
import electrosphere.net.server.ServerConnectionHandler;
|
import electrosphere.net.server.ServerConnectionHandler;
|
||||||
|
import electrosphere.net.server.player.Player;
|
||||||
|
import electrosphere.server.datacell.Realm;
|
||||||
|
import electrosphere.server.terrain.editing.TerrainEditing;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
import electrosphere.server.terrain.models.TerrainModification;
|
import electrosphere.server.terrain.models.TerrainModification;
|
||||||
|
|
||||||
@ -27,10 +32,16 @@ public class TerrainProtocol {
|
|||||||
message.getworldX(), message.getworldY(), message.getworldZ()
|
message.getworldX(), message.getworldY(), message.getworldZ()
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case REQUESTEDITVOXEL: {
|
||||||
|
attemptTerrainEdit(connectionHandler, message);
|
||||||
|
} break;
|
||||||
|
case REQUESTUSETERRAINPALETTE: {
|
||||||
|
attemptUseTerrainEditPalette(connectionHandler, message);
|
||||||
|
} break;
|
||||||
//all ignored message types
|
//all ignored message types
|
||||||
case RESPONSEMETADATA:
|
case RESPONSEMETADATA:
|
||||||
case SPAWNPOSITION:
|
case SPAWNPOSITION:
|
||||||
case UPDATE:
|
case UPDATEVOXEL:
|
||||||
case SENDCHUNKDATA:
|
case SENDCHUNKDATA:
|
||||||
//silently ignore
|
//silently ignore
|
||||||
break;
|
break;
|
||||||
@ -69,12 +80,19 @@ public class TerrainProtocol {
|
|||||||
|
|
||||||
// long[][] randomizer = chunk.getRandomizer();//Globals.serverTerrainManager.getRandomizer(message.getworldX(), message.getworldY());
|
// long[][] randomizer = chunk.getRandomizer();//Globals.serverTerrainManager.getRandomizer(message.getworldX(), message.getworldY());
|
||||||
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(ServerTerrainChunk.CHUNK_DIMENSION*ServerTerrainChunk.CHUNK_DIMENSION*ServerTerrainChunk.CHUNK_DIMENSION*(4+4));
|
//The length along each access of the chunk data. Typically, should be at least 17.
|
||||||
|
//Because CHUNK_SIZE is 16, 17 adds the necessary extra value. Each chunk needs the value of the immediately following position to generate
|
||||||
|
//chunk data that connects seamlessly to the next chunk.
|
||||||
|
int xWidth = chunk.getWeights().length;
|
||||||
|
int yWidth = chunk.getWeights()[0].length;
|
||||||
|
int zWidth = chunk.getWeights()[0][0].length;
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(xWidth*yWidth*zWidth*(4+4));
|
||||||
FloatBuffer floatView = buffer.asFloatBuffer();
|
FloatBuffer floatView = buffer.asFloatBuffer();
|
||||||
|
|
||||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
for(int x = 0; x < xWidth; x++){
|
||||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
for(int y = 0; y < yWidth; y++){
|
||||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
for(int z = 0; z < zWidth; z++){
|
||||||
floatView.put(chunk.getWeights()[x][y][z]);
|
floatView.put(chunk.getWeights()[x][y][z]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,9 +101,9 @@ public class TerrainProtocol {
|
|||||||
IntBuffer intView = buffer.asIntBuffer();
|
IntBuffer intView = buffer.asIntBuffer();
|
||||||
intView.position(floatView.position());
|
intView.position(floatView.position());
|
||||||
|
|
||||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
for(int x = 0; x < xWidth; x++){
|
||||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
for(int y = 0; y < yWidth; y++){
|
||||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
for(int z = 0; z < zWidth; z++){
|
||||||
intView.put(chunk.getValues()[x][y][z]);
|
intView.put(chunk.getValues()[x][y][z]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,4 +209,24 @@ public class TerrainProtocol {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to perform an edit requested by a client
|
||||||
|
* @param message The message containing the edit request
|
||||||
|
*/
|
||||||
|
static void attemptTerrainEdit(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
||||||
|
Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to use an edit palette on the terrain
|
||||||
|
* @param connectionHandler The connection handler
|
||||||
|
* @param message The message that contains the request to use an edit palette
|
||||||
|
*/
|
||||||
|
static void attemptUseTerrainEditPalette(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
||||||
|
Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
|
||||||
|
Realm realm = Globals.realmManager.getPlayerRealm(player);
|
||||||
|
Vector3d location = new Vector3d(message.getrealLocationX(), message.getrealLocationY(), message.getrealLocationZ());
|
||||||
|
TerrainEditing.editTerrain(realm, location, message.getvalue(), message.getterrainValue(), message.getterrainWeight());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -582,35 +582,6 @@ public class Mesh {
|
|||||||
HomogenousInstancedArray buffer = uniformGlBufferMap.get(attribute);
|
HomogenousInstancedArray buffer = uniformGlBufferMap.get(attribute);
|
||||||
buffer.updateBuffer(buffers.get(attribute), 0);
|
buffer.updateBuffer(buffers.get(attribute), 0);
|
||||||
buffer.bind(renderPipelineState);
|
buffer.bind(renderPipelineState);
|
||||||
// switch(uniformTypeMap.get(uniformName)){
|
|
||||||
// case VEC3F: {
|
|
||||||
// FloatBuffer buffer = (FloatBuffer)buffers.get(key);
|
|
||||||
// int bufferIndex = GL31.glGetUniformBlockIndex(shaderIndex, "Lights");
|
|
||||||
// //bind that position to the slot '2'
|
|
||||||
// GL31.glUniformBlockBinding(shaderIndex, bufferIndex, BIND_POINT);
|
|
||||||
// //bind our buffer to slot '2' as well
|
|
||||||
// GL31.glBindBufferBase(GL_UNIFORM_BUFFER, BIND_POINT, uboIndex);
|
|
||||||
// //alternatively if want to use range, do glBindBufferRange(GL_UNIFORM_BUFFER, 2, uboExampleBlock, 0, 152);
|
|
||||||
// } break;
|
|
||||||
// case VEC3D: {
|
|
||||||
|
|
||||||
// } break;
|
|
||||||
// case VEC4F: {
|
|
||||||
|
|
||||||
// } break;
|
|
||||||
// case VEC4D: {
|
|
||||||
|
|
||||||
// } break;
|
|
||||||
// case DOUBLE: {
|
|
||||||
|
|
||||||
// } break;
|
|
||||||
// case FLOAT: {
|
|
||||||
|
|
||||||
// } break;
|
|
||||||
// case INT: {
|
|
||||||
|
|
||||||
// } break;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.PriorityQueue;
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
import org.joml.Matrix4d;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
@ -93,6 +94,9 @@ public class InstanceData {
|
|||||||
case MAT4F: {
|
case MAT4F: {
|
||||||
attributeCpuBufferMap.put(shaderAttribute, BufferUtils.createFloatBuffer(capacity * 4 * 4));
|
attributeCpuBufferMap.put(shaderAttribute, BufferUtils.createFloatBuffer(capacity * 4 * 4));
|
||||||
} break;
|
} break;
|
||||||
|
case MAT4D: {
|
||||||
|
attributeCpuBufferMap.put(shaderAttribute, BufferUtils.createFloatBuffer(capacity * 4 * 4));
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
if(shaderAttribute.isSingleIndex()){
|
if(shaderAttribute.isSingleIndex()){
|
||||||
attributeGlBufferMap.put(shaderAttribute,HomogenousInstancedArray.createHomogenousInstancedArray(shaderAttribute.getIndex(), type, capacity));
|
attributeGlBufferMap.put(shaderAttribute,HomogenousInstancedArray.createHomogenousInstancedArray(shaderAttribute.getIndex(), type, capacity));
|
||||||
@ -156,6 +160,10 @@ public class InstanceData {
|
|||||||
buffer.limit(buffer.capacity());
|
buffer.limit(buffer.capacity());
|
||||||
// System.out.println(buffer.position() + " " + buffer.limit());
|
// System.out.println(buffer.position() + " " + buffer.limit());
|
||||||
} break;
|
} break;
|
||||||
|
case MAT4D: {
|
||||||
|
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
|
buffer.limit(buffer.capacity());
|
||||||
|
} break;
|
||||||
case DOUBLE: {
|
case DOUBLE: {
|
||||||
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
|
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
buffer.limit(buffer.capacity());
|
buffer.limit(buffer.capacity());
|
||||||
@ -227,27 +235,29 @@ public class InstanceData {
|
|||||||
buffer.put(mat.m31());
|
buffer.put(mat.m31());
|
||||||
buffer.put(mat.m32());
|
buffer.put(mat.m32());
|
||||||
buffer.put(mat.m33());
|
buffer.put(mat.m33());
|
||||||
/*
|
} break;
|
||||||
buffer.put(mat.m00());
|
case MAT4D: {
|
||||||
buffer.put(mat.m10());
|
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
buffer.put(mat.m20());
|
Matrix4d mat = (Matrix4d)actor.getAttributeValue(attribute);
|
||||||
buffer.put(mat.m30());
|
buffer.put((float)mat.m00());
|
||||||
|
buffer.put((float)mat.m10());
|
||||||
|
buffer.put((float)mat.m20());
|
||||||
|
buffer.put((float)mat.m30());
|
||||||
|
|
||||||
buffer.put(mat.m01());
|
buffer.put((float)mat.m10());
|
||||||
buffer.put(mat.m11());
|
buffer.put((float)mat.m11());
|
||||||
buffer.put(mat.m21());
|
buffer.put((float)mat.m12());
|
||||||
buffer.put(mat.m31());
|
buffer.put((float)mat.m13());
|
||||||
|
|
||||||
buffer.put(mat.m02());
|
buffer.put((float)mat.m20());
|
||||||
buffer.put(mat.m12());
|
buffer.put((float)mat.m21());
|
||||||
buffer.put(mat.m22());
|
buffer.put((float)mat.m22());
|
||||||
buffer.put(mat.m32());
|
buffer.put((float)mat.m23());
|
||||||
|
|
||||||
buffer.put(mat.m03());
|
buffer.put((float)mat.m30());
|
||||||
buffer.put(mat.m13());
|
buffer.put((float)mat.m31());
|
||||||
buffer.put(mat.m23());
|
buffer.put((float)mat.m32());
|
||||||
buffer.put(mat.m33());
|
buffer.put((float)mat.m33());
|
||||||
*/
|
|
||||||
} break;
|
} break;
|
||||||
case DOUBLE: {
|
case DOUBLE: {
|
||||||
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
|
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
@ -293,6 +303,11 @@ public class InstanceData {
|
|||||||
buffer.flip();
|
buffer.flip();
|
||||||
// System.out.println(buffer.position() + " " + buffer.limit());
|
// System.out.println(buffer.position() + " " + buffer.limit());
|
||||||
} break;
|
} break;
|
||||||
|
case MAT4D: {
|
||||||
|
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
|
buffer.flip();
|
||||||
|
// System.out.println(buffer.position() + " " + buffer.limit());
|
||||||
|
} break;
|
||||||
case DOUBLE: {
|
case DOUBLE: {
|
||||||
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
|
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
@ -333,6 +348,10 @@ public class InstanceData {
|
|||||||
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
|
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
} break;
|
} break;
|
||||||
|
case MAT4D: {
|
||||||
|
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
|
buffer.flip();
|
||||||
|
} break;
|
||||||
case DOUBLE: {
|
case DOUBLE: {
|
||||||
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
|
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
|
|||||||
@ -4,6 +4,7 @@ package electrosphere.renderer.actor.instance;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.joml.Matrix4d;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
@ -78,6 +79,13 @@ public class InstancedActor implements Comparable<InstancedActor> {
|
|||||||
attributes.put(attribute, new Matrix4f((Matrix4f)value));
|
attributes.put(attribute, new Matrix4f((Matrix4f)value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(value instanceof Matrix4d){
|
||||||
|
if(attributes.containsKey(attribute)){
|
||||||
|
((Matrix4d)attributes.get(attribute)).set((Matrix4d)value);
|
||||||
|
} else {
|
||||||
|
attributes.put(attribute, new Matrix4d((Matrix4d)value));
|
||||||
|
}
|
||||||
|
}
|
||||||
// attributes.put(attribute, value);
|
// attributes.put(attribute, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -119,6 +119,9 @@ public class HomogenousInstancedArray {
|
|||||||
case MAT4F: {
|
case MAT4F: {
|
||||||
return capacity * 4 * 4 * 4;
|
return capacity * 4 * 4 * 4;
|
||||||
}
|
}
|
||||||
|
case MAT4D: {
|
||||||
|
return capacity * 4 * 4 * 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -166,6 +169,29 @@ public class HomogenousInstancedArray {
|
|||||||
GL45.glVertexAttribDivisor(matrixAttributeIndices[1], 1);
|
GL45.glVertexAttribDivisor(matrixAttributeIndices[1], 1);
|
||||||
GL45.glVertexAttribDivisor(matrixAttributeIndices[2], 1);
|
GL45.glVertexAttribDivisor(matrixAttributeIndices[2], 1);
|
||||||
GL45.glVertexAttribDivisor(matrixAttributeIndices[3], 1);
|
GL45.glVertexAttribDivisor(matrixAttributeIndices[3], 1);
|
||||||
|
} else if(type == HomogenousBufferTypes.MAT4D){
|
||||||
|
//https://solhsa.com/instancing.html
|
||||||
|
//https://stackoverflow.com/questions/17355051/using-a-matrix-as-vertex-attribute-in-opengl3-core-profile
|
||||||
|
//"opengl matrix attribute"
|
||||||
|
//https://learnopengl.com/code_viewer_gh.php?code=src/4.advanced_opengl/10.3.asteroids_instanced/asteroids_instanced.cpp
|
||||||
|
GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, bufferPointer);
|
||||||
|
//enable attributes
|
||||||
|
GL45.glEnableVertexAttribArray(matrixAttributeIndices[0]);
|
||||||
|
GL45.glEnableVertexAttribArray(matrixAttributeIndices[1]);
|
||||||
|
GL45.glEnableVertexAttribArray(matrixAttributeIndices[2]);
|
||||||
|
GL45.glEnableVertexAttribArray(matrixAttributeIndices[3]);
|
||||||
|
//update attribute to point to buffer at correct offset + stride
|
||||||
|
GL45.glVertexAttribPointer(matrixAttributeIndices[0], 4, GL45.GL_FLOAT, false, 64, 0 * 4);
|
||||||
|
GL45.glVertexAttribPointer(matrixAttributeIndices[1], 4, GL45.GL_FLOAT, false, 64, 4 * 4);
|
||||||
|
GL45.glVertexAttribPointer(matrixAttributeIndices[2], 4, GL45.GL_FLOAT, false, 64, 4 * 8);
|
||||||
|
GL45.glVertexAttribPointer(matrixAttributeIndices[3], 4, GL45.GL_FLOAT, false, 64, 4 * 12);
|
||||||
|
//bind buffer
|
||||||
|
GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, bufferPointer);
|
||||||
|
//tell opengl to send a new value from buffer for each instance (instead of whole buffer for every instance)
|
||||||
|
GL45.glVertexAttribDivisor(matrixAttributeIndices[0], 1);
|
||||||
|
GL45.glVertexAttribDivisor(matrixAttributeIndices[1], 1);
|
||||||
|
GL45.glVertexAttribDivisor(matrixAttributeIndices[2], 1);
|
||||||
|
GL45.glVertexAttribDivisor(matrixAttributeIndices[3], 1);
|
||||||
} else {
|
} else {
|
||||||
LoggerInterface.loggerRenderer.ERROR("Unsupported operation", new Exception());
|
LoggerInterface.loggerRenderer.ERROR("Unsupported operation", new Exception());
|
||||||
}
|
}
|
||||||
@ -211,7 +237,11 @@ public class HomogenousInstancedArray {
|
|||||||
} break;
|
} break;
|
||||||
case MAT4F: {
|
case MAT4F: {
|
||||||
FloatBuffer buffer = (FloatBuffer)object;
|
FloatBuffer buffer = (FloatBuffer)object;
|
||||||
// GL45.glNamedBufferSubData(bufferPointer, startIndex, buffer);
|
GL45.glNamedBufferSubData(bufferPointer, startIndex, buffer);
|
||||||
|
} break;
|
||||||
|
case MAT4D: {
|
||||||
|
FloatBuffer buffer = (FloatBuffer)object;
|
||||||
|
GL45.glNamedBufferSubData(bufferPointer, startIndex, buffer);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
//unbind the buffer
|
//unbind the buffer
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public class HomogenousUniformBuffer {
|
|||||||
VEC4F,
|
VEC4F,
|
||||||
VEC4D,
|
VEC4D,
|
||||||
MAT4F,
|
MAT4F,
|
||||||
|
MAT4D,
|
||||||
INT,
|
INT,
|
||||||
FLOAT,
|
FLOAT,
|
||||||
DOUBLE,
|
DOUBLE,
|
||||||
@ -111,6 +112,9 @@ public class HomogenousUniformBuffer {
|
|||||||
case MAT4F: {
|
case MAT4F: {
|
||||||
return capacity * 4 * 4 * 4;
|
return capacity * 4 * 4 * 4;
|
||||||
}
|
}
|
||||||
|
case MAT4D: {
|
||||||
|
return capacity * 4 * 4 * 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -177,6 +181,10 @@ public class HomogenousUniformBuffer {
|
|||||||
FloatBuffer buffer = (FloatBuffer)object;
|
FloatBuffer buffer = (FloatBuffer)object;
|
||||||
GL45.glNamedBufferSubData(bufferPointer, startIndex, buffer);
|
GL45.glNamedBufferSubData(bufferPointer, startIndex, buffer);
|
||||||
} break;
|
} break;
|
||||||
|
case MAT4D: {
|
||||||
|
FloatBuffer buffer = (FloatBuffer)object;
|
||||||
|
GL45.glNamedBufferSubData(bufferPointer, startIndex, buffer);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
//unbind the buffer
|
//unbind the buffer
|
||||||
// GL45.glBindBuffer(GL45.GL_UNIFORM_BUFFER, 0);
|
// GL45.glBindBuffer(GL45.GL_UNIFORM_BUFFER, 0);
|
||||||
|
|||||||
@ -675,7 +675,11 @@ public class TerrainChunkModelGeneration {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a mesh based on a terrainchunkdata object
|
||||||
|
* @param data The terrain chunk data object
|
||||||
|
* @return The mesh
|
||||||
|
*/
|
||||||
protected static Mesh generateTerrainMesh(TerrainChunkData data){
|
protected static Mesh generateTerrainMesh(TerrainChunkData data){
|
||||||
|
|
||||||
Mesh mesh = new Mesh();
|
Mesh mesh = new Mesh();
|
||||||
@ -780,7 +784,11 @@ public class TerrainChunkModelGeneration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a model based on a terrainchunkdata object
|
||||||
|
* @param data The terrain chunk data object
|
||||||
|
* @return The model
|
||||||
|
*/
|
||||||
public static Model generateTerrainModel(TerrainChunkData data){
|
public static Model generateTerrainModel(TerrainChunkData data){
|
||||||
Model rVal = new Model();
|
Model rVal = new Model();
|
||||||
rVal.meshes = new ArrayList<Mesh>();
|
rVal.meshes = new ArrayList<Mesh>();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,371 @@
|
|||||||
|
package electrosphere.renderer.meshgen;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.types.terrain.TerrainChunkData;
|
||||||
|
import electrosphere.renderer.Material;
|
||||||
|
import electrosphere.renderer.Mesh;
|
||||||
|
import electrosphere.renderer.Model;
|
||||||
|
import electrosphere.renderer.meshgen.TerrainChunkModelGeneration.GridCell;
|
||||||
|
import electrosphere.renderer.meshgen.TerrainChunkModelGeneration.Triangle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility functions for generating transvoxel based meshes
|
||||||
|
*/
|
||||||
|
public class TransvoxelModelGeneration {
|
||||||
|
|
||||||
|
// static class Triangle {
|
||||||
|
// int[] indices = new int[3]; //array of size 3
|
||||||
|
|
||||||
|
// public Triangle(int index0, int index1, int index2){
|
||||||
|
// indices[0] = index0;
|
||||||
|
// indices[1] = index1;
|
||||||
|
// indices[2] = index2;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static class GridCell {
|
||||||
|
// Vector3f[] points = new Vector3f[8]; //array of size 8
|
||||||
|
// double[] val = new double[8]; //array of size 8
|
||||||
|
// public void setValues(
|
||||||
|
// Vector3f p1, Vector3f p2, Vector3f p3, Vector3f p4,
|
||||||
|
// Vector3f p5, Vector3f p6, Vector3f p7, Vector3f p8,
|
||||||
|
// double val1, double val2, double val3, double val4,
|
||||||
|
// double val5, double val6, double val7, double val8
|
||||||
|
// ){
|
||||||
|
// points[0] = p1; points[1] = p2; points[2] = p3; points[3] = p4;
|
||||||
|
// points[4] = p5; points[5] = p6; points[6] = p7; points[7] = p8;
|
||||||
|
// val[0] = val1; val[1] = val2; val[2] = val3; val[3] = val4;
|
||||||
|
// val[4] = val5; val[5] = val6; val[6] = val7; val[7] = val8;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// protected static int polygonize(
|
||||||
|
// GridCell grid,
|
||||||
|
// double isolevel,
|
||||||
|
// List<Triangle> triangles,
|
||||||
|
// Map<String,Integer> vertMap,
|
||||||
|
// List<Vector3f> verts,
|
||||||
|
// List<Vector3f> normals,
|
||||||
|
// List<Integer> trianglesSharingVert
|
||||||
|
// ){
|
||||||
|
// int i;
|
||||||
|
// int ntriang;
|
||||||
|
// int cubeIndex = 0;
|
||||||
|
// Vector3f[] vertList = new Vector3f[12];
|
||||||
|
|
||||||
|
// //get lookup key (index) for edge table
|
||||||
|
// //edge table tells us which vertices are inside of the surface
|
||||||
|
// if (grid.val[0] < isolevel) cubeIndex |= 1;
|
||||||
|
// if (grid.val[1] < isolevel) cubeIndex |= 2;
|
||||||
|
// if (grid.val[2] < isolevel) cubeIndex |= 4;
|
||||||
|
// if (grid.val[3] < isolevel) cubeIndex |= 8;
|
||||||
|
// if (grid.val[4] < isolevel) cubeIndex |= 16;
|
||||||
|
// if (grid.val[5] < isolevel) cubeIndex |= 32;
|
||||||
|
// if (grid.val[6] < isolevel) cubeIndex |= 64;
|
||||||
|
// if (grid.val[7] < isolevel) cubeIndex |= 128;
|
||||||
|
|
||||||
|
// //Cube is entirely in/out of the surface
|
||||||
|
// if (edgeTable[cubeIndex] == 0)
|
||||||
|
// return(0);
|
||||||
|
|
||||||
|
// //instead of having all intersections be perfectly at the midpoint,
|
||||||
|
// //for each edge this code calculates where along the edge to place the vertex
|
||||||
|
// //this should dramatically smooth the surface
|
||||||
|
// if ((edgeTable[cubeIndex] & 1) > 0)
|
||||||
|
// vertList[0] =
|
||||||
|
// VertexInterp(isolevel,grid.points[0],grid.points[1],grid.val[0],grid.val[1]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 2) > 0)
|
||||||
|
// vertList[1] =
|
||||||
|
// VertexInterp(isolevel,grid.points[1],grid.points[2],grid.val[1],grid.val[2]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 4) > 0)
|
||||||
|
// vertList[2] =
|
||||||
|
// VertexInterp(isolevel,grid.points[2],grid.points[3],grid.val[2],grid.val[3]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 8) > 0)
|
||||||
|
// vertList[3] =
|
||||||
|
// VertexInterp(isolevel,grid.points[3],grid.points[0],grid.val[3],grid.val[0]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 16) > 0)
|
||||||
|
// vertList[4] =
|
||||||
|
// VertexInterp(isolevel,grid.points[4],grid.points[5],grid.val[4],grid.val[5]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 32) > 0)
|
||||||
|
// vertList[5] =
|
||||||
|
// VertexInterp(isolevel,grid.points[5],grid.points[6],grid.val[5],grid.val[6]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 64) > 0)
|
||||||
|
// vertList[6] =
|
||||||
|
// VertexInterp(isolevel,grid.points[6],grid.points[7],grid.val[6],grid.val[7]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 128) > 0)
|
||||||
|
// vertList[7] =
|
||||||
|
// VertexInterp(isolevel,grid.points[7],grid.points[4],grid.val[7],grid.val[4]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 256) > 0)
|
||||||
|
// vertList[8] =
|
||||||
|
// VertexInterp(isolevel,grid.points[0],grid.points[4],grid.val[0],grid.val[4]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 512) > 0)
|
||||||
|
// vertList[9] =
|
||||||
|
// VertexInterp(isolevel,grid.points[1],grid.points[5],grid.val[1],grid.val[5]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 1024) > 0)
|
||||||
|
// vertList[10] =
|
||||||
|
// VertexInterp(isolevel,grid.points[2],grid.points[6],grid.val[2],grid.val[6]);
|
||||||
|
// if ((edgeTable[cubeIndex] & 2048) > 0)
|
||||||
|
// vertList[11] =
|
||||||
|
// VertexInterp(isolevel,grid.points[3],grid.points[7],grid.val[3],grid.val[7]);
|
||||||
|
|
||||||
|
// //Create the triangle
|
||||||
|
// ntriang = 0;
|
||||||
|
// for (i=0; triTable[cubeIndex][i]!=-1; i+=3) {
|
||||||
|
// //
|
||||||
|
// // Triangles calculation
|
||||||
|
// //
|
||||||
|
// //get indices
|
||||||
|
// Vector3f vert0 = vertList[triTable[cubeIndex][i+0]];
|
||||||
|
// Vector3f vert1 = vertList[triTable[cubeIndex][i+1]];
|
||||||
|
// Vector3f vert2 = vertList[triTable[cubeIndex][i+2]];
|
||||||
|
// int index0 = getVertIndex(vert0,vertMap,verts);
|
||||||
|
// int index1 = getVertIndex(vert1,vertMap,verts);
|
||||||
|
// int index2 = getVertIndex(vert2,vertMap,verts);
|
||||||
|
|
||||||
|
// //add 0's to normals until it matches vert count
|
||||||
|
// while(trianglesSharingVert.size() < verts.size()){
|
||||||
|
// trianglesSharingVert.add(0);
|
||||||
|
// normals.add(new Vector3f());
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// //add new triangle
|
||||||
|
// Triangle newTriangle = new Triangle(index0,index1,index2);
|
||||||
|
// triangles.add(newTriangle);
|
||||||
|
// ntriang++;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// //
|
||||||
|
// // Normals calculation
|
||||||
|
// //
|
||||||
|
|
||||||
|
|
||||||
|
// //calculate normal for new triangle
|
||||||
|
// Vector3f u = verts.get(index1).sub(verts.get(index0), new Vector3f());
|
||||||
|
// Vector3f v = verts.get(index2).sub(verts.get(index1), new Vector3f());
|
||||||
|
// Vector3f n = new Vector3f(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x).normalize();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// //for each vertex, average the new normal with the normals that are already there
|
||||||
|
// int trianglesSharingIndex0 = trianglesSharingVert.get(index0);
|
||||||
|
// //calculate proportion of each normal
|
||||||
|
// float oldProportion = trianglesSharingIndex0 / (float)(trianglesSharingIndex0 + 1);
|
||||||
|
// float newProportion = 1.0f / (float)(trianglesSharingIndex0 + 1);
|
||||||
|
// //increment number of triangles sharing vert
|
||||||
|
// trianglesSharingVert.set(index0, trianglesSharingIndex0 + 1);
|
||||||
|
|
||||||
|
// Vector3f currentNormal = normals.get(index0);
|
||||||
|
// currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion);
|
||||||
|
// normals.get(index0).set(currentNormal);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// int trianglesSharingIndex1 = trianglesSharingVert.get(index1);
|
||||||
|
// //calculate proportion of each normal
|
||||||
|
// oldProportion = trianglesSharingIndex1 / (float)(trianglesSharingIndex1 + 1);
|
||||||
|
// newProportion = 1.0f / (float)(trianglesSharingIndex1 + 1);
|
||||||
|
// //increment number of triangles sharing vert
|
||||||
|
// trianglesSharingVert.set(index1, trianglesSharingIndex1 + 1);
|
||||||
|
|
||||||
|
// currentNormal = normals.get(index1);
|
||||||
|
// currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion);
|
||||||
|
// normals.get(index1).set(currentNormal);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// int trianglesSharingIndex2 = trianglesSharingVert.get(index2);
|
||||||
|
// //calculate proportion of each normal
|
||||||
|
// oldProportion = trianglesSharingIndex2 / (float)(trianglesSharingIndex2 + 1);
|
||||||
|
// newProportion = 1.0f / (float)(trianglesSharingIndex2 + 1);
|
||||||
|
// //increment number of triangles sharing vert
|
||||||
|
// trianglesSharingVert.set(index2, trianglesSharingIndex2 + 1);
|
||||||
|
|
||||||
|
// currentNormal = normals.get(index2);
|
||||||
|
// currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion);
|
||||||
|
// normals.get(index2).set(currentNormal);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return(ntriang);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //interpolates the location that the edge gets cut based on the magnitudes of the scalars of the vertices at either end of the edge
|
||||||
|
// static Vector3f VertexInterp(double isolevel, Vector3f p1, Vector3f p2, double valp1, double valp2){
|
||||||
|
// double mu;
|
||||||
|
// float x, y, z;
|
||||||
|
|
||||||
|
// if (Math.abs(isolevel-valp1) < 0.00001)
|
||||||
|
// return(p1);
|
||||||
|
// if (Math.abs(isolevel-valp2) < 0.00001)
|
||||||
|
// return(p2);
|
||||||
|
// if (Math.abs(valp1-valp2) < 0.00001)
|
||||||
|
// return(p1);
|
||||||
|
// mu = (isolevel - valp1) / (valp2 - valp1);
|
||||||
|
// x = (float)(p1.x + mu * (p2.x - p1.x));
|
||||||
|
// y = (float)(p1.y + mu * (p2.y - p1.y));
|
||||||
|
// z = (float)(p1.z + mu * (p2.z - p1.z));
|
||||||
|
|
||||||
|
// return new Vector3f(x,y,z);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Creates terrain chunk data based on data provided
|
||||||
|
// * @param terrainGrid the grid of weights to generate off of
|
||||||
|
// * @param textureGrid the grid of texture indices to generate off of
|
||||||
|
// * @param neighborLODLevels The lod levels of all neighbors and this cell. Should be 3x3x3 array of lod level values.
|
||||||
|
// */
|
||||||
|
// public static TerrainChunkData generateTerrainChunkData(float[][][] terrainGrid, int[][][] textureGrid, int[][][] neighborLODLevels){
|
||||||
|
|
||||||
|
// // 5 6
|
||||||
|
// // +-------------+ +-----5-------+ ^ Y
|
||||||
|
// // / | / | / | /| | _
|
||||||
|
// // / | / | 4 9 6 10 | /\ Z
|
||||||
|
// // 4 +-----+-------+ 7 | +-----+7------+ | | /
|
||||||
|
// // | 1 +-------+-----+ 2 | +-----1-+-----+ | /
|
||||||
|
// // | / | / 8 0 11 2 | /
|
||||||
|
// // | / | / | / | / |/
|
||||||
|
// // 0 +-------------+ 3 +------3------+ +---------------> X
|
||||||
|
|
||||||
|
// //the current grid cell
|
||||||
|
// GridCell currentCell = new GridCell();
|
||||||
|
// //the list of all triangles
|
||||||
|
// List<Triangle> triangles = new LinkedList<Triangle>();
|
||||||
|
// //the map of vertex to index
|
||||||
|
// Map<String,Integer> vertMap = new HashMap<String,Integer>();
|
||||||
|
// //the list of all verts
|
||||||
|
// List<Vector3f> verts = new LinkedList<Vector3f>();
|
||||||
|
// //the list of all normals
|
||||||
|
// List<Vector3f> normals = new LinkedList<Vector3f>();
|
||||||
|
// //the list of number of triangles that share a vert
|
||||||
|
// List<Integer> trianglesSharingVert = new LinkedList<Integer>();
|
||||||
|
// //List of elements in order
|
||||||
|
// List<Integer> faceElements = new LinkedList<Integer>();
|
||||||
|
// //List of UVs
|
||||||
|
// List<Float> UVs = new LinkedList<Float>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// for(int x = 0; x < terrainGrid.length - 1; x++){
|
||||||
|
// for(int y = 0; y < terrainGrid[0].length - 1; y++){
|
||||||
|
// for(int z = 0; z < terrainGrid[0][0].length - 1; z++){
|
||||||
|
// //push the current cell's values into the gridcell
|
||||||
|
// currentCell.setValues(
|
||||||
|
// new Vector3f(x+0,y+0,z+0), new Vector3f(x+0,y+0,z+1), new Vector3f(x+1,y+0,z+1), new Vector3f(x+1,y+0,z+0),
|
||||||
|
// new Vector3f(x+0,y+1,z+0), new Vector3f(x+0,y+1,z+1), new Vector3f(x+1,y+1,z+1), new Vector3f(x+1,y+1,z+0),
|
||||||
|
// terrainGrid[x+0][y+0][z+0], terrainGrid[x+0][y+0][z+1], terrainGrid[x+1][y+0][z+1], terrainGrid[x+1][y+0][z+0],
|
||||||
|
// terrainGrid[x+0][y+1][z+0], terrainGrid[x+0][y+1][z+1], terrainGrid[x+1][y+1][z+1], terrainGrid[x+1][y+1][z+0]
|
||||||
|
// );
|
||||||
|
// //polygonize the current gridcell
|
||||||
|
// polygonize(currentCell, 0, triangles, vertMap, verts, normals, trianglesSharingVert);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //all verts in order, flattened as an array of floats instead of vecs
|
||||||
|
// List<Float> vertsFlat = new LinkedList<Float>();
|
||||||
|
// //all normals in order, flattened as an array of floats instead of vecs
|
||||||
|
// List<Float> normalsFlat = new LinkedList<Float>();
|
||||||
|
// //all elements of faces in order
|
||||||
|
// List<Integer> elementsFlat = new LinkedList<Integer>();
|
||||||
|
|
||||||
|
// //flatten verts + normals
|
||||||
|
// for(Vector3f vert : verts){
|
||||||
|
// vertsFlat.add(vert.x);
|
||||||
|
// vertsFlat.add(vert.y);
|
||||||
|
// vertsFlat.add(vert.z);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for(Vector3f normal : normals){
|
||||||
|
// normalsFlat.add(normal.x);
|
||||||
|
// normalsFlat.add(normal.y);
|
||||||
|
// normalsFlat.add(normal.z);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// for(Triangle triangle : triangles){
|
||||||
|
// elementsFlat.add(triangle.indices[0]);
|
||||||
|
// elementsFlat.add(triangle.indices[1]);
|
||||||
|
// elementsFlat.add(triangle.indices[2]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// float[] temp = new float[3];
|
||||||
|
// int i = 0;
|
||||||
|
// for(Vector3f normal : normals){
|
||||||
|
// Vector3f vert = verts.get(i);
|
||||||
|
|
||||||
|
// float absX = Math.abs(normal.x);
|
||||||
|
// float absY = Math.abs(normal.y);
|
||||||
|
// float absZ = Math.abs(normal.z);
|
||||||
|
|
||||||
|
// float uvX = vert.z * absX + vert.x * absY + vert.x * absZ;
|
||||||
|
// float uvY = vert.y * absX + vert.z * absY + vert.y * absZ;
|
||||||
|
// temp[0] = uvX;
|
||||||
|
// temp[1] = uvY;
|
||||||
|
|
||||||
|
// // if(absX >= absZ && absX >= absY){
|
||||||
|
// // temp[0] = normal.z / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ));
|
||||||
|
// // temp[1] = normal.y / 2.0f + 0.5f + vert.x * (absY / (absX + absY)) + vert.y * (absX / (absX + absY));
|
||||||
|
// // } else if(absZ >= absX && absZ >= absY){
|
||||||
|
// // temp[0] = normal.x / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ));
|
||||||
|
// // temp[1] = normal.y / 2.0f + 0.5f + vert.z * (absY / (absZ + absY)) + vert.y * (absZ / (absZ + absY));
|
||||||
|
// // } else if(absY >= absX && absY >= absZ){
|
||||||
|
// // temp[0] = normal.x / 2.0f + 0.5f + vert.y * (absX / (absX + absY)) + vert.x * (absY / (absX + absY));
|
||||||
|
// // temp[1] = normal.z / 2.0f + 0.5f + vert.y * (absZ / (absZ + absY)) + vert.z * (absY / (absZ + absY));
|
||||||
|
// // } else {
|
||||||
|
// // temp[0] = vert.x / 1.5f + vert.z / 1.5f;
|
||||||
|
// // temp[1] = vert.y / 1.5f + vert.z / 1.5f;
|
||||||
|
// // }
|
||||||
|
// i++;
|
||||||
|
// UVs.add(temp[0]);
|
||||||
|
// UVs.add(temp[1]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //List<Float> vertices, List<Float> normals, List<Integer> faceElements, List<Float> uvs
|
||||||
|
// TerrainChunkData rVal = new TerrainChunkData(vertsFlat, normalsFlat, elementsFlat, UVs);
|
||||||
|
// return rVal;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private static String getVertKeyFromPoints(float x, float y, float z){
|
||||||
|
// return x + "_" + y + "_" + z;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private static int getVertIndex(Vector3f vert, Map<String,Integer> vertMap, List<Vector3f> verts){
|
||||||
|
// int rVal = -1;
|
||||||
|
// String vertKey = getVertKeyFromPoints(vert.x,vert.y,vert.z);
|
||||||
|
// if(vertMap.containsKey(vertKey)){
|
||||||
|
// return vertMap.get(vertKey);
|
||||||
|
// } else {
|
||||||
|
// rVal = verts.size();
|
||||||
|
// verts.add(vert);
|
||||||
|
// vertMap.put(vertKey,rVal);
|
||||||
|
// return rVal;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private static Vector3f averageNormals(Vector3f normal0, float proportion0, Vector3f normal1, float proportion1){
|
||||||
|
// Vector3f rVal = new Vector3f(normal0);
|
||||||
|
// rVal = rVal.mul(proportion0).add(new Vector3f(normal1).mul(proportion1));
|
||||||
|
// return rVal;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
@ -27,7 +27,7 @@ public class ScriptEngine {
|
|||||||
//create context
|
//create context
|
||||||
context = Context.newBuilder("js").engine(engine).build();
|
context = Context.newBuilder("js").engine(engine).build();
|
||||||
//read scripts into source map
|
//read scripts into source map
|
||||||
readScriptsDirectory("/Scripts", FileUtils.getAssetFile("/Scripts"));
|
readScriptsDirectory("/src/main/sql", FileUtils.getAssetFile("/src/main/sql"));
|
||||||
//create bindings
|
//create bindings
|
||||||
// try {
|
// try {
|
||||||
// String content = FileUtils.getAssetFileAsString("/Scripts/test.js");
|
// String content = FileUtils.getAssetFileAsString("/Scripts/test.js");
|
||||||
|
|||||||
@ -2,8 +2,6 @@ package electrosphere.server.datacell;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
@ -14,11 +12,12 @@ import org.joml.Vector3i;
|
|||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityUtils;
|
import electrosphere.entity.EntityUtils;
|
||||||
import electrosphere.entity.Scene;
|
|
||||||
import electrosphere.game.server.world.ServerWorldData;
|
import electrosphere.game.server.world.ServerWorldData;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||||
import electrosphere.net.server.player.Player;
|
import electrosphere.net.server.player.Player;
|
||||||
import electrosphere.server.datacell.interfaces.DataCellManager;
|
import electrosphere.server.datacell.interfaces.DataCellManager;
|
||||||
|
import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
||||||
import electrosphere.server.datacell.physics.PhysicsDataCell;
|
import electrosphere.server.datacell.physics.PhysicsDataCell;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
@ -26,7 +25,7 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
|||||||
/**
|
/**
|
||||||
* Implementation of DataCellManager that lays out cells in a logical grid (array). Useful for eg 3d terrain gridded world.
|
* Implementation of DataCellManager that lays out cells in a logical grid (array). Useful for eg 3d terrain gridded world.
|
||||||
*/
|
*/
|
||||||
public class GriddedDataCellManager implements DataCellManager {
|
public class GriddedDataCellManager implements DataCellManager, VoxelCellManager {
|
||||||
//these are going to be the natural ground grid of data cells, but we're going to have more than this
|
//these are going to be the natural ground grid of data cells, but we're going to have more than this
|
||||||
Map<String,ServerDataCell> groundDataCells = new HashMap<String,ServerDataCell>();
|
Map<String,ServerDataCell> groundDataCells = new HashMap<String,ServerDataCell>();
|
||||||
//loaded cells
|
//loaded cells
|
||||||
@ -37,6 +36,8 @@ public class GriddedDataCellManager implements DataCellManager {
|
|||||||
Realm parent;
|
Realm parent;
|
||||||
//Manager for terrain for this particular cell manager
|
//Manager for terrain for this particular cell manager
|
||||||
ServerTerrainManager serverTerrainManager;
|
ServerTerrainManager serverTerrainManager;
|
||||||
|
//lock for terrain editing
|
||||||
|
Semaphore terrainEditLock = new Semaphore(1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -61,6 +62,7 @@ public class GriddedDataCellManager implements DataCellManager {
|
|||||||
* @param player The player
|
* @param player The player
|
||||||
*/
|
*/
|
||||||
public void addPlayerToRealm(Player player){
|
public void addPlayerToRealm(Player player){
|
||||||
|
Globals.realmManager.setPlayerRealm(player, parent);
|
||||||
int playerSimulationRadius = player.getSimulationRadius();
|
int playerSimulationRadius = player.getSimulationRadius();
|
||||||
Vector3i worldPos = player.getWorldPos();
|
Vector3i worldPos = player.getWorldPos();
|
||||||
for(int x = worldPos.x - playerSimulationRadius; x < worldPos.x + playerSimulationRadius + 1; x++){
|
for(int x = worldPos.x - playerSimulationRadius; x < worldPos.x + playerSimulationRadius + 1; x++){
|
||||||
@ -342,4 +344,56 @@ public class GriddedDataCellManager implements DataCellManager {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/**
|
||||||
|
* Gets the weight of a single voxel at a position
|
||||||
|
* @param worldPosition The position in world coordinates of the chunk to grab data from
|
||||||
|
* @param voxelPosition The position in voxel coordinates (local/relative to the chunk) to get voxel values from
|
||||||
|
* @return The weight of the described voxel
|
||||||
|
*/
|
||||||
|
public float getVoxelWeightAtLocalPosition(Vector3i worldPosition, Vector3i voxelPosition) {
|
||||||
|
return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z).getWeights()[voxelPosition.x][voxelPosition.y][voxelPosition.z];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/**
|
||||||
|
* Gets the type of a single voxel at a position
|
||||||
|
* @param worldPosition The position in world coordinates of the chunk to grab data from
|
||||||
|
* @param voxelPosition The position in voxel coordinates (local/relative to the chunk) to get voxel values from
|
||||||
|
* @return The type of the described voxel
|
||||||
|
*/
|
||||||
|
public int getVoxelTypeAtLocalPosition(Vector3i worldPosition, Vector3i voxelPosition) {
|
||||||
|
return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z).getValues()[voxelPosition.x][voxelPosition.y][voxelPosition.z];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/**
|
||||||
|
* Gets the chunk data at a given world position
|
||||||
|
* @param worldPosition The position in world coordinates
|
||||||
|
* @return The ServerTerrainChunk of data at that position, or null if it is out of bounds or otherwise doesn't exist
|
||||||
|
*/
|
||||||
|
public ServerTerrainChunk getChunkAtPosition(Vector3i worldPosition) {
|
||||||
|
return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/**
|
||||||
|
* Edits a single voxel
|
||||||
|
* @param worldPosition The world position of the chunk to edit
|
||||||
|
* @param voxelPosition The voxel position of the voxel to edit
|
||||||
|
* @param weight The weight to set the voxel to
|
||||||
|
* @param type The type to set the voxel to
|
||||||
|
*/
|
||||||
|
public void editChunk(Vector3i worldPosition, Vector3i voxelPosition, float weight, int type) {
|
||||||
|
terrainEditLock.acquireUninterruptibly();
|
||||||
|
//update terrain
|
||||||
|
serverTerrainManager.deformTerrainAtLocationToValue(worldPosition, voxelPosition, weight, type);
|
||||||
|
//broadcast update to terrain
|
||||||
|
groundDataCells.get(getServerDataCellKey(worldPosition)).broadcastNetworkMessage(TerrainMessage.constructUpdateVoxelMessage(
|
||||||
|
worldPosition.x, worldPosition.y, worldPosition.z,
|
||||||
|
voxelPosition.x, voxelPosition.y, voxelPosition.z,
|
||||||
|
weight, type));
|
||||||
|
terrainEditLock.release();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,33 +1,26 @@
|
|||||||
package electrosphere.server.datacell;
|
package electrosphere.server.datacell;
|
||||||
|
|
||||||
import electrosphere.collision.CollisionEngine;
|
import electrosphere.collision.CollisionEngine;
|
||||||
import electrosphere.collision.CollisionWorldData;
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.engine.Main;
|
import electrosphere.engine.Main;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityUtils;
|
|
||||||
import electrosphere.entity.Scene;
|
import electrosphere.entity.Scene;
|
||||||
import electrosphere.entity.types.hitbox.HitboxManager;
|
import electrosphere.entity.types.hitbox.HitboxManager;
|
||||||
import electrosphere.game.server.world.ServerWorldData;
|
|
||||||
import electrosphere.logger.LoggerInterface;
|
|
||||||
import electrosphere.net.parser.net.message.NetworkMessage;
|
import electrosphere.net.parser.net.message.NetworkMessage;
|
||||||
import electrosphere.net.server.Server;
|
|
||||||
import electrosphere.net.server.player.Player;
|
|
||||||
import electrosphere.server.datacell.interfaces.DataCellManager;
|
import electrosphere.server.datacell.interfaces.DataCellManager;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
import org.joml.Vector3d;
|
|
||||||
import org.joml.Vector3f;
|
|
||||||
import org.joml.Vector3i;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages data cells on the server side
|
* Manages data cells on the server side
|
||||||
*/
|
*/
|
||||||
public class Realm {
|
public class Realm {
|
||||||
|
|
||||||
List<ServerDataCell> loadedDataCells = new LinkedList<ServerDataCell>();
|
//The set containing all data cells loaded into this realm
|
||||||
|
Set<ServerDataCell> loadedDataCells = new HashSet<ServerDataCell>();
|
||||||
|
|
||||||
//this is the cell that all players loading into the game (via connection startup, death, etc) reside in
|
//this is the cell that all players loading into the game (via connection startup, death, etc) reside in
|
||||||
ServerDataCell loadingCell = new ServerDataCell(new Scene());
|
ServerDataCell loadingCell = new ServerDataCell(new Scene());
|
||||||
|
|
||||||
@ -91,11 +84,22 @@ public class Realm {
|
|||||||
cell.broadcastNetworkMessage(message);
|
cell.broadcastNetworkMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Used for cleaning server data cells no longer in use from the realm
|
||||||
|
Set<ServerDataCell> toCleanQueue = new HashSet<ServerDataCell>();
|
||||||
/**
|
/**
|
||||||
* Unloads all chunks that haven't had players in them for a set amount of time
|
* Unloads all chunks that haven't had players in them for a set amount of time
|
||||||
*/
|
*/
|
||||||
public void unloadPlayerlessChunks(){
|
public void unloadPlayerlessChunks(){
|
||||||
//TODO: implement and actually call it
|
//TODO: improve to make have less performance impact
|
||||||
|
for(ServerDataCell cell : loadedDataCells){
|
||||||
|
if(cell.getPlayers().size() < 1){
|
||||||
|
toCleanQueue.add(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(ServerDataCell cell : toCleanQueue){
|
||||||
|
deregisterCell(cell);
|
||||||
|
}
|
||||||
|
toCleanQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
package electrosphere.server.datacell;
|
package electrosphere.server.datacell;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -13,6 +11,7 @@ import electrosphere.engine.Globals;
|
|||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.types.hitbox.HitboxManager;
|
import electrosphere.entity.types.hitbox.HitboxManager;
|
||||||
import electrosphere.game.server.world.ServerWorldData;
|
import electrosphere.game.server.world.ServerWorldData;
|
||||||
|
import electrosphere.net.server.player.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages all realms for the engine. Should be a singleton
|
* Manages all realms for the engine. Should be a singleton
|
||||||
@ -23,6 +22,8 @@ public class RealmManager {
|
|||||||
Set<Realm> realms = new CopyOnWriteArraySet<Realm>();
|
Set<Realm> realms = new CopyOnWriteArraySet<Realm>();
|
||||||
//Map of entities to the realm the entity is in
|
//Map of entities to the realm the entity is in
|
||||||
Map<Entity,Realm> entityToRealmMap = new ConcurrentHashMap<Entity,Realm>();
|
Map<Entity,Realm> entityToRealmMap = new ConcurrentHashMap<Entity,Realm>();
|
||||||
|
//Map of player to the realm the player is in
|
||||||
|
Map<Player,Realm> playerToRealmMap = new ConcurrentHashMap<Player,Realm>();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,5 +109,24 @@ public class RealmManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: !!URGENT!! come up with some mechanism to enforce this actually being called every time a player is added to a server data cell
|
||||||
|
/**
|
||||||
|
* Adds a player to a realm
|
||||||
|
* @param player The player
|
||||||
|
* @param realm The realm
|
||||||
|
*/
|
||||||
|
public void setPlayerRealm(Player player, Realm realm){
|
||||||
|
playerToRealmMap.put(player, realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the realm of a given player
|
||||||
|
* @param player The player
|
||||||
|
* @return The realm
|
||||||
|
*/
|
||||||
|
public Realm getPlayerRealm(Player player){
|
||||||
|
return playerToRealmMap.get(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,8 +14,8 @@ import electrosphere.server.content.EnvironmentGenerator;
|
|||||||
import electrosphere.server.pathfinding.NavMeshUtils;
|
import electrosphere.server.pathfinding.NavMeshUtils;
|
||||||
import electrosphere.server.pathfinding.navmesh.NavMesh;
|
import electrosphere.server.pathfinding.navmesh.NavMesh;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container for entities loaded into memory. This isn't intended to be in charge
|
* Container for entities loaded into memory. This isn't intended to be in charge
|
||||||
@ -28,9 +28,15 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class ServerDataCell {
|
public class ServerDataCell {
|
||||||
|
|
||||||
List<Player> activePlayers = new LinkedList<Player>();
|
//all players attached to this server data cell
|
||||||
|
Set<Player> activePlayers = new HashSet<Player>();
|
||||||
|
|
||||||
|
//the navmesh for the data cell
|
||||||
NavMesh navMesh;
|
NavMesh navMesh;
|
||||||
|
|
||||||
|
//the scene backing the server data cell
|
||||||
Scene scene;
|
Scene scene;
|
||||||
|
|
||||||
//controls whether the server data cell simulates its entities or not
|
//controls whether the server data cell simulates its entities or not
|
||||||
boolean ready = false;
|
boolean ready = false;
|
||||||
|
|
||||||
@ -73,6 +79,14 @@ public class ServerDataCell {
|
|||||||
activePlayers.remove(p);
|
activePlayers.remove(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the set of all players in the server data cell
|
||||||
|
* @return The set of players in the data cell
|
||||||
|
*/
|
||||||
|
public Set<Player> getPlayers(){
|
||||||
|
return activePlayers;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This should be used to translate a character from macrolevel simulation to
|
* This should be used to translate a character from macrolevel simulation to
|
||||||
* microlevel, datacell based simulation.
|
* microlevel, datacell based simulation.
|
||||||
@ -84,25 +98,6 @@ public class ServerDataCell {
|
|||||||
throw new UnsupportedOperationException("Not implemented yet");
|
throw new UnsupportedOperationException("Not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * This should be used to translate an entity from one data cell to another.
|
|
||||||
// * @param e
|
|
||||||
// */
|
|
||||||
// protected void addEntity(Entity e){
|
|
||||||
// loadedEntities.add(e);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Intention of this function is to entirely remove the entity from microlevel simulation.
|
|
||||||
// * This should be conbined with code to convert the entity into a tracked macrolevel character.
|
|
||||||
// * The previous should not be true if you're tracking something inconsequential like
|
|
||||||
// * a rabbit or something. Then just delete it.
|
|
||||||
// * @param e
|
|
||||||
// */
|
|
||||||
// public void removeEntity(Entity e){
|
|
||||||
// loadedEntities.remove(e);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcast a message to all players within range of this cell.
|
* Broadcast a message to all players within range of this cell.
|
||||||
* @param message
|
* @param message
|
||||||
|
|||||||
@ -0,0 +1,44 @@
|
|||||||
|
package electrosphere.server.datacell.interfaces;
|
||||||
|
|
||||||
|
import org.joml.Vector3i;
|
||||||
|
|
||||||
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of a DataCellManager that provides voxel terrain access and editing functions
|
||||||
|
*/
|
||||||
|
public interface VoxelCellManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the weight of a single voxel at a position
|
||||||
|
* @param worldPosition The position in world coordinates of the chunk to grab data from
|
||||||
|
* @param voxelPosition The position in voxel coordinates (local/relative to the chunk) to get voxel values from
|
||||||
|
* @return The weight of the described voxel
|
||||||
|
*/
|
||||||
|
public float getVoxelWeightAtLocalPosition(Vector3i worldPosition, Vector3i voxelPosition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type of a single voxel at a position
|
||||||
|
* @param worldPosition The position in world coordinates of the chunk to grab data from
|
||||||
|
* @param voxelPosition The position in voxel coordinates (local/relative to the chunk) to get voxel values from
|
||||||
|
* @return The type of the described voxel
|
||||||
|
*/
|
||||||
|
public int getVoxelTypeAtLocalPosition(Vector3i worldPosition, Vector3i voxelPosition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the chunk data at a given world position
|
||||||
|
* @param worldPosition The position in world coordinates
|
||||||
|
* @return The ServerTerrainChunk of data at that position, or null if it is out of bounds or otherwise doesn't exist
|
||||||
|
*/
|
||||||
|
public ServerTerrainChunk getChunkAtPosition(Vector3i worldPosition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits a single voxel
|
||||||
|
* @param worldPosition The world position of the chunk to edit
|
||||||
|
* @param voxelPosition The voxel position of the voxel to edit
|
||||||
|
* @param weight The weight to set the voxel to
|
||||||
|
* @param type The type to set the voxel to
|
||||||
|
*/
|
||||||
|
public void editChunk(Vector3i worldPosition, Vector3i voxelPosition, float weight, int type);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
package electrosphere.server.terrain.editing;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
import org.joml.Vector3i;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.server.datacell.Realm;
|
||||||
|
import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
||||||
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides utilities for editing terrain (particularly brushes, etc)
|
||||||
|
*/
|
||||||
|
public class TerrainEditing {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a terrain chunk edit. Basically has a sphere around the provided position that it attempts to add value to.
|
||||||
|
* @param position The position to perform the edit
|
||||||
|
* @param editMagnitude The magnitude of the edit to perform
|
||||||
|
* @param type The type of block to make all edited blocks
|
||||||
|
* @param weight The weight of the sphere to apply the edit to
|
||||||
|
*/
|
||||||
|
public static void editTerrain(Realm realm, Vector3d position, float editMagnitude, int type, float weight){
|
||||||
|
if(position != null && realm != null && realm.getDataCellManager() instanceof VoxelCellManager){
|
||||||
|
VoxelCellManager voxelCellManager = (VoxelCellManager) realm.getDataCellManager();
|
||||||
|
//calculate kernel size
|
||||||
|
int numPlacesToCheck = (int)((editMagnitude * 2 + 1) * (editMagnitude * 2 + 1) * (editMagnitude * 2 + 1));
|
||||||
|
//create and fill in kernel of positions to check
|
||||||
|
int[] xOffsetSet = new int[numPlacesToCheck];
|
||||||
|
int[] yOffsetSet = new int[numPlacesToCheck];
|
||||||
|
int[] zOffsetSet = new int[numPlacesToCheck];
|
||||||
|
int i = 0;
|
||||||
|
for(int x = -(int)editMagnitude; x <= (int)editMagnitude; x++){
|
||||||
|
for(int y = -(int)editMagnitude; y <= (int)editMagnitude; y++){
|
||||||
|
for(int z = -(int)editMagnitude; z <= (int)editMagnitude; z++){
|
||||||
|
xOffsetSet[i] = x;
|
||||||
|
yOffsetSet[i] = y;
|
||||||
|
zOffsetSet[i] = z;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(i = 0; i < numPlacesToCheck; i++){
|
||||||
|
//calculate position of edit
|
||||||
|
Vector3d offsetPos = new Vector3d(position).add(xOffsetSet[i],yOffsetSet[i],zOffsetSet[i]);
|
||||||
|
Vector3i chunkPos = Globals.serverWorldData.convertRealToWorldSpace(offsetPos);
|
||||||
|
Vector3i voxelPos = Globals.serverWorldData.convertRealToVoxelSpace(offsetPos);
|
||||||
|
//get distance from true center point of sphere to current voxel position in world space
|
||||||
|
float distance = (float)new Vector3d(Math.floor(offsetPos.x),Math.floor(offsetPos.y),Math.floor(offsetPos.z)).distance(position);
|
||||||
|
float currentPositionMagnitude = editMagnitude - distance;
|
||||||
|
|
||||||
|
ServerTerrainChunk data = voxelCellManager.getChunkAtPosition(chunkPos);
|
||||||
|
if(
|
||||||
|
voxelPos.x < ServerTerrainChunk.CHUNK_DIMENSION &&
|
||||||
|
voxelPos.y < ServerTerrainChunk.CHUNK_DIMENSION &&
|
||||||
|
voxelPos.z < ServerTerrainChunk.CHUNK_DIMENSION &&
|
||||||
|
currentPositionMagnitude > 0 &&
|
||||||
|
data != null
|
||||||
|
){
|
||||||
|
float current = data.getWeights()[voxelPos.x][voxelPos.y][voxelPos.z];
|
||||||
|
//hard clamp so it doesn't go over 1
|
||||||
|
float finalValue = Math.max(Math.min(current + weight,1),-1);
|
||||||
|
voxelCellManager.editChunk(chunkPos, voxelPos, finalValue, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -12,6 +12,8 @@ public class ServerTerrainChunk {
|
|||||||
|
|
||||||
//all chunks are 16x16x16
|
//all chunks are 16x16x16
|
||||||
public static final int CHUNK_DIMENSION = 16;
|
public static final int CHUNK_DIMENSION = 16;
|
||||||
|
//The size of the data passed into marching cubes/transvoxel to generate a fully connected and seamless chunk
|
||||||
|
public static final int CHUNK_DATA_GENERATOR_SIZE = CHUNK_DIMENSION + 1;
|
||||||
|
|
||||||
int worldX, worldY, worldZ;
|
int worldX, worldY, worldZ;
|
||||||
List<TerrainModification> modifications = new LinkedList<TerrainModification>();
|
List<TerrainModification> modifications = new LinkedList<TerrainModification>();
|
||||||
@ -26,20 +28,29 @@ public class ServerTerrainChunk {
|
|||||||
this.values = values;
|
this.values = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an arena chunk. Should be flat land if worldY=0, otherwise all air
|
||||||
|
* @param worldX The world x position
|
||||||
|
* @param worldY The world y position
|
||||||
|
* @param worldZ The world z position
|
||||||
|
* @return The ServerTerrainChunk
|
||||||
|
*/
|
||||||
public static ServerTerrainChunk getArenaChunk(int worldX, int worldY, int worldZ){
|
public static ServerTerrainChunk getArenaChunk(int worldX, int worldY, int worldZ){
|
||||||
float[][][] weights = new float[CHUNK_DIMENSION][CHUNK_DIMENSION][CHUNK_DIMENSION];
|
//Each chunk also needs custody of the next chunk's first values so that they can perfectly overlap.
|
||||||
int[][][] values = new int[CHUNK_DIMENSION][CHUNK_DIMENSION][CHUNK_DIMENSION];
|
//Hence, width should actually be chunk dimension + 1
|
||||||
for(int inc = 0; inc < CHUNK_DIMENSION; inc++){
|
float[][][] weights = new float[CHUNK_DATA_GENERATOR_SIZE][CHUNK_DATA_GENERATOR_SIZE][CHUNK_DATA_GENERATOR_SIZE];
|
||||||
for(int weightX = 0; weightX < CHUNK_DIMENSION; weightX++){
|
int[][][] values = new int[CHUNK_DATA_GENERATOR_SIZE][CHUNK_DATA_GENERATOR_SIZE][CHUNK_DATA_GENERATOR_SIZE];
|
||||||
for(int weightZ = 0; weightZ < CHUNK_DIMENSION; weightZ++){
|
for(int inc = 0; inc < CHUNK_DATA_GENERATOR_SIZE; inc++){
|
||||||
|
for(int weightX = 0; weightX < CHUNK_DATA_GENERATOR_SIZE; weightX++){
|
||||||
|
for(int weightZ = 0; weightZ < 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 < CHUNK_DIMENSION; weightX++){
|
for(int weightX = 0; weightX < CHUNK_DATA_GENERATOR_SIZE; weightX++){
|
||||||
for(int weightZ = 0; weightZ < CHUNK_DIMENSION; weightZ++){
|
for(int weightZ = 0; weightZ < CHUNK_DATA_GENERATOR_SIZE; weightZ++){
|
||||||
weights[weightX][0][weightZ] = 0.1f;
|
weights[weightX][0][weightZ] = 0.1f;
|
||||||
values[weightX][0][weightZ] = 1;
|
values[weightX][0][weightZ] = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -268,6 +268,13 @@ public class ServerTerrainManager {
|
|||||||
return worldX + "_" + worldY + "_" + worldZ;
|
return worldX + "_" + worldY + "_" + worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a server terrain chunk
|
||||||
|
* @param worldX The world x position
|
||||||
|
* @param worldY The world y position
|
||||||
|
* @param worldZ The world z position
|
||||||
|
* @return The ServerTerrainChunk
|
||||||
|
*/
|
||||||
public ServerTerrainChunk getChunk(int worldX, int worldY, int worldZ){
|
public ServerTerrainChunk getChunk(int worldX, int worldY, int worldZ){
|
||||||
if(model != null){
|
if(model != null){
|
||||||
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
||||||
@ -279,13 +286,15 @@ public class ServerTerrainManager {
|
|||||||
returnedChunk = chunkCache.get(key);
|
returnedChunk = chunkCache.get(key);
|
||||||
return returnedChunk;
|
return returnedChunk;
|
||||||
} else {
|
} else {
|
||||||
|
//Each chunk also needs custody of the next chunk's first values so that they can perfectly overlap.
|
||||||
|
//Hence, width should actually be chunk dimension + 1
|
||||||
float[][] heightmap = getHeightmap(worldX, worldZ);
|
float[][] heightmap = getHeightmap(worldX, worldZ);
|
||||||
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 weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
|
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightX++){
|
||||||
for(int weightY = 0; weightY < ServerTerrainChunk.CHUNK_DIMENSION; weightY++){
|
for(int weightY = 0; weightY < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightY++){
|
||||||
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
|
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightZ++){
|
||||||
if(weightY < heightmap[ServerTerrainChunk.CHUNK_DIMENSION * worldX + weightX][ServerTerrainChunk.CHUNK_DIMENSION * worldZ + weightZ]){
|
if(weightY < heightmap[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldX + weightX][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldZ + weightZ]){
|
||||||
weights[weightX][weightY][weightZ] = 1;
|
weights[weightX][weightY][weightZ] = 1;
|
||||||
values[weightX][weightY][weightZ] = 1;
|
values[weightX][weightY][weightZ] = 1;
|
||||||
} else {
|
} else {
|
||||||
@ -346,14 +355,19 @@ public class ServerTerrainManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deformTerrainAtLocationToValue(
|
/**
|
||||||
Vector3i worldPos,
|
* Applies a deform to terrain at a given location
|
||||||
Vector3i subChunkPos,
|
* @param worldPos The world coordinates of the chunk to modify
|
||||||
Vector3i voxelPos,
|
* @param voxelPos The voxel coordinates of the voxel to modify
|
||||||
float weight, int value){
|
* @param weight The weight to set it to
|
||||||
System.out.println("Add modification at " + worldPos.x + "," + worldPos.z + " subloc " + voxelPos.x + "," + voxelPos.z);
|
* @param value The value to set it to
|
||||||
TerrainModification modification = new TerrainModification(worldPos,subChunkPos,voxelPos,weight,value);
|
*/
|
||||||
|
public void deformTerrainAtLocationToValue(Vector3i worldPos, Vector3i voxelPos, float weight, int value){
|
||||||
|
TerrainModification modification = new TerrainModification(worldPos,voxelPos,weight,value);
|
||||||
|
//could be null if, for instance, arena mode
|
||||||
|
if(model != null){
|
||||||
model.addModification(modification);
|
model.addModification(modification);
|
||||||
|
}
|
||||||
String key = getKey(worldPos.x,worldPos.y,worldPos.z);
|
String key = getKey(worldPos.x,worldPos.y,worldPos.z);
|
||||||
if(chunkCache.containsKey(key)){
|
if(chunkCache.containsKey(key)){
|
||||||
ServerTerrainChunk chunk = chunkCache.get(key);
|
ServerTerrainChunk chunk = chunkCache.get(key);
|
||||||
|
|||||||
@ -10,14 +10,12 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
|||||||
*/
|
*/
|
||||||
public class TerrainModification {
|
public class TerrainModification {
|
||||||
Vector3i worldPos;
|
Vector3i worldPos;
|
||||||
Vector3i subChunkPos;
|
|
||||||
Vector3i voxelPos;
|
Vector3i voxelPos;
|
||||||
float weight;
|
float weight;
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
public TerrainModification(Vector3i worldPos, Vector3i subChunkPos, Vector3i voxelPos, float weight, int value) {
|
public TerrainModification(Vector3i worldPos, Vector3i voxelPos, float weight, int value) {
|
||||||
this.worldPos = worldPos;
|
this.worldPos = worldPos;
|
||||||
this.subChunkPos = subChunkPos;
|
|
||||||
this.voxelPos = voxelPos;
|
this.voxelPos = voxelPos;
|
||||||
this.weight = weight;
|
this.weight = weight;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
@ -27,10 +25,6 @@ public class TerrainModification {
|
|||||||
return worldPos;
|
return worldPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3i getSubChunkPos() {
|
|
||||||
return subChunkPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3i getVoxelPos() {
|
public Vector3i getVoxelPos() {
|
||||||
return voxelPos;
|
return voxelPos;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -186,7 +186,7 @@ public class FileUtils {
|
|||||||
|
|
||||||
public static String getSQLScriptFileAsString(String pathName) throws IOException {
|
public static String getSQLScriptFileAsString(String pathName) throws IOException {
|
||||||
String sanitizedFilePath = sanitizeFilePath(pathName);
|
String sanitizedFilePath = sanitizeFilePath(pathName);
|
||||||
File targetFile = new File("./Scripts" + sanitizedFilePath);
|
File targetFile = new File("./src/main/sql" + sanitizedFilePath);
|
||||||
return Files.readString(targetFile.toPath());
|
return Files.readString(targetFile.toPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user