BulletSim: tweaking so avatar can be pushed. In particular, llPushObject,

which called BSCharacter.AddForce, can now move a character.
LSLKeyTest
Robert Adams 2016-01-02 17:36:42 -08:00
parent 151001c70b
commit d4e88f8883
5 changed files with 57 additions and 18 deletions

View File

@ -187,13 +187,26 @@ public class BSActorAvatarMove : BSActor
if (m_controllingPrim.IsColliding) 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) if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect)
{
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_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
m_controllingPrim.IsStationary = true; m_controllingPrim.IsStationary = true;
m_controllingPrim.ZeroMotion(true /* inTaintTime */); 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 // Standing has more friction on the ground
if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction) if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction)
@ -222,8 +235,8 @@ public class BSActorAvatarMove : BSActor
} }
} }
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", 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.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding,m_controllingPrim.IsStationary);
} }
else else
{ {
@ -237,6 +250,8 @@ public class BSActorAvatarMove : BSActor
m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); 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) if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
{ {
stepVelocity.Z = m_controllingPrim.RawVelocity.Z; stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
@ -267,11 +282,9 @@ public class BSActorAvatarMove : BSActor
} }
else else
{ {
// Since we're not affected by anything, the avatar must be falling and we do not want that to be too fast. // 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) if (m_controllingPrim.RawVelocity.Z < BSParam.AvatarTerminalVelocity)
{ {
stepVelocity.Z = BSParam.AvatarTerminalVelocity; stepVelocity.Z = BSParam.AvatarTerminalVelocity;
} }
else else
@ -315,7 +328,11 @@ public class BSActorAvatarMove : BSActor
if (m_controllingPrim.IsStationary) if (m_controllingPrim.IsStationary)
{ {
entprop.Position = m_controllingPrim.RawPosition; entprop.Position = m_controllingPrim.RawPosition;
// 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; entprop.Velocity = OMV.Vector3.Zero;
}
m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation); m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
} }

View File

@ -652,13 +652,16 @@ public sealed class BSCharacter : BSPhysObject
public override void AddForce(OMV.Vector3 force, bool pushforce) 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. // 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 // The interaction of this force with the simulator rate and collision occurance is tricky.
// with a adicional parameter to sync with old ode // ODE multiplies the force by 100
if(pushforce) // ubODE multiplies the force by 5.3
addForce = addForce * Density * BSParam.DensityScaleFactor * 0.08f;; // 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); AddForce(addForce, pushforce, false);
} }
@ -666,7 +669,7 @@ public sealed class BSCharacter : BSPhysObject
if (force.IsFinite()) if (force.IsFinite())
{ {
OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 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() 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); // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
if (PhysBody.HasPhysicalBody) 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.ApplyCentralForce(PhysBody, addForce);
PhysScene.PE.Activate(PhysBody, true); PhysScene.PE.Activate(PhysBody, true);
} }

View File

@ -149,7 +149,9 @@ public static class BSParam
public static float AvatarFlyingGroundUpForce { get; private set; } public static float AvatarFlyingGroundUpForce { get; private set; }
public static float AvatarTerminalVelocity { get; private set; } public static float AvatarTerminalVelocity { get; private set; }
public static float AvatarContactProcessingThreshold { 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 AvatarStopZeroThreshold { get; private set; }
public static float AvatarStopZeroThresholdSquared { get; private set; }
public static int AvatarJumpFrames { get; private set; } public static int AvatarJumpFrames { get; private set; }
public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
public static float AvatarStepHeight { 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_D { get; private set; } // derivative
public static float PID_P { get; private set; } // proportional 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. // Various constants that come from that other virtual world that shall not be named.
public const float MinGravityZ = -1f; public const float MinGravityZ = -1f;
public const float MaxGravityZ = 28f; public const float MaxGravityZ = 28f;
@ -601,7 +605,7 @@ public static class BSParam
1.3f ), 1.3f ),
// For historical reasons, density is reported * 100 // For historical reasons, density is reported * 100
new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation. Scaled times 100.", new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation. Scaled times 100.",
3500f) , // 3.5 * 100 350f) , // 3.5 * 100
new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
0f ), 0f ),
new ParameterDefn<int>("AvatarShape", "Code for avatar physical shape: 0:capsule, 1:cube, 2:ovoid, 2:mesh", new ParameterDefn<int>("AvatarShape", "Code for avatar physical shape: 0:capsule, 1:cube, 2:ovoid, 2:mesh",
@ -626,8 +630,12 @@ public static class BSParam
-54.0f ), -54.0f ),
new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
0.1f ), 0.1f ),
new ParameterDefn<float>("AvatarAddForcePushFactor", "BSCharacter.AddForce is multiplied by this and mass to be like other physics engines",
0.315f ),
new ParameterDefn<float>("AvatarStopZeroThreshold", "Movement velocity below which avatar is assumed to be stopped", new ParameterDefn<float>("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<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
1.0f ), 1.0f ),
new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.", new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
@ -812,6 +820,9 @@ public static class BSParam
new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
40 ), 40 ),
new ParameterDefn<float>("DebugNumber", "A console setable number sometimes used for debugging",
1.0f ),
new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)", new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
0, 0,
(s) => { return s.PhysicsMetricDumpFrames; }, (s) => { return s.PhysicsMetricDumpFrames; },

View File

@ -239,8 +239,10 @@ public abstract class BSPhysObject : PhysicsActor
public virtual OMV.Vector3 RawVelocity { get; set; } public virtual OMV.Vector3 RawVelocity { get; set; }
public abstract OMV.Vector3 ForceVelocity { 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 RawForce { get; set; }
public OMV.Vector3 RawTorque { get; set; } public OMV.Vector3 RawTorque { get; set; }
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) public override void AddAngularForce(OMV.Vector3 force, bool pushforce)
{ {
AddAngularForce(force, pushforce, false); AddAngularForce(force, pushforce, false);
@ -570,7 +572,11 @@ public abstract class BSPhysObject : PhysicsActor
PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate() PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate()
{ {
if (PhysBody.HasPhysicalBody) if (PhysBody.HasPhysicalBody)
{
CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 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 else

View File

@ -679,7 +679,6 @@ namespace OpenSim.Region.PhysicsModule.BulletS
try try
{ {
numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
} }
catch (Exception e) catch (Exception e)
{ {