BulletSim: change PositionSanityCheck to apply a force to correct position corrections (below ground and floating).

connector_plugin
Robert Adams 2012-11-20 08:43:43 -08:00
parent 2f5fe4b88e
commit 4d29488216
2 changed files with 30 additions and 33 deletions

View File

@ -47,7 +47,6 @@ public sealed class BSPrim : BSPhysObject
// _size is what the user passed. Scale is what we pass to the physics engine with the mesh. // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
// Often Scale is unity because the meshmerizer will apply _size when creating the mesh. // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
// private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
private bool _grabbed; private bool _grabbed;
private bool _isSelected; private bool _isSelected;
@ -274,19 +273,19 @@ public sealed class BSPrim : BSPhysObject
if (!Linkset.IsRoot(this)) if (!Linkset.IsRoot(this))
_position = Linkset.Position(this); _position = Linkset.Position(this);
// don't do the GetObjectPosition for root elements because this function is called a zillion times // don't do the GetObjectPosition for root elements because this function is called a zillion times.
// _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
return _position; return _position;
} }
set { set {
// If you must push the position into the physics engine, use ForcePosition. // If the position must be forced into the physics engine, use ForcePosition.
if (_position == value) if (_position == value)
{ {
return; return;
} }
_position = value; _position = value;
// TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
PositionSanityCheck(); PositionSanityCheck(false);
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
{ {
// DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
@ -302,7 +301,7 @@ public sealed class BSPrim : BSPhysObject
} }
set { set {
_position = value; _position = value;
PositionSanityCheck(); // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better.
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
ActivateIfPhysical(false); ActivateIfPhysical(false);
} }
@ -311,52 +310,43 @@ public sealed class BSPrim : BSPhysObject
// Check that the current position is sane and, if not, modify the position to make it so. // Check that the current position is sane and, if not, modify the position to make it so.
// Check for being below terrain and being out of bounds. // Check for being below terrain and being out of bounds.
// Returns 'true' of the position was made sane by some action. // Returns 'true' of the position was made sane by some action.
private bool PositionSanityCheck() private bool PositionSanityCheck(bool inTaintTime)
{ {
bool ret = false; bool ret = false;
// If totally below the ground, move the prim up
// TODO: figure out the right solution for this... only for dynamic objects?
/*
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
OMV.Vector3 upForce = OMV.Vector3.Zero;
if (Position.Z < terrainHeight) if (Position.Z < terrainHeight)
{ {
DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
_position.Z = terrainHeight + 2.0f; float targetHeight = terrainHeight + (Size.Z / 2f);
// Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
upForce.Z = (terrainHeight - Position.Z) * 1f;
ret = true; ret = true;
} }
*/
if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
{ {
float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
// TODO: a floating motor so object will bob in the water // TODO: a floating motor so object will bob in the water
if (Position.Z < waterHeight) if (Math.Abs(Position.Z - waterHeight) > 0.1f)
{ {
_position.Z = waterHeight; // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
upForce.Z = (waterHeight - Position.Z) * 1f;
ret = true; ret = true;
} }
} }
// TODO: check for out of bounds // TODO: check for out of bounds
return ret;
}
// A version of the sanity check that also makes sure a new position value is // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
// pushed to the physics engine. This routine would be used by anyone if (ret)
// who is not already pushing the value.
private bool PositionSanityCheck(bool inTaintTime)
{ {
bool ret = false; PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck:belowTerrain", delegate()
if (PositionSanityCheck())
{ {
// The new position value must be pushed into the physics engine but we can't // Apply upforce and overcome gravity.
// just assign to "Position" because of potential call loops. ForceVelocity = ForceVelocity + upForce - PhysicsScene.DefaultGravity;
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate()
{
DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
ForcePosition = _position;
}); });
ret = true;
} }
return ret; return ret;
} }
@ -940,6 +930,7 @@ public sealed class BSPrim : BSPhysObject
public override void AddForce(OMV.Vector3 force, bool pushforce) { public override void AddForce(OMV.Vector3 force, bool pushforce) {
AddForce(force, pushforce, false); AddForce(force, pushforce, false);
} }
// Applying a force just adds this to the total force on the object.
public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
// for an object, doesn't matter if force is a pushforce or not // for an object, doesn't matter if force is a pushforce or not
if (force.IsFinite()) if (force.IsFinite())
@ -971,6 +962,7 @@ public sealed class BSPrim : BSPhysObject
}); });
} }
// An impulse force is scaled by the mass of the object.
public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
{ {
OMV.Vector3 applyImpulse = impulse; OMV.Vector3 applyImpulse = impulse;
@ -1423,7 +1415,7 @@ public sealed class BSPrim : BSPhysObject
if (changed != 0) if (changed != 0)
{ {
// Only update the position of single objects and linkset roots // Only update the position of single objects and linkset roots
if (this._parentPrim == null) if (Linkset.IsRoot(this))
{ {
base.RequestPhysicsterseUpdate(); base.RequestPhysicsterseUpdate();
} }
@ -1435,19 +1427,24 @@ public sealed class BSPrim : BSPhysObject
// Updates only for individual prims and for the root object of a linkset. // Updates only for individual prims and for the root object of a linkset.
if (Linkset.IsRoot(this)) if (Linkset.IsRoot(this))
{ {
// Assign to the local variables so the normal set action does not happen // Assign directly to the local variables so the normal set action does not happen
_position = entprop.Position; _position = entprop.Position;
_orientation = entprop.Rotation; _orientation = entprop.Rotation;
_velocity = entprop.Velocity; _velocity = entprop.Velocity;
_acceleration = entprop.Acceleration; _acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity; _rotationalVelocity = entprop.RotationalVelocity;
// The sanity check can change the velocity and/or position.
if (PositionSanityCheck(true))
{
entprop.Position = _position;
entprop.Velocity = _velocity;
}
// remember the current and last set values // remember the current and last set values
LastEntityProperties = CurrentEntityProperties; LastEntityProperties = CurrentEntityProperties;
CurrentEntityProperties = entprop; CurrentEntityProperties = entprop;
PositionSanityCheck(true);
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);

View File

@ -940,7 +940,7 @@ public sealed class BSShapeCollection : IDisposable
else else
{ {
bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
prim.LocalID, prim.ForcePosition, prim.ForceOrientation); prim.LocalID, prim.RawPosition, prim.RawOrientation);
DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
} }
aBody = new BulletBody(prim.LocalID, bodyPtr); aBody = new BulletBody(prim.LocalID, bodyPtr);