Generated buildings

This commit is contained in:
2015-06-10 11:49:43 +03:00
parent 352f212ae9
commit 4b61f0bdb5
47 changed files with 892 additions and 110 deletions

View File

@ -0,0 +1,97 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TransportGame.Model;
using UnityEngine;
namespace TransportGame.Unity
{
public class BuildingMeshGenerator
{
public Material BuildingMaterial { get; set; }
private GameObject parent = new GameObject("buildings");
private Map map;
public IEnumerable Generate(Map map)
{
this.map = map;
foreach (var building in map.Buildings)
{
GenerateBuilding(building);
yield return null;
}
}
private void GenerateBuilding(Building building)
{
List<Vector3> vertices = new List<Vector3>();
List<UnityEngine.Vector2> uv = new List<UnityEngine.Vector2>();
List<int> triangles = new List<int>();
int vIndex = 0;
if (building.Polygons.Length == 0)
return;
float terrainHeight = building.Polygons[0].SelectMany(poly => poly.Points).Min(pt => map.GetHeight((int)pt.X, (int)pt.Y));
float minY, maxY = terrainHeight;
for (int i = 0; i < building.Polygons.Length; i++)
{
// Update minY and maxY
minY = maxY;
maxY += building.LevelHeights[i];
for (int p = 0; p < building.Polygons[i].Length; p++)
{
// Build mesh
var center = building.Polygons[i][p].Position;
var pts = building.Polygons[i][p].Points;
for (int j = 0; j < pts.Length; j++)
{
int k = (j + 1) % pts.Length;
vertices.Add(new Vector3(pts[j].Y, minY, pts[j].X));
vertices.Add(new Vector3(pts[k].Y, minY, pts[k].X));
vertices.Add(new Vector3(pts[k].Y, maxY, pts[k].X));
vertices.Add(new Vector3(pts[j].Y, maxY, pts[j].X));
vertices.Add(new Vector3(center.Y, maxY, center.X));
uv.Add(new UnityEngine.Vector2(0, 0));
uv.Add(new UnityEngine.Vector2(0, 1));
uv.Add(new UnityEngine.Vector2(1, 1));
uv.Add(new UnityEngine.Vector2(1, 0));
uv.Add(new UnityEngine.Vector2(0.5f, 0.5f));
triangles.AddRange(new[] { vIndex, vIndex + 1, vIndex + 2 });
triangles.AddRange(new[] { vIndex, vIndex + 2, vIndex + 3 });
triangles.AddRange(new[] { vIndex + 4, vIndex + 3, vIndex + 2 }); // top side
vIndex = vertices.Count;
}
}
}
// Construct mesh
Mesh mesh = new Mesh();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.uv = uv.ToArray();
mesh.RecalculateNormals();
// Construct game object
GameObject inters = new GameObject("building");
inters.transform.parent = parent.transform;
MeshFilter meshFilter = inters.AddComponent<MeshFilter>();
meshFilter.mesh = mesh;
MeshRenderer meshRenderer = inters.AddComponent<MeshRenderer>();
meshRenderer.materials = new[] { BuildingMaterial };
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 285289bd35a5aac429d15f8fdf99512f
timeCreated: 1433859861
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -16,6 +16,7 @@ public class TerrainGeneratorScript : MonoBehaviour
public GameObject WaterObject;
public Texture2D[] Textures;
public Material RoadMaterial;
public Material BuildingMaterial;
// Use this for initialization
void Start()
@ -54,7 +55,7 @@ public class TerrainGeneratorScript : MonoBehaviour
private IEnumerator GenerateMap()
{
// Generate terrain
foreach (var i in Task.RunAsync(GenerateTerrainThread))
foreach (var i in Task.Await(GenerateTerrainThread))
yield return i;
// Generate terrain data
@ -105,20 +106,62 @@ public class TerrainGeneratorScript : MonoBehaviour
// Set up textures
Logger.Info("Setting up textures...");
foreach (var i in SetupSplatmaps(terrainData))
BeginSetupSplatmaps(terrainData);
foreach (var lot in map.BuildingLots)
{
for (int i = 0; i < lot.Points.Length; i++)
{
int j = (i + 1) % lot.Points.Length;
if (!map.IsInside(lot.Points[i]))
{
Logger.Warning("Generated point not inside: {0}", lot.Points[i]);
continue;
}
if (!map.IsInside(lot.Points[j]))
{
Logger.Warning("Generated point not inside: {0}", lot.Points[j]);
continue;
}
Debug.DrawLine(
new Vector3(lot.Points[i].Y, map.GetHeight((int)lot.Points[i].X, (int)lot.Points[i].Y) + 0.5f, lot.Points[i].X),
new Vector3(lot.Points[j].Y, map.GetHeight((int)lot.Points[j].X, (int)lot.Points[j].Y) + 0.5f, lot.Points[j].X),
Color.yellow, 10000);
}
}
// Generate road & building mesh (we run the loops in parallel)
Logger.Info("Generating buildings and roads...");
BuildingMeshGenerator buildingMeshGenerator = new BuildingMeshGenerator();
buildingMeshGenerator.BuildingMaterial = BuildingMaterial;
var it1 = buildingMeshGenerator.Generate(map).GetEnumerator();
RoadMeshGenerator roadMeshGenerator = new RoadMeshGenerator();
roadMeshGenerator.RoadMaterial = RoadMaterial;
var it2 = roadMeshGenerator.Generate(map).GetEnumerator();
bool stop;
do
{
stop = true;
if (it1.MoveNext())
{
yield return it1.Current;
stop = false;
}
if (it2.MoveNext())
{
yield return it2.Current;
stop = false;
}
} while (!stop);
// Finish setting up textures
foreach (var i in EndSetupSplatmaps(terrainData))
yield return i;
// Generate road mesh
Logger.Info("Generating roads...");
RoadMeshGenerator meshGenerator = new RoadMeshGenerator();
meshGenerator.RoadMaterial = RoadMaterial;
foreach (object i in meshGenerator.Generate(map))
yield return i;
// -- DEBUG --
foreach (var center in map.PopulationCenters)
Debug.DrawLine(new Vector3(center.Y, 0, center.X), new Vector3(center.Y, map.Biome.Height, center.X), Color.yellow, 100000);
}
private float[,,] GenerateSplatData(int alphaWidth, int alphaHeight, int alphaLayers)
@ -174,14 +217,21 @@ public class TerrainGeneratorScript : MonoBehaviour
return splatData;
}
private IEnumerable SetupSplatmaps(TerrainData terrainData)
float[, ,] splatData = null;
private Task splatmapsTask = null;
private void BeginSetupSplatmaps(TerrainData terrainData)
{
float[, ,] splatData = null;
int alphaW = terrainData.alphamapWidth;
int alphaH = terrainData.alphamapHeight;
int alphaL = terrainData.alphamapLayers;
foreach (var i in Task.RunAsync(() => splatData = GenerateSplatData(alphaW, alphaH, alphaL)))
splatmapsTask = Task.RunAsync(() => splatData = GenerateSplatData(alphaW, alphaH, alphaL));
}
private IEnumerable EndSetupSplatmaps(TerrainData terrainData)
{
foreach (var i in splatmapsTask.Await())
yield return i;
terrainData.SetAlphamaps(0, 0, splatData);