aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
diff options
context:
space:
mode:
authorRobert Adams2012-12-21 13:35:44 -0800
committerRobert Adams2012-12-21 13:35:44 -0800
commitae4d932e7f00e781db9c9cdd5c29efc51e2425fb (patch)
treeb03beb291cd35d4227fb82baf04ce14512b859eb /OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
parentBulletSim: small fix to avatar movement motor use which keeps avatar from fly... (diff)
downloadopensim-SC-ae4d932e7f00e781db9c9cdd5c29efc51e2425fb.zip
opensim-SC-ae4d932e7f00e781db9c9cdd5c29efc51e2425fb.tar.gz
opensim-SC-ae4d932e7f00e781db9c9cdd5c29efc51e2425fb.tar.bz2
opensim-SC-ae4d932e7f00e781db9c9cdd5c29efc51e2425fb.tar.xz
BulletSim: Move all the parameter variables, tables and get and fetch logic to a separate, static class for easier addition and to remove all that bulk from the BSScene class.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs549
1 files changed, 34 insertions, 515 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 2ca4912..492a255 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -77,12 +77,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
77 public ILog Logger { get { return m_log; } } 77 public ILog Logger { get { return m_log; } }
78 78
79 public IMesher mesher; 79 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; } 80 public uint WorldID { get; private set; }
87 public BulletSim World { get; private set; } 81 public BulletSim World { get; private set; }
88 82
@@ -90,21 +84,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
90 public BSConstraintCollection Constraints { get; private set; } 84 public BSConstraintCollection Constraints { get; private set; }
91 85
92 // Simulation parameters 86 // Simulation parameters
93 private int m_maxSubSteps; 87 internal int m_maxSubSteps;
94 private float m_fixedTimeStep; 88 internal float m_fixedTimeStep;
95 private long m_simulationStep = 0; 89 internal long m_simulationStep = 0;
96 public long SimulationStep { get { return m_simulationStep; } } 90 public long SimulationStep { get { return m_simulationStep; } }
97 private int m_taintsToProcessPerStep; 91 internal int m_taintsToProcessPerStep;
98
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 92
109 public delegate void PreStepAction(float timeStep); 93 public delegate void PreStepAction(float timeStep);
110 public event PreStepAction BeforeStep; 94 public event PreStepAction BeforeStep;
@@ -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);
@@ -889,7 +864,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
889 { 864 {
890 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); 865 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); 866 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. 867 Util.PrintCallStack(DetailLog); // Prints the stack into the DEBUG log file.
893 } 868 }
894 return InTaintTime; 869 return InTaintTime;
895 } 870 }
@@ -936,12 +911,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
936 911
937 private void DoPreStepActions(float timeStep) 912 private void DoPreStepActions(float timeStep)
938 { 913 {
914 InTaintTime = true; // Only used for debugging so locking is not necessary.
939 ProcessVehicles(timeStep); 915 ProcessVehicles(timeStep);
940 916
941 PreStepAction actions = BeforeStep; 917 PreStepAction actions = BeforeStep;
942 if (actions != null) 918 if (actions != null)
943 actions(timeStep); 919 actions(timeStep);
944 920
921 InTaintTime = false;
922
945 } 923 }
946 924
947 // Some prims have extra vehicle actions 925 // Some prims have extra vehicle actions
@@ -957,472 +935,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
957 935
958 #region INI and command line parameter processing 936 #region INI and command line parameter processing
959 937
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 938 #region IPhysicsParameters
1421 // Get the list of parameters this physics engine supports 939 // Get the list of parameters this physics engine supports
1422 public PhysParameterEntry[] GetParameterList() 940 public PhysParameterEntry[] GetParameterList()
1423 { 941 {
1424 BuildParameterTable(); 942 BSParam.BuildParameterTable();
1425 return SettableParameters; 943 return BSParam.SettableParameters;
1426 } 944 }
1427 945
1428 // Set parameter on a specific or all instances. 946 // Set parameter on a specific or all instances.
@@ -1434,8 +952,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1434 public bool SetPhysicsParameter(string parm, float val, uint localID) 952 public bool SetPhysicsParameter(string parm, float val, uint localID)
1435 { 953 {
1436 bool ret = false; 954 bool ret = false;
1437 ParameterDefn theParam; 955 BSParam.ParameterDefn theParam;
1438 if (TryGetParameter(parm, out theParam)) 956 if (BSParam.TryGetParameter(parm, out theParam))
1439 { 957 {
1440 theParam.setter(this, parm, localID, val); 958 theParam.setter(this, parm, localID, val);
1441 ret = true; 959 ret = true;
@@ -1447,19 +965,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1447 // If the local ID is APPLY_TO_NONE, just change the default value 965 // 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 966 // 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 967 // 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) 968 internal delegate void AssignVal(float x);
969 internal void UpdateParameterObject(AssignVal setDefault, string parm, uint localID, float val)
1451 { 970 {
1452 List<uint> objectIDs = new List<uint>(); 971 List<uint> objectIDs = new List<uint>();
1453 switch (localID) 972 switch (localID)
1454 { 973 {
1455 case PhysParameterEntry.APPLY_TO_NONE: 974 case PhysParameterEntry.APPLY_TO_NONE:
1456 defaultLoc = val; // setting only the default value 975 setDefault(val); // setting only the default value
1457 // This will cause a call into the physical world if some operation is specified (SetOnObject). 976 // This will cause a call into the physical world if some operation is specified (SetOnObject).
1458 objectIDs.Add(TERRAIN_ID); 977 objectIDs.Add(TERRAIN_ID);
1459 TaintedUpdateParameter(parm, objectIDs, val); 978 TaintedUpdateParameter(parm, objectIDs, val);
1460 break; 979 break;
1461 case PhysParameterEntry.APPLY_TO_ALL: 980 case PhysParameterEntry.APPLY_TO_ALL:
1462 defaultLoc = val; // setting ALL also sets the default value 981 setDefault(val); // setting ALL also sets the default value
1463 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); 982 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
1464 TaintedUpdateParameter(parm, objectIDs, val); 983 TaintedUpdateParameter(parm, objectIDs, val);
1465 break; 984 break;
@@ -1478,8 +997,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1478 List<uint> xlIDs = lIDs; 997 List<uint> xlIDs = lIDs;
1479 string xparm = parm; 998 string xparm = parm;
1480 TaintedObject("BSScene.UpdateParameterSet", delegate() { 999 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1481 ParameterDefn thisParam; 1000 BSParam.ParameterDefn thisParam;
1482 if (TryGetParameter(xparm, out thisParam)) 1001 if (BSParam.TryGetParameter(xparm, out thisParam))
1483 { 1002 {
1484 if (thisParam.onObject != null) 1003 if (thisParam.onObject != null)
1485 { 1004 {
@@ -1500,8 +1019,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1500 { 1019 {
1501 float val = 0f; 1020 float val = 0f;
1502 bool ret = false; 1021 bool ret = false;
1503 ParameterDefn theParam; 1022 BSParam.ParameterDefn theParam;
1504 if (TryGetParameter(parm, out theParam)) 1023 if (BSParam.TryGetParameter(parm, out theParam))
1505 { 1024 {
1506 val = theParam.getter(this); 1025 val = theParam.getter(this);
1507 ret = true; 1026 ret = true;