/// <summary> /// Get the terrain elevation map corresponding to the specified position. /// </summary> /// <param name="viewPosition"> /// The <see cref="Vertex2d"/> that specify the current view position, using an absolute cartesian reference system. /// </param> /// <returns> /// It returns the <see cref="Image"/> that contains the terrain elevation data corresponding to <paramref name="viewPosition"/>. /// </returns> public Image GetTerrainElevationMap(Vertex2d viewPosition) { // Apply clipmap offset double lodUnitScale = Math.Pow(2.0, Lod) * UnitScale; Vertex2d texturePositionOffset = viewPosition - _CurrentViewPosition; texturePositionOffset /= lodUnitScale; // Determine whether an texture update is not required bool xNormOffset = texturePositionOffset.x > -1.0 && texturePositionOffset.x < 1.0; bool yNormOffset = texturePositionOffset.y > -1.0 && texturePositionOffset.y < 1.0; if (xNormOffset && yNormOffset && _TerrainElevationInitialized) { return(null); } // Discard fractional part, move towards zero texturePositionOffset = new Vertex2d(Math.Truncate(texturePositionOffset.x), Math.Truncate(texturePositionOffset.y)); // Determine the dataset section to load Vertex2d rasterPosition = _CurrentTexPosition + (texturePositionOffset * Math.Pow(2.0, Lod)); double w2 = _TerrainElevation.Width / 2, h2 = _TerrainElevation.Height / 2; // Specify the LOD 0 size // Note: the dataset should have overviews, in order to make CPU friendly update w2 *= Math.Pow(2.0, Lod); h2 *= Math.Pow(2.0, Lod); double x1 = rasterPosition.x - w2, x2 = rasterPosition.x + w2; double y1 = rasterPosition.y - h2, y2 = rasterPosition.y + h2; Rectangle datasetSection = new Rectangle(); datasetSection.X = (int)Math.Floor(x1); datasetSection.Y = (int)Math.Floor(y1); datasetSection.Width = (int)Math.Floor(x2 - x1); Debug.Assert(datasetSection.Width % _TerrainElevation.Width == 0); datasetSection.Height = (int)Math.Floor(y2 - y1); Debug.Assert(datasetSection.Height % _TerrainElevation.Height == 0); // Update current terrain elevation, following the updated position ImageCodecCriteria datasetCriteria = new ImageCodecCriteria(); datasetCriteria.ImageSection = datasetSection; GdalImageCodecPlugin.Load_GrayIndex(_DatabaseDataset, 1, datasetCriteria, _TerrainElevation); // Update current positions _CurrentTexPosition = rasterPosition; _CurrentViewPosition = _CurrentViewPosition + (texturePositionOffset * lodUnitScale);; // Trace.TraceInformation("Texture LOD {0} reposition: {1}", Lod, _CurrentTexPosition); // Allow first time initialization _TerrainElevationInitialized = true; return(_TerrainElevation); }
/// <summary> /// Static constructor. /// </summary> static Terrain() { GdalImageCodecPlugin.AllRegister(); }