aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-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.