BulletSim: rework parameter setting for different types of values

(like vectors or quaternions).
user_profiles
Robert Adams 2013-02-16 22:14:38 -08:00
parent 6560d80fa8
commit 885b45b112
5 changed files with 346 additions and 392 deletions

View File

@ -1133,8 +1133,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
p.numberOfSolverIterations = o[0].numberOfSolverIterations; p.numberOfSolverIterations = o[0].numberOfSolverIterations;
p.linksetImplementation = BSParam.LinksetImplementation; p.linksetImplementation = BSParam.LinksetImplementation;
p.linkConstraintUseFrameOffset = BSParam.LinkConstraintUseFrameOffset; p.linkConstraintUseFrameOffset = BSParam.NumericBool(BSParam.LinkConstraintUseFrameOffset);
p.linkConstraintEnableTransMotor = BSParam.LinkConstraintEnableTransMotor; p.linkConstraintEnableTransMotor = BSParam.NumericBool(BSParam.LinkConstraintEnableTransMotor);
p.linkConstraintTransMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel; p.linkConstraintTransMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
p.linkConstraintTransMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce; p.linkConstraintTransMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
p.linkConstraintERP = BSParam.LinkConstraintERP; p.linkConstraintERP = BSParam.LinkConstraintERP;

View File

@ -144,7 +144,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
enableAngularVerticalAttraction = true; enableAngularVerticalAttraction = true;
enableAngularDeflection = false; enableAngularDeflection = false;
enableAngularBanking = false; enableAngularBanking = false;
if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse) if (BSParam.VehicleDebuggingEnabled)
{ {
enableAngularVerticalAttraction = true; enableAngularVerticalAttraction = true;
enableAngularDeflection = false; enableAngularDeflection = false;
@ -607,8 +607,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
// Maybe compute linear and angular factor and damping from params. // Maybe compute linear and angular factor and damping from params.
PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping); PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping);
PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactorV); PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactor);
PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactorV); PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactor);
// Vehicles report collision events so we know when it's on the ground // Vehicles report collision events so we know when it's on the ground
PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);

View File

@ -223,8 +223,8 @@ public sealed class BSLinksetConstraints : BSLinkset
constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
// tweek the constraint to increase stability // tweek the constraint to increase stability
constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset)); constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset);
constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor), constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor,
BSParam.LinkConstraintTransMotorMaxVel, BSParam.LinkConstraintTransMotorMaxVel,
BSParam.LinkConstraintTransMotorMaxForce); BSParam.LinkConstraintTransMotorMaxForce);
constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP); constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);

View File

@ -37,6 +37,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
public static class BSParam public static class BSParam
{ {
private static string LogHeader = "[BULLETSIM PARAMETERS]";
// Level of Detail values kept as float because that's what the Meshmerizer wants // Level of Detail values kept as float because that's what the Meshmerizer wants
public static float MeshLOD { get; private set; } public static float MeshLOD { get; private set; }
public static float MeshCircularLOD { get; private set; } public static float MeshCircularLOD { get; private set; }
@ -80,14 +82,13 @@ public static class BSParam
// Physics Engine operation // Physics Engine operation
public static float MaxPersistantManifoldPoolSize; public static float MaxPersistantManifoldPoolSize;
public static float MaxCollisionAlgorithmPoolSize; public static float MaxCollisionAlgorithmPoolSize;
public static float ShouldDisableContactPoolDynamicAllocation; public static bool ShouldDisableContactPoolDynamicAllocation;
public static float ShouldForceUpdateAllAabbs; public static bool ShouldForceUpdateAllAabbs;
public static float ShouldRandomizeSolverOrder; public static bool ShouldRandomizeSolverOrder;
public static float ShouldSplitSimulationIslands; public static bool ShouldSplitSimulationIslands;
public static float ShouldEnableFrictionCaching; public static bool ShouldEnableFrictionCaching;
public static float NumberOfSolverIterations; public static float NumberOfSolverIterations;
public static bool UseSingleSidedMeshes { get { return UseSingleSidedMeshesF != ConfigurationParameters.numericFalse; } } public static bool UseSingleSidedMeshes;
public static float UseSingleSidedMeshesF;
public static float GlobalContactBreakingThreshold; public static float GlobalContactBreakingThreshold;
// Avatar parameters // Avatar parameters
@ -112,16 +113,14 @@ public static class BSParam
public static float VehicleAngularDamping { get; private set; } public static float VehicleAngularDamping { get; private set; }
public static float VehicleFriction { get; private set; } public static float VehicleFriction { get; private set; }
public static float VehicleRestitution { get; private set; } public static float VehicleRestitution { get; private set; }
public static float VehicleLinearFactor { get; private set; } public static Vector3 VehicleLinearFactor { get; private set; }
public static Vector3 VehicleLinearFactorV { get; private set; } public static Vector3 VehicleAngularFactor { get; private set; }
public static float VehicleAngularFactor { get; private set; }
public static Vector3 VehicleAngularFactorV { get; private set; }
public static float VehicleGroundGravityFudge { get; private set; } public static float VehicleGroundGravityFudge { get; private set; }
public static float VehicleDebuggingEnabled { get; private set; } public static bool VehicleDebuggingEnabled { get; private set; }
public static float LinksetImplementation { get; private set; } public static float LinksetImplementation { get; private set; }
public static float LinkConstraintUseFrameOffset { get; private set; } public static bool LinkConstraintUseFrameOffset { get; private set; }
public static float LinkConstraintEnableTransMotor { get; private set; } public static bool LinkConstraintEnableTransMotor { get; private set; }
public static float LinkConstraintTransMotorMaxVel { get; private set; } public static float LinkConstraintTransMotorMaxVel { get; private set; }
public static float LinkConstraintTransMotorMaxForce { get; private set; } public static float LinkConstraintTransMotorMaxForce { get; private set; }
public static float LinkConstraintERP { get; private set; } public static float LinkConstraintERP { get; private set; }
@ -141,40 +140,106 @@ public static class BSParam
public const float MinRestitution = 0f; public const float MinRestitution = 0f;
public const float MaxRestitution = 1f; public const float MaxRestitution = 1f;
// =========================================================================== // =====================================================================================
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 // Base parameter definition that gets and sets parameter values via a string
public abstract class ParameterDefnBase
{ {
public string name; // string name of the parameter public string name; // string name of the parameter
public string desc; // a short description of what the parameter means public string desc; // a short description of what the parameter means
public float defaultValue; // default value if not specified anywhere else public ParameterDefnBase(string pName, string pDesc)
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; name = pName;
desc = d; desc = pDesc;
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) // Set the parameter value to the default
public abstract void AssignDefault(BSScene s);
// Get the value as a string
public abstract string GetValue(BSScene s);
// Set the value to this string value
public abstract void SetValue(BSScene s, string valAsString);
// set the value on a particular object (usually sets in physics engine)
public abstract void SetOnObject(BSScene s, BSPhysObject obj);
public abstract bool HasSetOnObject { get; }
}
// Specific parameter definition for a parameter of a specific type.
public delegate T PGetValue<T>(BSScene s);
public delegate void PSetValue<T>(BSScene s, T val);
public delegate void PSetOnObject<T>(BSScene scene, BSPhysObject obj);
public sealed class ParameterDefn<T> : ParameterDefnBase
{
T defaultValue;
PSetValue<T> setter;
PGetValue<T> getter;
PSetOnObject<T> objectSet;
public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
: base(pName, pDesc)
{ {
name = n; defaultValue = pDefault;
desc = d; setter = pSetter;
defaultValue = v; getter = pGetter;
userParam = u; objectSet = null;
getter = g; }
setter = s; public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter, PSetOnObject<T> pObjSetter)
onObject = o; : base(pName, pDesc)
{
defaultValue = pDefault;
setter = pSetter;
getter = pGetter;
objectSet = pObjSetter;
}
public override void AssignDefault(BSScene s)
{
setter(s, defaultValue);
}
public override string GetValue(BSScene s)
{
return String.Format("{0}", getter(s));
}
public override void SetValue(BSScene s, string valAsString)
{
// Get the generic type of the setter
Type genericType = setter.GetType().GetGenericArguments()[0];
// Find the 'Parse' method on that type
System.Reflection.MethodInfo parser = null;
try
{
parser = genericType.GetMethod("Parse", new Type[] { typeof(String) } );
}
catch (Exception e)
{
s.Logger.ErrorFormat("{0} Exception getting parser for type '{1}': {2}", LogHeader, genericType, e);
parser = null;
}
if (parser != null)
{
// Parse the input string
try
{
T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString });
setter(s, setValue);
// s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue);
}
catch
{
s.Logger.ErrorFormat("{0} Failed parsing parameter value '{1}' as type '{2}'", LogHeader, valAsString, genericType);
}
}
else
{
s.Logger.ErrorFormat("{0} Could not find parameter parser for type '{1}'", LogHeader, genericType);
}
}
public override bool HasSetOnObject
{
get { return objectSet != null; }
}
public override void SetOnObject(BSScene s, BSPhysObject obj)
{
if (objectSet != null)
objectSet(s, obj);
} }
} }
@ -184,462 +249,375 @@ public static class BSParam
// location somewhere in the program and make an entry in this table with the // location somewhere in the program and make an entry in this table with the
// getters and setters. // getters and setters.
// It is easiest to find an existing definition and copy it. // 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: // A ParameterDefn<T>() takes the following parameters:
// -- the text name of the parameter. This is used for console input and ini file. // -- 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 short text description of the parameter. This shows up in the console listing.
// -- a default value (float) // -- a default value
// -- a delegate for fetching the parameter from the ini file. // -- a delegate for getting the value
// Should handle fetching the right type from the ini file and converting it. // -- a delegate for setting the value
// -- 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 // -- an optional delegate to update the value in the world. Most often used to
// push the new value to an in-world object. // push the new value to an in-world object.
// //
// The single letter parameters for the delegates are: // The single letter parameters for the delegates are:
// s = BSScene // s = BSScene
// o = BSPhysObject // o = BSPhysObject
// p = string parameter name
// l = localID of referenced object
// v = value (float) // v = value (float)
// cf = parameter configuration class (for fetching values from ini file) private static ParameterDefnBase[] ParameterDefinitions =
private static ParameterDefn[] ParameterDefinitions =
{ {
new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", new ParameterDefn<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties",
ConfigurationParameters.numericTrue, true,
(s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, (s) => { return ShouldMeshSculptedPrim; },
(s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); }, (s,v) => { ShouldMeshSculptedPrim = v; } ),
(s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ), new ParameterDefn<bool>("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", false,
ConfigurationParameters.numericFalse, (s) => { return ShouldForceSimplePrimMeshing; },
(s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, (s,v) => { ShouldForceSimplePrimMeshing = v; } ),
(s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); }, new ParameterDefn<bool>("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
(s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ), true,
new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", (s) => { return ShouldUseHullsForPhysicalObjects; },
ConfigurationParameters.numericTrue, (s,v) => { ShouldUseHullsForPhysicalObjects = v; } ),
(s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
(s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); }, true,
(s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ), (s) => { return ShouldRemoveZeroWidthTriangles; },
new ParameterDefn("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes", (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
ConfigurationParameters.numericTrue,
(s,cf,p,v) => { ShouldRemoveZeroWidthTriangles = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
(s) => { return BSParam.NumericBool(ShouldRemoveZeroWidthTriangles); },
(s,p,l,v) => { ShouldRemoveZeroWidthTriangles = BSParam.BoolNumeric(v); } ),
new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", new ParameterDefn<float>("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
32f, 32f,
(s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); },
(s) => { return MeshLOD; }, (s) => { return MeshLOD; },
(s,p,l,v) => { MeshLOD = v; } ), (s,v) => { MeshLOD = v; } ),
new ParameterDefn("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes", new ParameterDefn<float>("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes",
32f, 32f,
(s,cf,p,v) => { MeshCircularLOD = (float)cf.GetInt(p, (int)v); },
(s) => { return MeshCircularLOD; }, (s) => { return MeshCircularLOD; },
(s,p,l,v) => { MeshCircularLOD = v; } ), (s,v) => { MeshCircularLOD = v; } ),
new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", new ParameterDefn<float>("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
10f, 10f,
(s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
(s) => { return MeshMegaPrimThreshold; }, (s) => { return MeshMegaPrimThreshold; },
(s,p,l,v) => { MeshMegaPrimThreshold = v; } ), (s,v) => { MeshMegaPrimThreshold = v; } ),
new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", new ParameterDefn<float>("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
32f, 32f,
(s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
(s) => { return MeshMegaPrimLOD; }, (s) => { return MeshMegaPrimLOD; },
(s,p,l,v) => { MeshMegaPrimLOD = v; } ), (s,v) => { MeshMegaPrimLOD = v; } ),
new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", new ParameterDefn<float>("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
32f, 32f,
(s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); },
(s) => { return SculptLOD; }, (s) => { return SculptLOD; },
(s,p,l,v) => { SculptLOD = v; } ), (s,v) => { SculptLOD = v; } ),
new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", new ParameterDefn<int>("MaxSubStep", "In simulation step, maximum number of substeps",
10f, 10,
(s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); }, (s) => { return s.m_maxSubSteps; },
(s) => { return (float)s.m_maxSubSteps; }, (s,v) => { s.m_maxSubSteps = (int)v; } ),
(s,p,l,v) => { s.m_maxSubSteps = (int)v; } ), new ParameterDefn<float>("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
1f / 60f, 1f / 60f,
(s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, (s) => { return s.m_fixedTimeStep; },
(s) => { return (float)s.m_fixedTimeStep; }, (s,v) => { s.m_fixedTimeStep = v; } ),
(s,p,l,v) => { s.m_fixedTimeStep = v; } ), new ParameterDefn<float>("NominalFrameRate", "The base frame rate we claim",
new ParameterDefn("NominalFrameRate", "The base frame rate we claim",
55f, 55f,
(s,cf,p,v) => { s.NominalFrameRate = cf.GetInt(p, (int)v); }, (s) => { return s.NominalFrameRate; },
(s) => { return (float)s.NominalFrameRate; }, (s,v) => { s.NominalFrameRate = (int)v; } ),
(s,p,l,v) => { s.NominalFrameRate = (int)v; } ), new ParameterDefn<int>("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", 2048,
2048f, (s) => { return s.m_maxCollisionsPerFrame; },
(s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, (s,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
(s) => { return (float)s.m_maxCollisionsPerFrame; }, new ParameterDefn<int>("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
(s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ), 8000,
new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame", (s) => { return s.m_maxUpdatesPerFrame; },
8000f, (s,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
(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("MinObjectMass", "Minimum object mass (0.0001)", new ParameterDefn<float>("MinObjectMass", "Minimum object mass (0.0001)",
0.0001f, 0.0001f,
(s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
(s) => { return MinimumObjectMass; }, (s) => { return MinimumObjectMass; },
(s,p,l,v) => { MinimumObjectMass = v; } ), (s,v) => { MinimumObjectMass = v; } ),
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", new ParameterDefn<float>("MaxObjectMass", "Maximum object mass (10000.01)",
10000.01f, 10000.01f,
(s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
(s) => { return MaximumObjectMass; }, (s) => { return MaximumObjectMass; },
(s,p,l,v) => { MaximumObjectMass = v; } ), (s,v) => { MaximumObjectMass = v; } ),
new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object", new ParameterDefn<float>("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
1000.0f, 1000.0f,
(s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
(s) => { return MaxLinearVelocity; }, (s) => { return MaxLinearVelocity; },
(s,p,l,v) => { MaxLinearVelocity = v; } ), (s,v) => { MaxLinearVelocity = v; } ),
new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object", new ParameterDefn<float>("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
1000.0f, 1000.0f,
(s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
(s) => { return MaxAngularVelocity; }, (s) => { return MaxAngularVelocity; },
(s,p,l,v) => { MaxAngularVelocity = v; } ), (s,v) => { MaxAngularVelocity = v; } ),
// LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)", new ParameterDefn<float>("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
20000.0f, 20000.0f,
(s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
(s) => { return MaxAddForceMagnitude; }, (s) => { return MaxAddForceMagnitude; },
(s,p,l,v) => { MaxAddForceMagnitude = v; } ), (s,v) => { MaxAddForceMagnitude = v; } ),
// Density is passed around as 100kg/m3. This scales that to 1kg/m3. // Density is passed around as 100kg/m3. This scales that to 1kg/m3.
new ParameterDefn("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)", new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
0.01f, 0.01f,
(s,cf,p,v) => { DensityScaleFactor = cf.GetFloat(p, v); },
(s) => { return DensityScaleFactor; }, (s) => { return DensityScaleFactor; },
(s,p,l,v) => { DensityScaleFactor = v; } ), (s,v) => { DensityScaleFactor = v; } ),
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing",
2200f, 2200f,
(s,cf,p,v) => { PID_D = cf.GetFloat(p, v); },
(s) => { return (float)PID_D; }, (s) => { return (float)PID_D; },
(s,p,l,v) => { PID_D = v; } ), (s,v) => { PID_D = v; } ),
new ParameterDefn("PID_P", "Parameteric factor for motion smoothing", new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing",
900f, 900f,
(s,cf,p,v) => { PID_P = cf.GetFloat(p, v); },
(s) => { return (float)PID_P; }, (s) => { return (float)PID_P; },
(s,p,l,v) => { PID_P = v; } ), (s,v) => { PID_P = v; } ),
new ParameterDefn("DefaultFriction", "Friction factor used on new objects", new ParameterDefn<float>("DefaultFriction", "Friction factor used on new objects",
0.2f, 0.2f,
(s,cf,p,v) => { DefaultFriction = cf.GetFloat(p, v); },
(s) => { return DefaultFriction; }, (s) => { return DefaultFriction; },
(s,p,l,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ), (s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
new ParameterDefn("DefaultDensity", "Density for new objects" , new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
10.000006836f, // Aluminum g/cm3 10.000006836f, // Aluminum g/cm3
(s,cf,p,v) => { DefaultDensity = cf.GetFloat(p, v); },
(s) => { return DefaultDensity; }, (s) => { return DefaultDensity; },
(s,p,l,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ), (s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
new ParameterDefn("DefaultRestitution", "Bouncyness of an object" , new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
0f, 0f,
(s,cf,p,v) => { DefaultRestitution = cf.GetFloat(p, v); },
(s) => { return DefaultRestitution; }, (s) => { return DefaultRestitution; },
(s,p,l,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ), (s,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ),
new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", new ParameterDefn<float>("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
0.04f, 0.04f,
(s,cf,p,v) => { CollisionMargin = cf.GetFloat(p, v); },
(s) => { return CollisionMargin; }, (s) => { return CollisionMargin; },
(s,p,l,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ), (s,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ),
new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)", new ParameterDefn<float>("Gravity", "Vertical force of gravity (negative means down)",
-9.80665f, -9.80665f,
(s,cf,p,v) => { Gravity = cf.GetFloat(p, v); },
(s) => { return Gravity; }, (s) => { return Gravity; },
(s,p,l,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; }, (s,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; },
(s,o,v) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,v)); } ), (s,o) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,Gravity)); } ),
new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", new ParameterDefn<float>("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
0f, 0f,
(s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); },
(s) => { return LinearDamping; }, (s) => { return LinearDamping; },
(s,p,l,v) => { LinearDamping = v; }, (s,v) => { LinearDamping = v; },
(s,o,v) => { s.PE.SetDamping(o.PhysBody, v, AngularDamping); } ), (s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", new ParameterDefn<float>("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
0f, 0f,
(s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); },
(s) => { return AngularDamping; }, (s) => { return AngularDamping; },
(s,p,l,v) => { AngularDamping = v; }, (s,v) => { AngularDamping = v; },
(s,o,v) => { s.PE.SetDamping(o.PhysBody, LinearDamping, v); } ), (s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", new ParameterDefn<float>("DeactivationTime", "Seconds before considering an object potentially static",
0.2f, 0.2f,
(s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); },
(s) => { return DeactivationTime; }, (s) => { return DeactivationTime; },
(s,p,l,v) => { DeactivationTime = v; }, (s,v) => { DeactivationTime = v; },
(s,o,v) => { s.PE.SetDeactivationTime(o.PhysBody, v); } ), (s,o) => { s.PE.SetDeactivationTime(o.PhysBody, DeactivationTime); } ),
new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", new ParameterDefn<float>("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
0.8f, 0.8f,
(s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); },
(s) => { return LinearSleepingThreshold; }, (s) => { return LinearSleepingThreshold; },
(s,p,l,v) => { LinearSleepingThreshold = v;}, (s,v) => { LinearSleepingThreshold = v;},
(s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ), (s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", new ParameterDefn<float>("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
1.0f, 1.0f,
(s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); },
(s) => { return AngularSleepingThreshold; }, (s) => { return AngularSleepingThreshold; },
(s,p,l,v) => { AngularSleepingThreshold = v;}, (s,v) => { AngularSleepingThreshold = v;},
(s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ), (s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , new ParameterDefn<float>("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
0.0f, // set to zero to disable 0.0f, // set to zero to disable
(s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
(s) => { return CcdMotionThreshold; }, (s) => { return CcdMotionThreshold; },
(s,p,l,v) => { CcdMotionThreshold = v;}, (s,v) => { CcdMotionThreshold = v;},
(s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ), (s,o) => { s.PE.SetCcdMotionThreshold(o.PhysBody, CcdMotionThreshold); } ),
new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , new ParameterDefn<float>("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
0.2f, 0.2f,
(s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
(s) => { return CcdSweptSphereRadius; }, (s) => { return CcdSweptSphereRadius; },
(s,p,l,v) => { CcdSweptSphereRadius = v;}, (s,v) => { CcdSweptSphereRadius = v;},
(s,o,v) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, v); } ), (s,o) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, CcdSweptSphereRadius); } ),
new ParameterDefn("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" , new ParameterDefn<float>("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" ,
0.0f, 0.0f,
(s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); },
(s) => { return ContactProcessingThreshold; }, (s) => { return ContactProcessingThreshold; },
(s,p,l,v) => { ContactProcessingThreshold = v;}, (s,v) => { ContactProcessingThreshold = v;},
(s,o,v) => { s.PE.SetContactProcessingThreshold(o.PhysBody, v); } ), (s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ),
new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
(float)BSTerrainPhys.TerrainImplementation.Mesh, (float)BSTerrainPhys.TerrainImplementation.Mesh,
(s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); },
(s) => { return TerrainImplementation; }, (s) => { return TerrainImplementation; },
(s,p,l,v) => { TerrainImplementation = v; } ), (s,v) => { TerrainImplementation = v; } ),
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
0.3f, 0.3f,
(s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); },
(s) => { return TerrainFriction; }, (s) => { return TerrainFriction; },
(s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ), (s,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" ,
0.8f, 0.8f,
(s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); },
(s) => { return TerrainHitFraction; }, (s) => { return TerrainHitFraction; },
(s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ), (s,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
new ParameterDefn("TerrainRestitution", "Bouncyness" , new ParameterDefn<float>("TerrainRestitution", "Bouncyness" ,
0f, 0f,
(s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); },
(s) => { return TerrainRestitution; }, (s) => { return TerrainRestitution; },
(s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ), (s,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" , new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
0.08f, 0.08f,
(s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
(s) => { return TerrainCollisionMargin; }, (s) => { return TerrainCollisionMargin; },
(s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ), (s,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", new ParameterDefn<float>("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
0.2f, 0.2f,
(s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); },
(s) => { return AvatarFriction; }, (s) => { return AvatarFriction; },
(s,p,l,v) => { AvatarFriction = v; } ), (s,v) => { AvatarFriction = v; } ),
new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
0.95f, 0.95f,
(s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
(s) => { return AvatarStandingFriction; }, (s) => { return AvatarStandingFriction; },
(s,p,l,v) => { AvatarStandingFriction = v; } ), (s,v) => { AvatarStandingFriction = v; } ),
new ParameterDefn("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run", new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
1.3f, 1.3f,
(s,cf,p,v) => { AvatarAlwaysRunFactor = cf.GetFloat(p, v); },
(s) => { return AvatarAlwaysRunFactor; }, (s) => { return AvatarAlwaysRunFactor; },
(s,p,l,v) => { AvatarAlwaysRunFactor = v; } ), (s,v) => { AvatarAlwaysRunFactor = v; } ),
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
3.5f, 3.5f,
(s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
(s) => { return AvatarDensity; }, (s) => { return AvatarDensity; },
(s,p,l,v) => { AvatarDensity = v; } ), (s,v) => { AvatarDensity = v; } ),
new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
0f, 0f,
(s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); },
(s) => { return AvatarRestitution; }, (s) => { return AvatarRestitution; },
(s,p,l,v) => { AvatarRestitution = v; } ), (s,v) => { AvatarRestitution = v; } ),
new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
0.6f, 0.6f,
(s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); },
(s) => { return AvatarCapsuleWidth; }, (s) => { return AvatarCapsuleWidth; },
(s,p,l,v) => { AvatarCapsuleWidth = v; } ), (s,v) => { AvatarCapsuleWidth = v; } ),
new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
0.45f, 0.45f,
(s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); },
(s) => { return AvatarCapsuleDepth; }, (s) => { return AvatarCapsuleDepth; },
(s,p,l,v) => { AvatarCapsuleDepth = v; } ), (s,v) => { AvatarCapsuleDepth = v; } ),
new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar",
1.5f, 1.5f,
(s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); },
(s) => { return AvatarCapsuleHeight; }, (s) => { return AvatarCapsuleHeight; },
(s,p,l,v) => { AvatarCapsuleHeight = v; } ), (s,v) => { AvatarCapsuleHeight = v; } ),
new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
0.1f, 0.1f,
(s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
(s) => { return AvatarContactProcessingThreshold; }, (s) => { return AvatarContactProcessingThreshold; },
(s,p,l,v) => { AvatarContactProcessingThreshold = v; } ), (s,v) => { AvatarContactProcessingThreshold = v; } ),
new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction", new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
0.3f, 0.3f,
(s,cf,p,v) => { AvatarStepHeight = cf.GetFloat(p, v); },
(s) => { return AvatarStepHeight; }, (s) => { return AvatarStepHeight; },
(s,p,l,v) => { AvatarStepHeight = v; } ), (s,v) => { AvatarStepHeight = v; } ),
new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
0.6f, 0.6f,
(s,cf,p,v) => { AvatarStepApproachFactor = cf.GetFloat(p, v); },
(s) => { return AvatarStepApproachFactor; }, (s) => { return AvatarStepApproachFactor; },
(s,p,l,v) => { AvatarStepApproachFactor = v; } ), (s,v) => { AvatarStepApproachFactor = v; } ),
new ParameterDefn("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step", new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
2.0f, 2.0f,
(s,cf,p,v) => { AvatarStepForceFactor = cf.GetFloat(p, v); },
(s) => { return AvatarStepForceFactor; }, (s) => { return AvatarStepForceFactor; },
(s,p,l,v) => { AvatarStepForceFactor = v; } ), (s,v) => { AvatarStepForceFactor = v; } ),
new ParameterDefn("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle", new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
1000.0f, 1000.0f,
(s,cf,p,v) => { VehicleMaxLinearVelocity = cf.GetFloat(p, v); },
(s) => { return (float)VehicleMaxLinearVelocity; }, (s) => { return (float)VehicleMaxLinearVelocity; },
(s,p,l,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ), (s,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ),
new ParameterDefn("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle", new ParameterDefn<float>("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
12.0f, 12.0f,
(s,cf,p,v) => { VehicleMaxAngularVelocity = cf.GetFloat(p, v); },
(s) => { return (float)VehicleMaxAngularVelocity; }, (s) => { return (float)VehicleMaxAngularVelocity; },
(s,p,l,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ), (s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
0.0f, 0.0f,
(s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
(s) => { return VehicleAngularDamping; }, (s) => { return VehicleAngularDamping; },
(s,p,l,v) => { VehicleAngularDamping = v; } ), (s,v) => { VehicleAngularDamping = v; } ),
new ParameterDefn("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (0.0 - 1.0)", new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)",
1.0f, new Vector3(1f, 1f, 1f),
(s,cf,p,v) => { VehicleLinearFactor = cf.GetFloat(p, v); },
(s) => { return VehicleLinearFactor; }, (s) => { return VehicleLinearFactor; },
(s,p,l,v) => { VehicleLinearFactor = v; VehicleLinearFactorV = new Vector3(v, v, v); } ), (s,v) => { VehicleLinearFactor = v; } ),
new ParameterDefn("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (0.0 - 1.0)", new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
1.0f, new Vector3(1f, 1f, 1f),
(s,cf,p,v) => { VehicleAngularFactor = cf.GetFloat(p, v); },
(s) => { return VehicleAngularFactor; }, (s) => { return VehicleAngularFactor; },
(s,p,l,v) => { VehicleAngularFactor = v; VehicleAngularFactorV = new Vector3(v, v, v); } ), (s,v) => { VehicleAngularFactor = v; } ),
new ParameterDefn("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)", new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
0.0f, 0.0f,
(s,cf,p,v) => { VehicleFriction = cf.GetFloat(p, v); },
(s) => { return VehicleFriction; }, (s) => { return VehicleFriction; },
(s,p,l,v) => { VehicleFriction = v; } ), (s,v) => { VehicleFriction = v; } ),
new ParameterDefn("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)", new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
0.0f, 0.0f,
(s,cf,p,v) => { VehicleRestitution = cf.GetFloat(p, v); },
(s) => { return VehicleRestitution; }, (s) => { return VehicleRestitution; },
(s,p,l,v) => { VehicleRestitution = v; } ), (s,v) => { VehicleRestitution = v; } ),
new ParameterDefn("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
0.2f, 0.2f,
(s,cf,p,v) => { VehicleGroundGravityFudge = cf.GetFloat(p, v); },
(s) => { return VehicleGroundGravityFudge; }, (s) => { return VehicleGroundGravityFudge; },
(s,p,l,v) => { VehicleGroundGravityFudge = v; } ), (s,v) => { VehicleGroundGravityFudge = v; } ),
new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging", new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
ConfigurationParameters.numericFalse, false,
(s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
(s) => { return VehicleDebuggingEnabled; }, (s) => { return VehicleDebuggingEnabled; },
(s,p,l,v) => { VehicleDebuggingEnabled = v; } ), (s,v) => { VehicleDebuggingEnabled = v; } ),
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
0f, 0f,
(s,cf,p,v) => { MaxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
(s) => { return MaxPersistantManifoldPoolSize; }, (s) => { return MaxPersistantManifoldPoolSize; },
(s,p,l,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ), (s,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", new ParameterDefn<float>("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
0f, 0f,
(s,cf,p,v) => { MaxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
(s) => { return MaxCollisionAlgorithmPoolSize; }, (s) => { return MaxCollisionAlgorithmPoolSize; },
(s,p,l,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ), (s,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
ConfigurationParameters.numericFalse, false,
(s,cf,p,v) => { ShouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
(s) => { return ShouldDisableContactPoolDynamicAllocation; }, (s) => { return ShouldDisableContactPoolDynamicAllocation; },
(s,p,l,v) => { ShouldDisableContactPoolDynamicAllocation = v; s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ), (s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
ConfigurationParameters.numericFalse, new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
(s,cf,p,v) => { ShouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, false,
(s) => { return ShouldForceUpdateAllAabbs; }, (s) => { return ShouldForceUpdateAllAabbs; },
(s,p,l,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ), (s,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = NumericBool(v); } ),
new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", new ParameterDefn<bool>("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
ConfigurationParameters.numericTrue, true,
(s,cf,p,v) => { ShouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
(s) => { return ShouldRandomizeSolverOrder; }, (s) => { return ShouldRandomizeSolverOrder; },
(s,p,l,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ), (s,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = NumericBool(v); } ),
new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", new ParameterDefn<bool>("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
ConfigurationParameters.numericTrue, true,
(s,cf,p,v) => { ShouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
(s) => { return ShouldSplitSimulationIslands; }, (s) => { return ShouldSplitSimulationIslands; },
(s,p,l,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ), (s,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = NumericBool(v); } ),
new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", new ParameterDefn<bool>("ShouldEnableFrictionCaching", "Enable friction computation caching",
ConfigurationParameters.numericTrue, true,
(s,cf,p,v) => { ShouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
(s) => { return ShouldEnableFrictionCaching; }, (s) => { return ShouldEnableFrictionCaching; },
(s,p,l,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ), (s,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = NumericBool(v); } ),
new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)", new ParameterDefn<float>("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
0f, // zero says use Bullet default 0f, // zero says use Bullet default
(s,cf,p,v) => { NumberOfSolverIterations = cf.GetFloat(p, v); },
(s) => { return NumberOfSolverIterations; }, (s) => { return NumberOfSolverIterations; },
(s,p,l,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ), (s,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
new ParameterDefn("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.", new ParameterDefn<bool>("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.",
ConfigurationParameters.numericTrue, true,
(s,cf,p,v) => { UseSingleSidedMeshesF = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, (s) => { return UseSingleSidedMeshes; },
(s) => { return UseSingleSidedMeshesF; }, (s,v) => { UseSingleSidedMeshes = v; s.UnmanagedParams[0].useSingleSidedMeshes = NumericBool(v); } ),
(s,p,l,v) => { UseSingleSidedMeshesF = v; s.UnmanagedParams[0].useSingleSidedMeshes = v; } ), new ParameterDefn<float>("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
new ParameterDefn("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
0f, 0f,
(s,cf,p,v) => { GlobalContactBreakingThreshold = cf.GetFloat(p, v); },
(s) => { return GlobalContactBreakingThreshold; }, (s) => { return GlobalContactBreakingThreshold; },
(s,p,l,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ), (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
(float)BSLinkset.LinksetImplementation.Compound, (float)BSLinkset.LinksetImplementation.Compound,
(s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); },
(s) => { return LinksetImplementation; }, (s) => { return LinksetImplementation; },
(s,p,l,v) => { LinksetImplementation = v; } ), (s,v) => { LinksetImplementation = v; } ),
new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
ConfigurationParameters.numericFalse, false,
(s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
(s) => { return LinkConstraintUseFrameOffset; }, (s) => { return LinkConstraintUseFrameOffset; },
(s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ), (s,v) => { LinkConstraintUseFrameOffset = v; } ),
new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
ConfigurationParameters.numericTrue, true,
(s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
(s) => { return LinkConstraintEnableTransMotor; }, (s) => { return LinkConstraintEnableTransMotor; },
(s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ), (s,v) => { LinkConstraintEnableTransMotor = v; } ),
new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
5.0f, 5.0f,
(s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
(s) => { return LinkConstraintTransMotorMaxVel; }, (s) => { return LinkConstraintTransMotorMaxVel; },
(s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ), (s,v) => { LinkConstraintTransMotorMaxVel = v; } ),
new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
0.1f, 0.1f,
(s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
(s) => { return LinkConstraintTransMotorMaxForce; }, (s) => { return LinkConstraintTransMotorMaxForce; },
(s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ), (s,v) => { LinkConstraintTransMotorMaxForce = v; } ),
new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
0.1f, 0.1f,
(s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); },
(s) => { return LinkConstraintCFM; }, (s) => { return LinkConstraintCFM; },
(s,p,l,v) => { LinkConstraintCFM = v; } ), (s,v) => { LinkConstraintCFM = v; } ),
new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
0.1f, 0.1f,
(s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); },
(s) => { return LinkConstraintERP; }, (s) => { return LinkConstraintERP; },
(s,p,l,v) => { LinkConstraintERP = v; } ), (s,v) => { LinkConstraintERP = v; } ),
new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
40, 40,
(s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); },
(s) => { return LinkConstraintSolverIterations; }, (s) => { return LinkConstraintSolverIterations; },
(s,p,l,v) => { LinkConstraintSolverIterations = v; } ), (s,v) => { LinkConstraintSolverIterations = v; } ),
new ParameterDefn("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)", new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
0,
(s) => { return s.PhysicsMetricDumpFrames; },
(s,v) => { s.PhysicsMetricDumpFrames = v; } ),
new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
0f, 0f,
(s,cf,p,v) => { s.PhysicsMetricDumpFrames = cf.GetFloat(p, (int)v); },
(s) => { return (float)s.PhysicsMetricDumpFrames; },
(s,p,l,v) => { s.PhysicsMetricDumpFrames = (int)v; } ),
new ParameterDefn("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
0f,
(s,cf,p,v) => { ; },
(s) => { return 0f; }, (s) => { return 0f; },
(s,p,l,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ), (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ),
new ParameterDefn("ResetConstraintSolver", "Setting this is any value resets the constraint solver", new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
0f, 0f,
(s,cf,p,v) => { ; },
(s) => { return 0f; }, (s) => { return 0f; },
(s,p,l,v) => { BSParam.ResetConstraintSolverTainted(s, v); } ), (s,v) => { BSParam.ResetConstraintSolverTainted(s, v); } ),
}; };
// Convert a boolean to our numeric true and false values // Convert a boolean to our numeric true and false values
@ -658,13 +636,13 @@ public static class BSParam
// ParameterDefn structure. // ParameterDefn structure.
// Case does not matter as names are compared after converting to lower case. // Case does not matter as names are compared after converting to lower case.
// Returns 'false' if the parameter is not found. // Returns 'false' if the parameter is not found.
internal static bool TryGetParameter(string paramName, out ParameterDefn defn) internal static bool TryGetParameter(string paramName, out ParameterDefnBase defn)
{ {
bool ret = false; bool ret = false;
ParameterDefn foundDefn = new ParameterDefn(); ParameterDefnBase foundDefn = null;
string pName = paramName.ToLower(); string pName = paramName.ToLower();
foreach (ParameterDefn parm in ParameterDefinitions) foreach (ParameterDefnBase parm in ParameterDefinitions)
{ {
if (pName == parm.name.ToLower()) if (pName == parm.name.ToLower())
{ {
@ -680,18 +658,18 @@ public static class BSParam
// Pass through the settable parameters and set the default values // Pass through the settable parameters and set the default values
internal static void SetParameterDefaultValues(BSScene physicsScene) internal static void SetParameterDefaultValues(BSScene physicsScene)
{ {
foreach (ParameterDefn parm in ParameterDefinitions) foreach (ParameterDefnBase parm in ParameterDefinitions)
{ {
parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue); parm.AssignDefault(physicsScene);
} }
} }
// Get user set values out of the ini file. // Get user set values out of the ini file.
internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg) internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
{ {
foreach (ParameterDefn parm in ParameterDefinitions) foreach (ParameterDefnBase parm in ParameterDefinitions)
{ {
parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue); parm.SetValue(physicsScene, cfg.GetString(parm.name, parm.GetValue(physicsScene)));
} }
} }
@ -706,11 +684,11 @@ public static class BSParam
List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
for (int ii = 0; ii < ParameterDefinitions.Length; ii++) for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
{ {
ParameterDefn pd = ParameterDefinitions[ii]; ParameterDefnBase pd = ParameterDefinitions[ii];
entries.Add(new PhysParameterEntry(pd.name, pd.desc)); entries.Add(new PhysParameterEntry(pd.name, pd.desc));
} }
// make the list alphabetical for estetic reasons // make the list alphabetical for ease of finding anything
entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); }); entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); });
SettableParameters = entries.ToArray(); SettableParameters = entries.ToArray();

View File

@ -161,7 +161,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
private int m_physicsLoggingFileMinutes; private int m_physicsLoggingFileMinutes;
private bool m_physicsLoggingDoFlush; private bool m_physicsLoggingDoFlush;
private bool m_physicsPhysicalDumpEnabled; private bool m_physicsPhysicalDumpEnabled;
public float PhysicsMetricDumpFrames { get; set; } public int PhysicsMetricDumpFrames { get; set; }
// 'true' of the vehicle code is to log lots of details // 'true' of the vehicle code is to log lots of details
public bool VehicleLoggingEnabled { get; private set; } public bool VehicleLoggingEnabled { get; private set; }
public bool VehiclePhysicalLoggingEnabled { get; private set; } public bool VehiclePhysicalLoggingEnabled { get; private set; }
@ -542,7 +542,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
collidersCount = 0; collidersCount = 0;
} }
if ((m_simulationStep % PhysicsMetricDumpFrames) == 0) if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0))
PE.DumpPhysicsStatistics(World); PE.DumpPhysicsStatistics(World);
// Get a value for 'now' so all the collision and update routines don't have to get their own. // Get a value for 'now' so all the collision and update routines don't have to get their own.
@ -880,38 +880,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{ {
bool ret = false; bool ret = false;
float valf = 0f; BSParam.ParameterDefnBase theParam;
if (val.ToLower() == "true")
{
valf = PhysParameterEntry.NUMERIC_TRUE;
}
else
{
if (val.ToLower() == "false")
{
valf = PhysParameterEntry.NUMERIC_FALSE;
}
else
{
try
{
valf = float.Parse(val);
}
catch
{
valf = 0f;
}
}
}
BSParam.ParameterDefn theParam;
if (BSParam.TryGetParameter(parm, out theParam)) if (BSParam.TryGetParameter(parm, out theParam))
{ {
// Set the value in the C# code // Set the value in the C# code
theParam.setter(this, parm, localID, valf); theParam.SetValue(this, val);
// Optionally set the parameter in the unmanaged code // Optionally set the parameter in the unmanaged code
if (theParam.onObject != null) if (theParam.HasSetOnObject)
{ {
// update all the localIDs specified // update all the localIDs specified
// If the local ID is APPLY_TO_NONE, just change the default value // If the local ID is APPLY_TO_NONE, just change the default value
@ -923,16 +899,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
case PhysParameterEntry.APPLY_TO_NONE: case PhysParameterEntry.APPLY_TO_NONE:
// This will cause a call into the physical world if some operation is specified (SetOnObject). // This will cause a call into the physical world if some operation is specified (SetOnObject).
objectIDs.Add(TERRAIN_ID); objectIDs.Add(TERRAIN_ID);
TaintedUpdateParameter(parm, objectIDs, valf); TaintedUpdateParameter(parm, objectIDs, val);
break; break;
case PhysParameterEntry.APPLY_TO_ALL: case PhysParameterEntry.APPLY_TO_ALL:
lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
TaintedUpdateParameter(parm, objectIDs, valf); TaintedUpdateParameter(parm, objectIDs, val);
break; break;
default: default:
// setting only one localID // setting only one localID
objectIDs.Add(localID); objectIDs.Add(localID);
TaintedUpdateParameter(parm, objectIDs, valf); TaintedUpdateParameter(parm, objectIDs, val);
break; break;
} }
} }
@ -943,22 +919,22 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
} }
// schedule the actual updating of the paramter to when the phys engine is not busy // schedule the actual updating of the paramter to when the phys engine is not busy
private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val) private void TaintedUpdateParameter(string parm, List<uint> lIDs, string val)
{ {
float xval = val; string xval = val;
List<uint> xlIDs = lIDs; List<uint> xlIDs = lIDs;
string xparm = parm; string xparm = parm;
TaintedObject("BSScene.UpdateParameterSet", delegate() { TaintedObject("BSScene.UpdateParameterSet", delegate() {
BSParam.ParameterDefn thisParam; BSParam.ParameterDefnBase thisParam;
if (BSParam.TryGetParameter(xparm, out thisParam)) if (BSParam.TryGetParameter(xparm, out thisParam))
{ {
if (thisParam.onObject != null) if (thisParam.HasSetOnObject)
{ {
foreach (uint lID in xlIDs) foreach (uint lID in xlIDs)
{ {
BSPhysObject theObject = null; BSPhysObject theObject = null;
if (PhysObjects.TryGetValue(lID, out theObject)) if (PhysObjects.TryGetValue(lID, out theObject))
thisParam.onObject(this, theObject, xval); thisParam.SetOnObject(this, theObject);
} }
} }
} }
@ -971,10 +947,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{ {
string val = String.Empty; string val = String.Empty;
bool ret = false; bool ret = false;
BSParam.ParameterDefn theParam; BSParam.ParameterDefnBase theParam;
if (BSParam.TryGetParameter(parm, out theParam)) if (BSParam.TryGetParameter(parm, out theParam))
{ {
val = theParam.getter(this).ToString(); val = theParam.GetValue(this);
ret = true; ret = true;
} }
value = val; value = val;