diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules/World/Sun')
-rw-r--r-- | OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs | 226 |
1 files changed, 179 insertions, 47 deletions
diff --git a/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs b/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs index 7d9bdd9..75cf786 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; | |||
33 | using OpenSim.Region.Environment.Interfaces; | 33 | using OpenSim.Region.Environment.Interfaces; |
34 | using OpenSim.Region.Environment.Scenes; | 34 | using OpenSim.Region.Environment.Scenes; |
35 | 35 | ||
36 | namespace OpenSim.Region.Environment.Modules.World.Sun | 36 | namespace OpenSim.Region.Environment.Modules |
37 | { | 37 | { |
38 | public class SunModule : IRegionModule | 38 | public class SunModule : IRegionModule |
39 | { | 39 | { |
40 | //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
41 | 40 | ||
42 | private const int m_default_frame = 100; | 41 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
43 | private const double m_real_day = 24.0; | ||
44 | private double m_day_length; | ||
45 | private int m_dilation; | ||
46 | private int m_frame; | ||
47 | private int m_frame_mod; | ||
48 | 42 | ||
49 | private Scene m_scene; | 43 | private const double SeasonalTilt = 0.03 * Math.PI; // A daily shift of approximately 1.7188 degrees |
50 | private long m_start; | 44 | private const double AverageTilt = -0.25 * Math.PI; // A 45 degree tilt |
45 | private const double SunCycle = 2.0D * Math.PI; // A perfect circle measured in radians | ||
46 | private const double SeasonalCycle = 2.0D * Math.PI; // Ditto | ||
51 | 47 | ||
52 | #region IRegionModule Members | 48 | // |
49 | // Per Region Values | ||
50 | // | ||
51 | |||
52 | private bool ready = false; | ||
53 | |||
54 | // Configurable values | ||
55 | private int m_frame_mod = 0; | ||
56 | private double m_day_length = 0; | ||
57 | private int m_year_length = 0; | ||
58 | private double m_day_night = 0; | ||
59 | // Configurable defaults Defaults close to SL | ||
60 | private int d_frame_mod = 100; // Every 10 seconds (actually less) | ||
61 | private double d_day_length = 4; // A VW day is 4 RW hours long | ||
62 | private int d_year_length = 60; // There are 60 VW days in a VW year | ||
63 | private double d_day_night = 0.45; // axis offset: ratio of light-to-dark, approx 1:3 | ||
64 | |||
65 | // Frame counter | ||
66 | private uint m_frame = 0; | ||
67 | |||
68 | // Cached Scene reference | ||
69 | private Scene m_scene = null; | ||
70 | |||
71 | // Calculated Once in the lifetime of a region | ||
72 | private ulong TicksToEpoch; // Elapsed time for 1/1/1970 | ||
73 | private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds | ||
74 | private uint SecondsPerYear; // Length of a virtual year in RW seconds | ||
75 | private double SunSpeed; // Rate of passage in radians/second | ||
76 | private double SeasonSpeed; // Rate of change for seasonal effects | ||
77 | private double HoursToRadians; // Rate of change for seasonal effects | ||
78 | |||
79 | // Calculated every update | ||
80 | private float OrbitalPosition; // Orbital placement at a point in time | ||
81 | private double HorizonShift; // Axis offset to skew day and night | ||
82 | private double TotalDistanceTravelled; // Distance since beginning of time (in radians) | ||
83 | private double SeasonalOffset; // Seaonal variation of tilt | ||
84 | private float Magnitude; // Normal tilt | ||
85 | private double VWTimeRatio; // VW time as a ratio of real time | ||
86 | |||
87 | // Working values | ||
88 | private LLVector3 Position = new LLVector3(0,0,0); | ||
89 | private LLVector3 Velocity = new LLVector3(0,0,0); | ||
90 | private LLQuaternion Tilt = new LLQuaternion(1,0,0,0); | ||
91 | |||
92 | // Current time in elpased seconds since Jan 1st 1970 | ||
93 | private ulong CurrentTime | ||
94 | { | ||
95 | get { return (ulong)((((ulong)System.DateTime.Now.Ticks)-TicksToEpoch)/10000000); } | ||
96 | } | ||
97 | |||
98 | // Called immediately after the module is loaded for a given region | ||
99 | // i.e. Immediately after instance creation. | ||
53 | 100 | ||
54 | public void Initialise(Scene scene, IConfigSource config) | 101 | public void Initialise(Scene scene, IConfigSource config) |
55 | { | 102 | { |
56 | m_start = DateTime.Now.Ticks; | 103 | |
104 | m_log.Debug("[SUN] Initializing"); | ||
105 | |||
106 | m_scene = scene; | ||
107 | |||
57 | m_frame = 0; | 108 | m_frame = 0; |
58 | 109 | ||
110 | // Align ticks with Second Life | ||
111 | |||
112 | TicksToEpoch = (ulong) new System.DateTime(1970,1,1).Ticks; | ||
113 | |||
59 | // Just in case they don't have the stanzas | 114 | // Just in case they don't have the stanzas |
60 | try | 115 | try |
61 | { | 116 | { |
62 | m_day_length = config.Configs["Sun"].GetDouble("day_length", m_real_day); | 117 | // Day length in decimal hours |
63 | m_frame_mod = config.Configs["Sun"].GetInt("frame_rate", m_default_frame); | 118 | m_year_length = config.Configs["Sun"].GetInt("year_length", d_year_length); |
119 | // Day length in decimal hours | ||
120 | m_day_length = config.Configs["Sun"].GetDouble("day_length", d_day_length); | ||
121 | // Day to Night Ratio | ||
122 | m_day_night = config.Configs["Sun"].GetDouble("day_night_offset", d_day_night); | ||
123 | // Update frequency in frames | ||
124 | m_frame_mod = config.Configs["Sun"].GetInt("update_interval", d_frame_mod); | ||
64 | } | 125 | } |
65 | catch (Exception) | 126 | catch (Exception e) |
66 | { | 127 | { |
67 | m_day_length = m_real_day; | 128 | m_log.Debug("[SUN] Configuration access failed, using defaults. Reason: "+e.Message); |
68 | m_frame_mod = m_default_frame; | 129 | m_year_length = d_year_length; |
130 | m_day_length = d_day_length; | ||
131 | m_day_night = d_day_night; | ||
132 | m_frame_mod = d_frame_mod; | ||
69 | } | 133 | } |
70 | 134 | ||
71 | m_dilation = (int) (m_real_day / m_day_length); | 135 | // Time taken to complete a cycle (day and season) |
72 | m_scene = scene; | 136 | |
73 | scene.EventManager.OnFrame += SunUpdate; | 137 | SecondsPerSunCycle = (uint) (m_day_length * 60 * 60); |
138 | SecondsPerYear = (uint) (SecondsPerSunCycle*m_year_length); | ||
139 | |||
140 | // Ration of real-to-virtual time | ||
141 | |||
142 | VWTimeRatio = 24/m_day_length; | ||
143 | |||
144 | // Speed of rotation needed to complete a cycle in the | ||
145 | // designated period (day and season) | ||
146 | |||
147 | SunSpeed = SunCycle/SecondsPerSunCycle; | ||
148 | SeasonSpeed = SeasonalCycle/SecondsPerYear; | ||
149 | |||
150 | // Horizon translation | ||
151 | |||
152 | HorizonShift = m_day_night; // Z axis translation | ||
153 | HoursToRadians = (SunCycle/24)*VWTimeRatio; | ||
154 | |||
155 | // Insert our event handling hooks | ||
156 | |||
157 | scene.EventManager.OnFrame += SunUpdate; | ||
74 | scene.EventManager.OnNewClient += SunToClient; | 158 | scene.EventManager.OnNewClient += SunToClient; |
159 | |||
160 | ready = true; | ||
161 | |||
162 | m_log.Debug("[SUN] Initialization completed. Day is "+SecondsPerSunCycle+" seconds, and year is "+m_year_length+" days"); | ||
163 | m_log.Debug("[SUN] Axis offset is "+m_day_night); | ||
164 | m_log.Debug("[SUN] Positional data updated every "+m_frame_mod+" frames"); | ||
165 | |||
75 | } | 166 | } |
76 | 167 | ||
77 | public void PostInitialise() | 168 | public void PostInitialise() |
@@ -80,6 +171,10 @@ namespace OpenSim.Region.Environment.Modules.World.Sun | |||
80 | 171 | ||
81 | public void Close() | 172 | public void Close() |
82 | { | 173 | { |
174 | ready = false; | ||
175 | // Remove our hooks | ||
176 | m_scene.EventManager.OnFrame -= SunUpdate; | ||
177 | m_scene.EventManager.OnNewClient -= SunToClient; | ||
83 | } | 178 | } |
84 | 179 | ||
85 | public string Name | 180 | public string Name |
@@ -92,51 +187,88 @@ namespace OpenSim.Region.Environment.Modules.World.Sun | |||
92 | get { return false; } | 187 | get { return false; } |
93 | } | 188 | } |
94 | 189 | ||
95 | #endregion | ||
96 | |||
97 | public void SunToClient(IClientAPI client) | 190 | public void SunToClient(IClientAPI client) |
98 | { | 191 | { |
99 | client.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f)); | 192 | if(ready) |
193 | { | ||
194 | GenSunPos(); // Generate shared values once | ||
195 | client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); | ||
196 | } | ||
100 | } | 197 | } |
101 | 198 | ||
102 | public void SunUpdate() | 199 | public void SunUpdate() |
103 | { | 200 | { |
104 | if (m_frame < m_frame_mod) | 201 | |
202 | if(((m_frame++%m_frame_mod) != 0) || !ready) | ||
105 | { | 203 | { |
106 | m_frame++; | ||
107 | return; | 204 | return; |
108 | } | 205 | } |
109 | // m_log.InfoFormat("[SUN]: I've got an update {0} => {1}", m_scene.RegionsInfo.RegionName, HourOfTheDay()); | 206 | |
207 | GenSunPos(); // Generate shared values once | ||
208 | |||
110 | List<ScenePresence> avatars = m_scene.GetAvatars(); | 209 | List<ScenePresence> avatars = m_scene.GetAvatars(); |
111 | foreach (ScenePresence avatar in avatars) | 210 | foreach (ScenePresence avatar in avatars) |
112 | { | 211 | { |
113 | avatar.ControllingClient.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f)); | 212 | avatar.ControllingClient.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); |
114 | } | 213 | } |
214 | |||
115 | // set estate settings for region access to sun position | 215 | // set estate settings for region access to sun position |
116 | m_scene.RegionInfo.EstateSettings.sunPosition = SunPos(HourOfTheDay()); | 216 | m_scene.RegionInfo.EstateSettings.sunPosition = Position; |
117 | 217 | ||
118 | m_frame = 0; | ||
119 | } | 218 | } |
120 | 219 | ||
121 | // Hour of the Day figures out the hour of the day as a float. | 220 | /// <summary> |
122 | // The intent here is that we seed hour of the day with real | 221 | /// Calculate the sun's orbital position and its velocity. |
123 | // time when the simulator starts, then run time forward | 222 | /// </summary> |
124 | // faster based on time dilation factor. This means that | ||
125 | // ticks don't get out of hand | ||
126 | private double HourOfTheDay() | ||
127 | { | ||
128 | long m_addticks = (DateTime.Now.Ticks - m_start) * m_dilation; | ||
129 | DateTime dt = new DateTime(m_start + m_addticks); | ||
130 | return dt.Hour + (dt.Minute / 60.0); | ||
131 | } | ||
132 | 223 | ||
133 | private static LLVector3 SunPos(double hour) | 224 | private void GenSunPos() |
134 | { | 225 | { |
135 | // now we have our radian position | 226 | |
136 | double rad = (hour / m_real_day) * 2 * Math.PI - (Math.PI / 2.0); | 227 | TotalDistanceTravelled = SunSpeed * CurrentTime; // distance measured in radians |
137 | double z = Math.Sin(rad); | 228 | OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); // position measured in radians |
138 | double x = Math.Cos(rad); | 229 | |
139 | return new LLVector3((float) x, 0f, (float) z); | 230 | // TotalDistanceTravelled += HoursToRadians-(0.25*Math.PI)*Math.Cos(HoursToRadians)-OrbitalPosition; |
231 | // OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); | ||
232 | |||
233 | SeasonalOffset = SeasonSpeed * CurrentTime; // Present season determined as total radians travelled around season cycle | ||
234 | |||
235 | Tilt.W = (float) (AverageTilt + (SeasonalTilt*Math.Sin(SeasonalOffset))); // Calculate seasonal orbital N/S tilt | ||
236 | |||
237 | // m_log.Debug("[SUN] Total distance travelled = "+TotalDistanceTravelled+", present position = "+OrbitalPosition+"."); | ||
238 | // m_log.Debug("[SUN] Total seasonal progress = "+SeasonalOffset+", present tilt = "+Tilt.W+"."); | ||
239 | |||
240 | // The sun rotates about the Z axis | ||
241 | |||
242 | Position.X = (float) Math.Cos(-TotalDistanceTravelled); | ||
243 | Position.Y = (float) Math.Sin(-TotalDistanceTravelled); | ||
244 | Position.Z = 0; | ||
245 | |||
246 | // For interest we rotate it slightly about the X access. | ||
247 | // Celestial tilt is a value that ranges .025 | ||
248 | |||
249 | Position = LLVector3.Rot(Position,Tilt); | ||
250 | |||
251 | // Finally we shift the axis so that more of the | ||
252 | // circle is above the horizon than below. This | ||
253 | // makes the nights shorter than the days. | ||
254 | |||
255 | Position.Z = Position.Z + (float) HorizonShift; | ||
256 | Position = LLVector3.Norm(Position); | ||
257 | |||
258 | // m_log.Debug("[SUN] Position("+Position.X+","+Position.Y+","+Position.Z+")"); | ||
259 | |||
260 | Velocity.X = 0; | ||
261 | Velocity.Y = 0; | ||
262 | Velocity.Z = (float) SunSpeed; | ||
263 | |||
264 | // Correct angular velocity to reflect the seasonal rotation | ||
265 | |||
266 | Magnitude = LLVector3.Mag(Position); | ||
267 | |||
268 | Velocity = LLVector3.Rot(Velocity, Tilt)*((float)(1.0/Magnitude)); | ||
269 | |||
270 | // m_log.Debug("[SUN] Velocity("+Velocity.X+","+Velocity.Y+","+Velocity.Z+")"); | ||
271 | |||
140 | } | 272 | } |
141 | } | 273 | } |
142 | } \ No newline at end of file | 274 | } |