Generated buildings
This commit is contained in:
97
Game/Assets/Scripts/Unity/BuildingMeshGenerator.cs
Normal file
97
Game/Assets/Scripts/Unity/BuildingMeshGenerator.cs
Normal 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 };
|
||||
}
|
||||
}
|
||||
}
|
12
Game/Assets/Scripts/Unity/BuildingMeshGenerator.cs.meta
Normal file
12
Game/Assets/Scripts/Unity/BuildingMeshGenerator.cs.meta
Normal 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:
|
@ -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);
|
||||
|
Reference in New Issue
Block a user