From 48e0e05446b8490476fab4fb117d55c66abb40d3 Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Mon, 24 Sep 2007 15:46:03 +0000 Subject: * 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. --- OpenSim/Region/Environment/Scenes/Scene.cs | 248 ++++++++++++++++++----------- 1 file changed, 158 insertions(+), 90 deletions(-) (limited to 'OpenSim/Region/Environment/Scenes/Scene.cs') diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 8fc477a..4e9cbe3 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -60,15 +60,9 @@ namespace OpenSim.Region.Environment.Scenes protected Dictionary m_scenePresences; protected Dictionary 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,123 +254,180 @@ namespace OpenSim.Region.Environment.Scenes /// public override void Update() { + TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate; + // Aquire a lock so only one update call happens at once updateLock.WaitOne(); + try { - if (phyScene.IsThreaded) - { - phyScene.GetResults(); - /// no engines implement this, and what does it have to do with threading? possible DEAD CODE - } + // Increment the frame counter + m_frame++; - List moveEntities = new List(Entities.Values); + // Loop it + if (m_frame == Int32.MaxValue) + m_frame = 0; - foreach (EntityBase entity in moveEntities) - { - entity.UpdateMovement(); - } + if (m_frame % m_update_physics == 0) + UpdatePreparePhysics(); - lock (m_syncRoot) - { - phyScene.Simulate(timeStep); - } + if (m_frame % m_update_entitymovement == 0) + UpdateEntityMovement(); - List updateEntities = new List(Entities.Values); + if (m_frame % m_update_physics == 0) + UpdatePhysics( + Math.Min(SinceLastFrame.TotalSeconds, 0.001) + ); - foreach (EntityBase entity in updateEntities) - { - entity.Update(); - } + if (m_frame % m_update_entities == 0) + UpdateEntities(); + + if (m_frame % m_update_events == 0) + UpdateEvents(); - // General purpose event manager - m_eventManager.TriggerOnFrame(); + if (m_frame % m_update_backup == 0) + UpdateStorageBackup(); - //backup scene data - storageCount++; - if (storageCount > 1200) //set to how often you want to backup + 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(); + } + } + + private void UpdateAvatars() + { + m_timeUpdateCount++; + if (m_timeUpdateCount > 600) + { + List avatars = GetAvatars(); + foreach (ScenePresence avatar in avatars) { - Backup(); - storageCount = 0; + avatar.ControllingClient.SendViewerTime(m_timePhase); } - terrainCheckCount++; - if (terrainCheckCount >= 50) + m_timeUpdateCount = 0; + m_timePhase++; + if (m_timePhase > 94) { - terrainCheckCount = 0; + m_timePhase = 0; + } + } + } - if (Terrain.Tainted()) - { - CreateTerrainTexture(); + private void UpdateLand() + { + if (m_LandManager.landPrimCountTainted) + { + //Perform land update of prim count + performParcelPrimCountUpdate(); + } + } - lock (Terrain.heightmap) - { - lock (m_syncRoot) - { - phyScene.SetTerrain(Terrain.GetHeights1D()); - } + private void UpdateTerrain() + { + if (Terrain.Tainted()) + { + CreateTerrainTexture(); - storageManager.DataStore.StoreTerrain(Terrain.GetHeights2DD()); + lock (Terrain.heightmap) + { + lock (m_syncRoot) + { + phyScene.SetTerrain(Terrain.GetHeights1D()); + } - float[] terData = Terrain.GetHeights1D(); + storageManager.DataStore.StoreTerrain(Terrain.GetHeights2DD()); - Broadcast(delegate(IClientAPI client) + float[] terData = Terrain.GetHeights1D(); + + Broadcast(delegate(IClientAPI client) + { + for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) { - for (int x = 0; x < 16; x++) + if (Terrain.Tainted(x * 16, y * 16)) { - for (int y = 0; y < 16; y++) - { - if (Terrain.Tainted(x * 16, y * 16)) - { - client.SendLayerData(x, y, terData); - } - } + client.SendLayerData(x, y, terData); } - }); + } + } + }); - Terrain.ResetTaint(); - } - } + Terrain.ResetTaint(); } + } + } - landPrimCheckCount++; - if (landPrimCheckCount > 50) //check every 5 seconds for tainted prims - { - if (m_LandManager.landPrimCountTainted) - { - //Perform land update of prim count - performParcelPrimCountUpdate(); - landPrimCheckCount = 0; - } - } + private void UpdateStorageBackup() + { + Backup(); + } - m_timeUpdateCount++; - if (m_timeUpdateCount > 600) - { - List avatars = GetAvatars(); - foreach (ScenePresence avatar in avatars) - { - avatar.ControllingClient.SendViewerTime(m_timePhase); - } + private void UpdateEvents() + { + m_eventManager.TriggerOnFrame(); + } - m_timeUpdateCount = 0; - m_timePhase++; - if (m_timePhase > 94) - { - m_timePhase = 0; - } - } + private void UpdateEntities() + { + List updateEntities = new List(Entities.Values); + + foreach (EntityBase entity in updateEntities) + { + entity.Update(); } - catch (NotImplementedException) + } + + private void UpdatePhysics(double elapsed) + { + lock (m_syncRoot) { - throw; + phyScene.Simulate((float)elapsed); } - catch (Exception e) + } + + private void UpdateEntityMovement() + { + List moveEntities = new List(Entities.Values); + + foreach (EntityBase entity in moveEntities) { - MainLog.Instance.Error("Scene", "Failed with exception " + e.ToString()); + entity.UpdateMovement(); } - updateLock.ReleaseMutex(); } /// -- cgit v1.1