//Disables itself if far enough public void UpdateVisibilityOrLOD() { float viewerDistanceFromNearestEdge = Mathf.Sqrt(worldBounds.SqrDistance(viewerPosition)); bool shouldBeVisible = viewerDistanceFromNearestEdge <= viewerSightLimit; if (!shouldBeVisible && assignedChunkGO != null) //Needed because this method can also be called from callbacks { disableChunkGO(); } //Going through all the LOD limits (but the last one, because the player cannot see past that one, and choosing the corrent LOD if (shouldBeVisible && hasRecievedMapData) { int lodIndex = 0; //Finding the correct LOD... for (int i = 0; i < LODLimits.Length - 1; i++) { if (viewerDistanceFromNearestEdge > LODLimits[i].distanceUpperBound) { lodIndex = i + 1; } else { break; } } if (currentLevelOfDetailIndex != lodIndex) { LODMesh lodMesh = levelOfDetailMeshes[lodIndex]; if (lodMesh.hasRecievedMesh) { //Now that there's a mesh ready, we can request for a gameobject to represent us if (assignedChunkGO == null) { assignedChunkGO = FindObjectOfType <TerrainChunkPooler>().supplyTCObject(); setUpChunkGO(); } //Setting the mesh currentLevelOfDetailIndex = lodIndex; assignedChunkGO.setMesh(lodMesh.mesh); artifactManager.enableArtifacts(lodMesh.meshLevelOfDetail); } else if (!lodMesh.hasRequestedMesh) { lodMesh.RequestMesh(mapData); } //Otherwise we'll just have to wait and see if data has been recieved yet. //UpdateVisibilityOrLOD will be called from a callback when a mesh is recieved. } if (shouldBeVisible) { terrainChunksVisibleLastFrame.Add(this); } } }
public static void updateChunk(ChunkPos cp, Action <BlockType[, , ], Action <int, int, int, BlockType> > cb) { TerrainChunkObject chunkObject = chunks[cp]; BlockType[,,] blocks = chunkObject.Chunk.blocks; HashSet <TerrainChunkObject> changed = new HashSet <TerrainChunkObject>(); cb(blocks, (x, y, z, block) => { updateChunkNearbyHelper(cp, changed, x, y, z, block); if (x == 1) { updateChunkNearbyHelper(new ChunkPos(cp.x - TerrainChunk.chunkWidth, cp.z), changed, TerrainChunk.chunkWidth + 1, y, z, block); } if (z == 1) { updateChunkNearbyHelper(new ChunkPos(cp.x, cp.z - TerrainChunk.chunkWidth), changed, x, y, TerrainChunk.chunkWidth + 1, block); } if (x == 1 + TerrainChunk.chunkWidth - 1) { updateChunkNearbyHelper(new ChunkPos(cp.x + TerrainChunk.chunkWidth, cp.z), changed, 0, y, z, block); } if (z == 1 + TerrainChunk.chunkWidth - 1) { updateChunkNearbyHelper(new ChunkPos(cp.x, cp.z + TerrainChunk.chunkWidth), changed, x, y, 0, block); } }); foreach (var chunk in changed) { chunk.UpdateChunk(); } }
public static BlockType getBlock(ChunkPos pos, int x, int y, int z) { while (x < 0) { x += TerrainChunk.chunkWidth; pos = new ChunkPos(pos.x - TerrainChunk.chunkWidth, pos.z); } while (x >= TerrainChunk.chunkWidth) { x -= TerrainChunk.chunkWidth; pos = new ChunkPos(pos.x + TerrainChunk.chunkWidth, pos.z); } while (z < 0) { z += TerrainChunk.chunkWidth; pos = new ChunkPos(pos.x, pos.z - TerrainChunk.chunkWidth); } while (z >= TerrainChunk.chunkWidth) { z -= TerrainChunk.chunkWidth; pos = new ChunkPos(pos.x, pos.z + TerrainChunk.chunkWidth); } if (!chunks.ContainsKey(pos)) { return(BlockType.Air); } TerrainChunkObject chunk = chunks[pos]; return(chunk.Chunk.blocks[x + 1, y, z + 1]); }
TerrainChunkObject LoadChunk(ChunkPos cp, bool instant) { if (chunks.ContainsKey(cp)) { return(chunks[cp]); } TerrainChunk chunk = TerrainChunkGenerator.request(cp, instant); if (chunk == null) { return(null); } int xPos = cp.x; int zPos = cp.z; GameObject chunkGO = Instantiate(terrainChunkPrefab, new Vector3(xPos, 0, zPos), Quaternion.identity); TerrainChunkObject chunkObject = chunkGO.GetComponent <TerrainChunkObject>(); chunkObject.transform.parent = transform; chunkObject.name = "Chunk:" + cp; chunkObject.BuildMesh(chunk); WaterChunk wat = chunkObject.transform.GetComponentInChildren <WaterChunk>(); wat.SetLocs(chunk.blocks, chunkObject.Chunk); wat.BuildMesh(); chunks.Add(cp, chunkObject); return(chunkObject); }
public void disableChunkGO() { if (assignedChunkGO == null) { return; } assignedChunkGO.release(); artifactManager.disableAtifacts(); assignedChunkGO = null; }
/// <summary> /// raise the heightmap of the terrain and rebuild the mesh afterwards /// uses the BrushSizeSlider value for it's size /// </summary> /// <param name="centerX">x position of the center point</param> /// <param name="centerY">y position of the center point</param> public void RaiseTerrain(int centerX, int centerY, TerrainChunkObject targetChunk) { int r = TerrainTerraforming.Singleton.brushSize; //brush radius float s = TerrainTerraforming.Singleton.brushStrength; //brush strength int ox = centerX, oy = centerY; // origin int worldSize = WORLD_CHUNK_SIZE * TerrainChunkObject.TERRAIN_CHUNK_TILE_SIZE; //total world size List<TerrainChunkObject> affectedChunks = new List<TerrainChunkObject>(); //the chunks that will need to be rebuilt //raise the heightmap floats for (int x = -r; x < r; x++) { int height = (int)Mathf.Sqrt(r * r - x * x); for (int y = -height; y < height; y++) { if (x + ox >= 0 && x + ox < worldSize && y + oy >= 0 && y + oy < worldSize) { m_globalheightMap.AddToFloat(x + ox, y + oy, s); } } } int globalX = ox; //global x of the circle's center int globalY = oy; //global y of the circle's center //calculate affected chunks for (int width = 0; width < WORLD_CHUNK_SIZE; width++) { for (int length = 0; length < WORLD_CHUNK_SIZE; length++) { int currentGlobalX = m_terrainChunks[width, length].worldX * TerrainChunkObject.TERRAIN_CHUNK_TILE_SIZE; int currentGlobalY = m_terrainChunks[width, length].worldY * TerrainChunkObject.TERRAIN_CHUNK_TILE_SIZE; if (globalX + r > currentGlobalX && globalY + r > currentGlobalY) if (globalX - r < (currentGlobalX + TerrainChunkObject.TERRAIN_CHUNK_TILE_SIZE) && globalY - r < (currentGlobalY + TerrainChunkObject.TERRAIN_CHUNK_TILE_SIZE)) affectedChunks.Add(m_terrainChunks[width, length]); //reset the highlighing color m_terrainChunks[width, length].GetComponent<Renderer>().material.color = Color.white; } } //apply changed height floats for (int x = 0; x < WORLD_CHUNK_SIZE; x++) { for (int y = 0; y < WORLD_CHUNK_SIZE; y++) { m_chunkHeigtmaps[x, y].SetHeightMap(m_globalheightMap.GetPortion(x * TerrainChunkObject.TERRAIN_CHUNK_TILE_SIZE, y * TerrainChunkObject.TERRAIN_CHUNK_TILE_SIZE, TerrainChunkObject.TERRAIN_CHUNK_TILE_SIZE), m_globalheightMap.highestFloat, m_globalheightMap.lowestFloat, m_globalheightMap.totalStrength); } } //rebuild affected chunks for (int i = 0; i < affectedChunks.Count; i++) { affectedChunks[i].RebuildObject(); if(renderChunkUpdates) affectedChunks[i].GetComponent<Renderer>().material.color = Color.blue; } }