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