BulletSim: Parameters settable from ini file. Linksets. Physical property value tuning
parent
a95f2fe4b3
commit
7640b5abf6
|
@ -51,8 +51,6 @@ public class BSCharacter : PhysicsActor
|
||||||
private Vector3 _position;
|
private Vector3 _position;
|
||||||
private float _mass = 80f;
|
private float _mass = 80f;
|
||||||
public float _density = 60f;
|
public float _density = 60f;
|
||||||
public float CAPSULE_RADIUS = 0.37f;
|
|
||||||
public float CAPSULE_LENGTH = 2.140599f;
|
|
||||||
private Vector3 _force;
|
private Vector3 _force;
|
||||||
private Vector3 _velocity;
|
private Vector3 _velocity;
|
||||||
private Vector3 _torque;
|
private Vector3 _torque;
|
||||||
|
@ -96,7 +94,8 @@ public class BSCharacter : PhysicsActor
|
||||||
_velocity = Vector3.Zero;
|
_velocity = Vector3.Zero;
|
||||||
_buoyancy = 0f; // characters return a buoyancy of zero
|
_buoyancy = 0f; // characters return a buoyancy of zero
|
||||||
_scale = new Vector3(1f, 1f, 1f);
|
_scale = new Vector3(1f, 1f, 1f);
|
||||||
float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
|
float AVvolume = (float) (Math.PI*Math.Pow(_scene.Params.avatarCapsuleRadius, 2)*_scene.Params.avatarCapsuleHeight);
|
||||||
|
_density = _scene.Params.avatarDensity;
|
||||||
_mass = _density*AVvolume;
|
_mass = _density*AVvolume;
|
||||||
|
|
||||||
ShapeData shapeData = new ShapeData();
|
ShapeData shapeData = new ShapeData();
|
||||||
|
@ -109,6 +108,8 @@ public class BSCharacter : PhysicsActor
|
||||||
shapeData.Mass = _mass;
|
shapeData.Mass = _mass;
|
||||||
shapeData.Buoyancy = isFlying ? 1f : 0f;
|
shapeData.Buoyancy = isFlying ? 1f : 0f;
|
||||||
shapeData.Static = ShapeData.numericFalse;
|
shapeData.Static = ShapeData.numericFalse;
|
||||||
|
shapeData.Friction = _scene.Params.avatarFriction;
|
||||||
|
shapeData.Restitution = _scene.Params.defaultRestitution;
|
||||||
|
|
||||||
// do actual create at taint time
|
// do actual create at taint time
|
||||||
_scene.TaintedObject(delegate()
|
_scene.TaintedObject(delegate()
|
||||||
|
@ -395,9 +396,9 @@ public class BSCharacter : PhysicsActor
|
||||||
_acceleration = entprop.Acceleration;
|
_acceleration = entprop.Acceleration;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (_rotationalVelocity != entprop.AngularVelocity)
|
if (_rotationalVelocity != entprop.RotationalVelocity)
|
||||||
{
|
{
|
||||||
_rotationalVelocity = entprop.AngularVelocity;
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed)
|
||||||
|
|
|
@ -71,6 +71,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
private bool _isPhysical;
|
private bool _isPhysical;
|
||||||
private bool _flying;
|
private bool _flying;
|
||||||
private float _friction;
|
private float _friction;
|
||||||
|
private float _restitution;
|
||||||
private bool _setAlwaysRun;
|
private bool _setAlwaysRun;
|
||||||
private bool _throttleUpdates;
|
private bool _throttleUpdates;
|
||||||
private bool _isColliding;
|
private bool _isColliding;
|
||||||
|
@ -101,7 +102,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
private float _PIDHoverTao;
|
private float _PIDHoverTao;
|
||||||
|
|
||||||
public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
||||||
OMV.Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
|
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
|
// m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
|
||||||
_localID = localID;
|
_localID = localID;
|
||||||
|
@ -113,15 +114,16 @@ public sealed class BSPrim : PhysicsActor
|
||||||
_orientation = rotation;
|
_orientation = rotation;
|
||||||
_buoyancy = 1f;
|
_buoyancy = 1f;
|
||||||
_velocity = OMV.Vector3.Zero;
|
_velocity = OMV.Vector3.Zero;
|
||||||
|
_rotationalVelocity = OMV.Vector3.Zero;
|
||||||
_angularVelocity = OMV.Vector3.Zero;
|
_angularVelocity = OMV.Vector3.Zero;
|
||||||
_mesh = mesh;
|
|
||||||
_hullKey = 0;
|
_hullKey = 0;
|
||||||
_pbs = pbs;
|
_pbs = pbs;
|
||||||
_isPhysical = pisPhysical;
|
_isPhysical = pisPhysical;
|
||||||
_isVolumeDetect = false;
|
_isVolumeDetect = false;
|
||||||
_subscribedEventsMs = 0;
|
_subscribedEventsMs = 0;
|
||||||
_friction = _scene.DefaultFriction; // TODO: compute based on object material
|
_friction = _scene.Params.defaultFriction; // TODO: compute based on object material
|
||||||
_density = _scene.DefaultDensity; // TODO: compute based on object material
|
_density = _scene.Params.defaultDensity; // TODO: compute based on object material
|
||||||
|
_restitution = _scene.Params.defaultRestitution;
|
||||||
_parentPrim = null; // not a child or a parent
|
_parentPrim = null; // not a child or a parent
|
||||||
_vehicle = new BSDynamics(this); // add vehicleness
|
_vehicle = new BSDynamics(this); // add vehicleness
|
||||||
_childrenPrims = new List<BSPrim>();
|
_childrenPrims = new List<BSPrim>();
|
||||||
|
@ -132,8 +134,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
// do the actual object creation at taint time
|
// do the actual object creation at taint time
|
||||||
_scene.TaintedObject(delegate()
|
_scene.TaintedObject(delegate()
|
||||||
{
|
{
|
||||||
CreateGeom();
|
RecreateGeomAndObject();
|
||||||
CreateObject();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,6 +240,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I am the root of a linkset and a new child is being added
|
||||||
public void AddChildToLinkset(BSPrim pchild)
|
public void AddChildToLinkset(BSPrim pchild)
|
||||||
{
|
{
|
||||||
BSPrim child = pchild;
|
BSPrim child = pchild;
|
||||||
|
@ -254,6 +256,8 @@ public sealed class BSPrim : PhysicsActor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I am the root of a linkset and one of my children is being removed.
|
||||||
|
// Safe to call even if the child is not really in my linkset.
|
||||||
public void RemoveChildFromLinkset(BSPrim pchild)
|
public void RemoveChildFromLinkset(BSPrim pchild)
|
||||||
{
|
{
|
||||||
BSPrim child = pchild;
|
BSPrim child = pchild;
|
||||||
|
@ -290,6 +294,17 @@ public sealed class BSPrim : PhysicsActor
|
||||||
get { return (_parentPrim == null && _childrenPrims.Count != 0); }
|
get { return (_parentPrim == null && _childrenPrims.Count != 0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set motion values to zero.
|
||||||
|
// Do it to the properties so the values get set in the physics engine.
|
||||||
|
// Push the setting of the values to the viewer.
|
||||||
|
private void ZeroMotion()
|
||||||
|
{
|
||||||
|
Velocity = OMV.Vector3.Zero;
|
||||||
|
_acceleration = OMV.Vector3.Zero;
|
||||||
|
RotationalVelocity = OMV.Vector3.Zero;
|
||||||
|
base.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
public override void LockAngularMotion(OMV.Vector3 axis) { return; }
|
public override void LockAngularMotion(OMV.Vector3 axis) { return; }
|
||||||
|
|
||||||
public override OMV.Vector3 Position {
|
public override OMV.Vector3 Position {
|
||||||
|
@ -390,18 +405,6 @@ public sealed class BSPrim : PhysicsActor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public OMV.Vector3 AngularVelocity
|
|
||||||
{
|
|
||||||
get { return _angularVelocity; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_angularVelocity = value;
|
|
||||||
_scene.TaintedObject(delegate()
|
|
||||||
{
|
|
||||||
BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _angularVelocity);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override OMV.Vector3 Torque {
|
public override OMV.Vector3 Torque {
|
||||||
get { return _torque; }
|
get { return _torque; }
|
||||||
set { _torque = value;
|
set { _torque = value;
|
||||||
|
@ -419,11 +422,11 @@ public sealed class BSPrim : PhysicsActor
|
||||||
get { return _orientation; }
|
get { return _orientation; }
|
||||||
set {
|
set {
|
||||||
_orientation = value;
|
_orientation = value;
|
||||||
|
// m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation);
|
||||||
_scene.TaintedObject(delegate()
|
_scene.TaintedObject(delegate()
|
||||||
{
|
{
|
||||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||||
// m_log.DebugFormat("{0}: set orientation: {1}", LogHeader, _orientation);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -505,8 +508,16 @@ public sealed class BSPrim : PhysicsActor
|
||||||
get { return _rotationalVelocity; }
|
get { return _rotationalVelocity; }
|
||||||
set { _rotationalVelocity = value;
|
set { _rotationalVelocity = value;
|
||||||
// m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
|
// m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
|
||||||
|
_scene.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public OMV.Vector3 AngularVelocity {
|
||||||
|
get { return _angularVelocity; }
|
||||||
|
set { _angularVelocity = value; }
|
||||||
|
}
|
||||||
public override bool Kinematic {
|
public override bool Kinematic {
|
||||||
get { return _kinematic; }
|
get { return _kinematic; }
|
||||||
set { _kinematic = value;
|
set { _kinematic = value;
|
||||||
|
@ -866,9 +877,6 @@ public sealed class BSPrim : PhysicsActor
|
||||||
|
|
||||||
returnMass = _density * volume;
|
returnMass = _density * volume;
|
||||||
|
|
||||||
if (returnMass <= 0)
|
|
||||||
returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
|
|
||||||
|
|
||||||
if (IsRootOfLinkset)
|
if (IsRootOfLinkset)
|
||||||
{
|
{
|
||||||
foreach (BSPrim prim in _childrenPrims)
|
foreach (BSPrim prim in _childrenPrims)
|
||||||
|
@ -877,8 +885,12 @@ public sealed class BSPrim : PhysicsActor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnMass > _scene.maximumMassObject)
|
if (returnMass <= 0)
|
||||||
returnMass = _scene.maximumMassObject;
|
returnMass = 0.0001f;
|
||||||
|
|
||||||
|
if (returnMass > _scene.MaximumObjectMass)
|
||||||
|
returnMass = _scene.MaximumObjectMass;
|
||||||
|
|
||||||
return returnMass;
|
return returnMass;
|
||||||
}// end CalculateMass
|
}// end CalculateMass
|
||||||
#endregion Mass Calculation
|
#endregion Mass Calculation
|
||||||
|
@ -887,6 +899,15 @@ public sealed class BSPrim : PhysicsActor
|
||||||
// No locking here because this is done when we know physics is not simulating
|
// No locking here because this is done when we know physics is not simulating
|
||||||
private void CreateGeom()
|
private void CreateGeom()
|
||||||
{
|
{
|
||||||
|
// Since we're recreating new, get rid of any previously generated shape
|
||||||
|
if (_hullKey != 0)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
|
||||||
|
BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
|
||||||
|
_hullKey = 0;
|
||||||
|
_hulls.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (_mesh == null)
|
if (_mesh == null)
|
||||||
{
|
{
|
||||||
// the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
|
// the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
|
||||||
|
@ -902,21 +923,13 @@ public sealed class BSPrim : PhysicsActor
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: CreateGeom: mesh null. Defaulting to box of size {1}", LogHeader, _size);
|
// m_log.DebugFormat("{0}: CreateGeom: mesh null. Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size);
|
||||||
_shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
|
_shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
|
||||||
_scale = _size;
|
_scale = _size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_hullKey != 0)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
|
|
||||||
BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
|
|
||||||
_hullKey = 0;
|
|
||||||
_hulls.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
int[] indices = _mesh.getIndexListAsInt();
|
int[] indices = _mesh.getIndexListAsInt();
|
||||||
List<OMV.Vector3> vertices = _mesh.getVertexList();
|
List<OMV.Vector3> vertices = _mesh.getVertexList();
|
||||||
|
|
||||||
|
@ -997,7 +1010,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
|
|
||||||
// create the hull definition in Bullet
|
// create the hull definition in Bullet
|
||||||
_hullKey = (ulong)_pbs.GetHashCode();
|
_hullKey = (ulong)_pbs.GetHashCode();
|
||||||
// m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid= {1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
|
// m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
|
||||||
BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
|
BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
|
||||||
_shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
|
_shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
|
||||||
// meshes are already scaled by the meshmerizer
|
// meshes are already scaled by the meshmerizer
|
||||||
|
@ -1006,6 +1019,8 @@ public sealed class BSPrim : PhysicsActor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Callback from convex hull creater with a newly created hull.
|
||||||
|
// Just add it to the collection of hulls for this shape.
|
||||||
private void HullReturn(ConvexResult result)
|
private void HullReturn(ConvexResult result)
|
||||||
{
|
{
|
||||||
_hulls.Add(result);
|
_hulls.Add(result);
|
||||||
|
@ -1019,13 +1034,12 @@ public sealed class BSPrim : PhysicsActor
|
||||||
if (IsRootOfLinkset)
|
if (IsRootOfLinkset)
|
||||||
{
|
{
|
||||||
// Create a linkset around this object
|
// Create a linkset around this object
|
||||||
CreateLinksetWithCompoundHull();
|
// CreateLinksetWithCompoundHull();
|
||||||
// CreateLinksetWithConstraints();
|
CreateLinksetWithConstraints();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// simple object
|
// simple object
|
||||||
// m_log.DebugFormat("{0}: CreateObject. ID={1}", LogHeader, LocalID);
|
|
||||||
ShapeData shape;
|
ShapeData shape;
|
||||||
FillShapeInfo(out shape);
|
FillShapeInfo(out shape);
|
||||||
BulletSimAPI.CreateObject(_scene.WorldID, shape);
|
BulletSimAPI.CreateObject(_scene.WorldID, shape);
|
||||||
|
@ -1034,6 +1048,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
|
|
||||||
// Create a linkset by creating a compound hull at the root prim that consists of all
|
// Create a linkset by creating a compound hull at the root prim that consists of all
|
||||||
// the children.
|
// the children.
|
||||||
|
// NOTE: This does not allow proper collisions with the children prims so it is not a workable solution
|
||||||
void CreateLinksetWithCompoundHull()
|
void CreateLinksetWithCompoundHull()
|
||||||
{
|
{
|
||||||
// If I am the root prim of a linkset, replace my physical shape with all the
|
// If I am the root prim of a linkset, replace my physical shape with all the
|
||||||
|
@ -1055,8 +1070,27 @@ public sealed class BSPrim : PhysicsActor
|
||||||
BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes);
|
BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy prim's info into the BulletSim shape description structure
|
||||||
|
public void FillShapeInfo(out ShapeData shape)
|
||||||
|
{
|
||||||
|
shape.ID = _localID;
|
||||||
|
shape.Type = _shapeType;
|
||||||
|
shape.Position = _position;
|
||||||
|
shape.Rotation = _orientation;
|
||||||
|
shape.Velocity = _velocity;
|
||||||
|
shape.Scale = _scale;
|
||||||
|
shape.Mass = _isPhysical ? _mass : 0f;
|
||||||
|
shape.Buoyancy = _buoyancy;
|
||||||
|
shape.MeshKey = _hullKey;
|
||||||
|
shape.Friction = _friction;
|
||||||
|
shape.Restitution = _restitution;
|
||||||
|
shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
|
||||||
|
shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the linkset by putting constraints between the objects of the set so they cannot move
|
// Create the linkset by putting constraints between the objects of the set so they cannot move
|
||||||
// relative to each other.
|
// relative to each other.
|
||||||
|
// TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added
|
||||||
void CreateLinksetWithConstraints()
|
void CreateLinksetWithConstraints()
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
|
// m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
|
||||||
|
@ -1070,76 +1104,48 @@ public sealed class BSPrim : PhysicsActor
|
||||||
// create constraints between the root prim and each of the children
|
// create constraints between the root prim and each of the children
|
||||||
foreach (BSPrim prim in _childrenPrims)
|
foreach (BSPrim prim in _childrenPrims)
|
||||||
{
|
{
|
||||||
// this is a constraint that allows no freedom of movement between the two objects
|
|
||||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
|
||||||
// m_log.DebugFormat("{0}: CreateObject: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
|
// m_log.DebugFormat("{0}: CreateObject: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
|
||||||
|
|
||||||
|
// Zero motion for children so they don't interpolate
|
||||||
|
prim.ZeroMotion();
|
||||||
|
|
||||||
// relative position normalized to the root prim
|
// relative position normalized to the root prim
|
||||||
OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation);
|
OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation);
|
||||||
// OMV.Quaternion relativeRotation = OMV.Quaternion.Identity;
|
|
||||||
|
|
||||||
// rotation is pointing up the vector between the object centers
|
// relative rotation of the child to the parent
|
||||||
OMV.Quaternion relativeRotation = OMV.Quaternion.CreateFromAxisAngle(childRelativePosition, 0f);
|
OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation;
|
||||||
|
|
||||||
/* // the logic for relative rotation from http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6391
|
|
||||||
OMV.Vector3 rrn = childRelativePosition;
|
|
||||||
rrn.Normalize();
|
|
||||||
rrn /= rrn.X;
|
|
||||||
OMV.Matrix4 rotmat = new OMV.Matrix4(rrn.X, rrn.Y, rrn.Z, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
||||||
OMV.Quaternion relativeRotation = OMV.Quaternion.CreateFromRotationMatrix(rotmat);
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
// this is a constraint that allows no freedom of movement between the two objects
|
||||||
|
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||||
BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID,
|
BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID,
|
||||||
childRelativePosition / 2,
|
childRelativePosition,
|
||||||
relativeRotation,
|
|
||||||
-childRelativePosition / 2,
|
|
||||||
relativeRotation,
|
relativeRotation,
|
||||||
|
OMV.Vector3.Zero,
|
||||||
|
OMV.Quaternion.Identity,
|
||||||
OMV.Vector3.Zero, OMV.Vector3.Zero,
|
OMV.Vector3.Zero, OMV.Vector3.Zero,
|
||||||
OMV.Vector3.Zero, OMV.Vector3.Zero);
|
OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy prim's info into the BulletSim shape description structure
|
|
||||||
public void FillShapeInfo(out ShapeData shape)
|
|
||||||
{
|
|
||||||
shape.ID = _localID;
|
|
||||||
shape.Type = _shapeType;
|
|
||||||
shape.Position = _position;
|
|
||||||
shape.Rotation = _orientation;
|
|
||||||
shape.Velocity = _velocity;
|
|
||||||
shape.Scale = _scale;
|
|
||||||
shape.Mass = _isPhysical ? _mass : 0f;
|
|
||||||
shape.Buoyancy = _buoyancy;
|
|
||||||
shape.MeshKey = _hullKey;
|
|
||||||
shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
|
|
||||||
shape.Friction = _friction;
|
|
||||||
shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rebuild the geometry and object.
|
// Rebuild the geometry and object.
|
||||||
// This is called when the shape changes so we need to recreate the mesh/hull.
|
// This is called when the shape changes so we need to recreate the mesh/hull.
|
||||||
// No locking here because this is done when the physics engine is not simulating
|
// No locking here because this is done when the physics engine is not simulating
|
||||||
private void RecreateGeomAndObject()
|
private void RecreateGeomAndObject()
|
||||||
{
|
{
|
||||||
if (_hullKey != 0)
|
|
||||||
{
|
|
||||||
// if a hull already exists, delete the old one
|
|
||||||
BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
|
|
||||||
_hullKey = 0;
|
|
||||||
}
|
|
||||||
// If this object is complex or we are the root of a linkset, build a mesh.
|
// If this object is complex or we are the root of a linkset, build a mesh.
|
||||||
// The root of a linkset must be a mesh so we can create the linked compound object.
|
// The root of a linkset must be a mesh so we can create the linked compound object.
|
||||||
if (_scene.NeedsMeshing(_pbs) || IsRootOfLinkset )
|
// if (_scene.NeedsMeshing(_pbs) || IsRootOfLinkset )
|
||||||
|
if (_scene.NeedsMeshing(_pbs)) // linksets with constraints don't need a root mesh
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: RecreateGeomAndObject: creating mesh", LogHeader);
|
// m_log.DebugFormat("{0}: RecreateGeomAndObject: creating mesh", LogHeader);
|
||||||
_mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, _scene.meshLOD, _isPhysical);
|
_mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, _scene.MeshLOD, _isPhysical);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// it's a BulletSim native shape.
|
// implement the shape with a Bullet native shape.
|
||||||
_mesh = null;
|
_mesh = null;
|
||||||
}
|
}
|
||||||
CreateGeom(); // create the geometry for this prim
|
CreateGeom();
|
||||||
CreateObject();
|
CreateObject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1152,48 +1158,82 @@ public sealed class BSPrim : PhysicsActor
|
||||||
Rotation = 1 << 1,
|
Rotation = 1 << 1,
|
||||||
Velocity = 1 << 2,
|
Velocity = 1 << 2,
|
||||||
Acceleration = 1 << 3,
|
Acceleration = 1 << 3,
|
||||||
AngularVel = 1 << 4
|
RotationalVel = 1 << 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float ROTATION_TOLERANCE = 0.01f;
|
||||||
|
const float VELOCITY_TOLERANCE = 0.001f;
|
||||||
|
const float POSITION_TOLERANCE = 0.05f;
|
||||||
|
const float ACCELERATION_TOLERANCE = 0.01f;
|
||||||
|
const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
|
||||||
|
const bool SHOULD_DAMP_UPDATES = false;
|
||||||
|
|
||||||
public void UpdateProperties(EntityProperties entprop)
|
public void UpdateProperties(EntityProperties entprop)
|
||||||
{
|
{
|
||||||
UpdatedProperties changed = 0;
|
UpdatedProperties changed = 0;
|
||||||
// assign to the local variables so the normal set action does not happen
|
if (SHOULD_DAMP_UPDATES)
|
||||||
if (_position != entprop.Position)
|
|
||||||
{
|
{
|
||||||
_position = entprop.Position;
|
// assign to the local variables so the normal set action does not happen
|
||||||
// m_log.DebugFormat("{0}: UpdateProperties: position = {1}", LogHeader, _position);
|
// if (_position != entprop.Position)
|
||||||
changed |= UpdatedProperties.Position;
|
if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
|
||||||
|
{
|
||||||
|
_position = entprop.Position;
|
||||||
|
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position);
|
||||||
|
changed |= UpdatedProperties.Position;
|
||||||
|
}
|
||||||
|
// if (_orientation != entprop.Rotation)
|
||||||
|
if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
|
||||||
|
{
|
||||||
|
_orientation = entprop.Rotation;
|
||||||
|
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation);
|
||||||
|
changed |= UpdatedProperties.Rotation;
|
||||||
|
}
|
||||||
|
// if (_velocity != entprop.Velocity)
|
||||||
|
if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
|
||||||
|
{
|
||||||
|
_velocity = entprop.Velocity;
|
||||||
|
// m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity);
|
||||||
|
changed |= UpdatedProperties.Velocity;
|
||||||
|
}
|
||||||
|
// if (_acceleration != entprop.Acceleration)
|
||||||
|
if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
|
||||||
|
{
|
||||||
|
_acceleration = entprop.Acceleration;
|
||||||
|
// m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration);
|
||||||
|
changed |= UpdatedProperties.Acceleration;
|
||||||
|
}
|
||||||
|
// if (_rotationalVelocity != entprop.RotationalVelocity)
|
||||||
|
if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
|
||||||
|
{
|
||||||
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
|
// m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity);
|
||||||
|
changed |= UpdatedProperties.RotationalVel;
|
||||||
|
}
|
||||||
|
if (changed != 0)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
|
||||||
|
// Only update the position of single objects and linkset roots
|
||||||
|
if (this._parentPrim == null)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
|
||||||
|
base.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (_orientation != entprop.Rotation)
|
else
|
||||||
{
|
{
|
||||||
_orientation = entprop.Rotation;
|
// Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
|
||||||
// m_log.DebugFormat("{0}: UpdateProperties: rotation = {1}", LogHeader, _orientation);
|
|
||||||
changed |= UpdatedProperties.Rotation;
|
|
||||||
}
|
|
||||||
if (_velocity != entprop.Velocity)
|
|
||||||
{
|
|
||||||
_velocity = entprop.Velocity;
|
|
||||||
// m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity);
|
|
||||||
changed |= UpdatedProperties.Velocity;
|
|
||||||
}
|
|
||||||
if (_acceleration != entprop.Acceleration)
|
|
||||||
{
|
|
||||||
_acceleration = entprop.Acceleration;
|
|
||||||
// m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration);
|
|
||||||
changed |= UpdatedProperties.Acceleration;
|
|
||||||
}
|
|
||||||
if (_rotationalVelocity != entprop.AngularVelocity)
|
|
||||||
{
|
|
||||||
_rotationalVelocity = entprop.AngularVelocity;
|
|
||||||
// m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity);
|
|
||||||
changed |= UpdatedProperties.AngularVel;
|
|
||||||
}
|
|
||||||
if (changed != 0)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
|
|
||||||
if (this._parentPrim == null)
|
if (this._parentPrim == null)
|
||||||
|
{
|
||||||
|
// Assign to the local variables so the normal set action does not happen
|
||||||
|
_position = entprop.Position;
|
||||||
|
_orientation = entprop.Rotation;
|
||||||
|
_velocity = entprop.Velocity;
|
||||||
|
_acceleration = entprop.Acceleration;
|
||||||
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
|
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
|
||||||
base.RequestPhysicsterseUpdate();
|
base.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1201,7 +1241,8 @@ public sealed class BSPrim : PhysicsActor
|
||||||
public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
||||||
// The following makes IsColliding() and IsCollidingGround() work
|
|
||||||
|
// The following lines make IsColliding() and IsCollidingGround() work
|
||||||
_collidingStep = _scene.SimulationStep;
|
_collidingStep = _scene.SimulationStep;
|
||||||
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,11 +71,17 @@ public class BSScene : PhysicsScene
|
||||||
private uint m_worldID;
|
private uint m_worldID;
|
||||||
public uint WorldID { get { return m_worldID; } }
|
public uint WorldID { get { return m_worldID; } }
|
||||||
|
|
||||||
public IMesher mesher;
|
private bool m_initialized = false;
|
||||||
public int meshLOD = 32;
|
|
||||||
|
|
||||||
private int m_maxSubSteps = 10;
|
public IMesher mesher;
|
||||||
private float m_fixedTimeStep = 1f / 60f;
|
private int m_meshLOD;
|
||||||
|
public int MeshLOD
|
||||||
|
{
|
||||||
|
get { return m_meshLOD; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int m_maxSubSteps;
|
||||||
|
private float m_fixedTimeStep;
|
||||||
private long m_simulationStep = 0;
|
private long m_simulationStep = 0;
|
||||||
public long SimulationStep { get { return m_simulationStep; } }
|
public long SimulationStep { get { return m_simulationStep; } }
|
||||||
|
|
||||||
|
@ -84,68 +90,65 @@ public class BSScene : PhysicsScene
|
||||||
private int m_simulationNowTime;
|
private int m_simulationNowTime;
|
||||||
public int SimulationNowTime { get { return m_simulationNowTime; } }
|
public int SimulationNowTime { get { return m_simulationNowTime; } }
|
||||||
|
|
||||||
private int m_maxCollisionsPerFrame = 2048;
|
private int m_maxCollisionsPerFrame;
|
||||||
private CollisionDesc[] m_collisionArray;
|
private CollisionDesc[] m_collisionArray;
|
||||||
private GCHandle m_collisionArrayPinnedHandle;
|
private GCHandle m_collisionArrayPinnedHandle;
|
||||||
|
|
||||||
private int m_maxUpdatesPerFrame = 2048;
|
private int m_maxUpdatesPerFrame;
|
||||||
private EntityProperties[] m_updateArray;
|
private EntityProperties[] m_updateArray;
|
||||||
private GCHandle m_updateArrayPinnedHandle;
|
private GCHandle m_updateArrayPinnedHandle;
|
||||||
|
|
||||||
private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
|
private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
|
||||||
private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
|
private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
|
||||||
public float maximumMassObject = 10000.01f;
|
|
||||||
|
|
||||||
public const uint TERRAIN_ID = 0;
|
public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
|
||||||
public const uint GROUNDPLANE_ID = 1;
|
public const uint GROUNDPLANE_ID = 1;
|
||||||
|
|
||||||
public float DefaultFriction = 0.70f;
|
public ConfigurationParameters Params
|
||||||
public float DefaultDensity = 10.000006836f; // Aluminum g/cm3; TODO: compute based on object material
|
{
|
||||||
public Vector3 DefaultGravity = new Vector3(0, 0, -9.80665f);
|
get { return m_params[0]; }
|
||||||
|
}
|
||||||
|
public Vector3 DefaultGravity
|
||||||
|
{
|
||||||
|
get { return new Vector3(0f, 0f, Params.gravity); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private float m_maximumObjectMass;
|
||||||
|
public float MaximumObjectMass
|
||||||
|
{
|
||||||
|
get { return m_maximumObjectMass; }
|
||||||
|
}
|
||||||
|
|
||||||
public delegate void TaintCallback();
|
public delegate void TaintCallback();
|
||||||
private List<TaintCallback> _taintedObjects;
|
private List<TaintCallback> _taintedObjects;
|
||||||
private Object _taintLock = new Object();
|
private Object _taintLock = new Object();
|
||||||
|
|
||||||
// A pointer to an instance if this structure is passed to the C++ code
|
// A pointer to an instance if this structure is passed to the C++ code
|
||||||
// Format of this structure must match the definition in the C++ code
|
ConfigurationParameters[] m_params;
|
||||||
private struct ConfigurationParameters
|
|
||||||
{
|
|
||||||
public float defaultFriction;
|
|
||||||
public float defaultDensity;
|
|
||||||
public float collisionMargin;
|
|
||||||
public float gravity;
|
|
||||||
|
|
||||||
public float linearDamping;
|
|
||||||
public float angularDamping;
|
|
||||||
public float deactivationTime;
|
|
||||||
public float linearSleepingThreshold;
|
|
||||||
public float angularSleepingThreshold;
|
|
||||||
|
|
||||||
public float terrainFriction;
|
|
||||||
public float terrainHitFriction;
|
|
||||||
public float terrainRestitution;
|
|
||||||
public float avatarFriction;
|
|
||||||
public float avatarCapsuleRadius;
|
|
||||||
public float avatarCapsuleHeight;
|
|
||||||
}
|
|
||||||
ConfigurationParameters m_params;
|
|
||||||
GCHandle m_paramsHandle;
|
GCHandle m_paramsHandle;
|
||||||
|
|
||||||
private BulletSimAPI.DebugLogCallback debugLogCallbackHandle;
|
private BulletSimAPI.DebugLogCallback debugLogCallbackHandle;
|
||||||
|
|
||||||
public BSScene(string identifier)
|
public BSScene(string identifier)
|
||||||
{
|
{
|
||||||
|
m_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialise(IMesher meshmerizer, IConfigSource config)
|
public override void Initialise(IMesher meshmerizer, IConfigSource config)
|
||||||
{
|
{
|
||||||
m_params = new ConfigurationParameters();
|
// Allocate pinned memory to pass parameters.
|
||||||
|
m_params = new ConfigurationParameters[1];
|
||||||
m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned);
|
m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned);
|
||||||
|
|
||||||
// Set default values for physics parameters plus any overrides from the ini file
|
// Set default values for physics parameters plus any overrides from the ini file
|
||||||
GetInitialParameterValues(config);
|
GetInitialParameterValues(config);
|
||||||
|
|
||||||
|
// allocate more pinned memory close to the above in an attempt to get the memory all together
|
||||||
|
m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
|
||||||
|
m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned);
|
||||||
|
m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
|
||||||
|
m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
|
||||||
|
|
||||||
// if Debug, enable logging from the unmanaged code
|
// if Debug, enable logging from the unmanaged code
|
||||||
if (m_log.IsDebugEnabled)
|
if (m_log.IsDebugEnabled)
|
||||||
{
|
{
|
||||||
|
@ -160,68 +163,95 @@ public class BSScene : PhysicsScene
|
||||||
// The bounding box for the simulated world
|
// The bounding box for the simulated world
|
||||||
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 4096f);
|
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 4096f);
|
||||||
|
|
||||||
// Allocate pinned memory to pass back object property updates and collisions from simulation step
|
|
||||||
m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
|
|
||||||
m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned);
|
|
||||||
m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
|
|
||||||
m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
|
|
||||||
|
|
||||||
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
||||||
m_worldID = BulletSimAPI.Initialize(worldExtent,
|
m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
|
||||||
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
||||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
|
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All default parameter values are set here. There should be no values set in the
|
||||||
|
// variable definitions.
|
||||||
private void GetInitialParameterValues(IConfigSource config)
|
private void GetInitialParameterValues(IConfigSource config)
|
||||||
{
|
{
|
||||||
|
ConfigurationParameters parms = new ConfigurationParameters();
|
||||||
|
|
||||||
_meshSculptedPrim = true; // mesh sculpted prims
|
_meshSculptedPrim = true; // mesh sculpted prims
|
||||||
_forceSimplePrimMeshing = false; // use complex meshing if called for
|
_forceSimplePrimMeshing = false; // use complex meshing if called for
|
||||||
|
|
||||||
// Set the default values for the physics parameters
|
m_meshLOD = 32;
|
||||||
m_params.defaultFriction = 0.70f;
|
|
||||||
m_params.defaultDensity = 10.000006836f; // Aluminum g/cm3
|
|
||||||
m_params.collisionMargin = 0.0f;
|
|
||||||
m_params.gravity = -9.80665f;
|
|
||||||
|
|
||||||
m_params.linearDamping = 0.1f;
|
m_maxSubSteps = 10;
|
||||||
m_params.angularDamping = 0.85f;
|
m_fixedTimeStep = 1f / 60f;
|
||||||
m_params.deactivationTime = 0.2f;
|
m_maxCollisionsPerFrame = 2048;
|
||||||
m_params.linearSleepingThreshold = 0.8f;
|
m_maxUpdatesPerFrame = 2048;
|
||||||
m_params.angularSleepingThreshold = 1.0f;
|
m_maximumObjectMass = 10000.01f;
|
||||||
|
|
||||||
m_params.terrainFriction = 0.85f;
|
parms.defaultFriction = 0.70f;
|
||||||
m_params.terrainHitFriction = 0.8f;
|
parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
|
||||||
m_params.terrainRestitution = 0.2f;
|
parms.defaultRestitution = 0f;
|
||||||
m_params.avatarFriction = 0.85f;
|
parms.collisionMargin = 0.0f;
|
||||||
m_params.avatarCapsuleRadius = 0.37f;
|
parms.gravity = -9.80665f;
|
||||||
m_params.avatarCapsuleHeight = 1.5f; // 2.140599f
|
|
||||||
|
parms.linearDamping = 0.0f;
|
||||||
|
parms.angularDamping = 0.0f;
|
||||||
|
parms.deactivationTime = 0.2f;
|
||||||
|
parms.linearSleepingThreshold = 0.8f;
|
||||||
|
parms.angularSleepingThreshold = 1.0f;
|
||||||
|
parms.ccdMotionThreshold = 0.5f; // set to zero to disable
|
||||||
|
parms.ccdSweptSphereRadius = 0.2f;
|
||||||
|
|
||||||
|
parms.terrainFriction = 0.85f;
|
||||||
|
parms.terrainHitFriction = 0.8f;
|
||||||
|
parms.terrainRestitution = 0.2f;
|
||||||
|
parms.avatarFriction = 0.85f;
|
||||||
|
parms.avatarDensity = 60f;
|
||||||
|
parms.avatarCapsuleRadius = 0.37f;
|
||||||
|
parms.avatarCapsuleHeight = 1.5f; // 2.140599f
|
||||||
|
|
||||||
if (config != null)
|
if (config != null)
|
||||||
{
|
{
|
||||||
// If there are specifications in the ini file, use those values
|
// If there are specifications in the ini file, use those values
|
||||||
|
// WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO ALSO UPDATE OpenSimDefaults.ini
|
||||||
IConfig pConfig = config.Configs["BulletSim"];
|
IConfig pConfig = config.Configs["BulletSim"];
|
||||||
if (pConfig != null)
|
if (pConfig != null)
|
||||||
{
|
{
|
||||||
_meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", true);
|
_meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim);
|
||||||
_forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", false);
|
_forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing);
|
||||||
|
|
||||||
m_params.defaultFriction = pConfig.GetFloat("DefaultFriction", m_params.defaultFriction);
|
m_meshLOD = pConfig.GetInt("MeshLevelOfDetail", m_meshLOD);
|
||||||
m_params.defaultDensity = pConfig.GetFloat("DefaultDensity", m_params.defaultDensity);
|
|
||||||
m_params.collisionMargin = pConfig.GetFloat("CollisionMargin", m_params.collisionMargin);
|
m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps);
|
||||||
m_params.gravity = pConfig.GetFloat("Gravity", m_params.gravity);
|
m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep);
|
||||||
m_params.linearDamping = pConfig.GetFloat("LinearDamping", m_params.linearDamping);
|
m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame);
|
||||||
m_params.angularDamping = pConfig.GetFloat("AngularDamping", m_params.angularDamping);
|
m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
|
||||||
m_params.deactivationTime = pConfig.GetFloat("DeactivationTime", m_params.deactivationTime);
|
m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
|
||||||
m_params.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", m_params.linearSleepingThreshold);
|
|
||||||
m_params.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", m_params.angularSleepingThreshold);
|
parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
|
||||||
m_params.terrainFriction = pConfig.GetFloat("TerrainFriction", m_params.terrainFriction);
|
parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
|
||||||
m_params.terrainHitFriction = pConfig.GetFloat("TerrainHitFriction", m_params.terrainHitFriction);
|
parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
|
||||||
m_params.terrainRestitution = pConfig.GetFloat("TerrainRestitution", m_params.terrainRestitution);
|
parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin);
|
||||||
m_params.avatarFriction = pConfig.GetFloat("AvatarFriction", m_params.avatarFriction);
|
parms.gravity = pConfig.GetFloat("Gravity", parms.gravity);
|
||||||
m_params.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", m_params.avatarCapsuleRadius);
|
|
||||||
m_params.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", m_params.avatarCapsuleHeight);
|
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.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction);
|
||||||
|
parms.terrainHitFriction = pConfig.GetFloat("TerrainHitFriction", parms.terrainHitFriction);
|
||||||
|
parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution);
|
||||||
|
parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction);
|
||||||
|
parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity);
|
||||||
|
parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius);
|
||||||
|
parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_params[0] = parms;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called directly from unmanaged code so don't do much
|
// Called directly from unmanaged code so don't do much
|
||||||
|
@ -282,20 +312,13 @@ public class BSScene : PhysicsScene
|
||||||
Vector3 size, Quaternion rotation, bool isPhysical, uint localID)
|
Vector3 size, Quaternion rotation, bool isPhysical, uint localID)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName);
|
// m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName);
|
||||||
IMesh mesh = null;
|
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
|
||||||
if (NeedsMeshing(pbs))
|
|
||||||
{
|
|
||||||
// if the prim is complex, create the mesh for it.
|
|
||||||
// If simple (box or sphere) leave 'mesh' null and physics will do a native shape.
|
|
||||||
mesh = mesher.CreateMesh(primName, pbs, size, this.meshLOD, isPhysical);
|
|
||||||
}
|
|
||||||
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, mesh, pbs, isPhysical);
|
|
||||||
lock (m_prims) m_prims.Add(localID, prim);
|
lock (m_prims) m_prims.Add(localID, prim);
|
||||||
return prim;
|
return prim;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a call from the simulator saying that some physical property has been updated.
|
// This is a call from the simulator saying that some physical property has been updated.
|
||||||
// The BulletS driver senses the changing of relevant properties so this taint
|
// The BulletSim driver senses the changing of relevant properties so this taint
|
||||||
// information call is not needed.
|
// information call is not needed.
|
||||||
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
|
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
|
||||||
|
|
||||||
|
@ -307,6 +330,9 @@ public class BSScene : PhysicsScene
|
||||||
int collidersCount;
|
int collidersCount;
|
||||||
IntPtr collidersPtr;
|
IntPtr collidersPtr;
|
||||||
|
|
||||||
|
// prevent simulation until we've been initialized
|
||||||
|
if (!m_initialized) return 10.0f;
|
||||||
|
|
||||||
// update the prim states while we know the physics engine is not busy
|
// update the prim states while we know the physics engine is not busy
|
||||||
ProcessTaints();
|
ProcessTaints();
|
||||||
|
|
||||||
|
@ -360,7 +386,7 @@ public class BSScene : PhysicsScene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fps calculation wrong. This calculation always returns about 1 in normal operation.
|
// FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation.
|
||||||
return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
|
return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,8 +395,7 @@ public class BSScene : PhysicsScene
|
||||||
{
|
{
|
||||||
if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
|
if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
|
||||||
{
|
{
|
||||||
// we never send collisions to the terrain
|
return; // don't send collisions to the terrain
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorTypes type = ActorTypes.Prim;
|
ActorTypes type = ActorTypes.Prim;
|
||||||
|
@ -381,12 +406,12 @@ public class BSScene : PhysicsScene
|
||||||
|
|
||||||
BSPrim prim;
|
BSPrim prim;
|
||||||
if (m_prims.TryGetValue(localID, out prim)) {
|
if (m_prims.TryGetValue(localID, out prim)) {
|
||||||
prim.Collide(collidingWith, type, collidePoint, collideNormal, 0.01f);
|
prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BSCharacter actor;
|
BSCharacter actor;
|
||||||
if (m_avatars.TryGetValue(localID, out actor)) {
|
if (m_avatars.TryGetValue(localID, out actor)) {
|
||||||
actor.Collide(collidingWith, type, collidePoint, collideNormal, 0.01f);
|
actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -448,7 +473,7 @@ public class BSScene : PhysicsScene
|
||||||
|
|
||||||
if (pbs.SculptEntry && !_meshSculptedPrim)
|
if (pbs.SculptEntry && !_meshSculptedPrim)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: NeedsMeshing: scultpy mesh", LogHeader);
|
// Render sculpties as boxes
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,14 @@ using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin {
|
namespace OpenSim.Region.Physics.BulletSPlugin {
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct ConvexHull
|
public struct ConvexHull
|
||||||
{
|
{
|
||||||
Vector3 Offset;
|
Vector3 Offset;
|
||||||
int VertexCount;
|
int VertexCount;
|
||||||
Vector3[] Vertices;
|
Vector3[] Vertices;
|
||||||
}
|
}
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct ShapeData
|
public struct ShapeData
|
||||||
{
|
{
|
||||||
public enum PhysicsShapeType
|
public enum PhysicsShapeType
|
||||||
|
@ -49,6 +51,7 @@ public struct ShapeData
|
||||||
SHAPE_SPHERE = 4,
|
SHAPE_SPHERE = 4,
|
||||||
SHAPE_HULL = 5
|
SHAPE_HULL = 5
|
||||||
};
|
};
|
||||||
|
// note that bools are passed as ints since bool size changes by language
|
||||||
public const int numericTrue = 1;
|
public const int numericTrue = 1;
|
||||||
public const int numericFalse = 0;
|
public const int numericFalse = 0;
|
||||||
public uint ID;
|
public uint ID;
|
||||||
|
@ -60,11 +63,12 @@ public struct ShapeData
|
||||||
public float Mass;
|
public float Mass;
|
||||||
public float Buoyancy;
|
public float Buoyancy;
|
||||||
public System.UInt64 MeshKey;
|
public System.UInt64 MeshKey;
|
||||||
public int Collidable;
|
|
||||||
public float Friction;
|
public float Friction;
|
||||||
|
public float Restitution;
|
||||||
|
public int Collidable;
|
||||||
public int Static; // true if a static object. Otherwise gravity, etc.
|
public int Static; // true if a static object. Otherwise gravity, etc.
|
||||||
// note that bools are passed as ints since bool size changes by language
|
|
||||||
}
|
}
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct SweepHit
|
public struct SweepHit
|
||||||
{
|
{
|
||||||
public uint ID;
|
public uint ID;
|
||||||
|
@ -72,12 +76,14 @@ public struct SweepHit
|
||||||
public Vector3 Normal;
|
public Vector3 Normal;
|
||||||
public Vector3 Point;
|
public Vector3 Point;
|
||||||
}
|
}
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct RaycastHit
|
public struct RaycastHit
|
||||||
{
|
{
|
||||||
public uint ID;
|
public uint ID;
|
||||||
public float Fraction;
|
public float Fraction;
|
||||||
public Vector3 Normal;
|
public Vector3 Normal;
|
||||||
}
|
}
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct CollisionDesc
|
public struct CollisionDesc
|
||||||
{
|
{
|
||||||
public uint aID;
|
public uint aID;
|
||||||
|
@ -85,6 +91,7 @@ public struct CollisionDesc
|
||||||
public Vector3 point;
|
public Vector3 point;
|
||||||
public Vector3 normal;
|
public Vector3 normal;
|
||||||
}
|
}
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct EntityProperties
|
public struct EntityProperties
|
||||||
{
|
{
|
||||||
public uint ID;
|
public uint ID;
|
||||||
|
@ -92,13 +99,42 @@ public struct EntityProperties
|
||||||
public Quaternion Rotation;
|
public Quaternion Rotation;
|
||||||
public Vector3 Velocity;
|
public Vector3 Velocity;
|
||||||
public Vector3 Acceleration;
|
public Vector3 Acceleration;
|
||||||
public Vector3 AngularVelocity;
|
public Vector3 RotationalVelocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format of this structure must match the definition in the C++ code
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct ConfigurationParameters
|
||||||
|
{
|
||||||
|
public float defaultFriction;
|
||||||
|
public float defaultDensity;
|
||||||
|
public float defaultRestitution;
|
||||||
|
public float collisionMargin;
|
||||||
|
public float gravity;
|
||||||
|
|
||||||
|
public float linearDamping;
|
||||||
|
public float angularDamping;
|
||||||
|
public float deactivationTime;
|
||||||
|
public float linearSleepingThreshold;
|
||||||
|
public float angularSleepingThreshold;
|
||||||
|
public float ccdMotionThreshold;
|
||||||
|
public float ccdSweptSphereRadius;
|
||||||
|
|
||||||
|
public float terrainFriction;
|
||||||
|
public float terrainHitFriction;
|
||||||
|
public float terrainRestitution;
|
||||||
|
public float avatarFriction;
|
||||||
|
public float avatarDensity;
|
||||||
|
public float avatarRestitution;
|
||||||
|
public float avatarCapsuleRadius;
|
||||||
|
public float avatarCapsuleHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class BulletSimAPI {
|
static class BulletSimAPI {
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern uint Initialize(Vector3 maxPosition, int maxCollisions, IntPtr collisionArray,
|
public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
|
||||||
|
int maxCollisions, IntPtr collisionArray,
|
||||||
int maxUpdates, IntPtr updateArray);
|
int maxUpdates, IntPtr updateArray);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -159,6 +159,7 @@
|
||||||
;physics = basicphysics
|
;physics = basicphysics
|
||||||
;physics = POS
|
;physics = POS
|
||||||
;physics = modified_BulletX
|
;physics = modified_BulletX
|
||||||
|
;physics = BulletSim
|
||||||
|
|
||||||
; ##
|
; ##
|
||||||
; ## PERMISSIONS
|
; ## PERMISSIONS
|
||||||
|
@ -725,6 +726,47 @@
|
||||||
; true. Note that this will increase memory usage and region startup time. Default is false.
|
; true. Note that this will increase memory usage and region startup time. Default is false.
|
||||||
;force_simple_prim_meshing = true
|
;force_simple_prim_meshing = true
|
||||||
|
|
||||||
|
[BulletSim]
|
||||||
|
; World parameters
|
||||||
|
DefaultFriction = 0.70
|
||||||
|
DefaultDensity = 10.000006836
|
||||||
|
DefaultRestitution = 0.0
|
||||||
|
Gravity = -9.80665
|
||||||
|
|
||||||
|
TerrainFriction = 0.85
|
||||||
|
TerrainHitFriction = 0.8
|
||||||
|
TerrainRestitution = 0.2
|
||||||
|
AvatarFriction = 0.85
|
||||||
|
AvatarDensity = 60.0
|
||||||
|
AvatarCapsuleRadius = 0.37
|
||||||
|
AvatarCapsuleHeight = 1.5
|
||||||
|
|
||||||
|
MaxObjectMass = 10000.01
|
||||||
|
|
||||||
|
; Dynamic parameters
|
||||||
|
LinearDamping = 0.0
|
||||||
|
AngularDamping = 0.0
|
||||||
|
DeactivationTime = 0.2
|
||||||
|
LinearSleepingThreshold = 0.8
|
||||||
|
AngularSleepingThreshold = 1.0
|
||||||
|
CcdMotionThreshold = 0.5
|
||||||
|
CcdSweptSphereRadius = 0.2
|
||||||
|
|
||||||
|
; Whether to mesh sculpties
|
||||||
|
MeshSculptedPrim = true
|
||||||
|
|
||||||
|
; If 'true', force simple prims (box and sphere) to be meshed
|
||||||
|
ForceSimplePrimMeshing = false
|
||||||
|
|
||||||
|
; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies
|
||||||
|
MeshLevelOfDetail = 32
|
||||||
|
|
||||||
|
; Bullet step parameters
|
||||||
|
MaxSubSteps = 10;
|
||||||
|
FixedTimeStep = .01667
|
||||||
|
|
||||||
|
MaxCollisionsPerFrame = 2048
|
||||||
|
MaxUpdatesPerFrame = 2048
|
||||||
|
|
||||||
[RemoteAdmin]
|
[RemoteAdmin]
|
||||||
enabled = false
|
enabled = false
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue