diff --git a/src/main/java/electrosphere/client/fluid/cells/FluidCellManager.java b/src/main/java/electrosphere/client/fluid/cells/FluidCellManager.java index ef4556ba..6b856f64 100644 --- a/src/main/java/electrosphere/client/fluid/cells/FluidCellManager.java +++ b/src/main/java/electrosphere/client/fluid/cells/FluidCellManager.java @@ -404,7 +404,7 @@ public class FluidCellManager { * @return The chunk data at the specified points */ ChunkData getChunkDataAtPoint(int worldX, int worldY, int worldZ){ - return Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldX,worldY,worldZ); + return Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldX,worldY,worldZ,ChunkData.NO_STRIDE); } diff --git a/src/main/java/electrosphere/client/foliagemanager/FoliageCell.java b/src/main/java/electrosphere/client/foliagemanager/FoliageCell.java index 2205ad8d..7b652ab8 100644 --- a/src/main/java/electrosphere/client/foliagemanager/FoliageCell.java +++ b/src/main/java/electrosphere/client/foliagemanager/FoliageCell.java @@ -205,7 +205,7 @@ public class FoliageCell { protected void generate(){ boolean shouldGenerate = false; //get foliage types supported - ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPosition); + ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPosition,ChunkData.NO_STRIDE); if(data == null){ return; } diff --git a/src/main/java/electrosphere/client/foliagemanager/FoliageChunk.java b/src/main/java/electrosphere/client/foliagemanager/FoliageChunk.java index 67979564..de56289b 100644 --- a/src/main/java/electrosphere/client/foliagemanager/FoliageChunk.java +++ b/src/main/java/electrosphere/client/foliagemanager/FoliageChunk.java @@ -77,9 +77,9 @@ public class FoliageChunk { */ public void initCells(){ Globals.profiler.beginCpuSample("FoliageChunk.initCells"); - this.currentChunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos); + this.currentChunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos,ChunkData.NO_STRIDE); // //evaluate top cells if chunk above this one exists - this.aboveChunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i(worldPos).add(0,1,0)); + this.aboveChunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i(worldPos).add(0,1,0),ChunkData.NO_STRIDE); this.updateCells(true); Globals.profiler.endCpuSample(); } @@ -113,7 +113,7 @@ public class FoliageChunk { * @return true if contains foliage voxel, false otherwise */ private boolean checkContainsFoliageVoxel(){ - ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(this.getWorldPos()); + ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(this.getWorldPos(),ChunkData.NO_STRIDE); if(data == null){ return false; } diff --git a/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java b/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java index c1628975..a8d2509a 100644 --- a/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java +++ b/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java @@ -22,9 +22,14 @@ public class ClientTerrainCache { int cacheSize; /** - * The map of chunk key -> chunk data + * The map of full res chunk key -> chunk data */ - Map cacheMap = new ConcurrentHashMap(); + Map cacheMapFullRes = new ConcurrentHashMap(); + + /** + * The map of half res chunk key -> chunk data + */ + Map cacheMapHalfRes = new ConcurrentHashMap(); /** * The list of keys in the cache @@ -52,11 +57,12 @@ public class ClientTerrainCache { * @param chunkData The chunk data to add at the specified positions */ public void addChunkDataToCache(int worldX, int worldY, int worldZ, ChunkData chunkData){ - cacheMap.put(getKey(worldX,worldY,worldZ),chunkData); + Map cache = this.getCache(chunkData.getStride()); + cache.put(getKey(worldX,worldY,worldZ),chunkData); chunkPositionMap.put(chunkData,new Vector3i(worldX,worldY,worldZ)); while(cacheList.size() > cacheSize){ Long currentChunk = cacheList.remove(0); - cacheMap.remove(currentChunk); + cache.remove(currentChunk); } } @@ -65,7 +71,8 @@ public class ClientTerrainCache { */ public void evictAll(){ this.cacheList.clear(); - this.cacheMap.clear(); + this.cacheMapFullRes.clear(); + this.cacheMapHalfRes.clear(); this.chunkPositionMap.clear(); } @@ -86,10 +93,11 @@ public class ClientTerrainCache { * @param worldX The x world position * @param worldY The y world position * @param worldZ The z world position + * @param stride The stride of the data * @return True if the cache contains chunk data at the specified point, false otherwise */ - public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){ - return cacheMap.containsKey(getKey(worldX,worldY,worldZ)); + public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ, int stride){ + return this.getCache(stride).containsKey(getKey(worldX,worldY,worldZ)); } @@ -101,10 +109,11 @@ public class ClientTerrainCache { * @param worldX The x world position * @param worldY The y world position * @param worldZ The z world position + * @param stride The stride of the data * @return The chunk data if it exists, null otherwise */ - public ChunkData getSubChunkDataAtPoint(int worldX, int worldY, int worldZ){ - return cacheMap.get(getKey(worldX,worldY,worldZ)); + public ChunkData getSubChunkDataAtPoint(int worldX, int worldY, int worldZ, int stride){ + return this.getCache(stride).get(getKey(worldX,worldY,worldZ)); } /** @@ -112,7 +121,7 @@ public class ClientTerrainCache { * @return The list of all chunks in the cache */ public Collection getAllChunks(){ - return this.cacheMap.values(); + return this.cacheMapFullRes.values(); } /** @@ -124,4 +133,23 @@ public class ClientTerrainCache { return chunkPositionMap.get(chunk); } + /** + * Gets the cache + * @param stride The stride of the data + * @return The cache to use + */ + public Map getCache(int stride){ + switch(stride){ + case 0: { + return cacheMapFullRes; + } + case 1: { + return cacheMapHalfRes; + } + default: { + throw new Error("Invalid stride probided! " + stride); + } + } + } + } diff --git a/src/main/java/electrosphere/client/terrain/cells/ClientDrawCellManager.java b/src/main/java/electrosphere/client/terrain/cells/ClientDrawCellManager.java index b7e584cc..73602ec1 100644 --- a/src/main/java/electrosphere/client/terrain/cells/ClientDrawCellManager.java +++ b/src/main/java/electrosphere/client/terrain/cells/ClientDrawCellManager.java @@ -500,7 +500,7 @@ public class ClientDrawCellManager { */ boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){ if(Globals.clientTerrainManager != null){ - return Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldX,worldY,worldZ); + return Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldX,worldY,worldZ,ChunkData.NO_STRIDE); } return true; } @@ -523,7 +523,7 @@ public class ClientDrawCellManager { posToCheck.y < Globals.clientWorldData.getWorldDiscreteSize() && posToCheck.z >= 0 && posToCheck.z < Globals.clientWorldData.getWorldDiscreteSize() && - !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z) + !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z, ChunkData.NO_STRIDE) ){ //client should request chunk data from server for each chunk necessary to create the model LoggerInterface.loggerNetworking.DEBUG("(Client) Send Request for terrain at " + posToCheck); @@ -554,7 +554,7 @@ public class ClientDrawCellManager { posToCheck.y < Globals.clientWorldData.getWorldDiscreteSize() && posToCheck.z >= 0 && posToCheck.z < Globals.clientWorldData.getWorldDiscreteSize() && - !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z) + !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z, ChunkData.NO_STRIDE) ){ return false; } @@ -595,7 +595,7 @@ public class ClientDrawCellManager { posToCheck.y < Globals.clientWorldData.getWorldDiscreteSize() && posToCheck.z >= 0 && posToCheck.z < Globals.clientWorldData.getWorldDiscreteSize() && - !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z) + !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z, ChunkData.NO_STRIDE) ){ return false; } diff --git a/src/main/java/electrosphere/client/terrain/cells/DrawCell.java b/src/main/java/electrosphere/client/terrain/cells/DrawCell.java index 96eed5b9..0bb6b3ef 100644 --- a/src/main/java/electrosphere/client/terrain/cells/DrawCell.java +++ b/src/main/java/electrosphere/client/terrain/cells/DrawCell.java @@ -194,7 +194,8 @@ public class DrawCell { ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint( worldPos.x + (x * spacingFactor) / ChunkData.CHUNK_SIZE, worldPos.y + (y * spacingFactor) / ChunkData.CHUNK_SIZE, - worldPos.z + (z * spacingFactor) / ChunkData.CHUNK_SIZE + worldPos.z + (z * spacingFactor) / ChunkData.CHUNK_SIZE, + ChunkData.NO_STRIDE ); if(currentChunk == null){ return false; @@ -248,11 +249,14 @@ public class DrawCell { //implicitly performing transforms to adapt from face-space to world & local space switch(higherLODFace){ case X_POSITIVE: { - ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i( - worldPos.x + (17 * mainSpacing) / ChunkData.CHUNK_SIZE, - worldPos.y + worldCoordOffset1, - worldPos.z + worldCoordOffset2 - )); + ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint( + new Vector3i( + worldPos.x + (17 * mainSpacing) / ChunkData.CHUNK_SIZE, + worldPos.y + worldCoordOffset1, + worldPos.z + worldCoordOffset2 + ), + ChunkData.NO_STRIDE + ); if(currentChunk == null){ return false; } @@ -268,11 +272,14 @@ public class DrawCell { ); } break; case X_NEGATIVE: { - ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i( - worldPos.x, - worldPos.y + worldCoordOffset1, - worldPos.z + worldCoordOffset2 - )); + ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint( + new Vector3i( + worldPos.x, + worldPos.y + worldCoordOffset1, + worldPos.z + worldCoordOffset2 + ), + ChunkData.NO_STRIDE + ); if(currentChunk == null){ return false; } @@ -288,11 +295,14 @@ public class DrawCell { ); } break; case Y_POSITIVE: { - ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i( - worldPos.x + worldCoordOffset1, - worldPos.y + (17 * mainSpacing) / ChunkData.CHUNK_SIZE, - worldPos.z + worldCoordOffset2 - )); + ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint( + new Vector3i( + worldPos.x + worldCoordOffset1, + worldPos.y + (17 * mainSpacing) / ChunkData.CHUNK_SIZE, + worldPos.z + worldCoordOffset2 + ), + ChunkData.NO_STRIDE + ); if(currentChunk == null){ return false; } @@ -308,11 +318,14 @@ public class DrawCell { ); } break; case Y_NEGATIVE: { - ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i( - worldPos.x + worldCoordOffset1, - worldPos.y, - worldPos.z + worldCoordOffset2 - )); + ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint( + new Vector3i( + worldPos.x + worldCoordOffset1, + worldPos.y, + worldPos.z + worldCoordOffset2 + ), + ChunkData.NO_STRIDE + ); if(currentChunk == null){ return false; } @@ -328,11 +341,14 @@ public class DrawCell { ); } break; case Z_POSITIVE: { - ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i( - worldPos.x + worldCoordOffset1, - worldPos.y + worldCoordOffset2, - worldPos.z + (17 * mainSpacing) / ChunkData.CHUNK_SIZE - )); + ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint( + new Vector3i( + worldPos.x + worldCoordOffset1, + worldPos.y + worldCoordOffset2, + worldPos.z + (17 * mainSpacing) / ChunkData.CHUNK_SIZE + ), + ChunkData.NO_STRIDE + ); if(currentChunk == null){ return false; } @@ -348,11 +364,14 @@ public class DrawCell { ); } break; case Z_NEGATIVE: { - ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i( - worldPos.x + worldCoordOffset1, - worldPos.y + worldCoordOffset2, - worldPos.z - )); + ChunkData currentChunk = Globals.clientTerrainManager.getChunkDataAtWorldPoint( + new Vector3i( + worldPos.x + worldCoordOffset1, + worldPos.y + worldCoordOffset2, + worldPos.z + ), + ChunkData.NO_STRIDE + ); if(currentChunk == null){ return false; } diff --git a/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java b/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java index de4c287e..0d514141 100644 --- a/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java +++ b/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java @@ -176,7 +176,7 @@ public class DrawCellManager { posToCheck.y < Globals.clientWorldData.getWorldDiscreteSize() && posToCheck.z >= 0 && posToCheck.z < Globals.clientWorldData.getWorldDiscreteSize() && - !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z) + !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z, ChunkData.NO_STRIDE) ){ if(!requested.contains(requestKey)){ //client should request chunk data from server for each chunk necessary to create the model @@ -429,7 +429,7 @@ public class DrawCellManager { */ boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){ if(Globals.clientTerrainManager != null){ - return Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldX,worldY,worldZ); + return Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldX,worldY,worldZ,ChunkData.NO_STRIDE); } return true; } @@ -442,7 +442,7 @@ public class DrawCellManager { * @return The chunk data at the specified points */ ChunkData getChunkDataAtPoint(int worldX, int worldY, int worldZ){ - return Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldX,worldY,worldZ); + return Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldX,worldY,worldZ,ChunkData.NO_STRIDE); } diff --git a/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java b/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java index 60d5719a..8bdd02a7 100644 --- a/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java +++ b/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java @@ -169,19 +169,21 @@ public class ClientTerrainManager { * @param worldX the x position * @param worldY the y position * @param worldZ the z position + * @param stride The stride of the data * @return true if the data exists, false otherwise */ - public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){ - return terrainCache.containsChunkDataAtWorldPoint(worldX, worldY, worldZ); + public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ, int stride){ + return terrainCache.containsChunkDataAtWorldPoint(worldX, worldY, worldZ, stride); } /** * Checks if the terrain cache contains chunk data at a given world position * @param worldPos The vector containing the world-space position + * @param stride The stride of the data * @return true if the data exists, false otherwise */ - public boolean containsChunkDataAtWorldPoint(Vector3i worldPos){ - return terrainCache.containsChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z); + public boolean containsChunkDataAtWorldPoint(Vector3i worldPos, int stride){ + return this.containsChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z, stride); } /** @@ -200,40 +202,26 @@ public class ClientTerrainManager { )); } - /** - * Checks that the cache contains chunk data at a real-space coordinate - * @param x the x coordinate - * @param y the y coordinate - * @param z the z coordinate - * @return true if the cache contains the chunk data at the coordinate, false otherwise - */ - public boolean containsChunkDataAtRealPoint(double x, double y, double z){ - assert clientWorldData != null; - return terrainCache.containsChunkDataAtWorldPoint( - clientWorldData.convertRealToChunkSpace(x), - clientWorldData.convertRealToChunkSpace(y), - clientWorldData.convertRealToChunkSpace(z) - ); - } - /** * Gets the chunk data at a given world position * @param worldX The x component of the world coordinate * @param worldY The y component of the world coordinate * @param worldZ The z component of the world coordinate + * @param stride The stride of the data * @return The chunk data if it exists, otherwise null */ - public ChunkData getChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){ - return terrainCache.getSubChunkDataAtPoint(worldX, worldY, worldZ); + public ChunkData getChunkDataAtWorldPoint(int worldX, int worldY, int worldZ, int stride){ + return terrainCache.getSubChunkDataAtPoint(worldX, worldY, worldZ, stride); } /** * Gets the chunk data at a given world position * @param worldPos The world position as a joml vector + * @param stride The stride of the data * @return The chunk data if it exists, otherwise null */ - public ChunkData getChunkDataAtWorldPoint(Vector3i worldPos){ - return terrainCache.getSubChunkDataAtPoint(worldPos.x, worldPos.y, worldPos.z); + public ChunkData getChunkDataAtWorldPoint(Vector3i worldPos, int stride){ + return this.getChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z, stride); } diff --git a/src/main/java/electrosphere/client/terrain/sampling/ClientVoxelSampler.java b/src/main/java/electrosphere/client/terrain/sampling/ClientVoxelSampler.java index 8834bd06..d8fd6dab 100644 --- a/src/main/java/electrosphere/client/terrain/sampling/ClientVoxelSampler.java +++ b/src/main/java/electrosphere/client/terrain/sampling/ClientVoxelSampler.java @@ -36,8 +36,8 @@ public class ClientVoxelSampler { int voxelId = 0; Vector3i chunkSpacePos = Globals.clientWorldData.convertRealToWorldSpace(realPos); Vector3i voxelSpacePos = Globals.clientWorldData.convertRealToVoxelSpace(realPos); - if(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(chunkSpacePos)){ - ChunkData chunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(chunkSpacePos); + if(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(chunkSpacePos, ChunkData.NO_STRIDE)){ + ChunkData chunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(chunkSpacePos, ChunkData.NO_STRIDE); voxelId = chunkData.getType(voxelSpacePos); } else { return INVALID_POSITION; diff --git a/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java index aee25351..45a1c6a2 100644 --- a/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java @@ -83,8 +83,8 @@ public class TerrainProtocol implements ClientProtocolTemplate { } // //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(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z, ChunkData.NO_STRIDE)){ + ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z, ChunkData.NO_STRIDE); if(data != null){ data.updatePosition( message.getvoxelX(), @@ -98,8 +98,8 @@ public class TerrainProtocol implements ClientProtocolTemplate { // //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(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z, ChunkData.NO_STRIDE)){ + ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z, ChunkData.NO_STRIDE); if(data != null){ Globals.clientDrawCellManager.markUpdateable(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z); }