Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
0aaf52fca4
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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 OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
|
||||
public class BSConstraint : IDisposable
|
||||
{
|
||||
private BulletSim m_world;
|
||||
private BulletBody m_body1;
|
||||
private BulletBody m_body2;
|
||||
private BulletConstraint m_constraint;
|
||||
private bool m_enabled = false;
|
||||
|
||||
public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
|
||||
Vector3 frame1, Quaternion frame1rot,
|
||||
Vector3 frame2, Quaternion frame2rot
|
||||
)
|
||||
{
|
||||
m_world = world;
|
||||
m_body1 = obj1;
|
||||
m_body2 = obj2;
|
||||
m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
|
||||
frame1, frame1rot,
|
||||
frame2, frame2rot));
|
||||
m_enabled = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
|
||||
BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
|
||||
m_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public BulletBody Body1 { get { return m_body1; } }
|
||||
public BulletBody Body2 { get { return m_body2; } }
|
||||
|
||||
public bool SetLinearLimits(Vector3 low, Vector3 high)
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_enabled)
|
||||
ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SetAngularLimits(Vector3 low, Vector3 high)
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_enabled)
|
||||
ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool UseFrameOffset(bool useOffset)
|
||||
{
|
||||
bool ret = false;
|
||||
float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
|
||||
if (m_enabled)
|
||||
ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
|
||||
{
|
||||
bool ret = false;
|
||||
float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
|
||||
if (m_enabled)
|
||||
ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool CalculateTransforms()
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_enabled)
|
||||
{
|
||||
BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* 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 log4net;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
|
||||
public class BSConstraintCollection : IDisposable
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
|
||||
|
||||
delegate bool ConstraintAction(BSConstraint constrain);
|
||||
|
||||
private List<BSConstraint> m_constraints;
|
||||
private BulletSim m_world;
|
||||
|
||||
public BSConstraintCollection(BulletSim world)
|
||||
{
|
||||
m_world = world;
|
||||
m_constraints = new List<BSConstraint>();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Clear();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (BSConstraint cons in m_constraints)
|
||||
{
|
||||
cons.Dispose();
|
||||
}
|
||||
m_constraints.Clear();
|
||||
}
|
||||
|
||||
public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
|
||||
Vector3 frame1, Quaternion frame1rot,
|
||||
Vector3 frame2, Quaternion frame2rot)
|
||||
{
|
||||
BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
|
||||
|
||||
this.AddConstraint(constrain);
|
||||
return constrain;
|
||||
}
|
||||
|
||||
public bool AddConstraint(BSConstraint cons)
|
||||
{
|
||||
// There is only one constraint between any bodies. Remove any old just to make sure.
|
||||
RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
|
||||
|
||||
m_constraints.Add(cons);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the constraint between two bodies. There can be only one the way we're using them.
|
||||
public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint)
|
||||
{
|
||||
bool found = false;
|
||||
BSConstraint foundConstraint = null;
|
||||
|
||||
uint lookingID1 = body1.ID;
|
||||
uint lookingID2 = body2.ID;
|
||||
ForEachConstraint(delegate(BSConstraint constrain)
|
||||
{
|
||||
if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
|
||||
|| (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
|
||||
{
|
||||
foundConstraint = constrain;
|
||||
found = true;
|
||||
}
|
||||
return found;
|
||||
});
|
||||
returnConstraint = foundConstraint;
|
||||
return found;
|
||||
}
|
||||
|
||||
public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
|
||||
{
|
||||
// return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
|
||||
|
||||
bool ret = false;
|
||||
BSConstraint constrain;
|
||||
|
||||
if (this.TryGetConstraint(body1, body2, out constrain))
|
||||
{
|
||||
// remove the constraint from our collection
|
||||
m_constraints.Remove(constrain);
|
||||
// tell the engine that all its structures need to be freed
|
||||
constrain.Dispose();
|
||||
// we destroyed something
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool RemoveAndDestroyConstraint(BulletBody body1)
|
||||
{
|
||||
// return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID);
|
||||
|
||||
List<BSConstraint> toRemove = new List<BSConstraint>();
|
||||
uint lookingID = body1.ID;
|
||||
ForEachConstraint(delegate(BSConstraint constrain)
|
||||
{
|
||||
if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
|
||||
{
|
||||
toRemove.Add(constrain);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
lock (m_constraints)
|
||||
{
|
||||
foreach (BSConstraint constrain in toRemove)
|
||||
{
|
||||
m_constraints.Remove(constrain);
|
||||
constrain.Dispose();
|
||||
}
|
||||
}
|
||||
return (toRemove.Count > 0);
|
||||
}
|
||||
|
||||
public bool RecalculateAllConstraints()
|
||||
{
|
||||
foreach (BSConstraint constrain in m_constraints)
|
||||
{
|
||||
constrain.CalculateTransforms();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Lock the constraint list and loop through it.
|
||||
// The constraint action returns 'true' if it wants the loop aborted.
|
||||
private void ForEachConstraint(ConstraintAction action)
|
||||
{
|
||||
lock (m_constraints)
|
||||
{
|
||||
foreach (BSConstraint constrain in m_constraints)
|
||||
{
|
||||
if (action(constrain))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -97,6 +97,9 @@ public sealed class BSPrim : PhysicsActor
|
|||
long _collidingStep;
|
||||
long _collidingGroundStep;
|
||||
|
||||
private BulletBody m_body;
|
||||
public BulletBody Body { get { return m_body; } }
|
||||
|
||||
private BSDynamics _vehicle;
|
||||
|
||||
private OMV.Vector3 _PIDTarget;
|
||||
|
@ -138,6 +141,11 @@ public sealed class BSPrim : PhysicsActor
|
|||
_scene.TaintedObject(delegate()
|
||||
{
|
||||
RecreateGeomAndObject();
|
||||
|
||||
// Get the pointer to the physical body for this object.
|
||||
// At the moment, we're still letting BulletSim manage the creation and destruction
|
||||
// of the object. Someday we'll move that into the C# code.
|
||||
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -161,7 +169,7 @@ public sealed class BSPrim : PhysicsActor
|
|||
_parentPrim = null;
|
||||
}
|
||||
|
||||
// make sure there are no possible children depending on me
|
||||
// make sure there are no other prims linked to me
|
||||
UnlinkAllChildren();
|
||||
|
||||
// everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
|
||||
|
@ -333,11 +341,10 @@ public sealed class BSPrim : PhysicsActor
|
|||
_rotationalVelocity = OMV.Vector3.Zero;
|
||||
|
||||
// Zero some other properties directly into the physics engine
|
||||
IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID);
|
||||
BulletSimAPI.SetVelocity2(obj, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetAngularVelocity2(obj, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetInterpolation2(obj, OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
BulletSimAPI.ClearForces2(obj);
|
||||
BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
BulletSimAPI.ClearForces2(Body.Ptr);
|
||||
}
|
||||
|
||||
public override void LockAngularMotion(OMV.Vector3 axis)
|
||||
|
@ -383,7 +390,8 @@ public sealed class BSPrim : PhysicsActor
|
|||
_scene.TaintedObject(delegate()
|
||||
{
|
||||
DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
|
||||
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
|
||||
// BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
|
||||
BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -407,8 +415,7 @@ public sealed class BSPrim : PhysicsActor
|
|||
_scene.TaintedObject(delegate()
|
||||
{
|
||||
// Tell the physics engine to clear state
|
||||
IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID);
|
||||
BulletSimAPI.ClearForces2(obj);
|
||||
BulletSimAPI.ClearForces2(this.Body.Ptr);
|
||||
});
|
||||
|
||||
// make it so the scene will call us each tick to do vehicle things
|
||||
|
@ -420,7 +427,6 @@ public sealed class BSPrim : PhysicsActor
|
|||
}
|
||||
public override void VehicleFloatParam(int param, float value)
|
||||
{
|
||||
m_log.DebugFormat("{0} VehicleFloatParam. {1} <= {2}", LogHeader, param, value);
|
||||
_scene.TaintedObject(delegate()
|
||||
{
|
||||
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
|
||||
|
@ -428,7 +434,6 @@ public sealed class BSPrim : PhysicsActor
|
|||
}
|
||||
public override void VehicleVectorParam(int param, OMV.Vector3 value)
|
||||
{
|
||||
m_log.DebugFormat("{0} VehicleVectorParam. {1} <= {2}", LogHeader, param, value);
|
||||
_scene.TaintedObject(delegate()
|
||||
{
|
||||
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
|
||||
|
@ -436,7 +441,6 @@ public sealed class BSPrim : PhysicsActor
|
|||
}
|
||||
public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
|
||||
{
|
||||
m_log.DebugFormat("{0} VehicleRotationParam. {1} <= {2}", LogHeader, param, rotation);
|
||||
_scene.TaintedObject(delegate()
|
||||
{
|
||||
_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
|
||||
|
@ -444,7 +448,6 @@ public sealed class BSPrim : PhysicsActor
|
|||
}
|
||||
public override void VehicleFlags(int param, bool remove)
|
||||
{
|
||||
m_log.DebugFormat("{0} VehicleFlags. {1}. Remove={2}", LogHeader, param, remove);
|
||||
_scene.TaintedObject(delegate()
|
||||
{
|
||||
_vehicle.ProcessVehicleFlags(param, remove);
|
||||
|
@ -1292,11 +1295,10 @@ public sealed class BSPrim : PhysicsActor
|
|||
// relative to each other.
|
||||
void CreateLinkset()
|
||||
{
|
||||
DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
|
||||
// DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
|
||||
|
||||
// remove any constraints that might be in place
|
||||
DebugLog("{0}: CreateLinkset: RemoveConstraints between me and any children", LogHeader, LocalID);
|
||||
BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
|
||||
UnlinkAllChildren();
|
||||
|
||||
// create constraints between the root prim and each of the children
|
||||
foreach (BSPrim prim in _childrenPrims)
|
||||
|
@ -1321,15 +1323,25 @@ public sealed class BSPrim : PhysicsActor
|
|||
|
||||
// create a constraint that allows no freedom of movement between the two objects
|
||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||
DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
|
||||
// DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
|
||||
DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
|
||||
BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, childPrim.LocalID,
|
||||
childRelativePosition,
|
||||
childRelativeRotation,
|
||||
OMV.Vector3.Zero,
|
||||
OMV.Quaternion.Identity,
|
||||
OMV.Vector3.Zero, OMV.Vector3.Zero,
|
||||
OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
BSConstraint constrain = _scene.Constraints.CreateConstraint(
|
||||
_scene.World, this.Body, childPrim.Body,
|
||||
childRelativePosition,
|
||||
childRelativeRotation,
|
||||
OMV.Vector3.Zero,
|
||||
OMV.Quaternion.Identity);
|
||||
constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
|
||||
// tweek the constraint to increase stability
|
||||
constrain.UseFrameOffset(_scene.BoolNumeric(_scene.Params.linkConstraintUseFrameOffset));
|
||||
if (_scene.BoolNumeric(_scene.Params.linkConstraintEnableTransMotor))
|
||||
{
|
||||
constrain.TranslationalLimitMotor(true,
|
||||
_scene.Params.linkConstraintTransMotorMaxVel,
|
||||
_scene.Params.linkConstraintTransMotorMaxForce);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove linkage between myself and a particular child
|
||||
|
@ -1339,7 +1351,8 @@ public sealed class BSPrim : PhysicsActor
|
|||
DebugLog("{0}: UnlinkAChildFromMe: RemoveConstraint between root prim {1} and child prim {2}",
|
||||
LogHeader, LocalID, childPrim.LocalID);
|
||||
DetailLog("{0},UnlinkAChildFromMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
|
||||
BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
|
||||
// BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
|
||||
_scene.Constraints.RemoveAndDestroyConstraint(this.Body, childPrim.Body);
|
||||
}
|
||||
|
||||
// Remove linkage between myself and any possible children I might have
|
||||
|
@ -1348,7 +1361,8 @@ public sealed class BSPrim : PhysicsActor
|
|||
{
|
||||
DebugLog("{0}: UnlinkAllChildren:", LogHeader);
|
||||
DetailLog("{0},UnlinkAllChildren,taint", LocalID);
|
||||
BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
|
||||
_scene.Constraints.RemoveAndDestroyConstraint(this.Body);
|
||||
// BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
|
||||
}
|
||||
|
||||
#endregion // Linkset creation and destruction
|
||||
|
|
|
@ -103,6 +103,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
get { return m_sculptLOD; }
|
||||
}
|
||||
|
||||
private BulletSim m_worldSim;
|
||||
public BulletSim World
|
||||
{
|
||||
get { return m_worldSim; }
|
||||
}
|
||||
private BSConstraintCollection m_constraintCollection;
|
||||
public BSConstraintCollection Constraints
|
||||
{
|
||||
get { return m_constraintCollection; }
|
||||
}
|
||||
|
||||
private int m_maxSubSteps;
|
||||
private float m_fixedTimeStep;
|
||||
private long m_simulationStep = 0;
|
||||
|
@ -229,6 +240,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
|
||||
|
||||
// Initialization to support the transition to a new API which puts most of the logic
|
||||
// into the C# code so it is easier to modify and add to.
|
||||
m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID));
|
||||
m_constraintCollection = new BSConstraintCollection(World);
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
|
@ -237,116 +253,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
private void GetInitialParameterValues(IConfigSource config)
|
||||
{
|
||||
ConfigurationParameters parms = new ConfigurationParameters();
|
||||
m_params[0] = parms;
|
||||
|
||||
_meshSculptedPrim = true; // mesh sculpted prims
|
||||
_forceSimplePrimMeshing = false; // use complex meshing if called for
|
||||
|
||||
m_meshLOD = 8f;
|
||||
m_sculptLOD = 32f;
|
||||
|
||||
shouldDebugLog = false;
|
||||
m_detailedStatsStep = 0; // disabled
|
||||
|
||||
m_maxSubSteps = 10;
|
||||
m_fixedTimeStep = 1f / 60f;
|
||||
m_maxCollisionsPerFrame = 2048;
|
||||
m_maxUpdatesPerFrame = 2048;
|
||||
m_maximumObjectMass = 10000.01f;
|
||||
|
||||
PID_D = 2200f;
|
||||
PID_P = 900f;
|
||||
|
||||
parms.defaultFriction = 0.5f;
|
||||
parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
|
||||
parms.defaultRestitution = 0f;
|
||||
parms.collisionMargin = 0.0f;
|
||||
parms.gravity = -9.80665f;
|
||||
|
||||
parms.linearDamping = 0.0f;
|
||||
parms.angularDamping = 0.0f;
|
||||
parms.deactivationTime = 0.2f;
|
||||
parms.linearSleepingThreshold = 0.8f;
|
||||
parms.angularSleepingThreshold = 1.0f;
|
||||
parms.ccdMotionThreshold = 0.0f; // set to zero to disable
|
||||
parms.ccdSweptSphereRadius = 0.0f;
|
||||
parms.contactProcessingThreshold = 0.1f;
|
||||
|
||||
parms.terrainFriction = 0.5f;
|
||||
parms.terrainHitFraction = 0.8f;
|
||||
parms.terrainRestitution = 0f;
|
||||
parms.avatarFriction = 0.5f;
|
||||
parms.avatarRestitution = 0.0f;
|
||||
parms.avatarDensity = 60f;
|
||||
parms.avatarCapsuleRadius = 0.37f;
|
||||
parms.avatarCapsuleHeight = 1.5f; // 2.140599f
|
||||
parms.avatarContactProcessingThreshold = 0.1f;
|
||||
|
||||
parms.maxPersistantManifoldPoolSize = 0f;
|
||||
parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue;
|
||||
parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse;
|
||||
parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse;
|
||||
parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse;
|
||||
parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse;
|
||||
parms.numberOfSolverIterations = 0f; // means use default
|
||||
SetParameterDefaultValues();
|
||||
|
||||
if (config != null)
|
||||
{
|
||||
// If there are specifications in the ini file, use those values
|
||||
// WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO UPDATE OpenSimDefaults.ini
|
||||
// ALSO REMEMBER TO UPDATE THE RUNTIME SETTING OF THE PARAMETERS.
|
||||
IConfig pConfig = config.Configs["BulletSim"];
|
||||
if (pConfig != null)
|
||||
{
|
||||
_meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim);
|
||||
_forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing);
|
||||
|
||||
shouldDebugLog = pConfig.GetBoolean("ShouldDebugLog", shouldDebugLog);
|
||||
m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep);
|
||||
|
||||
m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD);
|
||||
m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD);
|
||||
|
||||
m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps);
|
||||
m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep);
|
||||
m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame);
|
||||
m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
|
||||
m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
|
||||
|
||||
PID_D = pConfig.GetFloat("PIDDerivative", PID_D);
|
||||
PID_P = pConfig.GetFloat("PIDProportional", PID_P);
|
||||
|
||||
parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
|
||||
parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
|
||||
parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
|
||||
parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin);
|
||||
parms.gravity = pConfig.GetFloat("Gravity", parms.gravity);
|
||||
|
||||
parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping);
|
||||
parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping);
|
||||
parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime);
|
||||
parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold);
|
||||
parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold);
|
||||
parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold);
|
||||
parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius);
|
||||
parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold);
|
||||
|
||||
parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction);
|
||||
parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction);
|
||||
parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution);
|
||||
parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction);
|
||||
parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution);
|
||||
parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity);
|
||||
parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius);
|
||||
parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight);
|
||||
parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold);
|
||||
|
||||
parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize);
|
||||
parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation);
|
||||
parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs);
|
||||
parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder);
|
||||
parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
|
||||
parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
|
||||
parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
|
||||
SetParameterConfigurationValues(pConfig);
|
||||
|
||||
// Very detailed logging for physics debugging
|
||||
m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
|
||||
|
@ -357,7 +274,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||
}
|
||||
}
|
||||
m_params[0] = parms;
|
||||
}
|
||||
|
||||
// A helper function that handles a true/false parameter and returns the proper float number encoding
|
||||
|
@ -634,6 +550,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
// make sure no stepping happens while we're deleting stuff
|
||||
m_initialized = false;
|
||||
|
||||
if (m_constraintCollection != null)
|
||||
{
|
||||
m_constraintCollection.Dispose();
|
||||
m_constraintCollection = null;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
||||
{
|
||||
kvp.Value.Destroy();
|
||||
|
@ -776,10 +698,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
}
|
||||
|
||||
// The calls to the PhysicsActors can't directly call into the physics engine
|
||||
// because it might be busy. We we delay changes to a known time.
|
||||
// because it might be busy. We delay changes to a known time.
|
||||
// We rely on C#'s closure to save and restore the context for the delegate.
|
||||
public void TaintedObject(TaintCallback callback)
|
||||
{
|
||||
if (!m_initialized) return;
|
||||
|
||||
lock (_taintLock)
|
||||
_taintedObjects.Add(callback);
|
||||
return;
|
||||
|
@ -853,61 +777,371 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
}
|
||||
#endregion Vehicles
|
||||
|
||||
#region Runtime settable parameters
|
||||
public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[]
|
||||
#region Parameters
|
||||
|
||||
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);
|
||||
|
||||
private struct ParameterDefn
|
||||
{
|
||||
new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"),
|
||||
new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"),
|
||||
new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"),
|
||||
new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"),
|
||||
new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"),
|
||||
new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"),
|
||||
public string name;
|
||||
public string desc;
|
||||
public float defaultValue;
|
||||
public ParamUser userParam;
|
||||
public ParamGet getter;
|
||||
public ParamSet setter;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"),
|
||||
new PhysParameterEntry("DefaultDensity", "Density for new objects" ),
|
||||
new PhysParameterEntry("DefaultRestitution", "Bouncyness of an object" ),
|
||||
// new PhysParameterEntry("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!!)" ),
|
||||
new PhysParameterEntry("Gravity", "Vertical force of gravity (negative means down)" ),
|
||||
// List of all of the externally visible parameters.
|
||||
// For each parameter, this table maps a text name to getter and setters.
|
||||
// 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
|
||||
//
|
||||
// To add a new variable, it is best to find an existing definition and copy it.
|
||||
private ParameterDefn[] ParameterDefinitions =
|
||||
{
|
||||
new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||
(s) => { return s.NumericBool(s._meshSculptedPrim); },
|
||||
(s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ),
|
||||
new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||
(s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
|
||||
(s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
|
||||
|
||||
new PhysParameterEntry("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)" ),
|
||||
new PhysParameterEntry("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)" ),
|
||||
new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ),
|
||||
new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ),
|
||||
new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ),
|
||||
new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ),
|
||||
new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ),
|
||||
new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ),
|
||||
// Can only change the following at initialization time. Change the INI file and reboot.
|
||||
new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"),
|
||||
new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"),
|
||||
new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"),
|
||||
new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"),
|
||||
new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"),
|
||||
new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"),
|
||||
new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"),
|
||||
new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
|
||||
8f,
|
||||
(s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.m_meshLOD; },
|
||||
(s,p,l,v) => { s.m_meshLOD = (int)v; } ),
|
||||
new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
|
||||
32,
|
||||
(s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.m_sculptLOD; },
|
||||
(s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
|
||||
|
||||
new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ),
|
||||
new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ),
|
||||
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("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||
10000.01f,
|
||||
(s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)s.m_maximumObjectMass; },
|
||||
(s,p,l,v) => { s.m_maximumObjectMass = v; } ),
|
||||
|
||||
new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ),
|
||||
new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ),
|
||||
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 PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ),
|
||||
new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ),
|
||||
new PhysParameterEntry("TerrainRestitution", "Bouncyness" ),
|
||||
new PhysParameterEntry("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation." ),
|
||||
new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ),
|
||||
new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ),
|
||||
new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ),
|
||||
new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ),
|
||||
new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions")
|
||||
new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
|
||||
0.5f,
|
||||
(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!)",
|
||||
0f,
|
||||
(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.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,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.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
|
||||
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.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, 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.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, 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.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, 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.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, 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.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, 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.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, 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.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
|
||||
|
||||
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||
0.5f,
|
||||
(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; s.TaintedUpdateParameter(p,l,v); } ),
|
||||
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; s.TaintedUpdateParameter(p,l,v); } ),
|
||||
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; s.TaintedUpdateParameter(p,l,v); } ),
|
||||
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
|
||||
0.5f,
|
||||
(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.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, 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.UpdateParameterAvatars(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.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
|
||||
new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
|
||||
0.37f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarCapsuleRadius; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, 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.UpdateParameterAvatars(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.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
|
||||
|
||||
|
||||
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)",
|
||||
0f, // zero to disable
|
||||
(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("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = 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.numericFalse,
|
||||
(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.numericFalse,
|
||||
(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("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(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("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.m_detailedStatsStep; },
|
||||
(s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
|
||||
new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||
(s) => { return s.NumericBool(s.shouldDebugLog); },
|
||||
(s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(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];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -919,63 +1153,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
// value activated ('terrainFriction' for instance).
|
||||
public bool SetPhysicsParameter(string parm, float val, uint localID)
|
||||
{
|
||||
bool ret = true;
|
||||
string lparm = parm.ToLower();
|
||||
switch (lparm)
|
||||
bool ret = false;
|
||||
ParameterDefn theParam;
|
||||
if (TryGetParameter(parm, out theParam))
|
||||
{
|
||||
case "detailedstats": m_detailedStatsStep = (int)val; break;
|
||||
|
||||
case "meshlod": m_meshLOD = (int)val; break;
|
||||
case "sculptlod": m_sculptLOD = (int)val; break;
|
||||
case "maxsubstep": m_maxSubSteps = (int)val; break;
|
||||
case "fixedtimestep": m_fixedTimeStep = val; break;
|
||||
case "maxobjectmass": m_maximumObjectMass = val; break;
|
||||
|
||||
case "defaultfriction": m_params[0].defaultFriction = val; break;
|
||||
case "defaultdensity": m_params[0].defaultDensity = val; break;
|
||||
case "defaultrestitution": m_params[0].defaultRestitution = val; break;
|
||||
case "collisionmargin": m_params[0].collisionMargin = val; break;
|
||||
case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break;
|
||||
|
||||
case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break;
|
||||
case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
|
||||
case "deactivationtime": UpdateParameterPrims(ref m_params[0].deactivationTime, lparm, localID, val); break;
|
||||
case "linearsleepingthreshold": UpdateParameterPrims(ref m_params[0].linearSleepingThreshold, lparm, localID, val); break;
|
||||
case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
|
||||
case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break;
|
||||
case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break;
|
||||
case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break;
|
||||
// the following are used only at initialization time so setting them makes no sense
|
||||
// case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break;
|
||||
// case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break;
|
||||
// case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break;
|
||||
// case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break;
|
||||
// case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break;
|
||||
// case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break;
|
||||
// case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break;
|
||||
|
||||
case "friction": TaintedUpdateParameter(lparm, localID, val); break;
|
||||
case "restitution": TaintedUpdateParameter(lparm, localID, val); break;
|
||||
|
||||
// set a terrain physical feature and cause terrain to be recalculated
|
||||
case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break;
|
||||
case "terrainhitfraction": m_params[0].terrainHitFraction = val; TaintedUpdateParameter("terrain", 0, val); break;
|
||||
case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break;
|
||||
// set an avatar physical feature and cause avatar(s) to be recalculated
|
||||
case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break;
|
||||
case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break;
|
||||
case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break;
|
||||
case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break;
|
||||
case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break;
|
||||
case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break;
|
||||
|
||||
default: ret = false; break;
|
||||
theParam.setter(this, parm, localID, val);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// check to see if we are updating a parameter for a particular or all of the prims
|
||||
private void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
|
||||
protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
|
||||
{
|
||||
List<uint> operateOn;
|
||||
lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
|
||||
|
@ -983,7 +1172,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
}
|
||||
|
||||
// check to see if we are updating a parameter for a particular or all of the avatars
|
||||
private void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
|
||||
protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
|
||||
{
|
||||
List<uint> operateOn;
|
||||
lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
|
||||
|
@ -994,7 +1183,7 @@ public 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 UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
|
||||
protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
|
||||
{
|
||||
switch (localID)
|
||||
{
|
||||
|
@ -1021,7 +1210,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
}
|
||||
|
||||
// schedule the actual updating of the paramter to when the phys engine is not busy
|
||||
private void TaintedUpdateParameter(string parm, uint localID, float val)
|
||||
protected void TaintedUpdateParameter(string parm, uint localID, float val)
|
||||
{
|
||||
uint xlocalID = localID;
|
||||
string xparm = parm.ToLower();
|
||||
|
@ -1036,50 +1225,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
|||
public bool GetPhysicsParameter(string parm, out float value)
|
||||
{
|
||||
float val = 0f;
|
||||
bool ret = true;
|
||||
switch (parm.ToLower())
|
||||
bool ret = false;
|
||||
ParameterDefn theParam;
|
||||
if (TryGetParameter(parm, out theParam))
|
||||
{
|
||||
case "detailedstats": val = (int)m_detailedStatsStep; break;
|
||||
case "meshlod": val = (float)m_meshLOD; break;
|
||||
case "sculptlod": val = (float)m_sculptLOD; break;
|
||||
case "maxsubstep": val = (float)m_maxSubSteps; break;
|
||||
case "fixedtimestep": val = m_fixedTimeStep; break;
|
||||
case "maxobjectmass": val = m_maximumObjectMass; break;
|
||||
|
||||
case "defaultfriction": val = m_params[0].defaultFriction; break;
|
||||
case "defaultdensity": val = m_params[0].defaultDensity; break;
|
||||
case "defaultrestitution": val = m_params[0].defaultRestitution; break;
|
||||
case "collisionmargin": val = m_params[0].collisionMargin; break;
|
||||
case "gravity": val = m_params[0].gravity; break;
|
||||
|
||||
case "lineardamping": val = m_params[0].linearDamping; break;
|
||||
case "angulardamping": val = m_params[0].angularDamping; break;
|
||||
case "deactivationtime": val = m_params[0].deactivationTime; break;
|
||||
case "linearsleepingthreshold": val = m_params[0].linearSleepingThreshold; break;
|
||||
case "angularsleepingthreshold": val = m_params[0].angularDamping; break;
|
||||
case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break;
|
||||
case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break;
|
||||
case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break;
|
||||
case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break;
|
||||
case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break;
|
||||
case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break;
|
||||
case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break;
|
||||
case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break;
|
||||
case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break;
|
||||
case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break;
|
||||
|
||||
case "terrainfriction": val = m_params[0].terrainFriction; break;
|
||||
case "terrainhitfraction": val = m_params[0].terrainHitFraction; break;
|
||||
case "terrainrestitution": val = m_params[0].terrainRestitution; break;
|
||||
|
||||
case "avatarfriction": val = m_params[0].avatarFriction; break;
|
||||
case "avatardensity": val = m_params[0].avatarDensity; break;
|
||||
case "avatarrestitution": val = m_params[0].avatarRestitution; break;
|
||||
case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break;
|
||||
case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break;
|
||||
case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break;
|
||||
default: ret = false; break;
|
||||
|
||||
val = theParam.getter(this);
|
||||
ret = true;
|
||||
}
|
||||
value = val;
|
||||
return ret;
|
||||
|
|
|
@ -32,6 +32,28 @@ using OpenMetaverse;
|
|||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin {
|
||||
|
||||
// Classes to allow some type checking for the API
|
||||
public struct BulletSim
|
||||
{
|
||||
public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; }
|
||||
public IntPtr Ptr;
|
||||
public uint ID;
|
||||
}
|
||||
|
||||
public struct BulletBody
|
||||
{
|
||||
public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
|
||||
public IntPtr Ptr;
|
||||
public uint ID;
|
||||
}
|
||||
|
||||
public struct BulletConstraint
|
||||
{
|
||||
public BulletConstraint(IntPtr xx) { Ptr = xx; }
|
||||
public IntPtr Ptr;
|
||||
}
|
||||
|
||||
// ===============================================================================
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ConvexHull
|
||||
{
|
||||
|
@ -142,6 +164,11 @@ public struct ConfigurationParameters
|
|||
public float shouldEnableFrictionCaching;
|
||||
public float numberOfSolverIterations;
|
||||
|
||||
public float linkConstraintUseFrameOffset;
|
||||
public float linkConstraintEnableTransMotor;
|
||||
public float linkConstraintTransMotorMaxVel;
|
||||
public float linkConstraintTransMotorMaxForce;
|
||||
|
||||
public const float numericTrue = 1f;
|
||||
public const float numericFalse = 0f;
|
||||
}
|
||||
|
@ -162,6 +189,7 @@ public enum CollisionFlags : uint
|
|||
PHYSICAL_OBJECT = 1 << 12,
|
||||
};
|
||||
|
||||
// ===============================================================================
|
||||
static class BulletSimAPI {
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
|
@ -214,6 +242,7 @@ public static extern bool CreateObject(uint worldID, ShapeData shapeData);
|
|||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
|
||||
|
||||
/* Remove old functionality
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void AddConstraint(uint worldID, uint id1, uint id2,
|
||||
Vector3 frame1, Quaternion frame1rot,
|
||||
|
@ -225,6 +254,7 @@ public static extern bool RemoveConstraintByID(uint worldID, uint id1);
|
|||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
|
||||
*/
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
|
||||
|
@ -350,8 +380,22 @@ public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData);
|
|||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2,
|
||||
Vector3 frame1loc, Quaternion frame1rot,
|
||||
Vector3 frame2loc, Quaternion frame2rot,
|
||||
Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
|
||||
Vector3 frame2loc, Quaternion frame2rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool CalculateTransforms2(IntPtr constrain);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain);
|
||||
|
|
|
@ -914,6 +914,12 @@
|
|||
ShouldEnableFrictionCaching = False;
|
||||
NumberOfSolverIterations = 0;
|
||||
|
||||
; Linkset constraint parameters
|
||||
LinkConstraintUseFrameOffset = True;
|
||||
LinkConstraintEnableTransMotor = True;
|
||||
LinkConstraintTransMotorMaxVel = 5.0;
|
||||
LinkConstraintTransMotorMaxForce = 0.1;
|
||||
|
||||
|
||||
; Whether to mesh sculpties
|
||||
MeshSculptedPrim = true
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue