clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 using System;
28 using System.Collections.Generic;
29 using System.Reflection;
30 using System.Text;
31  
32 using OpenSim.Region.Physics.Manager;
33  
34 using OpenMetaverse;
35 using Nini.Config;
36  
37 namespace OpenSim.Region.Physics.BulletSPlugin
38 {
39 public static class BSParam
40 {
41 private static string LogHeader = "[BULLETSIM PARAMETERS]";
42  
43 // Tuning notes:
44 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575
45 // Contact points can be added even if the distance is positive. The constraint solver can deal with
46 // contacts with positive distances as well as negative (penetration). Contact points are discarded
47 // if the distance exceeds a certain threshold.
48 // Bullet has a contact processing threshold and a contact breaking threshold.
49 // If the distance is larger than the contact breaking threshold, it will be removed after one frame.
50 // If the distance is larger than the contact processing threshold, the constraint solver will ignore it.
51  
52 // This is separate/independent from the collision margin. The collision margin increases the object a bit
53 // to improve collision detection performance and accuracy.
54 // ===================
55 // From:
56  
57 public static bool UseSeparatePhysicsThread { get; private set; }
58 public static float PhysicsTimeStep { get; private set; }
59  
60 // Level of Detail values kept as float because that's what the Meshmerizer wants
61 public static float MeshLOD { get; private set; }
62 public static float MeshCircularLOD { get; private set; }
63 public static float MeshMegaPrimLOD { get; private set; }
64 public static float MeshMegaPrimThreshold { get; private set; }
65 public static float SculptLOD { get; private set; }
66  
67 public static int CrossingFailuresBeforeOutOfBounds { get; private set; }
68 public static float UpdateVelocityChangeThreshold { get; private set; }
69  
70 public static float MinimumObjectMass { get; private set; }
71 public static float MaximumObjectMass { get; private set; }
72 public static float MaxLinearVelocity { get; private set; }
73 public static float MaxLinearVelocitySquared { get; private set; }
74 public static float MaxAngularVelocity { get; private set; }
75 public static float MaxAngularVelocitySquared { get; private set; }
76 public static float MaxAddForceMagnitude { get; private set; }
77 public static float MaxAddForceMagnitudeSquared { get; private set; }
78 public static float DensityScaleFactor { get; private set; }
79  
80 public static float LinearDamping { get; private set; }
81 public static float AngularDamping { get; private set; }
82 public static float DeactivationTime { get; private set; }
83 public static float LinearSleepingThreshold { get; private set; }
84 public static float AngularSleepingThreshold { get; private set; }
85 public static float CcdMotionThreshold { get; private set; }
86 public static float CcdSweptSphereRadius { get; private set; }
87 public static float ContactProcessingThreshold { get; private set; }
88  
89 public static bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
90 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
91 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
92 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
93 public static bool ShouldUseBulletHACD { get; set; }
94 public static bool ShouldUseSingleConvexHullForPrims { get; set; }
95 public static bool ShouldUseGImpactShapeForPrims { get; set; }
96 public static bool ShouldUseAssetHulls { get; set; }
97  
98 public static float TerrainImplementation { get; set; }
99 public static int TerrainMeshMagnification { get; private set; }
100 public static float TerrainFriction { get; private set; }
101 public static float TerrainHitFraction { get; private set; }
102 public static float TerrainRestitution { get; private set; }
103 public static float TerrainContactProcessingThreshold { get; private set; }
104 public static float TerrainCollisionMargin { get; private set; }
105  
106 public static float DefaultFriction { get; private set; }
107 public static float DefaultDensity { get; private set; }
108 public static float DefaultRestitution { get; private set; }
109 public static float CollisionMargin { get; private set; }
110 public static float Gravity { get; private set; }
111  
112 // Physics Engine operation
113 public static float MaxPersistantManifoldPoolSize { get; private set; }
114 public static float MaxCollisionAlgorithmPoolSize { get; private set; }
115 public static bool ShouldDisableContactPoolDynamicAllocation { get; private set; }
116 public static bool ShouldForceUpdateAllAabbs { get; private set; }
117 public static bool ShouldRandomizeSolverOrder { get; private set; }
118 public static bool ShouldSplitSimulationIslands { get; private set; }
119 public static bool ShouldEnableFrictionCaching { get; private set; }
120 public static float NumberOfSolverIterations { get; private set; }
121 public static bool UseSingleSidedMeshes { get; private set; }
122 public static float GlobalContactBreakingThreshold { get; private set; }
123  
124 // Avatar parameters
125 public static float AvatarFriction { get; private set; }
126 public static float AvatarStandingFriction { get; private set; }
127 public static float AvatarAlwaysRunFactor { get; private set; }
128 public static float AvatarDensity { get; private set; }
129 public static float AvatarRestitution { get; private set; }
130 public static float AvatarCapsuleWidth { get; private set; }
131 public static float AvatarCapsuleDepth { get; private set; }
132 public static float AvatarCapsuleHeight { get; private set; }
133 public static float AvatarHeightLowFudge { get; private set; }
134 public static float AvatarHeightMidFudge { get; private set; }
135 public static float AvatarHeightHighFudge { get; private set; }
136 public static float AvatarContactProcessingThreshold { get; private set; }
137 public static float AvatarStopZeroThreshold { get; private set; }
138 public static int AvatarJumpFrames { get; private set; }
139 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
140 public static float AvatarStepHeight { get; private set; }
141 public static float AvatarStepApproachFactor { get; private set; }
142 public static float AvatarStepForceFactor { get; private set; }
143 public static float AvatarStepUpCorrectionFactor { get; private set; }
144 public static int AvatarStepSmoothingSteps { get; private set; }
145  
146 // Vehicle parameters
147 public static float VehicleMaxLinearVelocity { get; private set; }
148 public static float VehicleMaxLinearVelocitySquared { get; private set; }
149 public static float VehicleMaxAngularVelocity { get; private set; }
150 public static float VehicleMaxAngularVelocitySq { get; private set; }
151 public static float VehicleAngularDamping { get; private set; }
152 public static float VehicleFriction { get; private set; }
153 public static float VehicleRestitution { get; private set; }
154 public static Vector3 VehicleLinearFactor { get; private set; }
155 public static Vector3 VehicleAngularFactor { get; private set; }
156 public static Vector3 VehicleInertiaFactor { get; private set; }
157 public static float VehicleGroundGravityFudge { get; private set; }
158 public static float VehicleAngularBankingTimescaleFudge { get; private set; }
159 public static bool VehicleEnableLinearDeflection { get; private set; }
160 public static bool VehicleLinearDeflectionNotCollidingNoZ { get; private set; }
161 public static bool VehicleEnableAngularVerticalAttraction { get; private set; }
162 public static int VehicleAngularVerticalAttractionAlgorithm { get; private set; }
163 public static bool VehicleEnableAngularDeflection { get; private set; }
164 public static bool VehicleEnableAngularBanking { get; private set; }
165  
166 // Convex Hulls
167 public static int CSHullMaxDepthSplit { get; private set; }
168 public static int CSHullMaxDepthSplitForSimpleShapes { get; private set; }
169 public static float CSHullConcavityThresholdPercent { get; private set; }
170 public static float CSHullVolumeConservationThresholdPercent { get; private set; }
171 public static int CSHullMaxVertices { get; private set; }
172 public static float CSHullMaxSkinWidth { get; private set; }
173 public static float BHullMaxVerticesPerHull { get; private set; } // 100
174 public static float BHullMinClusters { get; private set; } // 2
175 public static float BHullCompacityWeight { get; private set; } // 0.1
176 public static float BHullVolumeWeight { get; private set; } // 0.0
177 public static float BHullConcavity { get; private set; } // 100
178 public static bool BHullAddExtraDistPoints { get; private set; } // false
179 public static bool BHullAddNeighboursDistPoints { get; private set; } // false
180 public static bool BHullAddFacesPoints { get; private set; } // false
181 public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
182  
183 // Linkset implementation parameters
184 public static float LinksetImplementation { get; private set; }
185 public static bool LinksetOffsetCenterOfMass { get; private set; }
186 public static bool LinkConstraintUseFrameOffset { get; private set; }
187 public static bool LinkConstraintEnableTransMotor { get; private set; }
188 public static float LinkConstraintTransMotorMaxVel { get; private set; }
189 public static float LinkConstraintTransMotorMaxForce { get; private set; }
190 public static float LinkConstraintERP { get; private set; }
191 public static float LinkConstraintCFM { get; private set; }
192 public static float LinkConstraintSolverIterations { get; private set; }
193  
194 public static float PID_D { get; private set; } // derivative
195 public static float PID_P { get; private set; } // proportional
196  
197 // Various constants that come from that other virtual world that shall not be named.
198 public const float MinGravityZ = -1f;
199 public const float MaxGravityZ = 28f;
200 public const float MinFriction = 0f;
201 public const float MaxFriction = 255f;
202 public const float MinDensity = 0.01f;
203 public const float MaxDensity = 22587f;
204 public const float MinRestitution = 0f;
205 public const float MaxRestitution = 1f;
206  
207 // =====================================================================================
208 // =====================================================================================
209  
210 // Base parameter definition that gets and sets parameter values via a string
211 public abstract class ParameterDefnBase
212 {
213 public string name; // string name of the parameter
214 public string desc; // a short description of what the parameter means
215 public ParameterDefnBase(string pName, string pDesc)
216 {
217 name = pName;
218 desc = pDesc;
219 }
220 // Set the parameter value to the default
221 public abstract void AssignDefault(BSScene s);
222 // Get the value as a string
223 public abstract string GetValue(BSScene s);
224 // Set the value to this string value
225 public abstract void SetValue(BSScene s, string valAsString);
226 // set the value on a particular object (usually sets in physics engine)
227 public abstract void SetOnObject(BSScene s, BSPhysObject obj);
228 public abstract bool HasSetOnObject { get; }
229 }
230  
231 // Specific parameter definition for a parameter of a specific type.
232 public delegate T PGetValue<T>(BSScene s);
233 public delegate void PSetValue<T>(BSScene s, T val);
234 public delegate void PSetOnObject<T>(BSScene scene, BSPhysObject obj);
235 public sealed class ParameterDefn<T> : ParameterDefnBase
236 {
237 private T defaultValue;
238 private PSetValue<T> setter;
239 private PGetValue<T> getter;
240 private PSetOnObject<T> objectSet;
241 public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
242 : base(pName, pDesc)
243 {
244 defaultValue = pDefault;
245 setter = pSetter;
246 getter = pGetter;
247 objectSet = null;
248 }
249 public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter, PSetOnObject<T> pObjSetter)
250 : base(pName, pDesc)
251 {
252 defaultValue = pDefault;
253 setter = pSetter;
254 getter = pGetter;
255 objectSet = pObjSetter;
256 }
257 // Simple parameter variable where property name is the same as the INI file name
258 // and the value is only a simple get and set.
259 public ParameterDefn(string pName, string pDesc, T pDefault)
260 : base(pName, pDesc)
261 {
262 defaultValue = pDefault;
263 setter = (s, v) => { SetValueByName(s, name, v); };
264 getter = (s) => { return GetValueByName(s, name); };
265 objectSet = null;
266 }
267 // Use reflection to find the property named 'pName' in BSParam and assign 'val' to same.
268 private void SetValueByName(BSScene s, string pName, T val)
269 {
270 PropertyInfo prop = typeof(BSParam).GetProperty(pName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
271 if (prop == null)
272 {
273 // This should only be output when someone adds a new INI parameter and misspells the name.
274 s.Logger.ErrorFormat("{0} SetValueByName: did not find '{1}'. Verify specified property name is the same as the given INI parameters name.", LogHeader, pName);
275 }
276 else
277 {
278 prop.SetValue(null, val, null);
279 }
280 }
281 // Use reflection to find the property named 'pName' in BSParam and return the value in same.
282 private T GetValueByName(BSScene s, string pName)
283 {
284 PropertyInfo prop = typeof(BSParam).GetProperty(pName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
285 if (prop == null)
286 {
287 // This should only be output when someone adds a new INI parameter and misspells the name.
288 s.Logger.ErrorFormat("{0} GetValueByName: did not find '{1}'. Verify specified property name is the same as the given INI parameter name.", LogHeader, pName);
289 }
290 return (T)prop.GetValue(null, null);
291 }
292 public override void AssignDefault(BSScene s)
293 {
294 setter(s, defaultValue);
295 }
296 public override string GetValue(BSScene s)
297 {
298 return getter(s).ToString();
299 }
300 public override void SetValue(BSScene s, string valAsString)
301 {
302 // Get the generic type of the setter
303 Type genericType = setter.GetType().GetGenericArguments()[0];
304 // Find the 'Parse' method on that type
305 System.Reflection.MethodInfo parser = null;
306 try
307 {
308 parser = genericType.GetMethod("Parse", new Type[] { typeof(String) } );
309 }
310 catch (Exception e)
311 {
312 s.Logger.ErrorFormat("{0} Exception getting parser for type '{1}': {2}", LogHeader, genericType, e);
313 parser = null;
314 }
315 if (parser != null)
316 {
317 // Parse the input string
318 try
319 {
320 T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString });
321 // Store the parsed value
322 setter(s, setValue);
323 // s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue);
324 }
325 catch
326 {
327 s.Logger.ErrorFormat("{0} Failed parsing parameter value '{1}' as type '{2}'", LogHeader, valAsString, genericType);
328 }
329 }
330 else
331 {
332 s.Logger.ErrorFormat("{0} Could not find parameter parser for type '{1}'", LogHeader, genericType);
333 }
334 }
335 public override bool HasSetOnObject
336 {
337 get { return objectSet != null; }
338 }
339 public override void SetOnObject(BSScene s, BSPhysObject obj)
340 {
341 if (objectSet != null)
342 objectSet(s, obj);
343 }
344 }
345  
346 // List of all of the externally visible parameters.
347 // For each parameter, this table maps a text name to getter and setters.
348 // To add a new externally referencable/settable parameter, add the paramter storage
349 // location somewhere in the program and make an entry in this table with the
350 // getters and setters.
351 // It is easiest to find an existing definition and copy it.
352 //
353 // A ParameterDefn<T>() takes the following parameters:
354 // -- the text name of the parameter. This is used for console input and ini file.
355 // -- a short text description of the parameter. This shows up in the console listing.
356 // -- a default value
357 // -- a delegate for getting the value
358 // -- a delegate for setting the value
359 // -- an optional delegate to update the value in the world. Most often used to
360 // push the new value to an in-world object.
361 //
362 // The single letter parameters for the delegates are:
363 // s = BSScene
364 // o = BSPhysObject
365 // v = value (appropriate type)
366 private static ParameterDefnBase[] ParameterDefinitions =
367 {
368 new ParameterDefn<bool>("UseSeparatePhysicsThread", "If 'true', the physics engine runs independent from the simulator heartbeat",
369 false ),
370 new ParameterDefn<float>("PhysicsTimeStep", "If separate thread, seconds to simulate each interval",
371 0.089f ),
372  
373 new ParameterDefn<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties",
374 true,
375 (s) => { return ShouldMeshSculptedPrim; },
376 (s,v) => { ShouldMeshSculptedPrim = v; } ),
377 new ParameterDefn<bool>("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
378 false,
379 (s) => { return ShouldForceSimplePrimMeshing; },
380 (s,v) => { ShouldForceSimplePrimMeshing = v; } ),
381 new ParameterDefn<bool>("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
382 true,
383 (s) => { return ShouldUseHullsForPhysicalObjects; },
384 (s,v) => { ShouldUseHullsForPhysicalObjects = v; } ),
385 new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
386 true ),
387 new ParameterDefn<bool>("ShouldUseBulletHACD", "If true, use the Bullet version of HACD",
388 false ),
389 new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
390 true ),
391 new ParameterDefn<bool>("ShouldUseGImpactShapeForPrims", "If true, use a GImpact shape for prims with cuts and twists",
392 false ),
393 new ParameterDefn<bool>("ShouldUseAssetHulls", "If true, use hull if specified in the mesh asset info",
394 true ),
395  
396 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
397 5 ),
398 new ParameterDefn<float>("UpdateVelocityChangeThreshold", "Change in updated velocity required before reporting change to simulator",
399 0.1f ),
400  
401 new ParameterDefn<float>("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
402 32f,
403 (s) => { return MeshLOD; },
404 (s,v) => { MeshLOD = v; } ),
405 new ParameterDefn<float>("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes",
406 32f,
407 (s) => { return MeshCircularLOD; },
408 (s,v) => { MeshCircularLOD = v; } ),
409 new ParameterDefn<float>("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
410 10f,
411 (s) => { return MeshMegaPrimThreshold; },
412 (s,v) => { MeshMegaPrimThreshold = v; } ),
413 new ParameterDefn<float>("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
414 32f,
415 (s) => { return MeshMegaPrimLOD; },
416 (s,v) => { MeshMegaPrimLOD = v; } ),
417 new ParameterDefn<float>("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
418 32f,
419 (s) => { return SculptLOD; },
420 (s,v) => { SculptLOD = v; } ),
421  
422 new ParameterDefn<int>("MaxSubStep", "In simulation step, maximum number of substeps",
423 10,
424 (s) => { return s.m_maxSubSteps; },
425 (s,v) => { s.m_maxSubSteps = (int)v; } ),
426 new ParameterDefn<float>("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
427 1f / 60f,
428 (s) => { return s.m_fixedTimeStep; },
429 (s,v) => { s.m_fixedTimeStep = v; } ),
430 new ParameterDefn<float>("NominalFrameRate", "The base frame rate we claim",
431 55f,
432 (s) => { return s.NominalFrameRate; },
433 (s,v) => { s.NominalFrameRate = (int)v; } ),
434 new ParameterDefn<int>("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
435 2048,
436 (s) => { return s.m_maxCollisionsPerFrame; },
437 (s,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
438 new ParameterDefn<int>("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
439 8000,
440 (s) => { return s.m_maxUpdatesPerFrame; },
441 (s,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
442  
443 new ParameterDefn<float>("MinObjectMass", "Minimum object mass (0.0001)",
444 0.0001f,
445 (s) => { return MinimumObjectMass; },
446 (s,v) => { MinimumObjectMass = v; } ),
447 new ParameterDefn<float>("MaxObjectMass", "Maximum object mass (10000.01)",
448 10000.01f,
449 (s) => { return MaximumObjectMass; },
450 (s,v) => { MaximumObjectMass = v; } ),
451 new ParameterDefn<float>("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
452 1000.0f,
453 (s) => { return MaxLinearVelocity; },
454 (s,v) => { MaxLinearVelocity = v; MaxLinearVelocitySquared = v * v; } ),
455 new ParameterDefn<float>("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
456 1000.0f,
457 (s) => { return MaxAngularVelocity; },
458 (s,v) => { MaxAngularVelocity = v; MaxAngularVelocitySquared = v * v; } ),
459 // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
460 new ParameterDefn<float>("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
461 20000.0f,
462 (s) => { return MaxAddForceMagnitude; },
463 (s,v) => { MaxAddForceMagnitude = v; MaxAddForceMagnitudeSquared = v * v; } ),
464 // Density is passed around as 100kg/m3. This scales that to 1kg/m3.
465 // Reduce by power of 100 because Bullet doesn't seem to handle objects with large mass very well
466 new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
467 0.01f ),
468  
469 new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing",
470 2200f ),
471 new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing",
472 900f ),
473  
474 new ParameterDefn<float>("DefaultFriction", "Friction factor used on new objects",
475 0.2f,
476 (s) => { return DefaultFriction; },
477 (s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
478 // For historical reasons, the viewer and simulator multiply the density by 100
479 new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
480 1000.0006836f, // Aluminum g/cm3 * 100
481 (s) => { return DefaultDensity; },
482 (s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
483 new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
484 0f,
485 (s) => { return DefaultRestitution; },
486 (s,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ),
487 new ParameterDefn<float>("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
488 0.04f,
489 (s) => { return CollisionMargin; },
490 (s,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ),
491 new ParameterDefn<float>("Gravity", "Vertical force of gravity (negative means down)",
492 -9.80665f,
493 (s) => { return Gravity; },
494 (s,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; },
495 (s,o) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,Gravity)); } ),
496  
497  
498 new ParameterDefn<float>("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
499 0f,
500 (s) => { return LinearDamping; },
501 (s,v) => { LinearDamping = v; },
502 (s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
503 new ParameterDefn<float>("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
504 0f,
505 (s) => { return AngularDamping; },
506 (s,v) => { AngularDamping = v; },
507 (s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
508 new ParameterDefn<float>("DeactivationTime", "Seconds before considering an object potentially static",
509 0.2f,
510 (s) => { return DeactivationTime; },
511 (s,v) => { DeactivationTime = v; },
512 (s,o) => { s.PE.SetDeactivationTime(o.PhysBody, DeactivationTime); } ),
513 new ParameterDefn<float>("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
514 0.8f,
515 (s) => { return LinearSleepingThreshold; },
516 (s,v) => { LinearSleepingThreshold = v;},
517 (s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
518 new ParameterDefn<float>("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
519 1.0f,
520 (s) => { return AngularSleepingThreshold; },
521 (s,v) => { AngularSleepingThreshold = v;},
522 (s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
523 new ParameterDefn<float>("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
524 0.0f, // set to zero to disable
525 (s) => { return CcdMotionThreshold; },
526 (s,v) => { CcdMotionThreshold = v;},
527 (s,o) => { s.PE.SetCcdMotionThreshold(o.PhysBody, CcdMotionThreshold); } ),
528 new ParameterDefn<float>("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
529 0.2f,
530 (s) => { return CcdSweptSphereRadius; },
531 (s,v) => { CcdSweptSphereRadius = v;},
532 (s,o) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, CcdSweptSphereRadius); } ),
533 new ParameterDefn<float>("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" ,
534 0.0f,
535 (s) => { return ContactProcessingThreshold; },
536 (s,v) => { ContactProcessingThreshold = v;},
537 (s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ),
538  
539 new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
540 (float)BSTerrainPhys.TerrainImplementation.Mesh ),
541 new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
542 2 ),
543 new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
544 0.3f ),
545 new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" ,
546 0.8f ),
547 new ParameterDefn<float>("TerrainRestitution", "Bouncyness" ,
548 0f ),
549 new ParameterDefn<float>("TerrainContactProcessingThreshold", "Distance from terrain to stop processing collisions" ,
550 0.0f ),
551 new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
552 0.08f ),
553  
554 new ParameterDefn<float>("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
555 0.2f ),
556 new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
557 0.95f ),
558 new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
559 1.3f ),
560 // For historical reasons, density is reported * 100
561 new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation. Scaled times 100.",
562 3500f) , // 3.5 * 100
563 new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
564 0f ),
565 new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
566 0.6f ) ,
567 new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
568 0.45f ),
569 new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar",
570 1.5f ),
571 new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground",
572 -0.2f ),
573 new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground",
574 0.1f ),
575 new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground",
576 0.1f ),
577 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
578 0.1f ),
579 new ParameterDefn<float>("AvatarStopZeroThreshold", "Movement velocity below which avatar is assumed to be stopped",
580 0.1f ),
581 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
582 1.0f ),
583 new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
584 4 ),
585 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
586 0.6f ) ,
587 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
588 0.6f ),
589 new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
590 1.0f ),
591 new ParameterDefn<float>("AvatarStepUpCorrectionFactor", "Multiplied by height of step collision to create up movement at step",
592 1.0f ),
593 new ParameterDefn<int>("AvatarStepSmoothingSteps", "Number of frames after a step collision that we continue walking up stairs",
594 2 ),
595  
596 new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
597 1000.0f,
598 (s) => { return (float)VehicleMaxLinearVelocity; },
599 (s,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySquared = v * v; } ),
600 new ParameterDefn<float>("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
601 12.0f,
602 (s) => { return (float)VehicleMaxAngularVelocity; },
603 (s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
604 new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
605 0.0f ),
606 new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)",
607 new Vector3(1f, 1f, 1f) ),
608 new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
609 new Vector3(1f, 1f, 1f) ),
610 new ParameterDefn<Vector3>("VehicleInertiaFactor", "Fraction of physical inertia applied (<0,0,0> to <1,1,1>)",
611 new Vector3(1f, 1f, 1f) ),
612 new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
613 0.0f ),
614 new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
615 0.0f ),
616 new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
617 0.2f ),
618 new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.",
619 60.0f ),
620 new ParameterDefn<bool>("VehicleEnableLinearDeflection", "Turn on/off vehicle linear deflection effect",
621 true ),
622 new ParameterDefn<bool>("VehicleLinearDeflectionNotCollidingNoZ", "Turn on/off linear deflection Z effect on non-colliding vehicles",
623 true ),
624 new ParameterDefn<bool>("VehicleEnableAngularVerticalAttraction", "Turn on/off vehicle angular vertical attraction effect",
625 true ),
626 new ParameterDefn<int>("VehicleAngularVerticalAttractionAlgorithm", "Select vertical attraction algo. You need to look at the source.",
627  
628 new ParameterDefn<bool>("VehicleEnableAngularDeflection", "Turn on/off vehicle angular deflection effect",
629 true ),
630 new ParameterDefn<bool>("VehicleEnableAngularBanking", "Turn on/off vehicle angular banking effect",
631 true ),
632  
633 new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
634 0f,
635 (s) => { return MaxPersistantManifoldPoolSize; },
636 (s,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
637 new ParameterDefn<float>("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
638 0f,
639 (s) => { return MaxCollisionAlgorithmPoolSize; },
640 (s,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
641 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
642 false,
643 (s) => { return ShouldDisableContactPoolDynamicAllocation; },
644 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
645 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
646 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
647 false,
648 (s) => { return ShouldForceUpdateAllAabbs; },
649 (s,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = NumericBool(v); } ),
650 new ParameterDefn<bool>("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
651 true,
652 (s) => { return ShouldRandomizeSolverOrder; },
653 (s,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = NumericBool(v); } ),
654 new ParameterDefn<bool>("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
655 true,
656 (s) => { return ShouldSplitSimulationIslands; },
657 (s,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = NumericBool(v); } ),
658 new ParameterDefn<bool>("ShouldEnableFrictionCaching", "Enable friction computation caching",
659 true,
660 (s) => { return ShouldEnableFrictionCaching; },
661 (s,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = NumericBool(v); } ),
662 new ParameterDefn<float>("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
663 0f, // zero says use Bullet default
664 (s) => { return NumberOfSolverIterations; },
665 (s,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
666 new ParameterDefn<bool>("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.",
667 true,
668 (s) => { return UseSingleSidedMeshes; },
669 (s,v) => { UseSingleSidedMeshes = v; s.UnmanagedParams[0].useSingleSidedMeshes = NumericBool(v); } ),
670 new ParameterDefn<float>("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
671 0f,
672 (s) => { return GlobalContactBreakingThreshold; },
673 (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
674  
675 new ParameterDefn<int>("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy",
676 7 ),
677 new ParameterDefn<int>("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes",
678 2 ),
679 new ParameterDefn<float>("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)",
680 5f ),
681 new ParameterDefn<float>("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)",
682 5f ),
683 new ParameterDefn<int>("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.",
684 32 ),
685 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
686 0f ),
687  
688 new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
689 200f ),
690 new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
691 10f ),
692 new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
693 20f ),
694 new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
695 0.1f ),
696 new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
697 10f ),
698 new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
699 true ),
700 new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
701 true ),
702 new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
703 true ),
704 new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
705 false ),
706  
707 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
708 (float)BSLinkset.LinksetImplementation.Compound ),
709 new ParameterDefn<bool>("LinksetOffsetCenterOfMass", "If 'true', compute linkset center-of-mass and offset linkset position to account for same",
710 true ),
711 new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
712 false ),
713 new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
714 true ),
715 new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
716 5.0f ),
717 new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
718 0.1f ),
719 new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
720 0.1f ),
721 new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
722 0.1f ),
723 new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
724 40 ),
725  
726 new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
727 0,
728 (s) => { return s.PhysicsMetricDumpFrames; },
729 (s,v) => { s.PhysicsMetricDumpFrames = v; } ),
730 new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
731 0f,
732 (s) => { return 0f; },
733 (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v, false /* inTaintTime */); } ),
734 new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
735 0f,
736 (s) => { return 0f; },
737 (s,v) => { BSParam.ResetConstraintSolverTainted(s, v); } ),
738 };
739  
740 // Convert a boolean to our numeric true and false values
741 public static float NumericBool(bool b)
742 {
743 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
744 }
745  
746 // Convert numeric true and false values to a boolean
747 public static bool BoolNumeric(float b)
748 {
749 return (b == ConfigurationParameters.numericTrue ? true : false);
750 }
751  
752 // Search through the parameter definitions and return the matching
753 // ParameterDefn structure.
754 // Case does not matter as names are compared after converting to lower case.
755 // Returns 'false' if the parameter is not found.
756 internal static bool TryGetParameter(string paramName, out ParameterDefnBase defn)
757 {
758 bool ret = false;
759 ParameterDefnBase foundDefn = null;
760 string pName = paramName.ToLower();
761  
762 foreach (ParameterDefnBase parm in ParameterDefinitions)
763 {
764 if (pName == parm.name.ToLower())
765 {
766 foundDefn = parm;
767 ret = true;
768 break;
769 }
770 }
771 defn = foundDefn;
772 return ret;
773 }
774  
775 // Pass through the settable parameters and set the default values
776 internal static void SetParameterDefaultValues(BSScene physicsScene)
777 {
778 foreach (ParameterDefnBase parm in ParameterDefinitions)
779 {
780 parm.AssignDefault(physicsScene);
781 }
782 }
783  
784 // Get user set values out of the ini file.
785 internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
786 {
787 foreach (ParameterDefnBase parm in ParameterDefinitions)
788 {
789 parm.SetValue(physicsScene, cfg.GetString(parm.name, parm.GetValue(physicsScene)));
790 }
791 }
792  
793 internal static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
794  
795 // This creates an array in the correct format for returning the list of
796 // parameters. This is used by the 'list' option of the 'physics' command.
797 internal static void BuildParameterTable()
798 {
799 if (SettableParameters.Length < ParameterDefinitions.Length)
800 {
801 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
802 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
803 {
804 ParameterDefnBase pd = ParameterDefinitions[ii];
805 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
806 }
807  
808 // make the list alphabetical for ease of finding anything
809 entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); });
810  
811 SettableParameters = entries.ToArray();
812 }
813 }
814  
815 // =====================================================================
816 // =====================================================================
817 // There are parameters that, when set, cause things to happen in the physics engine.
818 // This causes the broadphase collision cache to be cleared.
819 private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v, bool inTaintTime)
820 {
821 BSScene physScene = pPhysScene;
822 physScene.TaintedObject(inTaintTime, "BSParam.ResetBroadphasePoolTainted", delegate()
823 {
824 physScene.PE.ResetBroadphasePool(physScene.World);
825 });
826 }
827  
828 // This causes the constraint solver cache to be cleared and reset.
829 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
830 {
831 BSScene physScene = pPhysScene;
832 physScene.TaintedObject(BSScene.DetailLogZero, "BSParam.ResetConstraintSolver", delegate()
833 {
834 physScene.PE.ResetConstraintSolver(physScene.World);
835 });
836 }
837 }
838 }