diff options
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 138 |
1 files changed, 122 insertions, 16 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 9e95ce5..cb52937 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -171,7 +171,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
171 | } | 171 | } |
172 | } | 172 | } |
173 | private Object _taintLock = new Object(); // lock for using the next object | 173 | private Object _taintLock = new Object(); // lock for using the next object |
174 | private List<TaintCallbackEntry> _taintedObjects; | 174 | private List<TaintCallbackEntry> _taintOperations; |
175 | private Dictionary<string, TaintCallbackEntry> _postTaintOperations; | ||
176 | private List<TaintCallbackEntry> _postStepOperations; | ||
175 | 177 | ||
176 | // A pointer to an instance if this structure is passed to the C++ code | 178 | // A pointer to an instance if this structure is passed to the C++ code |
177 | // Used to pass basic configuration values to the unmanaged code. | 179 | // Used to pass basic configuration values to the unmanaged code. |
@@ -203,7 +205,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
203 | public override void Initialise(IMesher meshmerizer, IConfigSource config) | 205 | public override void Initialise(IMesher meshmerizer, IConfigSource config) |
204 | { | 206 | { |
205 | mesher = meshmerizer; | 207 | mesher = meshmerizer; |
206 | _taintedObjects = new List<TaintCallbackEntry>(); | 208 | _taintOperations = new List<TaintCallbackEntry>(); |
209 | _postTaintOperations = new Dictionary<string, TaintCallbackEntry>(); | ||
210 | _postStepOperations = new List<TaintCallbackEntry>(); | ||
207 | PhysObjects = new Dictionary<uint, BSPhysObject>(); | 211 | PhysObjects = new Dictionary<uint, BSPhysObject>(); |
208 | Shapes = new BSShapeCollection(this); | 212 | Shapes = new BSShapeCollection(this); |
209 | 213 | ||
@@ -475,23 +479,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
475 | if (!m_initialized) return 5.0f; | 479 | if (!m_initialized) return 5.0f; |
476 | 480 | ||
477 | // update the prim states while we know the physics engine is not busy | 481 | // update the prim states while we know the physics engine is not busy |
478 | int numTaints = _taintedObjects.Count; | 482 | int numTaints = _taintOperations.Count; |
479 | ProcessTaints(); | 483 | ProcessTaints(); |
480 | 484 | ||
481 | // Some of the prims operate with special vehicle properties | 485 | // Some of the prims operate with special vehicle properties |
482 | ProcessVehicles(timeStep); | 486 | ProcessVehicles(timeStep); |
483 | numTaints += _taintedObjects.Count; | 487 | numTaints += _taintOperations.Count; |
484 | ProcessTaints(); // the vehicles might have added taints | 488 | ProcessTaints(); // the vehicles might have added taints |
485 | 489 | ||
486 | // step the physical world one interval | 490 | // step the physical world one interval |
487 | m_simulationStep++; | 491 | m_simulationStep++; |
488 | int numSubSteps = 0; | 492 | int numSubSteps = 0; |
489 | 493 | ||
490 | // DEBUG | ||
491 | // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); | ||
492 | |||
493 | try | 494 | try |
494 | { | 495 | { |
496 | // DumpVehicles(); // DEBUG | ||
495 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); | 497 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); |
496 | 498 | ||
497 | numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, | 499 | numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, |
@@ -500,6 +502,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
500 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); | 502 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); |
501 | DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", | 503 | DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", |
502 | DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); | 504 | DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); |
505 | // DumpVehicles(); // DEBUG | ||
503 | } | 506 | } |
504 | catch (Exception e) | 507 | catch (Exception e) |
505 | { | 508 | { |
@@ -579,6 +582,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
579 | // Only enable this in a limited test world with few objects. | 582 | // Only enable this in a limited test world with few objects. |
580 | // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG | 583 | // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG |
581 | 584 | ||
585 | ProcessPostStepTaints(); | ||
586 | |||
582 | // The physics engine returns the number of milliseconds it simulated this call. | 587 | // The physics engine returns the number of milliseconds it simulated this call. |
583 | // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. | 588 | // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. |
584 | // We multiply by 55 to give a recognizable running rate (55 or less). | 589 | // We multiply by 55 to give a recognizable running rate (55 or less). |
@@ -670,6 +675,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
670 | 675 | ||
671 | public override bool IsThreaded { get { return false; } } | 676 | public override bool IsThreaded { get { return false; } } |
672 | 677 | ||
678 | #region Taints | ||
679 | |||
673 | // Calls to the PhysicsActors can't directly call into the physics engine | 680 | // Calls to the PhysicsActors can't directly call into the physics engine |
674 | // because it might be busy. We delay changes to a known time. | 681 | // because it might be busy. We delay changes to a known time. |
675 | // We rely on C#'s closure to save and restore the context for the delegate. | 682 | // We rely on C#'s closure to save and restore the context for the delegate. |
@@ -679,7 +686,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
679 | 686 | ||
680 | lock (_taintLock) | 687 | lock (_taintLock) |
681 | { | 688 | { |
682 | _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); | 689 | _taintOperations.Add(new TaintCallbackEntry(ident, callback)); |
683 | } | 690 | } |
684 | 691 | ||
685 | return; | 692 | return; |
@@ -690,19 +697,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
690 | // here just before the physics engine is called to step the simulation. | 697 | // here just before the physics engine is called to step the simulation. |
691 | public void ProcessTaints() | 698 | public void ProcessTaints() |
692 | { | 699 | { |
693 | if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process | 700 | ProcessRegularTaints(); |
701 | ProcessPostTaintTaints(); | ||
702 | } | ||
703 | |||
704 | private void ProcessRegularTaints() | ||
705 | { | ||
706 | if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process | ||
694 | { | 707 | { |
695 | int taintCount = m_taintsToProcessPerStep; | 708 | int taintCount = m_taintsToProcessPerStep; |
696 | TaintCallbackEntry oneCallback = new TaintCallbackEntry(); | 709 | TaintCallbackEntry oneCallback = new TaintCallbackEntry(); |
697 | while (_taintedObjects.Count > 0 && taintCount-- > 0) | 710 | while (_taintOperations.Count > 0 && taintCount-- > 0) |
698 | { | 711 | { |
699 | bool gotOne = false; | 712 | bool gotOne = false; |
700 | lock (_taintLock) | 713 | lock (_taintLock) |
701 | { | 714 | { |
702 | if (_taintedObjects.Count > 0) | 715 | if (_taintOperations.Count > 0) |
703 | { | 716 | { |
704 | oneCallback = _taintedObjects[0]; | 717 | oneCallback = _taintOperations[0]; |
705 | _taintedObjects.RemoveAt(0); | 718 | _taintOperations.RemoveAt(0); |
706 | gotOne = true; | 719 | gotOne = true; |
707 | } | 720 | } |
708 | } | 721 | } |
@@ -746,6 +759,89 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
746 | } | 759 | } |
747 | } | 760 | } |
748 | 761 | ||
762 | // Schedule an update to happen after all the regular taints are processed. | ||
763 | // Note that new requests for the same operation ("ident") for the same object ("ID") | ||
764 | // will replace any previous operation by the same object. | ||
765 | public void PostTaintObject(String ident, uint ID, TaintCallback callback) | ||
766 | { | ||
767 | if (!m_initialized) return; | ||
768 | |||
769 | lock (_taintLock) | ||
770 | { | ||
771 | _postTaintOperations[ident] = new TaintCallbackEntry(ident + "-" + ID.ToString(), callback); | ||
772 | } | ||
773 | |||
774 | return; | ||
775 | } | ||
776 | |||
777 | private void ProcessPostTaintTaints() | ||
778 | { | ||
779 | if (_postTaintOperations.Count > 0) | ||
780 | { | ||
781 | Dictionary<string, TaintCallbackEntry> oldList; | ||
782 | lock (_taintLock) | ||
783 | { | ||
784 | oldList = _postTaintOperations; | ||
785 | _postTaintOperations = new Dictionary<string, TaintCallbackEntry>(); | ||
786 | } | ||
787 | |||
788 | foreach (KeyValuePair<string,TaintCallbackEntry> kvp in oldList) | ||
789 | { | ||
790 | try | ||
791 | { | ||
792 | DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG | ||
793 | kvp.Value.callback(); | ||
794 | } | ||
795 | catch (Exception e) | ||
796 | { | ||
797 | m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); | ||
798 | } | ||
799 | } | ||
800 | oldList.Clear(); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | public void PostStepTaintObject(String ident, TaintCallback callback) | ||
805 | { | ||
806 | if (!m_initialized) return; | ||
807 | |||
808 | lock (_taintLock) | ||
809 | { | ||
810 | _postStepOperations.Add(new TaintCallbackEntry(ident, callback)); | ||
811 | } | ||
812 | |||
813 | return; | ||
814 | } | ||
815 | |||
816 | private void ProcessPostStepTaints() | ||
817 | { | ||
818 | if (_postStepOperations.Count > 0) | ||
819 | { | ||
820 | List<TaintCallbackEntry> oldList; | ||
821 | lock (_taintLock) | ||
822 | { | ||
823 | oldList = _postStepOperations; | ||
824 | _postStepOperations = new List<TaintCallbackEntry>(); | ||
825 | } | ||
826 | |||
827 | foreach (TaintCallbackEntry tcbe in oldList) | ||
828 | { | ||
829 | try | ||
830 | { | ||
831 | DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG | ||
832 | tcbe.callback(); | ||
833 | } | ||
834 | catch (Exception e) | ||
835 | { | ||
836 | m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); | ||
837 | } | ||
838 | } | ||
839 | oldList.Clear(); | ||
840 | } | ||
841 | } | ||
842 | |||
843 | #endregion // Taints | ||
844 | |||
749 | #region Vehicles | 845 | #region Vehicles |
750 | 846 | ||
751 | public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) | 847 | public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) |
@@ -1006,7 +1102,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1006 | (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, | 1102 | (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, |
1007 | (s) => { return s.m_params[0].ccdSweptSphereRadius; }, | 1103 | (s) => { return s.m_params[0].ccdSweptSphereRadius; }, |
1008 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, | 1104 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, |
1009 | (s,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ), | 1105 | (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.BSBody.ptr, v); } ), |
1010 | new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , | 1106 | new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , |
1011 | 0.1f, | 1107 | 0.1f, |
1012 | (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, | 1108 | (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, |
@@ -1128,12 +1224,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1128 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, | 1224 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, |
1129 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), | 1225 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), |
1130 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", | 1226 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", |
1131 | 0.001f, | 1227 | 0.1f, |
1132 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, | 1228 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, |
1133 | (s) => { return s.m_params[0].linkConstraintCFM; }, | 1229 | (s) => { return s.m_params[0].linkConstraintCFM; }, |
1134 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), | 1230 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), |
1135 | new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", | 1231 | new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", |
1136 | 0.8f, | 1232 | 0.1f, |
1137 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, | 1233 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, |
1138 | (s) => { return s.m_params[0].linkConstraintERP; }, | 1234 | (s) => { return s.m_params[0].linkConstraintERP; }, |
1139 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), | 1235 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), |
@@ -1326,6 +1422,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1326 | 1422 | ||
1327 | #endregion Runtime settable parameters | 1423 | #endregion Runtime settable parameters |
1328 | 1424 | ||
1425 | // Debugging routine for dumping detailed physical information for vehicle prims | ||
1426 | private void DumpVehicles() | ||
1427 | { | ||
1428 | foreach (BSPrim prim in m_vehicles) | ||
1429 | { | ||
1430 | BulletSimAPI.DumpRigidBody2(World.ptr, prim.BSBody.ptr); | ||
1431 | BulletSimAPI.DumpCollisionShape2(World.ptr, prim.BSShape.ptr); | ||
1432 | } | ||
1433 | } | ||
1434 | |||
1329 | // Invoke the detailed logger and output something if it's enabled. | 1435 | // Invoke the detailed logger and output something if it's enabled. |
1330 | public void DetailLog(string msg, params Object[] args) | 1436 | public void DetailLog(string msg, params Object[] args) |
1331 | { | 1437 | { |