// Get biome layer topology and smooth between layers at edges using Perlin or Simplex noise private Topology GetBiomeTopology(int x, int z, Column column, TerrainLibrary.Biome biome) { // Global voxel column coordinates int gx = (int)(x + column.position.x); int gz = (int)(z + column.position.z); // Base noise to map biome layers and base height float baseNoise = biome.BaseNoise(gx, gz); TerrainLibrary.BiomeLayer layer = biome.GetLayer(baseNoise); // Do not overwrite data for this block when getting adjacent biome topology if (column.biomeLayers[x, z] == null) { column.biomeLayers[x, z] = layer; } // Make sure gradient margins don't overlap float margin = (layer.max - layer.min) / 2; // Clamp margin at max margin = margin > layer.maxMargin ? layer.maxMargin : margin; // Layer height data for current layer Topology currentTopology = new Topology(layer.Noise(gx, gz), layer.maxHeight, baseNoise); // Closeness to top and bottom of baseNoise range defining this biome layer float bottomGradient = EdgeGradient(baseNoise, layer.min, margin); float topGradient = EdgeGradient(baseNoise, layer.max, margin); TerrainLibrary.BiomeLayer adjacentLayer = null; float interpValue; // Smooth to above layer if (bottomGradient != 2 && layer.min != 0) { adjacentLayer = biome.layers[layer.index - 1]; interpValue = bottomGradient; } // Smooth to below layer else if (topGradient != 2 && layer.max != 1) { adjacentLayer = biome.layers[layer.index + 1]; interpValue = topGradient; } // Not within margin distance of another layer else { // No smoothing required return(new Topology(currentTopology.noise, currentTopology.height, baseNoise)); } // Layer height data for adjacent layer Topology adjacentTopology = new Topology(adjacentLayer.Noise(gx, gz), adjacentLayer.maxHeight, baseNoise); // Return smoothed topology return(SmoothTopologys(currentTopology, adjacentTopology, interpValue)); }
// Get biome topology and smooth between biomes if necessary // using Cellular value and distance-to-edge noise respectively public void GetTopologyData(Column column) { int chunkSize = World.chunkSize; column.heightMap = new int[chunkSize, chunkSize]; // Iterate over height map for (int x = 0; x < chunkSize; x++) { for (int z = 0; z < chunkSize; z++) { // Global voxel column coordinates int gx = (int)(x + column.position.x); int gz = (int)(z + column.position.z); // Get cellular noise data FastNoise.EdgeData edgeData = column.edgeMap[x, z]; // Get current biome type TerrainLibrary.Biome currentBiome = worldBiomes.GetBiome(edgeData.currentCellValue); // Get adjacent biome type TerrainLibrary.Biome adjacentBiome = worldBiomes.GetBiome(edgeData.adjacentCellValue); // Get topology for this pixel Topology currentTolopogy = GetBiomeTopology(x, z, column, currentBiome); Topology finalTopology; // Within smoothing radius and adjacent biome is different if (edgeData.distance2Edge < worldBiomes.smoothRadius && currentBiome != adjacentBiome) { if (!column.biomeBoundary) { column.biomeBoundary = true; } float InterpValue = Mathf.InverseLerp(0, worldBiomes.smoothRadius, edgeData.distance2Edge); // Get topology for this pixel if adjacent biome type Topology adjacentTopology = GetBiomeTopology(x, z, column, adjacentBiome); // Smooth between topologys finalTopology = SmoothTopologys(currentTolopogy, adjacentTopology, InterpValue); } else { finalTopology = currentTolopogy; } int POIheight = 0; // Where points of interest exist, flatten terrain if (column.POIHeightGradient != null && column.POIHeightGradient[x, z] != 0) { float interpValue = (float)column.POIHeightGradient[x, z] / chunkSize; Topology POITopology = new Topology(0.5f, finalTopology.height, 0.5f); finalTopology = SmoothToPOI(POITopology, finalTopology, interpValue); // Adjust heighest point POIheight = column.POIType.wallHeight; } // Generate final height value for chunk data column.heightMap[x, z] = (int)Mathf.Lerp(0, finalTopology.height, finalTopology.baseNoise * finalTopology.noise); // Update highest and lowest block in chunk column column.CheckHighest(column.heightMap[x, z] + POIheight); column.CheckLowest(column.heightMap[x, z]); } } }