Esempio n. 1
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;

            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);
            }
        }