city-generation/Game/Assets/Scripts/Unity/BuildingMeshGenerator.cs

115 lines
4.3 KiB
C#
Raw Normal View History

2015-06-10 08:49:43 +00:00
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; }
public Texture2D[] Textures { get; set; }
2015-06-10 08:49:43 +00:00
private GameObject parent = new GameObject("buildings");
private Map map;
private System.Random random = new System.Random();
2015-06-10 08:49:43 +00:00
public IEnumerable Generate(Map map)
{
this.map = map;
int i = 0;
2015-06-10 08:49:43 +00:00
foreach (var building in map.Buildings)
{
GenerateBuilding(building);
if (++i % 10 == 0)
yield return null;
2015-06-10 08:49:43 +00:00
}
}
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;
2015-06-10 09:46:04 +00:00
// Side
2015-06-10 08:49:43 +00:00
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));
uv.Add(new UnityEngine.Vector2(pts[j].Y + pts[j].X, minY));
uv.Add(new UnityEngine.Vector2(pts[k].Y + pts[k].X, minY));
uv.Add(new UnityEngine.Vector2(pts[k].Y + pts[k].X, maxY));
uv.Add(new UnityEngine.Vector2(pts[j].Y + pts[j].X, maxY));
2015-06-10 08:49:43 +00:00
triangles.AddRange(new[] { vIndex, vIndex + 1, vIndex + 2 });
triangles.AddRange(new[] { vIndex, vIndex + 2, vIndex + 3 });
2015-06-10 09:46:04 +00:00
vIndex = vertices.Count;
2015-06-10 08:49:43 +00:00
2015-06-10 09:46:04 +00:00
// Top side
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, 0));
uv.Add(new UnityEngine.Vector2(0, 0));
2015-06-10 09:46:04 +00:00
triangles.AddRange(new[] { vIndex + 2, vIndex + 1, vIndex + 0 });
2015-06-10 08:49:43 +00:00
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 };
// Pick random texture
if (Textures != null)
{
int t = random.Next(Textures.Length);
meshRenderer.material.mainTexture = Textures[t];
}
2015-06-10 08:49:43 +00:00
}
}
}