diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs index 57f03fb9e3..04ac65979d 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 b1537615a1..e1990eea5d 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 7ff0a07d5a..bcc3b4ae79 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 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 4ec6f514be..8d8fc95823 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 3329395274..308769b3d0 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()