/// <summary> /// Readies a biome map for creation and pulls heightmap /// information from the passed <see cref="Tile"/> /// </summary> /// <param name="tile">Tile to refernce heightmap from</param> /// <param name="resolution">Resolution of the map (must be lower /// than or equal to heightmap resolution)</param> public BiomeMap(Tile tile, int resolution) { _tile = tile; _resolution = resolution; _heightmap = _tile.MeshManager.Heightmap; _heightmapResolution = _tile.MeshManager.HeightmapResolution; Map = new BiomeData[resolution, resolution]; BiomeSet = new List <BiomeData>(); }
/// <summary> /// Gets the bottom-most biome that is active within the list of /// biomes stored in <see cref="TerraConfig"/>. /// </summary> /// <param name="x">X location in heightmap</param> /// <param name="z">Z location in heightmap</param> public BiomeData GetBiomeAt(int x, int z) { BiomeData bottomMost = null; var tm = Config.TemperatureMapData; var mm = Config.MoistureMapData; //TODO Add angle constraint foreach (BiomeData b in Config.BiomesData) { if (b.IsTemperatureConstrained && !tm.HasGenerator()) { continue; } if (b.IsMoistureConstrained && !mm.HasGenerator()) { continue; } //Calculate x and z offsets for checking heightmap int offset = _resolution / _heightmapResolution; x *= offset; z *= offset; //Calculate height and world x/z positions var height = _heightmap[x, z]; var local = TileMesh.PositionToLocal(x, z, _resolution); var world = TileMesh.LocalToWorld(_tile == null ? new GridPosition() : _tile.GridPosition, local.x, local.y); var wx = world.x; var wz = world.y; var temp = tm.GetValue(wx, wz); var moisture = mm.GetValue(wx, wz); //If no constraints continue if (!b.IsHeightConstrained && !b.IsTemperatureConstrained && !b.IsMoistureConstrained) { bottomMost = b; continue; } //Which map constraints fit the passed value bool passHeight = b.IsHeightConstrained && b.HeightConstraint.Fits(height); bool passTemp = b.IsTemperatureConstrained && b.TemperatureConstraint.Fits(temp); bool passMoisture = b.IsMoistureConstrained && b.MoistureConstraint.Fits(moisture); if (passHeight && passTemp && passMoisture) { bottomMost = b; } } return(bottomMost); }
public void CreateMap() { WeightedMap = new KeyValuePair <BiomeData[], float[]> [_resolution, _resolution]; WeightedBiomeSet = new List <BiomeData>(); for (int x = 0; x < _resolution; x++) { for (int z = 0; z < _resolution; z++) { List <BiomeData> biomes = new List <BiomeData>(); List <float> weights = new List <float>(); //Collect weight of every biome at this coordinate for (var i = 0; i < Config.BiomesData.Count; i++) { BiomeData b = Config.BiomesData[i]; float weight = GetWeight(b, x, z); if (weight > 0.0001f) { biomes.Add(b); weights.Add(weight); if (i != 0) { weights[i - 1] = 1 - weight; weights[i] = weight; } } } //Normalize weights float sum = weights.Sum(); for (var i = 0; i < weights.Count; i++) { weights[i] /= sum; } WeightedMap[x, z] = new KeyValuePair <BiomeData[], float[]>(biomes.ToArray(), weights.ToArray()); //Add to biome set biomes.ForEach(b => { if (!WeightedBiomeSet.Exists(existing => ReferenceEquals(existing, b))) { WeightedBiomeSet.Add(b); } }); } } }
public void CreateMap() { for (int x = 0; x < _resolution; x++) { for (int z = 0; z < _resolution; z++) { //Get biome at this coordinate BiomeData biome = GetBiomeAt(x, z); Map[x, z] = biome; //Add to biome set BiomeSet.ForEach(b => { if (!BiomeSet.Exists(existing => ReferenceEquals(existing, b))) { BiomeSet.Add(b); } }); } } }
/// <summary> /// Calculates the "weight", value between 0 and 1 which represents /// how much a biome appears. The <see cref="Tile"/> that was used /// when constructing must have a heightmap. /// </summary> /// <param name="biome">Biome to check</param> /// <param name="x">X location in heightmap</param> /// <param name="z">Z location in heightmap</param> public float GetWeight(BiomeData biome, int x, int z) { BiomeData b = biome; var tm = Config.TemperatureMapData; var mm = Config.MoistureMapData; if (b.IsTemperatureConstrained && !tm.HasGenerator()) { return(0); } if (b.IsMoistureConstrained && !mm.HasGenerator()) { return(0); } //Calculate x and z offsets for checking heightmap int offset = _resolution / _heightmapResolution; x *= offset; z *= offset; //Calculate height and world x/z positions var local = TileMesh.PositionToLocal(x, z, _resolution); var world = TileMesh.LocalToWorld(_tile == null ? new GridPosition() : _tile.GridPosition, local.x, local.y); var wx = world.x; var wz = world.y; //Establish and clamp sampled values between 1 & 0 var height = _heightmap[x, z]; var temp = tm.GetValue(wx, wz, tm.Spread); var moisture = mm.GetValue(wx, wz, mm.Spread); height = Mathf.Clamp01(height); temp = Mathf.Clamp01(temp); moisture = Mathf.Clamp01(moisture); //If no constraints return 1f if (!b.IsHeightConstrained && !b.IsTemperatureConstrained && !b.IsMoistureConstrained) { return(1f); } //Which map constraints fit the passed value //todo figure this out v //bool passHeight = b.IsHeightConstrained && (b.HeightConstraint.Fits(height) || b.HeightConstraint.FitsMinMax(height)); //bool passTemp = b.IsTemperatureConstrained && (b.TemperatureConstraint.Fits(temp) || b.TemperatureConstraint.FitsMinMax(temp)); //bool passMoisture = b.IsMoistureConstrained && (b.MoistureConstraint.Fits(moisture) || b.MoistureConstraint.FitsMinMax(moisture)); bool passHeight = b.IsHeightConstrained && (b.HeightConstraint.Fits(height)); bool passTemp = b.IsTemperatureConstrained && (b.TemperatureConstraint.Fits(temp)); bool passMoisture = b.IsMoistureConstrained && (b.MoistureConstraint.Fits(moisture)); float blend = Config.Generator.BiomeBlendAmount; //Confirm constraint requirements int passAmt = new[] { passHeight, passTemp, passMoisture }.Count(pass => pass); int passMax = new[] { b.IsHeightConstrained, b.IsTemperatureConstrained, b.IsMoistureConstrained }.Count(pass => pass); //Not all constraints were passed, return 0f if (passAmt < passMax && b.MixMethod == BiomeData.ConstraintMixMethod.AND) { return(0f); } var maxWeight = new[] { new { value = height, pass = passHeight, constraint = b.HeightConstraint }, new { value = temp, pass = passTemp, constraint = b.TemperatureConstraint }, new { value = moisture, pass = passMoisture, constraint = b.MoistureConstraint } } .Where(type => type.pass) .Aggregate((agg, next) => agg.value > next.value ? next : agg); return(maxWeight.constraint.Weight(maxWeight.value, blend, Config.Generator.BiomeFalloff)); //Calculate weight given to each map // float weight = 0; // if (passHeight) { // weight += b.HeightConstraint.Weight(height, blend); // } // if (passTemp) { // weight += b.TemperatureConstraint.Weight(temp, blend); // } // if (passMoisture) { // weight += b.MoistureConstraint.Weight(moisture, blend); // } // // return weight / passAmt; }