diff options
Diffstat (limited to 'OpenSim/Region/Physics')
-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. |