* Refactored the central update loop - now easier to work with. Switching from per-framecounts to per-second time periods and moving to OpenSim.ini shortly.

afrisby
Adam Frisby 2007-09-24 15:46:03 +00:00
parent 0eac34b7ab
commit 48e0e05446
1 changed files with 170 additions and 102 deletions

View File

@ -60,15 +60,9 @@ namespace OpenSim.Region.Environment.Scenes
protected Dictionary<LLUUID, ScenePresence> m_scenePresences;
protected Dictionary<LLUUID, SceneObjectGroup> m_sceneObjects;
/// publicized so it can be accessed from SceneObjectGroup.
protected float timeStep = 0.1f;
private Random Rand = new Random();
private uint _primCount = 702000;
private readonly Mutex _primAllocateMutex = new Mutex(false);
private int storageCount;
private int terrainCheckCount;
private int landPrimCheckCount;
private int m_timePhase = 24;
private int m_timeUpdateCount;
@ -98,6 +92,23 @@ namespace OpenSim.Region.Environment.Scenes
private IHttpRequests m_httpRequestModule = null;
private ISimChat m_simChatModule = null;
// Central Update Loop
protected int m_fps = 10;
protected int m_frame = 0;
protected float m_timespan = 0.1f;
protected DateTime m_lastupdate = DateTime.Now;
private int m_update_physics = 1;
private int m_update_entitymovement = 1;
private int m_update_entities = 1;
private int m_update_events = 1;
private int m_update_backup = 200;
private int m_update_terrain = 50;
private int m_update_land = 1;
private int m_update_avatars = 1;
#region Properties
public AgentCircuitManager AuthenticateHandler
@ -222,7 +233,7 @@ namespace OpenSim.Region.Environment.Scenes
public void StartTimer()
{
m_heartbeatTimer.Enabled = true;
m_heartbeatTimer.Interval = 100;
m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
}
@ -243,50 +254,108 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary>
public override void Update()
{
TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate;
// Aquire a lock so only one update call happens at once
updateLock.WaitOne();
try
{
// Increment the frame counter
m_frame++;
// Loop it
if (m_frame == Int32.MaxValue)
m_frame = 0;
if (m_frame % m_update_physics == 0)
UpdatePreparePhysics();
if (m_frame % m_update_entitymovement == 0)
UpdateEntityMovement();
if (m_frame % m_update_physics == 0)
UpdatePhysics(
Math.Min(SinceLastFrame.TotalSeconds, 0.001)
);
if (m_frame % m_update_entities == 0)
UpdateEntities();
if (m_frame % m_update_events == 0)
UpdateEvents();
if (m_frame % m_update_backup == 0)
UpdateStorageBackup();
if (m_frame % m_update_terrain == 0)
UpdateTerrain();
if (m_frame % m_update_land == 0)
UpdateLand();
if (m_frame % m_update_avatars == 0)
UpdateAvatars();
}
catch (NotImplementedException)
{
throw;
}
catch (Exception e)
{
MainLog.Instance.Error("Scene", "Failed with exception " + e.ToString());
}
finally
{
updateLock.ReleaseMutex();
m_lastupdate = DateTime.Now;
}
}
private void UpdatePreparePhysics()
{
// If we are using a threaded physics engine
// grab the latest scene from the engine before
// trying to process it.
// PhysX does this (runs in the background).
if (phyScene.IsThreaded)
{
phyScene.GetResults();
/// no engines implement this, and what does it have to do with threading? possible DEAD CODE
}
}
List<EntityBase> moveEntities = new List<EntityBase>(Entities.Values);
foreach (EntityBase entity in moveEntities)
private void UpdateAvatars()
{
entity.UpdateMovement();
m_timeUpdateCount++;
if (m_timeUpdateCount > 600)
{
List<ScenePresence> avatars = GetAvatars();
foreach (ScenePresence avatar in avatars)
{
avatar.ControllingClient.SendViewerTime(m_timePhase);
}
lock (m_syncRoot)
m_timeUpdateCount = 0;
m_timePhase++;
if (m_timePhase > 94)
{
phyScene.Simulate(timeStep);
m_timePhase = 0;
}
}
}
List<EntityBase> updateEntities = new List<EntityBase>(Entities.Values);
foreach (EntityBase entity in updateEntities)
private void UpdateLand()
{
entity.Update();
if (m_LandManager.landPrimCountTainted)
{
//Perform land update of prim count
performParcelPrimCountUpdate();
}
}
// General purpose event manager
m_eventManager.TriggerOnFrame();
//backup scene data
storageCount++;
if (storageCount > 1200) //set to how often you want to backup
private void UpdateTerrain()
{
Backup();
storageCount = 0;
}
terrainCheckCount++;
if (terrainCheckCount >= 50)
{
terrainCheckCount = 0;
if (Terrain.Tainted())
{
CreateTerrainTexture();
@ -323,43 +392,42 @@ namespace OpenSim.Region.Environment.Scenes
}
}
landPrimCheckCount++;
if (landPrimCheckCount > 50) //check every 5 seconds for tainted prims
private void UpdateStorageBackup()
{
if (m_LandManager.landPrimCountTainted)
Backup();
}
private void UpdateEvents()
{
//Perform land update of prim count
performParcelPrimCountUpdate();
landPrimCheckCount = 0;
m_eventManager.TriggerOnFrame();
}
private void UpdateEntities()
{
List<EntityBase> updateEntities = new List<EntityBase>(Entities.Values);
foreach (EntityBase entity in updateEntities)
{
entity.Update();
}
}
m_timeUpdateCount++;
if (m_timeUpdateCount > 600)
private void UpdatePhysics(double elapsed)
{
List<ScenePresence> avatars = GetAvatars();
foreach (ScenePresence avatar in avatars)
lock (m_syncRoot)
{
avatar.ControllingClient.SendViewerTime(m_timePhase);
phyScene.Simulate((float)elapsed);
}
}
m_timeUpdateCount = 0;
m_timePhase++;
if (m_timePhase > 94)
private void UpdateEntityMovement()
{
m_timePhase = 0;
}
}
}
catch (NotImplementedException)
List<EntityBase> moveEntities = new List<EntityBase>(Entities.Values);
foreach (EntityBase entity in moveEntities)
{
throw;
entity.UpdateMovement();
}
catch (Exception e)
{
MainLog.Instance.Error("Scene", "Failed with exception " + e.ToString());
}
updateLock.ReleaseMutex();
}
/// <summary>