aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs159
1 files changed, 99 insertions, 60 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index a43de29..18376c3 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -329,6 +329,17 @@ namespace OpenSim.Region.Framework.Scenes
329 private Dictionary<string, string> m_extraSettings; 329 private Dictionary<string, string> m_extraSettings;
330 330
331 /// <summary> 331 /// <summary>
332 /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer
333 /// rather than on a single thread that sleeps.
334 /// </summary>
335 public bool UpdateOnTimer { get; set; }
336
337 /// <summary>
338 /// Only used if we are updating scene on a timer rather than sleeping a thread.
339 /// </summary>
340 private Timer m_sceneUpdateTimer;
341
342 /// <summary>
332 /// Current scene frame number 343 /// Current scene frame number
333 /// </summary> 344 /// </summary>
334 public uint Frame 345 public uint Frame
@@ -430,7 +441,8 @@ namespace OpenSim.Region.Framework.Scenes
430 /// Is the scene active? 441 /// Is the scene active?
431 /// </summary> 442 /// </summary>
432 /// <remarks> 443 /// <remarks>
433 /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if 444 /// If false, maintenance and update loops are not being run, though after setting to false update may still
445 /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if
434 /// the scene is not active. 446 /// the scene is not active.
435 /// </remarks> 447 /// </remarks>
436 public bool Active 448 public bool Active
@@ -453,8 +465,11 @@ namespace OpenSim.Region.Framework.Scenes
453 } 465 }
454 private volatile bool m_active; 466 private volatile bool m_active;
455 467
456// private int m_lastUpdate; 468 /// <summary>
457// private bool m_firstHeartbeat = true; 469 /// If true then updates are running. This may be true for a short period after a scene is de-activated.
470 /// </summary>
471 public bool IsRunning { get { return m_isRunning; } }
472 private volatile bool m_isRunning;
458 473
459 private Timer m_mapGenerationTimer = new Timer(); 474 private Timer m_mapGenerationTimer = new Timer();
460 private bool m_generateMaptiles; 475 private bool m_generateMaptiles;
@@ -1352,19 +1367,18 @@ namespace OpenSim.Region.Framework.Scenes
1352 /// </param> 1367 /// </param>
1353 public void Start(bool startScripts) 1368 public void Start(bool startScripts)
1354 { 1369 {
1370 if (IsRunning)
1371 return;
1372
1373 m_isRunning = true;
1355 m_active = true; 1374 m_active = true;
1356 1375
1357// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1376// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1358
1359 //m_heartbeatTimer.Enabled = true;
1360 //m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
1361 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1362 if (m_heartbeatThread != null) 1377 if (m_heartbeatThread != null)
1363 { 1378 {
1364 m_heartbeatThread.Abort(); 1379 m_heartbeatThread.Abort();
1365 m_heartbeatThread = null; 1380 m_heartbeatThread = null;
1366 } 1381 }
1367// m_lastUpdate = Util.EnvironmentTickCount();
1368 1382
1369 m_heartbeatThread 1383 m_heartbeatThread
1370 = Watchdog.StartThread( 1384 = Watchdog.StartThread(
@@ -1401,15 +1415,6 @@ namespace OpenSim.Region.Framework.Scenes
1401 /// </summary> 1415 /// </summary>
1402 private void Heartbeat() 1416 private void Heartbeat()
1403 { 1417 {
1404// if (!Monitor.TryEnter(m_heartbeatLock))
1405// {
1406// Watchdog.RemoveThread();
1407// return;
1408// }
1409
1410// try
1411// {
1412
1413 m_eventManager.TriggerOnRegionStarted(this); 1418 m_eventManager.TriggerOnRegionStarted(this);
1414 1419
1415 // The first frame can take a very long time due to physics actors being added on startup. Therefore, 1420 // The first frame can take a very long time due to physics actors being added on startup. Therefore,
@@ -1418,21 +1423,47 @@ namespace OpenSim.Region.Framework.Scenes
1418 Update(1); 1423 Update(1);
1419 1424
1420 Watchdog.StartThread( 1425 Watchdog.StartThread(
1421 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); 1426 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true);
1422 1427
1423 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1428 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1424 Update(-1); 1429 m_lastFrameTick = Util.EnvironmentTickCount();
1425 1430
1426// m_lastUpdate = Util.EnvironmentTickCount(); 1431 if (UpdateOnTimer)
1427// m_firstHeartbeat = false; 1432 {
1428// } 1433 m_sceneUpdateTimer = new Timer(MinFrameTime * 1000);
1429// finally 1434 m_sceneUpdateTimer.AutoReset = true;
1430// { 1435 m_sceneUpdateTimer.Elapsed += Update;
1431// Monitor.Pulse(m_heartbeatLock); 1436 m_sceneUpdateTimer.Start();
1432// Monitor.Exit(m_heartbeatLock); 1437 }
1433// } 1438 else
1439 {
1440 Update(-1);
1441 Watchdog.RemoveThread();
1442 m_isRunning = false;
1443 }
1444 }
1434 1445
1435 Watchdog.RemoveThread(); 1446 private volatile bool m_isTimerUpdateRunning;
1447
1448 private void Update(object sender, ElapsedEventArgs e)
1449 {
1450 if (m_isTimerUpdateRunning)
1451 return;
1452
1453 m_isTimerUpdateRunning = true;
1454
1455 // If the last frame did not complete on time, then immediately start the next update on the same thread
1456 // and ignore further timed updates until we have a frame that had spare time.
1457 while (!Update(1) && Active) {}
1458
1459 if (!Active || m_shuttingDown)
1460 {
1461 m_sceneUpdateTimer.Stop();
1462 m_sceneUpdateTimer = null;
1463 m_isRunning = false;
1464 }
1465
1466 m_isTimerUpdateRunning = false;
1436 } 1467 }
1437 1468
1438 private void Maintenance() 1469 private void Maintenance()
@@ -1502,7 +1533,7 @@ namespace OpenSim.Region.Framework.Scenes
1502 } 1533 }
1503 } 1534 }
1504 1535
1505 public override void Update(int frames) 1536 public override bool Update(int frames)
1506 { 1537 {
1507 long? endFrame = null; 1538 long? endFrame = null;
1508 1539
@@ -1511,7 +1542,6 @@ namespace OpenSim.Region.Framework.Scenes
1511 1542
1512 float physicsFPS = 0f; 1543 float physicsFPS = 0f;
1513 int previousFrameTick, tmpMS; 1544 int previousFrameTick, tmpMS;
1514 int maintc = Util.EnvironmentTickCount();
1515 1545
1516 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1546 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1517 { 1547 {
@@ -1651,24 +1681,29 @@ namespace OpenSim.Region.Framework.Scenes
1651 } 1681 }
1652 1682
1653 EventManager.TriggerRegionHeartbeatEnd(this); 1683 EventManager.TriggerRegionHeartbeatEnd(this);
1684 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1654 1685
1655 Watchdog.UpdateThread(); 1686 if (!UpdateOnTimer)
1687 {
1688 Watchdog.UpdateThread();
1656 1689
1657 previousFrameTick = m_lastFrameTick; 1690 tmpMS = Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), m_lastFrameTick);
1658 m_lastFrameTick = Util.EnvironmentTickCount(); 1691 tmpMS = (int)(MinFrameTime * 1000) - tmpMS;
1659 tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1660 tmpMS = (int)(MinFrameTime * 1000) - tmpMS;
1661 1692
1662 if (tmpMS > 0) 1693 if (tmpMS > 0)
1694 {
1695 spareMS = tmpMS;
1696 Thread.Sleep(tmpMS);
1697 }
1698 }
1699 else
1663 { 1700 {
1664 Thread.Sleep(tmpMS); 1701 spareMS = Math.Max(0, (int)(MinFrameTime * 1000) - physicsMS2 - agentMS - physicsMS -otherMS);
1665 spareMS += tmpMS;
1666 } 1702 }
1667 1703
1668 frameMS = Util.EnvironmentTickCountSubtract(maintc); 1704 previousFrameTick = m_lastFrameTick;
1669 maintc = Util.EnvironmentTickCount(); 1705 frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick);
1670 1706 m_lastFrameTick = Util.EnvironmentTickCount();
1671 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1672 1707
1673 // if (Frame%m_update_avatars == 0) 1708 // if (Frame%m_update_avatars == 0)
1674 // UpdateInWorldTime(); 1709 // UpdateInWorldTime();
@@ -1683,7 +1718,7 @@ namespace OpenSim.Region.Framework.Scenes
1683 StatsReporter.AddSpareMS(spareMS); 1718 StatsReporter.AddSpareMS(spareMS);
1684 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); 1719 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1685 1720
1686 // Optionally warn if a frame takes double the amount of time that it should. 1721 // Optionally warn if a frame takes double the amount of time that it should.
1687 if (DebugUpdates 1722 if (DebugUpdates
1688 && Util.EnvironmentTickCountSubtract( 1723 && Util.EnvironmentTickCountSubtract(
1689 m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) 1724 m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2))
@@ -1693,6 +1728,8 @@ namespace OpenSim.Region.Framework.Scenes
1693 MinFrameTime * 1000, 1728 MinFrameTime * 1000,
1694 RegionInfo.RegionName); 1729 RegionInfo.RegionName);
1695 } 1730 }
1731
1732 return spareMS >= 0;
1696 } 1733 }
1697 1734
1698 public void AddGroupTarget(SceneObjectGroup grp) 1735 public void AddGroupTarget(SceneObjectGroup grp)
@@ -2073,8 +2110,8 @@ namespace OpenSim.Region.Framework.Scenes
2073 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 2110 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
2074 2111
2075 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 2112 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
2076 Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z); 2113 Vector3 AXOrigin = RayStart;
2077 Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z); 2114 Vector3 AXdirection = direction;
2078 2115
2079 if (target != null) 2116 if (target != null)
2080 { 2117 {
@@ -2090,19 +2127,19 @@ namespace OpenSim.Region.Framework.Scenes
2090 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 2127 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
2091 2128
2092 // Un-comment out the following line to Get Raytrace results printed to the console. 2129 // Un-comment out the following line to Get Raytrace results printed to the console.
2093 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 2130 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2094 float ScaleOffset = 0.5f; 2131 float ScaleOffset = 0.5f;
2095 2132
2096 // If we hit something 2133 // If we hit something
2097 if (ei.HitTF) 2134 if (ei.HitTF)
2098 { 2135 {
2099 Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z); 2136 Vector3 scaleComponent = ei.AAfaceNormal;
2100 if (scaleComponent.X != 0) ScaleOffset = scale.X; 2137 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2101 if (scaleComponent.Y != 0) ScaleOffset = scale.Y; 2138 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2102 if (scaleComponent.Z != 0) ScaleOffset = scale.Z; 2139 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2103 ScaleOffset = Math.Abs(ScaleOffset); 2140 ScaleOffset = Math.Abs(ScaleOffset);
2104 Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2141 Vector3 intersectionpoint = ei.ipoint;
2105 Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z); 2142 Vector3 normal = ei.normal;
2106 // Set the position to the intersection point 2143 // Set the position to the intersection point
2107 Vector3 offset = (normal * (ScaleOffset / 2f)); 2144 Vector3 offset = (normal * (ScaleOffset / 2f));
2108 pos = (intersectionpoint + offset); 2145 pos = (intersectionpoint + offset);
@@ -2127,8 +2164,9 @@ namespace OpenSim.Region.Framework.Scenes
2127 2164
2128 if (ei.HitTF) 2165 if (ei.HitTF)
2129 { 2166 {
2130 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2167 pos = ei.ipoint;
2131 } else 2168 }
2169 else
2132 { 2170 {
2133 // fall back to our stupid functionality 2171 // fall back to our stupid functionality
2134 pos = RayEnd; 2172 pos = RayEnd;
@@ -3181,8 +3219,8 @@ namespace OpenSim.Region.Framework.Scenes
3181 if (target != null && target2 != null) 3219 if (target != null && target2 != null)
3182 { 3220 {
3183 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 3221 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
3184 Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z); 3222 Vector3 AXOrigin = RayStart;
3185 Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z); 3223 Vector3 AXdirection = direction;
3186 3224
3187 pos = target2.AbsolutePosition; 3225 pos = target2.AbsolutePosition;
3188 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); 3226 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
@@ -3203,13 +3241,13 @@ namespace OpenSim.Region.Framework.Scenes
3203 if (ei.HitTF) 3241 if (ei.HitTF)
3204 { 3242 {
3205 Vector3 scale = target.Scale; 3243 Vector3 scale = target.Scale;
3206 Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z); 3244 Vector3 scaleComponent = ei.AAfaceNormal;
3207 if (scaleComponent.X != 0) ScaleOffset = scale.X; 3245 if (scaleComponent.X != 0) ScaleOffset = scale.X;
3208 if (scaleComponent.Y != 0) ScaleOffset = scale.Y; 3246 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
3209 if (scaleComponent.Z != 0) ScaleOffset = scale.Z; 3247 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
3210 ScaleOffset = Math.Abs(ScaleOffset); 3248 ScaleOffset = Math.Abs(ScaleOffset);
3211 Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 3249 Vector3 intersectionpoint = ei.ipoint;
3212 Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z); 3250 Vector3 normal = ei.normal;
3213 Vector3 offset = normal * (ScaleOffset / 2f); 3251 Vector3 offset = normal * (ScaleOffset / 2f);
3214 pos = intersectionpoint + offset; 3252 pos = intersectionpoint + offset;
3215 3253
@@ -3229,6 +3267,7 @@ namespace OpenSim.Region.Framework.Scenes
3229 { 3267 {
3230 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); 3268 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity);
3231 } 3269 }
3270
3232 if (copy != null) 3271 if (copy != null)
3233 EventManager.TriggerObjectAddedToScene(copy); 3272 EventManager.TriggerObjectAddedToScene(copy);
3234 } 3273 }
@@ -5061,7 +5100,7 @@ namespace OpenSim.Region.Framework.Scenes
5061 case PhysicsJointType.Ball: 5100 case PhysicsJointType.Ball:
5062 { 5101 {
5063 Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); 5102 Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint);
5064 Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z); 5103 Vector3 proxyPos = jointAnchor;
5065 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update 5104 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update
5066 } 5105 }
5067 break; 5106 break;
@@ -5086,7 +5125,7 @@ namespace OpenSim.Region.Framework.Scenes
5086 jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene); 5125 jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene);
5087 } 5126 }
5088 5127
5089 Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z); 5128 Vector3 proxyPos = jointAnchor;
5090 Quaternion q = trackedBody.RotationOffset * joint.LocalRotation; 5129 Quaternion q = trackedBody.RotationOffset * joint.LocalRotation;
5091 5130
5092 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update 5131 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update
@@ -5187,8 +5226,8 @@ namespace OpenSim.Region.Framework.Scenes
5187 y = Heightmap.Height - 1; 5226 y = Heightmap.Height - 1;
5188 5227
5189 Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]); 5228 Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]);
5190 Vector3 p1 = new Vector3(p0); 5229 Vector3 p1 = p0;
5191 Vector3 p2 = new Vector3(p0); 5230 Vector3 p2 = p0;
5192 5231
5193 p1.X += 1.0f; 5232 p1.X += 1.0f;
5194 if (p1.X < Heightmap.Width) 5233 if (p1.X < Heightmap.Width)