BulletSim: change nonimal physics frame rate to 55 to give same numbers as ODE.

Change character scaling to represent size of capsule (diameter rather than radius)
Modify create capsule call to pass radius and height.
Eliminate errors when calculating shape inertia (should have some type checking).
connector_plugin
Robert Adams 2012-10-17 08:30:10 -07:00
parent fc33afddd3
commit e87a179c89
6 changed files with 57 additions and 52 deletions

View File

@ -89,13 +89,15 @@ public class BSCharacter : BSPhysObject
_appliedVelocity = OMV.Vector3.Zero; _appliedVelocity = OMV.Vector3.Zero;
_buoyancy = ComputeBuoyancyFromFlying(isFlying); _buoyancy = ComputeBuoyancyFromFlying(isFlying);
_currentFriction = PhysicsScene.Params.avatarStandingFriction; _currentFriction = PhysicsScene.Params.avatarStandingFriction;
_avatarDensity = PhysicsScene.Params.avatarDensity;
// The dimensions of the avatar capsule are kept in the scale. // The dimensions of the avatar capsule are kept in the scale.
// Physics creates a unit capsule which is scaled by the physics engine. // Physics creates a unit capsule which is scaled by the physics engine.
ComputeAvatarScale(_size); ComputeAvatarScale(_size);
_avatarDensity = PhysicsScene.Params.avatarDensity;
// set _avatarVolume and _mass based on capsule size, _density and Scale // set _avatarVolume and _mass based on capsule size, _density and Scale
ComputeAvatarVolumeAndMass(); ComputeAvatarVolumeAndMass();
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw);
ShapeData shapeData = new ShapeData(); ShapeData shapeData = new ShapeData();
shapeData.ID = LocalID; shapeData.ID = LocalID;
@ -103,6 +105,7 @@ public class BSCharacter : BSPhysObject
shapeData.Position = _position; shapeData.Position = _position;
shapeData.Rotation = _orientation; shapeData.Rotation = _orientation;
shapeData.Velocity = _velocity; shapeData.Velocity = _velocity;
shapeData.Size = Scale;
shapeData.Scale = Scale; shapeData.Scale = Scale;
shapeData.Mass = _mass; shapeData.Mass = _mass;
shapeData.Buoyancy = _buoyancy; shapeData.Buoyancy = _buoyancy;
@ -114,8 +117,9 @@ public class BSCharacter : BSPhysObject
PhysicsScene.TaintedObject("BSCharacter.create", delegate() PhysicsScene.TaintedObject("BSCharacter.create", delegate()
{ {
DetailLog("{0},BSCharacter.create,taint", LocalID); DetailLog("{0},BSCharacter.create,taint", LocalID);
PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); // New body and shape into BSBody and BSShape
PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null);
SetPhysicalProperties(); SetPhysicalProperties();
}); });
return; return;
@ -138,7 +142,7 @@ public class BSCharacter : BSPhysObject
ZeroMotion(); ZeroMotion();
OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
ForcePosition = _position; ForcePosition = _position;
@ -151,13 +155,13 @@ public class BSCharacter : BSPhysObject
{ {
BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
} }
BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT);
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr);
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr);
// Do this after the object has been added to the world // Do this after the object has been added to the world
@ -176,7 +180,7 @@ public class BSCharacter : BSPhysObject
get get
{ {
// Avatar capsule size is kept in the scale parameter. // Avatar capsule size is kept in the scale parameter.
return new OMV.Vector3(Scale.X * 2, Scale.Y * 2, Scale.Z); return _size;
} }
set { set {
@ -184,11 +188,13 @@ public class BSCharacter : BSPhysObject
_size = value; _size = value;
ComputeAvatarScale(_size); ComputeAvatarScale(_size);
ComputeAvatarVolumeAndMass(); ComputeAvatarVolumeAndMass();
DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}",
LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw);
PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
{ {
BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
}); });
@ -578,13 +584,13 @@ public class BSCharacter : BSPhysObject
private void ComputeAvatarScale(OMV.Vector3 size) private void ComputeAvatarScale(OMV.Vector3 size)
{ {
OMV.Vector3 newScale = OMV.Vector3.Zero; OMV.Vector3 newScale = OMV.Vector3.Zero;
newScale.X = PhysicsScene.Params.avatarCapsuleRadius; // Scale wants the diameter so mult radius by two
newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; newScale.X = PhysicsScene.Params.avatarCapsuleRadius * 2f;
newScale.Y = PhysicsScene.Params.avatarCapsuleRadius * 2f;
// The 1.15 came from ODE but it seems to cause the avatar to float off the ground // From the total height, add the capsule half spheres that are at each end
// Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); // newScale.Z = (size.Z) - Math.Min(newScale.X, newScale.Y);
// From the total height, remove the capsule half spheres that are at each end newScale.Z = (size.Z * 2f);
newScale.Z = (size.Z) - (Math.Min(newScale.X, newScale.Y) * 2f);
Scale = newScale; Scale = newScale;
} }
@ -593,14 +599,14 @@ public class BSCharacter : BSPhysObject
{ {
_avatarVolume = (float)( _avatarVolume = (float)(
Math.PI Math.PI
* Scale.X * (Scale.X / 2f)
* Scale.Y // the area of capsule cylinder * (Scale.Y / 2f) // the area of capsule cylinder
* Scale.Z // times height of capsule cylinder * Scale.Z // times height of capsule cylinder
+ 1.33333333f + 1.33333333f
* Math.PI * Math.PI
* Scale.X * (Scale.X / 2f)
* Math.Min(Scale.X, Scale.Y) * (Math.Min(Scale.X, Scale.Y) / 2f)
* Scale.Y // plus the volume of the capsule end caps * (Scale.Y / 2f) // plus the volume of the capsule end caps
); );
_mass = _avatarDensity * _avatarVolume; _mass = _avatarDensity * _avatarVolume;
} }

View File

@ -141,18 +141,15 @@ public abstract class BSPhysObject : PhysicsActor
// if someone has subscribed for collision events.... // if someone has subscribed for collision events....
if (SubscribedEvents()) { if (SubscribedEvents()) {
CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
// DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
// LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
ret = true; ret = true;
} }
return ret; return ret;
} }
// Routine to send the collected collisions into the simulator. // Send the collected collisions into the simulator.
// Also handles removal of this from the collection of objects with collisions if
// there are no collisions from this object. Mechanism is create one last
// collision event to make collision_end work.
// Called at taint time from within the Step() function thus no locking problems // Called at taint time from within the Step() function thus no locking problems
// with CollisionCollection and ObjectsWithNoMoreCollisions. // with CollisionCollection and ObjectsWithNoMoreCollisions.
// Return 'true' if there were some actual collisions passed up // Return 'true' if there were some actual collisions passed up
@ -161,10 +158,9 @@ public abstract class BSPhysObject : PhysicsActor
bool ret = true; bool ret = true;
// throttle the collisions to the number of milliseconds specified in the subscription // throttle the collisions to the number of milliseconds specified in the subscription
int nowTime = PhysicsScene.SimulationNowTime; if (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)
if (nowTime >= NextCollisionOkTime)
{ {
NextCollisionOkTime = nowTime + SubscribedEventsMs; NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs;
// We are called if we previously had collisions. If there are no collisions // We are called if we previously had collisions. If there are no collisions
// this time, send up one last empty event so OpenSim can sense collision end. // this time, send up one last empty event so OpenSim can sense collision end.

View File

@ -48,10 +48,10 @@ public sealed class BSPrim : BSPhysObject
private PrimitiveBaseShape _pbs; private PrimitiveBaseShape _pbs;
// _size is what the user passed. _scale is what we pass to the physics engine with the mesh. // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
// Often _scale is unity because the meshmerizer will apply _size when creating the mesh. // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
private bool _grabbed; private bool _grabbed;
private bool _isSelected; private bool _isSelected;
@ -98,7 +98,7 @@ public sealed class BSPrim : BSPhysObject
_physicsActorType = (int)ActorTypes.Prim; _physicsActorType = (int)ActorTypes.Prim;
_position = pos; _position = pos;
_size = size; _size = size;
_scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type
_orientation = rotation; _orientation = rotation;
_buoyancy = 1f; _buoyancy = 1f;
_velocity = OMV.Vector3.Zero; _velocity = OMV.Vector3.Zero;
@ -166,7 +166,7 @@ public sealed class BSPrim : BSPhysObject
// Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
// scale and margins are set. // scale and margins are set.
CreateGeomAndObject(true); CreateGeomAndObject(true);
// DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical); // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, Scale, _mass, IsPhysical);
}); });
} }
} }
@ -1224,7 +1224,8 @@ public sealed class BSPrim : BSPhysObject
shape.Position = _position; shape.Position = _position;
shape.Rotation = _orientation; shape.Rotation = _orientation;
shape.Velocity = _velocity; shape.Velocity = _velocity;
shape.Scale = _scale; shape.Size = _size;
shape.Scale = Scale;
shape.Mass = _isPhysical ? _mass : 0f; shape.Mass = _isPhysical ? _mass : 0f;
shape.Buoyancy = _buoyancy; shape.Buoyancy = _buoyancy;
shape.HullKey = 0; shape.HullKey = 0;
@ -1234,7 +1235,6 @@ public sealed class BSPrim : BSPhysObject
shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue; shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue;
shape.Size = _size;
} }
// 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.

View File

@ -533,7 +533,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
} }
// This is a kludge to get avatar movement updates. // This is a kludge to get avatar movement updates.
// the simulator expects collisions for avatars even if there are have been no collisions. This updates // The simulator expects collisions for avatars even if there are have been no collisions. This updates
// avatar animations and stuff. // avatar animations and stuff.
// If you fix avatar animation updates, remove this overhead and let normal collision processing happen. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
foreach (BSPhysObject bsp in m_avatars) foreach (BSPhysObject bsp in m_avatars)
@ -577,9 +577,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// The physics engine returns the number of milliseconds it simulated this call. // The physics engine returns the number of milliseconds it simulated this call.
// These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
// We multiply by 45 to give a recognizable running rate (45 or less). // We multiply by 55 to give a recognizable running rate (55 or less).
return numSubSteps * m_fixedTimeStep * 1000 * 45; return numSubSteps * m_fixedTimeStep * 1000 * 55;
// return timeStep * 1000 * 45; // return timeStep * 1000 * 55;
} }
// Something has collided // Something has collided
@ -795,7 +795,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
delegate float ParamGet(BSScene scene); delegate float ParamGet(BSScene scene);
delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
private struct ParameterDefn private struct ParameterDefn
@ -805,7 +805,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
public float defaultValue; // default value if not specified anywhere else public float defaultValue; // default value if not specified anywhere else
public ParamUser userParam; // get the value from the configuration file public ParamUser userParam; // get the value from the configuration file
public ParamGet getter; // return the current value stored for this parameter public ParamGet getter; // return the current value stored for this parameter
public ParamSet setter; // set the current value for this parameter public ParamSet setter; // set the current value for this parameter
public SetOnObject onObject; // set the value on an object in the physical domain public SetOnObject onObject; // set the value on an object in the physical domain
public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
{ {
@ -814,7 +814,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
defaultValue = v; defaultValue = v;
userParam = u; userParam = u;
getter = g; getter = g;
setter = s; setter = s;
onObject = null; onObject = null;
} }
public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
@ -824,7 +824,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
defaultValue = v; defaultValue = v;
userParam = u; userParam = u;
getter = g; getter = g;
setter = s; setter = s;
onObject = o; onObject = o;
} }
} }
@ -1266,13 +1266,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
objectIDs.Add(TERRAIN_ID); objectIDs.Add(TERRAIN_ID);
TaintedUpdateParameter(parm, objectIDs, val); TaintedUpdateParameter(parm, objectIDs, val);
break; break;
case PhysParameterEntry.APPLY_TO_ALL: case PhysParameterEntry.APPLY_TO_ALL:
defaultLoc = val; // setting ALL also sets the default value defaultLoc = val; // setting ALL also sets the default value
lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
TaintedUpdateParameter(parm, objectIDs, val); TaintedUpdateParameter(parm, objectIDs, val);
break; break;
default: default:
// setting only one localID // setting only one localID
objectIDs.Add(localID); objectIDs.Add(localID);
TaintedUpdateParameter(parm, objectIDs, val); TaintedUpdateParameter(parm, objectIDs, val);
break; break;
@ -1282,8 +1282,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// schedule the actual updating of the paramter to when the phys engine is not busy // schedule the actual updating of the paramter to when the phys engine is not busy
protected void TaintedUpdateParameter(string parm, List<uint> lIDs, float val) protected void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
{ {
float xval = val; float xval = val;
List<uint> xlIDs = lIDs; List<uint> xlIDs = lIDs;
string xparm = parm; string xparm = parm;
TaintedObject("BSScene.UpdateParameterSet", delegate() { TaintedObject("BSScene.UpdateParameterSet", delegate() {
ParameterDefn thisParam; ParameterDefn thisParam;

View File

@ -417,7 +417,10 @@ public class BSShapeCollection : IDisposable
if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
{ {
newShape = new BulletShape(BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, shapeData), shapeType); // The radius is scaled by 1/2 because we scale by the diameter.
newShape = new BulletShape(
BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 0.5f, 1.0f, shapeData.Scale),
shapeType);
newShape.shapeKey = (System.UInt64)shapeKey; newShape.shapeKey = (System.UInt64)shapeKey;
newShape.isNativeShape = true; newShape.isNativeShape = true;
} }
@ -428,7 +431,7 @@ public class BSShapeCollection : IDisposable
newShape.isNativeShape = true; newShape.isNativeShape = true;
} }
// Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
// DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape);
prim.BSShape = newShape; prim.BSShape = newShape;

View File

@ -608,7 +608,7 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData)
public static extern bool IsNativeShape2(IntPtr shape); public static extern bool IsNativeShape2(IntPtr shape);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr BuildCapsuleShape2(IntPtr world, ShapeData shapeData); public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateCompoundShape2(IntPtr sim); public static extern IntPtr CreateCompoundShape2(IntPtr sim);