diff --git a/assets/Shaders/VertexShaderNoBones.vs b/assets/Shaders/VertexShaderNoBones.vs index 705dcba4..e9055b94 100644 --- a/assets/Shaders/VertexShaderNoBones.vs +++ b/assets/Shaders/VertexShaderNoBones.vs @@ -22,6 +22,7 @@ uniform mat4 lightSpaceMatrix; out vec3 Normal; out vec3 FragPos; out vec2 TexCoord; +out vec3 ViewFragPos; out vec4 FragPosLightSpace; @@ -35,6 +36,7 @@ void main() { //push frag, normal, and texture positions to fragment shader FragPos = vec3(model * FinalVertex); + ViewFragPos = vec3(view * model * FinalVertex); Normal = mat3(transpose(inverse(model))) * aNormal; TexCoord = aTex; diff --git a/assets/Shaders/core/oit/general/VertexShaderNoBones.vs b/assets/Shaders/core/oit/general/VertexShaderNoBones.vs index ee6c2fc2..3f696117 100644 --- a/assets/Shaders/core/oit/general/VertexShaderNoBones.vs +++ b/assets/Shaders/core/oit/general/VertexShaderNoBones.vs @@ -21,6 +21,7 @@ uniform mat4 lightSpaceMatrix; //output buffers out vec3 Normal; out vec3 FragPos; +out vec3 ViewFragPos; out vec2 TexCoord; out vec4 FragPosLightSpace; @@ -35,6 +36,7 @@ void main() { //push frag, normal, and texture positions to fragment shader FragPos = vec3(model * FinalVertex); + ViewFragPos = vec3(view * model * FinalVertex); Normal = mat3(transpose(inverse(model))) * aNormal; TexCoord = aTex; diff --git a/buildNumber.properties b/buildNumber.properties index 87898e04..14badf94 100644 --- a/buildNumber.properties +++ b/buildNumber.properties @@ -1,3 +1,3 @@ #maven.buildNumber.plugin properties file -#Wed Sep 18 20:37:06 EDT 2024 -buildNumber=338 +#Thu Sep 19 15:35:07 EDT 2024 +buildNumber=339 diff --git a/docs/src/progress/bigthings.md b/docs/src/progress/bigthings.md index bd559a1a..a124af11 100644 --- a/docs/src/progress/bigthings.md +++ b/docs/src/progress/bigthings.md @@ -15,8 +15,6 @@ TODO(?): - Building cube voxels w/ LOD - - Deferred Shading Pipeline - - Audio Ray Tracing - Hair/Cloth Simulation diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index d12de903..3c744f20 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -807,6 +807,10 @@ Work on clustered lighting Cluster lighting completed ClientPointLightComponent Small rendering info display +Fix terrain editing across chunk borders on server + - This is because the ray on the client doesn't intersect at the border (because the physics generation isn't working on chunk-end) + - Also because the client doesn't scan border chunks to see if they should update +Fix shader program bug with no-bone variants # TODO diff --git a/src/main/java/electrosphere/collision/CollisionBodyCreation.java b/src/main/java/electrosphere/collision/CollisionBodyCreation.java index 12cea366..8f7fa50b 100644 --- a/src/main/java/electrosphere/collision/CollisionBodyCreation.java +++ b/src/main/java/electrosphere/collision/CollisionBodyCreation.java @@ -233,18 +233,23 @@ public class CollisionBodyCreation { public static DBody generateBodyFromTerrainData(CollisionEngine collisionEngine, TerrainChunkData data, long categoryBits){ DBody body = null; - float[] vertices = new float[data.getVertices().size()]; + int elementCount = data.getFaceElements().size(); + + float[] vertices = new float[elementCount * 3]; int vertexInserterPos = 0; - int[] indices = new int[data.getFaceElements().size()]; + int[] indices = new int[elementCount]; int indexInserterPos = 0; - for(float vertexValue : data.getVertices()){ - vertices[vertexInserterPos] = vertexValue; - vertexInserterPos++; - } - for(int element : data.getFaceElements()){ - indices[indexInserterPos] = element; + //add a new vertex + vertices[vertexInserterPos*3+0] = data.getVertices().get(element*3+0); + vertices[vertexInserterPos*3+1] = data.getVertices().get(element*3+1); + vertices[vertexInserterPos*3+2] = data.getVertices().get(element*3+2); + vertexInserterPos = vertexInserterPos + 1; + + //push faces -- instead of pushing the element directly, instead use the incrementer because we want to draw a new vertex + //there should be no vertex-sharing between triangles. This keeps the meshes from blurring texture/lighting + indices[indexInserterPos] = indexInserterPos; indexInserterPos++; } diff --git a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java index fc666892..b9477f95 100644 --- a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java +++ b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java @@ -422,7 +422,7 @@ public class PhysicsEntityUtils { * @return The rigid body created (note, attachment has already been performed) */ public static DBody clientAttachTerrainChunkRigidBody(Entity terrain, TerrainChunkData data){ - DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientSceneWrapper.getCollisionEngine(), data,Collidable.TYPE_STATIC_BIT); + DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT); Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_TERRAIN, false)); diff --git a/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java index 55b43581..bab65358 100644 --- a/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java @@ -1,7 +1,11 @@ package electrosphere.net.client.protocol; +import java.util.LinkedList; +import java.util.List; + import org.joml.Vector3f; +import org.joml.Vector3i; import electrosphere.client.scene.ClientWorldData; import electrosphere.client.terrain.cache.ChunkData; @@ -44,8 +48,39 @@ public class TerrainProtocol implements ClientProtocolTemplate { Globals.clientTerrainManager.attachTerrainMessage(message); break; case UPDATEVOXEL: { - if(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(message.getworldX(), message.getworldY(), message.getworldZ())){ - ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(message.getworldX(), message.getworldY(), message.getworldZ()); + // + //find what all drawcells might be updated by this voxel update + Vector3i worldPos = new Vector3i(message.getworldX(), message.getworldY(), message.getworldZ()); + List positionsToUpdate = new LinkedList(); + positionsToUpdate.add(worldPos); + if(message.getvoxelX() < 1){ + positionsToUpdate.add(new Vector3i(worldPos).sub(1,0,0)); + if(message.getvoxelY() < 1){ + positionsToUpdate.add(new Vector3i(worldPos).sub(1,1,0)); + if(message.getvoxelZ() < 1){ + positionsToUpdate.add(new Vector3i(worldPos).sub(1,1,1)); + } + } else { + if(message.getvoxelZ() < 1){ + positionsToUpdate.add(new Vector3i(worldPos).sub(1,0,1)); + } + } + } else { + if(message.getvoxelY() < 1){ + positionsToUpdate.add(new Vector3i(worldPos).sub(0,1,0)); + if(message.getvoxelZ() < 1){ + positionsToUpdate.add(new Vector3i(worldPos).sub(0,1,1)); + } + } else { + if(message.getvoxelZ() < 1){ + positionsToUpdate.add(new Vector3i(worldPos).sub(0,0,1)); + } + } + } + // + //update the terrain cache + if(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z)){ + ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z); if(data != null){ data.updatePosition( message.getvoxelX(), @@ -54,7 +89,16 @@ public class TerrainProtocol implements ClientProtocolTemplate { message.getterrainWeight(), message.getterrainValue() ); - Globals.drawCellManager.markUpdateable(message.getworldX(), message.getworldY(), message.getworldZ()); + } + } + // + //mark all relevant drawcells as updateable + for(Vector3i worldPosToUpdate : positionsToUpdate){ + if(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z)){ + ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z); + if(data != null){ + Globals.drawCellManager.markUpdateable(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z); + } } } } break; diff --git a/src/main/java/electrosphere/renderer/meshgen/TerrainChunkModelGeneration.java b/src/main/java/electrosphere/renderer/meshgen/TerrainChunkModelGeneration.java index 6b6ca9a3..763008a5 100644 --- a/src/main/java/electrosphere/renderer/meshgen/TerrainChunkModelGeneration.java +++ b/src/main/java/electrosphere/renderer/meshgen/TerrainChunkModelGeneration.java @@ -1,6 +1,7 @@ package electrosphere.renderer.meshgen; import java.nio.FloatBuffer; +import java.nio.IntBuffer; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -673,7 +674,7 @@ public class TerrainChunkModelGeneration { //all normals in order, flattened as an array of floats instead of vecs List normalsFlat = new LinkedList(); //all elements of faces in order - List elementsFlat = new LinkedList(); + LinkedList elementsFlat = new LinkedList(); //List of texture sampler values List textureSamplers = new LinkedList(); //List of texture ratio values @@ -792,6 +793,8 @@ public class TerrainChunkModelGeneration { FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 3); FloatBuffer normalArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 3); FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 2); + IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(elementCount); + int incrementer = 0; for(int element : data.getFaceElements()){ //for each element, need to push vert, normal, etc @@ -808,6 +811,11 @@ public class TerrainChunkModelGeneration { //push current uvs textureArrayBufferData.put(data.getUVs().get(element*2+0)); textureArrayBufferData.put(data.getUVs().get(element*2+1)); + + //push faces -- instead of pushing the element directly, instead use the incrementer because we want to draw a new vertex + //there should be no vertex-sharing between triangles. This keeps the meshes from blurring texture/lighting + elementArrayBufferData.put(incrementer); + incrementer++; } //actually buffer vertices @@ -828,14 +836,17 @@ public class TerrainChunkModelGeneration { mesh.bufferTextureCoords(textureArrayBufferData, 2); } + //buffer element indices + if(elementArrayBufferData.position() > 0){ + elementArrayBufferData.flip(); + mesh.bufferFaces(elementArrayBufferData, elementCount); + } + } catch (NullPointerException ex){ ex.printStackTrace(); } - //alert mesh to use direct array access and set the number of elements in the direct arrays - mesh.setUseElementArray(false); - mesh.setDirectArraySize(elementCount); // diff --git a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java index 31c0cf67..c6091aed 100644 --- a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java @@ -2,6 +2,8 @@ package electrosphere.server.datacell; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -375,6 +377,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager loadedCells.add(groundDataCells.get(getServerDataCellKey(worldPos))); cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(worldPos)),0); loadedCellsLock.release(); + } else { + LoggerInterface.loggerEngine.WARNING("Trying to create data cell outside world bounds! " + worldPos); } return groundDataCells.get(getServerDataCellKey(worldPos)); } @@ -524,14 +528,42 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager terrainEditLock.acquireUninterruptibly(); //update terrain serverTerrainManager.deformTerrainAtLocationToValue(worldPosition, voxelPosition, weight, type); - this.createTerrainPhysicsEntities(worldPosition); - //broadcast update to terrain - ServerDataCell cell = groundDataCells.get(getServerDataCellKey(worldPosition)); - if(cell != null){ - cell.broadcastNetworkMessage(TerrainMessage.constructUpdateVoxelMessage( - worldPosition.x, worldPosition.y, worldPosition.z, - voxelPosition.x, voxelPosition.y, voxelPosition.z, - weight, type)); + List worldPositionsToUpdate = new LinkedList(); + worldPositionsToUpdate.add(worldPosition); + if(voxelPosition.x < 1){ + worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(1,0,0)); + if(voxelPosition.y < 1){ + worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(1,1,0)); + if(voxelPosition.z < 1){ + worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(1,1,1)); + } + } else { + if(voxelPosition.z < 1){ + worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(1,0,1)); + } + } + } else { + if(voxelPosition.y < 1){ + worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,1,0)); + if(voxelPosition.z < 1){ + worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,1,1)); + } + } else { + if(voxelPosition.z < 1){ + worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,0,1)); + } + } + } + //update all loaded cells + for(Vector3i toUpdate : worldPositionsToUpdate){ + ServerDataCell cell = groundDataCells.get(getServerDataCellKey(toUpdate)); + if(cell != null){ + this.createTerrainPhysicsEntities(toUpdate); + cell.broadcastNetworkMessage(TerrainMessage.constructUpdateVoxelMessage( + worldPosition.x, worldPosition.y, worldPosition.z, + voxelPosition.x, voxelPosition.y, voxelPosition.z, + weight, type)); + } } terrainEditLock.release(); } diff --git a/src/main/java/electrosphere/server/terrain/editing/TerrainEditing.java b/src/main/java/electrosphere/server/terrain/editing/TerrainEditing.java index bfc31ef6..f8235f92 100644 --- a/src/main/java/electrosphere/server/terrain/editing/TerrainEditing.java +++ b/src/main/java/electrosphere/server/terrain/editing/TerrainEditing.java @@ -56,9 +56,9 @@ public class TerrainEditing { voxelPos.x < ServerTerrainChunk.CHUNK_DIMENSION && voxelPos.y < ServerTerrainChunk.CHUNK_DIMENSION && voxelPos.z < ServerTerrainChunk.CHUNK_DIMENSION && - voxelPos.x > 0 && - voxelPos.y > 0 && - voxelPos.z > 0 && + voxelPos.x >= 0 && + voxelPos.y >= 0 && + voxelPos.z >= 0 && currentPositionMagnitude > 0 && (data = voxelCellManager.getChunkAtPosition(chunkPos)) != null ){