From 382b9c18ed9736c88effb869e617ca3e3792d1db Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Wed, 7 May 2008 14:15:59 +0000 Subject: [PATCH] From: Alan M Webb The attached patch moves the sun module incrementally nearer where it needs to be. Default behavior, i.e. no overriding configuration is to match Second Life's diurnal/nocturnal rhythm. All designated values are now sent to the client.There remain a couple of unanswered questions about how this SHOULD be implemented though. --- OpenSim/Framework/IClientAPI.cs | 2 +- .../ClientStack/LindenUDP/LLClientView.cs | 18 +- .../Modules/World/Sun/SunModule.cs | 226 ++++++++++++++---- .../Examples/SimpleModule/MyNpcCharacter.cs | 2 +- 4 files changed, 193 insertions(+), 55 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 9d86036b46..d71a778d1c 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -832,7 +832,7 @@ namespace OpenSim.Framework void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels); bool AddMoney(int debit); - void SendSunPos(LLVector3 sunPos, LLVector3 sunVel); + void SendSunPos(LLVector3 sunPos, LLVector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition); void SendViewerTime(int phase); void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, string flAbout, diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index f5d4ad3022..d183f4aa21 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -1772,18 +1772,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(sound, ThrottleOutPacketType.Task); } - public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel) + public void SendSunPos(LLVector3 Position, LLVector3 Velocity, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition) { SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); - viewertime.TimeInfo.SunDirection = sunPos; - viewertime.TimeInfo.SunAngVelocity = sunVel; - viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch(); - viewertime.Header.Reliable = false; + viewertime.TimeInfo.SunDirection = Position; + viewertime.TimeInfo.SunAngVelocity = Velocity; + viewertime.TimeInfo.UsecSinceStart = CurrentTime; + viewertime.TimeInfo.SecPerDay = SecondsPerSunCycle; + viewertime.TimeInfo.SecPerYear = SecondsPerYear; + viewertime.TimeInfo.SunPhase = OrbitalPosition; + viewertime.Header.Reliable = false; OutPacket(viewertime, ThrottleOutPacketType.Task); } + // Currently Deprecated public void SendViewerTime(int phase) { + /* Console.WriteLine("SunPhase: {0}", phase); SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); //viewertime.TimeInfo.SecPerDay = 86400; @@ -1829,6 +1834,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch(); viewertime.Header.Reliable = false; OutPacket(viewertime, ThrottleOutPacketType.Task); + */ } public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, @@ -5474,4 +5480,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_sequence = info.sequence; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs b/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs index 7d9bdd96a4..75cf786e87 100644 --- a/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs +++ b/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs @@ -33,45 +33,136 @@ using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -namespace OpenSim.Region.Environment.Modules.World.Sun +namespace OpenSim.Region.Environment.Modules { public class SunModule : IRegionModule { - //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private const int m_default_frame = 100; - private const double m_real_day = 24.0; - private double m_day_length; - private int m_dilation; - private int m_frame; - private int m_frame_mod; + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private Scene m_scene; - private long m_start; + private const double SeasonalTilt = 0.03 * Math.PI; // A daily shift of approximately 1.7188 degrees + private const double AverageTilt = -0.25 * Math.PI; // A 45 degree tilt + private const double SunCycle = 2.0D * Math.PI; // A perfect circle measured in radians + private const double SeasonalCycle = 2.0D * Math.PI; // Ditto - #region IRegionModule Members + // + // Per Region Values + // + + private bool ready = false; + + // Configurable values + private int m_frame_mod = 0; + private double m_day_length = 0; + private int m_year_length = 0; + private double m_day_night = 0; + // Configurable defaults Defaults close to SL + private int d_frame_mod = 100; // Every 10 seconds (actually less) + private double d_day_length = 4; // A VW day is 4 RW hours long + private int d_year_length = 60; // There are 60 VW days in a VW year + private double d_day_night = 0.45; // axis offset: ratio of light-to-dark, approx 1:3 + + // Frame counter + private uint m_frame = 0; + + // Cached Scene reference + private Scene m_scene = null; + + // Calculated Once in the lifetime of a region + private ulong TicksToEpoch; // Elapsed time for 1/1/1970 + private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds + private uint SecondsPerYear; // Length of a virtual year in RW seconds + private double SunSpeed; // Rate of passage in radians/second + private double SeasonSpeed; // Rate of change for seasonal effects + private double HoursToRadians; // Rate of change for seasonal effects + + // Calculated every update + private float OrbitalPosition; // Orbital placement at a point in time + private double HorizonShift; // Axis offset to skew day and night + private double TotalDistanceTravelled; // Distance since beginning of time (in radians) + private double SeasonalOffset; // Seaonal variation of tilt + private float Magnitude; // Normal tilt + private double VWTimeRatio; // VW time as a ratio of real time + + // Working values + private LLVector3 Position = new LLVector3(0,0,0); + private LLVector3 Velocity = new LLVector3(0,0,0); + private LLQuaternion Tilt = new LLQuaternion(1,0,0,0); + + // Current time in elpased seconds since Jan 1st 1970 + private ulong CurrentTime + { + get { return (ulong)((((ulong)System.DateTime.Now.Ticks)-TicksToEpoch)/10000000); } + } + + // Called immediately after the module is loaded for a given region + // i.e. Immediately after instance creation. public void Initialise(Scene scene, IConfigSource config) { - m_start = DateTime.Now.Ticks; + + m_log.Debug("[SUN] Initializing"); + + m_scene = scene; + m_frame = 0; + // Align ticks with Second Life + + TicksToEpoch = (ulong) new System.DateTime(1970,1,1).Ticks; + // Just in case they don't have the stanzas try { - m_day_length = config.Configs["Sun"].GetDouble("day_length", m_real_day); - m_frame_mod = config.Configs["Sun"].GetInt("frame_rate", m_default_frame); + // Day length in decimal hours + m_year_length = config.Configs["Sun"].GetInt("year_length", d_year_length); + // Day length in decimal hours + m_day_length = config.Configs["Sun"].GetDouble("day_length", d_day_length); + // Day to Night Ratio + m_day_night = config.Configs["Sun"].GetDouble("day_night_offset", d_day_night); + // Update frequency in frames + m_frame_mod = config.Configs["Sun"].GetInt("update_interval", d_frame_mod); } - catch (Exception) + catch (Exception e) { - m_day_length = m_real_day; - m_frame_mod = m_default_frame; + m_log.Debug("[SUN] Configuration access failed, using defaults. Reason: "+e.Message); + m_year_length = d_year_length; + m_day_length = d_day_length; + m_day_night = d_day_night; + m_frame_mod = d_frame_mod; } - m_dilation = (int) (m_real_day / m_day_length); - m_scene = scene; - scene.EventManager.OnFrame += SunUpdate; + // Time taken to complete a cycle (day and season) + + SecondsPerSunCycle = (uint) (m_day_length * 60 * 60); + SecondsPerYear = (uint) (SecondsPerSunCycle*m_year_length); + + // Ration of real-to-virtual time + + VWTimeRatio = 24/m_day_length; + + // Speed of rotation needed to complete a cycle in the + // designated period (day and season) + + SunSpeed = SunCycle/SecondsPerSunCycle; + SeasonSpeed = SeasonalCycle/SecondsPerYear; + + // Horizon translation + + HorizonShift = m_day_night; // Z axis translation + HoursToRadians = (SunCycle/24)*VWTimeRatio; + + // Insert our event handling hooks + + scene.EventManager.OnFrame += SunUpdate; scene.EventManager.OnNewClient += SunToClient; + + ready = true; + + m_log.Debug("[SUN] Initialization completed. Day is "+SecondsPerSunCycle+" seconds, and year is "+m_year_length+" days"); + m_log.Debug("[SUN] Axis offset is "+m_day_night); + m_log.Debug("[SUN] Positional data updated every "+m_frame_mod+" frames"); + } public void PostInitialise() @@ -80,6 +171,10 @@ namespace OpenSim.Region.Environment.Modules.World.Sun public void Close() { + ready = false; + // Remove our hooks + m_scene.EventManager.OnFrame -= SunUpdate; + m_scene.EventManager.OnNewClient -= SunToClient; } public string Name @@ -92,51 +187,88 @@ namespace OpenSim.Region.Environment.Modules.World.Sun get { return false; } } - #endregion - public void SunToClient(IClientAPI client) { - client.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f)); + if(ready) + { + GenSunPos(); // Generate shared values once + client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); + } } public void SunUpdate() { - if (m_frame < m_frame_mod) + + if(((m_frame++%m_frame_mod) != 0) || !ready) { - m_frame++; return; } - // m_log.InfoFormat("[SUN]: I've got an update {0} => {1}", m_scene.RegionsInfo.RegionName, HourOfTheDay()); + + GenSunPos(); // Generate shared values once + List avatars = m_scene.GetAvatars(); foreach (ScenePresence avatar in avatars) { - avatar.ControllingClient.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f)); + avatar.ControllingClient.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); } + // set estate settings for region access to sun position - m_scene.RegionInfo.EstateSettings.sunPosition = SunPos(HourOfTheDay()); + m_scene.RegionInfo.EstateSettings.sunPosition = Position; - m_frame = 0; } - // Hour of the Day figures out the hour of the day as a float. - // The intent here is that we seed hour of the day with real - // time when the simulator starts, then run time forward - // faster based on time dilation factor. This means that - // ticks don't get out of hand - private double HourOfTheDay() - { - long m_addticks = (DateTime.Now.Ticks - m_start) * m_dilation; - DateTime dt = new DateTime(m_start + m_addticks); - return dt.Hour + (dt.Minute / 60.0); - } + /// + /// Calculate the sun's orbital position and its velocity. + /// - private static LLVector3 SunPos(double hour) + private void GenSunPos() { - // now we have our radian position - double rad = (hour / m_real_day) * 2 * Math.PI - (Math.PI / 2.0); - double z = Math.Sin(rad); - double x = Math.Cos(rad); - return new LLVector3((float) x, 0f, (float) z); + + TotalDistanceTravelled = SunSpeed * CurrentTime; // distance measured in radians + OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); // position measured in radians + + // TotalDistanceTravelled += HoursToRadians-(0.25*Math.PI)*Math.Cos(HoursToRadians)-OrbitalPosition; + // OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); + + SeasonalOffset = SeasonSpeed * CurrentTime; // Present season determined as total radians travelled around season cycle + + Tilt.W = (float) (AverageTilt + (SeasonalTilt*Math.Sin(SeasonalOffset))); // Calculate seasonal orbital N/S tilt + + // m_log.Debug("[SUN] Total distance travelled = "+TotalDistanceTravelled+", present position = "+OrbitalPosition+"."); + // m_log.Debug("[SUN] Total seasonal progress = "+SeasonalOffset+", present tilt = "+Tilt.W+"."); + + // The sun rotates about the Z axis + + Position.X = (float) Math.Cos(-TotalDistanceTravelled); + Position.Y = (float) Math.Sin(-TotalDistanceTravelled); + Position.Z = 0; + + // For interest we rotate it slightly about the X access. + // Celestial tilt is a value that ranges .025 + + Position = LLVector3.Rot(Position,Tilt); + + // Finally we shift the axis so that more of the + // circle is above the horizon than below. This + // makes the nights shorter than the days. + + Position.Z = Position.Z + (float) HorizonShift; + Position = LLVector3.Norm(Position); + + // m_log.Debug("[SUN] Position("+Position.X+","+Position.Y+","+Position.Z+")"); + + Velocity.X = 0; + Velocity.Y = 0; + Velocity.Z = (float) SunSpeed; + + // Correct angular velocity to reflect the seasonal rotation + + Magnitude = LLVector3.Mag(Position); + + Velocity = LLVector3.Rot(Velocity, Tilt)*((float)(1.0/Magnitude)); + + // m_log.Debug("[SUN] Velocity("+Velocity.X+","+Velocity.Y+","+Velocity.Z+")"); + } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index f4577732d6..e6e47cbae6 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -573,7 +573,7 @@ namespace OpenSim.Region.Examples.SimpleModule return false; } - public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel) + public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel, ulong time, uint dlen, uint ylen, float phase) { }