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.cs198
1 files changed, 170 insertions, 28 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index db0c99e..740f339 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
@@ -475,23 +486,21 @@ 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; 494 numTaints += _taintOperations.Count;
484 ProcessTaints(); // the vehicles might have added taints 495 ProcessTaints(); // the vehicles might have added taints
485 496
486 // step the physical world one interval 497 // step the physical world one interval
487 m_simulationStep++; 498 m_simulationStep++;
488 int numSubSteps = 0; 499 int numSubSteps = 0;
489 500
490 // DEBUG
491 // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep);
492
493 try 501 try
494 { 502 {
503 // DumpVehicles(); // DEBUG
495 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 504 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
496 505
497 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, 506 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
@@ -500,6 +509,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
500 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); 509 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
501 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", 510 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); 511 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
512 // DumpVehicles(); // DEBUG
503 } 513 }
504 catch (Exception e) 514 catch (Exception e)
505 { 515 {
@@ -575,6 +585,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
575 } 585 }
576 } 586 }
577 587
588 ProcessPostStepTaints();
589
578 // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. 590 // 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. 591 // Only enable this in a limited test world with few objects.
580 // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG 592 // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG
@@ -670,6 +682,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
670 682
671 public override bool IsThreaded { get { return false; } } 683 public override bool IsThreaded { get { return false; } }
672 684
685 #region Taints
686
673 // Calls to the PhysicsActors can't directly call into the physics engine 687 // 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. 688 // 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. 689 // We rely on C#'s closure to save and restore the context for the delegate.
@@ -679,30 +693,48 @@ public class BSScene : PhysicsScene, IPhysicsParameters
679 693
680 lock (_taintLock) 694 lock (_taintLock)
681 { 695 {
682 _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); 696 _taintOperations.Add(new TaintCallbackEntry(ident, callback));
683 } 697 }
684 698
685 return; 699 return;
686 } 700 }
687 701
702 // Sometimes a potentially tainted operation can be used in and out of taint time.
703 // This routine executes the command immediately if in taint-time otherwise it is queued.
704 public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback)
705 {
706 if (inTaintTime)
707 callback();
708 else
709 TaintedObject(ident, callback);
710 }
711
688 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues 712 // 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 713 // 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. 714 // here just before the physics engine is called to step the simulation.
691 public void ProcessTaints() 715 public void ProcessTaints()
692 { 716 {
693 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process 717 InTaintTime = true;
718 ProcessRegularTaints();
719 ProcessPostTaintTaints();
720 InTaintTime = false;
721 }
722
723 private void ProcessRegularTaints()
724 {
725 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process
694 { 726 {
695 int taintCount = m_taintsToProcessPerStep; 727 int taintCount = m_taintsToProcessPerStep;
696 TaintCallbackEntry oneCallback = new TaintCallbackEntry(); 728 TaintCallbackEntry oneCallback = new TaintCallbackEntry();
697 while (_taintedObjects.Count > 0 && taintCount-- > 0) 729 while (_taintOperations.Count > 0 && taintCount-- > 0)
698 { 730 {
699 bool gotOne = false; 731 bool gotOne = false;
700 lock (_taintLock) 732 lock (_taintLock)
701 { 733 {
702 if (_taintedObjects.Count > 0) 734 if (_taintOperations.Count > 0)
703 { 735 {
704 oneCallback = _taintedObjects[0]; 736 oneCallback = _taintOperations[0];
705 _taintedObjects.RemoveAt(0); 737 _taintOperations.RemoveAt(0);
706 gotOne = true; 738 gotOne = true;
707 } 739 }
708 } 740 }
@@ -746,6 +778,101 @@ public class BSScene : PhysicsScene, IPhysicsParameters
746 } 778 }
747 } 779 }
748 780
781 // Schedule an update to happen after all the regular taints are processed.
782 // Note that new requests for the same operation ("ident") for the same object ("ID")
783 // will replace any previous operation by the same object.
784 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
785 {
786 if (!m_initialized) return;
787
788 string uniqueIdent = ident + "-" + ID.ToString();
789 lock (_taintLock)
790 {
791 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback);
792 }
793
794 return;
795 }
796
797 private void ProcessPostTaintTaints()
798 {
799 if (_postTaintOperations.Count > 0)
800 {
801 Dictionary<string, TaintCallbackEntry> oldList;
802 lock (_taintLock)
803 {
804 oldList = _postTaintOperations;
805 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>();
806 }
807
808 foreach (KeyValuePair<string,TaintCallbackEntry> kvp in oldList)
809 {
810 try
811 {
812 DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG
813 kvp.Value.callback();
814 }
815 catch (Exception e)
816 {
817 m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e);
818 }
819 }
820 oldList.Clear();
821 }
822 }
823
824 public void PostStepTaintObject(String ident, TaintCallback callback)
825 {
826 if (!m_initialized) return;
827
828 lock (_taintLock)
829 {
830 _postStepOperations.Add(new TaintCallbackEntry(ident, callback));
831 }
832
833 return;
834 }
835
836 private void ProcessPostStepTaints()
837 {
838 if (_postStepOperations.Count > 0)
839 {
840 List<TaintCallbackEntry> oldList;
841 lock (_taintLock)
842 {
843 oldList = _postStepOperations;
844 _postStepOperations = new List<TaintCallbackEntry>();
845 }
846
847 foreach (TaintCallbackEntry tcbe in oldList)
848 {
849 try
850 {
851 DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
852 tcbe.callback();
853 }
854 catch (Exception e)
855 {
856 m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
857 }
858 }
859 oldList.Clear();
860 }
861 }
862
863 public bool AssertInTaintTime(string whereFrom)
864 {
865 if (!InTaintTime)
866 {
867 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
868 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
869 Util.PrintCallStack();
870 }
871 return InTaintTime;
872 }
873
874 #endregion // Taints
875
749 #region Vehicles 876 #region Vehicles
750 877
751 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) 878 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
@@ -970,49 +1097,49 @@ public class BSScene : PhysicsScene, IPhysicsParameters
970 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, 1097 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
971 (s) => { return s.m_params[0].linearDamping; }, 1098 (s) => { return s.m_params[0].linearDamping; },
972 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, 1099 (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); } ), 1100 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ),
974 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 1101 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
975 0f, 1102 0f,
976 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, 1103 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
977 (s) => { return s.m_params[0].angularDamping; }, 1104 (s) => { return s.m_params[0].angularDamping; },
978 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, 1105 (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); } ), 1106 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ),
980 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 1107 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
981 0.2f, 1108 0.2f,
982 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, 1109 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
983 (s) => { return s.m_params[0].deactivationTime; }, 1110 (s) => { return s.m_params[0].deactivationTime; },
984 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, 1111 (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); } ), 1112 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ),
986 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 1113 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
987 0.8f, 1114 0.8f,
988 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, 1115 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
989 (s) => { return s.m_params[0].linearSleepingThreshold; }, 1116 (s) => { return s.m_params[0].linearSleepingThreshold; },
990 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, 1117 (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); } ), 1118 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
992 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1119 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
993 1.0f, 1120 1.0f,
994 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, 1121 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
995 (s) => { return s.m_params[0].angularSleepingThreshold; }, 1122 (s) => { return s.m_params[0].angularSleepingThreshold; },
996 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, 1123 (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); } ), 1124 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
998 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 1125 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
999 0f, // set to zero to disable 1126 0f, // set to zero to disable
1000 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, 1127 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1001 (s) => { return s.m_params[0].ccdMotionThreshold; }, 1128 (s) => { return s.m_params[0].ccdMotionThreshold; },
1002 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, 1129 (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); } ), 1130 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ),
1004 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 1131 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1005 0f, 1132 0f,
1006 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, 1133 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1007 (s) => { return s.m_params[0].ccdSweptSphereRadius; }, 1134 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1008 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, 1135 (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); } ), 1136 (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ),
1010 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 1137 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1011 0.1f, 1138 0.1f,
1012 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, 1139 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1013 (s) => { return s.m_params[0].contactProcessingThreshold; }, 1140 (s) => { return s.m_params[0].contactProcessingThreshold; },
1014 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, 1141 (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); } ), 1142 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
1016 1143
1017 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1144 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1018 0.5f, 1145 0.5f,
@@ -1107,6 +1234,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1107 (s) => { return s.m_params[0].numberOfSolverIterations; }, 1234 (s) => { return s.m_params[0].numberOfSolverIterations; },
1108 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), 1235 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1109 1236
1237 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
1238 (float)BSLinkset.LinksetImplementation.Compound,
1239 (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); },
1240 (s) => { return s.m_params[0].linksetImplementation; },
1241 (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.", 1242 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1111 ConfigurationParameters.numericFalse, 1243 ConfigurationParameters.numericFalse,
1112 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1244 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
@@ -1128,12 +1260,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1128 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, 1260 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1129 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), 1261 (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", 1262 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1131 0.001f, 1263 0.1f,
1132 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, 1264 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1133 (s) => { return s.m_params[0].linkConstraintCFM; }, 1265 (s) => { return s.m_params[0].linkConstraintCFM; },
1134 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), 1266 (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", 1267 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1136 0.8f, 1268 0.1f,
1137 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, 1269 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1138 (s) => { return s.m_params[0].linkConstraintERP; }, 1270 (s) => { return s.m_params[0].linkConstraintERP; },
1139 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), 1271 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
@@ -1259,7 +1391,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1259 // If the local ID is APPLY_TO_NONE, just change the default value 1391 // 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 1392 // 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 1393 // 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) 1394 private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val)
1263 { 1395 {
1264 List<uint> objectIDs = new List<uint>(); 1396 List<uint> objectIDs = new List<uint>();
1265 switch (localID) 1397 switch (localID)
@@ -1284,7 +1416,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1284 } 1416 }
1285 1417
1286 // schedule the actual updating of the paramter to when the phys engine is not busy 1418 // 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) 1419 private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
1288 { 1420 {
1289 float xval = val; 1421 float xval = val;
1290 List<uint> xlIDs = lIDs; 1422 List<uint> xlIDs = lIDs;
@@ -1326,12 +1458,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1326 1458
1327 #endregion Runtime settable parameters 1459 #endregion Runtime settable parameters
1328 1460
1461 // Debugging routine for dumping detailed physical information for vehicle prims
1462 private void DumpVehicles()
1463 {
1464 foreach (BSPrim prim in m_vehicles)
1465 {
1466 BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr);
1467 BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr);
1468 }
1469 }
1470
1329 // Invoke the detailed logger and output something if it's enabled. 1471 // Invoke the detailed logger and output something if it's enabled.
1330 public void DetailLog(string msg, params Object[] args) 1472 public void DetailLog(string msg, params Object[] args)
1331 { 1473 {
1332 PhysicsLogging.Write(msg, args); 1474 PhysicsLogging.Write(msg, args);
1333 // Add the Flush() if debugging crashes to get all the messages written out. 1475 // Add the Flush() if debugging crashes. Gets all the messages written out.
1334 // PhysicsLogging.Flush(); 1476 PhysicsLogging.Flush();
1335 } 1477 }
1336 // Used to fill in the LocalID when there isn't one. It's the correct number of characters. 1478 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
1337 public const string DetailLogZero = "0000000000"; 1479 public const string DetailLogZero = "0000000000";