public void AddTrees(ref WorldData worldData, int seed) { List <TreeData> treeData = new List <TreeData>(); System.Random rng = new System.Random(seed); int size = TerrainGenerator.size * (int)treesPerVoxel; float[,] landNoise = Procedural.NoiseMap(seed, TerrainGenerator.size, TerrainGenerator.noiseScale, terrainGenerator.multiplier); float[,] treeNoise = Procedural.NoiseMap(seed + 1, size, treeNoiseScale, AnimationCurve.Linear(0f, 0f, 1f, 1f)); for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { Coords voxelCoords = new Coords(Mathf.FloorToInt(x / treesPerVoxel), Mathf.FloorToInt(y / treesPerVoxel)); bool adjacentOcean = Util.AdjacentProperty(Util.CoordsToVoxels(worldData.voxelData, Util.GetAdjacent(voxelCoords, true)), "isOcean"); bool adjacentLake = Util.AdjacentProperty(Util.CoordsToVoxels(worldData.voxelData, Util.GetAdjacent(voxelCoords, true)), "isLake"); if (worldData.voxelData[voxelCoords.x, voxelCoords.y].isLand && !worldData.voxelData[voxelCoords.x, voxelCoords.y].occupied && !adjacentOcean && (treeNoise[x, y] < treeThreshold || adjacentLake) && rng.Next(0, 1000) / 1000f < treeNoise[x, y] * landNoise[voxelCoords.x, voxelCoords.y] * treeDensity) { int treeType = rng.Next(0, treeObjects.Length); Coords treeCoords = new Coords(x, y); float rotation = rng.Next(0, 360); TreeData tree = new TreeData(treeCoords, voxelCoords, treeType, rotation); treeData.Add(tree); worldData.voxelData[voxelCoords.x, voxelCoords.y].occupied = true; worldData.voxelData[voxelCoords.x, voxelCoords.y].hasTrees = true; } } } worldData.treeData = treeData; }
public void AddRocks(ref WorldData worldData, int seed) { List <RockData> rockData = new List <RockData>(); System.Random rng = new System.Random(seed); int size = TerrainGenerator.size; float[,] noiseMap = Procedural.NoiseMap(seed + 2, size, rockNoiseScale, AnimationCurve.Linear(0f, 0f, 1f, 1f)); for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { Coords coords = new Coords(x, y); bool adjacentOcean = Util.AdjacentProperty(Util.CoordsToVoxels(worldData.voxelData, Util.GetAdjacent(coords, true)), "isOcean"); if (worldData.voxelData[x, y].isLand && !adjacentOcean && !worldData.voxelData[x, y].occupied && noiseMap[x, y] < rockThreshold) { RockData rock = new RockData(coords, rng.Next(0, rockObjects.Length), rng.Next(0, 360)); rockData.Add(rock); worldData.voxelData[coords.x, coords.y].occupied = true; worldData.voxelData[coords.x, coords.y].navigable = false; } } } worldData.rockData = rockData; }
public VoxelData[,] GenerateVoxelData(int seed) { System.Random rng = new System.Random(seed); VoxelData[,] voxelData = new VoxelData[size, size]; float[,] landNoise = Procedural.NoiseMap(seed, size, noiseScale, multiplier); float[,] colorNoise = Procedural.NoiseMap(seed + 1, size, ObjectGenerator.treeNoiseScale, AnimationCurve.Linear(0f, 0f, 1f, 1f)); float[,] falloffMap = Procedural.FalloffMap(size); //Determine what is land for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { landNoise[x, y] = Mathf.Max(0, landNoise[x, y] - falloffMap[x, y]); } } //Set corresponding voxel values for land for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { voxelData[x, y] = new VoxelData { coords = new Coords(x, y) }; if (landNoise[x, y] > waterThreshold) { voxelData[x, y].isLand = true; voxelData[x, y].navigable = true; } else { voxelData[x, y].isOcean = true; } } } //Find and mark lakes bool[,] marked = new bool[size, size]; List <List <Coords> > bodiesOfWater = new List <List <Coords> >(); for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { marked[x, y] = false; } } for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { if (!marked[x, y] && voxelData[x, y].isOcean) { Stack <Coords> stack = new Stack <Coords>(); List <Coords> list = new List <Coords>(); stack.Push(new Coords(x, y)); while (stack.Count > 0) { Coords v = stack.Pop(); if (!marked[(int)v.x, (int)v.y]) { list.Add(v); marked[(int)v.x, (int)v.y] = true; foreach (Coords adj in Util.GetAdjacent(v, true)) { if (voxelData[(int)adj.x, (int)adj.y].isOcean) { stack.Push(adj); } } } } bodiesOfWater.Add(list); } } } foreach (List <Coords> body in bodiesOfWater) { if (body.Count < 100) { foreach (Coords v in body) { voxelData[v.x, v.y].isOcean = false; voxelData[v.x, v.y].isLake = true; } } } //Set voxel colors for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { if (voxelData[x, y].isLand) { Color baseColor = Color.Lerp(Palette.LandMin, Palette.LandMax, rng.Next(0, 1000) / 1000f); voxelData[x, y].color = SerializableColor.FromColor(Color.Lerp(baseColor, Palette.Chartreuse, Mathf.Pow(colorNoise[x, y] * landNoise[x, y], 2))); } else { voxelData[x, y].color = SerializableColor.FromColor(Palette.Water); } } } //Set beaches and coasts for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { Coords coords = new Coords(x, y); if (voxelData[x, y].isLand && Util.AdjacentProperty(Util.CoordsToVoxels(voxelData, Util.GetAdjacent(coords, true)), "isOcean") && colorNoise[x, y] > .5f) { voxelData[x, y].color = SerializableColor.FromColor(Color.Lerp(voxelData[x, y].color.ToColor(), Palette.Sand, Mathf.Pow(colorNoise[x, y], 2))); } else if (voxelData[x, y].isOcean && Util.AdjacentProperty(Util.CoordsToVoxels(voxelData, Util.GetAdjacent(coords, true)), "isLand")) { voxelData[x, y].color = SerializableColor.FromColor(Color.Lerp(voxelData[x, y].color.ToColor(), Palette.Coast, .1f)); } } } return(voxelData); }