package net.kennux.cubicworld.voxel; import java.util.ArrayList; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import net.kennux.cubicworld.CubicWorld; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.g3d.ModelBatch; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.math.Vector3; /** * Chunk grid implementation. * This is basically the same as a hashmap only with a ChunkKey as key. * * @author KennuX * */ public class ChunkManager { /** * This hashmap contains all chunks. */ private ConcurrentHashMap<ChunkKey, VoxelChunk> chunks = new ConcurrentHashMap<ChunkKey, VoxelChunk>(); /** * Adds a chunk to the grid. * * @param key * @param chunk */ public void put(ChunkKey key, VoxelChunk chunk) { this.chunks.put(key, chunk); } /** * Returns true if the ChunkGrid contains the given chunk key. Use this only * if you just need to check if the key exists. If you want to get the chunk * just call get() and check for null. * * @param key */ public boolean containsKey(ChunkKey key) { return this.chunks.containsKey(key); } /** * Adds a chunk to the grid. Returns null if the key was not found. * * @param key * @param chunk */ public VoxelChunk get(ChunkKey key) { return this.chunks.get(key); } /** * Performs a bounds check for all loaded chunks. chunkPos is the position * of the player (global chunkspace), radius the chunk loading radius. * * @param middle * @param radius * @return */ public ChunkKey[] getChunksNotInside(Vector3 chunkPos, int radius) { ArrayList<ChunkKey> chunksNotInside = new ArrayList<ChunkKey>(); for (ChunkKey key : this.chunks.keySet()) { // Do radius check if (key != null) if (new Vector3(chunkPos).sub(new Vector3(key.x, chunkPos.y, key.z)).len() > radius) chunksNotInside.add(key); } // Return the chunks not inside this radius. return chunksNotInside.toArray(new ChunkKey[chunksNotInside.size()]); } /** * Performs a bounds check for all loaded chunks. chunkPositions are the * positions of the players (global chunkspace), radius the chunk loading * radius. * * @param middle * @param radius * @return */ public ChunkKey[] getChunksNotInside(Vector3[] chunkPositions, int radius) { ArrayList<ChunkKey> chunksNotInside = new ArrayList<ChunkKey>(); for (ChunkKey key : this.chunks.keySet()) { boolean isInRadius = true; // Do radius check if (key != null) for (Vector3 chunkPos : chunkPositions) if (new Vector3(chunkPos).sub(new Vector3(key.x, chunkPos.y, key.z)).len() > radius) isInRadius = false; if (!isInRadius) { chunksNotInside.add(key); } } // Return the chunks not inside this radius. return chunksNotInside.toArray(new ChunkKey[chunksNotInside.size()]); } /** * Returns all keys in this instance (only copies of them). * * @return */ public ChunkKey[] getKeys() { Set<ChunkKey> keySet = this.chunks.keySet(); return keySet.toArray(new ChunkKey[keySet.size()]); } /** * Removes the given chunk key from the grid. * * @param key */ public void remove(ChunkKey key) { VoxelChunk chunk = this.chunks.get(key); this.chunks.remove(key); if (chunk != null) chunk.dispose(); } /** * Calls the render and renderModels method on all chunk objects. * * @param cam * @param shader */ public void render(Camera cam, ShaderProgram shader, ModelBatch modelBatch) { // Voxel render pass for (VoxelChunk c : this.chunks.values()) { if (c != null) c.render(cam, shader); } // Model render pass modelBatch.begin(cam); for (VoxelChunk c : this.chunks.values()) { if (c != null) c.renderModels(cam, modelBatch); } modelBatch.end(); } /** * Calls the update and simulate method on all chunk objects. */ public void update() { for (VoxelChunk c : this.chunks.values()) { if (c != null) { c.simulate(); c.update(); } } } /** * Returns true if all chunks are ready for rendering. */ public boolean allChunksReady() { boolean allReady = true; for (VoxelChunk c : this.chunks.values()) { if (c != null && !c.isReadyForRendering()) allReady = false; } return allReady; } }