using Mapbox.Vector.Tile; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using UnityEngine.Networking; namespace Wander { public struct PolygonIndices { public List<int> indices; } public class VectorTile { bool valid; bool finished; bool triangulated; internal UnityWebRequestAsyncOperation request; bool Valid => valid; bool Finished => finished; Task parseTileTask; // These lists must match. List<VectorTileLayer> layers; List<List<PolygonIndices>> polygonIndices; bool IsFinished() { if (finished) return true; if (!request.isDone) return false; if (request.webRequest.result == UnityWebRequest.Result.Success) { if (parseTileTask == null) { parseTileTask = Task.Run( () => { var stream = new MemoryStream( request.webRequest.downloadHandler.data ); layers = VectorTileParser.Parse( stream ); } ); } else if (parseTileTask.IsCompleted) { valid = parseTileTask.IsCompletedSuccessfully; finished = true; parseTileTask = null; } } return finished; } void Triangulate() { polygonIndices = new List<List<PolygonIndices>>(); List<double> vertices = new List<double>(); List<int> holeIndices = new List<int>(); for ( int i =0; i < layers.Count; i++ ) { var features = layers[i].VectorTileFeatures; var featurePolygonIndices = new List<PolygonIndices>(); polygonIndices.Add( featurePolygonIndices ); for (int j = 0; j< features.Count; j++) { if (features[j].GeometryType != Tile.GeomType.Polygon) continue; vertices.Clear(); holeIndices.Clear(); var rings = features[j].Geometry; for (int k = 0;k < rings.Count;k++) { if (k != 0) // if is not first ring, this is a hole { holeIndices.Add( vertices.Count ); } var ring = rings[k]; for (int q = 0;q < ring.Count;q++) { vertices.Add( ring[q].X ); vertices.Add( ring[q].Y ); } } PolygonIndices polyIndices = new PolygonIndices(); polyIndices.indices = EarcutNet.Earcut.Tessellate( vertices, holeIndices ); featurePolygonIndices.Add( polyIndices ); } } } } public static class VectorTileLoader { public static VectorTile LoadFromUrl( string url ) { VectorTile tile = new VectorTile(); tile.request = UnityWebRequest.Get( url ).SendWebRequest(); return tile; } } }