public override void Run(VectorFeatureUnity feature, MeshData md, UnityTile tile = null) { scaledX = tile.Rect.Size.x * tile.TileScale; scaledY = tile.Rect.Size.y * tile.TileScale; _counter = md.Vertices.Count; if (_counter > 0) { for (int i = 0; i < _counter; i++) { var h = tile.QueryHeightData( (float)((md.Vertices[i].x + md.PositionInTile.x + scaledX / 2) / scaledX), (float)((md.Vertices[i].z + md.PositionInTile.z + scaledY / 2) / scaledY)); md.Vertices[i] += new Vector3(0, h, 0); } } else { foreach (var sub in feature.Points) { _counter = sub.Count; for (int i = 0; i < _counter; i++) { var h = tile.QueryHeightData( (float)((sub[i].x + md.PositionInTile.x + scaledX / 2) / scaledX), (float)((sub[i].z + md.PositionInTile.z + scaledY / 2) / scaledY)); sub[i] += new Vector3(0, h, 0); } } } }
public override void Run(VectorFeatureUnity feature, MeshData md, UnityTile tile = null) { // TODO: Get this from tile as IMapReadable. float worldScale = FindObjectOfType <AbstractMap>().WorldRelativeScale; if (md.Vertices.Count > 0) { for (int i = 0; i < md.Vertices.Count; i++) { var h = tile.QueryHeightData((float)((md.Vertices[i].x + tile.Rect.Size.x / 2) / tile.Rect.Size.x), (float)((md.Vertices[i].z + tile.Rect.Size.y / 2) / tile.Rect.Size.y)); RaycastHit hit; Vector3 rayCenter = new Vector3(md.Vertices[i].x * worldScale + tile.transform.position.x, h * worldScale + RAY_LENGTH / 2, md.Vertices[i].z * worldScale + tile.transform.position.z); if (Physics.Raycast(rayCenter, Vector3.down, out hit, RAY_LENGTH, _terrainMask)) { md.Vertices[i] += new Vector3(0, hit.point.y / worldScale, 0); } else { // Raycasting sometimes fails at terrain boundaries, fallback to tile height data. md.Vertices[i] += new Vector3(0, h, 0); } } } else { foreach (var sub in feature.Points) { for (int i = 0; i < sub.Count; i++) { var h = tile.QueryHeightData((float)((sub[i].x + tile.Rect.Size.x / 2) / tile.Rect.Size.x), (float)((sub[i].z + tile.Rect.Size.y / 2) / tile.Rect.Size.y)); RaycastHit hit; Vector3 rayCenter = new Vector3(sub[i].x * worldScale + tile.transform.position.x, h * worldScale + RAY_LENGTH / 2, sub[i].z * worldScale + tile.transform.position.z); if (Physics.Raycast(rayCenter, Vector3.down, out hit, RAY_LENGTH, _terrainMask)) { sub[i] += new Vector3(0, hit.point.y / worldScale, 0); } else { // Raycasting sometimes fails at terrain boundaries, fallback to tile height data. sub[i] += new Vector3(0, h, 0); } } } } }
/* * Get the altitude of a lnt/lat location */ float GetLocationHeight(Vector2d location) { //Get tile ID var tileIDUnwrapped = TileCover.CoordinateToTileId(new Mapbox.Utils.Vector2d(location[0], location[1]), (int)map.Zoom); //Get tile try { UnityTile tile = map.MapVisualizer.GetUnityTileFromUnwrappedTileId(tileIDUnwrapped); //Lat lon to meters because the tiles rect is also in meters Vector2d v2d = Conversions.LatLonToMeters(new Mapbox.Utils.Vector2d(location[0], location[1])); //Get the origin of the tile in meters Vector2d v2dcenter = tile.Rect.Center - new Mapbox.Utils.Vector2d(tile.Rect.Size.x / 2, tile.Rect.Size.y / 2); //Offset between the tile origin and the lat lon point Vector2d diff = v2d - v2dcenter; //Maping the diffetences to (0-1) float Dx = (float)(diff.x / tile.Rect.Size.x); float Dy = (float)(diff.y / tile.Rect.Size.y); //returns height in unity units return(tile.QueryHeightData(Dx, Dy)); } catch (Exception e) { Mapbox.Unity.Utilities.Console.Instance.Log("ERROR", "red"); } return(480f); }
public double HeightForPrefab(double lat, double lon, BasicMap _map) { //get tile ID //Debug.Log("lat: " + lat + ", long: " + lon); var tileIDUnwrapped = TileCover.CoordinateToTileId(new Mapbox.Utils.Vector2d(lat, lon), 15); // Debug.Log(tileIDUnwrapped); //get tile UnityTile tile = _map._mapVisualizer.GetUnityTileFromUnwrappedTileId(tileIDUnwrapped); //lat lon to meters because the tiles rect is also in meters Vector2d v2d = Conversions.LatLonToMeters(new Mapbox.Utils.Vector2d(lat, lon)); //get the origin of the tile in meters Vector2d v2dcenter = tile.Rect.Center - new Mapbox.Utils.Vector2d(tile.Rect.Size.x / 2, tile.Rect.Size.y / 2); //offset between the tile origin and the lat lon point Vector2d diff = v2d - v2dcenter; //maping the diffetences to (0-1) float Dx = (float)(diff.x / tile.Rect.Size.x); float Dy = (float)(diff.y / tile.Rect.Size.y); //height in unity units var h = tile.QueryHeightData(Dx, Dy); //lat lon to unity units Vector3 location = Conversions.GeoToWorldPosition(lat, lon, _map.CenterMercator, _map.WorldRelativeScale).ToVector3xz(); //replace y in position location = new Vector3(location.x, h, location.z); //Debug.Log("our height is: " + h); return(h); }
public override void Run(VectorFeatureUnity feature, MeshData md, UnityTile tile = null) { scaledX = tile.Rect.Size.x * tile.TileScale; scaledY = tile.Rect.Size.y * tile.TileScale; foreach (var sub in feature.Points) { for (int i = 0; i < sub.Count; i++) { var h = tile.QueryHeightData((float)((sub[i].x + md.PositionInTile.x + scaledX / 2) / scaledX), (float)((sub[i].z + md.PositionInTile.z + scaledY / 2) / scaledY)); RaycastHit hit; Vector3 rayCenter = new Vector3(sub[i].x + md.PositionInTile.x + tile.transform.position.x, h + RAY_LENGTH / 2, sub[i].z + md.PositionInTile.z + tile.transform.position.z); if (Physics.Raycast(rayCenter, Vector3.down, out hit, RAY_LENGTH * 5, _terrainMask)) { sub[i] += new Vector3(0, hit.point.y + md.PositionInTile.y - tile.transform.position.y, 0); } else { // Raycasting sometimes fails at terrain boundaries, fallback to tile height data. sub[i] += new Vector3(0, h, 0); } } } }
private void GenerateCubes(UnityTile tile, float size, float exaggeration, float baseScale) { for (int i = 0; i < subdivs; i++) { for (int j = 0; j < subdivs; j++) { float y = tile.QueryHeightData((float)i / subdivs, (float)j / subdivs); if (y < 0.01f) { continue; } Vector2 gradient = new Vector2( tile.QueryHeightData((float)i / subdivs + 1f / subdivs, (float)j / subdivs) - tile.QueryHeightData((float)i / subdivs - 1f / subdivs, (float)j / subdivs) , tile.QueryHeightData((float)i / subdivs, (float)j / subdivs + 1f / subdivs) - tile.QueryHeightData((float)i / subdivs, (float)j / subdivs - 1f / subdivs) ); // if(gradient.magnitude < 1.5f && y > 2f) continue; // possible optimization int cliffs = 1 + (int)(gradient.magnitude / 1.5f); float rot = Random.Range(0, 90); for (int k = 0; k < cliffs; k++) { GameObject cube = Instantiate(rockPrefab, tile.transform.position, tile.transform.rotation); cube.transform.SetParent(tile.transform); cube.transform.localPosition = new Vector3( -size / 2 + (float)i / subdivs * size, y * exaggeration, -size / 2 + (float)j / subdivs * size ); cube.transform.localScale = new Vector3( baseScale * 1.5f + k * 0.5f * baseScale, (1f + gradient.magnitude * 2f) * exaggeration / (1 + k), baseScale * 1.5f + k * 0.5f * baseScale ); cube.transform.Rotate(0, rot, 0); } } } }
public override void Run(VectorFeatureUnity feature, MeshData md, UnityTile tile = null) { if (md.Vertices.Count > 0) { for (int i = 0; i < md.Vertices.Count; i++) { var h = tile.QueryHeightData((float)((md.Vertices[i].x + tile.Rect.Size.x / 2) / tile.Rect.Size.x), (float)((md.Vertices[i].z + tile.Rect.Size.y / 2) / tile.Rect.Size.y)); md.Vertices[i] += new Vector3(0, h, 0); } } else { foreach (var sub in feature.Points) { for (int i = 0; i < sub.Count; i++) { var h = tile.QueryHeightData((float)((sub[i].x + tile.Rect.Size.x / 2) / tile.Rect.Size.x), (float)((sub[i].z + tile.Rect.Size.y / 2) / tile.Rect.Size.y)); sub[i] += new Vector3(0, h, 0); } } } }
private void Build(VectorFeatureUnity feature, UnityTile tile, GameObject parent) { if (!feature.Points.Any()) { return; } int selpos = feature.Points[0].Count / 2; var met = feature.Points[0][selpos]; if (Math.Abs(met.x) > Math.Abs(tile.Rect.Size.x) / 2 || Math.Abs(met.y) > Math.Abs(tile.Rect.Size.y) / 2) { return; } if (!feature.Properties.ContainsKey("name")) { return; } var go = Instantiate(PoiPrefab); go.name = _key + " " + feature.Data.Id.ToString(); var rx = (met.x - tile.Rect.Min.x) / tile.Rect.Size.x; var ry = 1 - (met.z - tile.Rect.Min.y) / tile.Rect.Size.y; var h = tile.QueryHeightData((int)rx, (int)ry); met.y += h; go.transform.position = met; go.transform.SetParent(parent.transform, false); if (!_scaleDownWithWorld) { go.transform.localScale = Vector3.one / go.transform.lossyScale.x; } var bd = go.AddComponent <FeatureBehaviour>(); bd.Init(feature); var tm = go.GetComponent <IFeaturePropertySettable>(); if (tm != null) { tm.Set(feature.Properties); } }
/// <summary> /// Apply Snap World to Zero setting by moving map in Y Axis such that /// center of the given tile will be at y=0. /// </summary> /// <param name="referenceTile">Tile to use for Y axis correction.</param> private void ApplySnapWorldToZero(UnityTile referenceTile) { if (_options.placementOptions.snapMapToZero) { var h = referenceTile.QueryHeightData(.5f, .5f); Root.transform.position = new Vector3( Root.transform.position.x, -h, Root.transform.position.z); } else { Root.transform.position = new Vector3( Root.transform.position.x, 0, Root.transform.position.z); } }
public float getHeightAt(float lat, float lon) { UnityTile tile = getTileAt(lat, lon); //lat lon to meters because the tiles rect is also in meters Vector2d v2d = Conversions.LatLonToMeters(new Vector2d(lat, lon)); //get the origin of the tile in meters Vector2d v2dcenter = tile.Rect.Center - new Vector2d(tile.Rect.Size.x / 2.0, tile.Rect.Size.y / 2.0); //offset between the tile origin and the lat lon point Vector2d diff = v2d - v2dcenter; //maping the diffetences to (0-1) float Dx = (float)(diff.x / tile.Rect.Size.x); float Dy = (float)(diff.y / tile.Rect.Size.y); //height in unity units float h = tile.QueryHeightData(Dx, Dy); return(h / tile.TileScale); //return height_in_meter }
private void Build(VectorFeatureUnity feature, UnityTile tile, GameObject parent) { //go.layer = LayerMask.NameToLayer(_key); if (!feature.Points.Any()) { return; } int selpos = feature.Points[0].Count / 2; var met = Conversions.LatLonToMeters(feature.Points[0][selpos].Lat, feature.Points[0][selpos].Lng); if (!tile.Rect.Contains(met, true)) { return; } if (!feature.Properties.ContainsKey("name")) { return; } var go = Instantiate(PoiPrefab); go.name = _key + " " + feature.Data.Id.ToString(); var pos = met.ToVector3xz() - tile.Rect.center.ToVector3xz(); var rx = (pos.x - tile.Rect.min.x) / tile.Rect.width; var ry = 1 - (pos.z - tile.Rect.min.y) / tile.Rect.height; var h = tile.QueryHeightData(rx, ry); pos.y += h; go.transform.position = pos; go.transform.SetParent(parent.transform, false); var bd = go.AddComponent <FeatureBehaviour>(); bd.Init(feature); var tm = go.GetComponent <ILabelVisualizationHelper>(); tm.Initialize(feature.Properties); }
private float GetHeight(double lat, double lon, UnwrappedTileId tileIDUnwrapped) { float height; //get tile UnityTile tile = map.MapVisualizer.GetUnityTileFromUnwrappedTileId(tileIDUnwrapped); //lat lon to meters because the tiles rect is also in meters Vector2d v2d = Conversions.LatLonToMeters(new Mapbox.Utils.Vector2d(lat, lon)); //get the origin of the tile in meters Vector2d v2dcenter = tile.Rect.Center - new Mapbox.Utils.Vector2d(tile.Rect.Size.x / 2, tile.Rect.Size.y / 2); //offset between the tile origin and the lat lon point Vector2d diff = v2d - v2dcenter; //maping the diffetences to (0-1) float Dx = (float)(diff.x / tile.Rect.Size.x); float Dy = (float)(diff.y / tile.Rect.Size.y); height = tile.QueryHeightData(Dx, Dy); return(height); }
private void Build(VectorFeatureUnity feature, UnityTile tile, GameObject parent) { if (!feature.Points.Any()) { return; } int selpos = feature.Points[0].Count / 2; var met = feature.Points[0][selpos]; if (Math.Abs(met.x) > Math.Abs(tile.Rect.Size.x) / 2 || Math.Abs(met.y) > Math.Abs(tile.Rect.Size.y) / 2) { return; } if (!feature.Properties.ContainsKey("name")) { return; } var go = Instantiate(PoiPrefab); go.name = _key + " " + feature.Data.Id.ToString(); var rx = (met.x - tile.Rect.Min.x) / tile.Rect.Size.x; var ry = 1 - (met.z - tile.Rect.Min.y) / tile.Rect.Size.y; var h = tile.QueryHeightData((float)rx, (float)ry); met.y += h; go.transform.position = met; go.transform.SetParent(parent.transform, false); var bd = go.AddComponent <FeatureBehaviour>(); bd.Init(feature); var tm = go.GetComponent <ILabelVisualizationHelper>(); tm.Initialize(feature.Properties); }
public float getAltitudeHeightLevel(double lat, double lon, float zoom) { UnwrappedTileId tileIDUnwrapped = TileCover.CoordinateToTileId(new Mapbox.Utils.Vector2d(lat, lon), (int)zoom); //get tile UnityTile tile = _mapManager.MapVisualizer.GetUnityTileFromUnwrappedTileId(tileIDUnwrapped); //lat lon to meters because the tiles rect is also in meters Vector2d v2d = Conversions.LatLonToMeters(new Mapbox.Utils.Vector2d(lat, lon)); //get the origin of the tile in meters Vector2d v2dcenter = tile.Rect.Center - new Mapbox.Utils.Vector2d(tile.Rect.Size.x / 2, tile.Rect.Size.y / 2); //offset between the tile origin and the lat lon point Vector2d diff = v2d - v2dcenter; //maping the diffetences to (0-1) float Dx = (float)(diff.x / tile.Rect.Size.x); float Dy = (float)(diff.y / tile.Rect.Size.y); //height in unity units float h = tile.QueryHeightData(Dx, Dy); return(h); }
/// <summary> /// Creates the non-flat terrain mesh, using a grid by defined resolution (_sampleCount). Vertex order goes right & up. Normals are calculated manually and UV map is fitted/stretched 1-1. /// Any additional scripts or logic, like MeshCollider or setting layer, can be done here. /// </summary> /// <param name="tile"></param> /// <param name="heightMultiplier">Multiplier for queried height value</param> private void GenerateTerrainMesh(UnityTile tile) { #if UNITY_5_5_OR_NEWER tile.MeshFilter.mesh.GetVertices(_currentTileMeshData.Vertices); tile.MeshFilter.mesh.GetNormals(_currentTileMeshData.Normals); #else _currentTileMeshData.Vertices.Clear(); _currentTileMeshData.Vertices.AddRange(tile.MeshFilter.mesh.vertices); _currentTileMeshData.Normals.Clear(); _currentTileMeshData.Normals.AddRange(tile.MeshFilter.mesh.normals); #endif var cap = (_sampleCount - 1); for (float y = 0; y < cap; y++) { for (float x = 0; x < cap; x++) { _currentTileMeshData.Vertices[(int)(y * cap + x) * 6] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6].x, tile.QueryHeightData(x / cap, 1 - y / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6].z); _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1].x, tile.QueryHeightData((x + 1) / cap, 1 - y / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1].z); _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2].x, tile.QueryHeightData(x / cap, 1 - (y + 1) / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2].z); //-- _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3].x, tile.QueryHeightData((x + 1) / cap, 1 - y / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3].z); _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4].x, tile.QueryHeightData((x + 1) / cap, 1 - (y + 1) / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4].z); _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5].x, tile.QueryHeightData(x / cap, 1 - (y + 1) / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5].z); _newDir = Vector3.Cross(_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6], _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6]); _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 0] = _newDir; _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 1] = _newDir; _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 2] = _newDir; //-- _newDir = Vector3.Cross(_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3], _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3]); _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 3] = _newDir; _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 4] = _newDir; _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 5] = _newDir; } } FixStitches(tile.UnwrappedTileId, _currentTileMeshData); tile.MeshFilter.mesh.SetVertices(_currentTileMeshData.Vertices); tile.MeshFilter.mesh.SetNormals(_currentTileMeshData.Normals); tile.MeshFilter.mesh.RecalculateBounds(); if (!_meshData.ContainsKey(tile.UnwrappedTileId)) { _meshData.Add(tile.UnwrappedTileId, tile.MeshFilter.mesh); } }
private void Build(VectorFeatureUnity feature, UnityTile tile, GameObject parent) { if (feature.Properties.ContainsKey("extrude") && !bool.Parse(feature.Properties["extrude"].ToString())) { return; } foreach (var geometry in feature.Points) { var meshData = new MeshData(); meshData.TileRect = tile.Rect; if (geometry.Count <= 1) { continue; } System.Object sel = null; if (string.IsNullOrEmpty(_classificationKey)) { sel = feature.Properties.ContainsKey("type") ? feature.Properties["type"] : feature.Properties["class"]; } else if (feature.Properties.ContainsKey(_classificationKey)) { sel = feature.Properties[_classificationKey].ToString().ToLowerInvariant(); } else { continue; } //we'll run all visualizers on MeshData here var list = geometry.Select(x => Conversions.LatLonToMeters(x.Lat, x.Lng).ToVector3xz()).ToList(); if (true) { var verts = new List <Vector3>(); if (list.Count > 1) { for (int i = 0; i < list.Count - 1; i++) { verts.Add(list[i]); var dist = Vector3.Distance(list[i], list[i + 1]); var step = System.Math.Min(40f, dist / 10); if (step > 1) { var counter = 1; while (counter < step) { var nv = Vector3.Lerp(list[i], list[i + 1], Mathf.Min(1, counter / step)); verts.Add(nv); counter++; } } } } verts.Add(list.Last()); list = verts; } meshData.Vertices = list.Select(vertex => { var cord = vertex - tile.Rect.center.ToVector3xz(); var rx = (vertex.x - tile.Rect.min.x) / tile.Rect.width; var ry = 1 - (vertex.z - tile.Rect.min.y) / tile.Rect.height; var h = tile.QueryHeightData(rx, ry); cord.y += h; //BRNKHY TODO height is broken if (feature.Properties.ContainsKey("min_height")) { var min_height = Convert.ToSingle(feature.Properties["min_height"]); cord.y += min_height; } return(cord); }).ToList(); var mod = Stacks.FirstOrDefault(x => x.Type.Contains(sel.ToString().ToLowerInvariant())); GameObject go; if (mod != null) { go = mod.Stack.Execute(feature, meshData, parent, mod.Type); } else { if (_defaultStack != null) { go = _defaultStack.Execute(feature, meshData, parent, _key); } } //go.layer = LayerMask.NameToLayer(_key); } }
/// <summary> /// Creates the non-flat terrain mesh, using a grid by defined resolution (_sampleCount). Vertex order goes right & up. Normals are calculated manually and UV map is fitted/stretched 1-1. /// Any additional scripts or logic, like MeshCollider or setting layer, can be done here. /// </summary> /// <param name="tile"></param> // <param name="heightMultiplier">Multiplier for queried height value</param> private void GenerateTerrainMesh(UnityTile tile) { tile.MeshFilter.sharedMesh.GetVertices(_currentTileMeshData.Vertices); tile.MeshFilter.sharedMesh.GetNormals(_currentTileMeshData.Normals); var cap = (_elevationOptions.modificationOptions.sampleCount - 1); for (float y = 0; y < cap; y++) { for (float x = 0; x < cap; x++) { _currentTileMeshData.Vertices[(int)(y * cap + x) * 6] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6].x, tile.QueryHeightData(x / cap, 1 - y / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6].z); _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1].x, tile.QueryHeightData((x + 1) / cap, 1 - y / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1].z); _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2].x, tile.QueryHeightData(x / cap, 1 - (y + 1) / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2].z); //-- _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3].x, tile.QueryHeightData((x + 1) / cap, 1 - y / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3].z); _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4].x, tile.QueryHeightData((x + 1) / cap, 1 - (y + 1) / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4].z); _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5] = new Vector3( _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5].x, tile.QueryHeightData(x / cap, 1 - (y + 1) / cap), _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5].z); _newDir = Vector3.Cross(_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6], _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6]); _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 0] = _newDir; _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 1] = _newDir; _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 2] = _newDir; //-- _newDir = Vector3.Cross(_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3], _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3]); _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 3] = _newDir; _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 4] = _newDir; _currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 5] = _newDir; } } FixStitches(tile.UnwrappedTileId, _currentTileMeshData); tile.MeshFilter.sharedMesh.SetVertices(_currentTileMeshData.Vertices); tile.MeshFilter.sharedMesh.SetNormals(_currentTileMeshData.Normals); tile.MeshFilter.sharedMesh.RecalculateBounds(); if (!_meshData.ContainsKey(tile.UnwrappedTileId)) { _meshData.Add(tile.UnwrappedTileId, tile.MeshFilter.sharedMesh); } if (_elevationOptions.colliderOptions.addCollider) { var meshCollider = tile.Collider as MeshCollider; if (meshCollider) { meshCollider.sharedMesh = tile.MeshFilter.sharedMesh; } } }
/// <summary> /// Preprocess features, finds the relevant modifier stack and passes the feature to that stack /// </summary> /// <param name="feature"></param> /// <param name="tile"></param> /// <param name="parent"></param> private void Build(VectorFeatureUnity feature, UnityTile tile, GameObject parent) { if (feature.Properties.ContainsKey("extrude") && !bool.Parse(feature.Properties["extrude"].ToString())) { return; } //we're not cutting out the holes yet foreach (var geometry in feature.Points) { var meshData = new MeshData(); meshData.TileRect = tile.Rect; if (geometry.Count <= 1) { continue; } //this will be improved in next version and will probably be replaced by filters string styleSelectorKey = ""; if (string.IsNullOrEmpty(_classificationKey)) { if (feature.Properties.ContainsKey("type")) { styleSelectorKey = feature.Properties["type"].ToString().ToLowerInvariant(); } else if (feature.Properties.ContainsKey("class")) { styleSelectorKey = feature.Properties["class"].ToString().ToLowerInvariant(); } } else if (feature.Properties.ContainsKey(_classificationKey)) { if (feature.Properties.ContainsKey(_classificationKey)) { styleSelectorKey = feature.Properties[_classificationKey].ToString().ToLowerInvariant(); } } //we'll run all visualizers on MeshData here var list = geometry; //.Select(x => Conversions.GeoToWorldPosition(x.Lat, x.Lng, tile.Rect.Center).ToVector3xz()).ToList(); //long straight edges looks bad on bumpy terrain if (_subdivideLongEdges) { var verts = new List <Vector3>(); if (list.Count > 1) { for (int i = 0; i < list.Count - 1; i++) { verts.Add(list[i]); var dist = Vector3.Distance(list[i], list[i + 1]); var step = Math.Min(_maxEdgeSectionCount, dist / _preferredEdgeSectionLength); if (step > 1) { var counter = 1; while (counter < step) { var nv = Vector3.Lerp(list[i], list[i + 1], Mathf.Min(1, counter / step)); verts.Add(nv); counter++; } } } } verts.Add(list.Last()); list = verts; } //adding terrain & building min_height to vertices //we may move this into height modifier in the future meshData.Vertices = list.Select(vertex => { var h = tile.QueryHeightData((float)((vertex.x + tile.Rect.Size.x / 2) / tile.Rect.Size.x), (float)((vertex.z + tile.Rect.Size.y / 2) / tile.Rect.Size.y)); vertex += new Vector3(0, h, 0); if (feature.Properties.ContainsKey("min_height")) { var min_height = Convert.ToSingle(feature.Properties["min_height"]); vertex += new Vector3(0, min_height, 0); } return(vertex); }).ToList(); //and finally, running the modifier stack on the feature var mod = Stacks.FirstOrDefault(x => x.Type.Contains(styleSelectorKey)); GameObject go; if (mod != null) { go = mod.Stack.Execute(tile, feature, meshData, parent, mod.Type); } else { if (_defaultStack != null) { go = _defaultStack.Execute(tile, feature, meshData, parent, _key); } } //go.layer = LayerMask.NameToLayer(_key); } }
private void GenerateTerrainMesh(UnityTile tile) { tile.MeshFilter.mesh.GetVertices(_currentTileMeshData.Vertices); tile.MeshFilter.mesh.GetNormals(_currentTileMeshData.Normals); var _sampleCount = _elevationOptions.modificationOptions.sampleCount; for (float y = 0; y < _sampleCount; y++) { for (float x = 0; x < _sampleCount; x++) { _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)] = new Vector3( _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)].x, tile.QueryHeightData(x / (_sampleCount - 1), 1 - y / (_sampleCount - 1)), _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)].z); _currentTileMeshData.Normals[(int)(y * _sampleCount + x)] = Mapbox.Unity.Constants.Math.Vector3Zero; } } tile.MeshFilter.mesh.SetVertices(_currentTileMeshData.Vertices); for (int y = 0; y < _sampleCount - 1; y++) { for (int x = 0; x < _sampleCount - 1; x++) { _vertA = (y * _sampleCount) + x; _vertB = (y * _sampleCount) + x + _sampleCount + 1; _vertC = (y * _sampleCount) + x + _sampleCount; _newDir = Vector3.Cross(_currentTileMeshData.Vertices[_vertB] - _currentTileMeshData.Vertices[_vertA], _currentTileMeshData.Vertices[_vertC] - _currentTileMeshData.Vertices[_vertA]); _currentTileMeshData.Normals[_vertA] += _newDir; _currentTileMeshData.Normals[_vertB] += _newDir; _currentTileMeshData.Normals[_vertC] += _newDir; _vertA = (y * _sampleCount) + x; _vertB = (y * _sampleCount) + x + 1; _vertC = (y * _sampleCount) + x + _sampleCount + 1; _newDir = Vector3.Cross(_currentTileMeshData.Vertices[_vertB] - _currentTileMeshData.Vertices[_vertA], _currentTileMeshData.Vertices[_vertC] - _currentTileMeshData.Vertices[_vertA]); _currentTileMeshData.Normals[_vertA] += _newDir; _currentTileMeshData.Normals[_vertB] += _newDir; _currentTileMeshData.Normals[_vertC] += _newDir; } } FixStitches(tile.UnwrappedTileId, _currentTileMeshData); tile.MeshFilter.mesh.SetNormals(_currentTileMeshData.Normals); tile.MeshFilter.mesh.SetVertices(_currentTileMeshData.Vertices); tile.MeshFilter.mesh.RecalculateBounds(); if (!_meshData.ContainsKey(tile.UnwrappedTileId)) { _meshData.Add(tile.UnwrappedTileId, tile.MeshFilter.mesh); } if (_elevationOptions.requiredOptions.addCollider) { var meshCollider = tile.Collider as MeshCollider; if (meshCollider) { meshCollider.sharedMesh = tile.MeshFilter.mesh; } } }
/// <summary> /// Creates the non-flat terrain mesh, using a grid by defined resolution (_sampleCount). Vertex order goes right & up. Normals are calculated manually and UV map is fitted/stretched 1-1. /// Any additional scripts or logic, like MeshCollider or setting layer, can be done here. /// </summary> /// <param name="tile"></param> /// <param name="heightMultiplier">Multiplier for queried height value</param> private void GenerateTerrainMesh(UnityTile tile) { #if UNITY_5_5_OR_NEWER tile.MeshFilter.mesh.GetVertices(_currentTileMeshData.Vertices); tile.MeshFilter.mesh.GetNormals(_currentTileMeshData.Normals); #else _currentTileMeshData.Vertices.Clear(); _currentTileMeshData.Vertices.AddRange(tile.MeshFilter.mesh.vertices); _currentTileMeshData.Normals.Clear(); _currentTileMeshData.Normals.AddRange(tile.MeshFilter.mesh.normals); #endif for (float y = 0; y < _sampleCount; y++) { for (float x = 0; x < _sampleCount; x++) { _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)] = new Vector3( _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)].x, tile.QueryHeightData(x / (_sampleCount - 1), 1 - y / (_sampleCount - 1)), _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)].z); _currentTileMeshData.Normals[(int)(y * _sampleCount + x)] = Unity.Constants.Math.Vector3Zero; } } tile.MeshFilter.mesh.SetVertices(_currentTileMeshData.Vertices); for (int y = 0; y < _sampleCount - 1; y++) { for (int x = 0; x < _sampleCount - 1; x++) { _vertA = (y * _sampleCount) + x; _vertB = (y * _sampleCount) + x + _sampleCount + 1; _vertC = (y * _sampleCount) + x + _sampleCount; _newDir = Vector3.Cross(_currentTileMeshData.Vertices[_vertB] - _currentTileMeshData.Vertices[_vertA], _currentTileMeshData.Vertices[_vertC] - _currentTileMeshData.Vertices[_vertA]); _currentTileMeshData.Normals[_vertA] += _newDir; _currentTileMeshData.Normals[_vertB] += _newDir; _currentTileMeshData.Normals[_vertC] += _newDir; _vertA = (y * _sampleCount) + x; _vertB = (y * _sampleCount) + x + 1; _vertC = (y * _sampleCount) + x + _sampleCount + 1; _newDir = Vector3.Cross(_currentTileMeshData.Vertices[_vertB] - _currentTileMeshData.Vertices[_vertA], _currentTileMeshData.Vertices[_vertC] - _currentTileMeshData.Vertices[_vertA]); _currentTileMeshData.Normals[_vertA] += _newDir; _currentTileMeshData.Normals[_vertB] += _newDir; _currentTileMeshData.Normals[_vertC] += _newDir; } } FixStitches(tile.CanonicalTileId, _currentTileMeshData); tile.MeshFilter.mesh.SetNormals(_currentTileMeshData.Normals); tile.MeshFilter.mesh.SetVertices(_currentTileMeshData.Vertices); tile.MeshFilter.mesh.RecalculateBounds(); if (!_meshData.ContainsKey(tile.CanonicalTileId)) { _meshData.Add(tile.CanonicalTileId, tile.MeshFilter.mesh); } if (_addCollider) { var meshCollider = tile.Collider as MeshCollider; if (meshCollider) { meshCollider.sharedMesh = tile.MeshFilter.mesh; } } }