From d4e88f8883eca60021ec852a97507c2b94685452 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 2 Jan 2016 17:36:42 -0800 Subject: [PATCH] BulletSim: tweaking so avatar can be pushed. In particular, llPushObject, which called BSCharacter.AddForce, can now move a character. --- .../BulletS/BSActorAvatarMove.cs | 35 ++++++++++++++----- .../PhysicsModules/BulletS/BSCharacter.cs | 18 ++++++---- .../Region/PhysicsModules/BulletS/BSParam.cs | 15 ++++++-- .../PhysicsModules/BulletS/BSPhysObject.cs | 6 ++++ .../Region/PhysicsModules/BulletS/BSScene.cs | 1 - 5 files changed, 57 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs b/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs index 0191893781..12ffacbce1 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs @@ -187,12 +187,25 @@ public class BSActorAvatarMove : BSActor if (m_controllingPrim.IsColliding) { - // If we are colliding with a stationary object, presume we're standing and don't move around + // if colliding with something stationary and we're not doing volume detect . if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect) { - m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID); - m_controllingPrim.IsStationary = true; - m_controllingPrim.ZeroMotion(true /* inTaintTime */); + m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,totalForce={1}, vel={2}", /* DEBUG */ + m_controllingPrim.LocalID, m_physicsScene.PE.GetTotalForce(m_controllingPrim.PhysBody), m_controllingPrim.Velocity); /* DEBUG */ + // If velocity is very small, assume it is movement creep and suppress it. + // Applying push forces (Character.AddForce) should move the avatar and that is only seen here as velocity. + if ( (m_controllingPrim.Velocity.LengthSquared() < BSParam.AvatarStopZeroThresholdSquared) + && (m_physicsScene.PE.GetTotalForce(m_controllingPrim.PhysBody).LengthSquared() < BSParam.AvatarStopZeroThresholdSquared) ) + { + m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID); + m_controllingPrim.IsStationary = true; + m_controllingPrim.ZeroMotion(true /* inTaintTime */); + } + else + { + m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,not zeroing because velocity={1}", + m_controllingPrim.LocalID, m_controllingPrim.Velocity); + } } // Standing has more friction on the ground @@ -222,8 +235,8 @@ public class BSActorAvatarMove : BSActor } } - m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", - m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding); + m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2},isStationary={3}", + m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding,m_controllingPrim.IsStationary); } else { @@ -237,6 +250,8 @@ public class BSActorAvatarMove : BSActor m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); } + // If not flying and not colliding, assume falling and keep the downward motion component. + // This check is done here for the next jump test. if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) { stepVelocity.Z = m_controllingPrim.RawVelocity.Z; @@ -267,11 +282,9 @@ public class BSActorAvatarMove : BSActor } else { - // Since we're not affected by anything, the avatar must be falling and we do not want that to be too fast. if (m_controllingPrim.RawVelocity.Z < BSParam.AvatarTerminalVelocity) { - stepVelocity.Z = BSParam.AvatarTerminalVelocity; } else @@ -315,7 +328,11 @@ public class BSActorAvatarMove : BSActor if (m_controllingPrim.IsStationary) { entprop.Position = m_controllingPrim.RawPosition; - entprop.Velocity = OMV.Vector3.Zero; + // Suppress small movement velocity + if (entprop.Velocity.LengthSquared() < BSParam.AvatarStopZeroThresholdSquared) { + m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,OnPreUpdate,zeroing velocity={1}", m_controllingPrim.LocalID, entprop.Velocity); + entprop.Velocity = OMV.Vector3.Zero; + } m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation); } diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs index bd3c7acff2..ab9cc27e3f 100644 --- a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs @@ -652,13 +652,16 @@ public sealed class BSCharacter : BSPhysObject public override void AddForce(OMV.Vector3 force, bool pushforce) { // Since this force is being applied in only one step, make this a force per second. - OMV.Vector3 addForce = force / PhysScene.LastTimeStep; + OMV.Vector3 addForce = force; - // compensate for density variation - // with a adicional parameter to sync with old ode - if(pushforce) - addForce = addForce * Density * BSParam.DensityScaleFactor * 0.08f;; + // The interaction of this force with the simulator rate and collision occurance is tricky. + // ODE multiplies the force by 100 + // ubODE multiplies the force by 5.3 + // BulletSim, after much in-world testing, thinks it gets a similar effect by multiplying mass*0.315f + // This number could be a feature of friction or timing, but it seems to move avatars the same as ubODE + addForce *= Mass * BSParam.AvatarAddForcePushFactor; + DetailLog("{0},BSCharacter.addForce,call,force={1},addForce={2},push={3},mass={4}", LocalID, force, addForce, pushforce, Mass); AddForce(addForce, pushforce, false); } @@ -666,7 +669,7 @@ public sealed class BSCharacter : BSPhysObject if (force.IsFinite()) { OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); - // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); + // DetailLog("{0},BSCharacter.addForce,call,force={1},push={2},inTaint={3}", LocalID, addForce, pushforce, inTaintTime); PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.AddForce", delegate() { @@ -674,6 +677,9 @@ public sealed class BSCharacter : BSPhysObject // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); if (PhysBody.HasPhysicalBody) { + // Bullet adds this central force to the total force for this tick. + // Deep down in Bullet: + // linearVelocity += totalForce / mass * timeStep; PhysScene.PE.ApplyCentralForce(PhysBody, addForce); PhysScene.PE.Activate(PhysBody, true); } diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs b/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs index c2960086bf..aea69d7061 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs @@ -149,7 +149,9 @@ public static class BSParam public static float AvatarFlyingGroundUpForce { get; private set; } public static float AvatarTerminalVelocity { get; private set; } public static float AvatarContactProcessingThreshold { get; private set; } + public static float AvatarAddForcePushFactor { get; private set; } public static float AvatarStopZeroThreshold { get; private set; } + public static float AvatarStopZeroThresholdSquared { get; private set; } public static int AvatarJumpFrames { get; private set; } public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } public static float AvatarStepHeight { get; private set; } @@ -230,6 +232,8 @@ public static class BSParam public static float PID_D { get; private set; } // derivative public static float PID_P { get; private set; } // proportional + public static float DebugNumber { get; private set; } // A console setable number used for debugging + // Various constants that come from that other virtual world that shall not be named. public const float MinGravityZ = -1f; public const float MaxGravityZ = 28f; @@ -601,7 +605,7 @@ public static class BSParam 1.3f ), // For historical reasons, density is reported * 100 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation. Scaled times 100.", - 3500f) , // 3.5 * 100 + 350f) , // 3.5 * 100 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 0f ), new ParameterDefn("AvatarShape", "Code for avatar physical shape: 0:capsule, 1:cube, 2:ovoid, 2:mesh", @@ -626,8 +630,12 @@ public static class BSParam -54.0f ), new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 0.1f ), + new ParameterDefn("AvatarAddForcePushFactor", "BSCharacter.AddForce is multiplied by this and mass to be like other physics engines", + 0.315f ), new ParameterDefn("AvatarStopZeroThreshold", "Movement velocity below which avatar is assumed to be stopped", - 0.1f ), + 0.1f, + (s) => { return (float)AvatarStopZeroThreshold; }, + (s,v) => { AvatarStopZeroThreshold = v; AvatarStopZeroThresholdSquared = v * v; } ), new ParameterDefn("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", 1.0f ), new ParameterDefn("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.", @@ -812,6 +820,9 @@ public static class BSParam new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", 40 ), + new ParameterDefn("DebugNumber", "A console setable number sometimes used for debugging", + 1.0f ), + new ParameterDefn("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)", 0, (s) => { return s.PhysicsMetricDumpFrames; }, diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs index 0ad95c4a0d..e8ea604c2f 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs @@ -239,8 +239,10 @@ public abstract class BSPhysObject : PhysicsActor public virtual OMV.Vector3 RawVelocity { get; set; } public abstract OMV.Vector3 ForceVelocity { get; set; } + // RawForce is a constant force applied to object (see Force { set; } ) public OMV.Vector3 RawForce { get; set; } public OMV.Vector3 RawTorque { get; set; } + public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { AddAngularForce(force, pushforce, false); @@ -570,7 +572,11 @@ public abstract class BSPhysObject : PhysicsActor PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate() { if (PhysBody.HasPhysicalBody) + { CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + DetailLog("{0},{1}.SubscribeEvents,setting collision. ms={2}, collisionFlags={3:x}", + LocalID, TypeName, ms, CurrentCollisionFlags); + } }); } else diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs index f02104c5fb..747bad5ff9 100644 --- a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs @@ -679,7 +679,6 @@ namespace OpenSim.Region.PhysicsModule.BulletS try { numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); - } catch (Exception e) {