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

View File

@ -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.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,

View File

@ -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;
// 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<ScenePresence> 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);
}
/// <summary>
/// Calculate the sun's orbital position and its velocity.
/// </summary>
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+")");
}
}
}

View File

@ -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)
{
}