diff options
author | Adam Frisby | 2007-09-24 15:46:03 +0000 |
---|---|---|
committer | Adam Frisby | 2007-09-24 15:46:03 +0000 |
commit | 48e0e05446b8490476fab4fb117d55c66abb40d3 (patch) | |
tree | dd07bbd1589a87b7f504ded561c651fa738f152c /OpenSim/Region/Environment | |
parent | More structural changes to new SE (diff) | |
download | opensim-SC-48e0e05446b8490476fab4fb117d55c66abb40d3.zip opensim-SC-48e0e05446b8490476fab4fb117d55c66abb40d3.tar.gz opensim-SC-48e0e05446b8490476fab4fb117d55c66abb40d3.tar.bz2 opensim-SC-48e0e05446b8490476fab4fb117d55c66abb40d3.tar.xz |
* 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.
Diffstat (limited to 'OpenSim/Region/Environment')
-rw-r--r-- | OpenSim/Region/Environment/Scenes/Scene.cs | 248 |
1 files changed, 158 insertions, 90 deletions
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 | |||
60 | protected Dictionary<LLUUID, ScenePresence> m_scenePresences; | 60 | protected Dictionary<LLUUID, ScenePresence> m_scenePresences; |
61 | protected Dictionary<LLUUID, SceneObjectGroup> m_sceneObjects; | 61 | protected Dictionary<LLUUID, SceneObjectGroup> m_sceneObjects; |
62 | 62 | ||
63 | /// publicized so it can be accessed from SceneObjectGroup. | ||
64 | protected float timeStep = 0.1f; | ||
65 | |||
66 | private Random Rand = new Random(); | 63 | private Random Rand = new Random(); |
67 | private uint _primCount = 702000; | 64 | private uint _primCount = 702000; |
68 | private readonly Mutex _primAllocateMutex = new Mutex(false); | 65 | private readonly Mutex _primAllocateMutex = new Mutex(false); |
69 | private int storageCount; | ||
70 | private int terrainCheckCount; | ||
71 | private int landPrimCheckCount; | ||
72 | 66 | ||
73 | private int m_timePhase = 24; | 67 | private int m_timePhase = 24; |
74 | private int m_timeUpdateCount; | 68 | private int m_timeUpdateCount; |
@@ -98,6 +92,23 @@ namespace OpenSim.Region.Environment.Scenes | |||
98 | private IHttpRequests m_httpRequestModule = null; | 92 | private IHttpRequests m_httpRequestModule = null; |
99 | private ISimChat m_simChatModule = null; | 93 | private ISimChat m_simChatModule = null; |
100 | 94 | ||
95 | |||
96 | // Central Update Loop | ||
97 | |||
98 | protected int m_fps = 10; | ||
99 | protected int m_frame = 0; | ||
100 | protected float m_timespan = 0.1f; | ||
101 | protected DateTime m_lastupdate = DateTime.Now; | ||
102 | |||
103 | private int m_update_physics = 1; | ||
104 | private int m_update_entitymovement = 1; | ||
105 | private int m_update_entities = 1; | ||
106 | private int m_update_events = 1; | ||
107 | private int m_update_backup = 200; | ||
108 | private int m_update_terrain = 50; | ||
109 | private int m_update_land = 1; | ||
110 | private int m_update_avatars = 1; | ||
111 | |||
101 | #region Properties | 112 | #region Properties |
102 | 113 | ||
103 | public AgentCircuitManager AuthenticateHandler | 114 | public AgentCircuitManager AuthenticateHandler |
@@ -222,7 +233,7 @@ namespace OpenSim.Region.Environment.Scenes | |||
222 | public void StartTimer() | 233 | public void StartTimer() |
223 | { | 234 | { |
224 | m_heartbeatTimer.Enabled = true; | 235 | m_heartbeatTimer.Enabled = true; |
225 | m_heartbeatTimer.Interval = 100; | 236 | m_heartbeatTimer.Interval = (int)(m_timespan * 1000); |
226 | m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); | 237 | m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); |
227 | } | 238 | } |
228 | 239 | ||
@@ -243,123 +254,180 @@ namespace OpenSim.Region.Environment.Scenes | |||
243 | /// </summary> | 254 | /// </summary> |
244 | public override void Update() | 255 | public override void Update() |
245 | { | 256 | { |
257 | TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate; | ||
258 | // Aquire a lock so only one update call happens at once | ||
246 | updateLock.WaitOne(); | 259 | updateLock.WaitOne(); |
260 | |||
247 | try | 261 | try |
248 | { | 262 | { |
249 | if (phyScene.IsThreaded) | 263 | // Increment the frame counter |
250 | { | 264 | m_frame++; |
251 | phyScene.GetResults(); | ||
252 | /// no engines implement this, and what does it have to do with threading? possible DEAD CODE | ||
253 | } | ||
254 | 265 | ||
255 | List<EntityBase> moveEntities = new List<EntityBase>(Entities.Values); | 266 | // Loop it |
267 | if (m_frame == Int32.MaxValue) | ||
268 | m_frame = 0; | ||
256 | 269 | ||
257 | foreach (EntityBase entity in moveEntities) | 270 | if (m_frame % m_update_physics == 0) |
258 | { | 271 | UpdatePreparePhysics(); |
259 | entity.UpdateMovement(); | ||
260 | } | ||
261 | 272 | ||
262 | lock (m_syncRoot) | 273 | if (m_frame % m_update_entitymovement == 0) |
263 | { | 274 | UpdateEntityMovement(); |
264 | phyScene.Simulate(timeStep); | ||
265 | } | ||
266 | 275 | ||
267 | List<EntityBase> updateEntities = new List<EntityBase>(Entities.Values); | 276 | if (m_frame % m_update_physics == 0) |
277 | UpdatePhysics( | ||
278 | Math.Min(SinceLastFrame.TotalSeconds, 0.001) | ||
279 | ); | ||
268 | 280 | ||
269 | foreach (EntityBase entity in updateEntities) | 281 | if (m_frame % m_update_entities == 0) |
270 | { | 282 | UpdateEntities(); |
271 | entity.Update(); | 283 | |
272 | } | 284 | if (m_frame % m_update_events == 0) |
285 | UpdateEvents(); | ||
273 | 286 | ||
274 | // General purpose event manager | 287 | if (m_frame % m_update_backup == 0) |
275 | m_eventManager.TriggerOnFrame(); | 288 | UpdateStorageBackup(); |
276 | 289 | ||
277 | //backup scene data | 290 | if (m_frame % m_update_terrain == 0) |
278 | storageCount++; | 291 | UpdateTerrain(); |
279 | if (storageCount > 1200) //set to how often you want to backup | 292 | |
293 | if (m_frame % m_update_land == 0) | ||
294 | UpdateLand(); | ||
295 | |||
296 | if (m_frame % m_update_avatars == 0) | ||
297 | UpdateAvatars(); | ||
298 | } | ||
299 | catch (NotImplementedException) | ||
300 | { | ||
301 | throw; | ||
302 | } | ||
303 | catch (Exception e) | ||
304 | { | ||
305 | MainLog.Instance.Error("Scene", "Failed with exception " + e.ToString()); | ||
306 | } | ||
307 | finally | ||
308 | { | ||
309 | updateLock.ReleaseMutex(); | ||
310 | m_lastupdate = DateTime.Now; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | private void UpdatePreparePhysics() | ||
315 | { | ||
316 | // If we are using a threaded physics engine | ||
317 | // grab the latest scene from the engine before | ||
318 | // trying to process it. | ||
319 | |||
320 | // PhysX does this (runs in the background). | ||
321 | |||
322 | if (phyScene.IsThreaded) | ||
323 | { | ||
324 | phyScene.GetResults(); | ||
325 | } | ||
326 | } | ||
327 | |||
328 | private void UpdateAvatars() | ||
329 | { | ||
330 | m_timeUpdateCount++; | ||
331 | if (m_timeUpdateCount > 600) | ||
332 | { | ||
333 | List<ScenePresence> avatars = GetAvatars(); | ||
334 | foreach (ScenePresence avatar in avatars) | ||
280 | { | 335 | { |
281 | Backup(); | 336 | avatar.ControllingClient.SendViewerTime(m_timePhase); |
282 | storageCount = 0; | ||
283 | } | 337 | } |
284 | 338 | ||
285 | terrainCheckCount++; | 339 | m_timeUpdateCount = 0; |
286 | if (terrainCheckCount >= 50) | 340 | m_timePhase++; |
341 | if (m_timePhase > 94) | ||
287 | { | 342 | { |
288 | terrainCheckCount = 0; | 343 | m_timePhase = 0; |
344 | } | ||
345 | } | ||
346 | } | ||
289 | 347 | ||
290 | if (Terrain.Tainted()) | 348 | private void UpdateLand() |
291 | { | 349 | { |
292 | CreateTerrainTexture(); | 350 | if (m_LandManager.landPrimCountTainted) |
351 | { | ||
352 | //Perform land update of prim count | ||
353 | performParcelPrimCountUpdate(); | ||
354 | } | ||
355 | } | ||
293 | 356 | ||
294 | lock (Terrain.heightmap) | 357 | private void UpdateTerrain() |
295 | { | 358 | { |
296 | lock (m_syncRoot) | 359 | if (Terrain.Tainted()) |
297 | { | 360 | { |
298 | phyScene.SetTerrain(Terrain.GetHeights1D()); | 361 | CreateTerrainTexture(); |
299 | } | ||
300 | 362 | ||
301 | storageManager.DataStore.StoreTerrain(Terrain.GetHeights2DD()); | 363 | lock (Terrain.heightmap) |
364 | { | ||
365 | lock (m_syncRoot) | ||
366 | { | ||
367 | phyScene.SetTerrain(Terrain.GetHeights1D()); | ||
368 | } | ||
302 | 369 | ||
303 | float[] terData = Terrain.GetHeights1D(); | 370 | storageManager.DataStore.StoreTerrain(Terrain.GetHeights2DD()); |
304 | 371 | ||
305 | Broadcast(delegate(IClientAPI client) | 372 | float[] terData = Terrain.GetHeights1D(); |
373 | |||
374 | Broadcast(delegate(IClientAPI client) | ||
375 | { | ||
376 | for (int x = 0; x < 16; x++) | ||
377 | { | ||
378 | for (int y = 0; y < 16; y++) | ||
306 | { | 379 | { |
307 | for (int x = 0; x < 16; x++) | 380 | if (Terrain.Tainted(x * 16, y * 16)) |
308 | { | 381 | { |
309 | for (int y = 0; y < 16; y++) | 382 | client.SendLayerData(x, y, terData); |
310 | { | ||
311 | if (Terrain.Tainted(x * 16, y * 16)) | ||
312 | { | ||
313 | client.SendLayerData(x, y, terData); | ||
314 | } | ||
315 | } | ||
316 | } | 383 | } |
317 | }); | 384 | } |
385 | } | ||
386 | }); | ||
318 | 387 | ||
319 | 388 | ||
320 | 389 | ||
321 | Terrain.ResetTaint(); | 390 | Terrain.ResetTaint(); |
322 | } | ||
323 | } | ||
324 | } | 391 | } |
392 | } | ||
393 | } | ||
325 | 394 | ||
326 | landPrimCheckCount++; | 395 | private void UpdateStorageBackup() |
327 | if (landPrimCheckCount > 50) //check every 5 seconds for tainted prims | 396 | { |
328 | { | 397 | Backup(); |
329 | if (m_LandManager.landPrimCountTainted) | 398 | } |
330 | { | ||
331 | //Perform land update of prim count | ||
332 | performParcelPrimCountUpdate(); | ||
333 | landPrimCheckCount = 0; | ||
334 | } | ||
335 | } | ||
336 | 399 | ||
337 | m_timeUpdateCount++; | 400 | private void UpdateEvents() |
338 | if (m_timeUpdateCount > 600) | 401 | { |
339 | { | 402 | m_eventManager.TriggerOnFrame(); |
340 | List<ScenePresence> avatars = GetAvatars(); | 403 | } |
341 | foreach (ScenePresence avatar in avatars) | ||
342 | { | ||
343 | avatar.ControllingClient.SendViewerTime(m_timePhase); | ||
344 | } | ||
345 | 404 | ||
346 | m_timeUpdateCount = 0; | 405 | private void UpdateEntities() |
347 | m_timePhase++; | 406 | { |
348 | if (m_timePhase > 94) | 407 | List<EntityBase> updateEntities = new List<EntityBase>(Entities.Values); |
349 | { | 408 | |
350 | m_timePhase = 0; | 409 | foreach (EntityBase entity in updateEntities) |
351 | } | 410 | { |
352 | } | 411 | entity.Update(); |
353 | } | 412 | } |
354 | catch (NotImplementedException) | 413 | } |
414 | |||
415 | private void UpdatePhysics(double elapsed) | ||
416 | { | ||
417 | lock (m_syncRoot) | ||
355 | { | 418 | { |
356 | throw; | 419 | phyScene.Simulate((float)elapsed); |
357 | } | 420 | } |
358 | catch (Exception e) | 421 | } |
422 | |||
423 | private void UpdateEntityMovement() | ||
424 | { | ||
425 | List<EntityBase> moveEntities = new List<EntityBase>(Entities.Values); | ||
426 | |||
427 | foreach (EntityBase entity in moveEntities) | ||
359 | { | 428 | { |
360 | MainLog.Instance.Error("Scene", "Failed with exception " + e.ToString()); | 429 | entity.UpdateMovement(); |
361 | } | 430 | } |
362 | updateLock.ReleaseMutex(); | ||
363 | } | 431 | } |
364 | 432 | ||
365 | /// <summary> | 433 | /// <summary> |