public void MakeEroded(LiquidSettings liquidSettings, int dropCount) { for (int i = 0; i < dropCount; i++) { int xInd = Random.Range(0, map.resolution); int yInd = Random.Range(0, map.resolution); Droplet drop = new Droplet(liquidSettings, xInd, yInd, 1, 0); ErodeDroplet(drop); } }
public bool CanDropletRun(Droplet droplet) { if (droplet.lifetime >= droplet.settings.maxLifetime) { return(false); } if (droplet.volume <= 0) { return(false); } return(true); }
// Return true if x2/y2 is lower than x1/y1 // Return false if higher, same height, or out of bounds // https://stackoverflow.com/questions/49640250/calculate-normals-from-heightmap public Vector3 GetFlowDir(Droplet drop) { int xInd = (int)drop.xPos; int yInd = (int)drop.yPos; // Get the heights of the 4 bordering cells // If out of bounds, use height of map[y,x] float negX = GetHeightNegX(xInd, yInd); float negY = GetHeightNegY(xInd, yInd); float posX = GetHeightPosX(xInd, yInd); float posY = GetHeightPosY(xInd, yInd); Vector3 normal = new Vector3(negX - posX, negY - posY, -4); return(normal.normalized); }
private void ErodeDirt(float[,] brush, int xInd, int yInd, Droplet drop, float erodeAmount) { //float[,] brush = GetErosionBrush(drop.settings, erodeAmount); float lowestNeighborHeight = GetHeightOfLowestNeighbor(xInd, yInd); int xLen_map = map.resolution; int yLen_map = map.resolution; int xLen_brush = brush.GetLength(1); int yLen_brush = brush.GetLength(0); int xOffset = -(xLen_brush / 2); int yOffset = -(yLen_brush / 2); for (int y = 0; y < yLen_brush; y++) { for (int x = 0; x < xLen_brush; x++) { int xInd_map = xInd + xOffset + x; int yInd_map = yInd + yOffset + y; // Out of bounds if (!IsInBounds(xLen_map, yLen_map, xInd_map, yInd_map)) { continue; } // Too low to erode float heightDif = map[yInd_map, xInd_map].GroundHeight - lowestNeighborHeight; if (heightDif <= 0) { continue; } // Only erode down to lowest neighbor at most float actualErodeAmount = Mathf.Min(brush[y, x] * erodeAmount, heightDif); drop.dirt += actualErodeAmount; //map[yInd_map, xInd_map][TerrainValTypes.Rock] -= actualErodeAmount; map[yInd_map, xInd_map].RemoveGround(actualErodeAmount); } } }
public void ErodeDroplet(Droplet drop) { int xLen = map.resolution; int yLen = map.resolution; float[,] brush = drop.settings.GetErosionBrush(); while (CanDropletRun(drop)) { drop.lifetime++; int xInd = (int)drop.xPos; int yInd = (int)drop.yPos; // If in a pit, fast track evaporation // Deposit dirt up to height of lowest neighbor, reduce liquid volume proportionally if (!IsMovementPossible(xInd, yInd)) { float neighborHeight = GetHeightOfLowestNeighbor(xInd, yInd); float depositAmount = Mathf.Min(drop.dirt, neighborHeight - map[yInd, xInd].GroundHeight); // Lower liquid volume proportionally and deposit dirt drop.volume *= 1 - (drop.dirt / depositAmount); //map[yInd, xInd] += depositAmount; continue; //break; } Vector3 downDir = GetFlowDir(drop).Zof(0).normalized; drop.xPos = drop.xPos + downDir.x; drop.yPos = drop.yPos + downDir.y; int xIndNew = (int)drop.xPos; int yIndNew = (int)drop.yPos; // Verify new location is in bounds if (!IsInBounds(xLen, yLen, xIndNew, yIndNew)) { break; } // Hasn't moved enough to do a calculation this iteration if (!HasIndChanged(xInd, yInd, xIndNew, yIndNew)) { continue; } float dHeight = GetHeightDif(xInd, yInd, xIndNew, yIndNew); //TODO: What exactly is this doing? float totalCapacity = Mathf.Max( drop.settings.minDirt, drop.settings.dirtCapacity * -dHeight /* * drop.volume*/); // Deposit dirt if (drop.dirt > totalCapacity) { float dirtAmount = (drop.dirt - totalCapacity) * drop.settings.depositSpeed; DepositDirt(xInd, yInd, drop, dirtAmount); } // Erode dirt else { float dirtAmount = Mathf.Min((totalCapacity - drop.dirt) * drop.settings.erodeSpeed, -dHeight); ErodeDirt(brush, xInd, yInd, drop, dirtAmount); } // Slowly reduce amount of water drop.volume *= (1 - drop.settings.evapSpeed); } }
private void DepositDirt(int xInd, int yInd, Droplet drop, float depositAmount) { drop.dirt -= depositAmount; //map[yInd, xInd][TerrainValTypes.Rock] += depositAmount; map[yInd, xInd].AddGround(depositAmount); }