diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 198 |
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 | // |
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 | ||
@@ -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"; |