// Update is called once per frame private void Update() { DayNightCycle(); playerChunkCoord = worldData.GetChunkCoord(player.position); if (!playerChunkCoord.CompareCoords(playerLastChunkCoord)) { LoadChunks(player.position); } if (chunksToDraw.Count > 0) { chunksToDraw.Dequeue().CreateMesh(); } if (!applyingModifications) { ApplyModifications(); } if (chunksToUpdate.Count > 0) { UpdateChunks(); } }
private void SetPlayer() { spawnPoint = worldData.worldCenter + new Vector3(Random.Range(-8, 8), WorldData.chunkHeight + 50, Random.Range(-8, 8)); player.position = spawnPoint; playerLastChunkCoord = worldData.GetChunkCoord(player.position); }
private void Update() { playerChunkCoord = GetChunkCoordFromVector3(player.position); Shader.SetGlobalFloat("GlobalLightLevel", globalLightLevel); Camera.main.backgroundColor = Color.Lerp(night, day, globalLightLevel); if (!playerChunkCoord.Equals(playerLastChunkCoord)) { CheckViewDistance(); } if (chunksToCreate.Count > 0) { CreateChunk(); } if (chunksToDraw.Count > 0) { lock (chunksToDraw) { if (chunksToDraw.Peek().isEditable) { chunksToDraw.Dequeue().CreateMesh(); } } } if (Input.GetKeyDown(KeyCode.F3)) { debugScreen.SetActive(!debugScreen.activeSelf); } }
private void GenerateWorld() { for (int x = (VoxelData.worldSizeInChunks.x / 2) - GameManager.settings.ViewDistanceInChunks; x < (VoxelData.worldSizeInChunks.x / 2) + GameManager.settings.ViewDistanceInChunks; x++) { for (int z = (VoxelData.worldSizeInChunks.y / 2) - GameManager.settings.ViewDistanceInChunks; z < (VoxelData.worldSizeInChunks.y / 2) + GameManager.settings.ViewDistanceInChunks; z++) { //for (int x = 0; x < worldSizeInChunks.x; x++) //{ // for (int z = 0; z < worldSizeInChunks.y; z++) // { ChunkCoord newChunkCoord = new ChunkCoord(new int2(x, z)); chunks[x, z] = new Chunk(newChunkCoord, this, BlockDatabase, EntityManager, GameManager); chunksToCreate.Add(newChunkCoord); } } if (player != null) { player.SpawnPlayer(spawnLocation, BlockDatabase, this, GameManager); } CheckViewDistance(); }
void CreateChunk() { ChunkCoord c = chunksToCreate[0]; chunksToCreate.RemoveAt(0); chunkMap[new ChunkCoord(c.x, c.z)].Init(); }
private void Update() { playerChunkCoord = GetChunkCoordFromVector3(player.position); if (!playerChunkCoord.Equals(playerLastChunkCoord)) { CheckViewDistance(); } if (modifications.Count > 0 && !applyingModifications) { StartCoroutine(ApplyModifications()); } if (chunksToCreate.Count > 0) { CreateChunk(); } if (chunksToUpdate.Count > 0) { UpdateChunks(); } if (Input.GetKeyDown(KeyCode.F3)) { debugScreen.SetActive(!debugScreen.activeSelf); } }
private void FixedUpdate() { playerChunkCoord = GetChunkCoordFromVector3(player.position); if (!playerChunkCoord.Equals(playerLastChunkCoord)) { CheckViewDistance(); } if (chunksToCreate.Count > 0) { CreateChunk(); } if (chunksToDraw.Count > 0) { if (chunksToDraw.Peek().isEditable&& chunksToDraw.Peek().isVoxelMapPopulated) { Chunk hold = chunksToDraw.Dequeue(); hold.CreateMesh(); } else { Chunk hold = chunksToDraw.Dequeue(); chunksToDraw.Enqueue(hold); } } // Enable debug if (Input.GetKeyDown(KeyCode.F3)) { debugScreen.SetActive(!debugScreen.activeSelf); } }
void Update() { if (!playerLastChunkCoord.Equals(GetChunkCoord(player.position))) { CheckViewDistance(); playerLastChunkCoord = GetChunkCoord(player.position); worldGen.AttemptToSpawnStructures(); } if (chunksToCreate.Count > 0) { ChunkCoord cc = chunksToCreate[0]; chunksToCreate.RemoveAt(0); activeChunks.Add(cc); chunks[cc.x, cc.z].Init(); } if (subchunksToDraw.Count > 0) { lock (subchunksToDraw) { for (int i = 0; i < PerformanceSettings.subchunksToDrawPerFrame; i++) { if (subchunksToDraw.Count == 0) { break; } if (GetSubchunk(subchunksToDraw.Peek()).isEditable) { GetSubchunk(subchunksToDraw.Dequeue()).CreateMesh(); } } } } }
public RenderedHeightmap(ChunkCoord c, float[,] h, float[,,] sm, List<TreeInstance> ti) { coord = c; heightmap = h; splatmap = sm; treeInstances = ti; }
IEnumerator ApplyModifications() { applyingModifications = true; int count = 0; while (modifications.Count > 0) { VoxelMod v = modifications.Dequeue(); ChunkCoord c = GetChunkCoordFromVector3(v.position); if (chunks[c.x, c.z] == null) { chunks[c.x, c.z] = new Chunk(c, this, true); activeChunks.Add(c); } chunks[c.x, c.z].modifications.Enqueue(v); if (!chunksToUpdate.Contains(chunks[c.x, c.z])) { chunksToUpdate.Add(chunks[c.x, c.z]); } count++; if (count > 200) { count = 0; yield return(null); } } applyingModifications = false; }
public SubchunkCoord GetSubchunkCoord(Vector3 globalPos) { ChunkCoord superChunk = GetChunkCoord(globalPos); byte subchunkIndex = Subchunk.GetSubchunkIndex(Mathf.FloorToInt(globalPos.y)); return(new SubchunkCoord(superChunk, subchunkIndex)); }
public AnvilChunk(AnvilChunkManager manager, ChunkCoord coord) { _coord = coord; _manager = manager; _entities = new ChunkEntityCollection(new TagList()); _tileEntities = new Dictionary <BlockPos, TagCompound>(); }
void ApplyModifications() { applyingModifications = true; while (modifications.Count > 0) { Queue <CubeMod> queue = modifications.Dequeue(); while (queue.Count > 0) { CubeMod v = queue.Dequeue(); ChunkCoord c = GetChunkCoordFromVector3(v.position); if (chunks[c.x, c.z] == null) { chunks[c.x, c.z] = new Chunk(c, this, true); activeChunks.Add(c); } chunks[c.x, c.z].modifications.Enqueue(v); if (!chunksToUpdate.Contains(chunks[c.x, c.z])) { chunksToUpdate.Add(chunks[c.x, c.z]); } } } applyingModifications = false; }
public Chunk(ChunkCoord _coord) { coord = _coord; chunkObject = new GameObject(); meshFilter = chunkObject.AddComponent <MeshFilter>(); meshRenderer = chunkObject.AddComponent <MeshRenderer>(); materials[0] = World.Instance.material; materials[1] = World.Instance.transparentMaterial; meshRenderer.materials = materials; chunkObject.transform.SetParent(World.Instance.transform); chunkObject.transform.position = new Vector3(coord.x * VoxelData.ChunkWidth, 0f, coord.z * VoxelData.ChunkWidth); chunkObject.name = "Chunk " + coord.x + ", " + coord.z; position = chunkObject.transform.position; chunkData = World.Instance.worldData.RequestChunk(new Vector2Int((int)position.x, (int)position.z), true); chunkData.chunk = this; World.Instance.AddChunkToUpdate(this); if (World.Instance.settings.enableAnimatedChunks) { chunkObject.AddComponent <ChunkLoadAnimation>(); } }
void CreateChunk() { ChunkCoord c = chunksToCreate[0]; chunksToCreate.RemoveAt(0); chunks[c.x, c.z].init(); }
private void CreateChunk() { ChunkCoord chunk = chunksToCreate[0]; chunksToCreate.RemoveAt(0); chunks[chunk.x, chunk.z].CreateChunk(); }
public void AttemptToSpawnStructures() { List <int> chunksToRemoveFromList = new List <int>(); for (int i = 0; i < chunksToSpawnStructures.Count; i++) { ChunkCoord cc = chunksToSpawnStructures[i]; //Checks to see if chunk we are attempting spawning on is in the view distance. If not, skip if (Mathf.Abs(world.playerLastChunkCoord.x - cc.x) > VoxelData.ViewDistanceInChunks && Mathf.Abs(world.playerLastChunkCoord.z - cc.z) > VoxelData.ViewDistanceInChunks) { continue; } //Check neighbours to see if exist and voxels are populated if (AreNeighboursPopulated(cc)) { world.GetChunk(cc).PopulateSpawnableStructures(); chunksToRemoveFromList.Add(i); } } // Goes in reverse order so as to not disturb index. Removes chunks that have been populated for (int j = chunksToRemoveFromList.Count - 1; j >= 0; j--) { chunksToSpawnStructures.RemoveAt(j); } }
public void invalidateChunkAt(ref ChunkCoord neighbourNeedRefresh, bool Immediate) { lock (chunkDict) { chunkDict.TryGetValue(neighbourNeedRefresh, out neighbourNeedRefresh.chunk); } Chunk chunk = neighbourNeedRefresh.chunk; if (chunk != null) { if (Immediate) { chunk.PullChunkDataAndUpdateChunk(); neighbourNeedRefresh.chunk = null; } else { lock (threadingChunks) { // //ChunkUpdateThread.Interrupt(); // chunk.waitingForNewLoad = false; // threadingChunks.Insert(0, neighbourNeedRefresh); // //ChunkUpdateThread.Start(); new Thread(new ThreadStart(neighbourNeedRefresh.chunk.PullChunkDataAndUpdateChunk_)).Start(); } //todo } } neighbourNeedRefresh = null; }
public void SetChunk(Chunk chunk, ChunkCoord cc) { if (isChunkInWorld(cc)) { chunks[cc.x, cc.z] = chunk; } }
private void Start() { Debug.Log("Generating new world using seed: " + VoxelData.seed); worldData = SaveSystem.LoadWorld("New World"); //string jsonExport = JsonUtility.ToJson(settings); //Debug.Log(jsonExport); //File.WriteAllText(Application.dataPath + "/settings.cfg", jsonExport); string jsonImport = File.ReadAllText(Application.dataPath + "/settings.cfg"); settings = JsonUtility.FromJson <Settings>(jsonImport); Random.InitState(VoxelData.seed); Shader.SetGlobalFloat("minGlobalLightLevel", VoxelData.minLightLevel); Shader.SetGlobalFloat("maxGlobalLightLevel", VoxelData.maxLightLevel); if (settings.enableThreading) { ChunkUpdateThread = new Thread(new ThreadStart(ThreadedUpdate)); ChunkUpdateThread.Start(); } SetGlobalLightValue(); spawnPosition = new Vector3((VoxelData.WorldSizeInChunks * VoxelData.ChunkWidth) / 2f, VoxelData.ChunkHeight - 50f, (VoxelData.WorldSizeInChunks * VoxelData.ChunkWidth) / 2f); GenerateWorld(); playerLastChunkCoord = GetChunkCoordFromVector3(player.position); }
private void Update() { playerChunkCoord = GetChunkCoordFromVector3(player.Position); // Only update the chunks if the player has moved from the chunk they were previously on if (!playerChunkCoord.Equals(playerLastChunkCoord)) { CheckViewDistance(); } if (chunksToCreate.Count > 0 && !isCreatingChunks) { StartCoroutine(CreateChunks()); } if (!GameManager.settings.enableThreading) { if (chunksToUpdate.Count > 0) { UpdateChunks(); } } if (chunksToDraw.Count > 0) { if (chunksToDraw.Peek().IsEditable) { chunksToDraw.Dequeue().CreateMesh(BlockDatabase.blockMaterialAtlas); } } }
void ApplyModifications() { applyingModifications = true; while (modifications.Count > 0) { Queue <VoxelMod> queue = modifications.Dequeue(); while (queue.Count > 0) { VoxelMod v = queue.Dequeue(); ChunkCoord c = GetChunkCoordFromVector3(v.position); ChunkCoord newChunkCoord = new ChunkCoord(c.x, c.z); if (!chunkMap.ContainsKey(newChunkCoord)) { chunkMap.TryAdd(newChunkCoord, new Chunk(c, this)); chunksToCreate.Add(c); } chunkMap[newChunkCoord].modifications.Enqueue(v); } } applyingModifications = false; }
//from project settings the fixed update is set to 0.05 seconds ie. 20 tics per second //generating 1 chunk from queue every 0.05 seconds should offload some work when processing giant squares of new chunks at once //after trying it seems to not have impact on basic physics in game //if weird things wiith physics will occur probably switch to courutine private void FixedUpdate() { currentPlayerPosInChunk = ChunkCalculations.CalculateChunkFromWorldPos(player.position); if (currentChunkPos.posX != currentPlayerPosInChunk.posX || currentChunkPos.posZ != currentPlayerPosInChunk.posZ) { for (int i = -5; i <= 5; i++) { for (int j = -5; j <= 5; j++) { if (!VoxelData.chunkDictionary.ContainsKey(new ChunkCoord((int)(player.position.x / 15 + i), (int)(player.position.z / 15 + j)))) { int x = (int)(player.position.x / 15 + i); int z = (int)(player.position.z / 15 + j); if (toGenerateUniques.Add(new ChunkCoord(x, z))) { toGenerate.Enqueue(new ChunkCoord(x, z)); } } } } currentChunkPos = currentPlayerPosInChunk; } if (toGenerate.Count > 0) { toGenerateUniques.Remove(toGenerate.Peek()); SpawnChunk(toGenerate.Dequeue()); } }
private void Start() { worldData = SaveSystem.LoadWorld("Testing"); string jsonImport = File.ReadAllText(Application.dataPath + "/settings.cfg"); settings = JsonUtility.FromJson <Settings>(jsonImport); Random.InitState(VoxelData.seed); Shader.SetGlobalFloat("minGlobalLightLevel", VoxelData.minLightLevel); Shader.SetGlobalFloat("maxGlobalLightLevel", VoxelData.maxLightLevel); SetGlobalLightValue(); spawnPosition = new Vector3(VoxelData.WorldCentre, VoxelData.ChunkHeight - 50f, VoxelData.WorldCentre); LoadWorld(); //ApplyModifications(); GenerateWorld(); playerLastChunkCoord = GetChunkCoordFromVector3(player.position); if (settings.enableThreading) { ChunkUpdateThread = new Thread(new ThreadStart(ThreadedUpdate)); ChunkUpdateThread.Start(); } }
public void CheckViewDistance(int viewDistance, ChunkCoord coord) { for (int i = 0; i < activeChunks.Count; i++) { ChunkCoord c = activeChunks[i]; if ((c.x < coord.x - viewDistance || c.x > coord.x + viewDistance) || (c.z < coord.z - viewDistance || c.z > coord.z + viewDistance)) { GetChunkFromChunks(c).IsActive = false; activeChunks.RemoveAt(i); i--; } } for (int x = coord.x - viewDistance; x <= coord.x + viewDistance; x++) { for (int z = coord.z - viewDistance; z <= coord.z + viewDistance; z++) { ChunkCoord checkCoord = new ChunkCoord(x, z); Chunk current = GetChunkFromChunks(checkCoord); if (current == null) { QueueChunkForCreation(checkCoord); } else if (!current.IsActive) { current.IsActive = true; activeChunks.Add(checkCoord); } } } }
private void RepositionChunk(Chunk chunkToReposition, ChunkCoord coord) { chunkToReposition.waitingForNewLoad = true; //ChunkCoord from = new ChunkCoord(chunkToReposition.coord); lock (chunkDict) { chunkDict.Remove(chunkToReposition.coord); chunkDict.Add(coord, chunkToReposition); ChunkData data = chunkToReposition.getFilledData(); if (data != null) // 需要归还数据 回收 { lock (worldData) { if (!worldData.PeripheralChunkDataDict.ContainsKey(chunkToReposition.coord)) { worldData.PeripheralChunkDataDict.Add(chunkToReposition.coord, data); worldData.PeripheralChunkDatas.Add(data); } } } } chunkToReposition.Reposition(coord); //Debug.Log(string.Format("RepositionChunk From::{0}, {1} To::{2}, {3}", from.x, from.z, coord.x, coord.z)); lock (threadingChunks) { //threadingChunks.Insert(0, coord); threadingChunks.Remove(coord); threadingChunks.Add(coord); } //BoxDebug.DrawBox(new Vector3(coord.x*VoxelData.TileWidthUU, 40, coord.z*VoxelData.TileWidthUU), new Vector3(VoxelData.TileWidthUU, 10, VoxelData.TileWidthUU), Color.green, 6); }
/** * Render the chunk at the position chunkCenter. */ protected void loadChunk(Vector2 chunkCenter) { Chunk chunk; int details = getDetails(chunkCenter); ChunkCoord chunkCoord = getChunkCoord(chunkCenter); if (details == 0) { return; } //if the chunk does not exist, create the chunk if (!chunks.TryGetValue(chunkCoord, out chunk)) { chunk = new Chunk(chunkCenter, mapGenerator, materail); chunks.Add(chunkCoord, chunk); } //check the levelOfDetail of the chunks that are connected to this chunk bool lowResTop = getDetails(new Vector2(chunkCenter.x, chunkCenter.y + Chunk.size * h_sqrt_3)) > details; bool lowResBottom = getDetails(new Vector2(chunkCenter.x, chunkCenter.y - Chunk.size * h_sqrt_3)) > details; bool lowResLeft = getDetails(new Vector2(chunkCenter.x - Chunk.size, chunkCenter.y)) > details; bool lowResRight = getDetails(new Vector2(chunkCenter.x + Chunk.size, chunkCenter.y)) > details; chunk.visible(details, lowResTop, lowResRight, lowResBottom, lowResLeft); }
//generates world from player position when instance of script is created private void Start() { spawnPosition = new Vector3((VoxelData.WorldSizeInChunks * VoxelData.ChunkWidth) / 2f, VoxelData.ChunkHeight - 50f, (VoxelData.WorldSizeInChunks * VoxelData.ChunkWidth) / 2f); Random.InitState(seed); GenerateWorld(); playerLastChunkCoord = GetChunkCoordFromVector3(player.transform.position); }
void ApplyModifications() { applyingModifications = true; while (modifications.Count > 0) { Queue <VoxelMod> queue = modifications.Dequeue(); while (queue.Count > 0) { VoxelMod v = queue.Dequeue(); ChunkCoord c = GetChunkCoordFromVector3(v.position); if (chunks[c.x, c.z] == null) { chunks[c.x, c.z] = new Chunk(c, this); chunksToCreate.Add(c); } chunks[c.x, c.z].modifications.Enqueue(v); } } applyingModifications = false; }
private void Update() { playerChunkCoord = GetChunkCoordFromVector3(player.position); if (!playerChunkCoord.Equals(playerLastChunkCoord)) { CheckViewDistance(); } if (chunksToDraw.Count > 0) { chunksToDraw.Dequeue().CreateMesh(); } if (Input.GetKeyDown(KeyCode.F3)) { DebugScreen.SetActive(!DebugScreen.activeSelf); } if (!settings.EnableThreading) { if (!applyingModifications) { ApplyModifications(); } if (chunksToUpdate.Count > 0) { UpdateChunks(); } } if (Input.GetKeyDown(KeyCode.F5)) { SaveSystem.SaveWorld(worldData); } }
private void Start() { Debug.Log($"Seed id: {VoxelData.seed}"); worldData = SaveSystem.LoadWorld("Prototype"); ImportSettings(); UnityEngine.Random.InitState(VoxelData.seed); Shader.SetGlobalFloat("MinGlobalLightLevel", VoxelData.minGlobalLightLevel); Shader.SetGlobalFloat("MaxGlobalLightLevel", VoxelData.maxGlobalLightLevel); LoadWorld(); SetGlobalLightValue(); spawnPosition = new Vector3(VoxelData.WorldCenter, VoxelData.ChunkHeight - 50, VoxelData.WorldCenter); player.position = spawnPosition; CheckViewDistance(); playerChunkCoord = GetChunkCoordFromVector3(player.position); playerLastChunkCoord = playerChunkCoord; if (settings.EnableThreading) { chunkUpdateThread = new Thread(new ThreadStart(ThreadedUpdate)); chunkUpdateThread.Start(); } else { } }
internal FluidType GetLiquidType(ChunkCoord chunkCoord) { return LiquidTypes[chunkCoord.ChunkX, chunkCoord.ChunkY]; }
void stitchTerrain(TerrainData tData, ChunkCoord c) { TerrainData left = (TerrainData)chunks[new ChunkCoord(c.x - 1, c.z)]; TerrainData right = (TerrainData)chunks[new ChunkCoord(c.x + 1, c.z)]; TerrainData top = (TerrainData)chunks[new ChunkCoord(c.x, c.z - 1)]; TerrainData bottom = (TerrainData)chunks[new ChunkCoord(c.x, c.z + 1)]; if (left != null) { var seam = left.GetHeights(chunkResolution - 1, 0, 1, chunkResolution); tData.SetHeights(0, 0, seam); } if (right != null) { var seam = right.GetHeights(0, 0, 1, chunkResolution); tData.SetHeights(chunkResolution - 1, 0, seam); } if (top != null) { var seam = top.GetHeights(0, chunkResolution-1, chunkResolution, 1); tData.SetHeights(0, 0, seam); } if (bottom != null) { var seam = bottom.GetHeights(0, 0, chunkResolution, 1); tData.SetHeights(0, chunkResolution - 1, seam); } }
void ensureChunk(ChunkCoord c, bool async) { if (outstanding < threads) { if (!chunks.Contains(c)) { chunks.Add(c, null); if (async) { outstanding += 1; this.StartCoroutineAsync(generateHeightmapAsync(c)); } else { generateHeightmapSync(c); } } } }
IEnumerator generateHeightmapAsync(ChunkCoord c) { // This is called on a background thread. It needs to build the // heightmap array (and possibly some other stuff) and push it onto the // queue when ready. generateHeightmapSync(c); yield return Ninja.JumpToUnity; print("Outstanding: " + outstanding); outstanding -= 1; yield return Ninja.JumpBack; }
void generateHeightmapSync(ChunkCoord c) { int heightmapResolution = chunkResolution + (2 * fringeSize); float[,] heightmap = new float[heightmapResolution, heightmapResolution]; noiseHeightmap(c, heightmap); erodeHeightmap(c, heightmap); heightmap = extractChunk(heightmap); var splatmap = textureHeightmap(heightmap); // Done, push it into the queue so the main thread can process it into // a terrain object. heightmapQueue.Enqueue(new RenderedHeightmap(c, heightmap, splatmap)); }
internal float GetInterpolatedHeight(ChunkCoord chunkCoord, PointX2D coord, HeightMapFraction heightMapFraction) { // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid // +--------------> X // | h1--------h2 Coordinates are: // | | | | h1 0,0 // | | 1 | 2 | h2 0,1 // | |----h5---| h3 1,0 // | | 3 | 4 | h4 1,1 // | | | | h5 1/2,1/2 // | h3--------h4 // V Y if (HeightMaps == null) return float.NaN; var heightMap = HeightMaps[chunkCoord.ChunkX, chunkCoord.ChunkY]; if (heightMap == null) return float.NaN; var medianHeight = HalfUtils.Unpack(heightMap.MedianHeight); if (heightMap.IsFlat) return medianHeight; // Fixme: Indexing is backwards. var heightX = (coord.Y == TerrainConstants.UnitsPerChunkSide) ? (TerrainConstants.UnitsPerChunkSide - 1) : coord.Y; var heightY = (coord.X == TerrainConstants.UnitsPerChunkSide) ? (TerrainConstants.UnitsPerChunkSide - 1) : coord.X; // Determine what quad we're in var xf = heightMapFraction.FractionX; var yf = heightMapFraction.FractionY; float topLeft, topRight, bottomLeft, bottomRight; if (xf < 0.5f) { if (yf < 0.5) { // Calc the #1 quad // +--------------> X // | h1--------h2 Coordinates are: // | | | | h1 0,0 // | | 1 | | h2 0,1 // | |----h5---| h3 1,0 // | | | | h4 1,1 // | | | | h5 1/2,1/2 // | h3--------h4 // V Y var packed1 = heightMap.OuterHeightDiff[heightX, heightY]; var packed2 = heightMap.OuterHeightDiff[heightX, heightY + 1]; var packed3 = heightMap.OuterHeightDiff[heightX + 1, heightY]; var packed5 = heightMap.InnerHeightDiff[heightX, heightY]; var h1 = HalfUtils.Unpack(packed1); var h2 = HalfUtils.Unpack(packed2); var h3 = HalfUtils.Unpack(packed3); var h5 = HalfUtils.Unpack(packed5); topLeft = h1; topRight = (h1 + h2)/2.0f; bottomLeft = (h1 + h3)/2.0f; bottomRight = h5; } else { // Calc the #3 quad // +--------------> X // | h1--------h2 Coordinates are: // | | | | h1 0,0 // | | | | h2 0,1 // | |----h5---| h3 1,0 // | | 3 | | h4 1,1 // | | | | h5 1/2,1/2 // | h3--------h4 // V Y var packed1 = heightMap.OuterHeightDiff[heightX, heightY]; var packed3 = heightMap.OuterHeightDiff[heightX + 1, heightY]; var packed4 = heightMap.OuterHeightDiff[heightX + 1, heightY + 1]; var packed5 = heightMap.InnerHeightDiff[heightX, heightY]; var h1 = HalfUtils.Unpack(packed1); var h3 = HalfUtils.Unpack(packed3); var h4 = HalfUtils.Unpack(packed4); var h5 = HalfUtils.Unpack(packed5); topLeft = (h1 + h3) / 2.0f; topRight = h5; bottomLeft = h3; bottomRight = (h3 + h4) / 2.0f; yf -= 0.5f; } } else { if (yf < 0.5) { // Calc the #2 quad // +--------------> X // | h1--------h2 Coordinates are: // | | | | h1 0,0 // | | | 2 | h2 0,1 // | |----h5---| h3 1,0 // | | | | h4 1,1 // | | | | h5 1/2,1/2 // | h3--------h4 // V Y var packed1 = heightMap.OuterHeightDiff[heightX, heightY]; var packed2 = heightMap.OuterHeightDiff[heightX, heightY + 1]; var packed4 = heightMap.OuterHeightDiff[heightX + 1, heightY + 1]; var packed5 = heightMap.InnerHeightDiff[heightX, heightY]; var h1 = HalfUtils.Unpack(packed1); var h2 = HalfUtils.Unpack(packed2); var h4 = HalfUtils.Unpack(packed4); var h5 = HalfUtils.Unpack(packed5); topLeft = (h1 + h2) / 2.0f; topRight = h2; bottomLeft = h5; bottomRight = (h2 + h4) / 2.0f; xf -= 0.5f; } else { // Calc the #4 quad // +--------------> X // | h1--------h2 Coordinates are: // | | | | h1 0,0 // | | | | h2 0,1 // | |----h5---| h3 1,0 // | | | 4 | h4 1,1 // | | | | h5 1/2,1/2 // | h3--------h4 // V Y var packed2 = heightMap.OuterHeightDiff[heightX, heightY + 1]; var packed3 = heightMap.OuterHeightDiff[heightX + 1, heightY]; var packed4 = heightMap.OuterHeightDiff[heightX + 1, heightY + 1]; var packed5 = heightMap.InnerHeightDiff[heightX, heightY]; var h2 = HalfUtils.Unpack(packed2); var h3 = HalfUtils.Unpack(packed3); var h4 = HalfUtils.Unpack(packed4); var h5 = HalfUtils.Unpack(packed5); topLeft = h5; topRight = (h2 + h4) / 2.0f; bottomLeft = (h3 + h4) / 2.0f; bottomRight = h4; xf -= 0.5f; yf -= 0.5f; } } //var heightDiff = InterpolateTriangle(ref vec1, ref vec2, ref vec3, heightMapFraction); var heightDiff = BilinearInterpolate(ref topLeft, ref topRight, ref bottomLeft, ref bottomRight, ref xf, ref yf); return medianHeight + heightDiff; }
public RenderedHeightmap(ChunkCoord c, float[,] h, float[,,] sm) { coord = c; heightmap = h; splatmap = sm; }
internal void DumpChunk(ChunkCoord chunkCoord) { if (HeightMaps == null) return; var heightMap = HeightMaps[chunkCoord.ChunkX, chunkCoord.ChunkY]; if (heightMap == null) return; var medianHeight = HalfUtils.Unpack(heightMap.MedianHeight); var fileName = String.Format("Chunk_{0}_{1}.txt", chunkCoord.ChunkX, chunkCoord.ChunkY); var filePath = Path.Combine("C:\\Users\\Nate\\Desktop", fileName); var writer = new StreamWriter(filePath); writer.WriteLine(String.Format("MedianHeight: {0}", medianHeight)); if (heightMap.IsFlat) { writer.Close(); return; } writer.Write(writer.NewLine); for (var row = 0; row < 9; row++) { for (var col = 0; col < 9; col++) { var packed = heightMap.OuterHeightDiff[row, col]; var unpacked = HalfUtils.Unpack(packed); var value = Math.Round(unpacked, 2); if (value >= 0) writer.Write(" "); writer.Write(String.Format("{0:00.00} ", value)); } writer.Write(writer.NewLine); writer.Write(writer.NewLine); // write 8 floats if (row < 8) { writer.Write(" "); for (var col = 0; col < 8; col++) { var packed = heightMap.InnerHeightDiff[row, col]; var unpacked = HalfUtils.Unpack(packed); var value = Math.Round(unpacked, 2); if (value >= 0) writer.Write(" "); writer.Write(String.Format("{0:00.00} ", value)); } writer.Write(writer.NewLine); writer.Write(writer.NewLine); } } writer.Close(); }
void noiseHeightmap(ChunkCoord c, float[,] heightmap) { int width = heightmap.GetLength(0); int height = heightmap.GetLength(1); for (int z = 0; z < height; z++) { for (int x = 0; x < width; x++) { heightmap[z, x] = noise.Get( x + getWorldOX(c), z + getWorldOZ(c)); } } }
internal float GetLiquidHeight(ChunkCoord chunkCoord, PointX2D pointX2D) { if (!LiquidProfile[chunkCoord.ChunkX, chunkCoord.ChunkY]) return float.MinValue; var heightMap = HeightMaps[chunkCoord.ChunkX, chunkCoord.ChunkY]; var liquidHeights = heightMap.LiquidHeight; return (liquidHeights == null) ? float.MinValue : liquidHeights[pointX2D.X, pointX2D.Y]; }
void erodeHeightmap(ChunkCoord c, float[,] heightmap) { reverseThermalEroder.Erode(heightmap); hydraulicEroder.Erode(heightmap); thermalEroder.Erode(heightmap); }
float[,,] textureHeightmap(ChunkCoord c, float[,] heightmap, int[,] randomArray) { // determain the mix of textures 1, 2, 3 and 4 to use var splatmap = new float[ heightmap.GetLength(0), heightmap.GetLength(1), diffuses.Length]; splatmap = texturer.Texture( heightmap, splatmap, randomArray, getWorldOX(c), getWorldOZ(c)); return splatmap; }
int getWorldOX(ChunkCoord c) { return (c.x * chunkResolution - c.x - fringeSize); }
int getWorldOZ(ChunkCoord c) { return (c.z * chunkResolution - c.z - fringeSize); }
void noiseHeightmap(ChunkCoord c, float[,] heightmap) { int ox = c.x * chunkResolution - c.x - fringeSize; int oz = c.z * chunkResolution - c.z - fringeSize; int width = heightmap.GetLength(0); int height = heightmap.GetLength(1); for (int z = 0; z < height; z++) { for (int x = 0; x < width; x++) { heightmap[z, x] = noise.Get(ox + x, oz + z); } } }
void ensureChunk(ChunkCoord c, bool async) { if (outstanding < threads) { if (!chunks.Contains(c)) { chunks.Add(c, null); // RandomRangeInt can only be called from the main thread. // So we need to pass an array of random numbers to the child thread int heightmapResolution = chunkResolution + (2 * fringeSize); var randomArray = new int[heightmapResolution, heightmapResolution]; for (var i = 0; i < heightmapResolution; i++) { for (var j = 0; j < heightmapResolution; j++) { randomArray[i,j] = UnityEngine.Random.Range(0, 100000); } } if (async) { outstanding += 1; this.StartCoroutineAsync(generateHeightmapAsync(c, randomArray)); } else { generateHeightmapSync(c, randomArray); } } } }