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.
							parent
							
								
									2e3e95e846
								
							
						
					
					
						commit
						ae4d932e7f
					
				|  | @ -88,8 +88,8 @@ public sealed class BSCharacter : BSPhysObject | |||
|         // Old versions of ScenePresence passed only the height. If width and/or depth are zero, | ||||
|         //     replace with the default values. | ||||
|         _size = size; | ||||
|         if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth; | ||||
|         if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth; | ||||
|         if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth; | ||||
|         if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth; | ||||
| 
 | ||||
|         // A motor to control the acceleration and deceleration of the avatar movement. | ||||
|         // _velocityMotor = new BSVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f); | ||||
|  | @ -108,8 +108,8 @@ public sealed class BSCharacter : BSPhysObject | |||
|         _velocity = OMV.Vector3.Zero; | ||||
|         _appliedVelocity = OMV.Vector3.Zero; | ||||
|         _buoyancy = ComputeBuoyancyFromFlying(isFlying); | ||||
|         _currentFriction = PhysicsScene.Params.avatarStandingFriction; | ||||
|         _avatarDensity = PhysicsScene.Params.avatarDensity; | ||||
|         _currentFriction = BSParam.AvatarStandingFriction; | ||||
|         _avatarDensity = BSParam.AvatarDensity; | ||||
| 
 | ||||
|         // The dimensions of the avatar capsule are kept in the scale. | ||||
|         // Physics creates a unit capsule which is scaled by the physics engine. | ||||
|  | @ -161,14 +161,14 @@ public sealed class BSCharacter : BSPhysObject | |||
|         // Needs to be reset especially when an avatar is recreated after crossing a region boundry. | ||||
|         Flying = _flying; | ||||
| 
 | ||||
|         BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); | ||||
|         BulletSimAPI.SetRestitution2(PhysBody.ptr, BSParam.AvatarRestitution); | ||||
|         BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); | ||||
|         BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); | ||||
|         BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | ||||
|         if (PhysicsScene.Params.ccdMotionThreshold > 0f) | ||||
|         BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, BSParam.ContactProcessingThreshold); | ||||
|         if (BSParam.CcdMotionThreshold > 0f) | ||||
|         { | ||||
|             BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | ||||
|             BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | ||||
|             BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold); | ||||
|             BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius); | ||||
|         } | ||||
| 
 | ||||
|         UpdatePhysicalMassProperties(RawMass); | ||||
|  | @ -208,8 +208,8 @@ public sealed class BSCharacter : BSPhysObject | |||
|             _size = value; | ||||
|             // Old versions of ScenePresence passed only the height. If width and/or depth are zero, | ||||
|             //     replace with the default values. | ||||
|             if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth; | ||||
|             if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth; | ||||
|             if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth; | ||||
|             if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth; | ||||
| 
 | ||||
|             ComputeAvatarScale(_size); | ||||
|             ComputeAvatarVolumeAndMass(); | ||||
|  | @ -468,18 +468,18 @@ public sealed class BSCharacter : BSPhysObject | |||
|             //    to keep the avatar from slipping around | ||||
|             if (_velocity.Length() == 0) | ||||
|             { | ||||
|                 if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) | ||||
|                 if (_currentFriction != BSParam.AvatarStandingFriction) | ||||
|                 { | ||||
|                     _currentFriction = PhysicsScene.Params.avatarStandingFriction; | ||||
|                     _currentFriction = BSParam.AvatarStandingFriction; | ||||
|                     if (PhysBody.HasPhysicalBody) | ||||
|                         BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (_currentFriction != PhysicsScene.Params.avatarFriction) | ||||
|                 if (_currentFriction != BSParam.AvatarFriction) | ||||
|                 { | ||||
|                     _currentFriction = PhysicsScene.Params.avatarFriction; | ||||
|                     _currentFriction = BSParam.AvatarFriction; | ||||
|                     if (PhysBody.HasPhysicalBody) | ||||
|                         BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | ||||
|                 } | ||||
|  |  | |||
|  | @ -122,7 +122,7 @@ public abstract class BSConstraint : IDisposable | |||
|                 // Setting an object's mass to zero (making it static like when it's selected) | ||||
|                 //     automatically disables the constraints. | ||||
|                 // If the link is enabled, be sure to set the constraint itself to enabled. | ||||
|                 BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true)); | ||||
|                 BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, BSParam.NumericBool(true)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  |  | |||
|  | @ -563,7 +563,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
|                 // Moderate angular movement introduced by Bullet. | ||||
|                 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. | ||||
|                 //     Maybe compute linear and angular factor and damping from params. | ||||
|                 float angularDamping = PhysicsScene.Params.vehicleAngularDamping; | ||||
|                 float angularDamping = BSParam.VehicleAngularDamping; | ||||
|                 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); | ||||
| 
 | ||||
|                 // Vehicles report collision events so we know when it's on the ground | ||||
|  |  | |||
|  | @ -56,7 +56,7 @@ public abstract class BSLinkset | |||
|     { | ||||
|         BSLinkset ret = null; | ||||
| 
 | ||||
|         switch ((int)physScene.Params.linksetImplementation) | ||||
|         switch ((int)BSParam.LinksetImplementation) | ||||
|         { | ||||
|             case (int)LinksetImplementation.Constraint: | ||||
|                 ret = new BSLinksetConstraints(physScene, parent); | ||||
|  |  | |||
|  | @ -226,14 +226,14 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
|         constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | ||||
| 
 | ||||
|         // tweek the constraint to increase stability | ||||
|         constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); | ||||
|         constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), | ||||
|                         PhysicsScene.Params.linkConstraintTransMotorMaxVel, | ||||
|                         PhysicsScene.Params.linkConstraintTransMotorMaxForce); | ||||
|         constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); | ||||
|         if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) | ||||
|         constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset)); | ||||
|         constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor), | ||||
|                         BSParam.LinkConstraintTransMotorMaxVel, | ||||
|                         BSParam.LinkConstraintTransMotorMaxForce); | ||||
|         constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP); | ||||
|         if (BSParam.LinkConstraintSolverIterations != 0f) | ||||
|         { | ||||
|             constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); | ||||
|             constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations); | ||||
|         } | ||||
|         return constrain; | ||||
|     } | ||||
|  |  | |||
|  | @ -0,0 +1,558 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyrightD | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
| 
 | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| using Nini.Config; | ||||
| 
 | ||||
| namespace OpenSim.Region.Physics.BulletSPlugin | ||||
| { | ||||
| public static class BSParam | ||||
| { | ||||
|     // Level of Detail values kept as float because that's what the Meshmerizer wants | ||||
|     public static float MeshLOD { get; private set; } | ||||
|     public static float MeshMegaPrimLOD { get; private set; } | ||||
|     public static float MeshMegaPrimThreshold { get; private set; } | ||||
|     public static float SculptLOD { get; private set; } | ||||
| 
 | ||||
|     public static float MinimumObjectMass { get; private set; } | ||||
|     public static float MaximumObjectMass { get; private set; } | ||||
| 
 | ||||
|     public static float LinearDamping { get; private set; } | ||||
|     public static float AngularDamping { get; private set; } | ||||
|     public static float DeactivationTime { get; private set; } | ||||
|     public static float LinearSleepingThreshold { get; private set; } | ||||
|     public static float AngularSleepingThreshold { get; private set; } | ||||
| 	public static float CcdMotionThreshold { get; private set; } | ||||
| 	public static float CcdSweptSphereRadius { get; private set; } | ||||
|     public static float ContactProcessingThreshold { get; private set; } | ||||
| 
 | ||||
|     public static bool ShouldMeshSculptedPrim { get; private set; }   // cause scuplted prims to get meshed | ||||
|     public static bool ShouldForceSimplePrimMeshing { get; private set; }   // if a cube or sphere, let Bullet do internal shapes | ||||
|     public static bool ShouldUseHullsForPhysicalObjects { get; private set; }   // 'true' if should create hulls for physical objects | ||||
| 
 | ||||
|     public static float TerrainImplementation { get; private set; } | ||||
|     public static float TerrainFriction { get; private set; } | ||||
|     public static float TerrainHitFraction { get; private set; } | ||||
|     public static float TerrainRestitution { get; private set; } | ||||
|     public static float TerrainCollisionMargin { get; private set; } | ||||
| 
 | ||||
|     // Avatar parameters | ||||
|     public static float AvatarFriction { get; private set; } | ||||
|     public static float AvatarStandingFriction { get; private set; } | ||||
|     public static float AvatarDensity { get; private set; } | ||||
|     public static float AvatarRestitution { get; private set; } | ||||
|     public static float AvatarCapsuleWidth { get; private set; } | ||||
|     public static float AvatarCapsuleDepth { get; private set; } | ||||
|     public static float AvatarCapsuleHeight { get; private set; } | ||||
| 	public static float AvatarContactProcessingThreshold { get; private set; } | ||||
| 
 | ||||
|     public static float VehicleAngularDamping { get; private set; } | ||||
| 
 | ||||
|     public static float LinksetImplementation { get; private set; } | ||||
|     public static float LinkConstraintUseFrameOffset { get; private set; } | ||||
|     public static float LinkConstraintEnableTransMotor { get; private set; } | ||||
|     public static float LinkConstraintTransMotorMaxVel { get; private set; } | ||||
|     public static float LinkConstraintTransMotorMaxForce { get; private set; } | ||||
|     public static float LinkConstraintERP { get; private set; } | ||||
|     public static float LinkConstraintCFM { get; private set; } | ||||
|     public static float LinkConstraintSolverIterations { get; private set; } | ||||
| 
 | ||||
|     public static float PID_D { get; private set; }    // derivative | ||||
|     public static float PID_P { get; private set; }    // proportional | ||||
| 
 | ||||
|     public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); | ||||
|     public delegate float ParamGet(BSScene scene); | ||||
|     public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); | ||||
|     public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); | ||||
| 
 | ||||
|     public struct ParameterDefn | ||||
|     { | ||||
|         public string name;         // string name of the parameter | ||||
|         public string desc;         // a short description of what the parameter means | ||||
|         public float defaultValue;  // default value if not specified anywhere else | ||||
|         public ParamUser userParam; // get the value from the configuration file | ||||
|         public ParamGet getter;     // return the current value stored for this parameter | ||||
|         public ParamSet setter;     // set the current value for this parameter | ||||
|         public SetOnObject onObject;    // set the value on an object in the physical domain | ||||
|         public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) | ||||
|         { | ||||
|             name = n; | ||||
|             desc = d; | ||||
|             defaultValue = v; | ||||
|             userParam = u; | ||||
|             getter = g; | ||||
|             setter = s; | ||||
|             onObject = null; | ||||
|         } | ||||
|         public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) | ||||
|         { | ||||
|             name = n; | ||||
|             desc = d; | ||||
|             defaultValue = v; | ||||
|             userParam = u; | ||||
|             getter = g; | ||||
|             setter = s; | ||||
|             onObject = o; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // List of all of the externally visible parameters. | ||||
|     // For each parameter, this table maps a text name to getter and setters. | ||||
|     // To add a new externally referencable/settable parameter, add the paramter storage | ||||
|     //    location somewhere in the program and make an entry in this table with the | ||||
|     //    getters and setters. | ||||
|     // It is easiest to find an existing definition and copy it. | ||||
|     // Parameter values are floats. Booleans are converted to a floating value. | ||||
|     // | ||||
|     // A ParameterDefn() takes the following parameters: | ||||
|     //    -- the text name of the parameter. This is used for console input and ini file. | ||||
|     //    -- a short text description of the parameter. This shows up in the console listing. | ||||
|     //    -- a delegate for fetching the parameter from the ini file. | ||||
|     //          Should handle fetching the right type from the ini file and converting it. | ||||
|     //    -- a delegate for getting the value as a float | ||||
|     //    -- a delegate for setting the value from a float | ||||
|     //    -- an optional delegate to update the value in the world. Most often used to | ||||
|     //          push the new value to an in-world object. | ||||
|     // | ||||
|     // The single letter parameters for the delegates are: | ||||
|     //    s = BSScene | ||||
|     //    o = BSPhysObject | ||||
|     //    p = string parameter name | ||||
|     //    l = localID of referenced object | ||||
|     //    v = float value | ||||
|     //    cf = parameter configuration class (for fetching values from ini file) | ||||
|     private static ParameterDefn[] ParameterDefinitions = | ||||
|     { | ||||
|         new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, | ||||
|             (s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); }, | ||||
|             (s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ), | ||||
|         new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, | ||||
|             (s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); }, | ||||
|             (s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ), | ||||
|         new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, | ||||
|             (s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); }, | ||||
|             (s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ), | ||||
| 
 | ||||
|         new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", | ||||
|             8f, | ||||
|             (s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return MeshLOD; }, | ||||
|             (s,p,l,v) => { MeshLOD = v; } ), | ||||
|         new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", | ||||
|             16f, | ||||
|             (s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return MeshMegaPrimLOD; }, | ||||
|             (s,p,l,v) => { MeshMegaPrimLOD = v; } ), | ||||
|         new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", | ||||
|             10f, | ||||
|             (s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return MeshMegaPrimThreshold; }, | ||||
|             (s,p,l,v) => { MeshMegaPrimThreshold = v; } ), | ||||
|         new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", | ||||
|             32f, | ||||
|             (s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return SculptLOD; }, | ||||
|             (s,p,l,v) => { SculptLOD = v; } ), | ||||
| 
 | ||||
|         new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", | ||||
|             10f, | ||||
|             (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_maxSubSteps; }, | ||||
|             (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ), | ||||
|         new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)", | ||||
|             1f / 60f, | ||||
|             (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)s.m_fixedTimeStep; }, | ||||
|             (s,p,l,v) => { s.m_fixedTimeStep = v; } ), | ||||
|         new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", | ||||
|             2048f, | ||||
|             (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_maxCollisionsPerFrame; }, | ||||
|             (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ), | ||||
|         new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame", | ||||
|             8000f, | ||||
|             (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_maxUpdatesPerFrame; }, | ||||
|             (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), | ||||
|         new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", | ||||
|             500f, | ||||
|             (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_taintsToProcessPerStep; }, | ||||
|             (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), | ||||
|         new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)", | ||||
|             0.0001f, | ||||
|             (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)MinimumObjectMass; }, | ||||
|             (s,p,l,v) => { MinimumObjectMass = v; } ), | ||||
|         new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", | ||||
|             10000.01f, | ||||
|             (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)MaximumObjectMass; }, | ||||
|             (s,p,l,v) => { MaximumObjectMass = v; } ), | ||||
| 
 | ||||
|         new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", | ||||
|             2200f, | ||||
|             (s,cf,p,v) => { PID_D = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)PID_D; }, | ||||
|             (s,p,l,v) => { PID_D = v; } ), | ||||
|         new ParameterDefn("PID_P", "Parameteric factor for motion smoothing", | ||||
|             900f, | ||||
|             (s,cf,p,v) => { PID_P = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)PID_P; }, | ||||
|             (s,p,l,v) => { PID_P = v; } ), | ||||
| 
 | ||||
|         new ParameterDefn("DefaultFriction", "Friction factor used on new objects", | ||||
|             0.2f, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].defaultFriction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.UnmanagedParams[0].defaultFriction; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].defaultFriction = v; } ), | ||||
|         new ParameterDefn("DefaultDensity", "Density for new objects" , | ||||
|             10.000006836f,  // Aluminum g/cm3 | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].defaultDensity = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.UnmanagedParams[0].defaultDensity; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].defaultDensity = v; } ), | ||||
|         new ParameterDefn("DefaultRestitution", "Bouncyness of an object" , | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].defaultRestitution = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.UnmanagedParams[0].defaultRestitution; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].defaultRestitution = v; } ), | ||||
|         new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", | ||||
|             0.04f, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].collisionMargin = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.UnmanagedParams[0].collisionMargin; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].collisionMargin = v; } ), | ||||
|         new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)", | ||||
|             -9.80665f, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].gravity = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.UnmanagedParams[0].gravity; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{s.UnmanagedParams[0].gravity=x;}, p, PhysParameterEntry.APPLY_TO_NONE, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), | ||||
| 
 | ||||
| 
 | ||||
|         new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); }, | ||||
|             (s) => { return LinearDamping; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearDamping=x;}, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, AngularDamping); } ), | ||||
|         new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AngularDamping; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularDamping=x;}, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, LinearDamping, v); } ), | ||||
|         new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", | ||||
|             0.2f, | ||||
|             (s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); }, | ||||
|             (s) => { return DeactivationTime; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{DeactivationTime=x;}, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ), | ||||
|         new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", | ||||
|             0.8f, | ||||
|             (s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return LinearSleepingThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearSleepingThreshold=x;}, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), | ||||
|         new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", | ||||
|             1.0f, | ||||
|             (s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AngularSleepingThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularSleepingThreshold=x;}, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), | ||||
|         new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , | ||||
|             0f,     // set to zero to disable | ||||
|             (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return CcdMotionThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdMotionThreshold=x;}, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ), | ||||
|         new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , | ||||
|             0f, | ||||
|             (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); }, | ||||
|             (s) => { return CcdSweptSphereRadius; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdSweptSphereRadius=x;}, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ), | ||||
|         new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return ContactProcessingThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{ContactProcessingThreshold=x;}, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), | ||||
| 
 | ||||
| 	    new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", | ||||
|             (float)BSTerrainPhys.TerrainImplementation.Mesh, | ||||
|             (s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); }, | ||||
|             (s) => { return TerrainImplementation; }, | ||||
|             (s,p,l,v) => { TerrainImplementation = v; } ), | ||||
|         new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , | ||||
|             0.3f, | ||||
|             (s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return TerrainFriction; }, | ||||
|             (s,p,l,v) => { TerrainFriction = v;  /* TODO: set on real terrain */} ), | ||||
|         new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , | ||||
|             0.8f, | ||||
|             (s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return TerrainHitFraction; }, | ||||
|             (s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ), | ||||
|         new ParameterDefn("TerrainRestitution", "Bouncyness" , | ||||
|             0f, | ||||
|             (s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); }, | ||||
|             (s) => { return TerrainRestitution; }, | ||||
|             (s,p,l,v) => { TerrainRestitution = v;  /* TODO: set on real terrain */ } ), | ||||
|         new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" , | ||||
|             0.04f, | ||||
|             (s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); }, | ||||
|             (s) => { return TerrainCollisionMargin; }, | ||||
|             (s,p,l,v) => { TerrainCollisionMargin = v;  /* TODO: set on real terrain */ } ), | ||||
| 
 | ||||
|         new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", | ||||
|             0.2f, | ||||
|             (s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AvatarFriction; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarFriction=x;}, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", | ||||
|             10.0f, | ||||
|             (s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AvatarStandingFriction; }, | ||||
|             (s,p,l,v) => { AvatarStandingFriction = v; } ), | ||||
|         new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", | ||||
|             60f, | ||||
|             (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AvatarDensity; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AvatarRestitution; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarRestitution=x;}, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", | ||||
|             0.6f, | ||||
|             (s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AvatarCapsuleWidth; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleWidth=x;}, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", | ||||
|             0.45f, | ||||
|             (s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AvatarCapsuleDepth; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleDepth=x;}, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", | ||||
|             1.5f, | ||||
|             (s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AvatarCapsuleHeight; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleHeight=x;}, p, l, v); } ), | ||||
| 	    new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return AvatarContactProcessingThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ), | ||||
| 
 | ||||
|         new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", | ||||
|             0.95f, | ||||
|             (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); }, | ||||
|             (s) => { return VehicleAngularDamping; }, | ||||
|             (s,p,l,v) => { VehicleAngularDamping = v; } ), | ||||
| 
 | ||||
| 	    new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.UnmanagedParams[0].maxPersistantManifoldPoolSize; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ), | ||||
| 	    new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ), | ||||
| 	    new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, | ||||
|             (s) => { return s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ), | ||||
| 	    new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, | ||||
|             (s) => { return s.UnmanagedParams[0].shouldForceUpdateAllAabbs; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ), | ||||
| 	    new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, | ||||
|             (s) => { return s.UnmanagedParams[0].shouldRandomizeSolverOrder; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ), | ||||
| 	    new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, | ||||
|             (s) => { return s.UnmanagedParams[0].shouldSplitSimulationIslands; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ), | ||||
| 	    new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, | ||||
|             (s) => { return s.UnmanagedParams[0].shouldEnableFrictionCaching; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ), | ||||
| 	    new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)", | ||||
|             0f,     // zero says use Bullet default | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].numberOfSolverIterations = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.UnmanagedParams[0].numberOfSolverIterations; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].numberOfSolverIterations = v; } ), | ||||
| 
 | ||||
| 	    new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", | ||||
|             (float)BSLinkset.LinksetImplementation.Compound, | ||||
|             (s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); }, | ||||
|             (s) => { return LinksetImplementation; }, | ||||
|             (s,p,l,v) => { LinksetImplementation = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, | ||||
|             (s) => { return LinkConstraintUseFrameOffset; }, | ||||
|             (s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, | ||||
|             (s) => { return LinkConstraintEnableTransMotor; }, | ||||
|             (s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", | ||||
|             5.0f, | ||||
|             (s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); }, | ||||
|             (s) => { return LinkConstraintTransMotorMaxVel; }, | ||||
|             (s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, | ||||
|             (s) => { return LinkConstraintTransMotorMaxForce; }, | ||||
|             (s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); }, | ||||
|             (s) => { return LinkConstraintCFM; }, | ||||
|             (s,p,l,v) => { LinkConstraintCFM = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); }, | ||||
|             (s) => { return LinkConstraintERP; }, | ||||
|             (s,p,l,v) => { LinkConstraintERP = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", | ||||
|             40, | ||||
|             (s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); }, | ||||
|             (s) => { return LinkConstraintSolverIterations; }, | ||||
|             (s,p,l,v) => { LinkConstraintSolverIterations = v; } ), | ||||
| 
 | ||||
|         new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.UnmanagedParams[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.UnmanagedParams[0].physicsLoggingFrames; }, | ||||
|             (s,p,l,v) => { s.UnmanagedParams[0].physicsLoggingFrames = (int)v; } ), | ||||
|     }; | ||||
| 
 | ||||
|     // Convert a boolean to our numeric true and false values | ||||
|     public static float NumericBool(bool b) | ||||
|     { | ||||
|         return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse); | ||||
|     } | ||||
| 
 | ||||
|     // Convert numeric true and false values to a boolean | ||||
|     public static bool BoolNumeric(float b) | ||||
|     { | ||||
|         return (b == ConfigurationParameters.numericTrue ? true : false); | ||||
|     } | ||||
| 
 | ||||
|     // Search through the parameter definitions and return the matching | ||||
|     //    ParameterDefn structure. | ||||
|     // Case does not matter as names are compared after converting to lower case. | ||||
|     // Returns 'false' if the parameter is not found. | ||||
|     internal static bool TryGetParameter(string paramName, out ParameterDefn defn) | ||||
|     { | ||||
|         bool ret = false; | ||||
|         ParameterDefn foundDefn = new ParameterDefn(); | ||||
|         string pName = paramName.ToLower(); | ||||
| 
 | ||||
|         foreach (ParameterDefn parm in ParameterDefinitions) | ||||
|         { | ||||
|             if (pName == parm.name.ToLower()) | ||||
|             { | ||||
|                 foundDefn = parm; | ||||
|                 ret = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         defn = foundDefn; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     // Pass through the settable parameters and set the default values | ||||
|     internal static void SetParameterDefaultValues(BSScene physicsScene) | ||||
|     { | ||||
|         foreach (ParameterDefn parm in ParameterDefinitions) | ||||
|         { | ||||
|             parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Get user set values out of the ini file. | ||||
|     internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg) | ||||
|     { | ||||
|         foreach (ParameterDefn parm in ParameterDefinitions) | ||||
|         { | ||||
|             parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     internal static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; | ||||
| 
 | ||||
|     // This creates an array in the correct format for returning the list of | ||||
|     //    parameters. This is used by the 'list' option of the 'physics' command. | ||||
|     internal static void BuildParameterTable() | ||||
|     { | ||||
|         if (SettableParameters.Length < ParameterDefinitions.Length) | ||||
|         { | ||||
|             List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); | ||||
|             for (int ii = 0; ii < ParameterDefinitions.Length; ii++) | ||||
|             { | ||||
|                 ParameterDefn pd = ParameterDefinitions[ii]; | ||||
|                 entries.Add(new PhysParameterEntry(pd.name, pd.desc)); | ||||
|             } | ||||
| 
 | ||||
|             // make the list in alphabetical order for estetic reasons | ||||
|             entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2) | ||||
|             { | ||||
|                 return ppe1.name.CompareTo(ppe2.name); | ||||
|             }); | ||||
| 
 | ||||
|             SettableParameters = entries.ToArray(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| } | ||||
|  | @ -720,10 +720,10 @@ public sealed class BSPrim : BSPhysObject | |||
|             // Mass is zero which disables a bunch of physics stuff in Bullet | ||||
|             UpdatePhysicalMassProperties(0f); | ||||
|             // Set collision detection parameters | ||||
|             if (PhysicsScene.Params.ccdMotionThreshold > 0f) | ||||
|             if (BSParam.CcdMotionThreshold > 0f) | ||||
|             { | ||||
|                 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | ||||
|                 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | ||||
|                 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold); | ||||
|                 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius); | ||||
|             } | ||||
| 
 | ||||
|             // The activation state is 'disabled' so Bullet will not try to act on it. | ||||
|  | @ -761,17 +761,17 @@ public sealed class BSPrim : BSPhysObject | |||
|             UpdatePhysicalMassProperties(RawMass); | ||||
| 
 | ||||
|             // Set collision detection parameters | ||||
|             if (PhysicsScene.Params.ccdMotionThreshold > 0f) | ||||
|             if (BSParam.CcdMotionThreshold > 0f) | ||||
|             { | ||||
|                 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | ||||
|                 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | ||||
|                 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold); | ||||
|                 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius); | ||||
|             } | ||||
| 
 | ||||
|             // Various values for simulation limits | ||||
|             BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); | ||||
|             BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime); | ||||
|             BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); | ||||
|             BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | ||||
|             BulletSimAPI.SetDamping2(PhysBody.ptr, BSParam.LinearDamping, BSParam.AngularDamping); | ||||
|             BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, BSParam.DeactivationTime); | ||||
|             BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); | ||||
|             BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, BSParam.ContactProcessingThreshold); | ||||
| 
 | ||||
|             // This collides like an object. | ||||
|             PhysBody.collisionType = CollisionType.Dynamic; | ||||
|  | @ -1361,11 +1361,7 @@ public sealed class BSPrim : BSPhysObject | |||
|         } | ||||
|          */ | ||||
| 
 | ||||
|         if (returnMass <= 0) | ||||
|             returnMass = 0.0001f; | ||||
| 
 | ||||
|         if (returnMass > PhysicsScene.MaximumObjectMass) | ||||
|             returnMass = PhysicsScene.MaximumObjectMass; | ||||
|         returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); | ||||
| 
 | ||||
|         return returnMass; | ||||
|     }// end CalculateMass | ||||
|  |  | |||
|  | @ -77,12 +77,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|     public ILog Logger { get { return m_log; } } | ||||
| 
 | ||||
|     public IMesher mesher; | ||||
|     // Level of Detail values kept as float because that's what the Meshmerizer wants | ||||
|     public float MeshLOD { get; private set; } | ||||
|     public float MeshMegaPrimLOD { get; private set; } | ||||
|     public float MeshMegaPrimThreshold { get; private set; } | ||||
|     public float SculptLOD { get; private set; } | ||||
| 
 | ||||
|     public uint WorldID { get; private set; } | ||||
|     public BulletSim World { get; private set; } | ||||
| 
 | ||||
|  | @ -90,21 +84,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|     public BSConstraintCollection Constraints { get; private set; } | ||||
| 
 | ||||
|     // Simulation parameters | ||||
|     private int m_maxSubSteps; | ||||
|     private float m_fixedTimeStep; | ||||
|     private long m_simulationStep = 0; | ||||
|     internal int m_maxSubSteps; | ||||
|     internal float m_fixedTimeStep; | ||||
|     internal long m_simulationStep = 0; | ||||
|     public long SimulationStep { get { return m_simulationStep; } } | ||||
|     private int m_taintsToProcessPerStep; | ||||
| 
 | ||||
|     // Avatar parameters | ||||
|     public float ParamAvatarFriction { get; private set; } | ||||
|     public float ParamAvatarStandingFriction { get; private set; } | ||||
|     public float ParamAvatarDensity { get; private set; } | ||||
|     public float ParamAvatarRestitution { get; private set; } | ||||
|     public float ParamAvatarCapsuleWidth { get; private set; } | ||||
|     public float ParamAvatarCapsuleDepth { get; private set; } | ||||
|     public float ParamAvatarCapsuleHeight { get; private set; } | ||||
| 	public float ParamAvatarContactProcessingThreshold { get; private set; } | ||||
|     internal int m_taintsToProcessPerStep; | ||||
| 
 | ||||
|     public delegate void PreStepAction(float timeStep); | ||||
|     public event PreStepAction BeforeStep; | ||||
|  | @ -121,20 +105,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|     public bool InTaintTime { get; private set; } | ||||
| 
 | ||||
|     // Pinned memory used to pass step information between managed and unmanaged | ||||
|     private int m_maxCollisionsPerFrame; | ||||
|     private CollisionDesc[] m_collisionArray; | ||||
|     private GCHandle m_collisionArrayPinnedHandle; | ||||
|     internal int m_maxCollisionsPerFrame; | ||||
|     internal CollisionDesc[] m_collisionArray; | ||||
|     internal GCHandle m_collisionArrayPinnedHandle; | ||||
| 
 | ||||
|     private int m_maxUpdatesPerFrame; | ||||
|     private EntityProperties[] m_updateArray; | ||||
|     private GCHandle m_updateArrayPinnedHandle; | ||||
| 
 | ||||
|     public bool ShouldMeshSculptedPrim { get; private set; }   // cause scuplted prims to get meshed | ||||
|     public bool ShouldForceSimplePrimMeshing { get; private set; }   // if a cube or sphere, let Bullet do internal shapes | ||||
|     public bool ShouldUseHullsForPhysicalObjects { get; private set; }   // 'true' if should create hulls for physical objects | ||||
| 
 | ||||
|     public float PID_D { get; private set; }    // derivative | ||||
|     public float PID_P { get; private set; }    // proportional | ||||
|     internal int m_maxUpdatesPerFrame; | ||||
|     internal EntityProperties[] m_updateArray; | ||||
|     internal GCHandle m_updateArrayPinnedHandle; | ||||
| 
 | ||||
|     public const uint TERRAIN_ID = 0;       // OpenSim senses terrain with a localID of zero | ||||
|     public const uint GROUNDPLANE_ID = 1; | ||||
|  | @ -145,7 +122,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
| 
 | ||||
|     public ConfigurationParameters Params | ||||
|     { | ||||
|         get { return m_params[0]; } | ||||
|         get { return UnmanagedParams[0]; } | ||||
|     } | ||||
|     public Vector3 DefaultGravity | ||||
|     { | ||||
|  | @ -157,8 +134,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|         get { return Params.gravity; } | ||||
|     } | ||||
| 
 | ||||
|     public float MaximumObjectMass { get; private set; } | ||||
| 
 | ||||
|     // When functions in the unmanaged code must be called, it is only | ||||
|     //   done at a known time just before the simulation step. The taint | ||||
|     //   system saves all these function calls and executes them in | ||||
|  | @ -181,7 +156,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
| 
 | ||||
|     // A pointer to an instance if this structure is passed to the C++ code | ||||
|     // Used to pass basic configuration values to the unmanaged code. | ||||
|     ConfigurationParameters[] m_params; | ||||
|     internal ConfigurationParameters[] UnmanagedParams; | ||||
|     GCHandle m_paramsHandle; | ||||
| 
 | ||||
|     // 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 | |||
|         Shapes = new BSShapeCollection(this); | ||||
| 
 | ||||
|         // Allocate pinned memory to pass parameters. | ||||
|         m_params = new ConfigurationParameters[1]; | ||||
|         m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); | ||||
|         UnmanagedParams = new ConfigurationParameters[1]; | ||||
|         m_paramsHandle = GCHandle.Alloc(UnmanagedParams, GCHandleType.Pinned); | ||||
| 
 | ||||
|         // Set default values for physics parameters plus any overrides from the ini file | ||||
|         GetInitialParameterValues(config); | ||||
|  | @ -277,7 +252,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|         TerrainManager = new BSTerrainManager(this); | ||||
|         TerrainManager.CreateInitialGroundPlaneAndTerrain(); | ||||
| 
 | ||||
|         m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); | ||||
|         m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation); | ||||
| 
 | ||||
|         InTaintTime = false; | ||||
|         m_initialized = true; | ||||
|  | @ -288,9 +263,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|     private void GetInitialParameterValues(IConfigSource config) | ||||
|     { | ||||
|         ConfigurationParameters parms = new ConfigurationParameters(); | ||||
|         m_params[0] = parms; | ||||
|         UnmanagedParams[0] = parms; | ||||
| 
 | ||||
|         SetParameterDefaultValues(); | ||||
|         BSParam.SetParameterDefaultValues(this); | ||||
| 
 | ||||
|         if (config != null) | ||||
|         { | ||||
|  | @ -298,7 +273,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|             IConfig pConfig = config.Configs["BulletSim"]; | ||||
|             if (pConfig != null) | ||||
|             { | ||||
|                 SetParameterConfigurationValues(pConfig); | ||||
|                 BSParam.SetParameterConfigurationValues(this, pConfig); | ||||
| 
 | ||||
|                 // Very detailed logging for physics debugging | ||||
|                 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); | ||||
|  | @ -889,7 +864,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|         { | ||||
|             DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); | ||||
|             m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); | ||||
|             Util.PrintCallStack();  // Prints the stack into the DEBUG log file. | ||||
|             Util.PrintCallStack(DetailLog);  // Prints the stack into the DEBUG log file. | ||||
|         } | ||||
|         return InTaintTime; | ||||
|     } | ||||
|  | @ -936,12 +911,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
| 
 | ||||
|     private void DoPreStepActions(float timeStep) | ||||
|     { | ||||
|         InTaintTime = true; // Only used for debugging so locking is not necessary. | ||||
|         ProcessVehicles(timeStep); | ||||
| 
 | ||||
|         PreStepAction actions = BeforeStep; | ||||
|         if (actions != null) | ||||
|             actions(timeStep); | ||||
| 
 | ||||
|         InTaintTime = false; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     // Some prims have extra vehicle actions | ||||
|  | @ -957,472 +935,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
| 
 | ||||
|     #region INI and command line parameter processing | ||||
| 
 | ||||
|     delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); | ||||
|     delegate float ParamGet(BSScene scene); | ||||
|     delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); | ||||
|     delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); | ||||
| 
 | ||||
|     private struct ParameterDefn | ||||
|     { | ||||
|         public string name;         // string name of the parameter | ||||
|         public string desc;         // a short description of what the parameter means | ||||
|         public float defaultValue;  // default value if not specified anywhere else | ||||
|         public ParamUser userParam; // get the value from the configuration file | ||||
|         public ParamGet getter;     // return the current value stored for this parameter | ||||
|         public ParamSet setter;     // set the current value for this parameter | ||||
|         public SetOnObject onObject;    // set the value on an object in the physical domain | ||||
|         public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) | ||||
|         { | ||||
|             name = n; | ||||
|             desc = d; | ||||
|             defaultValue = v; | ||||
|             userParam = u; | ||||
|             getter = g; | ||||
|             setter = s; | ||||
|             onObject = null; | ||||
|         } | ||||
|         public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) | ||||
|         { | ||||
|             name = n; | ||||
|             desc = d; | ||||
|             defaultValue = v; | ||||
|             userParam = u; | ||||
|             getter = g; | ||||
|             setter = s; | ||||
|             onObject = o; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // List of all of the externally visible parameters. | ||||
|     // For each parameter, this table maps a text name to getter and setters. | ||||
|     // To add a new externally referencable/settable parameter, add the paramter storage | ||||
|     //    location somewhere in the program and make an entry in this table with the | ||||
|     //    getters and setters. | ||||
|     // It is easiest to find an existing definition and copy it. | ||||
|     // Parameter values are floats. Booleans are converted to a floating value. | ||||
|     // | ||||
|     // A ParameterDefn() takes the following parameters: | ||||
|     //    -- the text name of the parameter. This is used for console input and ini file. | ||||
|     //    -- a short text description of the parameter. This shows up in the console listing. | ||||
|     //    -- a delegate for fetching the parameter from the ini file. | ||||
|     //          Should handle fetching the right type from the ini file and converting it. | ||||
|     //    -- a delegate for getting the value as a float | ||||
|     //    -- a delegate for setting the value from a float | ||||
|     //    -- an optional delegate to update the value in the world. Most often used to | ||||
|     //          push the new value to an in-world object. | ||||
|     // | ||||
|     // The single letter parameters for the delegates are: | ||||
|     //    s = BSScene | ||||
|     //    o = BSPhysObject | ||||
|     //    p = string parameter name | ||||
|     //    l = localID of referenced object | ||||
|     //    v = float value | ||||
|     //    cf = parameter configuration class (for fetching values from ini file) | ||||
|     private ParameterDefn[] ParameterDefinitions = | ||||
|     { | ||||
|         new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, | ||||
|             (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); }, | ||||
|             (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ), | ||||
|         new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, | ||||
|             (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, | ||||
|             (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), | ||||
|         new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, | ||||
|             (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, | ||||
|             (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), | ||||
| 
 | ||||
|         new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", | ||||
|             8f, | ||||
|             (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return s.MeshLOD; }, | ||||
|             (s,p,l,v) => { s.MeshLOD = v; } ), | ||||
|         new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", | ||||
|             16f, | ||||
|             (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return s.MeshMegaPrimLOD; }, | ||||
|             (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ), | ||||
|         new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", | ||||
|             10f, | ||||
|             (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return s.MeshMegaPrimThreshold; }, | ||||
|             (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ), | ||||
|         new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", | ||||
|             32f, | ||||
|             (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return s.SculptLOD; }, | ||||
|             (s,p,l,v) => { s.SculptLOD = v; } ), | ||||
| 
 | ||||
|         new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", | ||||
|             10f, | ||||
|             (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_maxSubSteps; }, | ||||
|             (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ), | ||||
|         new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)", | ||||
|             1f / 60f, | ||||
|             (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)s.m_fixedTimeStep; }, | ||||
|             (s,p,l,v) => { s.m_fixedTimeStep = v; } ), | ||||
|         new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", | ||||
|             2048f, | ||||
|             (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_maxCollisionsPerFrame; }, | ||||
|             (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ), | ||||
|         new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame", | ||||
|             8000f, | ||||
|             (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_maxUpdatesPerFrame; }, | ||||
|             (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), | ||||
|         new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", | ||||
|             500f, | ||||
|             (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_taintsToProcessPerStep; }, | ||||
|             (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), | ||||
|         new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", | ||||
|             10000.01f, | ||||
|             (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)s.MaximumObjectMass; }, | ||||
|             (s,p,l,v) => { s.MaximumObjectMass = v; } ), | ||||
| 
 | ||||
|         new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", | ||||
|             2200f, | ||||
|             (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)s.PID_D; }, | ||||
|             (s,p,l,v) => { s.PID_D = v; } ), | ||||
|         new ParameterDefn("PID_P", "Parameteric factor for motion smoothing", | ||||
|             900f, | ||||
|             (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); }, | ||||
|             (s) => { return (float)s.PID_P; }, | ||||
|             (s,p,l,v) => { s.PID_P = v; } ), | ||||
| 
 | ||||
|         new ParameterDefn("DefaultFriction", "Friction factor used on new objects", | ||||
|             0.2f, | ||||
|             (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].defaultFriction; }, | ||||
|             (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ), | ||||
|         new ParameterDefn("DefaultDensity", "Density for new objects" , | ||||
|             10.000006836f,  // Aluminum g/cm3 | ||||
|             (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].defaultDensity; }, | ||||
|             (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ), | ||||
|         new ParameterDefn("DefaultRestitution", "Bouncyness of an object" , | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].defaultRestitution; }, | ||||
|             (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ), | ||||
|         new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", | ||||
|             0.04f, | ||||
|             (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].collisionMargin; }, | ||||
|             (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ), | ||||
|         new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)", | ||||
|             -9.80665f, | ||||
|             (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].gravity; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), | ||||
| 
 | ||||
| 
 | ||||
|         new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].linearDamping; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, s.m_params[0].angularDamping); } ), | ||||
|         new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].angularDamping; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, s.m_params[0].linearDamping, v); } ), | ||||
|         new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", | ||||
|             0.2f, | ||||
|             (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].deactivationTime; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ), | ||||
|         new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", | ||||
|             0.8f, | ||||
|             (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].linearSleepingThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), | ||||
|         new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", | ||||
|             1.0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].angularSleepingThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), | ||||
|         new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , | ||||
|             0f,     // set to zero to disable | ||||
|             (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].ccdMotionThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ), | ||||
|         new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].ccdSweptSphereRadius; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ), | ||||
|         new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].contactProcessingThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, | ||||
|             (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), | ||||
| 
 | ||||
| 	    new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", | ||||
|             (float)BSTerrainPhys.TerrainImplementation.Mesh, | ||||
|             (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); }, | ||||
|             (s) => { return s.m_params[0].terrainImplementation; }, | ||||
|             (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ), | ||||
|         new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , | ||||
|             0.3f, | ||||
|             (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].terrainFriction; }, | ||||
|             (s,p,l,v) => { s.m_params[0].terrainFriction = v;  /* TODO: set on real terrain */} ), | ||||
|         new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , | ||||
|             0.8f, | ||||
|             (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].terrainHitFraction; }, | ||||
|             (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ), | ||||
|         new ParameterDefn("TerrainRestitution", "Bouncyness" , | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].terrainRestitution; }, | ||||
|             (s,p,l,v) => { s.m_params[0].terrainRestitution = v;  /* TODO: set on real terrain */ } ), | ||||
|         new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" , | ||||
|             0.04f, | ||||
|             (s,cf,p,v) => { s.m_params[0].terrainCollisionMargin = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].terrainCollisionMargin; }, | ||||
|             (s,p,l,v) => { s.m_params[0].terrainCollisionMargin = v;  /* TODO: set on real terrain */ } ), | ||||
| 
 | ||||
|         new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", | ||||
|             0.2f, | ||||
|             (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].avatarFriction; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", | ||||
|             10.0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].avatarStandingFriction; }, | ||||
|             (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), | ||||
|         new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", | ||||
|             60f, | ||||
|             (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].avatarDensity; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].avatarRestitution; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", | ||||
|             0.6f, | ||||
|             (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].avatarCapsuleWidth; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", | ||||
|             0.45f, | ||||
|             (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].avatarCapsuleDepth; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ), | ||||
|         new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", | ||||
|             1.5f, | ||||
|             (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].avatarCapsuleHeight; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), | ||||
| 	    new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, | ||||
|             (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), | ||||
| 
 | ||||
|         new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", | ||||
|             0.95f, | ||||
|             (s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].vehicleAngularDamping; }, | ||||
|             (s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ), | ||||
| 
 | ||||
| 	    new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, | ||||
|             (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), | ||||
| 	    new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, | ||||
|             (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), | ||||
| 	    new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||||
|             (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; }, | ||||
|             (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ), | ||||
| 	    new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||||
|             (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, | ||||
|             (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), | ||||
| 	    new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||||
|             (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, | ||||
|             (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), | ||||
| 	    new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||||
|             (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, | ||||
|             (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), | ||||
| 	    new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||||
|             (s) => { return s.m_params[0].shouldEnableFrictionCaching; }, | ||||
|             (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ), | ||||
| 	    new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)", | ||||
|             0f,     // zero says use Bullet default | ||||
|             (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].numberOfSolverIterations; }, | ||||
|             (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), | ||||
| 
 | ||||
| 	    new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", | ||||
|             (float)BSLinkset.LinksetImplementation.Compound, | ||||
|             (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, | ||||
|             (s) => { return s.m_params[0].linksetImplementation; }, | ||||
|             (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", | ||||
|             ConfigurationParameters.numericFalse, | ||||
|             (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||||
|             (s) => { return s.m_params[0].linkConstraintUseFrameOffset; }, | ||||
|             (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", | ||||
|             ConfigurationParameters.numericTrue, | ||||
|             (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||||
|             (s) => { return s.m_params[0].linkConstraintEnableTransMotor; }, | ||||
|             (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", | ||||
|             5.0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; }, | ||||
|             (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, | ||||
|             (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].linkConstraintCFM; }, | ||||
|             (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", | ||||
|             0.1f, | ||||
|             (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].linkConstraintERP; }, | ||||
|             (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), | ||||
| 	    new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", | ||||
|             40, | ||||
|             (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); }, | ||||
|             (s) => { return s.m_params[0].linkConstraintSolverIterations; }, | ||||
|             (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), | ||||
| 
 | ||||
|         new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", | ||||
|             0f, | ||||
|             (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, | ||||
|             (s) => { return (float)s.m_params[0].physicsLoggingFrames; }, | ||||
|             (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ), | ||||
|     }; | ||||
| 
 | ||||
|     // Convert a boolean to our numeric true and false values | ||||
|     public float NumericBool(bool b) | ||||
|     { | ||||
|         return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse); | ||||
|     } | ||||
| 
 | ||||
|     // Convert numeric true and false values to a boolean | ||||
|     public bool BoolNumeric(float b) | ||||
|     { | ||||
|         return (b == ConfigurationParameters.numericTrue ? true : false); | ||||
|     } | ||||
| 
 | ||||
|     // Search through the parameter definitions and return the matching | ||||
|     //    ParameterDefn structure. | ||||
|     // Case does not matter as names are compared after converting to lower case. | ||||
|     // Returns 'false' if the parameter is not found. | ||||
|     private bool TryGetParameter(string paramName, out ParameterDefn defn) | ||||
|     { | ||||
|         bool ret = false; | ||||
|         ParameterDefn foundDefn = new ParameterDefn(); | ||||
|         string pName = paramName.ToLower(); | ||||
| 
 | ||||
|         foreach (ParameterDefn parm in ParameterDefinitions) | ||||
|         { | ||||
|             if (pName == parm.name.ToLower()) | ||||
|             { | ||||
|                 foundDefn = parm; | ||||
|                 ret = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         defn = foundDefn; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     // Pass through the settable parameters and set the default values | ||||
|     private void SetParameterDefaultValues() | ||||
|     { | ||||
|         foreach (ParameterDefn parm in ParameterDefinitions) | ||||
|         { | ||||
|             parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Get user set values out of the ini file. | ||||
|     private void SetParameterConfigurationValues(IConfig cfg) | ||||
|     { | ||||
|         foreach (ParameterDefn parm in ParameterDefinitions) | ||||
|         { | ||||
|             parm.userParam(this, cfg, parm.name, parm.defaultValue); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; | ||||
| 
 | ||||
|     // This creates an array in the correct format for returning the list of | ||||
|     //    parameters. This is used by the 'list' option of the 'physics' command. | ||||
|     private void BuildParameterTable() | ||||
|     { | ||||
|         if (SettableParameters.Length < ParameterDefinitions.Length) | ||||
|         { | ||||
|             List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); | ||||
|             for (int ii = 0; ii < ParameterDefinitions.Length; ii++) | ||||
|             { | ||||
|                 ParameterDefn pd = ParameterDefinitions[ii]; | ||||
|                 entries.Add(new PhysParameterEntry(pd.name, pd.desc)); | ||||
|             } | ||||
| 
 | ||||
|             // make the list in alphabetical order for estetic reasons | ||||
|             entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2) | ||||
|             { | ||||
|                 return ppe1.name.CompareTo(ppe2.name); | ||||
|             }); | ||||
| 
 | ||||
|             SettableParameters = entries.ToArray(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     #region IPhysicsParameters | ||||
|     // Get the list of parameters this physics engine supports | ||||
|     public PhysParameterEntry[] GetParameterList() | ||||
|     { | ||||
|         BuildParameterTable(); | ||||
|         return SettableParameters; | ||||
|         BSParam.BuildParameterTable(); | ||||
|         return BSParam.SettableParameters; | ||||
|     } | ||||
| 
 | ||||
|     // Set parameter on a specific or all instances. | ||||
|  | @ -1434,8 +952,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|     public bool SetPhysicsParameter(string parm, float val, uint localID) | ||||
|     { | ||||
|         bool ret = false; | ||||
|         ParameterDefn theParam; | ||||
|         if (TryGetParameter(parm, out theParam)) | ||||
|         BSParam.ParameterDefn theParam; | ||||
|         if (BSParam.TryGetParameter(parm, out theParam)) | ||||
|         { | ||||
|             theParam.setter(this, parm, localID, val); | ||||
|             ret = true; | ||||
|  | @ -1447,19 +965,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|     // If the local ID is APPLY_TO_NONE, just change the default value | ||||
|     // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs | ||||
|     // If the localID is a specific object, apply the parameter change to only that object | ||||
|     private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) | ||||
|     internal delegate void AssignVal(float x); | ||||
|     internal void UpdateParameterObject(AssignVal setDefault, string parm, uint localID, float val) | ||||
|     { | ||||
|         List<uint> objectIDs = new List<uint>(); | ||||
|         switch (localID) | ||||
|         { | ||||
|             case PhysParameterEntry.APPLY_TO_NONE: | ||||
|                 defaultLoc = val;   // setting only the default value | ||||
|                 setDefault(val);            // setting only the default value | ||||
|                 // This will cause a call into the physical world if some operation is specified (SetOnObject). | ||||
|                 objectIDs.Add(TERRAIN_ID); | ||||
|                 TaintedUpdateParameter(parm, objectIDs, val); | ||||
|                 break; | ||||
|             case PhysParameterEntry.APPLY_TO_ALL: | ||||
|                 defaultLoc = val;  // setting ALL also sets the default value | ||||
|                 setDefault(val);  // setting ALL also sets the default value | ||||
|                 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); | ||||
|                 TaintedUpdateParameter(parm, objectIDs, val); | ||||
|                 break; | ||||
|  | @ -1478,8 +997,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|         List<uint> xlIDs = lIDs; | ||||
|         string xparm = parm; | ||||
|         TaintedObject("BSScene.UpdateParameterSet", delegate() { | ||||
|             ParameterDefn thisParam; | ||||
|             if (TryGetParameter(xparm, out thisParam)) | ||||
|             BSParam.ParameterDefn thisParam; | ||||
|             if (BSParam.TryGetParameter(xparm, out thisParam)) | ||||
|             { | ||||
|                 if (thisParam.onObject != null) | ||||
|                 { | ||||
|  | @ -1500,8 +1019,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
|     { | ||||
|         float val = 0f; | ||||
|         bool ret = false; | ||||
|         ParameterDefn theParam; | ||||
|         if (TryGetParameter(parm, out theParam)) | ||||
|         BSParam.ParameterDefn theParam; | ||||
|         if (BSParam.TryGetParameter(parm, out theParam)) | ||||
|         { | ||||
|             val = theParam.getter(this); | ||||
|             ret = true; | ||||
|  |  | |||
|  | @ -456,7 +456,7 @@ public sealed class BSShapeCollection : IDisposable | |||
|         if (!haveShape | ||||
|                 && pbs != null | ||||
|                 && nativeShapePossible | ||||
|                 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) | ||||
|                 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) | ||||
|                     || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 | ||||
|                         && pbs.ProfileHollow == 0 | ||||
|                         && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 | ||||
|  | @ -520,7 +520,7 @@ public sealed class BSShapeCollection : IDisposable | |||
|         bool ret = false; | ||||
|         // Note that if it's a native shape, the check for physical/non-physical is not | ||||
|         //     made. Native shapes work in either case. | ||||
|         if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) | ||||
|         if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) | ||||
|         { | ||||
|             // Update prim.BSShape to reference a hull of this shape. | ||||
|             ret = GetReferenceToHull(prim,shapeCallback); | ||||
|  | @ -836,14 +836,14 @@ public sealed class BSShapeCollection : IDisposable | |||
|     private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | ||||
|     { | ||||
|         // level of detail based on size and type of the object | ||||
|         float lod = PhysicsScene.MeshLOD; | ||||
|         float lod = BSParam.MeshLOD; | ||||
|         if (pbs.SculptEntry) | ||||
|             lod = PhysicsScene.SculptLOD; | ||||
|             lod = BSParam.SculptLOD; | ||||
| 
 | ||||
|         // Mega prims usually get more detail because one can interact with shape approximations at this size. | ||||
|         float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); | ||||
|         if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) | ||||
|             lod = PhysicsScene.MeshMegaPrimLOD; | ||||
|         if (maxAxis > BSParam.MeshMegaPrimThreshold) | ||||
|             lod = BSParam.MeshMegaPrimLOD; | ||||
| 
 | ||||
|         retLod = lod; | ||||
|         return pbs.GetMeshKey(size, lod); | ||||
|  |  | |||
|  | @ -93,7 +93,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys | |||
|     { | ||||
|         m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, | ||||
|                                 m_mapInfo.minCoords, m_mapInfo.maxCoords,  | ||||
|                                 m_mapInfo.heightMap, PhysicsScene.Params.terrainCollisionMargin); | ||||
|                                 m_mapInfo.heightMap, BSParam.TerrainCollisionMargin); | ||||
| 
 | ||||
|         // Create the terrain shape from the mapInfo | ||||
|         m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), | ||||
|  | @ -110,9 +110,9 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys | |||
|                                             m_mapInfo.ID, centerPos, Quaternion.Identity)); | ||||
| 
 | ||||
|         // Set current terrain attributes | ||||
|         BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); | ||||
|         BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); | ||||
|         BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); | ||||
|         BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, BSParam.TerrainFriction); | ||||
|         BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, BSParam.TerrainHitFraction); | ||||
|         BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, BSParam.TerrainRestitution); | ||||
|         BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | ||||
| 
 | ||||
|         // Return the new terrain to the world of physical objects | ||||
|  |  | |||
|  | @ -135,7 +135,7 @@ public sealed class BSTerrainManager : IDisposable | |||
|         // The ground plane is here to catch things that are trying to drop to negative infinity | ||||
|         BulletShape groundPlaneShape = new BulletShape( | ||||
|                     BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f,  | ||||
|                                     PhysicsScene.Params.terrainCollisionMargin), | ||||
|                                     BSParam.TerrainCollisionMargin), | ||||
|                     BSPhysicsShapeType.SHAPE_GROUNDPLANE); | ||||
|         m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, | ||||
|                         BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, | ||||
|  | @ -309,9 +309,9 @@ public sealed class BSTerrainManager : IDisposable | |||
|     { | ||||
|         PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",  | ||||
|                                             LogHeader, PhysicsScene.RegionName, terrainRegionBase,  | ||||
|                                             (BSTerrainPhys.TerrainImplementation)PhysicsScene.Params.terrainImplementation); | ||||
|                                             (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); | ||||
|         BSTerrainPhys newTerrainPhys = null; | ||||
|         switch ((int)PhysicsScene.Params.terrainImplementation) | ||||
|         switch ((int)BSParam.TerrainImplementation) | ||||
|         { | ||||
|             case (int)BSTerrainPhys.TerrainImplementation.Heightmap: | ||||
|                 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, | ||||
|  | @ -324,8 +324,8 @@ public sealed class BSTerrainManager : IDisposable | |||
|             default: | ||||
|                 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", | ||||
|                                             LogHeader,  | ||||
|                                             (int)PhysicsScene.Params.terrainImplementation,  | ||||
|                                             PhysicsScene.Params.terrainImplementation, | ||||
|                                             (int)BSParam.TerrainImplementation,  | ||||
|                                             BSParam.TerrainImplementation, | ||||
|                                             PhysicsScene.RegionName, terrainRegionBase); | ||||
|                 break; | ||||
|         } | ||||
|  |  | |||
|  | @ -116,9 +116,9 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
|         } | ||||
| 
 | ||||
|         // Set current terrain attributes | ||||
|         BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); | ||||
|         BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); | ||||
|         BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); | ||||
|         BulletSimAPI.SetFriction2(m_terrainBody.ptr, BSParam.TerrainFriction); | ||||
|         BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, BSParam.TerrainHitFraction); | ||||
|         BulletSimAPI.SetRestitution2(m_terrainBody.ptr, BSParam.TerrainRestitution); | ||||
|         BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | ||||
| 
 | ||||
|         // Static objects are not very massive. | ||||
|  |  | |||
|  | @ -141,6 +141,8 @@ public struct EntityProperties | |||
| } | ||||
| 
 | ||||
| // Format of this structure must match the definition in the C++ code | ||||
| // NOTE: adding the X causes compile breaks if used. These are unused symbols | ||||
| //      that can be removed from both here and the unmanaged definition of this structure. | ||||
| [StructLayout(LayoutKind.Sequential)] | ||||
| public struct ConfigurationParameters | ||||
| { | ||||
|  | @ -150,31 +152,31 @@ public struct ConfigurationParameters | |||
|     public float collisionMargin; | ||||
|     public float gravity; | ||||
| 
 | ||||
|     public float linearDamping; | ||||
|     public float angularDamping; | ||||
|     public float deactivationTime; | ||||
|     public float linearSleepingThreshold; | ||||
|     public float angularSleepingThreshold; | ||||
| 	public float ccdMotionThreshold; | ||||
| 	public float ccdSweptSphereRadius; | ||||
|     public float contactProcessingThreshold; | ||||
|     public float XlinearDamping; | ||||
|     public float XangularDamping; | ||||
|     public float XdeactivationTime; | ||||
|     public float XlinearSleepingThreshold; | ||||
|     public float XangularSleepingThreshold; | ||||
| 	public float XccdMotionThreshold; | ||||
| 	public float XccdSweptSphereRadius; | ||||
|     public float XcontactProcessingThreshold; | ||||
| 
 | ||||
|     public float terrainImplementation; | ||||
|     public float terrainFriction; | ||||
|     public float terrainHitFraction; | ||||
|     public float terrainRestitution; | ||||
|     public float terrainCollisionMargin; | ||||
|     public float XterrainImplementation; | ||||
|     public float XterrainFriction; | ||||
|     public float XterrainHitFraction; | ||||
|     public float XterrainRestitution; | ||||
|     public float XterrainCollisionMargin; | ||||
| 
 | ||||
|     public float avatarFriction; | ||||
|     public float avatarStandingFriction; | ||||
|     public float avatarDensity; | ||||
|     public float avatarRestitution; | ||||
|     public float avatarCapsuleWidth; | ||||
|     public float avatarCapsuleDepth; | ||||
|     public float avatarCapsuleHeight; | ||||
| 	public float avatarContactProcessingThreshold; | ||||
|     public float XavatarFriction; | ||||
|     public float XavatarStandingFriction; | ||||
|     public float XavatarDensity; | ||||
|     public float XavatarRestitution; | ||||
|     public float XavatarCapsuleWidth; | ||||
|     public float XavatarCapsuleDepth; | ||||
|     public float XavatarCapsuleHeight; | ||||
| 	public float XavatarContactProcessingThreshold; | ||||
| 
 | ||||
|     public float vehicleAngularDamping; | ||||
|     public float XvehicleAngularDamping; | ||||
| 
 | ||||
| 	public float maxPersistantManifoldPoolSize; | ||||
| 	public float maxCollisionAlgorithmPoolSize; | ||||
|  | @ -185,14 +187,14 @@ public struct ConfigurationParameters | |||
| 	public float shouldEnableFrictionCaching; | ||||
| 	public float numberOfSolverIterations; | ||||
| 
 | ||||
|     public float linksetImplementation; | ||||
|     public float linkConstraintUseFrameOffset; | ||||
|     public float linkConstraintEnableTransMotor; | ||||
|     public float linkConstraintTransMotorMaxVel; | ||||
|     public float linkConstraintTransMotorMaxForce; | ||||
|     public float linkConstraintERP; | ||||
|     public float linkConstraintCFM; | ||||
|     public float linkConstraintSolverIterations; | ||||
|     public float XlinksetImplementation; | ||||
|     public float XlinkConstraintUseFrameOffset; | ||||
|     public float XlinkConstraintEnableTransMotor; | ||||
|     public float XlinkConstraintTransMotorMaxVel; | ||||
|     public float XlinkConstraintTransMotorMaxForce; | ||||
|     public float XlinkConstraintERP; | ||||
|     public float XlinkConstraintCFM; | ||||
|     public float XlinkConstraintSolverIterations; | ||||
| 
 | ||||
|     public float physicsLoggingFrames; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Robert Adams
						Robert Adams