From: Alan M Webb <awebb@vnet.ibm.com>

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.
0.6.0-stable
Justin Clarke Casey 2008-05-07 14:15:59 +00:00
parent 0ea48cf786
commit 382b9c18ed
4 changed files with 193 additions and 55 deletions

View File

@ -832,7 +832,7 @@ namespace OpenSim.Framework
void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels); void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels);
bool AddMoney(int debit); 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 SendViewerTime(int phase);
void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, string flAbout, void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, string flAbout,

View File

@ -1772,18 +1772,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(sound, ThrottleOutPacketType.Task); 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); SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
viewertime.TimeInfo.SunDirection = sunPos; viewertime.TimeInfo.SunDirection = Position;
viewertime.TimeInfo.SunAngVelocity = sunVel; viewertime.TimeInfo.SunAngVelocity = Velocity;
viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch(); viewertime.TimeInfo.UsecSinceStart = CurrentTime;
viewertime.Header.Reliable = false; viewertime.TimeInfo.SecPerDay = SecondsPerSunCycle;
viewertime.TimeInfo.SecPerYear = SecondsPerYear;
viewertime.TimeInfo.SunPhase = OrbitalPosition;
viewertime.Header.Reliable = false;
OutPacket(viewertime, ThrottleOutPacketType.Task); OutPacket(viewertime, ThrottleOutPacketType.Task);
} }
// Currently Deprecated
public void SendViewerTime(int phase) public void SendViewerTime(int phase)
{ {
/*
Console.WriteLine("SunPhase: {0}", phase); Console.WriteLine("SunPhase: {0}", phase);
SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
//viewertime.TimeInfo.SecPerDay = 86400; //viewertime.TimeInfo.SecPerDay = 86400;
@ -1829,6 +1834,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch(); viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch();
viewertime.Header.Reliable = false; viewertime.Header.Reliable = false;
OutPacket(viewertime, ThrottleOutPacketType.Task); OutPacket(viewertime, ThrottleOutPacketType.Task);
*/
} }
public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember,

View File

@ -33,45 +33,136 @@ using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules.World.Sun namespace OpenSim.Region.Environment.Modules
{ {
public class SunModule : IRegionModule 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 static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
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 Scene m_scene; private const double SeasonalTilt = 0.03 * Math.PI; // A daily shift of approximately 1.7188 degrees
private long m_start; 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) public void Initialise(Scene scene, IConfigSource config)
{ {
m_start = DateTime.Now.Ticks;
m_log.Debug("[SUN] Initializing");
m_scene = scene;
m_frame = 0; 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 // Just in case they don't have the stanzas
try try
{ {
m_day_length = config.Configs["Sun"].GetDouble("day_length", m_real_day); // Day length in decimal hours
m_frame_mod = config.Configs["Sun"].GetInt("frame_rate", m_default_frame); 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_log.Debug("[SUN] Configuration access failed, using defaults. Reason: "+e.Message);
m_frame_mod = m_default_frame; 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); // Time taken to complete a cycle (day and season)
m_scene = scene;
scene.EventManager.OnFrame += SunUpdate; 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; 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() public void PostInitialise()
@ -80,6 +171,10 @@ namespace OpenSim.Region.Environment.Modules.World.Sun
public void Close() public void Close()
{ {
ready = false;
// Remove our hooks
m_scene.EventManager.OnFrame -= SunUpdate;
m_scene.EventManager.OnNewClient -= SunToClient;
} }
public string Name public string Name
@ -92,51 +187,88 @@ namespace OpenSim.Region.Environment.Modules.World.Sun
get { return false; } get { return false; }
} }
#endregion
public void SunToClient(IClientAPI client) 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() public void SunUpdate()
{ {
if (m_frame < m_frame_mod)
if(((m_frame++%m_frame_mod) != 0) || !ready)
{ {
m_frame++;
return; return;
} }
// m_log.InfoFormat("[SUN]: I've got an update {0} => {1}", m_scene.RegionsInfo.RegionName, HourOfTheDay());
GenSunPos(); // Generate shared values once
List<ScenePresence> avatars = m_scene.GetAvatars(); List<ScenePresence> avatars = m_scene.GetAvatars();
foreach (ScenePresence avatar in avatars) 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 // 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. /// <summary>
// The intent here is that we seed hour of the day with real /// Calculate the sun's orbital position and its velocity.
// time when the simulator starts, then run time forward /// </summary>
// 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);
}
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); TotalDistanceTravelled = SunSpeed * CurrentTime; // distance measured in radians
double z = Math.Sin(rad); OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); // position measured in radians
double x = Math.Cos(rad);
return new LLVector3((float) x, 0f, (float) z); // 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+")");
} }
} }
} }

View File

@ -573,7 +573,7 @@ namespace OpenSim.Region.Examples.SimpleModule
return false; return false;
} }
public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel) public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel, ulong time, uint dlen, uint ylen, float phase)
{ {
} }