From fd7a097849b8a405bdd62cfe6d4ee2bbf0a3961c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 12 Oct 2012 16:03:03 -0700 Subject: BulletSim: Update BSCharacter to use API2 interface. Add capsule shape to BSShapeCollection(). Remember last updated values so inter frame diffs can be computed. Parameterize avatarStandingFriction and reduce to 10 from 999. The latter high value made avatars very hard to push. Set CCD parameters for prims and characters of specified. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 182 +++++++++++++++------ .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 12 ++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 66 +++++--- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 21 ++- .../Physics/BulletSPlugin/BSShapeCollection.cs | 51 ++++-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 11 +- 6 files changed, 250 insertions(+), 93 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2e6b2da..7c2f856 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 cae599c..34dec26 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 6a4365c..3421e30 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 2c3c481..5158011 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 d189f1d..7d0f84a 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 276111c..30754a7 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); @@ -604,6 +608,9 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData) 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); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From eaccfa6d99ac51b4963ae0fa457ff0d2b9ce65e7 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 14 Oct 2012 19:23:35 -0700 Subject: BulletSim: Fix small problems with last patch: BSScene.World properly initialized and setting of C++ parameters commented out. Comments and logging added. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 13 ++++--------- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 7c2f856..7bc6b69 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -146,7 +146,7 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); // Set the velocity and compute the proper friction diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 5158011..7998b08 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -261,10 +261,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), 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. - World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID)); - Constraints = new BSConstraintCollection(World); TerrainManager = new BSTerrainManager(this); @@ -1251,10 +1247,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value break; - case PhysParameterEntry.APPLY_TO_ALL: - m_log.ErrorFormat("{0} Cannot change parameters of multiple objects. Someday it will be added.", LogHeader); - /* + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value + /* List objectIDs = lIDs; string xparm = parm.ToLower(); float xval = val; @@ -1276,15 +1271,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) { + /* Settings in the C++ code are not working at the moment. TODO: fix the settings. 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 7d0f84a..5a77e52 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -369,6 +369,7 @@ public class BSShapeCollection : IDisposable // 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); + DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); haveShape = true; } // If the prim attributes are simple, this could be a simple Bullet native shape @@ -460,7 +461,6 @@ public class BSShapeCollection : IDisposable } 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; -- cgit v1.1 From fc33afddd360843d05f030750b7075315a526ae1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 15 Oct 2012 12:11:00 -0700 Subject: BulletSim: remove code in ShapeCollection that hinted at shape sharing. Add new function to ParameterDefn for calling BulletSimAPI to set values. Tweaking to BSCharacter parameter setting to try and have avatars stand. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 56 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 16 +-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 114 ++++++++++++--------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 110 +++++++------------- .../Physics/BulletSPlugin/BSTerrainManager.cs | 3 +- 5 files changed, 138 insertions(+), 161 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 7bc6b69..8e1171a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -114,17 +114,9 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); - + 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. - ForceBuoyancy = _buoyancy; - - // This works here because CreateObject has already put the character into the physical world. - BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, - (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); }); return; } @@ -146,27 +138,32 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + ForcePosition = _position; // 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.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); + + // Do this after the object has been added to the world + BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, + (uint)CollisionFilterGroups.AvatarFilter, + (uint)CollisionFilterGroups.AvatarMask); } public override void RequestPhysicsterseUpdate() @@ -174,9 +171,7 @@ public class BSCharacter : BSPhysObject base.RequestPhysicsterseUpdate(); } // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { - get { return false; } - } + public override bool Stopped { get { return false; } } public override OMV.Vector3 Size { get { @@ -185,18 +180,14 @@ public class BSCharacter : BSPhysObject } set { - // When an avatar's size is set, only the height is changed - // and that really only depends on the radius. + // When an avatar's size is set, only the height is changed. _size = value; ComputeAvatarScale(_size); - - // TODO: something has to be done with the avatar's vertical position - ComputeAvatarVolumeAndMass(); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetLocalScaling2(BSBody.ptr, Scale); + BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); }); @@ -300,7 +291,7 @@ public class BSCharacter : 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 // who is not already pushing the value. - private bool PositionSanityCheck2(bool inTaintTime) + private bool PositionSanityCheck(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -378,14 +369,16 @@ public class BSCharacter : BSPhysObject } else { - if (_currentFriction == 999f) + if (_currentFriction != PhysicsScene.Params.avatarFriction) { _currentFriction = PhysicsScene.Params.avatarFriction; BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); } } _velocity = value; + // Remember the set velocity so we can suppress the reduction by friction, ... _appliedVelocity = value; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); BulletSimAPI.Activate2(BSBody.ptr, true); } @@ -590,7 +583,8 @@ public class BSCharacter : BSPhysObject // 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); - newScale.Z = (_size.Z) - (Scale.X + Scale.Y); + // From the total height, remove the capsule half spheres that are at each end + newScale.Z = (size.Z) - (Math.Min(newScale.X, newScale.Y) * 2f); Scale = newScale; } @@ -621,7 +615,7 @@ public class BSCharacter : BSPhysObject _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck2(true); + PositionSanityCheck(true); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 3421e30..b9e1908 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -333,7 +333,7 @@ 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); + DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); ForcePosition = _position; }; if (inTaintTime) @@ -822,7 +822,7 @@ public sealed class BSPrim : BSPhysObject set { _buoyancy = value; PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() - { + { ForceBuoyancy = _buoyancy; }); } @@ -1286,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) { /* @@ -1343,10 +1343,10 @@ public sealed class BSPrim : BSPhysObject _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; - - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; + _rotationalVelocity = entprop.RotationalVelocity; + + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; PositionSanityCheck(true); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 7998b08..c6e8bc4 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -795,7 +795,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); - delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); private struct ParameterDefn { @@ -804,7 +805,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public float defaultValue; // default value if not specified anywhere else public ParamUser userParam; // get the value from the configuration file public ParamGet getter; // return the current value stored for this parameter - public ParamSet setter; // set the current value for this parameter + public ParamSet setter; // set the current value for this parameter + public SetOnObject onObject; // set the value on an object in the physical domain public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) { name = n; @@ -812,7 +814,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters defaultValue = v; userParam = u; getter = g; - setter = s; + setter = s; + onObject = null; + } + public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) + { + name = n; + desc = d; + defaultValue = v; + userParam = u; + getter = g; + setter = s; + onObject = o; } } @@ -834,6 +847,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // // The single letter parameters for the delegates are: // s = BSScene + // o = BSPhysObject // p = string parameter name // l = localID of referenced object // v = float value @@ -943,65 +957,74 @@ public class BSScene : PhysicsScene, IPhysicsParameters -9.80665f, (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].gravity; }, - (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); }, + (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 0.2f, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].deactivationTime; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ), new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 0.8f, (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1.0f, (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 0f, // set to zero to disable (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdMotionThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ), new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 0f, (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdSweptSphereRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ), new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].contactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainFriction; }, - (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 0.8f, (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainHitFraction; }, - (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ), new ParameterDefn("TerrainRestitution", "Bouncyness" , 0f, (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainRestitution; }, - (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 0.2f, (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, @@ -1228,58 +1251,55 @@ public class BSScene : PhysicsScene, IPhysicsParameters return ret; } - // check to see if we are updating a parameter for a particular or all of the prims - protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val) - { - List operateOn; - lock (PhysObjects) operateOn = new List(PhysObjects.Keys); - UpdateParameterSet(operateOn, ref loc, parm, localID, val); - } - // update all the localIDs specified // If the local ID is APPLY_TO_NONE, just change the default value // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs // If the localID is a specific object, apply the parameter change to only that object - protected void UpdateParameterSet(List lIDs, ref float defaultLoc, string parm, uint localID, float val) + protected void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) { + List objectIDs = new List(); switch (localID) { case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value + // This will cause a call into the physical world if some operation is specified (SetOnObject). + objectIDs.Add(TERRAIN_ID); + TaintedUpdateParameter(parm, objectIDs, val); break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value - /* - List objectIDs = lIDs; - string xparm = parm.ToLower(); - float xval = val; - TaintedObject("BSScene.UpdateParameterSet", delegate() { - foreach (uint lID in objectIDs) - { - BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval); - } - }); - */ + lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); + TaintedUpdateParameter(parm, objectIDs, val); break; default: - // setting only one localID - TaintedUpdateParameter(parm, localID, val); + // setting only one localID + objectIDs.Add(localID); + TaintedUpdateParameter(parm, objectIDs, val); break; } } // schedule the actual updating of the paramter to when the phys engine is not busy - protected void TaintedUpdateParameter(string parm, uint localID, float val) + protected void TaintedUpdateParameter(string parm, List lIDs, float val) { - /* Settings in the C++ code are not working at the moment. TODO: fix the settings. - 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); + float xval = val; + List xlIDs = lIDs; + string xparm = parm; + TaintedObject("BSScene.UpdateParameterSet", delegate() { + ParameterDefn thisParam; + if (TryGetParameter(xparm, out thisParam)) + { + if (thisParam.onObject != null) + { + foreach (uint lID in xlIDs) + { + BSPhysObject theObject = null; + PhysObjects.TryGetValue(lID, out theObject); + thisParam.onObject(this, theObject, xval); + } + } + } }); - */ } // Get parameter. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 5a77e52..bbfdac6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -51,7 +51,7 @@ public class BSShapeCollection : IDisposable } // Description of a hull. - // Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects + // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. private struct HullDesc { public IntPtr ptr; @@ -59,17 +59,9 @@ public class BSShapeCollection : IDisposable public DateTime lastReferenced; } - private struct BodyDesc - { - public IntPtr ptr; - // Bodies are only used once so reference count is always either one or zero - public int referenceCount; - public DateTime lastReferenced; - } - + // The sharable set of meshes and hulls. Indexed by their shape hash. private Dictionary Meshes = new Dictionary(); private Dictionary Hulls = new Dictionary(); - private Dictionary Bodies = new Dictionary(); public BSShapeCollection(BSScene physScene) { @@ -92,6 +84,10 @@ public class BSShapeCollection : IDisposable // First checks the shape and updates that if necessary then makes // sure the body is of the right type. // Return 'true' if either the body or the shape changed. + // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before + // the current shape or body is destroyed. This allows the caller to remove any + // higher level dependencies on the shape or body. Mostly used for LinkSets to + // remove the physical constraints before the body is destroyed. // Called at taint-time!! public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, @@ -103,7 +99,8 @@ public class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? - // Updates prim.BSShape with information/pointers to requested shape + // Updates prim.BSShape with information/pointers to shape. + // CreateGeom returns 'true' of BSShape as changed to a new shape. bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. @@ -125,35 +122,19 @@ public class BSShapeCollection : IDisposable { lock (m_collectionActivityLock) { - BodyDesc bodyDesc; - if (Bodies.TryGetValue(body.ID, out bodyDesc)) + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); + BSScene.TaintCallback createOperation = delegate() { - bodyDesc.referenceCount++; - DetailLog("{0},BSShapeCollection.ReferenceBody,existingBody,body={1},ref={2}", body.ID, body, bodyDesc.referenceCount); - } - else - { - // New entry - bodyDesc.ptr = body.ptr; - bodyDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}", - body.ID, body, bodyDesc.referenceCount); - BSScene.TaintCallback createOperation = delegate() + if (!BulletSimAPI.IsInWorld2(body.ptr)) { - if (!BulletSimAPI.IsInWorld2(body.ptr)) - { - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); - DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", - body.ID, body); - } - }; - if (inTaintTime) - createOperation(); - else - PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); - } - bodyDesc.lastReferenced = System.DateTime.Now; - Bodies[body.ID] = bodyDesc; + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); + DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); + } + }; + if (inTaintTime) + createOperation(); + else + PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); } } @@ -166,43 +147,25 @@ public class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { - BodyDesc bodyDesc; - if (Bodies.TryGetValue(body.ID, out bodyDesc)) + BSScene.TaintCallback removeOperation = delegate() { - bodyDesc.referenceCount--; - bodyDesc.lastReferenced = System.DateTime.Now; - Bodies[body.ID] = bodyDesc; - DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); - - // If body is no longer being used, free it -- bodies can never be shared. - if (bodyDesc.referenceCount == 0) - { - Bodies.Remove(body.ID); - BSScene.TaintCallback removeOperation = delegate() - { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", - body.ID, body.ptr.ToString("X"), inTaintTime); - // If the caller needs to know the old body is going away, pass the event up. - if (bodyCallback != null) bodyCallback(body); - - // It may have already been removed from the world in which case the next is a NOOP. - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); - - // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); - }; - // If already in taint-time, do the operations now. Otherwise queue for later. - if (inTaintTime) - removeOperation(); - else - PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); - } - } + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", + body.ID, body.ptr.ToString("X"), inTaintTime); + // If the caller needs to know the old body is going away, pass the event up. + if (bodyCallback != null) bodyCallback(body); + + // It may have already been removed from the world in which case the next is a NOOP. + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + + // Zero any reference to the shape so it is not freed when the body is deleted. + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); + }; + // If already in taint-time, do the operations now. Otherwise queue for later. + if (inTaintTime) + removeOperation(); else - { - DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount); - } + PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); } } @@ -271,7 +234,6 @@ public class BSShapeCollection : IDisposable } // Release the usage of a shape. - // The collisionObject is released since it is a copy of the real collision shape. public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index caf411e..9743d94 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -334,7 +334,8 @@ public class BSTerrainManager // Make sure the new shape is processed. // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); + // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); m_terrainModified = true; }; -- cgit v1.1 From e87a179c893ef246dae8338e0f56c3fe20458fbc Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 17 Oct 2012 08:30:10 -0700 Subject: 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). --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 46 ++++++++++++---------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 14 +++---- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 14 +++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 26 ++++++------ .../Physics/BulletSPlugin/BSShapeCollection.cs | 7 +++- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 6 files changed, 57 insertions(+), 52 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 8e1171a..e7bff6e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -89,13 +89,15 @@ public class BSCharacter : BSPhysObject _appliedVelocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); _currentFriction = PhysicsScene.Params.avatarStandingFriction; + _avatarDensity = PhysicsScene.Params.avatarDensity; // 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 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.ID = LocalID; @@ -103,6 +105,7 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; + shapeData.Size = Scale; shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; @@ -114,8 +117,9 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.create", delegate() { 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(); }); return; @@ -138,7 +142,7 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); ForcePosition = _position; @@ -151,13 +155,13 @@ public class BSCharacter : BSPhysObject { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - + } + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); 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); // Do this after the object has been added to the world @@ -176,7 +180,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 _size; } set { @@ -184,11 +188,13 @@ public class BSCharacter : BSPhysObject _size = value; ComputeAvatarScale(_size); ComputeAvatarVolumeAndMass(); + DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", + LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { 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); }); @@ -578,13 +584,13 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { OMV.Vector3 newScale = OMV.Vector3.Zero; - newScale.X = PhysicsScene.Params.avatarCapsuleRadius; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; + // Scale wants the diameter so mult radius by two + 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 - // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); - // From the total height, remove the capsule half spheres that are at each end - newScale.Z = (size.Z) - (Math.Min(newScale.X, newScale.Y) * 2f); + // From the total height, add the capsule half spheres that are at each end + // newScale.Z = (size.Z) - Math.Min(newScale.X, newScale.Y); + newScale.Z = (size.Z * 2f); Scale = newScale; } @@ -593,14 +599,14 @@ public class BSCharacter : BSPhysObject { _avatarVolume = (float)( Math.PI - * Scale.X - * Scale.Y // the area of capsule cylinder + * (Scale.X / 2f) + * (Scale.Y / 2f) // 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 / 2f) + * (Math.Min(Scale.X, Scale.Y) / 2f) + * (Scale.Y / 2f) // plus the volume of the capsule end caps ); _mass = _avatarDensity * _avatarVolume; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 34dec26..b8ef338 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -141,18 +141,15 @@ public abstract class BSPhysObject : PhysicsActor // if someone has subscribed for collision events.... if (SubscribedEvents()) { CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - // DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - // LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); + DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", + LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); ret = true; } return ret; } - // Routine to 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. + // Send the collected collisions into the simulator. // Called at taint time from within the Step() function thus no locking problems // with CollisionCollection and ObjectsWithNoMoreCollisions. // Return 'true' if there were some actual collisions passed up @@ -161,10 +158,9 @@ public abstract class BSPhysObject : PhysicsActor bool ret = true; // throttle the collisions to the number of milliseconds specified in the subscription - int nowTime = PhysicsScene.SimulationNowTime; - if (nowTime >= NextCollisionOkTime) + if (PhysicsScene.SimulationNowTime >= NextCollisionOkTime) { - NextCollisionOkTime = nowTime + SubscribedEventsMs; + NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; // 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. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b9e1908..8013e68 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -48,10 +48,10 @@ public sealed class BSPrim : BSPhysObject private PrimitiveBaseShape _pbs; - // _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. + // _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. 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 _isSelected; @@ -98,7 +98,7 @@ public sealed class BSPrim : BSPhysObject _physicsActorType = (int)ActorTypes.Prim; _position = pos; _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; _buoyancy = 1f; _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 // scale and margins are set. 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.Rotation = _orientation; shape.Velocity = _velocity; - shape.Scale = _scale; + shape.Size = _size; + shape.Scale = Scale; shape.Mass = _isPhysical ? _mass : 0f; shape.Buoyancy = _buoyancy; shape.HullKey = 0; @@ -1234,7 +1235,6 @@ public sealed class BSPrim : BSPhysObject shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue; - shape.Size = _size; } // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c6e8bc4..ab2835c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -533,7 +533,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // 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. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. 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. // 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). - return numSubSteps * m_fixedTimeStep * 1000 * 45; - // return timeStep * 1000 * 45; + // We multiply by 55 to give a recognizable running rate (55 or less). + return numSubSteps * m_fixedTimeStep * 1000 * 55; + // return timeStep * 1000 * 55; } // Something has collided @@ -795,7 +795,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); - delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); private struct ParameterDefn @@ -805,7 +805,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters public float defaultValue; // default value if not specified anywhere else public ParamUser userParam; // get the value from the configuration file public ParamGet getter; // return the current value stored for this parameter - public ParamSet setter; // set the current value for this parameter + public ParamSet setter; // set the current value for this parameter public SetOnObject onObject; // set the value on an object in the physical domain public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) { @@ -814,7 +814,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters defaultValue = v; userParam = u; getter = g; - setter = s; + setter = s; onObject = null; } 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; userParam = u; getter = g; - setter = s; + setter = s; onObject = o; } } @@ -1266,13 +1266,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters objectIDs.Add(TERRAIN_ID); TaintedUpdateParameter(parm, objectIDs, val); break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value - lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); + lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); TaintedUpdateParameter(parm, objectIDs, val); break; default: - // setting only one localID + // setting only one localID objectIDs.Add(localID); TaintedUpdateParameter(parm, objectIDs, val); 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 protected void TaintedUpdateParameter(string parm, List lIDs, float val) { - float xval = val; - List xlIDs = lIDs; + float xval = val; + List xlIDs = lIDs; string xparm = parm; TaintedObject("BSScene.UpdateParameterSet", delegate() { ParameterDefn thisParam; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index bbfdac6..3d15eaa 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -417,7 +417,10 @@ public class BSShapeCollection : IDisposable 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.isNativeShape = true; } @@ -428,7 +431,7 @@ public class BSShapeCollection : IDisposable 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); prim.BSShape = newShape; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 30754a7..24d8db6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -608,7 +608,7 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData) public static extern bool IsNativeShape2(IntPtr shape); [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] public static extern IntPtr CreateCompoundShape2(IntPtr sim); -- cgit v1.1 From f422b9b388fe67c61e610c79efabd5e07512884b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 19 Oct 2012 10:48:45 -0700 Subject: BulletSim: reorder avatar collision checking to eliminate double collision_end. Various tweekings to avatar shape/mass/inertia/etc. Remove change from avatar radius to diameter. But still the avatar sinks. Collision_end now happens immediately rather than at the next subscription time. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 33 +++++++++++----------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 ++- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 30 +++++++++++--------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 8 +++--- .../Physics/BulletSPlugin/BSTerrainManager.cs | 1 + .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 6 files changed, 43 insertions(+), 35 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index e7bff6e..fc4526b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -141,10 +141,6 @@ public class BSCharacter : BSPhysObject BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); ZeroMotion(); - - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); - BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); - ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; @@ -157,6 +153,9 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); @@ -583,14 +582,16 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { + // The 'size' given by the simulator is the mid-point of the avatar + // and X and Y are unspecified. + OMV.Vector3 newScale = OMV.Vector3.Zero; - // Scale wants the diameter so mult radius by two - newScale.X = PhysicsScene.Params.avatarCapsuleRadius * 2f; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius * 2f; + newScale.X = PhysicsScene.Params.avatarCapsuleRadius; + newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - // From the total height, add the capsule half spheres that are at each end - // newScale.Z = (size.Z) - Math.Min(newScale.X, newScale.Y); - newScale.Z = (size.Z * 2f); + // From the total height, remote the capsule half spheres that are at each end + newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y); + // newScale.Z = (size.Z * 2f); Scale = newScale; } @@ -599,14 +600,14 @@ public class BSCharacter : BSPhysObject { _avatarVolume = (float)( Math.PI - * (Scale.X / 2f) - * (Scale.Y / 2f) // 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 / 2f) - * (Math.Min(Scale.X, Scale.Y) / 2f) - * (Scale.Y / 2f) // 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; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index b8ef338..202052d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -156,9 +156,11 @@ public abstract class BSPhysObject : PhysicsActor public virtual bool SendCollisions() { bool ret = true; + // If the 'no collision' call, force it to happen right now so quick collision_end + bool force = CollisionCollection.Count == 0; // throttle the collisions to the number of milliseconds specified in the subscription - if (PhysicsScene.SimulationNowTime >= NextCollisionOkTime) + if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) { NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index ab2835c..6621d39 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -532,26 +532,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } - // 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 - // avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. - foreach (BSPhysObject bsp in m_avatars) - bsp.SendCollisions(); - // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. if (ObjectsWithCollisions.Count > 0) { foreach (BSPhysObject bsp in ObjectsWithCollisions) - if (!m_avatars.Contains(bsp)) // don't call avatars twice - if (!bsp.SendCollisions()) - { - // If the object is done colliding, see that it's removed from the colliding list - ObjectsWithNoMoreCollisions.Add(bsp); - } + if (!bsp.SendCollisions()) + { + // If the object is done colliding, see that it's removed from the colliding list + ObjectsWithNoMoreCollisions.Add(bsp); + } } + // This is a kludge to get avatar movement updates. + // The simulator expects collisions for avatars even if there are have been no collisions. + // The event updates avatar animations and stuff. + // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. + foreach (BSPhysObject bsp in m_avatars) + if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice + bsp.SendCollisions(); + // Objects that are done colliding are removed from the ObjectsWithCollisions list. // Not done above because it is inside an iteration of ObjectWithCollisions. if (ObjectsWithNoMoreCollisions.Count > 0) @@ -575,6 +575,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } + // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. + // Only enable this in a limited test world with few objects. + // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG + // 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. // We multiply by 55 to give a recognizable running rate (55 or less). diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 3d15eaa..861ffe7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -417,10 +417,9 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { - // 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); + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), + shapeType); newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; } @@ -432,7 +431,8 @@ public class BSShapeCollection : IDisposable } // 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},scale={2}", + shapeData.ID, newShape, shapeData.Scale); prim.BSShape = newShape; return true; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 9743d94..4106534 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -114,6 +114,7 @@ public class BSTerrainManager BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr); // Ground plane does not move BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); // Everything collides with the ground plane. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 24d8db6..5ffd591 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -390,7 +390,7 @@ public enum CollisionFilterGroups : uint VolumeDetectMask = ~BSensorTrigger, TerrainFilter = BTerrainFilter, TerrainMask = BAllFilter & ~BStaticFilter, - GroundPlaneFilter = BAllFilter, + GroundPlaneFilter = BGroundPlaneFilter, GroundPlaneMask = BAllFilter }; -- cgit v1.1 From d94c4646ccf0703019dd5a7915afb43706a4de35 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 19 Oct 2012 15:43:31 -0700 Subject: BulletSim: add asset fetching so BulletSim works with new physics asset handling. Refactor some names to make them available for the asset tracking and fetching. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 3 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 10 + OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 96 +++---- .../Physics/BulletSPlugin/BSShapeCollection.cs | 296 +++++++++++++-------- 4 files changed, 240 insertions(+), 165 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index fc4526b..623ac8f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -200,10 +200,9 @@ public class BSCharacter : BSPhysObject } } public override OMV.Vector3 Scale { get; set; } - private PrimitiveBaseShape _pbs; public override PrimitiveBaseShape Shape { - set { _pbs = value;} + set { BaseShape = value; } } public override bool Grabbed { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 202052d..ead6a08 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -47,6 +47,7 @@ public abstract class BSPhysObject : PhysicsActor TypeName = typeName; Linkset = new BSLinkset(PhysicsScene, this); + LastAssetBuildFailed = false; CollisionCollection = new CollisionEventUpdate(); SubscribedEventsMs = 0; @@ -69,6 +70,13 @@ public abstract class BSPhysObject : PhysicsActor // Reference to the physical shape (btCollisionShape) of this object public BulletShape BSShape; + // 'true' if the mesh's underlying asset failed to build. + // This will keep us from looping after the first time the build failed. + public bool LastAssetBuildFailed { get; set; } + + // The objects base shape information. Null if not a prim type shape. + public PrimitiveBaseShape BaseShape { get; protected set; } + // 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. @@ -101,6 +109,8 @@ public abstract class BSPhysObject : PhysicsActor public abstract float ForceBuoyancy { get; set; } + public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } + #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 8013e68..aeeb4dd 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -46,8 +46,6 @@ public sealed class BSPrim : BSPhysObject private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; - private PrimitiveBaseShape _pbs; - // _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. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user @@ -103,7 +101,7 @@ public sealed class BSPrim : BSPhysObject _buoyancy = 1f; _velocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - _pbs = pbs; + BaseShape = pbs; _isPhysical = pisPhysical; _isVolumeDetect = false; _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material @@ -160,14 +158,7 @@ public sealed class BSPrim : BSPhysObject get { return _size; } set { _size = value; - PhysicsScene.TaintedObject("BSPrim.setSize", delegate() - { - _mass = CalculateMass(); // changing size changes the mass - // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct - // scale and margins are set. - CreateGeomAndObject(true); - // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, Scale, _mass, IsPhysical); - }); + ForceBodyShapeRebuild(false); } } // Scale is what we set in the physics engine. It is different than 'size' in that @@ -176,14 +167,23 @@ public sealed class BSPrim : BSPhysObject public override PrimitiveBaseShape Shape { set { - _pbs = value; - PhysicsScene.TaintedObject("BSPrim.setShape", delegate() - { - _mass = CalculateMass(); // changing the shape changes the mass - CreateGeomAndObject(true); - }); + BaseShape = value; + ForceBodyShapeRebuild(false); } } + public override bool ForceBodyShapeRebuild(bool inTaintTime) + { + BSScene.TaintCallback rebuildOperation = delegate() + { + _mass = CalculateMass(); // changing the shape changes the mass + CreateGeomAndObject(true); + }; + if (inTaintTime) + rebuildOperation(); + else + PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation); + return true; + } public override bool Grabbed { set { _grabbed = value; } @@ -924,19 +924,19 @@ public sealed class BSPrim : BSPhysObject float tmp; float returnMass = 0; - float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; + float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; float hollowVolume = hollowAmount * hollowAmount; - switch (_pbs.ProfileShape) + switch (BaseShape.ProfileShape) { case ProfileShape.Square: // default box - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { if (hollowAmount > 0.0) { - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -960,19 +960,19 @@ public sealed class BSPrim : BSPhysObject } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { //a tube - volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); - tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); + volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); + tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); volume -= volume*tmp*tmp; if (hollowAmount > 0.0) { hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -997,13 +997,13 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.Circle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { volume *= 0.78539816339f; // elipse base if (hollowAmount > 0.0) { - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1025,10 +1025,10 @@ public sealed class BSPrim : BSPhysObject } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { - volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); volume *= (1.0f - tmp * tmp); if (hollowAmount > 0.0) @@ -1037,7 +1037,7 @@ public sealed class BSPrim : BSPhysObject // calculate the hollow volume by it's shape compared to the prim shape hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1061,7 +1061,7 @@ public sealed class BSPrim : BSPhysObject break; case ProfileShape.HalfCircle: - if (_pbs.PathCurve == (byte)Extrusion.Curve1) + if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.52359877559829887307710723054658f; } @@ -1069,7 +1069,7 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.EquilateralTriangle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { volume *= 0.32475953f; @@ -1077,7 +1077,7 @@ public sealed class BSPrim : BSPhysObject { // calculate the hollow volume by it's shape compared to the prim shape - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1102,11 +1102,11 @@ public sealed class BSPrim : BSPhysObject volume *= (1.0f - hollowVolume); } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.32475953f; - volume *= 0.01f * (float)(200 - _pbs.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); volume *= (1.0f - tmp * tmp); if (hollowAmount > 0.0) @@ -1114,7 +1114,7 @@ public sealed class BSPrim : BSPhysObject hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1154,26 +1154,26 @@ public sealed class BSPrim : BSPhysObject float profileBegin; float profileEnd; - if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) + if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) { - taperX1 = _pbs.PathScaleX * 0.01f; + taperX1 = BaseShape.PathScaleX * 0.01f; if (taperX1 > 1.0f) taperX1 = 2.0f - taperX1; taperX = 1.0f - taperX1; - taperY1 = _pbs.PathScaleY * 0.01f; + taperY1 = BaseShape.PathScaleY * 0.01f; if (taperY1 > 1.0f) taperY1 = 2.0f - taperY1; taperY = 1.0f - taperY1; } else { - taperX = _pbs.PathTaperX * 0.01f; + taperX = BaseShape.PathTaperX * 0.01f; if (taperX < 0.0f) taperX = -taperX; taperX1 = 1.0f - taperX; - taperY = _pbs.PathTaperY * 0.01f; + taperY = BaseShape.PathTaperY * 0.01f; if (taperY < 0.0f) taperY = -taperY; taperY1 = 1.0f - taperY; @@ -1183,13 +1183,13 @@ public sealed class BSPrim : BSPhysObject volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); - pathBegin = (float)_pbs.PathBegin * 2.0e-5f; - pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; + pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; + pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f; volume *= (pathEnd - pathBegin); // this is crude aproximation - profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; - profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; + profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; + profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; volume *= (profileEnd - profileBegin); returnMass = _density * volume; @@ -1251,7 +1251,7 @@ public sealed class BSPrim : BSPhysObject // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs, + PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 861ffe7..d3ba273 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -117,7 +117,7 @@ public class BSShapeCollection : IDisposable // Track another user of a body // We presume the caller has allocated the body. - // Bodies only have one user so the reference count is either 1 or 0. + // Bodies only have one user so the body is just put into the world if not already there. public void ReferenceBody(BulletBody body, bool inTaintTime) { lock (m_collectionActivityLock) @@ -241,26 +241,32 @@ public class BSShapeCollection : IDisposable BSScene.TaintCallback dereferenceOperation = delegate() { - switch (shape.type) + if (shape.ptr != IntPtr.Zero) { - case ShapeData.PhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: - break; - default: + if (shape.isNativeShape) + { // Native shapes are not tracked and are released immediately - if (shape.ptr != IntPtr.Zero & shape.isNativeShape) + DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", + BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); + if (shapeCallback != null) shapeCallback(shape); + BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + } + else + { + switch (shape.type) { - DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); - if (shapeCallback != null) shapeCallback(shape); - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + case ShapeData.PhysicsShapeType.SHAPE_HULL: + DereferenceHull(shape, shapeCallback); + break; + case ShapeData.PhysicsShapeType.SHAPE_MESH: + DereferenceMesh(shape, shapeCallback); + break; + case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + break; + default: + break; } - break; + } } }; if (inTaintTime) @@ -405,7 +411,6 @@ public class BSShapeCollection : IDisposable ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { - BulletShape newShape; shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in @@ -415,27 +420,35 @@ public class BSShapeCollection : IDisposable // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); + BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); + + // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. + DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", + shapeData.ID, newShape, shapeData.Scale); + + prim.BSShape = newShape; + return true; + } + + private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, + ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) + { + BulletShape newShape; + if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; } else { newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; } + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; - // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - shapeData.ID, newShape, shapeData.Scale); - - prim.BSShape = newShape; - return true; + return newShape; } // Builds a mesh shape in the physical world and updates prim.BSShape. @@ -461,6 +474,8 @@ public class BSShapeCollection : IDisposable DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); + // Take evasive action if the mesh was not constructed. + newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); ReferenceShape(newShape); @@ -474,7 +489,7 @@ public class BSShapeCollection : IDisposable private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { IMesh meshData = null; - IntPtr meshPtr; + IntPtr meshPtr = IntPtr.Zero; MeshDesc meshDesc; if (Meshes.TryGetValue(newMeshKey, out meshDesc)) { @@ -486,23 +501,26 @@ public class BSShapeCollection : IDisposable // Pass false for physicalness as this creates some sort of bounding box which we don't need meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - float[] verticesAsFloats = new float[vertices.Count * 3]; - int vi = 0; - foreach (OMV.Vector3 vv in vertices) + if (meshData != null) { - verticesAsFloats[vi++] = vv.X; - verticesAsFloats[vi++] = vv.Y; - verticesAsFloats[vi++] = vv.Z; - } + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); - // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); + float[] verticesAsFloats = new float[vertices.Count * 3]; + int vi = 0; + foreach (OMV.Vector3 vv in vertices) + { + verticesAsFloats[vi++] = vv.X; + verticesAsFloats[vi++] = vv.Y; + verticesAsFloats[vi++] = vv.Z; + } + + // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indices.GetLength(0), indices, vertices.Count, verticesAsFloats); + meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, + indices.GetLength(0), indices, vertices.Count, verticesAsFloats); + } } BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); newShape.shapeKey = newMeshKey; @@ -531,6 +549,7 @@ public class BSShapeCollection : IDisposable DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); + newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); ReferenceShape(newShape); @@ -544,7 +563,7 @@ public class BSShapeCollection : IDisposable private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { - IntPtr hullPtr; + IntPtr hullPtr = IntPtr.Zero; HullDesc hullDesc; if (Hulls.TryGetValue(newHullKey, out hullDesc)) { @@ -556,86 +575,89 @@ public class BSShapeCollection : IDisposable // Build a new hull in the physical world // Pass false for physicalness as this creates some sort of bounding box which we don't need IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - for (int ii = 0; ii < indices.GetLength(0); ii++) - { - convIndices.Add(indices[ii]); - } - foreach (OMV.Vector3 vv in vertices) + if (meshData != null) { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } - // setup and do convex hull conversion - m_hulls = new List(); - DecompDesc dcomp = new DecompDesc(); - dcomp.mIndices = convIndices; - dcomp.mVertices = convVertices; - ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); - // create the hull into the _hulls variable - convexBuilder.process(dcomp); - - // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. - // The format is: - // convHulls[0] = number of hulls - // convHulls[1] = number of vertices in first hull - // convHulls[2] = hull centroid X coordinate - // convHulls[3] = hull centroid Y coordinate - // convHulls[4] = hull centroid Z coordinate - // convHulls[5] = first hull vertex X - // convHulls[6] = first hull vertex Y - // convHulls[7] = first hull vertex Z - // convHulls[8] = second hull vertex X - // ... - // convHulls[n] = number of vertices in second hull - // convHulls[n+1] = second hull centroid X coordinate - // ... - // - // TODO: is is very inefficient. Someday change the convex hull generator to return - // data structures that do not need to be converted in order to pass to Bullet. - // And maybe put the values directly into pinned memory rather than marshaling. - int hullCount = m_hulls.Count; - int totalVertices = 1; // include one for the count of the hulls - foreach (ConvexResult cr in m_hulls) - { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); - convHulls[0] = (float)hullCount; - int jj = 1; - foreach (ConvexResult cr in m_hulls) - { - // copy vertices for index access - float3[] verts = new float3[cr.HullVertices.Count]; - int kk = 0; - foreach (float3 ff in cr.HullVertices) + //format conversion from IMesh format to DecompDesc format + List convIndices = new List(); + List convVertices = new List(); + for (int ii = 0; ii < indices.GetLength(0); ii++) { - verts[kk++] = ff; + convIndices.Add(indices[ii]); + } + foreach (OMV.Vector3 vv in vertices) + { + convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); } - // add to the array one hull's worth of data - convHulls[jj++] = cr.HullIndices.Count; - convHulls[jj++] = 0f; // centroid x,y,z - convHulls[jj++] = 0f; - convHulls[jj++] = 0f; - foreach (int ind in cr.HullIndices) + // setup and do convex hull conversion + m_hulls = new List(); + DecompDesc dcomp = new DecompDesc(); + dcomp.mIndices = convIndices; + dcomp.mVertices = convVertices; + ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); + // create the hull into the _hulls variable + convexBuilder.process(dcomp); + + // Convert the vertices and indices for passing to unmanaged. + // The hull information is passed as a large floating point array. + // The format is: + // convHulls[0] = number of hulls + // convHulls[1] = number of vertices in first hull + // convHulls[2] = hull centroid X coordinate + // convHulls[3] = hull centroid Y coordinate + // convHulls[4] = hull centroid Z coordinate + // convHulls[5] = first hull vertex X + // convHulls[6] = first hull vertex Y + // convHulls[7] = first hull vertex Z + // convHulls[8] = second hull vertex X + // ... + // convHulls[n] = number of vertices in second hull + // convHulls[n+1] = second hull centroid X coordinate + // ... + // + // TODO: is is very inefficient. Someday change the convex hull generator to return + // data structures that do not need to be converted in order to pass to Bullet. + // And maybe put the values directly into pinned memory rather than marshaling. + int hullCount = m_hulls.Count; + int totalVertices = 1; // include one for the count of the hulls + foreach (ConvexResult cr in m_hulls) { - convHulls[jj++] = verts[ind].x; - convHulls[jj++] = verts[ind].y; - convHulls[jj++] = verts[ind].z; + totalVertices += 4; // add four for the vertex count and centroid + totalVertices += cr.HullIndices.Count * 3; // we pass just triangles + } + float[] convHulls = new float[totalVertices]; + + convHulls[0] = (float)hullCount; + int jj = 1; + foreach (ConvexResult cr in m_hulls) + { + // copy vertices for index access + float3[] verts = new float3[cr.HullVertices.Count]; + int kk = 0; + foreach (float3 ff in cr.HullVertices) + { + verts[kk++] = ff; + } + + // add to the array one hull's worth of data + convHulls[jj++] = cr.HullIndices.Count; + convHulls[jj++] = 0f; // centroid x,y,z + convHulls[jj++] = 0f; + convHulls[jj++] = 0f; + foreach (int ind in cr.HullIndices) + { + convHulls[jj++] = verts[ind].x; + convHulls[jj++] = verts[ind].y; + convHulls[jj++] = verts[ind].z; + } } + // create the hull data structure in Bullet + hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } - // create the hull data structure in Bullet - hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); @@ -676,6 +698,50 @@ public class BSShapeCollection : IDisposable return ComputeShapeKey(shapeData, pbs, out lod); } + private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) + { + // If the shape was successfully created, nothing more to do + if (newShape.ptr != IntPtr.Zero) + return newShape; + + // The most common reason for failure is that an underlying asset is not available + + // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset + if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) + { + prim.LastAssetBuildFailed = true; + BSPhysObject xprim = prim; + Util.FireAndForget(delegate + { + RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; + if (assetProvider != null) + { + BSPhysObject yprim = xprim; // probably not necessary, but, just in case. + assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) + { + if (!yprim.BaseShape.SculptEntry) + return; + if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) + return; + + yprim.BaseShape.SculptData = new byte[asset.Data.Length]; + asset.Data.CopyTo(yprim.BaseShape.SculptData, 0); + // This will cause the prim to see that the filler shape is not the right + // one and try again to build the object. + yprim.ForceBodyShapeRebuild(false); + + }); + } + }); + } + + // While we figure out the real problem, stick a simple native shape on the object. + BulletShape fillinShape = + BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE); + + return fillinShape; + } + // Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. -- cgit v1.1