using System.Collections.Generic; using UnityEngine; using Mapbox.Unity.MeshGeneration.Data; using Mapbox.Unity.Map; using Mapbox.Unity.Utilities; namespace Mapbox.Unity.MeshGeneration.Factories.TerrainStrategies { public class FlatTerrainStrategy : TerrainStrategy { MeshDataArray _cachedQuad; public override int RequiredVertexCount { get { return 4; } } public override void Initialize(ElevationLayerProperties elOptions) { _elevationOptions = elOptions; } public override void RegisterTile(UnityTile tile) { if (_elevationOptions.unityLayerOptions.addToLayer && tile.gameObject.layer != _elevationOptions.unityLayerOptions.layerId) { tile.gameObject.layer = _elevationOptions.unityLayerOptions.layerId; } if (tile.RasterDataState != Enums.TilePropertyState.Loaded || tile.MeshFilter.sharedMesh.vertexCount != RequiredVertexCount) { if (_elevationOptions.sideWallOptions.isActive) { var firstMat = tile.MeshRenderer.materials[0]; tile.MeshRenderer.materials = new Material[2] { firstMat, _elevationOptions.sideWallOptions.wallMaterial }; } } if ((int)tile.ElevationType != (int)ElevationLayerType.FlatTerrain) { tile.MeshFilter.sharedMesh.Clear(); // HACK: This is here in to make the system trigger a finished state. GetQuad(tile, _elevationOptions.sideWallOptions.isActive); tile.ElevationType = TileTerrainType.Flat; } if (_elevationOptions.colliderOptions.addCollider) { var meshCollider = tile.Collider as MeshCollider; if (meshCollider) { meshCollider.sharedMesh = tile.MeshFilter.sharedMesh; } } } private void GetQuad(UnityTile tile, bool buildSide) { if (_cachedQuad != null) { var mesh = tile.MeshFilter.sharedMesh; mesh.vertices = _cachedQuad.Vertices; mesh.normals = _cachedQuad.Normals; mesh.triangles = _cachedQuad.Triangles; mesh.uv = _cachedQuad.Uvs; } else { if (buildSide) { BuildQuadWithSides(tile); } else { BuildQuad(tile); } } } private void BuildQuad(UnityTile tile) { var unityMesh = tile.MeshFilter.sharedMesh; var verts = new Vector3[4]; var norms = new Vector3[4]; verts[0] = tile.TileScale * ((tile.Rect.Min - tile.Rect.Center).ToVector3xz()); verts[1] = tile.TileScale * (new Vector3((float)(tile.Rect.Max.x - tile.Rect.Center.x), 0, (float)(tile.Rect.Min.y - tile.Rect.Center.y))); verts[2] = tile.TileScale * ((tile.Rect.Max - tile.Rect.Center).ToVector3xz()); verts[3] = tile.TileScale * (new Vector3((float)(tile.Rect.Min.x - tile.Rect.Center.x), 0, (float)(tile.Rect.Max.y - tile.Rect.Center.y))); norms[0] = Mapbox.Unity.Constants.Math.Vector3Up; norms[1] = Mapbox.Unity.Constants.Math.Vector3Up; norms[2] = Mapbox.Unity.Constants.Math.Vector3Up; norms[3] = Mapbox.Unity.Constants.Math.Vector3Up; unityMesh.vertices = verts; unityMesh.normals = norms; var trilist = new int[6] { 0, 1, 2, 0, 2, 3 }; unityMesh.triangles = trilist; var uvlist = new Vector2[4] { new Vector2(0,1), new Vector2(1,1), new Vector2(1,0), new Vector2(0,0) }; unityMesh.uv = uvlist; _cachedQuad = new MeshDataArray() { Vertices = verts, Normals = norms, Triangles = trilist, Uvs = uvlist }; } private void BuildQuadWithSides(UnityTile tile) { var unityMesh = tile.MeshFilter.sharedMesh; var verts = new Vector3[20]; var norms = new Vector3[20]; verts[0] = tile.TileScale * ((tile.Rect.Min - tile.Rect.Center).ToVector3xz()); verts[1] = tile.TileScale * (new Vector3((float)(tile.Rect.Max.x - tile.Rect.Center.x), 0, (float)(tile.Rect.Min.y - tile.Rect.Center.y))); verts[2] = tile.TileScale * ((tile.Rect.Max - tile.Rect.Center).ToVector3xz()); verts[3] = tile.TileScale * (new Vector3((float)(tile.Rect.Min.x - tile.Rect.Center.x), 0, (float)(tile.Rect.Max.y - tile.Rect.Center.y))); norms[0] = Mapbox.Unity.Constants.Math.Vector3Up; norms[1] = Mapbox.Unity.Constants.Math.Vector3Up; norms[2] = Mapbox.Unity.Constants.Math.Vector3Up; norms[3] = Mapbox.Unity.Constants.Math.Vector3Up; //verts goes //01 //32 unityMesh.subMeshCount = 2; Vector3 norm = Mapbox.Unity.Constants.Math.Vector3Up; for (int i = 0; i < 4; i++) { verts[4 * (i + 1)] = verts[i]; verts[4 * (i + 1) + 1] = verts[i + 1]; verts[4 * (i + 1) + 2] = verts[i] + new Vector3(0, -_elevationOptions.sideWallOptions.wallHeight, 0); verts[4 * (i + 1) + 3] = verts[i + 1] + new Vector3(0, -_elevationOptions.sideWallOptions.wallHeight, 0); norm = Vector3.Cross(verts[4 * (i + 1) + 1] - verts[4 * (i + 1) + 2], verts[4 * (i + 1)] - verts[4 * (i + 1) + 1]).normalized; norms[4 * (i + 1)] = norm; norms[4 * (i + 1) + 1] = norm; norms[4 * (i + 1) + 2] = norm; norms[4 * (i + 1) + 3] = norm; } unityMesh.vertices = verts; unityMesh.normals = norms; var trilist = new List(6) { 0, 1, 2, 0, 2, 3 }; unityMesh.SetTriangles(trilist, 0); trilist = new List(8); for (int i = 0; i < 4; i++) { trilist.Add(4 * (i + 1)); trilist.Add(4 * (i + 1) + 2); trilist.Add(4 * (i + 1) + 1); trilist.Add(4 * (i + 1) + 1); trilist.Add(4 * (i + 1) + 2); trilist.Add(4 * (i + 1) + 3); } unityMesh.SetTriangles(trilist, 1); var uvlist = new Vector2[20]; uvlist[0] = new Vector2(0, 1); uvlist[1] = new Vector2(1, 1); uvlist[2] = new Vector2(1, 0); uvlist[3] = new Vector2(0, 0); for (int i = 4; i < 20; i += 4) { uvlist[i] = new Vector2(1, 1); uvlist[i + 1] = new Vector2(0, 1); uvlist[i + 2] = new Vector2(1, 0); uvlist[i + 3] = new Vector2(0, 0); } unityMesh.uv = uvlist; _cachedQuad = new MeshDataArray() { Vertices = verts, Normals = norms, Triangles = trilist.ToArray(), Uvs = uvlist }; } } }