From 5c36561424c8b093e24c683c2ff6e83410739388 Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Mon, 28 Aug 2017 15:23:32 -0700
Subject: BulletSim: add clock and change logic for taint processing a little
 so taints check if they are not in simulation time and execute immediately if
 not.

---
 .../Region/PhysicsModules/BulletS/BSCharacter.cs   |  6 +-
 OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs    |  2 +-
 OpenSim/Region/PhysicsModules/BulletS/BSScene.cs   | 76 ++++++++++++++++------
 .../PhysicsModules/BulletS/BSShapeCollection.cs    |  4 +-
 .../Region/PhysicsModules/BulletS/BulletSimData.cs |  1 +
 5 files changed, 62 insertions(+), 27 deletions(-)

diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
index 57f03fb..04ac659 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
@@ -496,8 +496,8 @@ public sealed class BSCharacter : BSPhysObject
     public override OMV.Vector3 ForceVelocity {
         get { return RawVelocity; }
         set {
-            PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
-            DetailLog("{0}: BSCharacter.ForceVelocity.set = {1}", LocalID, value);
+            PhysScene.AssertNotInSimulationTime("BSCharacter.ForceVelocity");
+            DetailLog("{0},BSCharacter.ForceVelocity.set={1}", LocalID, value);
 
             RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
             PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
@@ -638,7 +638,7 @@ public sealed class BSCharacter : BSPhysObject
     public override float ForceBuoyancy {
         get { return _buoyancy; }
         set {
-            PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
+            PhysScene.AssertNotInSimulationTime("BSCharacter.ForceBuoyancy");
 
             _buoyancy = value;
             DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
index b153761..e1990ee 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
@@ -790,7 +790,7 @@ public class BSPrim : BSPhysObject
     public override OMV.Vector3 ForceVelocity {
         get { return RawVelocity; }
         set {
-            PhysScene.AssertInTaintTime("BSPrim.ForceVelocity");
+            PhysScene.AssertNotInSimulationTime("BSPrim.ForceVelocity");
 
             RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
             if (PhysBody.HasPhysicalBody)
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
index 7ff0a07..bcc3b4a 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
@@ -128,6 +128,9 @@ namespace OpenSim.Region.PhysicsModule.BulletS
         // Not guaranteed to be correct all the time (don't depend on this) but good for debugging.
         public bool InTaintTime { get; private set; }
 
+        // Flag that is true when the simulator is active and shouldn't be touched
+        public bool InSimulationTime { get; private set; }
+
         // Pinned memory used to pass step information between managed and unmanaged
         internal int m_maxCollisionsPerFrame;
         internal CollisionDesc[] m_collisionArray;
@@ -344,6 +347,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS
             // Put some informational messages into the log file.
             m_log.InfoFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation);
 
+            InSimulationTime = false;
             InTaintTime = false;
             m_initialized = true;
 
@@ -658,21 +662,21 @@ namespace OpenSim.Region.PhysicsModule.BulletS
             int beforeTime = Util.EnvironmentTickCount();
             int simTime = 0;
 
-            int numTaints = _taintOperations.Count;
-            InTaintTime = true; // Only used for debugging so locking is not necessary.
-
+            InTaintTime = true;
             // update the prim states while we know the physics engine is not busy
-            ProcessTaints();
+            int numTaints = ProcessTaints();
 
             // Some of the physical objects requre individual, pre-step calls
             //      (vehicles and avatar movement, in particular)
             TriggerPreStepEvent(timeStep);
 
             // the prestep actions might have added taints
-            numTaints += _taintOperations.Count;
-            ProcessTaints();
+            numTaints += ProcessTaints();
 
-            InTaintTime = false; // Only used for debugging so locking is not necessary.
+            lock (_taintLock)
+            {
+                InSimulationTime = true;
+            }
 
             // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
             // Only enable this in a limited test world with few objects.
@@ -700,6 +704,18 @@ namespace OpenSim.Region.PhysicsModule.BulletS
             if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0))
                 PE.DumpPhysicsStatistics(World);
 
+            lock (_taintLock)
+            {
+                InTaintTime = false;
+                InSimulationTime = false;
+            }
+
+            // Some actors want to know when the simulation step is complete.
+            TriggerPostStepEvent(timeStep);
+
+            // In case there were any parameter updates that happened during the simulation step
+            numTaints += ProcessTaints();
+
             // Get a value for 'now' so all the collision and update routines don't have to get their own.
             SimulationNowTime = Util.EnvironmentTickCount();
 
@@ -748,9 +764,6 @@ namespace OpenSim.Region.PhysicsModule.BulletS
                 }
             }
 
-            // Some actors want to know when the simulation step is complete.
-            TriggerPostStepEvent(timeStep);
-
             simTime = Util.EnvironmentTickCountSubtract(beforeTime);
             if (PhysicsLogging.Enabled)
             {
@@ -1090,6 +1103,15 @@ namespace OpenSim.Region.PhysicsModule.BulletS
         {
             if (!m_initialized) return;
 
+            lock (_taintLock) {
+                if (inTaintTime || !InSimulationTime) {
+                    pCallback();
+                }
+                else {
+                    _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback));
+                }
+            }
+            /*
             if (inTaintTime)
                 pCallback();
             else
@@ -1099,6 +1121,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS
                     _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback));
                 }
             }
+            */
         }
 
         private void TriggerPreStepEvent(float timeStep)
@@ -1120,14 +1143,19 @@ namespace OpenSim.Region.PhysicsModule.BulletS
         // When someone tries to change a property on a BSPrim or BSCharacter, the object queues
         // a callback into itself to do the actual property change. That callback is called
         // here just before the physics engine is called to step the simulation.
-        public void ProcessTaints()
+        // Returns the number of taints processed
+        public int ProcessTaints()
         {
-            ProcessRegularTaints();
-            ProcessPostTaintTaints();
+            int ret = 0;
+            ret += ProcessRegularTaints();
+            ret += ProcessPostTaintTaints();
+            return ret;
         }
 
-        private void ProcessRegularTaints()
+        // Returns the number of taints processed
+        private int ProcessRegularTaints()
         {
+            int ret = 0;
             if (m_initialized && _taintOperations.Count > 0)  // save allocating new list if there is nothing to process
             {
                 // swizzle a new list into the list location so we can process what's there
@@ -1144,6 +1172,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS
                     {
                         DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", tcbe.originator, tcbe.ident); // DEBUG DEBUG DEBUG
                         tcbe.callback();
+                        ret++;
                     }
                     catch (Exception e)
                     {
@@ -1152,6 +1181,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS
                 }
                 oldList.Clear();
             }
+            return ret;
         }
 
         // Schedule an update to happen after all the regular taints are processed.
@@ -1170,8 +1200,10 @@ namespace OpenSim.Region.PhysicsModule.BulletS
         }
 
         // Taints that happen after the normal taint processing but before the simulation step.
-        private void ProcessPostTaintTaints()
+        // Returns the number of taints processed
+        private int ProcessPostTaintTaints()
         {
+            int ret = 0;
             if (m_initialized && _postTaintOperations.Count > 0)
             {
                 Dictionary<string, TaintCallbackEntry> oldList;
@@ -1187,6 +1219,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS
                     {
                         DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG
                         kvp.Value.callback();
+                        ret++;
                     }
                     catch (Exception e)
                     {
@@ -1195,18 +1228,19 @@ namespace OpenSim.Region.PhysicsModule.BulletS
                 }
                 oldList.Clear();
             }
+            return ret;
         }
 
-        // Only used for debugging. Does not change state of anything so locking is not necessary.
-        public bool AssertInTaintTime(string whereFrom)
+        // Verify that things are being diddled when the physics engine is not running.
+        public bool AssertNotInSimulationTime(string whereFrom)
         {
-            if (!InTaintTime)
+            if (InSimulationTime)
             {
-                DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
-                m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
+                DetailLog("{0},BSScene.AssertInTaintTime,IN SIMULATION TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
+                m_log.ErrorFormat("{0} IN SIMULATION TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
                 // Util.PrintCallStack(DetailLog);
             }
-            return InTaintTime;
+            return InSimulationTime;
         }
 
         #endregion // Taints
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs b/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
index 4ec6f51..8d8fc95 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
@@ -75,7 +75,7 @@ public sealed class BSShapeCollection : IDisposable
     // Called at taint-time.
     public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback)
     {
-        m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
+        m_physicsScene.AssertNotInSimulationTime("BSShapeCollection.GetBodyAndShape");
 
         bool ret = false;
 
@@ -344,7 +344,7 @@ public sealed class BSShapeCollection : IDisposable
         if (!body.HasPhysicalBody)
             return;
 
-        m_physicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
+        m_physicsScene.AssertNotInSimulationTime("BSShapeCollection.DereferenceBody");
 
         lock (m_collectionActivityLock)
         {
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BulletSimData.cs b/OpenSim/Region/PhysicsModules/BulletS/BulletSimData.cs
index 3329395..308769b 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BulletSimData.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BulletSimData.cs
@@ -100,6 +100,7 @@ public class BulletBody
     }
 }
 
+// Handle to btCollisionObject - a shape that can be added to a btRidgidBody
 public class BulletShape
 {
     public BulletShape()
-- 
cgit v1.1