diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2e6b2dad90..7c2f85640b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -41,8 +41,6 @@ public class BSCharacter : BSPhysObject // private bool _stopped; private OMV.Vector3 _size; - private OMV.Vector3 _scale; - private PrimitiveBaseShape _pbs; private bool _grabbed; private bool _selected; private OMV.Vector3 _position; @@ -67,6 +65,10 @@ public class BSCharacter : BSPhysObject private bool _kinematic; private float _buoyancy; + // The friction and velocity of the avatar is modified depending on whether walking or not. + private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar + private float _currentFriction; // the friction currently being used (changed by setVelocity). + private OMV.Vector3 _PIDTarget; private bool _usePID; private float _PIDTau; @@ -84,13 +86,15 @@ public class BSCharacter : BSPhysObject _flying = isFlying; _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; + _appliedVelocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); + _currentFriction = PhysicsScene.Params.avatarStandingFriction; // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. 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(); ShapeData shapeData = new ShapeData(); @@ -99,24 +103,24 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; - shapeData.Scale = _scale; + shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; - shapeData.Friction = PhysicsScene.Params.avatarFriction; + shapeData.Friction = PhysicsScene.Params.avatarStandingFriction; shapeData.Restitution = PhysicsScene.Params.avatarRestitution; // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + + SetPhysicalProperties(); // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. // If not set at creation, the avatar will stop flying when created after crossing a region boundry. - BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); - - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); + ForceBuoyancy = _buoyancy; // This works here because CreateObject has already put the character into the physical world. BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, @@ -131,10 +135,40 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.Destroy", LocalID); PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { - BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); + PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); + PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); }); } + private void SetPhysicalProperties() + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); + + ZeroMotion(); + + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + + // Set the velocity and compute the proper friction + ForceVelocity = _velocity; + + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); + + BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); + BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); + + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } + + BulletSimAPI.SetActivationState2(BSBody.ptr, (int)ActivationState.DISABLE_DEACTIVATION); + + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + } + public override void RequestPhysicsterseUpdate() { base.RequestPhysicsterseUpdate(); @@ -147,7 +181,7 @@ public class BSCharacter : BSPhysObject get { // Avatar capsule size is kept in the scale parameter. - return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); + return new OMV.Vector3(Scale.X * 2, Scale.Y * 2, Scale.Z); } set { @@ -162,22 +196,25 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true); + BulletSimAPI.SetLocalScaling2(BSBody.ptr, Scale); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); }); } } - public override PrimitiveBaseShape Shape { - set { _pbs = value; - } + public override OMV.Vector3 Scale { get; set; } + private PrimitiveBaseShape _pbs; + public override PrimitiveBaseShape Shape + { + set { _pbs = value;} } + public override bool Grabbed { - set { _grabbed = value; - } + set { _grabbed = value; } } public override bool Selected { - set { _selected = value; - } + set { _selected = value; } } public override void CrossingFailure() { return; } public override void link(PhysicsActor obj) { return; } @@ -204,7 +241,7 @@ public class BSCharacter : BSPhysObject public override OMV.Vector3 Position { get { - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); + // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); return _position; } set { @@ -214,7 +251,7 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } } @@ -273,7 +310,7 @@ public class BSCharacter : BSPhysObject BSScene.TaintCallback sanityOperation = delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }; if (inTaintTime) sanityOperation(); @@ -284,11 +321,7 @@ public class BSCharacter : BSPhysObject return ret; } - public override float Mass { - get { - return _mass; - } - } + public override float Mass { get { return _mass; } } // used when we only want this prim's mass and not the linkset thing public override float MassRaw { get {return _mass; } } @@ -301,15 +334,13 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force); + BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); }); } } - public override int VehicleType { - get { return 0; } - set { return; } - } + // Avatars don't do vehicles + public override int VehicleType { get { return 0; } set { return; } } public override void VehicleFloatParam(int param, float value) { } public override void VehicleVectorParam(int param, OMV.Vector3 value) {} public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } @@ -328,15 +359,35 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); + ForceVelocity = _velocity; }); } } public override OMV.Vector3 ForceVelocity { get { return _velocity; } set { + // Depending on whether the avatar is moving or not, change the friction + // to keep the avatar from slipping around + if (_velocity.Length() == 0) + { + if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) + { + _currentFriction = PhysicsScene.Params.avatarStandingFriction; + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + } + } + else + { + if (_currentFriction == 999f) + { + _currentFriction = PhysicsScene.Params.avatarFriction; + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + } + } _velocity = value; - BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); + _appliedVelocity = value; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + BulletSimAPI.Activate2(BSBody.ptr, true); } } public override OMV.Vector3 Torque { @@ -360,8 +411,8 @@ public class BSCharacter : BSPhysObject // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + // _position = BulletSimAPI.GetPosition2(BSBody.ptr); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } } @@ -389,12 +440,18 @@ public class BSCharacter : BSPhysObject set { _isPhysical = value; } } + public override bool IsSolid { + get { return true; } + } + public override bool IsStatic { + get { return false; } + } public override bool Flying { get { return _flying; } set { _flying = value; // simulate flying by changing the effect of gravity - this.Buoyancy = ComputeBuoyancyFromFlying(_flying); + Buoyancy = ComputeBuoyancyFromFlying(_flying); } } // Flying is implimented by changing the avatar's buoyancy. @@ -454,10 +511,19 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); + ForceBuoyancy = _buoyancy; }); } } + public override float ForceBuoyancy { + get { return _buoyancy; } + set { _buoyancy = value; + DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + // Buoyancy is faked by changing the gravity applied to the object + float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); + BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + } + } // Used for MoveTo public override OMV.Vector3 PIDTarget { @@ -518,27 +584,29 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { - _scale.X = PhysicsScene.Params.avatarCapsuleRadius; - _scale.Y = PhysicsScene.Params.avatarCapsuleRadius; + OMV.Vector3 newScale = OMV.Vector3.Zero; + newScale.X = PhysicsScene.Params.avatarCapsuleRadius; + newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; // The 1.15 came from ODE but it seems to cause the avatar to float off the ground - // _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); - _scale.Z = (_size.Z) - (_scale.X + _scale.Y); + // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); + newScale.Z = (_size.Z) - (Scale.X + Scale.Y); + Scale = newScale; } - // set _avatarVolume and _mass based on capsule size, _density and _scale + // set _avatarVolume and _mass based on capsule size, _density and Scale private void ComputeAvatarVolumeAndMass() { _avatarVolume = (float)( Math.PI - * _scale.X - * _scale.Y // the area of capsule cylinder - * _scale.Z // times height of capsule cylinder + * Scale.X + * Scale.Y // the area of capsule cylinder + * Scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * _scale.X - * Math.Min(_scale.X, _scale.Y) - * _scale.Y // plus the volume of the capsule end caps + * Scale.X + * Math.Min(Scale.X, Scale.Y) + * Scale.Y // plus the volume of the capsule end caps ); _mass = _avatarDensity * _avatarVolume; } @@ -555,6 +623,22 @@ public class BSCharacter : BSPhysObject // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. PositionSanityCheck2(true); + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; + CurrentEntityProperties = entprop; + + if (entprop.Velocity != LastEntityProperties.Velocity) + { + // Changes in the velocity are suppressed in avatars. + // That's just the way they are defined. + OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); + _velocity = avVel; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); + } + + // Tell the linkset about this + Linkset.UpdateProperties(this); + // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index cae599c96f..34dec26ab3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -69,6 +69,16 @@ public abstract class BSPhysObject : PhysicsActor // Reference to the physical shape (btCollisionShape) of this object public BulletShape BSShape; + // When the physical properties are updated, an EntityProperty holds the update values. + // Keep the current and last EntityProperties to enable computation of differences + // between the current update and the previous values. + public EntityProperties CurrentEntityProperties { get; set; } + public EntityProperties LastEntityProperties { get; set; } + + public abstract OMV.Vector3 Scale { get; set; } + public abstract bool IsSolid { get; } + public abstract bool IsStatic { get; } + // Stop all physical motion. public abstract void ZeroMotion(); @@ -89,6 +99,8 @@ public abstract class BSPhysObject : PhysicsActor public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } + public abstract float ForceBuoyancy { get; set; } + #region Collisions // Requested number of milliseconds between collision events. Zero means disabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6a4365c84a..3421e309ed 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -172,11 +172,8 @@ public sealed class BSPrim : BSPhysObject } // Scale is what we set in the physics engine. It is different than 'size' in that // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. - public OMV.Vector3 Scale - { - get { return _scale; } - set { _scale = value; } - } + public override OMV.Vector3 Scale { get; set; } + public override PrimitiveBaseShape Shape { set { _pbs = value; @@ -325,9 +322,9 @@ public sealed class BSPrim : BSPhysObject } // A version of the sanity check that also makes sure a new position value is - // pushed back to the physics engine. This routine would be used by anyone + // pushed to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool inTaintTime) + private bool PositionSanityCheck(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -336,8 +333,8 @@ public sealed class BSPrim : BSPhysObject // just assign to "Position" because of potential call loops. BSScene.TaintCallback sanityOperation = delegate() { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); + ForcePosition = _position; }; if (inTaintTime) sanityOperation(); @@ -547,13 +544,13 @@ public sealed class BSPrim : BSPhysObject } // An object is static (does not move) if selected or not physical - private bool IsStatic + public override bool IsStatic { get { return _isSelected || !IsPhysical; } } // An object is solid if it's not phantom and if it's not doing VolumeDetect - public bool IsSolid + public override bool IsSolid { get { return !IsPhantom && !_isVolumeDetect; } } @@ -631,6 +628,12 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); // There is no inertia in a static object BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + // Set collision detection parameters + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'disabled' so Bullet will not try to act on it. @@ -662,6 +665,13 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + // Set collision detection parameters + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } + // Various values for simulation limits BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime); @@ -812,14 +822,21 @@ public sealed class BSPrim : BSPhysObject set { _buoyancy = value; PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() - { - // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + { + ForceBuoyancy = _buoyancy; }); } } + public override float ForceBuoyancy { + get { return _buoyancy; } + set { + _buoyancy = value; + // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + // Buoyancy is faked by changing the gravity applied to the object + float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); + BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + } + } // Used for MoveTo public override OMV.Vector3 PIDTarget { @@ -1269,8 +1286,8 @@ public sealed class BSPrim : BSPhysObject 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 float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; + public override void UpdateProperties(EntityProperties entprop) { /* @@ -1326,11 +1343,13 @@ public sealed class BSPrim : BSPhysObject _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; + _rotationalVelocity = entprop.RotationalVelocity; + + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; + CurrentEntityProperties = entprop; - PositionSanityCheck2(true); - - Linkset.UpdateProperties(this); + PositionSanityCheck(true); DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); @@ -1348,6 +1367,9 @@ public sealed class BSPrim : BSPhysObject entprop.Acceleration, entprop.RotationalVelocity); } */ + // The linkset implimentation might want to know about this. + + Linkset.UpdateProperties(this); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 2c3c481aea..5158011e4c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -256,10 +256,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); - WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), + World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(), m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), - m_DebugLogCallbackHandle); + m_DebugLogCallbackHandle)); // 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. @@ -360,7 +360,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // Anything left in the unmanaged code should be cleaned out - BulletSimAPI.Shutdown(WorldID); + BulletSimAPI.Shutdown2(World.ptr); // Not logging any more PhysicsLogging.Close(); @@ -498,7 +498,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); - numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep, + numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); @@ -1011,6 +1011,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarFriction; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), + new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", + 10f, + (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarStandingFriction; }, + (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 60f, (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, @@ -1246,7 +1251,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: + m_log.ErrorFormat("{0} Cannot change parameters of multiple objects. Someday it will be added.", LogHeader); + /* defaultLoc = val; // setting ALL also sets the default value List objectIDs = lIDs; string xparm = parm.ToLower(); @@ -1257,6 +1264,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval); } }); + */ break; default: // setting only one localID @@ -1268,12 +1276,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters // schedule the actual updating of the paramter to when the phys engine is not busy protected void TaintedUpdateParameter(string parm, uint localID, float val) { + m_log.ErrorFormat("{0} Cannot change parameters of base objects. Someday it will be added.", LogHeader); + /* uint xlocalID = localID; string xparm = parm.ToLower(); float xval = val; TaintedObject("BSScene.TaintedUpdateParameter", delegate() { BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); }); + */ } // Get parameter. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d189f1d287..7d0f84a525 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -93,7 +93,7 @@ public class BSShapeCollection : IDisposable // sure the body is of the right type. // Return 'true' if either the body or the shape changed. // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, + public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { @@ -351,19 +351,30 @@ public class BSShapeCollection : IDisposable // Create the geometry information in Bullet for later use. // The objects needs a hull if it's physical otherwise a mesh is enough. - // No locking here because this is done when we know physics is not simulating. - // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. + // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, + // shared geometries will be used. If the parameters of the existing shape are the same + // as this request, the shape is not rebuilt. + // Info in prim.BSShape is updated to the new shape. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, + private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; bool nativeShapePossible = true; + if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + // an avatar capsule is close to a native shape (it is not shared) + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); + haveShape = true; + } // If the prim attributes are simple, this could be a simple Bullet native shape - if (nativeShapePossible + if (!haveShape + && pbs != null + && nativeShapePossible && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 && pbs.ProfileHollow == 0 @@ -406,7 +417,7 @@ public class BSShapeCollection : IDisposable // If a simple shape is not happening, create a mesh and possibly a hull. // Note that if it's a native shape, the check for physical/non-physical is not // made. Native shapes are best used in either case. - if (!haveShape) + if (!haveShape && pbs != null) { if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { @@ -425,8 +436,9 @@ public class BSShapeCollection : IDisposable return ret; } - // Creates a native shape and assignes it to prim.BSShape - private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, + // Creates a native shape and assignes it to prim.BSShape. + // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). + private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { @@ -440,10 +452,19 @@ public class BSShapeCollection : IDisposable // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); - // Native shapes are always built independently. - newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; + if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + newShape = new BulletShape(BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; + } + else + { + // Native shapes are always built independently. + newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; + } // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); @@ -456,7 +477,7 @@ public class BSShapeCollection : IDisposable // Dereferences previous shape in BSShape and adds a reference for this new shape. // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! - private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + private bool GetReferenceToMesh(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); @@ -526,7 +547,7 @@ public class BSShapeCollection : IDisposable // See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + private bool GetReferenceToHull(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape; @@ -694,7 +715,7 @@ public class BSShapeCollection : IDisposable // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, + private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 276111c2b1..30754a7667 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -223,6 +223,7 @@ public struct ShapeData KEY_SPHERE = 2, KEY_CONE = 3, KEY_CYLINDER = 4, + KEY_CAPSULE = 5, } } [StructLayout(LayoutKind.Sequential)] @@ -282,6 +283,7 @@ public struct ConfigurationParameters public float terrainHitFraction; public float terrainRestitution; public float avatarFriction; + public float avatarStandingFriction; public float avatarDensity; public float avatarRestitution; public float avatarCapsuleRadius; @@ -428,6 +430,7 @@ public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg [return: MarshalAs(UnmanagedType.LPStr)] public static extern string GetVersion(); +/* Remove the linkage to the old api methods [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, @@ -531,7 +534,7 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); // =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpBulletStatistics(); - +*/ // Log a debug message [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetDebugLogCallback(DebugLogCallback callback); @@ -562,7 +565,8 @@ public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray); + int maxUpdates, IntPtr updateArray, + DebugLogCallback logRoutine); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); @@ -603,6 +607,9 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData) [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool IsNativeShape2(IntPtr shape); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr BuildCapsuleShape2(IntPtr world, ShapeData shapeData); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateCompoundShape2(IntPtr sim);