public void UpdateTerrainElevation(TerrainAccessor terrainAccessor) { // Update camera terrain elevation if (terrainAccessor != null) { if (Altitude < 300000) { if (System.DateTime.Now - this.lastElevationUpdate > TimeSpan.FromMilliseconds(500)) { float elevation; // Under camera target elevation = terrainAccessor.GetCachedElevationAt(Latitude.Degrees, Longitude.Degrees); TerrainElevation = float.IsNaN(elevation) ? (short)0 : (short)elevation; // Under the camera itself Vector3 cameraPos = Position; Vector3 cameraCoord = MathEngine.CartesianToSpherical(cameraPos.X, cameraPos.Y, cameraPos.Z); double camLat = MathEngine.RadiansToDegrees(cameraCoord.Y); double camLon = MathEngine.RadiansToDegrees(cameraCoord.Z); elevation = terrainAccessor.GetCachedElevationAt(camLat, camLon); TerrainElevationUnderCamera = float.IsNaN(elevation) ? (short)0 : (short)elevation; if (TerrainElevationUnderCamera < 0 && !World.Settings.AllowNegativeAltitude) { TerrainElevationUnderCamera = 0; } // reset timer this.lastElevationUpdate = System.DateTime.Now; } } else { TerrainElevation = 0; TerrainElevationUnderCamera = 0; } } else { TerrainElevation = 0; TerrainElevationUnderCamera = 0; } }
/// <summary> /// This is where we do our rendering /// Called from UI thread = UI code safe in this function /// </summary> public override void Render(DrawArgs drawArgs) { if (!isInitialized || (this.world.Name == "Earth" && World.Settings.EnableAtmosphericScattering)) { return; } // Camera & Device shortcuts ;) CameraBase camera = drawArgs.WorldCamera; Device device = drawArgs.device; //if(camera.Altitude > 200e3) return; Vector3 cameraPos = camera.Position; double distToCenterOfPlanet = (camera.Altitude + camera.WorldRadius); // Create or refresh SkyGradient dome if (mesh == null || lastAltitude != camera.Altitude) { // Compute distance to horizon and dome radius double tangentalDistance = Math.Sqrt(distToCenterOfPlanet * distToCenterOfPlanet - camera.WorldRadius * camera.WorldRadius); double domeRadius = tangentalDistance; // horizon latitude double horizonLat = (-Math.PI / 2 + Math.Acos(tangentalDistance / distToCenterOfPlanet)) * 180 / Math.PI; // zenith latitude double zenithLat = 90; if (camera.Altitude >= thickness) { double tangentalDistanceZenith = Math.Sqrt(distToCenterOfPlanet * distToCenterOfPlanet - (camera.WorldRadius + thickness) * (camera.WorldRadius + thickness)); zenithLat = (-Math.PI / 2 + Math.Acos(tangentalDistanceZenith / distToCenterOfPlanet)) * 180 / Math.PI; } if (camera.Altitude < thickness && camera.Altitude > thickness * 0.8) { zenithLat = (thickness - camera.Altitude) / (thickness - thickness * 0.8) * 90; } // new mesh if (mesh != null) { mesh.Dispose(); } mesh = ColoredSphere(device, (float)domeRadius, horizonLat, zenithLat, 128, 24); lastAltitude = camera.Altitude; } // set texture to null device.SetTexture(0, null); device.TextureState[0].ColorOperation = TextureOperation.BlendCurrentAlpha; device.VertexFormat = CustomVertex.PositionColored.Format; // save world and projection transform Matrix origWorld = device.Transform.World; Matrix origProjection = device.Transform.Projection; // move SkyGradient dome Matrix SkyGradientTrans; Vector3 cameraCoord = MathEngine.CartesianToSpherical(cameraPos.X, cameraPos.Y, cameraPos.Z); float camLat = cameraCoord.Y; float camLon = cameraCoord.Z; SkyGradientTrans = Matrix.Translation(0, 0, (float)distToCenterOfPlanet); SkyGradientTrans = Matrix.Multiply(SkyGradientTrans, Matrix.RotationY(-camLat + (float)Math.PI / 2)); SkyGradientTrans = Matrix.Multiply(SkyGradientTrans, Matrix.RotationZ(camLon)); device.Transform.World = SkyGradientTrans; // Recenter Recenter(drawArgs); // Save fog status bool origFog = device.RenderState.FogEnable; device.RenderState.FogEnable = false; // Set new one (to avoid being clipped) - probably better ways of doing this? float aspectRatio = (float)device.Viewport.Width / device.Viewport.Height; device.Transform.Projection = Matrix.PerspectiveFovRH((float)camera.Fov.Radians, aspectRatio, 1, float.MaxValue); // draw //device.RenderState.FillMode = FillMode.WireFrame; mesh.DrawSubset(0); // Restore device states device.RenderState.FillMode = FillMode.Solid; device.Transform.World = origWorld; device.Transform.Projection = origProjection; device.RenderState.FogEnable = origFog; device.RenderState.ZBufferEnable = true; // Fog effect if (useFog) { // Compute distance to horizon and camera altitude double tangentalDistance = Math.Sqrt(distToCenterOfPlanet * distToCenterOfPlanet - camera.WorldRadius * camera.WorldRadius); float a = (float)camera.Altitude; device.RenderState.FogEnable = true; device.RenderState.FogColor = horizonColor; device.RenderState.FogTableMode = FogMode.Linear; device.RenderState.FogStart = a * nearFactor; device.RenderState.FogEnd = (float)tangentalDistance * farFactor; } }