voxelImprovements #5
@ -5,6 +5,7 @@ import java.util.List;
 | 
				
			|||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.concurrent.ConcurrentHashMap;
 | 
					import java.util.concurrent.ConcurrentHashMap;
 | 
				
			||||||
import java.util.concurrent.CopyOnWriteArrayList;
 | 
					import java.util.concurrent.CopyOnWriteArrayList;
 | 
				
			||||||
 | 
					import java.util.concurrent.Semaphore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.joml.Vector3i;
 | 
					import org.joml.Vector3i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -51,6 +52,11 @@ public class ClientTerrainCache {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    Map<ChunkData,Vector3i> chunkPositionMap = new ConcurrentHashMap<ChunkData,Vector3i>();
 | 
					    Map<ChunkData,Vector3i> chunkPositionMap = new ConcurrentHashMap<ChunkData,Vector3i>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The lock on the terrain cache
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Semaphore lock = new Semaphore(1);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructor
 | 
					     * Constructor
 | 
				
			||||||
     * @param cacheSize The capacity of the cache
 | 
					     * @param cacheSize The capacity of the cache
 | 
				
			||||||
@ -67,6 +73,7 @@ public class ClientTerrainCache {
 | 
				
			|||||||
     * @param chunkData The chunk data to add at the specified positions
 | 
					     * @param chunkData The chunk data to add at the specified positions
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void addChunkDataToCache(int worldX, int worldY, int worldZ, ChunkData chunkData){
 | 
					    public void addChunkDataToCache(int worldX, int worldY, int worldZ, ChunkData chunkData){
 | 
				
			||||||
 | 
					        lock.acquireUninterruptibly();
 | 
				
			||||||
        Map<Long,ChunkData> cache = this.getCache(chunkData.getStride());
 | 
					        Map<Long,ChunkData> cache = this.getCache(chunkData.getStride());
 | 
				
			||||||
        cache.put(getKey(worldX,worldY,worldZ),chunkData);
 | 
					        cache.put(getKey(worldX,worldY,worldZ),chunkData);
 | 
				
			||||||
        chunkPositionMap.put(chunkData,new Vector3i(worldX,worldY,worldZ));
 | 
					        chunkPositionMap.put(chunkData,new Vector3i(worldX,worldY,worldZ));
 | 
				
			||||||
@ -74,16 +81,19 @@ public class ClientTerrainCache {
 | 
				
			|||||||
            Long currentChunk = cacheList.remove(0);
 | 
					            Long currentChunk = cacheList.remove(0);
 | 
				
			||||||
            cache.remove(currentChunk);
 | 
					            cache.remove(currentChunk);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        lock.release();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Evicts all chunks from the cache
 | 
					     * Evicts all chunks from the cache
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void evictAll(){
 | 
					    public void evictAll(){
 | 
				
			||||||
 | 
					        lock.acquireUninterruptibly();
 | 
				
			||||||
        this.cacheList.clear();
 | 
					        this.cacheList.clear();
 | 
				
			||||||
        this.cacheMapFullRes.clear();
 | 
					        this.cacheMapFullRes.clear();
 | 
				
			||||||
        this.cacheMapHalfRes.clear();
 | 
					        this.cacheMapHalfRes.clear();
 | 
				
			||||||
        this.chunkPositionMap.clear();
 | 
					        this.chunkPositionMap.clear();
 | 
				
			||||||
 | 
					        lock.release();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -107,7 +117,10 @@ public class ClientTerrainCache {
 | 
				
			|||||||
     * @return True if the cache contains chunk data at the specified point, false otherwise
 | 
					     * @return True if the cache contains chunk data at the specified point, false otherwise
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ, int stride){
 | 
					    public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ, int stride){
 | 
				
			||||||
        return this.getCache(stride).containsKey(getKey(worldX,worldY,worldZ));
 | 
					        lock.acquireUninterruptibly();
 | 
				
			||||||
 | 
					        boolean rVal = this.getCache(stride).containsKey(getKey(worldX,worldY,worldZ));
 | 
				
			||||||
 | 
					        lock.release();
 | 
				
			||||||
 | 
					        return rVal;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -123,7 +136,10 @@ public class ClientTerrainCache {
 | 
				
			|||||||
     * @return The chunk data if it exists, null otherwise
 | 
					     * @return The chunk data if it exists, null otherwise
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public ChunkData getSubChunkDataAtPoint(int worldX, int worldY, int worldZ, int stride){
 | 
					    public ChunkData getSubChunkDataAtPoint(int worldX, int worldY, int worldZ, int stride){
 | 
				
			||||||
        return this.getCache(stride).get(getKey(worldX,worldY,worldZ));
 | 
					        lock.acquireUninterruptibly();
 | 
				
			||||||
 | 
					        ChunkData rVal = this.getCache(stride).get(getKey(worldX,worldY,worldZ));
 | 
				
			||||||
 | 
					        lock.release();
 | 
				
			||||||
 | 
					        return rVal;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -602,8 +602,9 @@ public class ClientDrawCellManager {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Requests all chunks for a given draw cell
 | 
					     * Requests all chunks for a given draw cell
 | 
				
			||||||
     * @param cell The cell
 | 
					     * @param cell The cell
 | 
				
			||||||
 | 
					     * @return true if all cells were successfully requested, false otherwise
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void requestChunks(WorldOctTree.FloatingChunkTreeNode<DrawCell> node, List<DrawCellFace> highResFaces){
 | 
					    private boolean requestChunks(WorldOctTree.FloatingChunkTreeNode<DrawCell> node, List<DrawCellFace> highResFaces){
 | 
				
			||||||
        DrawCell cell = node.getData();
 | 
					        DrawCell cell = node.getData();
 | 
				
			||||||
        int lod = this.chunkTree.getMaxLevel() - node.getLevel();
 | 
					        int lod = this.chunkTree.getMaxLevel() - node.getLevel();
 | 
				
			||||||
        int spacingFactor = (int)Math.pow(2,lod);
 | 
					        int spacingFactor = (int)Math.pow(2,lod);
 | 
				
			||||||
@ -622,7 +623,9 @@ public class ClientDrawCellManager {
 | 
				
			|||||||
                        ){
 | 
					                        ){
 | 
				
			||||||
                            //client should request chunk data from server for each chunk necessary to create the model
 | 
					                            //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);
 | 
					                            LoggerInterface.loggerNetworking.DEBUG("(Client) Send Request for terrain at " + posToCheck);
 | 
				
			||||||
                            Globals.clientTerrainManager.requestChunk(posToCheck.x, posToCheck.y, posToCheck.z, lod);
 | 
					                            if(!Globals.clientTerrainManager.requestChunk(posToCheck.x, posToCheck.y, posToCheck.z, lod)){
 | 
				
			||||||
 | 
					                                return false;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -666,13 +669,16 @@ public class ClientDrawCellManager {
 | 
				
			|||||||
                            !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z, highResLod)
 | 
					                            !Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z, highResLod)
 | 
				
			||||||
                            ){
 | 
					                            ){
 | 
				
			||||||
                            LoggerInterface.loggerNetworking.DEBUG("(Client) Send Request for terrain at " + posToCheck);
 | 
					                            LoggerInterface.loggerNetworking.DEBUG("(Client) Send Request for terrain at " + posToCheck);
 | 
				
			||||||
                            Globals.clientTerrainManager.requestChunk(posToCheck.x, posToCheck.y, posToCheck.z, highResLod);
 | 
					                            if(!Globals.clientTerrainManager.requestChunk(posToCheck.x, posToCheck.y, posToCheck.z, highResLod)){
 | 
				
			||||||
 | 
					                                return false;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Checks if all chunk data required to generate this draw cell is present
 | 
					     * Checks if all chunk data required to generate this draw cell is present
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,9 @@ import java.nio.IntBuffer;
 | 
				
			|||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
import java.util.LinkedList;
 | 
					import java.util.LinkedList;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.UUID;
 | 
					import java.util.UUID;
 | 
				
			||||||
 | 
					import java.util.concurrent.ConcurrentHashMap;
 | 
				
			||||||
import java.util.concurrent.CopyOnWriteArrayList;
 | 
					import java.util.concurrent.CopyOnWriteArrayList;
 | 
				
			||||||
import java.util.concurrent.Semaphore;
 | 
					import java.util.concurrent.Semaphore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -25,6 +27,7 @@ import electrosphere.renderer.meshgen.TerrainChunkModelGeneration;
 | 
				
			|||||||
import electrosphere.renderer.model.Model;
 | 
					import electrosphere.renderer.model.Model;
 | 
				
			||||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
 | 
					import electrosphere.server.terrain.manager.ServerTerrainChunk;
 | 
				
			||||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
 | 
					import electrosphere.server.terrain.manager.ServerTerrainManager;
 | 
				
			||||||
 | 
					import io.github.studiorailgun.HashUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Manages terrain storage and access on the client
 | 
					 * Manages terrain storage and access on the client
 | 
				
			||||||
@ -59,6 +62,11 @@ public class ClientTerrainManager {
 | 
				
			|||||||
    //The queue of terrain chunk data to be buffered to gpu
 | 
					    //The queue of terrain chunk data to be buffered to gpu
 | 
				
			||||||
    static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new CopyOnWriteArrayList<TerrainChunkGenQueueItem>();
 | 
					    static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new CopyOnWriteArrayList<TerrainChunkGenQueueItem>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Tracks what outgoing requests are currently active
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Map<Long,Boolean> requestedMap = new ConcurrentHashMap<Long,Boolean>();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructor
 | 
					     * Constructor
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -134,6 +142,8 @@ public class ClientTerrainManager {
 | 
				
			|||||||
                        message.getworldX(), message.getworldY(), message.getworldZ(), 
 | 
					                        message.getworldX(), message.getworldY(), message.getworldZ(), 
 | 
				
			||||||
                        data
 | 
					                        data
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
 | 
					                    //remove from request map
 | 
				
			||||||
 | 
					                    this.requestedMap.remove(this.getRequestKey(message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution()));
 | 
				
			||||||
                } break;
 | 
					                } break;
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    LoggerInterface.loggerEngine.WARNING("ClientTerrainManager: unhandled network message of type" + message.getMessageSubtype());
 | 
					                    LoggerInterface.loggerEngine.WARNING("ClientTerrainManager: unhandled network message of type" + message.getMessageSubtype());
 | 
				
			||||||
@ -192,14 +202,23 @@ public class ClientTerrainManager {
 | 
				
			|||||||
     * @param worldY the world y coordinate of the chunk
 | 
					     * @param worldY the world y coordinate of the chunk
 | 
				
			||||||
     * @param worldZ the world z coordinate of the chunk
 | 
					     * @param worldZ the world z coordinate of the chunk
 | 
				
			||||||
     * @param stride The stride of the data
 | 
					     * @param stride The stride of the data
 | 
				
			||||||
 | 
					     * @return true if the request was successfully sent, false otherwise
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void requestChunk(int worldX, int worldY, int worldZ, int stride){
 | 
					    public boolean requestChunk(int worldX, int worldY, int worldZ, int stride){
 | 
				
			||||||
 | 
					        boolean rVal = false;
 | 
				
			||||||
 | 
					        lock.acquireUninterruptibly();
 | 
				
			||||||
 | 
					        if(!this.requestedMap.containsKey(this.getRequestKey(worldX, worldY, worldZ, stride))){
 | 
				
			||||||
            Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestReducedChunkDataMessage(
 | 
					            Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestReducedChunkDataMessage(
 | 
				
			||||||
                worldX,
 | 
					                worldX,
 | 
				
			||||||
                worldY,
 | 
					                worldY,
 | 
				
			||||||
                worldZ,
 | 
					                worldZ,
 | 
				
			||||||
                stride
 | 
					                stride
 | 
				
			||||||
            ));
 | 
					            ));
 | 
				
			||||||
 | 
					            this.requestedMap.put(this.getRequestKey(worldX, worldY, worldZ, stride), true);
 | 
				
			||||||
 | 
					            rVal = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        lock.release();
 | 
				
			||||||
 | 
					        return rVal;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -274,4 +293,16 @@ public class ClientTerrainManager {
 | 
				
			|||||||
        return terrainCache.getChunkPosition(chunk);
 | 
					        return terrainCache.getChunkPosition(chunk);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the key for a given request
 | 
				
			||||||
 | 
					     * @param worldX The world x coordinate
 | 
				
			||||||
 | 
					     * @param worldY The world y coordinate
 | 
				
			||||||
 | 
					     * @param worldZ The world z coordinate
 | 
				
			||||||
 | 
					     * @param stride The stride of the data
 | 
				
			||||||
 | 
					     * @return The key
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private Long getRequestKey(int worldX, int worldY, int worldZ, int stride){
 | 
				
			||||||
 | 
					        return (long)HashUtils.cantorHash(worldY, worldZ, worldZ);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user