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.cs748
1 files changed, 74 insertions, 674 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 2ca4912..e8e0d50 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -69,20 +69,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
69 // every tick so OpenSim will update its animation. 69 // every tick so OpenSim will update its animation.
70 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>(); 70 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
71 71
72 // List of all the objects that have vehicle properties and should be called
73 // to update each physics step.
74 private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
75
76 // let my minuions use my logger 72 // let my minuions use my logger
77 public ILog Logger { get { return m_log; } } 73 public ILog Logger { get { return m_log; } }
78 74
79 public IMesher mesher; 75 public IMesher mesher;
80 // Level of Detail values kept as float because that's what the Meshmerizer wants
81 public float MeshLOD { get; private set; }
82 public float MeshMegaPrimLOD { get; private set; }
83 public float MeshMegaPrimThreshold { get; private set; }
84 public float SculptLOD { get; private set; }
85
86 public uint WorldID { get; private set; } 76 public uint WorldID { get; private set; }
87 public BulletSim World { get; private set; } 77 public BulletSim World { get; private set; }
88 78
@@ -90,24 +80,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
90 public BSConstraintCollection Constraints { get; private set; } 80 public BSConstraintCollection Constraints { get; private set; }
91 81
92 // Simulation parameters 82 // Simulation parameters
93 private int m_maxSubSteps; 83 internal int m_maxSubSteps;
94 private float m_fixedTimeStep; 84 internal float m_fixedTimeStep;
95 private long m_simulationStep = 0; 85 internal long m_simulationStep = 0;
96 public long SimulationStep { get { return m_simulationStep; } } 86 public long SimulationStep { get { return m_simulationStep; } }
97 private int m_taintsToProcessPerStep; 87 internal int m_taintsToProcessPerStep;
98 88 internal float LastTimeStep { get; private set; }
99 // Avatar parameters
100 public float ParamAvatarFriction { get; private set; }
101 public float ParamAvatarStandingFriction { get; private set; }
102 public float ParamAvatarDensity { get; private set; }
103 public float ParamAvatarRestitution { get; private set; }
104 public float ParamAvatarCapsuleWidth { get; private set; }
105 public float ParamAvatarCapsuleDepth { get; private set; }
106 public float ParamAvatarCapsuleHeight { get; private set; }
107 public float ParamAvatarContactProcessingThreshold { get; private set; }
108 89
90 // Physical objects can register for prestep or poststep events
109 public delegate void PreStepAction(float timeStep); 91 public delegate void PreStepAction(float timeStep);
92 public delegate void PostStepAction(float timeStep);
110 public event PreStepAction BeforeStep; 93 public event PreStepAction BeforeStep;
94 public event PreStepAction AfterStep;
111 95
112 // A value of the time now so all the collision and update routines do not have to get their own 96 // A value of the time now so all the collision and update routines do not have to get their own
113 // Set to 'now' just before all the prims and actors are called for collisions and updates 97 // Set to 'now' just before all the prims and actors are called for collisions and updates
@@ -121,20 +105,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
121 public bool InTaintTime { get; private set; } 105 public bool InTaintTime { get; private set; }
122 106
123 // Pinned memory used to pass step information between managed and unmanaged 107 // Pinned memory used to pass step information between managed and unmanaged
124 private int m_maxCollisionsPerFrame; 108 internal int m_maxCollisionsPerFrame;
125 private CollisionDesc[] m_collisionArray; 109 internal CollisionDesc[] m_collisionArray;
126 private GCHandle m_collisionArrayPinnedHandle; 110 internal GCHandle m_collisionArrayPinnedHandle;
127
128 private int m_maxUpdatesPerFrame;
129 private EntityProperties[] m_updateArray;
130 private GCHandle m_updateArrayPinnedHandle;
131 111
132 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed 112 internal int m_maxUpdatesPerFrame;
133 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes 113 internal EntityProperties[] m_updateArray;
134 public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects 114 internal GCHandle m_updateArrayPinnedHandle;
135
136 public float PID_D { get; private set; } // derivative
137 public float PID_P { get; private set; } // proportional
138 115
139 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 116 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
140 public const uint GROUNDPLANE_ID = 1; 117 public const uint GROUNDPLANE_ID = 1;
@@ -145,7 +122,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
145 122
146 public ConfigurationParameters Params 123 public ConfigurationParameters Params
147 { 124 {
148 get { return m_params[0]; } 125 get { return UnmanagedParams[0]; }
149 } 126 }
150 public Vector3 DefaultGravity 127 public Vector3 DefaultGravity
151 { 128 {
@@ -157,8 +134,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
157 get { return Params.gravity; } 134 get { return Params.gravity; }
158 } 135 }
159 136
160 public float MaximumObjectMass { get; private set; }
161
162 // When functions in the unmanaged code must be called, it is only 137 // When functions in the unmanaged code must be called, it is only
163 // done at a known time just before the simulation step. The taint 138 // done at a known time just before the simulation step. The taint
164 // system saves all these function calls and executes them in 139 // system saves all these function calls and executes them in
@@ -181,7 +156,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
181 156
182 // A pointer to an instance if this structure is passed to the C++ code 157 // A pointer to an instance if this structure is passed to the C++ code
183 // Used to pass basic configuration values to the unmanaged code. 158 // Used to pass basic configuration values to the unmanaged code.
184 ConfigurationParameters[] m_params; 159 internal ConfigurationParameters[] UnmanagedParams;
185 GCHandle m_paramsHandle; 160 GCHandle m_paramsHandle;
186 161
187 // Handle to the callback used by the unmanaged code to call into the managed code. 162 // Handle to the callback used by the unmanaged code to call into the managed code.
@@ -218,8 +193,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
218 Shapes = new BSShapeCollection(this); 193 Shapes = new BSShapeCollection(this);
219 194
220 // Allocate pinned memory to pass parameters. 195 // Allocate pinned memory to pass parameters.
221 m_params = new ConfigurationParameters[1]; 196 UnmanagedParams = new ConfigurationParameters[1];
222 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); 197 m_paramsHandle = GCHandle.Alloc(UnmanagedParams, GCHandleType.Pinned);
223 198
224 // Set default values for physics parameters plus any overrides from the ini file 199 // Set default values for physics parameters plus any overrides from the ini file
225 GetInitialParameterValues(config); 200 GetInitialParameterValues(config);
@@ -277,7 +252,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
277 TerrainManager = new BSTerrainManager(this); 252 TerrainManager = new BSTerrainManager(this);
278 TerrainManager.CreateInitialGroundPlaneAndTerrain(); 253 TerrainManager.CreateInitialGroundPlaneAndTerrain();
279 254
280 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); 255 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation);
281 256
282 InTaintTime = false; 257 InTaintTime = false;
283 m_initialized = true; 258 m_initialized = true;
@@ -288,9 +263,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
288 private void GetInitialParameterValues(IConfigSource config) 263 private void GetInitialParameterValues(IConfigSource config)
289 { 264 {
290 ConfigurationParameters parms = new ConfigurationParameters(); 265 ConfigurationParameters parms = new ConfigurationParameters();
291 m_params[0] = parms; 266 UnmanagedParams[0] = parms;
292 267
293 SetParameterDefaultValues(); 268 BSParam.SetParameterDefaultValues(this);
294 269
295 if (config != null) 270 if (config != null)
296 { 271 {
@@ -298,7 +273,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
298 IConfig pConfig = config.Configs["BulletSim"]; 273 IConfig pConfig = config.Configs["BulletSim"];
299 if (pConfig != null) 274 if (pConfig != null)
300 { 275 {
301 SetParameterConfigurationValues(pConfig); 276 BSParam.SetParameterConfigurationValues(this, pConfig);
302 277
303 // Very detailed logging for physics debugging 278 // Very detailed logging for physics debugging
304 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 279 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@@ -492,6 +467,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
492 // Simulate one timestep 467 // Simulate one timestep
493 public override float Simulate(float timeStep) 468 public override float Simulate(float timeStep)
494 { 469 {
470 // prevent simulation until we've been initialized
471 if (!m_initialized) return 5.0f;
472
473 LastTimeStep = timeStep;
474
495 int updatedEntityCount = 0; 475 int updatedEntityCount = 0;
496 IntPtr updatedEntitiesPtr; 476 IntPtr updatedEntitiesPtr;
497 int collidersCount = 0; 477 int collidersCount = 0;
@@ -500,26 +480,27 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
500 int beforeTime = 0; 480 int beforeTime = 0;
501 int simTime = 0; 481 int simTime = 0;
502 482
503 // prevent simulation until we've been initialized
504 if (!m_initialized) return 5.0f;
505
506 // update the prim states while we know the physics engine is not busy 483 // update the prim states while we know the physics engine is not busy
507 int numTaints = _taintOperations.Count; 484 int numTaints = _taintOperations.Count;
485
486 InTaintTime = true; // Only used for debugging so locking is not necessary.
487
508 ProcessTaints(); 488 ProcessTaints();
509 489
510 // Some of the prims operate with special vehicle properties 490 // Some of the physical objects requre individual, pre-step calls
511 DoPreStepActions(timeStep); 491 TriggerPreStepEvent(timeStep);
512 492
513 // the prestep actions might have added taints 493 // the prestep actions might have added taints
514 ProcessTaints(); 494 ProcessTaints();
515 495
496 InTaintTime = false; // Only used for debugging so locking is not necessary.
497
516 // step the physical world one interval 498 // step the physical world one interval
517 m_simulationStep++; 499 m_simulationStep++;
518 int numSubSteps = 0; 500 int numSubSteps = 0;
519 501
520 try 502 try
521 { 503 {
522 if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
523 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 504 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
524 505
525 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, 506 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
@@ -529,7 +510,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
529 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", 510 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
530 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, 511 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
531 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); 512 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
532 if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
533 } 513 }
534 catch (Exception e) 514 catch (Exception e)
535 { 515 {
@@ -608,7 +588,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
608 } 588 }
609 } 589 }
610 590
611 ProcessPostStepTaints(); 591 TriggerPostStepEvent(timeStep);
612 592
613 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. 593 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
614 // Only enable this in a limited test world with few objects. 594 // Only enable this in a limited test world with few objects.
@@ -700,6 +680,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
700 public override bool IsThreaded { get { return false; } } 680 public override bool IsThreaded { get { return false; } }
701 681
702 #region Taints 682 #region Taints
683 // The simulation execution order is:
684 // Simulate()
685 // DoOneTimeTaints
686 // TriggerPreStepEvent
687 // DoOneTimeTaints
688 // Step()
689 // ProcessAndForwardCollisions
690 // ProcessAndForwardPropertyUpdates
691 // TriggerPostStepEvent
703 692
704 // Calls to the PhysicsActors can't directly call into the physics engine 693 // Calls to the PhysicsActors can't directly call into the physics engine
705 // because it might be busy. We delay changes to a known time. 694 // because it might be busy. We delay changes to a known time.
@@ -726,58 +715,35 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
726 TaintedObject(ident, callback); 715 TaintedObject(ident, callback);
727 } 716 }
728 717
718 private void TriggerPreStepEvent(float timeStep)
719 {
720 PreStepAction actions = BeforeStep;
721 if (actions != null)
722 actions(timeStep);
723
724 }
725
726 private void TriggerPostStepEvent(float timeStep)
727 {
728 PreStepAction actions = AfterStep;
729 if (actions != null)
730 actions(timeStep);
731
732 }
733
729 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues 734 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues
730 // a callback into itself to do the actual property change. That callback is called 735 // a callback into itself to do the actual property change. That callback is called
731 // here just before the physics engine is called to step the simulation. 736 // here just before the physics engine is called to step the simulation.
732 public void ProcessTaints() 737 public void ProcessTaints()
733 { 738 {
734 InTaintTime = true; // Only used for debugging so locking is not necessary.
735 ProcessRegularTaints(); 739 ProcessRegularTaints();
736 ProcessPostTaintTaints(); 740 ProcessPostTaintTaints();
737 InTaintTime = false;
738 } 741 }
739 742
740 private void ProcessRegularTaints() 743 private void ProcessRegularTaints()
741 { 744 {
742 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process 745 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process
743 { 746 {
744 /*
745 // Code to limit the number of taints processed per step. Meant to limit step time.
746 // Unsure if a good idea as code assumes that taints are done before the step.
747 int taintCount = m_taintsToProcessPerStep;
748 TaintCallbackEntry oneCallback = new TaintCallbackEntry();
749 while (_taintOperations.Count > 0 && taintCount-- > 0)
750 {
751 bool gotOne = false;
752 lock (_taintLock)
753 {
754 if (_taintOperations.Count > 0)
755 {
756 oneCallback = _taintOperations[0];
757 _taintOperations.RemoveAt(0);
758 gotOne = true;
759 }
760 }
761 if (gotOne)
762 {
763 try
764 {
765 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident);
766 oneCallback.callback();
767 }
768 catch (Exception e)
769 {
770 DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
771 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
772 }
773 }
774 }
775 if (_taintOperations.Count > 0)
776 {
777 DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count);
778 }
779 */
780
781 // swizzle a new list into the list location so we can process what's there 747 // swizzle a new list into the list location so we can process what's there
782 List<TaintCallbackEntry> oldList; 748 List<TaintCallbackEntry> oldList;
783 lock (_taintLock) 749 lock (_taintLock)
@@ -816,6 +782,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
816 return; 782 return;
817 } 783 }
818 784
785 // Taints that happen after the normal taint processing but before the simulation step.
819 private void ProcessPostTaintTaints() 786 private void ProcessPostTaintTaints()
820 { 787 {
821 if (_postTaintOperations.Count > 0) 788 if (_postTaintOperations.Count > 0)
@@ -843,45 +810,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
843 } 810 }
844 } 811 }
845 812
846 public void PostStepTaintObject(String ident, TaintCallback callback)
847 {
848 if (!m_initialized) return;
849
850 lock (_taintLock)
851 {
852 _postStepOperations.Add(new TaintCallbackEntry(ident, callback));
853 }
854
855 return;
856 }
857
858 private void ProcessPostStepTaints()
859 {
860 if (_postStepOperations.Count > 0)
861 {
862 List<TaintCallbackEntry> oldList;
863 lock (_taintLock)
864 {
865 oldList = _postStepOperations;
866 _postStepOperations = new List<TaintCallbackEntry>();
867 }
868
869 foreach (TaintCallbackEntry tcbe in oldList)
870 {
871 try
872 {
873 DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
874 tcbe.callback();
875 }
876 catch (Exception e)
877 {
878 m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
879 }
880 }
881 oldList.Clear();
882 }
883 }
884
885 // Only used for debugging. Does not change state of anything so locking is not necessary. 813 // Only used for debugging. Does not change state of anything so locking is not necessary.
886 public bool AssertInTaintTime(string whereFrom) 814 public bool AssertInTaintTime(string whereFrom)
887 { 815 {
@@ -889,540 +817,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
889 { 817 {
890 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); 818 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
891 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); 819 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
892 Util.PrintCallStack(); // Prints the stack into the DEBUG log file. 820 Util.PrintCallStack(DetailLog);
893 } 821 }
894 return InTaintTime; 822 return InTaintTime;
895 } 823 }
896 824
897 #endregion // Taints 825 #endregion // Taints
898 826
899 #region Vehicles
900
901 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
902 {
903 RemoveVehiclePrim(vehic);
904 if (newType != Vehicle.TYPE_NONE)
905 {
906 // make it so the scene will call us each tick to do vehicle things
907 AddVehiclePrim(vehic);
908 }
909 }
910
911 // Make so the scene will call this prim for vehicle actions each tick.
912 // Safe to call if prim is already in the vehicle list.
913 public void AddVehiclePrim(BSPrim vehicle)
914 {
915 lock (m_vehicles)
916 {
917 if (!m_vehicles.Contains(vehicle))
918 {
919 m_vehicles.Add(vehicle);
920 }
921 }
922 }
923
924 // Remove a prim from our list of vehicles.
925 // Safe to call if the prim is not in the vehicle list.
926 public void RemoveVehiclePrim(BSPrim vehicle)
927 {
928 lock (m_vehicles)
929 {
930 if (m_vehicles.Contains(vehicle))
931 {
932 m_vehicles.Remove(vehicle);
933 }
934 }
935 }
936
937 private void DoPreStepActions(float timeStep)
938 {
939 ProcessVehicles(timeStep);
940
941 PreStepAction actions = BeforeStep;
942 if (actions != null)
943 actions(timeStep);
944
945 }
946
947 // Some prims have extra vehicle actions
948 // Called at taint time!
949 private void ProcessVehicles(float timeStep)
950 {
951 foreach (BSPhysObject pobj in m_vehicles)
952 {
953 pobj.StepVehicle(timeStep);
954 }
955 }
956 #endregion Vehicles
957
958 #region INI and command line parameter processing 827 #region INI and command line parameter processing
959 828
960 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
961 delegate float ParamGet(BSScene scene);
962 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
963 delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
964
965 private struct ParameterDefn
966 {
967 public string name; // string name of the parameter
968 public string desc; // a short description of what the parameter means
969 public float defaultValue; // default value if not specified anywhere else
970 public ParamUser userParam; // get the value from the configuration file
971 public ParamGet getter; // return the current value stored for this parameter
972 public ParamSet setter; // set the current value for this parameter
973 public SetOnObject onObject; // set the value on an object in the physical domain
974 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
975 {
976 name = n;
977 desc = d;
978 defaultValue = v;
979 userParam = u;
980 getter = g;
981 setter = s;
982 onObject = null;
983 }
984 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
985 {
986 name = n;
987 desc = d;
988 defaultValue = v;
989 userParam = u;
990 getter = g;
991 setter = s;
992 onObject = o;
993 }
994 }
995
996 // List of all of the externally visible parameters.
997 // For each parameter, this table maps a text name to getter and setters.
998 // To add a new externally referencable/settable parameter, add the paramter storage
999 // location somewhere in the program and make an entry in this table with the
1000 // getters and setters.
1001 // It is easiest to find an existing definition and copy it.
1002 // Parameter values are floats. Booleans are converted to a floating value.
1003 //
1004 // A ParameterDefn() takes the following parameters:
1005 // -- the text name of the parameter. This is used for console input and ini file.
1006 // -- a short text description of the parameter. This shows up in the console listing.
1007 // -- a delegate for fetching the parameter from the ini file.
1008 // Should handle fetching the right type from the ini file and converting it.
1009 // -- a delegate for getting the value as a float
1010 // -- a delegate for setting the value from a float
1011 // -- an optional delegate to update the value in the world. Most often used to
1012 // push the new value to an in-world object.
1013 //
1014 // The single letter parameters for the delegates are:
1015 // s = BSScene
1016 // o = BSPhysObject
1017 // p = string parameter name
1018 // l = localID of referenced object
1019 // v = float value
1020 // cf = parameter configuration class (for fetching values from ini file)
1021 private ParameterDefn[] ParameterDefinitions =
1022 {
1023 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
1024 ConfigurationParameters.numericTrue,
1025 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
1026 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
1027 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
1028 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
1029 ConfigurationParameters.numericFalse,
1030 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
1031 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
1032 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
1033 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
1034 ConfigurationParameters.numericTrue,
1035 (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
1036 (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
1037 (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
1038
1039 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
1040 8f,
1041 (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
1042 (s) => { return s.MeshLOD; },
1043 (s,p,l,v) => { s.MeshLOD = v; } ),
1044 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
1045 16f,
1046 (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
1047 (s) => { return s.MeshMegaPrimLOD; },
1048 (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
1049 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
1050 10f,
1051 (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
1052 (s) => { return s.MeshMegaPrimThreshold; },
1053 (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
1054 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
1055 32f,
1056 (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
1057 (s) => { return s.SculptLOD; },
1058 (s,p,l,v) => { s.SculptLOD = v; } ),
1059
1060 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
1061 10f,
1062 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
1063 (s) => { return (float)s.m_maxSubSteps; },
1064 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
1065 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
1066 1f / 60f,
1067 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
1068 (s) => { return (float)s.m_fixedTimeStep; },
1069 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
1070 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
1071 2048f,
1072 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
1073 (s) => { return (float)s.m_maxCollisionsPerFrame; },
1074 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
1075 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
1076 8000f,
1077 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
1078 (s) => { return (float)s.m_maxUpdatesPerFrame; },
1079 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
1080 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
1081 500f,
1082 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
1083 (s) => { return (float)s.m_taintsToProcessPerStep; },
1084 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
1085 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
1086 10000.01f,
1087 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
1088 (s) => { return (float)s.MaximumObjectMass; },
1089 (s,p,l,v) => { s.MaximumObjectMass = v; } ),
1090
1091 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
1092 2200f,
1093 (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); },
1094 (s) => { return (float)s.PID_D; },
1095 (s,p,l,v) => { s.PID_D = v; } ),
1096 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
1097 900f,
1098 (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); },
1099 (s) => { return (float)s.PID_P; },
1100 (s,p,l,v) => { s.PID_P = v; } ),
1101
1102 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
1103 0.2f,
1104 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
1105 (s) => { return s.m_params[0].defaultFriction; },
1106 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
1107 new ParameterDefn("DefaultDensity", "Density for new objects" ,
1108 10.000006836f, // Aluminum g/cm3
1109 (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); },
1110 (s) => { return s.m_params[0].defaultDensity; },
1111 (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ),
1112 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
1113 0f,
1114 (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); },
1115 (s) => { return s.m_params[0].defaultRestitution; },
1116 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
1117 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
1118 0.04f,
1119 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
1120 (s) => { return s.m_params[0].collisionMargin; },
1121 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
1122 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
1123 -9.80665f,
1124 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
1125 (s) => { return s.m_params[0].gravity; },
1126 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); },
1127 (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
1128
1129
1130 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
1131 0f,
1132 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
1133 (s) => { return s.m_params[0].linearDamping; },
1134 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); },
1135 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, s.m_params[0].angularDamping); } ),
1136 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
1137 0f,
1138 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
1139 (s) => { return s.m_params[0].angularDamping; },
1140 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); },
1141 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, s.m_params[0].linearDamping, v); } ),
1142 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
1143 0.2f,
1144 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
1145 (s) => { return s.m_params[0].deactivationTime; },
1146 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); },
1147 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ),
1148 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
1149 0.8f,
1150 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
1151 (s) => { return s.m_params[0].linearSleepingThreshold; },
1152 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); },
1153 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1154 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
1155 1.0f,
1156 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
1157 (s) => { return s.m_params[0].angularSleepingThreshold; },
1158 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); },
1159 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1160 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1161 0f, // set to zero to disable
1162 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1163 (s) => { return s.m_params[0].ccdMotionThreshold; },
1164 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); },
1165 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ),
1166 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1167 0f,
1168 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1169 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1170 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); },
1171 (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ),
1172 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1173 0.1f,
1174 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1175 (s) => { return s.m_params[0].contactProcessingThreshold; },
1176 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
1177 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
1178
1179 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
1180 (float)BSTerrainPhys.TerrainImplementation.Mesh,
1181 (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); },
1182 (s) => { return s.m_params[0].terrainImplementation; },
1183 (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ),
1184 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1185 0.3f,
1186 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
1187 (s) => { return s.m_params[0].terrainFriction; },
1188 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
1189 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
1190 0.8f,
1191 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
1192 (s) => { return s.m_params[0].terrainHitFraction; },
1193 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ),
1194 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
1195 0f,
1196 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1197 (s) => { return s.m_params[0].terrainRestitution; },
1198 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
1199 new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
1200 0.04f,
1201 (s,cf,p,v) => { s.m_params[0].terrainCollisionMargin = cf.GetFloat(p, v); },
1202 (s) => { return s.m_params[0].terrainCollisionMargin; },
1203 (s,p,l,v) => { s.m_params[0].terrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
1204
1205 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1206 0.2f,
1207 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1208 (s) => { return s.m_params[0].avatarFriction; },
1209 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1210 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1211 10.0f,
1212 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1213 (s) => { return s.m_params[0].avatarStandingFriction; },
1214 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
1215 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1216 60f,
1217 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1218 (s) => { return s.m_params[0].avatarDensity; },
1219 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
1220 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1221 0f,
1222 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1223 (s) => { return s.m_params[0].avatarRestitution; },
1224 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1225 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
1226 0.6f,
1227 (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); },
1228 (s) => { return s.m_params[0].avatarCapsuleWidth; },
1229 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ),
1230 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
1231 0.45f,
1232 (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); },
1233 (s) => { return s.m_params[0].avatarCapsuleDepth; },
1234 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ),
1235 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1236 1.5f,
1237 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1238 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1239 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1240 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1241 0.1f,
1242 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1243 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1244 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1245
1246 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
1247 0.95f,
1248 (s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); },
1249 (s) => { return s.m_params[0].vehicleAngularDamping; },
1250 (s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ),
1251
1252 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1253 0f,
1254 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1255 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1256 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1257 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1258 0f,
1259 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1260 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1261 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
1262 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1263 ConfigurationParameters.numericFalse,
1264 (s,cf,p,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1265 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1266 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1267 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
1268 ConfigurationParameters.numericFalse,
1269 (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1270 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1271 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1272 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1273 ConfigurationParameters.numericTrue,
1274 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1275 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1276 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1277 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1278 ConfigurationParameters.numericTrue,
1279 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1280 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1281 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
1282 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
1283 ConfigurationParameters.numericFalse,
1284 (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1285 (s) => { return s.m_params[0].shouldEnableFrictionCaching; },
1286 (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ),
1287 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
1288 0f, // zero says use Bullet default
1289 (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); },
1290 (s) => { return s.m_params[0].numberOfSolverIterations; },
1291 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1292
1293 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
1294 (float)BSLinkset.LinksetImplementation.Compound,
1295 (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); },
1296 (s) => { return s.m_params[0].linksetImplementation; },
1297 (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ),
1298 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1299 ConfigurationParameters.numericFalse,
1300 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1301 (s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
1302 (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
1303 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
1304 ConfigurationParameters.numericTrue,
1305 (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1306 (s) => { return s.m_params[0].linkConstraintEnableTransMotor; },
1307 (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ),
1308 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
1309 5.0f,
1310 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
1311 (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; },
1312 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ),
1313 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
1314 0.1f,
1315 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1316 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1317 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1318 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1319 0.1f,
1320 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1321 (s) => { return s.m_params[0].linkConstraintCFM; },
1322 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
1323 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1324 0.1f,
1325 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1326 (s) => { return s.m_params[0].linkConstraintERP; },
1327 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1328 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1329 40,
1330 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1331 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1332 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1333
1334 new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
1335 0f,
1336 (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
1337 (s) => { return (float)s.m_params[0].physicsLoggingFrames; },
1338 (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ),
1339 };
1340
1341 // Convert a boolean to our numeric true and false values
1342 public float NumericBool(bool b)
1343 {
1344 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
1345 }
1346
1347 // Convert numeric true and false values to a boolean
1348 public bool BoolNumeric(float b)
1349 {
1350 return (b == ConfigurationParameters.numericTrue ? true : false);
1351 }
1352
1353 // Search through the parameter definitions and return the matching
1354 // ParameterDefn structure.
1355 // Case does not matter as names are compared after converting to lower case.
1356 // Returns 'false' if the parameter is not found.
1357 private bool TryGetParameter(string paramName, out ParameterDefn defn)
1358 {
1359 bool ret = false;
1360 ParameterDefn foundDefn = new ParameterDefn();
1361 string pName = paramName.ToLower();
1362
1363 foreach (ParameterDefn parm in ParameterDefinitions)
1364 {
1365 if (pName == parm.name.ToLower())
1366 {
1367 foundDefn = parm;
1368 ret = true;
1369 break;
1370 }
1371 }
1372 defn = foundDefn;
1373 return ret;
1374 }
1375
1376 // Pass through the settable parameters and set the default values
1377 private void SetParameterDefaultValues()
1378 {
1379 foreach (ParameterDefn parm in ParameterDefinitions)
1380 {
1381 parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
1382 }
1383 }
1384
1385 // Get user set values out of the ini file.
1386 private void SetParameterConfigurationValues(IConfig cfg)
1387 {
1388 foreach (ParameterDefn parm in ParameterDefinitions)
1389 {
1390 parm.userParam(this, cfg, parm.name, parm.defaultValue);
1391 }
1392 }
1393
1394 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1395
1396 // This creates an array in the correct format for returning the list of
1397 // parameters. This is used by the 'list' option of the 'physics' command.
1398 private void BuildParameterTable()
1399 {
1400 if (SettableParameters.Length < ParameterDefinitions.Length)
1401 {
1402 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1403 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1404 {
1405 ParameterDefn pd = ParameterDefinitions[ii];
1406 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
1407 }
1408
1409 // make the list in alphabetical order for estetic reasons
1410 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
1411 {
1412 return ppe1.name.CompareTo(ppe2.name);
1413 });
1414
1415 SettableParameters = entries.ToArray();
1416 }
1417 }
1418
1419
1420 #region IPhysicsParameters 829 #region IPhysicsParameters
1421 // Get the list of parameters this physics engine supports 830 // Get the list of parameters this physics engine supports
1422 public PhysParameterEntry[] GetParameterList() 831 public PhysParameterEntry[] GetParameterList()
1423 { 832 {
1424 BuildParameterTable(); 833 BSParam.BuildParameterTable();
1425 return SettableParameters; 834 return BSParam.SettableParameters;
1426 } 835 }
1427 836
1428 // Set parameter on a specific or all instances. 837 // Set parameter on a specific or all instances.
@@ -1434,8 +843,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1434 public bool SetPhysicsParameter(string parm, float val, uint localID) 843 public bool SetPhysicsParameter(string parm, float val, uint localID)
1435 { 844 {
1436 bool ret = false; 845 bool ret = false;
1437 ParameterDefn theParam; 846 BSParam.ParameterDefn theParam;
1438 if (TryGetParameter(parm, out theParam)) 847 if (BSParam.TryGetParameter(parm, out theParam))
1439 { 848 {
1440 theParam.setter(this, parm, localID, val); 849 theParam.setter(this, parm, localID, val);
1441 ret = true; 850 ret = true;
@@ -1447,19 +856,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1447 // If the local ID is APPLY_TO_NONE, just change the default value 856 // If the local ID is APPLY_TO_NONE, just change the default value
1448 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 857 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
1449 // If the localID is a specific object, apply the parameter change to only that object 858 // If the localID is a specific object, apply the parameter change to only that object
1450 private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) 859 internal delegate void AssignVal(float x);
860 internal void UpdateParameterObject(AssignVal setDefault, string parm, uint localID, float val)
1451 { 861 {
1452 List<uint> objectIDs = new List<uint>(); 862 List<uint> objectIDs = new List<uint>();
1453 switch (localID) 863 switch (localID)
1454 { 864 {
1455 case PhysParameterEntry.APPLY_TO_NONE: 865 case PhysParameterEntry.APPLY_TO_NONE:
1456 defaultLoc = val; // setting only the default value 866 setDefault(val); // setting only the default value
1457 // This will cause a call into the physical world if some operation is specified (SetOnObject). 867 // This will cause a call into the physical world if some operation is specified (SetOnObject).
1458 objectIDs.Add(TERRAIN_ID); 868 objectIDs.Add(TERRAIN_ID);
1459 TaintedUpdateParameter(parm, objectIDs, val); 869 TaintedUpdateParameter(parm, objectIDs, val);
1460 break; 870 break;
1461 case PhysParameterEntry.APPLY_TO_ALL: 871 case PhysParameterEntry.APPLY_TO_ALL:
1462 defaultLoc = val; // setting ALL also sets the default value 872 setDefault(val); // setting ALL also sets the default value
1463 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); 873 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
1464 TaintedUpdateParameter(parm, objectIDs, val); 874 TaintedUpdateParameter(parm, objectIDs, val);
1465 break; 875 break;
@@ -1478,8 +888,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1478 List<uint> xlIDs = lIDs; 888 List<uint> xlIDs = lIDs;
1479 string xparm = parm; 889 string xparm = parm;
1480 TaintedObject("BSScene.UpdateParameterSet", delegate() { 890 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1481 ParameterDefn thisParam; 891 BSParam.ParameterDefn thisParam;
1482 if (TryGetParameter(xparm, out thisParam)) 892 if (BSParam.TryGetParameter(xparm, out thisParam))
1483 { 893 {
1484 if (thisParam.onObject != null) 894 if (thisParam.onObject != null)
1485 { 895 {
@@ -1500,8 +910,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1500 { 910 {
1501 float val = 0f; 911 float val = 0f;
1502 bool ret = false; 912 bool ret = false;
1503 ParameterDefn theParam; 913 BSParam.ParameterDefn theParam;
1504 if (TryGetParameter(parm, out theParam)) 914 if (BSParam.TryGetParameter(parm, out theParam))
1505 { 915 {
1506 val = theParam.getter(this); 916 val = theParam.getter(this);
1507 ret = true; 917 ret = true;
@@ -1514,16 +924,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1514 924
1515 #endregion Runtime settable parameters 925 #endregion Runtime settable parameters
1516 926
1517 // Debugging routine for dumping detailed physical information for vehicle prims
1518 private void DumpVehicles()
1519 {
1520 foreach (BSPrim prim in m_vehicles)
1521 {
1522 BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr);
1523 BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr);
1524 }
1525 }
1526
1527 // Invoke the detailed logger and output something if it's enabled. 927 // Invoke the detailed logger and output something if it's enabled.
1528 public void DetailLog(string msg, params Object[] args) 928 public void DetailLog(string msg, params Object[] args)
1529 { 929 {