115 lines
4.3 KiB
C#
115 lines
4.3 KiB
C#
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; }
|
|
|
|
private GameObject parent = new GameObject("buildings");
|
|
private Map map;
|
|
private System.Random random = new System.Random();
|
|
|
|
public IEnumerable Generate(Map map)
|
|
{
|
|
this.map = map;
|
|
int i = 0;
|
|
|
|
foreach (var building in map.Buildings)
|
|
{
|
|
GenerateBuilding(building);
|
|
|
|
if (++i % 10 == 0)
|
|
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;
|
|
|
|
// Side
|
|
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));
|
|
triangles.AddRange(new[] { vIndex, vIndex + 1, vIndex + 2 });
|
|
triangles.AddRange(new[] { vIndex, vIndex + 2, vIndex + 3 });
|
|
vIndex = vertices.Count;
|
|
|
|
// 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));
|
|
triangles.AddRange(new[] { vIndex + 2, vIndex + 1, vIndex + 0 });
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
}
|