Ejemplo n.º 1
0
        /// <summary>
        /// Used to update information affecting the SkyMesh
        /// </summary>
        public void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
        {
            // Adjust dome position so the bottom edge is not visible
            Vector3 ViewerXNAPosition   = new Vector3(MSTSSkyViewer.Camera.Location.X, MSTSSkyViewer.Camera.Location.Y - 100, -MSTSSkyViewer.Camera.Location.Z);
            Matrix  XNASkyWorldLocation = Matrix.CreateTranslation(ViewerXNAPosition);

            if (mstsskyworldLoc == null)
            {
                // First time around, initialize the following items:
                mstsskyworldLoc       = new WorldLatLon();
                skySteps.OldClockTime = MSTSSkyViewer.Simulator.ClockTime % 86400;
                while (skySteps.OldClockTime < 0)
                {
                    skySteps.OldClockTime += 86400;
                }
                skySteps.Step1 = skySteps.Step2 = (int)(skySteps.OldClockTime / 1200);
                skySteps.Step2 = skySteps.Step2 < skySteps.MaxSteps - 1 ? skySteps.Step2 + 1 : 0; // limit to max. steps in case activity starts near midnight
                                                                                                  // Get the current latitude and longitude coordinates
                mstsskyworldLoc.ConvertWTC(MSTSSkyViewer.Camera.TileX, MSTSSkyViewer.Camera.TileZ, MSTSSkyViewer.Camera.Location, ref mstsskylatitude, ref mstsskylongitude);
                if (mstsskyseasonType != (int)MSTSSkyViewer.Simulator.Season)
                {
                    mstsskyseasonType = (int)MSTSSkyViewer.Simulator.Season;
                    date.ordinalDate  = mstsskylatitude >= 0 ? 82 + mstsskyseasonType * 91 : (82 + (mstsskyseasonType + 2) * 91) % 365;
                    // TODO: Set the following three externally from ORTS route files (future)
                    date.month = 1 + date.ordinalDate / 30;
                    date.day   = 21;
                    date.year  = 2017;
                }
                // Fill in the sun- and moon-position lookup tables
                for (int i = 0; i < skySteps.MaxSteps; i++)
                {
                    mstsskysolarPosArray[i] = SunMoonPos.SolarAngle(mstsskylatitude, mstsskylongitude, ((float)i / skySteps.MaxSteps), date);
                    mstsskylunarPosArray[i] = SunMoonPos.LunarAngle(mstsskylatitude, mstsskylongitude, ((float)i / skySteps.MaxSteps), date);
                }
                // Phase of the moon is generated at random
                mstsskymoonPhase = Viewer.Random.Next(8);
                if (mstsskymoonPhase == 6 && date.ordinalDate > 45 && date.ordinalDate < 330)
                {
                    mstsskymoonPhase = 3; // Moon dog only occurs in winter
                }
                // Overcast factor: 0.0=almost no clouds; 0.1=wispy clouds; 1.0=total overcast
                //mstsskyovercastFactor = MSTSSkyViewer.World.WeatherControl.overcastFactor;
                mstsskyfogDistance = MSTSSkyViewer.Simulator.Weather.FogDistance;
            }

            MPManager manager = MPManager.Instance();

            if (MPManager.IsClient() && manager.weatherChanged)
            {
                //received message about weather change
                if (manager.overcastFactor >= 0)
                {
                    mstsskyovercastFactor = manager.overcastFactor;
                }

                //received message about weather change
                if (manager.fogDistance > 0)
                {
                    mstsskyfogDistance = manager.fogDistance;
                }

                if (manager.overcastFactor >= 0 || manager.fogDistance > 0)
                {
                    manager.weatherChanged = false;
                    manager.overcastFactor = -1;
                    manager.fogDistance    = -1;
                }
            }

            ////////////////////// T E M P O R A R Y ///////////////////////////

            // The following keyboard commands are used for viewing sky and weather effects in "demo" mode.
            // Control- and Control+ for overcast, Shift- and Shift+ for fog and - and + for time.

            // Don't let multiplayer clients adjust the weather.
            if (!MPManager.IsClient())
            {
                // Overcast ranges from 0 (completely clear) to 1 (completely overcast).
                if (UserInput.IsDown(UserCommand.DebugOvercastIncrease))
                {
                    mstsskyovercastFactor = MathHelper.Clamp(mstsskyovercastFactor + elapsedTime.RealSeconds / 10, 0, 1);
                }
                if (UserInput.IsDown(UserCommand.DebugOvercastDecrease))
                {
                    mstsskyovercastFactor = MathHelper.Clamp(mstsskyovercastFactor - elapsedTime.RealSeconds / 10, 0, 1);
                }
                // Fog ranges from 10m (can't see anything) to 100km (clear arctic conditions).
                if (UserInput.IsDown(UserCommand.DebugFogIncrease))
                {
                    mstsskyfogDistance = MathHelper.Clamp(mstsskyfogDistance - elapsedTime.RealSeconds * mstsskyfogDistance, 10, 100000);
                }
                if (UserInput.IsDown(UserCommand.DebugFogDecrease))
                {
                    mstsskyfogDistance = MathHelper.Clamp(mstsskyfogDistance + elapsedTime.RealSeconds * mstsskyfogDistance, 10, 100000);
                }
            }
            // Don't let clock shift if multiplayer.
            if (!MPManager.IsMultiPlayer())
            {
                // Shift the clock forwards or backwards at 1h-per-second.
                if (UserInput.IsDown(UserCommand.DebugClockForwards))
                {
                    MSTSSkyViewer.Simulator.ClockTime += elapsedTime.RealSeconds * 3600;
                }
                if (UserInput.IsDown(UserCommand.DebugClockBackwards))
                {
                    MSTSSkyViewer.Simulator.ClockTime -= elapsedTime.RealSeconds * 3600;
                }
            }
            // Server needs to notify clients of weather changes.
            if (MPManager.IsServer())
            {
                if (UserInput.IsReleased(UserCommand.DebugOvercastIncrease) || UserInput.IsReleased(UserCommand.DebugOvercastDecrease) || UserInput.IsReleased(UserCommand.DebugFogIncrease) || UserInput.IsReleased(UserCommand.DebugFogDecrease))
                {
                    manager.SetEnvInfo(mstsskyovercastFactor, mstsskyfogDistance);
                    MPManager.Notify(new MSGWeather(-1, mstsskyovercastFactor, -1, mstsskyfogDistance).ToString());
                }
            }

            skySteps.SetSunAndMoonDirection(ref mstsskysolarDirection, ref mstsskylunarDirection, ref mstsskysolarPosArray, ref mstsskylunarPosArray,
                                            MSTSSkyViewer.Simulator.ClockTime);

            frame.AddPrimitive(MSTSSkyMaterial, MSTSSkyMesh, RenderPrimitiveGroup.Sky, ref XNASkyWorldLocation);
        }
Ejemplo n.º 2
0
            public void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime, Matrix xnaTileTranslation)
            {
                var initialise = DisplayState == -1;

                if (DisplayState != SignalHead.draw_state)
                {
#if DEBUG_SIGNAL_SHAPES
                    Console.WriteLine("{5} {0} signal {1} unit {2} state: {3} --> {4}",
                                      SignalShape.Location, SignalShape.UID, Index, DisplayState,
                                      SignalHead.draw_state, InfoDisplay.FormattedTime(Viewer.Simulator.ClockTime));
#endif
                    DisplayState = SignalHead.draw_state;
                    if (SignalTypeData.DrawAspects.ContainsKey(DisplayState))
                    {
                        SemaphoreTarget = SignalTypeData.DrawAspects[DisplayState].SemaphorePos;
                        SemaphoreSpeed  = SignalTypeData.SemaphoreAnimationTime <= 0 ? 0 : (SemaphoreTarget > SemaphorePos ? +1 : -1) / SignalTypeData.SemaphoreAnimationTime;
                        if (Sound != null)
                        {
                            Sound.HandleEvent(Event.SemaphoreArm);
                        }
                    }
                }

                CumulativeTime += elapsedTime.ClockSeconds;
                while (CumulativeTime > SignalTypeData.FlashTimeTotal)
                {
                    CumulativeTime -= SignalTypeData.FlashTimeTotal;
                }

                if (DisplayState < 0 || !SignalTypeData.DrawAspects.ContainsKey(DisplayState))
                {
                    return;
                }

                if (SignalTypeData.Semaphore)
                {
                    // We reset the animation matrix before preparing the lights, because they need to be positioned
                    // based on the original matrix only.
                    foreach (AnimatedPart SemaphorePart in SemaphoreParts)
                    {
                        SemaphorePart.SetFrameWrap(0);
                    }
                }

                for (var i = 0; i < SignalTypeData.Lights.Count; i++)
                {
                    SignalLightState state         = lightStates[i];
                    bool             semaphoreDark = SemaphorePos != SemaphoreTarget && SignalTypeData.LightsSemaphoreChange[i];
                    bool             constantDark  = !SignalTypeData.DrawAspects[DisplayState].DrawLights[i];
                    bool             flashingDark  = SignalTypeData.DrawAspects[DisplayState].FlashLights[i] && (CumulativeTime > SignalTypeData.FlashTimeOn);
                    state.UpdateIntensity(semaphoreDark || constantDark || flashingDark ? 0 : 1, elapsedTime);
                    if (!state.IsIlluminated())
                    {
                        continue;
                    }

                    bool isDay;
                    if (Viewer.Settings.UseMSTSEnv == false)
                    {
                        isDay = Viewer.World.Sky.solarDirection.Y > 0;
                    }
                    else
                    {
                        isDay = Viewer.World.MSTSSky.mstsskysolarDirection.Y > 0;
                    }
                    bool isPoorVisibility = Viewer.Simulator.Weather.FogDistance < 200;
                    if (!SignalTypeData.DayLight && isDay && !isPoorVisibility)
                    {
                        continue;
                    }

                    var slp       = SignalTypeData.Lights[i];
                    var xnaMatrix = Matrix.CreateTranslation(slp.Position);

                    foreach (int MatrixIndex in MatrixIndices)
                    {
                        Matrix.Multiply(ref xnaMatrix, ref SignalShape.XNAMatrices[MatrixIndex], out xnaMatrix);
                    }
                    Matrix.Multiply(ref xnaMatrix, ref xnaTileTranslation, out xnaMatrix);

                    void renderEffect(Material material)
                    {
                        frame.AddPrimitive(material, slp, RenderPrimitiveGroup.Lights, ref xnaMatrix, ShapeFlags.None, state);
                    }

                    renderEffect(SignalTypeData.Material);
                    if (Viewer.Settings.SignalLightGlow)
                    {
                        renderEffect(SignalTypeData.GlowMaterial);
                    }
                }

                if (SignalTypeData.Semaphore)
                {
                    // Now we update and re-animate the semaphore arm.
                    if (SignalTypeData.SemaphoreAnimationTime <= 0 || initialise)
                    {
                        // No timing (so instant switch) or we're initialising.
                        SemaphorePos   = SemaphoreTarget;
                        SemaphoreSpeed = 0;
                    }
                    else
                    {
                        // Animate slowly to target position.
                        SemaphorePos += SemaphoreSpeed * elapsedTime.ClockSeconds;
                        if (SemaphorePos * Math.Sign(SemaphoreSpeed) > SemaphoreTarget * Math.Sign(SemaphoreSpeed))
                        {
                            SemaphorePos   = SemaphoreTarget;
                            SemaphoreSpeed = 0;
                        }
                    }
                    foreach (AnimatedPart SemaphorePart in SemaphoreParts)
                    {
                        SemaphorePart.SetFrameCycle(SemaphorePos);
                    }
                }
            }
Ejemplo n.º 3
0
        public void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
        {
            if (UpdateState())
            {
                foreach (var lightPrimitive in LightPrimitives)
                {
                    lightPrimitive.UpdateState(this);
                }
#if DEBUG_LIGHT_STATES
                Console.WriteLine();
#endif
                UpdateActiveLightCone();
            }

            foreach (var lightPrimitive in LightPrimitives)
            {
                lightPrimitive.PrepareFrame(frame, elapsedTime);
            }

            int    dTileX = Car.WorldPosition.TileX - Viewer.Camera.TileX;
            int    dTileZ = Car.WorldPosition.TileZ - Viewer.Camera.TileZ;
            Matrix xnaDTileTranslation = Matrix.CreateTranslation(dTileX * 2048, 0, -dTileZ * 2048);  // object is offset from camera this many tiles
            xnaDTileTranslation = Car.WorldPosition.XNAMatrix * xnaDTileTranslation;

            Vector3 mstsLocation = new Vector3(xnaDTileTranslation.Translation.X, xnaDTileTranslation.Translation.Y, -xnaDTileTranslation.Translation.Z);

            float objectRadius          = 20;                              // Even more arbitrary.
            float objectViewingDistance = Viewer.Settings.ViewingDistance; // Arbitrary.
            if (Viewer.Camera.CanSee(mstsLocation, objectRadius, objectViewingDistance))
            {
                foreach (var lightPrimitive in LightPrimitives)
                {
                    if (lightPrimitive.Enabled || lightPrimitive.FadeOut)
                    {
                        if (lightPrimitive is LightGlowPrimitive)
                        {
                            frame.AddPrimitive(LightGlowMaterial, lightPrimitive, RenderPrimitiveGroup.Lights, ref xnaDTileTranslation);
                        }
                    }
                }
            }

#if DEBUG_LIGHT_CONE
            foreach (var lightPrimitive in LightPrimitives)
            {
                if (lightPrimitive.Enabled || lightPrimitive.FadeOut)
                {
                    if (lightPrimitive is LightConePrimitive)
                    {
                        frame.AddPrimitive(LightConeMaterial, lightPrimitive, RenderPrimitiveGroup.Lights, ref xnaDTileTranslation);
                    }
                }
            }
#endif

            // Set the active light cone info for the material code.
            if (HasLightCone && ActiveLightCone != null)
            {
                LightConePosition   = Vector3.Transform(Vector3.Lerp(ActiveLightCone.Position1, ActiveLightCone.Position2, ActiveLightCone.Fade.Y), xnaDTileTranslation);
                LightConeDirection  = Vector3.Transform(Vector3.Lerp(ActiveLightCone.Direction1, ActiveLightCone.Direction2, ActiveLightCone.Fade.Y), Car.WorldPosition.XNAMatrix);
                LightConeDirection -= Car.WorldPosition.XNAMatrix.Translation;
                LightConeDirection.Normalize();
                LightConeDistance      = MathHelper.Lerp(ActiveLightCone.Distance1, ActiveLightCone.Distance2, ActiveLightCone.Fade.Y);
                LightConeMinDotProduct = (float)Math.Cos(MathHelper.Lerp(ActiveLightCone.Angle1, ActiveLightCone.Angle2, ActiveLightCone.Fade.Y));
                LightConeColor         = Vector4.Lerp(ActiveLightCone.Color1, ActiveLightCone.Color2, ActiveLightCone.Fade.Y);
            }
        }
Ejemplo n.º 4
0
        public void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
        {
            // Adjust dome position so the bottom edge is not visible
            Vector3 ViewerXNAPosition   = new Vector3(Viewer.Camera.Location.X, Viewer.Camera.Location.Y - 100, -Viewer.Camera.Location.Z);
            Matrix  XNASkyWorldLocation = Matrix.CreateTranslation(ViewerXNAPosition);

            if (worldLoc == null)
            {
                // First time around, initialize the following items:
                worldLoc     = new WorldLatLon();
                oldClockTime = Viewer.Simulator.ClockTime % 86400;
                while (oldClockTime < 0)
                {
                    oldClockTime += 86400;
                }
                step1 = step2 = (int)(oldClockTime / 1200);
                step2 = step2 < maxSteps - 1 ? step2 + 1 : 0; // limit to max. steps in case activity starts near midnight

                // Get the current latitude and longitude coordinates
                worldLoc.ConvertWTC(Viewer.Camera.TileX, Viewer.Camera.TileZ, Viewer.Camera.Location, ref latitude, ref longitude);
                if (seasonType != (int)Viewer.Simulator.Season)
                {
                    seasonType       = (int)Viewer.Simulator.Season;
                    date.ordinalDate = latitude >= 0 ? 82 + seasonType * 91 : (82 + (seasonType + 2) * 91) % 365;
                    // TODO: Set the following three externally from ORTS route files (future)
                    date.month = 1 + date.ordinalDate / 30;
                    date.day   = 21;
                    date.year  = 2017;
                }
                // Fill in the sun- and moon-position lookup tables
                for (int i = 0; i < maxSteps; i++)
                {
                    solarPosArray[i] = SunMoonPos.SolarAngle(latitude, longitude, ((float)i / maxSteps), date);
                    lunarPosArray[i] = SunMoonPos.LunarAngle(latitude, longitude, ((float)i / maxSteps), date);
                }
                // Phase of the moon is generated at random
                moonPhase = Viewer.Random.Next(8);
                if (moonPhase == 6 && date.ordinalDate > 45 && date.ordinalDate < 330)
                {
                    moonPhase = 3; // Moon dog only occurs in winter
                }
            }


            // Current solar and lunar position are calculated by interpolation in the lookup arrays.
            // Using the Lerp() function, so need to calculate the in-between differential
            float diff = (float)(Viewer.Simulator.ClockTime - oldClockTime) / 1200;

            // The rest of this increments/decrements the array indices and checks for overshoot/undershoot.
            while (Viewer.Simulator.ClockTime >= (oldClockTime + 1200)) // Plus key, or normal forward in time; <CSComment> better so in case of fast forward
            {
                step1++;
                step2++;
                oldClockTime = oldClockTime + 1200;
                diff         = (float)(Viewer.Simulator.ClockTime - oldClockTime) / 1200;
                if (step2 >= maxSteps) // Midnight.
                {
                    step2 = 0;
                }
                if (step1 >= maxSteps) // Midnight.
                {
                    step1 = 0;
                }
            }
            if (Viewer.Simulator.ClockTime <= (oldClockTime - 1200)) // Minus key
            {
                step1--;
                step2--;
                oldClockTime = Viewer.Simulator.ClockTime;
                diff         = 0;
                if (step1 < 0) // Midnight.
                {
                    step1 = maxSteps - 1;
                }
                if (step2 < 0) // Midnight.
                {
                    step2 = maxSteps - 1;
                }
            }
            solarDirection.X = MathHelper.Lerp(solarPosArray[step1].X, solarPosArray[step2].X, diff);
            solarDirection.Y = MathHelper.Lerp(solarPosArray[step1].Y, solarPosArray[step2].Y, diff);
            solarDirection.Z = MathHelper.Lerp(solarPosArray[step1].Z, solarPosArray[step2].Z, diff);
            lunarDirection.X = MathHelper.Lerp(lunarPosArray[step1].X, lunarPosArray[step2].X, diff);
            lunarDirection.Y = MathHelper.Lerp(lunarPosArray[step1].Y, lunarPosArray[step2].Y, diff);
            lunarDirection.Z = MathHelper.Lerp(lunarPosArray[step1].Z, lunarPosArray[step2].Z, diff);

            frame.AddPrimitive(Material, Primitive, RenderPrimitiveGroup.Sky, ref XNASkyWorldLocation);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Used to update information affecting the SkyMesh
        /// </summary>
        public void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
        {
            if (mstsskyseasonType != (int)MSTSSkyViewer.Simulator.Season)
            {
                mstsskyseasonType = (int)MSTSSkyViewer.Simulator.Season;
                date.ordinalDate  = 82 + mstsskyseasonType * 91;
                // TODO: Set the following three externally from ORTS route files (future)
                date.month = 1 + date.ordinalDate / 30;
                date.day   = 21;
                date.year  = 2010;
            }
            // Adjust dome position so the bottom edge is not visible
            Vector3 ViewerXNAPosition   = new Vector3(MSTSSkyViewer.Camera.Location.X, MSTSSkyViewer.Camera.Location.Y - 100, -MSTSSkyViewer.Camera.Location.Z);
            Matrix  XNASkyWorldLocation = Matrix.CreateTranslation(ViewerXNAPosition);

            if (mstsskyworldLoc == null)
            {
                // First time around, initialize the following items:
                mstsskyworldLoc     = new WorldLatLon();
                mstsskyoldClockTime = MSTSSkyViewer.Simulator.ClockTime % 86400;
                while (mstsskyoldClockTime < 0)
                {
                    mstsskyoldClockTime += 86400;
                }
                step1 = step2 = (int)(mstsskyoldClockTime / 1200);
                step2 = step2 < maxSteps - 1 ? step2 + 1 : 0; // limit to max. steps in case activity starts near midnight
                // Get the current latitude and longitude coordinates
                mstsskyworldLoc.ConvertWTC(MSTSSkyViewer.Camera.TileX, MSTSSkyViewer.Camera.TileZ, MSTSSkyViewer.Camera.Location, ref mstsskylatitude, ref mstsskylongitude);
                // Fill in the sun- and moon-position lookup tables
                for (int i = 0; i < maxSteps; i++)
                {
                    mstsskysolarPosArray[i] = SunMoonPos.SolarAngle(mstsskylatitude, mstsskylongitude, ((float)i / maxSteps), date);
                    mstsskylunarPosArray[i] = SunMoonPos.LunarAngle(mstsskylatitude, mstsskylongitude, ((float)i / maxSteps), date);
                }
                // Phase of the moon is generated at random
                mstsskymoonPhase = Viewer.Random.Next(8);
                if (mstsskymoonPhase == 6 && date.ordinalDate > 45 && date.ordinalDate < 330)
                {
                    mstsskymoonPhase = 3; // Moon dog only occurs in winter
                }
                // Overcast factor: 0.0=almost no clouds; 0.1=wispy clouds; 1.0=total overcast
                //mstsskyovercastFactor = MSTSSkyViewer.World.WeatherControl.overcastFactor;
                mstsskyfogDistance = MSTSSkyViewer.Simulator.Weather.FogDistance;
            }

            if (Orts.MultiPlayer.MPManager.IsClient() && Orts.MultiPlayer.MPManager.Instance().weatherChanged)
            {
                //received message about weather change
                if (Orts.MultiPlayer.MPManager.Instance().overcastFactor >= 0)
                {
                    mstsskyovercastFactor = Orts.MultiPlayer.MPManager.Instance().overcastFactor;
                }
                //received message about weather change
                if (Orts.MultiPlayer.MPManager.Instance().fogDistance > 0)
                {
                    mstsskyfogDistance = Orts.MultiPlayer.MPManager.Instance().fogDistance;
                }
                try
                {
                    if (Orts.MultiPlayer.MPManager.Instance().overcastFactor >= 0 || Orts.MultiPlayer.MPManager.Instance().fogDistance > 0)
                    {
                        Orts.MultiPlayer.MPManager.Instance().weatherChanged = false;
                        Orts.MultiPlayer.MPManager.Instance().overcastFactor = -1;
                        Orts.MultiPlayer.MPManager.Instance().fogDistance    = -1;
                    }
                }
                catch { }
            }

            ////////////////////// T E M P O R A R Y ///////////////////////////

            // The following keyboard commands are used for viewing sky and weather effects in "demo" mode.
            // Control- and Control+ for overcast, Shift- and Shift+ for fog and - and + for time.

            // Don't let multiplayer clients adjust the weather.
            if (!Orts.MultiPlayer.MPManager.IsClient())
            {
                // Overcast ranges from 0 (completely clear) to 1 (completely overcast).
                if (UserInput.IsDown(UserCommands.DebugOvercastIncrease))
                {
                    mstsskyovercastFactor = MathHelper.Clamp(mstsskyovercastFactor + elapsedTime.RealSeconds / 10, 0, 1);
                }
                if (UserInput.IsDown(UserCommands.DebugOvercastDecrease))
                {
                    mstsskyovercastFactor = MathHelper.Clamp(mstsskyovercastFactor - elapsedTime.RealSeconds / 10, 0, 1);
                }
                // Fog ranges from 10m (can't see anything) to 100km (clear arctic conditions).
                if (UserInput.IsDown(UserCommands.DebugFogIncrease))
                {
                    mstsskyfogDistance = MathHelper.Clamp(mstsskyfogDistance - elapsedTime.RealSeconds * mstsskyfogDistance, 10, 100000);
                }
                if (UserInput.IsDown(UserCommands.DebugFogDecrease))
                {
                    mstsskyfogDistance = MathHelper.Clamp(mstsskyfogDistance + elapsedTime.RealSeconds * mstsskyfogDistance, 10, 100000);
                }
            }
            // Don't let clock shift if multiplayer.
            if (!Orts.MultiPlayer.MPManager.IsMultiPlayer())
            {
                // Shift the clock forwards or backwards at 1h-per-second.
                if (UserInput.IsDown(UserCommands.DebugClockForwards))
                {
                    MSTSSkyViewer.Simulator.ClockTime += elapsedTime.RealSeconds * 3600;
                }
                if (UserInput.IsDown(UserCommands.DebugClockBackwards))
                {
                    MSTSSkyViewer.Simulator.ClockTime -= elapsedTime.RealSeconds * 3600;
                }
            }
            // Server needs to notify clients of weather changes.
            if (Orts.MultiPlayer.MPManager.IsServer())
            {
                if (UserInput.IsReleased(UserCommands.DebugOvercastIncrease) || UserInput.IsReleased(UserCommands.DebugOvercastDecrease) || UserInput.IsReleased(UserCommands.DebugFogIncrease) || UserInput.IsReleased(UserCommands.DebugFogDecrease))
                {
                    Orts.MultiPlayer.MPManager.Instance().SetEnvInfo(mstsskyovercastFactor, mstsskyfogDistance);
                    Orts.MultiPlayer.MPManager.Notify((new Orts.MultiPlayer.MSGWeather(-1, mstsskyovercastFactor, -1, mstsskyfogDistance)).ToString());
                }
            }

            ////////////////////////////////////////////////////////////////////

            // Current solar and lunar position are calculated by interpolation in the lookup arrays.
            // Using the Lerp() function, so need to calculate the in-between differential
            float diff = (float)(MSTSSkyViewer.Simulator.ClockTime - mstsskyoldClockTime) / 1200;

            // The rest of this increments/decrements the array indices and checks for overshoot/undershoot.
            if (MSTSSkyViewer.Simulator.ClockTime >= (mstsskyoldClockTime + 1200)) // Plus key, or normal forward in time
            {
                step1++;
                step2++;
                mstsskyoldClockTime = MSTSSkyViewer.Simulator.ClockTime;
                diff = 0;
                if (step2 >= maxSteps) // Midnight.
                {
                    step2 = 0;
                }
                if (step1 >= maxSteps) // Midnight.
                {
                    step1 = 0;
                }
            }
            if (MSTSSkyViewer.Simulator.ClockTime <= (mstsskyoldClockTime - 1200)) // Minus key
            {
                step1--;
                step2--;
                mstsskyoldClockTime = MSTSSkyViewer.Simulator.ClockTime;
                diff = 0;
                if (step1 < 0) // Midnight.
                {
                    step1 = maxSteps - 1;
                }
                if (step2 < 0) // Midnight.
                {
                    step2 = maxSteps - 1;
                }
            }


            mstsskysolarDirection.X = MathHelper.Lerp(mstsskysolarPosArray[step1].X, mstsskysolarPosArray[step2].X, diff);
            mstsskysolarDirection.Y = MathHelper.Lerp(mstsskysolarPosArray[step1].Y, mstsskysolarPosArray[step2].Y, diff);
            mstsskysolarDirection.Z = MathHelper.Lerp(mstsskysolarPosArray[step1].Z, mstsskysolarPosArray[step2].Z, diff);
            mstsskylunarDirection.X = MathHelper.Lerp(mstsskylunarPosArray[step1].X, mstsskylunarPosArray[step2].X, diff);
            mstsskylunarDirection.Y = MathHelper.Lerp(mstsskylunarPosArray[step1].Y, mstsskylunarPosArray[step2].Y, diff);
            mstsskylunarDirection.Z = MathHelper.Lerp(mstsskylunarPosArray[step1].Z, mstsskylunarPosArray[step2].Z, diff);

            frame.AddPrimitive(MSTSSkyMaterial, MSTSSkyMesh, RenderPrimitiveGroup.Sky, ref XNASkyWorldLocation);
        }
Ejemplo n.º 6
0
            public void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime, Matrix xnaTileTranslation)
            {
                var initialise = DisplayState == -1;

                if (DisplayState != SignalHead.draw_state)
                {
#if DEBUG_SIGNAL_SHAPES
                    Console.WriteLine("{5} {0} signal {1} unit {2} state: {3} --> {4}",
                                      SignalShape.Location, SignalShape.UID, Index, DisplayState,
                                      SignalHead.draw_state, InfoDisplay.FormattedTime(Viewer.Simulator.ClockTime));
#endif
                    DisplayState = SignalHead.draw_state;
                    if (SignalTypeData.DrawAspects.ContainsKey(DisplayState))
                    {
                        SemaphoreTarget = SignalTypeData.DrawAspects[DisplayState].SemaphorePos;
                        SemaphoreSpeed  = SignalTypeData.SemaphoreAnimationTime <= 0 ? 0 : (SemaphoreTarget > SemaphorePos ? +1 : -1) / SignalTypeData.SemaphoreAnimationTime;
                        if (Sound != null)
                        {
                            Sound.HandleEvent(Event.SemaphoreArm);
                        }
                    }
                }

                CumulativeTime += elapsedTime.ClockSeconds;
                while (CumulativeTime > SignalTypeData.FlashTimeTotal)
                {
                    CumulativeTime -= SignalTypeData.FlashTimeTotal;
                }

                if (DisplayState < 0 || !SignalTypeData.DrawAspects.ContainsKey(DisplayState))
                {
                    return;
                }

                if (SignalTypeData.Semaphore)
                {
                    // We reset the animation matrix before preparing the lights, because they need to be positioned
                    // based on the original matrix only.
                    foreach (AnimatedPart SemaphorePart in SemaphoreParts)
                    {
                        SemaphorePart.SetFrameWrap(0);
                    }
                }

                for (var i = 0; i < SignalTypeData.Lights.Count; i++)
                {
                    if (SemaphorePos != SemaphoreTarget && SignalTypeData.LightsSemaphoreChange[i])
                    {
                        continue;
                    }
                    if (!SignalTypeData.DrawAspects[DisplayState].DrawLights[i])
                    {
                        continue;
                    }
                    if (SignalTypeData.DrawAspects[DisplayState].FlashLights[i] && (CumulativeTime > SignalTypeData.FlashTimeOn))
                    {
                        continue;
                    }

                    var xnaMatrix = Matrix.CreateTranslation(SignalTypeData.Lights[i].Position);

                    foreach (int MatrixIndex in MatrixIndices)
                    {
                        Matrix.Multiply(ref xnaMatrix, ref SignalShape.XNAMatrices[MatrixIndex], out xnaMatrix);
                    }
                    Matrix.Multiply(ref xnaMatrix, ref xnaTileTranslation, out xnaMatrix);

                    frame.AddPrimitive(SignalTypeData.Material, SignalTypeData.Lights[i], RenderPrimitiveGroup.Lights, ref xnaMatrix);
                    if (Viewer.Settings.SignalLightGlow)
                    {
                        frame.AddPrimitive(SignalTypeData.GlowMaterial, SignalTypeData.Lights[i], RenderPrimitiveGroup.Lights, ref xnaMatrix);
                    }
                }

                if (SignalTypeData.Semaphore)
                {
                    // Now we update and re-animate the semaphore arm.
                    if (SignalTypeData.SemaphoreAnimationTime <= 0 || initialise)
                    {
                        // No timing (so instant switch) or we're initialising.
                        SemaphorePos   = SemaphoreTarget;
                        SemaphoreSpeed = 0;
                    }
                    else
                    {
                        // Animate slowly to target position.
                        SemaphorePos += SemaphoreSpeed * elapsedTime.ClockSeconds;
                        if (SemaphorePos * Math.Sign(SemaphoreSpeed) > SemaphoreTarget * Math.Sign(SemaphoreSpeed))
                        {
                            SemaphorePos   = SemaphoreTarget;
                            SemaphoreSpeed = 0;
                        }
                    }
                    foreach (AnimatedPart SemaphorePart in SemaphoreParts)
                    {
                        SemaphorePart.SetFrameCycle(SemaphorePos);
                    }
                }
            }