aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorRobert Adams2012-12-21 17:27:53 -0800
committerRobert Adams2012-12-21 17:27:53 -0800
commit3d659fe97d79c04983dcfa8c78e9dde1623f54f2 (patch)
tree6333754a97f616a1fdf1de5b91f0358c21a16c83 /OpenSim/Region
parentBulletSim: repair vehicle problems introduced in previous 'improvements'. Fix... (diff)
downloadopensim-SC-3d659fe97d79c04983dcfa8c78e9dde1623f54f2.zip
opensim-SC-3d659fe97d79c04983dcfa8c78e9dde1623f54f2.tar.gz
opensim-SC-3d659fe97d79c04983dcfa8c78e9dde1623f54f2.tar.bz2
opensim-SC-3d659fe97d79c04983dcfa8c78e9dde1623f54f2.tar.xz
BulletSim: add BSPhysObject code to manage registrations of preStep events. Use same to implement setForce and setTorque so the values are restored at the beginning of each step (since Bullet zeros forces applied last step). Simplify implementation of AddForce and AddTorque by relying on the addition of forces in Bullet.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs56
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs112
3 files changed, 104 insertions, 66 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 7bde1c1..b392d75 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -134,6 +134,8 @@ public sealed class BSCharacter : BSPhysObject
134 // called when this character is being destroyed and the resources should be released 134 // called when this character is being destroyed and the resources should be released
135 public override void Destroy() 135 public override void Destroy()
136 { 136 {
137 base.Destroy();
138
137 DetailLog("{0},BSCharacter.Destroy", LocalID); 139 DetailLog("{0},BSCharacter.Destroy", LocalID);
138 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 140 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
139 { 141 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 92a5f2f..9525a11 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -45,6 +45,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. 45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
46 * The last two (and certainly the last one) should be referenced only in taint-time. 46 * The last two (and certainly the last one) should be referenced only in taint-time.
47 */ 47 */
48
49/*
50 * As of 20121221, the following are the call sequences (going down) for different script physical functions:
51 * llApplyImpulse llApplyRotImpulse llSetTorque llSetForce
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque
56 */
57
48public abstract class BSPhysObject : PhysicsActor 58public abstract class BSPhysObject : PhysicsActor
49{ 59{
50 protected BSPhysObject() 60 protected BSPhysObject()
@@ -69,6 +79,12 @@ public abstract class BSPhysObject : PhysicsActor
69 CollidingGroundStep = 0; 79 CollidingGroundStep = 0;
70 } 80 }
71 81
82 // Tell the object to clean up.
83 public virtual void Destroy()
84 {
85 UnRegisterAllPreStepActions();
86 }
87
72 public BSScene PhysicsScene { get; protected set; } 88 public BSScene PhysicsScene { get; protected set; }
73 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 89 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
74 public string PhysObjectName { get; protected set; } 90 public string PhysObjectName { get; protected set; }
@@ -130,9 +146,6 @@ public abstract class BSPhysObject : PhysicsActor
130 // Update the physical location and motion of the object. Called with data from Bullet. 146 // Update the physical location and motion of the object. Called with data from Bullet.
131 public abstract void UpdateProperties(EntityProperties entprop); 147 public abstract void UpdateProperties(EntityProperties entprop);
132 148
133 // Tell the object to clean up.
134 public abstract void Destroy();
135
136 public abstract OMV.Vector3 RawPosition { get; set; } 149 public abstract OMV.Vector3 RawPosition { get; set; }
137 public abstract OMV.Vector3 ForcePosition { get; set; } 150 public abstract OMV.Vector3 ForcePosition { get; set; }
138 151
@@ -280,11 +293,48 @@ public abstract class BSPhysObject : PhysicsActor
280 293
281 #endregion // Collisions 294 #endregion // Collisions
282 295
296 #region Per Simulation Step actions
297 // There are some actions that must be performed for a physical object before each simulation step.
298 // These actions are optional so, rather than scanning all the physical objects and asking them
299 // if they have anything to do, a physical object registers for an event call before the step is performed.
300 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
301 private Dictionary<string, BSScene.PreStepAction> RegisteredActions = new Dictionary<string, BSScene.PreStepAction>();
302 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
303 {
304 string identifier = op + "-" + id.ToString();
305 RegisteredActions[identifier] = actn;
306 PhysicsScene.BeforeStep += actn;
307 }
308
309 // Unregister a pre step action. Safe to call if the action has not been registered.
310 protected void UnRegisterPreStepAction(string op, uint id)
311 {
312 string identifier = op + "-" + id.ToString();
313 if (RegisteredActions.ContainsKey(identifier))
314 {
315 PhysicsScene.BeforeStep -= RegisteredActions[identifier];
316 RegisteredActions.Remove(identifier);
317 }
318 }
319
320 protected void UnRegisterAllPreStepActions()
321 {
322 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
323 {
324 PhysicsScene.BeforeStep -= kvp.Value;
325 }
326 RegisteredActions.Clear();
327 }
328
329
330 #endregion // Per Simulation Step actions
331
283 // High performance detailed logging routine used by the physical objects. 332 // High performance detailed logging routine used by the physical objects.
284 protected void DetailLog(string msg, params Object[] args) 333 protected void DetailLog(string msg, params Object[] args)
285 { 334 {
286 if (PhysicsScene.PhysicsLogging.Enabled) 335 if (PhysicsScene.PhysicsLogging.Enabled)
287 PhysicsScene.DetailLog(msg, args); 336 PhysicsScene.DetailLog(msg, args);
288 } 337 }
338
289} 339}
290} 340}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index e43bf8e..e6aeebb 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -129,6 +129,7 @@ public sealed class BSPrim : BSPhysObject
129 public override void Destroy() 129 public override void Destroy()
130 { 130 {
131 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 131 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
132 base.Destroy();
132 133
133 // Undo any links between me and any other object 134 // Undo any links between me and any other object
134 BSPhysObject parentBefore = Linkset.LinksetRoot; 135 BSPhysObject parentBefore = Linkset.LinksetRoot;
@@ -434,12 +435,22 @@ public sealed class BSPrim : BSPhysObject
434 get { return _force; } 435 get { return _force; }
435 set { 436 set {
436 _force = value; 437 _force = value;
437 PhysicsScene.TaintedObject("BSPrim.setForce", delegate() 438 if (_force != OMV.Vector3.Zero)
438 { 439 {
439 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 440 // If the force is non-zero, it must be reapplied each tick because
440 if (PhysBody.HasPhysicalBody) 441 // Bullet clears the forces applied last frame.
441 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); 442 RegisterPreStepAction("BSPrim.setForce", LocalID,
442 }); 443 delegate(float timeStep)
444 {
445 if (PhysBody.HasPhysicalBody)
446 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, _force);
447 }
448 );
449 }
450 else
451 {
452 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
453 }
443 } 454 }
444 } 455 }
445 456
@@ -550,7 +561,22 @@ public sealed class BSPrim : BSPhysObject
550 get { return _torque; } 561 get { return _torque; }
551 set { 562 set {
552 _torque = value; 563 _torque = value;
553 AddAngularForce(_torque, false, false); 564 if (_torque != OMV.Vector3.Zero)
565 {
566 // If the torque is non-zero, it must be reapplied each tick because
567 // Bullet clears the forces applied last frame.
568 RegisterPreStepAction("BSPrim.setTorque", LocalID,
569 delegate(float timeStep)
570 {
571 if (PhysBody.HasPhysicalBody)
572 AddAngularForce(_torque, false, true);
573 }
574 );
575 }
576 else
577 {
578 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
579 }
554 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 580 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
555 } 581 }
556 } 582 }
@@ -969,56 +995,32 @@ public sealed class BSPrim : BSPhysObject
969 public override float APIDStrength { set { return; } } 995 public override float APIDStrength { set { return; } }
970 public override float APIDDamping { set { return; } } 996 public override float APIDDamping { set { return; } }
971 997
972 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
973 public override void AddForce(OMV.Vector3 force, bool pushforce) { 998 public override void AddForce(OMV.Vector3 force, bool pushforce) {
974 AddForce(force, pushforce, false); 999 AddForce(force, pushforce, false);
975 } 1000 }
976 // Applying a force just adds this to the total force on the object. 1001 // Applying a force just adds this to the total force on the object.
1002 // This added force will only last the next simulation tick.
977 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1003 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
978 // for an object, doesn't matter if force is a pushforce or not 1004 // for an object, doesn't matter if force is a pushforce or not
979 if (force.IsFinite()) 1005 if (force.IsFinite())
980 { 1006 {
981 // _force += force; 1007 OMV.Vector3 addForce = force;
982 lock (m_accumulatedForces) 1008 DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
983 m_accumulatedForces.Add(new OMV.Vector3(force)); 1009 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
1010 {
1011 // Bullet adds this central force to the total force for this tick
1012 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1013 if (PhysBody.HasPhysicalBody)
1014 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, addForce);
1015 });
984 } 1016 }
985 else 1017 else
986 { 1018 {
987 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 1019 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
988 return; 1020 return;
989 } 1021 }
990 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
991 {
992 OMV.Vector3 fSum = OMV.Vector3.Zero;
993 lock (m_accumulatedForces)
994 {
995 // Sum the accumulated additional forces for one big force to apply once.
996 foreach (OMV.Vector3 v in m_accumulatedForces)
997 {
998 fSum += v;
999 }
1000 m_accumulatedForces.Clear();
1001 }
1002 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
1003 if (fSum != OMV.Vector3.Zero)
1004 if (PhysBody.HasPhysicalBody)
1005 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
1006 });
1007 } 1022 }
1008 1023
1009 // An impulse force is scaled by the mass of the object.
1010 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
1011 {
1012 OMV.Vector3 applyImpulse = impulse;
1013 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
1014 {
1015 DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
1016 if (PhysBody.HasPhysicalBody)
1017 BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
1018 });
1019 }
1020
1021 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
1022 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 1024 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
1023 AddAngularForce(force, pushforce, false); 1025 AddAngularForce(force, pushforce, false);
1024 } 1026 }
@@ -1026,36 +1028,20 @@ public sealed class BSPrim : BSPhysObject
1026 { 1028 {
1027 if (force.IsFinite()) 1029 if (force.IsFinite())
1028 { 1030 {
1029 // _force += force; 1031 OMV.Vector3 angForce = force;
1030 lock (m_accumulatedAngularForces) 1032 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
1031 m_accumulatedAngularForces.Add(new OMV.Vector3(force)); 1033 {
1034 if (PhysBody.HasPhysicalBody)
1035 BulletSimAPI.ApplyTorque2(PhysBody.ptr, angForce);
1036 });
1032 } 1037 }
1033 else 1038 else
1034 { 1039 {
1035 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 1040 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
1036 return; 1041 return;
1037 } 1042 }
1038 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
1039 {
1040 OMV.Vector3 fSum = OMV.Vector3.Zero;
1041 lock (m_accumulatedAngularForces)
1042 {
1043 // Sum the accumulated additional forces for one big force to apply once.
1044 foreach (OMV.Vector3 v in m_accumulatedAngularForces)
1045 {
1046 fSum += v;
1047 }
1048 m_accumulatedAngularForces.Clear();
1049 }
1050 DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
1051 if (fSum != OMV.Vector3.Zero)
1052 {
1053 if (PhysBody.HasPhysicalBody)
1054 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
1055 _torque = fSum;
1056 }
1057 });
1058 } 1043 }
1044
1059 // A torque impulse. 1045 // A torque impulse.
1060 // ApplyTorqueImpulse adds torque directly to the angularVelocity. 1046 // ApplyTorqueImpulse adds torque directly to the angularVelocity.
1061 // AddAngularForce accumulates the force and applied it to the angular velocity all at once. 1047 // AddAngularForce accumulates the force and applied it to the angular velocity all at once.