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.cs652
1 files changed, 403 insertions, 249 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 7cc3fe3..c6d622b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -73,7 +73,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
75 75
76 private void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } 76 public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
77 77
78 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
79 79
@@ -87,6 +87,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
87 private uint m_worldID; 87 private uint m_worldID;
88 public uint WorldID { get { return m_worldID; } } 88 public uint WorldID { get { return m_worldID; } }
89 89
90 // let my minuions use my logger
91 public ILog Logger { get { return m_log; } }
92
90 private bool m_initialized = false; 93 private bool m_initialized = false;
91 94
92 private int m_detailedStatsStep = 0; 95 private int m_detailedStatsStep = 0;
@@ -103,6 +106,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
103 get { return m_sculptLOD; } 106 get { return m_sculptLOD; }
104 } 107 }
105 108
109 private BulletSim m_worldSim;
110 public BulletSim World
111 {
112 get { return m_worldSim; }
113 }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
119
106 private int m_maxSubSteps; 120 private int m_maxSubSteps;
107 private float m_fixedTimeStep; 121 private float m_fixedTimeStep;
108 private long m_simulationStep = 0; 122 private long m_simulationStep = 0;
@@ -229,6 +243,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
229 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 243 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
230 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 244 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
231 245
246 // Initialization to support the transition to a new API which puts most of the logic
247 // into the C# code so it is easier to modify and add to.
248 m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID));
249 m_constraintCollection = new BSConstraintCollection(World);
250
232 m_initialized = true; 251 m_initialized = true;
233 } 252 }
234 253
@@ -237,116 +256,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
237 private void GetInitialParameterValues(IConfigSource config) 256 private void GetInitialParameterValues(IConfigSource config)
238 { 257 {
239 ConfigurationParameters parms = new ConfigurationParameters(); 258 ConfigurationParameters parms = new ConfigurationParameters();
259 m_params[0] = parms;
240 260
241 _meshSculptedPrim = true; // mesh sculpted prims 261 SetParameterDefaultValues();
242 _forceSimplePrimMeshing = false; // use complex meshing if called for
243
244 m_meshLOD = 8f;
245 m_sculptLOD = 32f;
246
247 shouldDebugLog = false;
248 m_detailedStatsStep = 0; // disabled
249
250 m_maxSubSteps = 10;
251 m_fixedTimeStep = 1f / 60f;
252 m_maxCollisionsPerFrame = 2048;
253 m_maxUpdatesPerFrame = 2048;
254 m_maximumObjectMass = 10000.01f;
255
256 PID_D = 2200f;
257 PID_P = 900f;
258
259 parms.defaultFriction = 0.5f;
260 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
261 parms.defaultRestitution = 0f;
262 parms.collisionMargin = 0.0f;
263 parms.gravity = -9.80665f;
264
265 parms.linearDamping = 0.0f;
266 parms.angularDamping = 0.0f;
267 parms.deactivationTime = 0.2f;
268 parms.linearSleepingThreshold = 0.8f;
269 parms.angularSleepingThreshold = 1.0f;
270 parms.ccdMotionThreshold = 0.0f; // set to zero to disable
271 parms.ccdSweptSphereRadius = 0.0f;
272 parms.contactProcessingThreshold = 0.1f;
273
274 parms.terrainFriction = 0.5f;
275 parms.terrainHitFraction = 0.8f;
276 parms.terrainRestitution = 0f;
277 parms.avatarFriction = 0.5f;
278 parms.avatarRestitution = 0.0f;
279 parms.avatarDensity = 60f;
280 parms.avatarCapsuleRadius = 0.37f;
281 parms.avatarCapsuleHeight = 1.5f; // 2.140599f
282 parms.avatarContactProcessingThreshold = 0.1f;
283
284 parms.maxPersistantManifoldPoolSize = 0f;
285 parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue;
286 parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse;
287 parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse;
288 parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse;
289 parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse;
290 parms.numberOfSolverIterations = 0f; // means use default
291 262
292 if (config != null) 263 if (config != null)
293 { 264 {
294 // If there are specifications in the ini file, use those values 265 // If there are specifications in the ini file, use those values
295 // WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO UPDATE OpenSimDefaults.ini
296 // ALSO REMEMBER TO UPDATE THE RUNTIME SETTING OF THE PARAMETERS.
297 IConfig pConfig = config.Configs["BulletSim"]; 266 IConfig pConfig = config.Configs["BulletSim"];
298 if (pConfig != null) 267 if (pConfig != null)
299 { 268 {
300 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); 269 SetParameterConfigurationValues(pConfig);
301 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing);
302
303 shouldDebugLog = pConfig.GetBoolean("ShouldDebugLog", shouldDebugLog);
304 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep);
305
306 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD);
307 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD);
308
309 m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps);
310 m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep);
311 m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame);
312 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
313 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
314
315 PID_D = pConfig.GetFloat("PIDDerivative", PID_D);
316 PID_P = pConfig.GetFloat("PIDProportional", PID_P);
317
318 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
319 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
320 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
321 parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin);
322 parms.gravity = pConfig.GetFloat("Gravity", parms.gravity);
323
324 parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping);
325 parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping);
326 parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime);
327 parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold);
328 parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold);
329 parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold);
330 parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius);
331 parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold);
332
333 parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction);
334 parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction);
335 parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution);
336 parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction);
337 parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution);
338 parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity);
339 parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius);
340 parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight);
341 parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold);
342
343 parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize);
344 parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation);
345 parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs);
346 parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder);
347 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
348 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
349 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
350 270
351 // Very detailed logging for physics debugging 271 // Very detailed logging for physics debugging
352 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 272 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@@ -357,7 +277,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
357 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 277 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
358 } 278 }
359 } 279 }
360 m_params[0] = parms;
361 } 280 }
362 281
363 // A helper function that handles a true/false parameter and returns the proper float number encoding 282 // A helper function that handles a true/false parameter and returns the proper float number encoding
@@ -634,6 +553,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
634 // make sure no stepping happens while we're deleting stuff 553 // make sure no stepping happens while we're deleting stuff
635 m_initialized = false; 554 m_initialized = false;
636 555
556 if (m_constraintCollection != null)
557 {
558 m_constraintCollection.Dispose();
559 m_constraintCollection = null;
560 }
561
637 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 562 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
638 { 563 {
639 kvp.Value.Destroy(); 564 kvp.Value.Destroy();
@@ -776,10 +701,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
776 } 701 }
777 702
778 // The calls to the PhysicsActors can't directly call into the physics engine 703 // The calls to the PhysicsActors can't directly call into the physics engine
779 // because it might be busy. We we delay changes to a known time. 704 // because it might be busy. We delay changes to a known time.
780 // We rely on C#'s closure to save and restore the context for the delegate. 705 // We rely on C#'s closure to save and restore the context for the delegate.
781 public void TaintedObject(TaintCallback callback) 706 public void TaintedObject(TaintCallback callback)
782 { 707 {
708 if (!m_initialized) return;
709
783 lock (_taintLock) 710 lock (_taintLock)
784 _taintedObjects.Add(callback); 711 _taintedObjects.Add(callback);
785 return; 712 return;
@@ -853,61 +780,371 @@ public class BSScene : PhysicsScene, IPhysicsParameters
853 } 780 }
854 #endregion Vehicles 781 #endregion Vehicles
855 782
856 #region Runtime settable parameters 783 #region Parameters
857 public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[] 784
785 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
786 delegate float ParamGet(BSScene scene);
787 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
788
789 private struct ParameterDefn
790 {
791 public string name;
792 public string desc;
793 public float defaultValue;
794 public ParamUser userParam;
795 public ParamGet getter;
796 public ParamSet setter;
797 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
798 {
799 name = n;
800 desc = d;
801 defaultValue = v;
802 userParam = u;
803 getter = g;
804 setter = s;
805 }
806 }
807
808 // List of all of the externally visible parameters.
809 // For each parameter, this table maps a text name to getter and setters.
810 // A ParameterDefn() takes the following parameters:
811 // -- the text name of the parameter. This is used for console input and ini file.
812 // -- a short text description of the parameter. This shows up in the console listing.
813 // -- a delegate for fetching the parameter from the ini file.
814 // Should handle fetching the right type from the ini file and converting it.
815 // -- a delegate for getting the value as a float
816 // -- a delegate for setting the value from a float
817 //
818 // To add a new variable, it is best to find an existing definition and copy it.
819 private ParameterDefn[] ParameterDefinitions =
858 { 820 {
859 new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"), 821 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
860 new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"), 822 ConfigurationParameters.numericTrue,
861 new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), 823 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
862 new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), 824 (s) => { return s.NumericBool(s._meshSculptedPrim); },
863 new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), 825 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ),
864 new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), 826 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
865 827 ConfigurationParameters.numericFalse,
866 new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), 828 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
867 new PhysParameterEntry("DefaultDensity", "Density for new objects" ), 829 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
868 new PhysParameterEntry("DefaultRestitution", "Bouncyness of an object" ), 830 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
869 // new PhysParameterEntry("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!!)" ), 831
870 new PhysParameterEntry("Gravity", "Vertical force of gravity (negative means down)" ), 832 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
871 833 8f,
872 new PhysParameterEntry("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)" ), 834 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); },
873 new PhysParameterEntry("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)" ), 835 (s) => { return (float)s.m_meshLOD; },
874 new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ), 836 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
875 new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ), 837 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
876 new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), 838 32,
877 new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ), 839 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
878 new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ), 840 (s) => { return (float)s.m_sculptLOD; },
879 new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), 841 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
880 // Can only change the following at initialization time. Change the INI file and reboot. 842
881 new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"), 843 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
882 new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"), 844 10f,
883 new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"), 845 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
884 new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"), 846 (s) => { return (float)s.m_maxSubSteps; },
885 new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"), 847 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
886 new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"), 848 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
887 new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"), 849 1f / 60f,
888 850 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
889 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 851 (s) => { return (float)s.m_fixedTimeStep; },
890 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 852 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
891 853 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
892 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 854 2048f,
893 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 855 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
894 856 (s) => { return (float)s.m_maxCollisionsPerFrame; },
895 new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), 857 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
896 new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), 858 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
897 new PhysParameterEntry("TerrainRestitution", "Bouncyness" ), 859 8000f,
898 new PhysParameterEntry("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation." ), 860 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
899 new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ), 861 (s) => { return (float)s.m_maxUpdatesPerFrame; },
900 new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ), 862 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
901 new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ), 863 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
902 new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ), 864 10000.01f,
903 new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions") 865 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
866 (s) => { return (float)s.m_maximumObjectMass; },
867 (s,p,l,v) => { s.m_maximumObjectMass = v; } ),
868
869 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
870 2200f,
871 (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); },
872 (s) => { return (float)s.PID_D; },
873 (s,p,l,v) => { s.PID_D = v; } ),
874 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
875 900f,
876 (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); },
877 (s) => { return (float)s.PID_P; },
878 (s,p,l,v) => { s.PID_P = v; } ),
879
880 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
881 0.5f,
882 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
883 (s) => { return s.m_params[0].defaultFriction; },
884 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
885 new ParameterDefn("DefaultDensity", "Density for new objects" ,
886 10.000006836f, // Aluminum g/cm3
887 (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); },
888 (s) => { return s.m_params[0].defaultDensity; },
889 (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ),
890 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
891 0f,
892 (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); },
893 (s) => { return s.m_params[0].defaultRestitution; },
894 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
895 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
896 0f,
897 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
898 (s) => { return s.m_params[0].collisionMargin; },
899 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
900 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
901 -9.80665f,
902 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
903 (s) => { return s.m_params[0].gravity; },
904 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ),
905
906
907 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
908 0f,
909 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
910 (s) => { return s.m_params[0].linearDamping; },
911 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
912 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
913 0f,
914 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
915 (s) => { return s.m_params[0].angularDamping; },
916 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
917 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
918 0.2f,
919 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
920 (s) => { return s.m_params[0].deactivationTime; },
921 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
922 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
923 0.8f,
924 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
925 (s) => { return s.m_params[0].linearSleepingThreshold; },
926 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
927 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
928 1.0f,
929 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
930 (s) => { return s.m_params[0].angularSleepingThreshold; },
931 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
932 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
933 0f, // set to zero to disable
934 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
935 (s) => { return s.m_params[0].ccdMotionThreshold; },
936 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
937 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
938 0f,
939 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
940 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
941 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
942 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
943 0.1f,
944 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
945 (s) => { return s.m_params[0].contactProcessingThreshold; },
946 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
947
948 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
949 0.5f,
950 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
951 (s) => { return s.m_params[0].terrainFriction; },
952 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ),
953 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
954 0.8f,
955 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
956 (s) => { return s.m_params[0].terrainHitFraction; },
957 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ),
958 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
959 0f,
960 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
961 (s) => { return s.m_params[0].terrainRestitution; },
962 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
963 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
964 0.5f,
965 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
966 (s) => { return s.m_params[0].avatarFriction; },
967 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
968 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
969 60f,
970 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
971 (s) => { return s.m_params[0].avatarDensity; },
972 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
973 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
974 0f,
975 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
976 (s) => { return s.m_params[0].avatarRestitution; },
977 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
978 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
979 0.37f,
980 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
981 (s) => { return s.m_params[0].avatarCapsuleRadius; },
982 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
983 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
984 1.5f,
985 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
986 (s) => { return s.m_params[0].avatarCapsuleHeight; },
987 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
988 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
989 0.1f,
990 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
991 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
992 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
993
994
995 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)",
996 0f, // zero to disable
997 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
999 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1000 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1001 ConfigurationParameters.numericTrue,
1002 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1003 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1004 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1005 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
1006 ConfigurationParameters.numericFalse,
1007 (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1008 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1009 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1010 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1011 ConfigurationParameters.numericFalse,
1012 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1013 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1014 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1015 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1016 ConfigurationParameters.numericFalse,
1017 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1018 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1019 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
1020 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
1021 ConfigurationParameters.numericFalse,
1022 (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1023 (s) => { return s.m_params[0].shouldEnableFrictionCaching; },
1024 (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ),
1025 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
1026 0f, // zero says use Bullet default
1027 (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); },
1028 (s) => { return s.m_params[0].numberOfSolverIterations; },
1029 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1030
1031 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1032 ConfigurationParameters.numericFalse,
1033 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1034 (s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
1035 (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
1036 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
1037 ConfigurationParameters.numericTrue,
1038 (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1039 (s) => { return s.m_params[0].linkConstraintEnableTransMotor; },
1040 (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ),
1041 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
1042 5.0f,
1043 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
1044 (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; },
1045 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ),
1046 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
1047 0.1f,
1048 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1050 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1051
1052 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1053 0f,
1054 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
1055 (s) => { return (float)s.m_detailedStatsStep; },
1056 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1057 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1058 ConfigurationParameters.numericFalse,
1059 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1060 (s) => { return s.NumericBool(s.shouldDebugLog); },
1061 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ),
904 1062
905 }; 1063 };
906 1064
1065 // Convert a boolean to our numeric true and false values
1066 public float NumericBool(bool b)
1067 {
1068 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
1069 }
1070
1071 // Convert numeric true and false values to a boolean
1072 public bool BoolNumeric(float b)
1073 {
1074 return (b == ConfigurationParameters.numericTrue ? true : false);
1075 }
1076
1077 // Search through the parameter definitions and return the matching
1078 // ParameterDefn structure.
1079 // Case does not matter as names are compared after converting to lower case.
1080 // Returns 'false' if the parameter is not found.
1081 private bool TryGetParameter(string paramName, out ParameterDefn defn)
1082 {
1083 bool ret = false;
1084 ParameterDefn foundDefn = new ParameterDefn();
1085 string pName = paramName.ToLower();
1086
1087 foreach (ParameterDefn parm in ParameterDefinitions)
1088 {
1089 if (pName == parm.name.ToLower())
1090 {
1091 foundDefn = parm;
1092 ret = true;
1093 break;
1094 }
1095 }
1096 defn = foundDefn;
1097 return ret;
1098 }
1099
1100 // Pass through the settable parameters and set the default values
1101 private void SetParameterDefaultValues()
1102 {
1103 foreach (ParameterDefn parm in ParameterDefinitions)
1104 {
1105 parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
1106 }
1107 }
1108
1109 // Get user set values out of the ini file.
1110 private void SetParameterConfigurationValues(IConfig cfg)
1111 {
1112 foreach (ParameterDefn parm in ParameterDefinitions)
1113 {
1114 parm.userParam(this, cfg, parm.name, parm.defaultValue);
1115 }
1116 }
1117
1118 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1119
1120 private void BuildParameterTable()
1121 {
1122 if (SettableParameters.Length < ParameterDefinitions.Length)
1123 {
1124
1125 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1126 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1127 {
1128 ParameterDefn pd = ParameterDefinitions[ii];
1129 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
1130 }
1131
1132 // make the list in alphabetical order for estetic reasons
1133 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
1134 {
1135 return ppe1.name.CompareTo(ppe2.name);
1136 });
1137
1138 SettableParameters = entries.ToArray();
1139 }
1140 }
1141
1142
907 #region IPhysicsParameters 1143 #region IPhysicsParameters
908 // Get the list of parameters this physics engine supports 1144 // Get the list of parameters this physics engine supports
909 public PhysParameterEntry[] GetParameterList() 1145 public PhysParameterEntry[] GetParameterList()
910 { 1146 {
1147 BuildParameterTable();
911 return SettableParameters; 1148 return SettableParameters;
912 } 1149 }
913 1150
@@ -919,63 +1156,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
919 // value activated ('terrainFriction' for instance). 1156 // value activated ('terrainFriction' for instance).
920 public bool SetPhysicsParameter(string parm, float val, uint localID) 1157 public bool SetPhysicsParameter(string parm, float val, uint localID)
921 { 1158 {
922 bool ret = true; 1159 bool ret = false;
923 string lparm = parm.ToLower(); 1160 ParameterDefn theParam;
924 switch (lparm) 1161 if (TryGetParameter(parm, out theParam))
925 { 1162 {
926 case "detailedstats": m_detailedStatsStep = (int)val; break; 1163 theParam.setter(this, parm, localID, val);
927 1164 ret = true;
928 case "meshlod": m_meshLOD = (int)val; break;
929 case "sculptlod": m_sculptLOD = (int)val; break;
930 case "maxsubstep": m_maxSubSteps = (int)val; break;
931 case "fixedtimestep": m_fixedTimeStep = val; break;
932 case "maxobjectmass": m_maximumObjectMass = val; break;
933
934 case "defaultfriction": m_params[0].defaultFriction = val; break;
935 case "defaultdensity": m_params[0].defaultDensity = val; break;
936 case "defaultrestitution": m_params[0].defaultRestitution = val; break;
937 case "collisionmargin": m_params[0].collisionMargin = val; break;
938 case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break;
939
940 case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break;
941 case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
942 case "deactivationtime": UpdateParameterPrims(ref m_params[0].deactivationTime, lparm, localID, val); break;
943 case "linearsleepingthreshold": UpdateParameterPrims(ref m_params[0].linearSleepingThreshold, lparm, localID, val); break;
944 case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
945 case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break;
946 case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break;
947 case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break;
948 // the following are used only at initialization time so setting them makes no sense
949 // case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break;
950 // case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break;
951 // case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break;
952 // case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break;
953 // case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break;
954 // case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break;
955 // case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break;
956
957 case "friction": TaintedUpdateParameter(lparm, localID, val); break;
958 case "restitution": TaintedUpdateParameter(lparm, localID, val); break;
959
960 // set a terrain physical feature and cause terrain to be recalculated
961 case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break;
962 case "terrainhitfraction": m_params[0].terrainHitFraction = val; TaintedUpdateParameter("terrain", 0, val); break;
963 case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break;
964 // set an avatar physical feature and cause avatar(s) to be recalculated
965 case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break;
966 case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break;
967 case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break;
968 case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break;
969 case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break;
970 case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break;
971
972 default: ret = false; break;
973 } 1165 }
974 return ret; 1166 return ret;
975 } 1167 }
976 1168
977 // check to see if we are updating a parameter for a particular or all of the prims 1169 // check to see if we are updating a parameter for a particular or all of the prims
978 private void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) 1170 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
979 { 1171 {
980 List<uint> operateOn; 1172 List<uint> operateOn;
981 lock (m_prims) operateOn = new List<uint>(m_prims.Keys); 1173 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
@@ -983,7 +1175,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
983 } 1175 }
984 1176
985 // check to see if we are updating a parameter for a particular or all of the avatars 1177 // check to see if we are updating a parameter for a particular or all of the avatars
986 private void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) 1178 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
987 { 1179 {
988 List<uint> operateOn; 1180 List<uint> operateOn;
989 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); 1181 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
@@ -994,7 +1186,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
994 // If the local ID is APPLY_TO_NONE, just change the default value 1186 // If the local ID is APPLY_TO_NONE, just change the default value
995 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1187 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
996 // If the localID is a specific object, apply the parameter change to only that object 1188 // If the localID is a specific object, apply the parameter change to only that object
997 private void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) 1189 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
998 { 1190 {
999 switch (localID) 1191 switch (localID)
1000 { 1192 {
@@ -1021,7 +1213,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1021 } 1213 }
1022 1214
1023 // schedule the actual updating of the paramter to when the phys engine is not busy 1215 // schedule the actual updating of the paramter to when the phys engine is not busy
1024 private void TaintedUpdateParameter(string parm, uint localID, float val) 1216 protected void TaintedUpdateParameter(string parm, uint localID, float val)
1025 { 1217 {
1026 uint xlocalID = localID; 1218 uint xlocalID = localID;
1027 string xparm = parm.ToLower(); 1219 string xparm = parm.ToLower();
@@ -1036,50 +1228,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1036 public bool GetPhysicsParameter(string parm, out float value) 1228 public bool GetPhysicsParameter(string parm, out float value)
1037 { 1229 {
1038 float val = 0f; 1230 float val = 0f;
1039 bool ret = true; 1231 bool ret = false;
1040 switch (parm.ToLower()) 1232 ParameterDefn theParam;
1233 if (TryGetParameter(parm, out theParam))
1041 { 1234 {
1042 case "detailedstats": val = (int)m_detailedStatsStep; break; 1235 val = theParam.getter(this);
1043 case "meshlod": val = (float)m_meshLOD; break; 1236 ret = true;
1044 case "sculptlod": val = (float)m_sculptLOD; break;
1045 case "maxsubstep": val = (float)m_maxSubSteps; break;
1046 case "fixedtimestep": val = m_fixedTimeStep; break;
1047 case "maxobjectmass": val = m_maximumObjectMass; break;
1048
1049 case "defaultfriction": val = m_params[0].defaultFriction; break;
1050 case "defaultdensity": val = m_params[0].defaultDensity; break;
1051 case "defaultrestitution": val = m_params[0].defaultRestitution; break;
1052 case "collisionmargin": val = m_params[0].collisionMargin; break;
1053 case "gravity": val = m_params[0].gravity; break;
1054
1055 case "lineardamping": val = m_params[0].linearDamping; break;
1056 case "angulardamping": val = m_params[0].angularDamping; break;
1057 case "deactivationtime": val = m_params[0].deactivationTime; break;
1058 case "linearsleepingthreshold": val = m_params[0].linearSleepingThreshold; break;
1059 case "angularsleepingthreshold": val = m_params[0].angularDamping; break;
1060 case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break;
1061 case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break;
1062 case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break;
1063 case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break;
1064 case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break;
1065 case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break;
1066 case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break;
1067 case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break;
1068 case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break;
1069 case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break;
1070
1071 case "terrainfriction": val = m_params[0].terrainFriction; break;
1072 case "terrainhitfraction": val = m_params[0].terrainHitFraction; break;
1073 case "terrainrestitution": val = m_params[0].terrainRestitution; break;
1074
1075 case "avatarfriction": val = m_params[0].avatarFriction; break;
1076 case "avatardensity": val = m_params[0].avatarDensity; break;
1077 case "avatarrestitution": val = m_params[0].avatarRestitution; break;
1078 case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break;
1079 case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break;
1080 case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break;
1081 default: ret = false; break;
1082
1083 } 1237 }
1084 value = val; 1238 value = val;
1085 return ret; 1239 return ret;