Fixed unity terrain generation bug.

This commit is contained in:
2015-03-19 12:34:58 +02:00
parent 8f9f935796
commit 68140b11a7
40 changed files with 326 additions and 245 deletions

View File

@ -45,10 +45,14 @@ namespace TransportGame.Generator
// Generate water level
float waterAmount = random.NextSingle(map.Biome.Moisture.Minimum, map.Biome.Moisture.Maximum);
map.WaterLevel = Mathf.Pow(waterAmount, ConfigurationManager.TerrGenConfig.WaterNonLinearPower)
* (map.Biome.HeightRange.Maximum - map.Biome.HeightRange.Minimum) + map.Biome.HeightRange.Minimum;
map.WaterLevel = Mathf.Pow(waterAmount, ConfigurationManager.TerrGenConfig.WaterNonLinearPower) * map.Biome.Height;
DumpData(map, "1generated.map");
// Simulate water erosion
//Erode(map);
//DumpData(map, "2eroded.map");
DumpData(map);
return map;
}
@ -64,14 +68,21 @@ namespace TransportGame.Generator
{
for (int x = 0; x < map.Width; ++x)
for (int y = 0; y < map.Height; ++y)
map[x, y] = Noise.Generate(x, y, map.Biome.HeightRange.Minimum, map.Biome.HeightRange.Maximum);
map[x, y] = Noise.Generate(x, y, 0, 1);
}
private void DumpData(Map map)
//private void Erode(Map map)
//{
// float[,] water = new float[map.Width, map.Height];
//}
private void DumpData(Map map, string filename)
{
XmlSerializer serializer = new XmlSerializer(typeof(Map));
using (StreamWriter writer = new StreamWriter(Path.Combine(Logger.LogsDirectory, "mapdump.map")))
using (StreamWriter writer = new StreamWriter(Path.Combine(Logger.LogsDirectory, filename)))
{
serializer.Serialize(writer, map);
writer.Close();

View File

@ -1,44 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using TransportGame.Utils;
namespace TransportGame.Model
{
[XmlRoot("biome")]
public class Biome
{
/// <summary>
/// Gets or sets the name of the biome
/// </summary>
[XmlElement("name")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the height range of the biome.
/// </summary>
/// <remarks>
/// 1 unit = 100 meters.
/// </remarks>
[XmlElement("heightRange")]
public Range HeightRange { get; set; }
/// <summary>
/// Gets or sets the moisture range.
/// </summary>
/// <remarks>
/// Moisture is the amount of water on a map.
/// Value is a probability, should be between 0 and 1.
/// </remarks>
[XmlElement("moisture")]
public Range Moisture { get; set; }
/// <summary>
/// Gets or sets the vegetation density of the biome
/// </summary>
[XmlElement("vegetationDensity")]
public Range VegetationDensity { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using TransportGame.Utils;
namespace TransportGame.Model
{
[XmlRoot("biome")]
public class Biome
{
/// <summary>
/// Gets or sets the name of the biome
/// </summary>
[XmlElement("name")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the maximum height of the biome.
/// </summary>
/// <remarks>
/// 1 unit = 100 meters.
/// </remarks>
[XmlElement("height")]
public float Height { get; set; }
/// <summary>
/// Gets or sets the moisture range.
/// </summary>
/// <remarks>
/// Moisture is the amount of water on a map.
/// Value is a probability, should be between 0 and 1.
/// </remarks>
[XmlElement("moisture")]
public Range Moisture { get; set; }
/// <summary>
/// Gets or sets the vegetation density of the biome
/// </summary>
[XmlElement("vegetationDensity")]
public Range VegetationDensity { get; set; }
}
}

View File

@ -140,7 +140,7 @@ namespace TransportGame.Model
/// <returns></returns>
public bool IsWater(int x, int y)
{
return grid[x, y] <= WaterLevel;
return grid[x, y] * Biome.Height <= WaterLevel;
}
}
}

View File

@ -1,87 +1,87 @@
using UnityEngine;
using System.Collections;
using TransportGame.Utils;
using System.Threading;
using TransportGame.Generator;
using TransportGame.Model;
using TransportGame.Business;
public class TerrainGeneratorScript : MonoBehaviour
{
private Map map = null;
public int TerrainWidth = 256;
public int TerrainHeight = 256;
public GameObject WaterObject;
// Use this for initialization
void Start()
{
StartCoroutine(GenerateMap());
}
private void GenerateMapThread()
{
TerrainGenerator generator = new TerrainGenerator();
map = generator.Generate(TerrainWidth, TerrainHeight);
}
private Mesh GenerateWater()
{
Mesh water = new Mesh();
water.name = "water";
water.vertices = new[] {
new Vector3(0, map.WaterLevel, 0),
new Vector3(0, map.WaterLevel, map.Height),
new Vector3(map.Width, map.WaterLevel, 0),
new Vector3(map.Width, map.WaterLevel, map.Height)
};
water.triangles = new[] { 0, 1, 2, 2, 1, 3 };
water.uv = new[] {
new Vector2(0, 0),
new Vector2(0, 1),
new Vector2(1, 0),
new Vector2(1, 1)
};
water.RecalculateNormals();
return water;
}
private IEnumerator GenerateMap()
{
// Wait for the map generation thread
foreach (var i in Task.RunAsync(GenerateMapThread))
yield return i;
// Generate terrain data
TerrainData terrainData = new TerrainData();
terrainData.heightmapResolution = Mathf.Max(map.Height, map.Width);
terrainData.size = new Vector3(map.Width, map.Biome.HeightRange.Maximum, map.Height);
terrainData.SetDetailResolution(1024, 8);
terrainData.SetHeights(0, 0, map.Heights);
terrainData.name = "Generated Terrain Data";
yield return null;
// Create terrain object
GameObject terrain = Terrain.CreateTerrainGameObject(terrainData);
terrain.name = "Generated Terrain";
yield return null;
Terrain terrainComp = terrain.GetComponent<Terrain>();
terrainComp.heightmapPixelError = 1;
yield return null;
// Set water
if (WaterObject != null)
{
MeshFilter waterMesh = WaterObject.GetComponent<MeshFilter>();
waterMesh.mesh = GenerateWater();
}
}
// Update is called once per frame
void Update()
{
}
}
using UnityEngine;
using System.Collections;
using TransportGame.Utils;
using System.Threading;
using TransportGame.Generator;
using TransportGame.Model;
using TransportGame.Business;
public class TerrainGeneratorScript : MonoBehaviour
{
private Map map = null;
public int TerrainWidth = 256;
public int TerrainHeight = 256;
public GameObject WaterObject;
// Use this for initialization
void Start()
{
StartCoroutine(GenerateMap());
}
private void GenerateMapThread()
{
TerrainGenerator generator = new TerrainGenerator();
map = generator.Generate(TerrainWidth, TerrainHeight);
}
private Mesh GenerateWater()
{
Mesh water = new Mesh();
water.name = "water";
water.vertices = new[] {
new Vector3(0, map.WaterLevel, 0),
new Vector3(0, map.WaterLevel, map.Height),
new Vector3(map.Width, map.WaterLevel, 0),
new Vector3(map.Width, map.WaterLevel, map.Height)
};
water.triangles = new[] { 0, 1, 2, 2, 1, 3 };
water.uv = new[] {
new Vector2(0, 0),
new Vector2(0, 1),
new Vector2(1, 0),
new Vector2(1, 1)
};
water.RecalculateNormals();
return water;
}
private IEnumerator GenerateMap()
{
// Wait for the map generation thread
foreach (var i in Task.RunAsync(GenerateMapThread))
yield return i;
// Generate terrain data
TerrainData terrainData = new TerrainData();
terrainData.heightmapResolution = Mathf.Max(map.Height, map.Width) + 1;
terrainData.size = new Vector3(map.Width, map.Biome.Height, map.Height);
terrainData.SetDetailResolution(1024, 8);
terrainData.SetHeights(0, 0, map.Heights);
terrainData.name = "Generated Terrain Data";
yield return null;
// Create terrain object
GameObject terrain = Terrain.CreateTerrainGameObject(terrainData);
terrain.name = "Generated Terrain";
yield return null;
Terrain terrainComp = terrain.GetComponent<Terrain>();
terrainComp.heightmapPixelError = 1;
yield return null;
// Set water
if (WaterObject != null)
{
MeshFilter waterMesh = WaterObject.GetComponent<MeshFilter>();
waterMesh.mesh = GenerateWater();
}
}
// Update is called once per frame
void Update()
{
}
}