aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSScene.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs244
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//
63namespace OpenSim.Region.Physics.BulletSPlugin 63namespace OpenSim.Region.Physics.BulletSPlugin
64{ 64{
65public class BSScene : PhysicsScene, IPhysicsParameters 65public 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}