diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSScene.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 244 |
1 files changed, 200 insertions, 44 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 6621d39..27a78d1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -62,7 +62,7 @@ using OpenMetaverse; | |||
62 | // | 62 | // |
63 | namespace OpenSim.Region.Physics.BulletSPlugin | 63 | namespace OpenSim.Region.Physics.BulletSPlugin |
64 | { | 64 | { |
65 | public class BSScene : PhysicsScene, IPhysicsParameters | 65 | public sealed class BSScene : PhysicsScene, IPhysicsParameters |
66 | { | 66 | { |
67 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 67 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
68 | private static readonly string LogHeader = "[BULLETS SCENE]"; | 68 | private static readonly string LogHeader = "[BULLETS SCENE]"; |
@@ -116,6 +116,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
116 | // True if initialized and ready to do simulation steps | 116 | // True if initialized and ready to do simulation steps |
117 | private bool m_initialized = false; | 117 | private bool m_initialized = false; |
118 | 118 | ||
119 | // Flag which is true when processing taints. | ||
120 | // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. | ||
121 | public bool InTaintTime { get; private set; } | ||
122 | |||
119 | // Pinned memory used to pass step information between managed and unmanaged | 123 | // Pinned memory used to pass step information between managed and unmanaged |
120 | private int m_maxCollisionsPerFrame; | 124 | private int m_maxCollisionsPerFrame; |
121 | private CollisionDesc[] m_collisionArray; | 125 | private CollisionDesc[] m_collisionArray; |
@@ -171,7 +175,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
171 | } | 175 | } |
172 | } | 176 | } |
173 | private Object _taintLock = new Object(); // lock for using the next object | 177 | private Object _taintLock = new Object(); // lock for using the next object |
174 | private List<TaintCallbackEntry> _taintedObjects; | 178 | private List<TaintCallbackEntry> _taintOperations; |
179 | private Dictionary<string, TaintCallbackEntry> _postTaintOperations; | ||
180 | private List<TaintCallbackEntry> _postStepOperations; | ||
175 | 181 | ||
176 | // A pointer to an instance if this structure is passed to the C++ code | 182 | // 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. | 183 | // Used to pass basic configuration values to the unmanaged code. |
@@ -203,7 +209,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
203 | public override void Initialise(IMesher meshmerizer, IConfigSource config) | 209 | public override void Initialise(IMesher meshmerizer, IConfigSource config) |
204 | { | 210 | { |
205 | mesher = meshmerizer; | 211 | mesher = meshmerizer; |
206 | _taintedObjects = new List<TaintCallbackEntry>(); | 212 | _taintOperations = new List<TaintCallbackEntry>(); |
213 | _postTaintOperations = new Dictionary<string, TaintCallbackEntry>(); | ||
214 | _postStepOperations = new List<TaintCallbackEntry>(); | ||
207 | PhysObjects = new Dictionary<uint, BSPhysObject>(); | 215 | PhysObjects = new Dictionary<uint, BSPhysObject>(); |
208 | Shapes = new BSShapeCollection(this); | 216 | Shapes = new BSShapeCollection(this); |
209 | 217 | ||
@@ -266,6 +274,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
266 | TerrainManager = new BSTerrainManager(this); | 274 | TerrainManager = new BSTerrainManager(this); |
267 | TerrainManager.CreateInitialGroundPlaneAndTerrain(); | 275 | TerrainManager.CreateInitialGroundPlaneAndTerrain(); |
268 | 276 | ||
277 | m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); | ||
278 | |||
279 | InTaintTime = false; | ||
269 | m_initialized = true; | 280 | m_initialized = true; |
270 | } | 281 | } |
271 | 282 | ||
@@ -320,7 +331,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
320 | { | 331 | { |
321 | m_log.Debug("[BULLETS UNMANAGED]:" + msg); | 332 | m_log.Debug("[BULLETS UNMANAGED]:" + msg); |
322 | } | 333 | } |
323 | 334 | ||
324 | // Called directly from unmanaged code so don't do much | 335 | // Called directly from unmanaged code so don't do much |
325 | private void BulletLoggerPhysLog(string msg) | 336 | private void BulletLoggerPhysLog(string msg) |
326 | { | 337 | { |
@@ -475,23 +486,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
475 | if (!m_initialized) return 5.0f; | 486 | if (!m_initialized) return 5.0f; |
476 | 487 | ||
477 | // update the prim states while we know the physics engine is not busy | 488 | // update the prim states while we know the physics engine is not busy |
478 | int numTaints = _taintedObjects.Count; | 489 | int numTaints = _taintOperations.Count; |
479 | ProcessTaints(); | 490 | ProcessTaints(); |
480 | 491 | ||
481 | // Some of the prims operate with special vehicle properties | 492 | // Some of the prims operate with special vehicle properties |
482 | ProcessVehicles(timeStep); | 493 | ProcessVehicles(timeStep); |
483 | numTaints += _taintedObjects.Count; | ||
484 | ProcessTaints(); // the vehicles might have added taints | 494 | ProcessTaints(); // the vehicles might have added taints |
485 | 495 | ||
486 | // step the physical world one interval | 496 | // step the physical world one interval |
487 | m_simulationStep++; | 497 | m_simulationStep++; |
488 | int numSubSteps = 0; | 498 | int numSubSteps = 0; |
489 | 499 | ||
490 | // DEBUG | ||
491 | // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); | ||
492 | |||
493 | try | 500 | try |
494 | { | 501 | { |
502 | if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG | ||
495 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); | 503 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); |
496 | 504 | ||
497 | numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, | 505 | numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, |
@@ -500,6 +508,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
500 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); | 508 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); |
501 | DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", | 509 | 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); | 510 | DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); |
511 | if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG | ||
503 | } | 512 | } |
504 | catch (Exception e) | 513 | catch (Exception e) |
505 | { | 514 | { |
@@ -511,7 +520,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
511 | collidersCount = 0; | 520 | collidersCount = 0; |
512 | } | 521 | } |
513 | 522 | ||
514 | |||
515 | // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in | 523 | // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in |
516 | 524 | ||
517 | // Get a value for 'now' so all the collision and update routines don't have to get their own | 525 | // Get a value for 'now' so all the collision and update routines don't have to get their own |
@@ -545,7 +553,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
545 | } | 553 | } |
546 | 554 | ||
547 | // This is a kludge to get avatar movement updates. | 555 | // This is a kludge to get avatar movement updates. |
548 | // The simulator expects collisions for avatars even if there are have been no collisions. | 556 | // The simulator expects collisions for avatars even if there are have been no collisions. |
549 | // The event updates avatar animations and stuff. | 557 | // The event updates avatar animations and stuff. |
550 | // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. | 558 | // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. |
551 | foreach (BSPhysObject bsp in m_avatars) | 559 | foreach (BSPhysObject bsp in m_avatars) |
@@ -575,6 +583,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
575 | } | 583 | } |
576 | } | 584 | } |
577 | 585 | ||
586 | ProcessPostStepTaints(); | ||
587 | |||
578 | // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. | 588 | // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. |
579 | // Only enable this in a limited test world with few objects. | 589 | // Only enable this in a limited test world with few objects. |
580 | // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG | 590 | // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG |
@@ -670,8 +680,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
670 | 680 | ||
671 | public override bool IsThreaded { get { return false; } } | 681 | public override bool IsThreaded { get { return false; } } |
672 | 682 | ||
683 | #region Taints | ||
684 | |||
673 | // Calls to the PhysicsActors can't directly call into the physics engine | 685 | // 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. | 686 | // 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. | 687 | // We rely on C#'s closure to save and restore the context for the delegate. |
676 | public void TaintedObject(String ident, TaintCallback callback) | 688 | public void TaintedObject(String ident, TaintCallback callback) |
677 | { | 689 | { |
@@ -679,31 +691,51 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
679 | 691 | ||
680 | lock (_taintLock) | 692 | lock (_taintLock) |
681 | { | 693 | { |
682 | _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); | 694 | _taintOperations.Add(new TaintCallbackEntry(ident, callback)); |
683 | } | 695 | } |
684 | 696 | ||
685 | return; | 697 | return; |
686 | } | 698 | } |
687 | 699 | ||
700 | // Sometimes a potentially tainted operation can be used in and out of taint time. | ||
701 | // This routine executes the command immediately if in taint-time otherwise it is queued. | ||
702 | public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) | ||
703 | { | ||
704 | if (inTaintTime) | ||
705 | callback(); | ||
706 | else | ||
707 | TaintedObject(ident, callback); | ||
708 | } | ||
709 | |||
688 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues | 710 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues |
689 | // a callback into itself to do the actual property change. That callback is called | 711 | // a callback into itself to do the actual property change. That callback is called |
690 | // here just before the physics engine is called to step the simulation. | 712 | // here just before the physics engine is called to step the simulation. |
691 | public void ProcessTaints() | 713 | public void ProcessTaints() |
692 | { | 714 | { |
693 | if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process | 715 | InTaintTime = true; // Only used for debugging so locking is not necessary. |
716 | ProcessRegularTaints(); | ||
717 | ProcessPostTaintTaints(); | ||
718 | InTaintTime = false; | ||
719 | } | ||
720 | |||
721 | private void ProcessRegularTaints() | ||
722 | { | ||
723 | if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process | ||
694 | { | 724 | { |
695 | // swizzle a new list into the list location so we can process what's there | 725 | /* |
726 | // Code to limit the number of taints processed per step. Meant to limit step time. | ||
727 | // Unsure if a good idea as code assumes that taints are done before the step. | ||
696 | int taintCount = m_taintsToProcessPerStep; | 728 | int taintCount = m_taintsToProcessPerStep; |
697 | TaintCallbackEntry oneCallback = new TaintCallbackEntry(); | 729 | TaintCallbackEntry oneCallback = new TaintCallbackEntry(); |
698 | while (_taintedObjects.Count > 0 && taintCount-- > 0) | 730 | while (_taintOperations.Count > 0 && taintCount-- > 0) |
699 | { | 731 | { |
700 | bool gotOne = false; | 732 | bool gotOne = false; |
701 | lock (_taintLock) | 733 | lock (_taintLock) |
702 | { | 734 | { |
703 | if (_taintedObjects.Count > 0) | 735 | if (_taintOperations.Count > 0) |
704 | { | 736 | { |
705 | oneCallback = _taintedObjects[0]; | 737 | oneCallback = _taintOperations[0]; |
706 | _taintedObjects.RemoveAt(0); | 738 | _taintOperations.RemoveAt(0); |
707 | gotOne = true; | 739 | gotOne = true; |
708 | } | 740 | } |
709 | } | 741 | } |
@@ -711,22 +743,28 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
711 | { | 743 | { |
712 | try | 744 | try |
713 | { | 745 | { |
714 | DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG | 746 | DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); |
715 | oneCallback.callback(); | 747 | oneCallback.callback(); |
716 | } | 748 | } |
717 | catch (Exception e) | 749 | catch (Exception e) |
718 | { | 750 | { |
751 | DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG | ||
719 | m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); | 752 | m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); |
720 | } | 753 | } |
721 | } | 754 | } |
722 | } | 755 | } |
723 | /* | 756 | if (_taintOperations.Count > 0) |
757 | { | ||
758 | DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count); | ||
759 | } | ||
760 | */ | ||
761 | |||
724 | // swizzle a new list into the list location so we can process what's there | 762 | // swizzle a new list into the list location so we can process what's there |
725 | List<TaintCallbackEntry> oldList; | 763 | List<TaintCallbackEntry> oldList; |
726 | lock (_taintLock) | 764 | lock (_taintLock) |
727 | { | 765 | { |
728 | oldList = _taintedObjects; | 766 | oldList = _taintOperations; |
729 | _taintedObjects = new List<TaintCallbackEntry>(); | 767 | _taintOperations = new List<TaintCallbackEntry>(); |
730 | } | 768 | } |
731 | 769 | ||
732 | foreach (TaintCallbackEntry tcbe in oldList) | 770 | foreach (TaintCallbackEntry tcbe in oldList) |
@@ -742,10 +780,103 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
742 | } | 780 | } |
743 | } | 781 | } |
744 | oldList.Clear(); | 782 | oldList.Clear(); |
745 | */ | ||
746 | } | 783 | } |
747 | } | 784 | } |
748 | 785 | ||
786 | // Schedule an update to happen after all the regular taints are processed. | ||
787 | // Note that new requests for the same operation ("ident") for the same object ("ID") | ||
788 | // will replace any previous operation by the same object. | ||
789 | public void PostTaintObject(String ident, uint ID, TaintCallback callback) | ||
790 | { | ||
791 | string uniqueIdent = ident + "-" + ID.ToString(); | ||
792 | lock (_taintLock) | ||
793 | { | ||
794 | _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); | ||
795 | } | ||
796 | |||
797 | return; | ||
798 | } | ||
799 | |||
800 | private void ProcessPostTaintTaints() | ||
801 | { | ||
802 | if (_postTaintOperations.Count > 0) | ||
803 | { | ||
804 | Dictionary<string, TaintCallbackEntry> oldList; | ||
805 | lock (_taintLock) | ||
806 | { | ||
807 | oldList = _postTaintOperations; | ||
808 | _postTaintOperations = new Dictionary<string, TaintCallbackEntry>(); | ||
809 | } | ||
810 | |||
811 | foreach (KeyValuePair<string,TaintCallbackEntry> kvp in oldList) | ||
812 | { | ||
813 | try | ||
814 | { | ||
815 | DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG | ||
816 | kvp.Value.callback(); | ||
817 | } | ||
818 | catch (Exception e) | ||
819 | { | ||
820 | m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); | ||
821 | } | ||
822 | } | ||
823 | oldList.Clear(); | ||
824 | } | ||
825 | } | ||
826 | |||
827 | public void PostStepTaintObject(String ident, TaintCallback callback) | ||
828 | { | ||
829 | if (!m_initialized) return; | ||
830 | |||
831 | lock (_taintLock) | ||
832 | { | ||
833 | _postStepOperations.Add(new TaintCallbackEntry(ident, callback)); | ||
834 | } | ||
835 | |||
836 | return; | ||
837 | } | ||
838 | |||
839 | private void ProcessPostStepTaints() | ||
840 | { | ||
841 | if (_postStepOperations.Count > 0) | ||
842 | { | ||
843 | List<TaintCallbackEntry> oldList; | ||
844 | lock (_taintLock) | ||
845 | { | ||
846 | oldList = _postStepOperations; | ||
847 | _postStepOperations = new List<TaintCallbackEntry>(); | ||
848 | } | ||
849 | |||
850 | foreach (TaintCallbackEntry tcbe in oldList) | ||
851 | { | ||
852 | try | ||
853 | { | ||
854 | DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG | ||
855 | tcbe.callback(); | ||
856 | } | ||
857 | catch (Exception e) | ||
858 | { | ||
859 | m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); | ||
860 | } | ||
861 | } | ||
862 | oldList.Clear(); | ||
863 | } | ||
864 | } | ||
865 | |||
866 | // Only used for debugging. Does not change state of anything so locking is not necessary. | ||
867 | public bool AssertInTaintTime(string whereFrom) | ||
868 | { | ||
869 | if (!InTaintTime) | ||
870 | { | ||
871 | DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); | ||
872 | m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); | ||
873 | Util.PrintCallStack(); // Prints the stack into the DEBUG log file. | ||
874 | } | ||
875 | return InTaintTime; | ||
876 | } | ||
877 | |||
878 | #endregion // Taints | ||
879 | |||
749 | #region Vehicles | 880 | #region Vehicles |
750 | 881 | ||
751 | public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) | 882 | public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) |
@@ -916,7 +1047,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
916 | (s) => { return (float)s.m_maxUpdatesPerFrame; }, | 1047 | (s) => { return (float)s.m_maxUpdatesPerFrame; }, |
917 | (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), | 1048 | (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), |
918 | new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", | 1049 | new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", |
919 | 100f, | 1050 | 500f, |
920 | (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, | 1051 | (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, |
921 | (s) => { return (float)s.m_taintsToProcessPerStep; }, | 1052 | (s) => { return (float)s.m_taintsToProcessPerStep; }, |
922 | (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), | 1053 | (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), |
@@ -970,50 +1101,55 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
970 | (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, | 1101 | (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, |
971 | (s) => { return s.m_params[0].linearDamping; }, | 1102 | (s) => { return s.m_params[0].linearDamping; }, |
972 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, | 1103 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, |
973 | (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), | 1104 | (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, s.m_params[0].angularDamping); } ), |
974 | new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", | 1105 | new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", |
975 | 0f, | 1106 | 0f, |
976 | (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, | 1107 | (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, |
977 | (s) => { return s.m_params[0].angularDamping; }, | 1108 | (s) => { return s.m_params[0].angularDamping; }, |
978 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, | 1109 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, |
979 | (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), | 1110 | (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, s.m_params[0].linearDamping, v); } ), |
980 | new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", | 1111 | new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", |
981 | 0.2f, | 1112 | 0.2f, |
982 | (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, | 1113 | (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, |
983 | (s) => { return s.m_params[0].deactivationTime; }, | 1114 | (s) => { return s.m_params[0].deactivationTime; }, |
984 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, | 1115 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, |
985 | (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ), | 1116 | (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ), |
986 | new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", | 1117 | new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", |
987 | 0.8f, | 1118 | 0.8f, |
988 | (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, | 1119 | (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, |
989 | (s) => { return s.m_params[0].linearSleepingThreshold; }, | 1120 | (s) => { return s.m_params[0].linearSleepingThreshold; }, |
990 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, | 1121 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, |
991 | (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), | 1122 | (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), |
992 | new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", | 1123 | new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", |
993 | 1.0f, | 1124 | 1.0f, |
994 | (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, | 1125 | (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, |
995 | (s) => { return s.m_params[0].angularSleepingThreshold; }, | 1126 | (s) => { return s.m_params[0].angularSleepingThreshold; }, |
996 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, | 1127 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, |
997 | (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), | 1128 | (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), |
998 | new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , | 1129 | new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , |
999 | 0f, // set to zero to disable | 1130 | 0f, // set to zero to disable |
1000 | (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, | 1131 | (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, |
1001 | (s) => { return s.m_params[0].ccdMotionThreshold; }, | 1132 | (s) => { return s.m_params[0].ccdMotionThreshold; }, |
1002 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, | 1133 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, |
1003 | (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ), | 1134 | (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ), |
1004 | new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , | 1135 | new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , |
1005 | 0f, | 1136 | 0f, |
1006 | (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, | 1137 | (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, |
1007 | (s) => { return s.m_params[0].ccdSweptSphereRadius; }, | 1138 | (s) => { return s.m_params[0].ccdSweptSphereRadius; }, |
1008 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, | 1139 | (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); } ), | 1140 | (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ), |
1010 | new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , | 1141 | new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , |
1011 | 0.1f, | 1142 | 0.1f, |
1012 | (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, | 1143 | (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, |
1013 | (s) => { return s.m_params[0].contactProcessingThreshold; }, | 1144 | (s) => { return s.m_params[0].contactProcessingThreshold; }, |
1014 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, | 1145 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, |
1015 | (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ), | 1146 | (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), |
1016 | 1147 | ||
1148 | new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", | ||
1149 | (float)BSTerrainPhys.TerrainImplementation.Mesh, | ||
1150 | (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); }, | ||
1151 | (s) => { return s.m_params[0].terrainImplementation; }, | ||
1152 | (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ), | ||
1017 | new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , | 1153 | new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , |
1018 | 0.5f, | 1154 | 0.5f, |
1019 | (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, | 1155 | (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, |
@@ -1049,11 +1185,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1049 | (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, | 1185 | (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, |
1050 | (s) => { return s.m_params[0].avatarRestitution; }, | 1186 | (s) => { return s.m_params[0].avatarRestitution; }, |
1051 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), | 1187 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), |
1052 | new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", | 1188 | new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", |
1053 | 0.37f, | 1189 | 0.6f, |
1054 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, | 1190 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); }, |
1055 | (s) => { return s.m_params[0].avatarCapsuleRadius; }, | 1191 | (s) => { return s.m_params[0].avatarCapsuleWidth; }, |
1056 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), | 1192 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ), |
1193 | new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", | ||
1194 | 0.45f, | ||
1195 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); }, | ||
1196 | (s) => { return s.m_params[0].avatarCapsuleDepth; }, | ||
1197 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ), | ||
1057 | new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", | 1198 | new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", |
1058 | 1.5f, | 1199 | 1.5f, |
1059 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, | 1200 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, |
@@ -1107,6 +1248,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1107 | (s) => { return s.m_params[0].numberOfSolverIterations; }, | 1248 | (s) => { return s.m_params[0].numberOfSolverIterations; }, |
1108 | (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), | 1249 | (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), |
1109 | 1250 | ||
1251 | new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", | ||
1252 | (float)BSLinkset.LinksetImplementation.Compound, | ||
1253 | (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, | ||
1254 | (s) => { return s.m_params[0].linksetImplementation; }, | ||
1255 | (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), | ||
1110 | new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", | 1256 | new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", |
1111 | ConfigurationParameters.numericFalse, | 1257 | ConfigurationParameters.numericFalse, |
1112 | (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | 1258 | (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, |
@@ -1128,12 +1274,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1128 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, | 1274 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, |
1129 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), | 1275 | (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", | 1276 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", |
1131 | 0.001f, | 1277 | 0.1f, |
1132 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, | 1278 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, |
1133 | (s) => { return s.m_params[0].linkConstraintCFM; }, | 1279 | (s) => { return s.m_params[0].linkConstraintCFM; }, |
1134 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), | 1280 | (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", | 1281 | new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", |
1136 | 0.8f, | 1282 | 0.1f, |
1137 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, | 1283 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, |
1138 | (s) => { return s.m_params[0].linkConstraintERP; }, | 1284 | (s) => { return s.m_params[0].linkConstraintERP; }, |
1139 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), | 1285 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), |
@@ -1259,7 +1405,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1259 | // If the local ID is APPLY_TO_NONE, just change the default value | 1405 | // If the local ID is APPLY_TO_NONE, just change the default value |
1260 | // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs | 1406 | // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs |
1261 | // If the localID is a specific object, apply the parameter change to only that object | 1407 | // If the localID is a specific object, apply the parameter change to only that object |
1262 | protected void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) | 1408 | private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) |
1263 | { | 1409 | { |
1264 | List<uint> objectIDs = new List<uint>(); | 1410 | List<uint> objectIDs = new List<uint>(); |
1265 | switch (localID) | 1411 | switch (localID) |
@@ -1284,7 +1430,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1284 | } | 1430 | } |
1285 | 1431 | ||
1286 | // schedule the actual updating of the paramter to when the phys engine is not busy | 1432 | // schedule the actual updating of the paramter to when the phys engine is not busy |
1287 | protected void TaintedUpdateParameter(string parm, List<uint> lIDs, float val) | 1433 | private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val) |
1288 | { | 1434 | { |
1289 | float xval = val; | 1435 | float xval = val; |
1290 | List<uint> xlIDs = lIDs; | 1436 | List<uint> xlIDs = lIDs; |
@@ -1326,14 +1472,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1326 | 1472 | ||
1327 | #endregion Runtime settable parameters | 1473 | #endregion Runtime settable parameters |
1328 | 1474 | ||
1475 | // Debugging routine for dumping detailed physical information for vehicle prims | ||
1476 | private void DumpVehicles() | ||
1477 | { | ||
1478 | foreach (BSPrim prim in m_vehicles) | ||
1479 | { | ||
1480 | BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr); | ||
1481 | BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr); | ||
1482 | } | ||
1483 | } | ||
1484 | |||
1329 | // Invoke the detailed logger and output something if it's enabled. | 1485 | // Invoke the detailed logger and output something if it's enabled. |
1330 | public void DetailLog(string msg, params Object[] args) | 1486 | public void DetailLog(string msg, params Object[] args) |
1331 | { | 1487 | { |
1332 | PhysicsLogging.Write(msg, args); | 1488 | PhysicsLogging.Write(msg, args); |
1333 | // Add the Flush() if debugging crashes to get all the messages written out. | 1489 | // Add the Flush() if debugging crashes. Gets all the messages written out. |
1334 | // PhysicsLogging.Flush(); | 1490 | // PhysicsLogging.Flush(); |
1335 | } | 1491 | } |
1336 | // used to fill in the LocalID when there isn't one | 1492 | // Used to fill in the LocalID when there isn't one. It's the correct number of characters. |
1337 | public const string DetailLogZero = "0000000000"; | 1493 | public const string DetailLogZero = "0000000000"; |
1338 | 1494 | ||
1339 | } | 1495 | } |