/// <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; Point3d 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, 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 Matrix4d SkyGradientTrans; Point3d cameraCoord = MathEngine.CartesianToSpherical(cameraPos.X, cameraPos.Y, cameraPos.Z); double camLat = cameraCoord.Y; double camLon = cameraCoord.Z; SkyGradientTrans = Matrix4d.Translation(0, 0, distToCenterOfPlanet); SkyGradientTrans = Matrix4d.Multiply(SkyGradientTrans, Matrix4d.RotationY(-camLat + Math.PI / 2)); SkyGradientTrans = Matrix4d.Multiply(SkyGradientTrans, Matrix4d.RotationZ(camLon)); device.Transform.World = ConvertDX.FromMatrix4d(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? double aspectRatio = (double)device.Viewport.Width / device.Viewport.Height; device.Transform.Projection = ConvertDX.FromMatrix4d(Matrix4d.PerspectiveFovRH(camera.Fov.Radians, aspectRatio, 1000, 30000000.0)); // 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); double a = camera.Altitude; device.RenderState.FogEnable = true; device.RenderState.FogColor = horizonColor; device.RenderState.FogTableMode = FogMode.Linear; device.RenderState.FogStart = (float)(a * nearFactor); device.RenderState.FogEnd = (float)(tangentalDistance * farFactor); } }