diff options
author | Robert Adams | 2012-12-21 17:27:53 -0800 |
---|---|---|
committer | Robert Adams | 2012-12-21 17:27:53 -0800 |
commit | 3d659fe97d79c04983dcfa8c78e9dde1623f54f2 (patch) | |
tree | 6333754a97f616a1fdf1de5b91f0358c21a16c83 | |
parent | BulletSim: repair vehicle problems introduced in previous 'improvements'. Fix... (diff) | |
download | opensim-SC_OLD-3d659fe97d79c04983dcfa8c78e9dde1623f54f2.zip opensim-SC_OLD-3d659fe97d79c04983dcfa8c78e9dde1623f54f2.tar.gz opensim-SC_OLD-3d659fe97d79c04983dcfa8c78e9dde1623f54f2.tar.bz2 opensim-SC_OLD-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.
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 56 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 112 |
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 | |||
48 | public abstract class BSPhysObject : PhysicsActor | 58 | public 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. |