/////////////////////////////////////////// static async Task RequestHeight(BoundingBox regionBounds) { var request = new ElevationRequest() { Bounds = regionBounds, Row = 32, Col = 32, BingMapsKey = _ApiKey }; Response response = await request.Execute(); if (response.StatusCode != 200) { Log.Warn("Bing Maps API error:\n" + string.Join('\n', response.ErrorDetails)); return; } ElevationData data = response.ResourceSets[0].Resources[0] as ElevationData; Color[] heights = new Color[32 * 32]; for (int y = 0; y < 32; y++) { for (int x = 0; x < 32; x++) { // Mount everest is 8,848m tall heights[x + (31 - y) * 32] = Color.White * (data.Elevations[x + y * 32] / 9000.0f); } } mapHeight = new Tex(TexType.ImageNomips, TexFormat.Rgba128); mapHeight.SetColors(32, 32, heights); mapHeight.AddressMode = TexAddress.Clamp; Geo.BoundsToWorld(regionBounds, regionBounds, out mapHeightSize, out mapHeightCenter); terrain.SetHeightData(mapHeight, mapHeightSize * worldScale, mapHeightCenter * worldScale); }
public IEnumerator CreateTerrainZoom(int zoom) { Terrain t1 = GetComponent <Terrain>(); t1.basemapDistance = 10000; Latlong RBLl = HarvenSin.pixelToLatlong(new Vector2(512 * 16, 512 * 16), latlongLT, zoom); ElevationData evData = new ElevationData(); //string ElvURL = "http://dev.virtualearth.net/REST/v1/Elevation/Bounds?bounds="+ RBLl.lati+","+latlongLT.longti+","+latlongLT.lati+","+ RBLl.longti+"&rows=32&cols=32&heights=ellipsoid&key="+bingKey; //yield return StartCoroutine(evData.GetDataFormUrl(ElvURL)); yield return(StartCoroutine(evData.GetElv(latlongLT, zoom))); float[,] heightmap = evData.GetHeightMap(); //float[,] heightmap = evData.GetHeightMap(32, 32); t1.terrainData.heightmapResolution = evData.size; t1.terrainData.SetHeights(0, 0, heightmap); //yield return StartCoroutine(GetImageFormTile(latlongLT,16,16,19)); yield return(StartCoroutine(ImageDataP.GetImageFormUrl(latlongLT, 16, 16, zoom))); SplatPrototype[] sp = new SplatPrototype[1]; t1.terrainData.size = new Vector3((float)HarvenSin.Distance(latlongLT.lati, latlongLT.longti, latlongLT.lati, RBLl.longti) * 1000, 10000f, (float)HarvenSin.Distance(RBLl.lati, latlongLT.longti, latlongLT.lati, latlongLT.longti) * 1000f); sp[0] = CreateSplatPrototype(imageCombined, new Vector2(t1.terrainData.size.x, t1.terrainData.size.z), new Vector2(0f, 0f)); File.WriteAllBytes("Assets/TerrainTexture/test.jpg", imageCombined.EncodeToJPG());//output Texture t1.terrainData.splatPrototypes = sp; }
public static Vertices3[] MakeRegularMesh(ref ElevationData evData) { evData.Elev[0] = 1; int ratio = 32768 / evData.TileSize; // min = double.MaxValue; // max = double.MinValue; double fact = (evData.MaxElevation - evData.MinElevation) / 32768; Vertices3[] vertices = new Vertices3[evData.TileSize * evData.TileSize]; for (int i = 0; i < evData.TileSize; i++) { for (int j = 0; j < evData.TileSize; j++) { var pos = j + (i * evData.TileSize); var elv = evData.Elev[pos]; // if (elv < min) // min = elv; // if (elv > max) // max = elv; vertices[i] = new Vertices3((ushort)(32767 - (i * ratio)), (ushort)(32767 - (j * ratio)), ConvertRange(evData.MinElevation, evData.MaxElevation, elv)); } } return(vertices); }
/// <summary> /// Setup GridSize for tile /// </summary> private void Initialise() { QMTileResponse.ResultStatus = RequestErrorStatus.FailedToBuildQuantizedMeshTile; ResultStatus = RequestErrorStatus.FailedToBuildQuantizedMeshTile; // Determine the QM tile resolution by the zoom level if (OverrideGridSize != QMConstants.NoGridSize) { TileGridSize = OverrideGridSize; } else { if (TileZ >= QMConstants.HighResolutionLevel) { TileGridSize = QMConstants.HighResolutionGridSize; } else if (TileZ >= QMConstants.MidResolutionLevel) { TileGridSize = QMConstants.MidResolutionGridSize; } else { TileGridSize = QMConstants.FlatResolutionGridSize; } } // Setup for return. In most cases you want to at least return an empty tile ElevData = new ElevationData(LowestElevation, TileGridSize); // elevation grid }
/// <summary> /// Creates a demo tile. Useful for development /// </summary> /// <returns></returns> private bool BuildDemoTile() { _log.LogDebug($"#Tile.({TileX},{TileY}) Returning demo tile. (X:{TileX}, Y:{TileX},{TileY}, Z:{TileZ}), GridSize{QMConstants.DemoResolutionGridSize}"); // Even empty tiles must have header info correctly calculated if (ElevData.GridSize == QMConstants.NoGridSize) { ElevData = new ElevationData(LowestElevation, QMConstants.DemoResolutionGridSize); // elevation grid } ElevData.MakeDemoTile(TileBoundaryLL); QMTileBuilder tileBuilder = new QMTileBuilder() { TileData = ElevData, GridSize = ElevData.GridSize }; if (!tileBuilder.BuildQuantizedMeshTile()) { _log.LogError($"Tile.({TileX},{TileY}) failed to build demo tile. Error code: {tileBuilder.BuildTileFaultCode}"); return(false); } QMTileResponse.ResultStatus = RequestErrorStatus.OK; QMTileResponse.data = tileBuilder.QuantizedMeshTile; // return QM tile in response ResultStatus = RequestErrorStatus.OK; return(true); }
/// <summary> /// No data so return an empty tile /// </summary> /// <returns></returns> private bool BuildEmptyTile() { _log.LogDebug($"#Tile#.({TileX},{TileY}) Execute End. Returning empty tile. Zoom:{TileZ}, GridSize{QMConstants.FlatResolutionGridSize}"); // Even empty tiles must have header info correctly calculated if (ElevData.GridSize == QMConstants.NoGridSize) { ElevData = new ElevationData(LowestElevation, QMConstants.FlatResolutionGridSize); // elevation grid } ElevData.MakeEmptyTile(TileBoundaryLL, HasLighting); if (ElevData.HasLighting) { ComputeNormalMap(); } QMTileBuilder tileBuilder = new QMTileBuilder() { TileData = ElevData, GridSize = ElevData.GridSize }; if (!tileBuilder.BuildQuantizedMeshTile()) { _log.LogError($"Tile.({TileX},{TileY}) failed to build empty tile. Error code: {tileBuilder.BuildTileFaultCode}"); return(false); } QMTileResponse.ResultStatus = RequestErrorStatus.OK; QMTileResponse.data = tileBuilder.QuantizedMeshTile; // return QM tile in response ResultStatus = RequestErrorStatus.OK; return(true); }
public void GenerateElevationProfile3(GpsLocation myLocation, double visibility, ElevationProfileData elevationData, Action <int> onProgressChange) { _elevationProfileData = new ElevationProfileData(myLocation, visibility); int progress = 0; foreach (var group in elevationData.GetData()) { progress++; onProgressChange(progress); var points = group.GetPoints() .Where(i => i.Distance > MIN_DISTANCE && i.Distance < visibility * 1000) .OrderBy(i => i.Distance); //Select visible points List <GpsLocation> tmpVisiblePoints = new List <GpsLocation>(); double maxViewAngle = -90; foreach (var point in points) { if (point.VerticalViewAngle > maxViewAngle) { tmpVisiblePoints.Add(point); maxViewAngle = point.VerticalViewAngle.Value; } } //Change order (now from the furthest to the nearest) tmpVisiblePoints.Reverse(); //... and ignore points on descending slope GpsLocation lastPoint = null; GpsLocation lastAddedPoint = null; var ed = new ElevationData(group.Angle); foreach (var point in tmpVisiblePoints) { if (lastPoint == null) { ed.Add(point); lastAddedPoint = point; lastPoint = point; continue; } //TODO: comment-out the folowing if for full rendering var distanceDiff = lastPoint.Distance.Value - point.Distance.Value; if (distanceDiff < lastPoint.Distance / 100 + 50) { lastPoint = point; continue; } ed.Add(point); lastAddedPoint = point; lastPoint = point; } _elevationProfileData.Add(ed); } }
/////////////////////////////////////////// public static async Task RequestHeight(string apiKey, BoundingBox regionBounds, Action <Tex, Vec3, Vec2> OnReceivedHeight) { // Here's an elevation request! This doesn't provide an image, rather, // it gives us a grid of height values. It's limited to a maximum of // 1024 values per request, so we're only asking for a grid of 32x32 // elevations. // However! This request does work exactly within the bounds provided, // so we're getting what we expect from the results of this request. // Details about the request can be found here: // https://github.com/microsoft/BingMapsRESTToolkit/blob/master/Docs/API%20Reference.md#ElevationRequest ElevationRequest request = new ElevationRequest() { Bounds = regionBounds, Row = 32, Col = 32, BingMapsKey = apiKey }; Response response = await ServiceManager.GetResponseAsync(request); // StatusCode is a web response status code, where 200-299 means // success. Details here: // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status if (response.StatusCode < 200 || response.StatusCode >= 300) { Log.Warn("Bing Maps API error:\n" + string.Join('\n', response.ErrorDetails)); return; } // Convert the elevation data we've received into a grayscale heightmap texture! ElevationData data = response.ResourceSets[0].Resources[0] as ElevationData; Color[] heights = new Color[32 * 32]; for (int y = 0; y < 32; y++) { for (int x = 0; x < 32; x++) { float height = data.Elevations[x + y * 32] / Geo.EarthTallest; // Height data is provided upside-down, so we're flipping it with // this index on the Y axis. heights[x + (31 - y) * 32] = Color.White * height; } } // Create a texture from the elevation data! We're storing it as // Rgba128 to preserve floating point precision in the height values. Tex texture = new Tex(TexType.ImageNomips, TexFormat.Rgba128); texture.SetColors(32, 32, heights); texture.AddressMode = TexAddress.Clamp; // Our bounds should be correct, but we still need it in StereoKit // units, so convert! Geo.BoundsToWorld(regionBounds, regionBounds, out Vec3 size, out Vec2 center); // Done! Pass the results back. OnReceivedHeight(texture, size, center); }
// todo work out bounding sphere public static void ComputeHeaderInfo(ref ElevationData evlData) { int m = 0; for (int y = 0; y < evlData.GridSize; y++) { for (int x = 0; x < evlData.GridSize; x++) { // vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio), QuantizeHeight(evlData.MinElevation, evlData.MaxElevation, evlData.Elev[m])); m++; } } }
public ElevationData ParseElevationData(byte[] fileData, int offset, int dbp) { _byteReader.Seek(offset + dbp + 28); var elevationData = new ElevationData() { BlockType = _byteReader.ReadString(fileData, 1), Name = _byteReader.ReadString(fileData, 3), Size = _byteReader.ReadShort(fileData), Atmos = _byteReader.ReadShort(fileData), Calibration = _byteReader.ReadFloat(fileData), }; _dataLogger.Log("Location 5 - End of Elevation Data - at byte location - " + _byteReader.Offset); _dataLogger.Log(JsonConvert.SerializeObject(elevationData)); return(elevationData); }
public VertexData MakeQuantizedMesh(ref ElevationData evlData) { int ratio = 32767 / evlData.GridSize; VertexData vertices = new VertexData((uint)evlData.GridSize, (uint)evlData.GridSize); // data flows sw to se and up int m = 0; bool firstRow = true; for (int y = 0; y <= evlData.GridSize; y++) { for (int x = 0; x <= evlData.GridSize; x++) { vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio), QuantizeHeight(evlData.MinimumHeight, evlData.MaximumHeight, evlData.Elev[m])); m++; } } return(vertices); }
public void TileBuilder_BuildTile() { LLBoundingBox TileBoundaryLL = MapGeo.TileXYZToRectLL(0, 0, 20, out var yFlip); ElevationData elevData = new ElevationData(0, 5); elevData.MakeEmptyTile(TileBoundaryLL, false); QMTileBuilder tileBuilder = new QMTileBuilder() { TileData = elevData, GridSize = elevData.GridSize }; var res = tileBuilder.BuildQuantizedMeshTile(); res.Should().Be(true); tileBuilder.QuantizedMeshTile.Should().HaveCountGreaterOrEqualTo(162); tileBuilder.QuantizedMeshTile.Should().HaveCountLessOrEqualTo(164); }
private IEnumerator AddTerrain(Place place) { // Store current place this._place = place; // Convert lat/long to Google/Bing/AGOL tile. var tile = this._place.Location.ToTile(this._place.Level); // Get children. var children = tile.GetChildren(CHILDREN_LEVEL); // Elevation and texture variables. ElevationData el = null; Texture2D[] textures = new Texture2D[children.Length]; yield return(null); // Retrieve elevation. this.StartCoroutine(Elevation.GetHeights(tile, elevation => { el = elevation; // Construct terrain if both elevation and textures downloaded. if (textures.All(t => t != null)) { this.StartCoroutine(this.BuildTerrain(el, textures)); } })); yield return(null); // Retrieve imagery. foreach (var child in children) { this.StartCoroutine(Imagery.GetTexture(child, texture => { textures[Array.IndexOf(children, child)] = texture; // Construct terrain if both elevation and textures downloaded. if (el != null && textures.All(t => t != null)) { this.StartCoroutine(this.BuildTerrain(el, textures)); } })); } }
/// <summary> /// Make tile header record /// </summary> private void MakeHeader(ref ElevationData evData) { // todo fill in all fields correctly Header = new TerrainTileHeader() { CenterX = -4869750.60295, CenterY = 517839.417383868, CenterZ = -4005385.98852821, MinimumHeight = evData.MinElevation, MaximumHeight = evData.MaxElevation, BoundingSphereCenterX = -4869750.60295, BoundingSphereCenterY = 517839.417383868, BoundingSphereCenterZ = -4005385.98852821, BoundingSphereRadius = 832547.176047396, HorizonOcclusionPointX = -0.775337351286795, HorizonOcclusionPointY = 0.0824478037997883, HorizonOcclusionPointZ = -0.639862876673674 }; }
public static VertexData MakeQuantizedMesh(ref ElevationData evlData) { // This ratio is an integer and represents the grids intervals in a range from 0 to 32767 // GridSize should always be an odd number for best result int ratio = QMConstants.TileValueRange / (evlData.GridSize - 1); VertexData vertices = new VertexData((uint)evlData.GridSize, (uint)evlData.GridSize); // data flows sw to se and up int m = 0; for (int y = 0; y < evlData.GridSize; y++) { for (int x = 0; x < evlData.GridSize; x++) { vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio), QuantizeHeight(evlData.MinimumHeight, evlData.MaximumHeight, evlData.ElevGrid[m])); m++; } } return(vertices); }
public VertexData MakeFakeMesh(ref ElevationData evlData) { // Simple routine to convert or grid of float elevations into a format suitable for a quantized mesh of unsigned short ints VertexData vertices = new VertexData((uint)evlData.GridSize, (uint)evlData.GridSize); try { double ratio = 32767 / (double)(evlData.GridSize - 1); // data flows sw to se and up int m = 0; for (int y = 0; y < evlData.GridSize; y++) { for (int x = 0; x < evlData.GridSize; x++) { try { // todo ratio is wrong vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio), QuantizeHeight(evlData.MinimumHeight, evlData.MaximumHeight, evlData.Elev[m])); } catch (Exception ex1) { System.Diagnostics.Debug.WriteLine($"**** MakeFakeMesh Error *********:{ex1}"); } m++; } } } catch (Exception ex) { #if DEBUG System.Diagnostics.Debug.WriteLine($"**** MakeFakeMesh Error *********:{ex}"); #endif } return(vertices); }
private ElevationData GetElevationDataForAngle(ushort angle, GpsLocation myLocation, double maxDistance, ElevationTileCollection etc) { var ed = new ElevationData(angle); for (double d = 500; d < maxDistance; d += Math.Min(100, d / 100)) { var x = GpsUtils.QuickGetGeoLocation(myLocation, d, angle); //int size = d < 5000 ? 1 : 3; int size = Math.Min(((int)d / 20000) + 1, 4);//0-20:1 20-40:2 40-60:3 60-100:4 if (etc.TryGetElevation(x, out var elevation, size)) { x.Altitude = elevation; x.Distance = d; x.Bearing = angle; x.GetVerticalViewAngle(myLocation); ed.Add(x); } } return(ed); }
/// <summary> /// /// </summary> /// <param name="bbox"></param> /// <returns></returns> private ElevationData MakeTileDEM(LLBoundingBox bbox) { // Steps // Using bounding box get elevation data for tile // Calculate header info Vector3[] ecefPoints; ElevationData ed = GetData(bbox, out ecefPoints); // Work out bounding sphere TileInfo tileInfo = new TileInfo(); var hdr = tileInfo.CalculateHeaderInfo(ref ecefPoints, false); ed.CenterX = hdr.CenterX; ed.CenterY = hdr.CenterY; ed.CenterZ = hdr.CenterZ; ed.BoundingSphereCenterX = hdr.CenterX; ed.BoundingSphereCenterY = hdr.CenterY; ed.BoundingSphereCenterZ = hdr.CenterZ; ed.BoundingSphereRadius = hdr.BoundingSphereRadius; // Work out HorizonOcclusionPoint var hop = HorizonOcclusionPoint.FromPoints(ecefPoints, tileInfo.BoundingSphere); ed.HorizonOcclusionPointX = hop.X; ed.HorizonOcclusionPointY = hop.Y; ed.HorizonOcclusionPointZ = hop.Z; /* Quicker cheat method untested * ed.HorizonOcclusionPointX = hdr.CenterX; * ed.HorizonOcclusionPointY = hdr.CenterY; * ed.HorizonOcclusionPointZ = maxElev; */ // todo lighting return(ed); }
public static VertexData MakeRegularQMesh(ref ElevationData evData) { evData.Elev[0] = 1; int ratio = 32768 / evData.TileSize; double fact = (evData.MaxElevation - evData.MinElevation) / 32768; VertexData vertices = new VertexData((uint)evData.TileSize, (uint)evData.TileSize); for (int i = 0; i < evData.TileSize; i++) { for (int j = 0; j < evData.TileSize; j++) { var pos = j + (i * evData.TileSize); var elv = evData.Elev[pos]; // if (elv < min) // min = elv; // if (elv > max) // max = elv; vertices.AddVertex(pos, (ushort)(32767 - (i * ratio)), (ushort)(32767 - (j * ratio)), ConvertRange(evData.MinElevation, evData.MaxElevation, elv)); } } return(vertices); }
public async Task <byte[]> QuantizeDEMAsync(ElevationData ed) { // throw new NotImplementedException(); VertexData verts = QuantizeMesh.MakeRegularQMesh(ref ed); // Assemble tile data MakeHeader(ref ed); MakeVertexData(ed.TileSize, ref verts); MakeIndexData(); MakeEdgeIndicesData(); // var newTerrain = new TerrainTile(); var ms = new MemoryStream(); using (BinaryWriter writer = new BinaryWriter(ms)) // using (BinaryWriter writer = new BinaryWriter(File.Open(outFile, FileMode.Create))) { // write header writer.Write(Header.CenterX); writer.Write(Header.CenterY); writer.Write(Header.CenterZ); writer.Write(Header.MinimumHeight); writer.Write(Header.MaximumHeight); writer.Write(Header.BoundingSphereCenterX); writer.Write(Header.BoundingSphereCenterY); writer.Write(Header.BoundingSphereCenterZ); writer.Write(Header.BoundingSphereRadius); writer.Write(Header.HorizonOcclusionPointX); writer.Write(Header.HorizonOcclusionPointY); writer.Write(Header.HorizonOcclusionPointZ); // write vertex data EncodeVertexBuffer(VertexData); // quantize writer.Write(VertexData.vertexCount); for (int i = 0; i < VertexData.vertexCount; i++) { writer.Write(VertexData.u[i]); // longitude } for (int i = 0; i < VertexData.vertexCount; i++) { writer.Write(VertexData.v[i]); // latitude } for (int i = 0; i < VertexData.vertexCount; i++) { writer.Write(VertexData.height[i]); //heights } // write triangle indices EncodeIndices(IndexData16); writer.Write(IndexData16.triangleCount); for (int i = 0; i < IndexData16.triangleCount * 3; i++) { writer.Write(IndexData16.indices[i]); } // write west indices writer.Write(EdgeIndices16.westVertexCount); for (int i = 0; i < EdgeIndices16.westVertexCount; i++) { writer.Write(EdgeIndices16.westIndices[i]); } // write south indices writer.Write(EdgeIndices16.southVertexCount); for (int i = 0; i < EdgeIndices16.southVertexCount; i++) { writer.Write(EdgeIndices16.southIndices[i]); } // write east indices writer.Write(EdgeIndices16.eastVertexCount); for (int i = 0; i < EdgeIndices16.eastVertexCount; i++) { writer.Write(EdgeIndices16.eastIndices[i]); } // write north indices writer.Write(EdgeIndices16.northVertexCount); for (int i = 0; i < EdgeIndices16.northVertexCount; i++) { writer.Write(EdgeIndices16.northIndices[i]); } // todo normals // var bytes = File.ReadAllBytes(ms); // using (FileStream fs = new FileStream(outFile, FileMode.Create)) // using (GZipStream zipStream = new GZipStream(fs, CompressionMode.Compress, false)) // { // zipStream.Write(ms.ToArray(), 0, ms.ToArray().Length);// .Write(bytes, 0, bytes.Length); // } byte[] buffer = ms.ToArray(); // new byte[100]; return(buffer); } }
/* * https://cesium.com/blog/2013/05/09/computing-the-horizon-occlusion-point/ * private computeMagnitude(ellipsoid, position, scaledSpaceDirectionToPoint) * { * var scaledSpacePosition = ellipsoid.transformPositionToScaledSpace(position); * var magnitudeSquared = scaledSpacePosition.magnitudeSquared(); * var magnitude = Math.sqrt(magnitudeSquared); * var direction = scaledSpacePosition.divideByScalar(magnitude); * * // For the purpose of this computation, points below the ellipsoid * // are considered to be on it instead. * magnitudeSquared = Math.max(1.0, magnitudeSquared); * magnitude = Math.max(1.0, magnitude); * * var cosAlpha = direction.dot(scaledSpaceDirectionToPoint); * var sinAlpha = direction.cross(scaledSpaceDirectionToPoint).magnitude(); * var cosBeta = 1.0 / magnitude; * var sinBeta = Math.sqrt(magnitudeSquared - 1.0) * cosBeta; * * return 1.0 / (cosAlpha * cosBeta - sinAlpha * sinBeta); * } */ /// <summary> /// By LatLon /// </summary> /// <param name="bb"></param> /// <returns></returns> private ElevationData MakeTileDEM(LLBoundingBox bb) { // todo we also need to comput header info for the quantized mesh Vector2 v; v.X = 0; v.Y = 0; int x2 = 0; int y2 = 0; int PixelCount = GridSize - 1; var DoRandom = false; int HgtMode = 2; float minElev = float.PositiveInfinity; float maxElev = float.NegativeInfinity; Random rnd = new Random(); ElevationData ed = new ElevationData(GridSize); var midPt = bb.GetCenter(); // var pt2 = Coord.geo_to_ecef(new Vector3( MapUtil.Deg2Rad(midPt.Longitude), MapUtil.Deg2Rad(midPt.Latitude),0)); // zero elevation for now var pt = MapUtil.LatLonToEcef(midPt.Latitude, midPt.Longitude, 0); // zero elevation for now Vector3[] ecefPoints = new Vector3[GridSize * GridSize]; try { // we are going to walk up from sw to ne for returning dem in latlon coordinates var yRange = bb.North - bb.South; var xRange = bb.East - bb.West; var xStep = xRange / PixelCount; var yStep = yRange / PixelCount; int i = 0; float hgt = 0; for (int y = 0; y < GridSize; y++) { for (int x = 0; x < GridSize; x++) { var lat = bb.South + (y * yStep); var lon = bb.West + (x * xStep); v = MapProject(lat, lon); // MapProject is lat long if (v.X >= Width) { v.X = Width - 1; } if (v.Y >= Depth) { v.Y = Depth - 1; } if (v.X < 0) { v.X = 0; } if (v.Y < 0) { v.Y = 0; } x2 = (int)v.X; y2 = (int)v.Y; //hgt = 0; // if (i == 4) // hgt = 100; if (HgtMode == 1) { ed.Elev[i] = rnd.Next(1, 8000); } else if (HgtMode == 2) { ed.Elev[i] = 0; if (lat >= -43.548006 & lat <= -43.547679) { if (lon >= 172.632951 & lon <= 172.633542) { ed.Elev[i] = (float)10.0; } } } else { hgt = Map.GetPixel(x2, y2).GetBrightness(); // 0=black, 1= white ed.Elev[i] = MapUtil.Lerp(0, 1, ElevMin, ElevMax, hgt); } if (ed.Elev[i] < minElev) { minElev = ed.Elev[i]; } if (ed.Elev[i] > maxElev) { maxElev = ed.Elev[i]; } // Make ecef point list for later calculations ecefPoints[i] = Coord.geo_to_ecef(new Vector3() { X = MapUtil.Deg2Rad(lon), Y = MapUtil.Deg2Rad(lat), Z = ed.Elev[i] }); i++; } } } catch (Exception ex) { #if DEBUG System.Diagnostics.Debug.WriteLine($"**** MakeTileDEM Exception ****:{ex} v:{v} x2{x2} y2{y2} "); // file writer System.Diagnostics.Trace.WriteLine($"**** MakeTileDEM Exception *********:{ex} v:{v} x2{x2} y2{y2} "); #endif } // todo now make a ecfc array to calculate header info TileInfo tileInfo = new TileInfo(); var hdr = tileInfo.CalculateHeaderInfo(ref ecefPoints, false); ed.CenterX = hdr.CenterX; ed.CenterY = hdr.CenterY; ed.CenterZ = hdr.CenterZ; ed.BoundingSphereCenterX = hdr.CenterX; ed.BoundingSphereCenterY = hdr.CenterY; ed.BoundingSphereCenterZ = hdr.CenterZ; ed.BoundingSphereRadius = hdr.BoundingSphereRadius; ed.MaximumHeight = maxElev; ed.MinimumHeight = minElev; var hop = HorizonOcclusionPoint.FromPoints(ecefPoints, tileInfo.BoundingSphere); ed.HorizonOcclusionPointX = hop.X; ed.HorizonOcclusionPointY = hop.Y; ed.HorizonOcclusionPointZ = hop.Z; /* * // FIXME: is there a better choice for a horizon occlusion point? * // Currently it's the center of tile elevated to bbox's max Z * header.horizon_occlusion = c; * header.horizon_occlusion.z = bbox.max.z; * * * ed.HorizonOcclusionPointX = hdr.CenterX; * ed.HorizonOcclusionPointY = hdr.CenterY; * ed.HorizonOcclusionPointZ = maxElev; */ return(ed); }
private IEnumerator AddTerrain(Place place) { // Store current place this._place = place; // Convert lat/long to Google/Bing/AGOL tile. var tile = this._place.Location.ToTile(this._place.Level); // Get children. //var children = tile.GetChildren(CHILDREN_LEVEL); var children = tile.GetNeighbor(CHILDREN_LEVEL); // Elevation and texture variables. ElevationData el = null; Texture2D[] textures = new Texture2D[children.Length]; yield return(null); // Retrieve elevation. if (currentDimension == "3D") { this.StartCoroutine(Elevation.GetHeights(tile, elevation => { el = elevation; // Construct terrain if both elevation and textures downloaded. if (textures.All(t => t != null)) { this.StartCoroutine(this.BuildTerrain(el, textures)); } })); yield return(null); } // Retrieve imagery. foreach (var child in children) { this.StartCoroutine(Imagery.GetTexture(child, currentStyle, texture => { textures[Array.IndexOf(children, child)] = texture; // Construct terrain if both elevation and textures downloaded. //if (el != null && textures.All(t => t != null)) if (textures.All(t => t != null)) { this.StartCoroutine(this.BuildTerrain(el, textures)); } })); } //add 2 /* * if (needupdate) * { * this.StartCoroutine(this.Updatemap(updateURL)); * //destroy all exist building,erase the items form * GameObject[] gameObjects = GameObject.FindGameObjectsWithTag("Rotate"); * for (var i = 0; i < gameObjects.Length; i++) * { * Destroy(gameObjects[i]); * } * //StartCoroutine(Eraseitems(queryURL)); * } */ }
public async override Task <ElevationData> GetDemLL(double lonMin, double latMin, double lonMax, double latMax) { // create grid of uniform heights var dem = new ElevationData(); dem.MinimumHeight = float.MaxValue; dem.MaximumHeight = float.MinValue; dem.GridSize = GridSize; float hgt; dem.Elev = new float[GridSize * GridSize]; // elevation order will be from sw, se, and up // old standard example form Cesium code for tilesize 1, 2 triangles. slopes from nw to se if (GridSize == 2) { dem.Elev[0] = 100; dem.Elev[1] = 200; dem.Elev[2] = 0; dem.Elev[3] = 100; dem.MinimumHeight = 0; dem.MaximumHeight = 400; } else if (GridSize == 3) { dem.Elev[0] = 0; dem.Elev[1] = 0; dem.Elev[2] = 0; dem.Elev[3] = 0; dem.Elev[4] = 100; dem.Elev[5] = 0; dem.Elev[6] = 0; dem.Elev[7] = 0; dem.Elev[8] = 0; dem.MinimumHeight = 0; dem.MaximumHeight = 100; } else { //Basic slope. Todo staircase hgt = 0; int pos = 0; for (int y = 0; y < GridSize; y++) { for (int x = 0; x < GridSize; x++) { if (x == 0 || y == 0) { dem.Elev[pos] = 0; } else { dem.Elev[pos] = hgt; } if (hgt < dem.MinimumHeight) { dem.MinimumHeight = hgt; } if (hgt > dem.MaximumHeight) { dem.MaximumHeight = hgt; } pos++; } if (y > GridSize / 2) { hgt = hgt + (float)-0.5; } else { hgt = hgt + (float)0.5; } } } return(dem); }
private ElevationData GetData(LLBoundingBox bbox, out Vector3[] ecefPoints) { //todo get data from TRex //Boolean dataAvailable = true; // if ((lat >= -43.548006 & lat <= -43.547679) & (lon >= 172.632951 & lon <= 172.633542)) ElevationData ed; LLBoundingBox data = new LLBoundingBox(172.632951, -43.548006, 172.633542, -43.547679); bool dataAvailable = data.East >= bbox.West && data.West <= bbox.East && data.North >= bbox.South && data.South <= bbox.North; LLBoundingBox data2 = new LLBoundingBox(-0.124629, 51.500745, 1.0, 51.6); bool dataAvailable2 = data2.East >= bbox.West && data2.West <= bbox.East && data2.North >= bbox.South && data2.South <= bbox.North; int _gridSize; if (dataAvailable | dataAvailable2) { _gridSize = GridSize; } else { _gridSize = 2; } ed = new ElevationData(_gridSize); ecefPoints = new Vector3[_gridSize * _gridSize]; int PixelCount = _gridSize - 1; var yRange = bbox.North - bbox.South; var xRange = bbox.East - bbox.West; var xStep = xRange / PixelCount; var yStep = yRange / PixelCount; float minElev = float.PositiveInfinity; float maxElev = float.NegativeInfinity; Random rnd = new Random(); int i = 0; float hgt = 0; var HgtMode = 2; for (int y = 0; y < GridSize; y++) { for (int x = 0; x < GridSize; x++) { var lat = bbox.South + (y * yStep); var lon = bbox.West + (x * xStep); if (HgtMode == 1) { ed.Elev[i] = rnd.Next(1, 8000); } else if (HgtMode == 2) { if ((lat >= -43.548006 & lat <= -43.547679) & (lon >= 172.632951 & lon <= 172.633542)) { ed.Elev[i] = (float)10.0; } else if ((lat >= 51.500745 & lat <= 51.6) & (lon >= -0.124629 & lon <= 1.0)) { ed.Elev[i] = rnd.Next(1, 10); } else { ed.Elev[i] = 0; } } if (ed.Elev[i] < minElev) { minElev = ed.Elev[i]; } if (ed.Elev[i] > maxElev) { maxElev = ed.Elev[i]; } // Make ecef point list for later header calculations ecefPoints[i] = Coord.geo_to_ecef(new Vector3() { X = MapUtil.Deg2Rad(lon), Y = MapUtil.Deg2Rad(lat), Z = ed.Elev[i] }); i++; } } ed.MaximumHeight = maxElev; ed.MinimumHeight = minElev; return(ed); }
private IEnumerator BuildTerrain(ElevationData elevation, Texture2D[] textures) { GameObject tc = GameObject.Find("terrain"); if (tc != null) { GameObject.Destroy(tc); } yield return(null); // Center position of terrain. var position = this.transform.position; position -= new Vector3(SIZE / 2, 0, SIZE / 2); // Create terrain game object. GameObject terrainObject = new GameObject("terrain"); terrainObject.transform.position = position; terrainObject.transform.parent = this.transform; yield return(null); // Create terrain data. TerrainData terrainData = new TerrainData(); terrainData.heightmapResolution = 33; terrainData.size = new Vector3(SIZE, HEIGHT, SIZE); terrainData.alphamapResolution = 32; terrainData.baseMapResolution = 1024; terrainData.SetDetailResolution(1024, 8); yield return(null); // Tiles per side. var dimension = (int)Math.Sqrt(textures.Length); // Splat maps. var splats = new List <SplatPrototype>(); foreach (var texture in textures) { splats.Add(new SplatPrototype() { tileOffset = new Vector2(0, 0), tileSize = new Vector2( SIZE / dimension, SIZE / dimension ), texture = texture }); yield return(null); } terrainData.splatPrototypes = splats.ToArray(); terrainData.RefreshPrototypes(); yield return(null); // Get tile var tile = this._place.Location.ToTile(this._place.Level); // Construct height map. float[,] data = new float[ terrainData.heightmapWidth, terrainData.heightmapHeight ]; for (int x = 0; x < terrainData.heightmapWidth; x++) { for (int y = 0; y < terrainData.heightmapHeight; y++) { // Scale elevation from 257x257 to 33x33 var x2 = Convert.ToInt32((double)x * 256 / (terrainData.heightmapWidth - 1)); var y2 = Convert.ToInt32((double)y * 256 / (terrainData.heightmapHeight - 1)); // Find index in Esri elevation array var id = y2 * 257 + x2; // Absolute height in map units. var h1 = elevation.Heights[id]; // Height in model units. var h2 = SIZE * (h1 - elevation.Min) / tile.Size; // Apply exaggeration. var h3 = h2 * VERTICAL_EXAGGERATION; // Apply base offset. var h4 = h3 + TERRAIN_BASE_HEIGHT; // Final height. data[terrainData.heightmapHeight - 1 - y, x] = h4; } } terrainData.SetHeights(0, 0, data); yield return(null); // Add alpha mapping //float[,,] maps = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight); var maps = new float[ terrainData.alphamapWidth, terrainData.alphamapHeight, textures.Length ]; for (int y = 0; y < terrainData.alphamapHeight; y++) { for (int x = 0; x < terrainData.alphamapWidth; x++) { // Convert alpha coordinates into tile index. Left to right, bottom to top. var tilex = x / (terrainData.alphamapWidth / dimension); var tiley = y / (terrainData.alphamapHeight / dimension); var index = (dimension - tiley - 1) * dimension + tilex; for (int t = 0; t < textures.Length; t++) { maps[y, x, t] = index == t ? 1f : 0f; } } } terrainData.SetAlphamaps(0, 0, maps); yield return(null); // Create terrain collider. TerrainCollider terrainCollider = terrainObject.AddComponent <TerrainCollider>(); terrainCollider.terrainData = terrainData; yield return(null); // Add terrain component. Terrain terrain = terrainObject.AddComponent <Terrain>(); terrain.terrainData = terrainData; yield return(null); // Calculate mesh vertices and triangles. List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); // Distance between vertices var step = SIZE / 32f; // Front for (int x = 0; x < terrainData.heightmapWidth; x++) { vertices.Add(new Vector3(x * step, 0f, 0f)); vertices.Add(new Vector3(x * step, data[0, x], 0f)); } yield return(null); // Right for (int z = 0; z < terrainData.heightmapHeight; z++) { vertices.Add(new Vector3(SIZE, 0f, z * step)); vertices.Add(new Vector3(SIZE, data[z, terrainData.heightmapWidth - 1], z * step)); } yield return(null); // Back for (int x = 0; x < terrainData.heightmapWidth; x++) { var xr = terrainData.heightmapWidth - 1 - x; vertices.Add(new Vector3(xr * step, 0f, SIZE)); vertices.Add(new Vector3(xr * step, data[terrainData.heightmapHeight - 1, xr], SIZE)); } yield return(null); // Left for (int z = 0; z < terrainData.heightmapHeight; z++) { var zr = terrainData.heightmapHeight - 1 - z; vertices.Add(new Vector3(0f, 0f, zr * step)); vertices.Add(new Vector3(0f, data[zr, 0], zr * step)); } yield return(null); // Quads for (int i = 0; i < vertices.Count / 2 - 1; i++) { triangles.AddRange(new int[] { 2 * i + 0, 2 * i + 1, 2 * i + 2, 2 * i + 2, 2 * i + 1, 2 * i + 3 }); } // Create single mesh for all four sides GameObject side = new GameObject("side"); side.transform.position = position; side.transform.parent = terrainObject.transform; yield return(null); // Create mesh Mesh mesh = new Mesh() { vertices = vertices.ToArray(), triangles = triangles.ToArray() }; mesh.RecalculateNormals(); mesh.RecalculateBounds(); yield return(null); MeshFilter meshFilter = side.AddComponent <MeshFilter>(); meshFilter.mesh = mesh; yield return(null); MeshRenderer meshRenderer = side.AddComponent <MeshRenderer>(); meshRenderer.material = new Material(Shader.Find("Standard")) { color = new Color32(0, 128, 128, 100) }; yield return(null); MeshCollider meshCollider = side.AddComponent <MeshCollider>(); yield return(null); buttonObject = Instantiate(buttonZoomPrefab, terrainObject.transform.position + new Vector3(0, 0.2f, 0), Quaternion.Euler(0, -90, 0)) as StableMenu; buttonObject.transform.parent = terrain.transform; yield return(null); }