aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs212
1 files changed, 201 insertions, 11 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index f6a890e..027c786 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -45,6 +45,26 @@ 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
58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc.
59public enum UpdatedProperties : uint
60{
61 Position = 1 << 0,
62 Orientation = 1 << 1,
63 Velocity = 1 << 2,
64 Acceleration = 1 << 3,
65 RotationalVelocity = 1 << 4,
66 EntPropUpdates = Position | Orientation | Velocity | Acceleration | RotationalVelocity,
67}
48public abstract class BSPhysObject : PhysicsActor 68public abstract class BSPhysObject : PhysicsActor
49{ 69{
50 protected BSPhysObject() 70 protected BSPhysObject()
@@ -57,26 +77,45 @@ public abstract class BSPhysObject : PhysicsActor
57 PhysObjectName = name; 77 PhysObjectName = name;
58 TypeName = typeName; 78 TypeName = typeName;
59 79
80 // We don't have any physical representation yet.
81 PhysBody = new BulletBody(localID);
82 PhysShape = new BulletShape();
83
84 // A linkset of just me
60 Linkset = BSLinkset.Factory(PhysicsScene, this); 85 Linkset = BSLinkset.Factory(PhysicsScene, this);
86 PositionDisplacement = OMV.Vector3.Zero;
87
61 LastAssetBuildFailed = false; 88 LastAssetBuildFailed = false;
62 89
90 // Default material type
91 Material = MaterialAttributes.Material.Wood;
92
63 CollisionCollection = new CollisionEventUpdate(); 93 CollisionCollection = new CollisionEventUpdate();
94 CollisionsLastTick = CollisionCollection;
64 SubscribedEventsMs = 0; 95 SubscribedEventsMs = 0;
65 CollidingStep = 0; 96 CollidingStep = 0;
66 CollidingGroundStep = 0; 97 CollidingGroundStep = 0;
67 } 98 }
68 99
100 // Tell the object to clean up.
101 public virtual void Destroy()
102 {
103 UnRegisterAllPreStepActions();
104 }
105
69 public BSScene PhysicsScene { get; protected set; } 106 public BSScene PhysicsScene { get; protected set; }
70 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 107 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
71 public string PhysObjectName { get; protected set; } 108 public string PhysObjectName { get; protected set; }
72 public string TypeName { get; protected set; } 109 public string TypeName { get; protected set; }
73 110
74 public BSLinkset Linkset { get; set; } 111 public BSLinkset Linkset { get; set; }
112 public BSLinksetInfo LinksetInfo { get; set; }
75 113
76 // Return the object mass without calculating it or having side effects 114 // Return the object mass without calculating it or having side effects
77 public abstract float RawMass { get; } 115 public abstract float RawMass { get; }
78 // Set the raw mass but also update physical mass properties (inertia, ...) 116 // Set the raw mass but also update physical mass properties (inertia, ...)
79 public abstract void UpdatePhysicalMassProperties(float mass); 117 // 'inWorld' true if the object has already been added to the dynamic world.
118 public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld);
80 119
81 // The last value calculated for the prim's inertia 120 // The last value calculated for the prim's inertia
82 public OMV.Vector3 Inertia { get; set; } 121 public OMV.Vector3 Inertia { get; set; }
@@ -105,9 +144,22 @@ public abstract class BSPhysObject : PhysicsActor
105 public EntityProperties CurrentEntityProperties { get; set; } 144 public EntityProperties CurrentEntityProperties { get; set; }
106 public EntityProperties LastEntityProperties { get; set; } 145 public EntityProperties LastEntityProperties { get; set; }
107 146
108 public abstract OMV.Vector3 Scale { get; set; } 147 public virtual OMV.Vector3 Scale { get; set; }
109 public abstract bool IsSolid { get; } 148 public abstract bool IsSolid { get; }
110 public abstract bool IsStatic { get; } 149 public abstract bool IsStatic { get; }
150 public abstract bool IsSelected { get; }
151
152 // It can be confusing for an actor to know if it should move or update an object
153 // depeneding on the setting of 'selected', 'physical, ...
154 // This flag is the true test -- if true, the object is being acted on in the physical world
155 public abstract bool IsPhysicallyActive { get; }
156
157 // Materialness
158 public MaterialAttributes.Material Material { get; private set; }
159 public override void SetMaterial(int material)
160 {
161 Material = (MaterialAttributes.Material)material;
162 }
111 163
112 // Stop all physical motion. 164 // Stop all physical motion.
113 public abstract void ZeroMotion(bool inTaintTime); 165 public abstract void ZeroMotion(bool inTaintTime);
@@ -119,15 +171,41 @@ public abstract class BSPhysObject : PhysicsActor
119 // Update the physical location and motion of the object. Called with data from Bullet. 171 // Update the physical location and motion of the object. Called with data from Bullet.
120 public abstract void UpdateProperties(EntityProperties entprop); 172 public abstract void UpdateProperties(EntityProperties entprop);
121 173
122 // Tell the object to clean up.
123 public abstract void Destroy();
124
125 public abstract OMV.Vector3 RawPosition { get; set; } 174 public abstract OMV.Vector3 RawPosition { get; set; }
126 public abstract OMV.Vector3 ForcePosition { get; set; } 175 public abstract OMV.Vector3 ForcePosition { get; set; }
127 176
177 // Position is what the simulator thinks the positions of the prim is.
178 // Because Bullet needs the zero coordinate to be the center of mass of the linkset,
179 // sometimes it is necessary to displace the position the physics engine thinks
180 // the position is. PositionDisplacement must be added and removed from the
181 // position as the simulator position is stored and fetched from the physics
182 // engine.
183 public virtual OMV.Vector3 PositionDisplacement { get; set; }
184
128 public abstract OMV.Quaternion RawOrientation { get; set; } 185 public abstract OMV.Quaternion RawOrientation { get; set; }
129 public abstract OMV.Quaternion ForceOrientation { get; set; } 186 public abstract OMV.Quaternion ForceOrientation { get; set; }
130 187
188 // The system is telling us the velocity it wants to move at.
189 // Velocity in world coordinates.
190 // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor
191 public override OMV.Vector3 TargetVelocity
192 {
193 get { return m_targetVelocity; }
194 set
195 {
196 m_targetVelocity = value;
197 Velocity = value;
198 }
199 }
200 public virtual float TargetSpeed
201 {
202 get
203 {
204 OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
205 return characterOrientedVelocity.X;
206 }
207 }
208 public abstract OMV.Vector3 RawVelocity { get; set; }
131 public abstract OMV.Vector3 ForceVelocity { get; set; } 209 public abstract OMV.Vector3 ForceVelocity { get; set; }
132 210
133 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 211 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
@@ -136,6 +214,15 @@ public abstract class BSPhysObject : PhysicsActor
136 214
137 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 215 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
138 216
217 public virtual float ForwardSpeed
218 {
219 get
220 {
221 OMV.Vector3 characterOrientedVelocity = RawVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
222 return characterOrientedVelocity.X;
223 }
224 }
225
139 #region Collisions 226 #region Collisions
140 227
141 // Requested number of milliseconds between collision events. Zero means disabled. 228 // Requested number of milliseconds between collision events. Zero means disabled.
@@ -146,26 +233,65 @@ public abstract class BSPhysObject : PhysicsActor
146 protected long CollidingStep { get; set; } 233 protected long CollidingStep { get; set; }
147 // The simulation step that last had a collision with the ground 234 // The simulation step that last had a collision with the ground
148 protected long CollidingGroundStep { get; set; } 235 protected long CollidingGroundStep { get; set; }
236 // The simulation step that last collided with an object
237 protected long CollidingObjectStep { get; set; }
149 // The collision flags we think are set in Bullet 238 // The collision flags we think are set in Bullet
150 protected CollisionFlags CurrentCollisionFlags { get; set; } 239 protected CollisionFlags CurrentCollisionFlags { get; set; }
151 240
241 public override bool IsColliding {
242 get { return (CollidingStep == PhysicsScene.SimulationStep); }
243 set {
244 if (value)
245 CollidingStep = PhysicsScene.SimulationStep;
246 else
247 CollidingStep = 0;
248 }
249 }
250 public override bool CollidingGround {
251 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
252 set
253 {
254 if (value)
255 CollidingGroundStep = PhysicsScene.SimulationStep;
256 else
257 CollidingGroundStep = 0;
258 }
259 }
260 public override bool CollidingObj {
261 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); }
262 set {
263 if (value)
264 CollidingObjectStep = PhysicsScene.SimulationStep;
265 else
266 CollidingObjectStep = 0;
267 }
268 }
269
152 // The collisions that have been collected this tick 270 // The collisions that have been collected this tick
153 protected CollisionEventUpdate CollisionCollection; 271 protected CollisionEventUpdate CollisionCollection;
272 // Remember collisions from last tick for fancy collision based actions
273 // (like a BSCharacter walking up stairs).
274 protected CollisionEventUpdate CollisionsLastTick;
154 275
155 // The simulation step is telling this object about a collision. 276 // The simulation step is telling this object about a collision.
156 // Return 'true' if a collision was processed and should be sent up. 277 // Return 'true' if a collision was processed and should be sent up.
278 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
157 // Called at taint time from within the Step() function 279 // Called at taint time from within the Step() function
158 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 280 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
159 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 281 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
160 { 282 {
161 bool ret = false; 283 bool ret = false;
162 284
163 // The following lines make IsColliding() and IsCollidingGround() work 285 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
164 CollidingStep = PhysicsScene.SimulationStep; 286 CollidingStep = PhysicsScene.SimulationStep;
165 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 287 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
166 { 288 {
167 CollidingGroundStep = PhysicsScene.SimulationStep; 289 CollidingGroundStep = PhysicsScene.SimulationStep;
168 } 290 }
291 else
292 {
293 CollidingObjectStep = PhysicsScene.SimulationStep;
294 }
169 295
170 // prims in the same linkset cannot collide with each other 296 // prims in the same linkset cannot collide with each other
171 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) 297 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
@@ -191,8 +317,9 @@ public abstract class BSPhysObject : PhysicsActor
191 public virtual bool SendCollisions() 317 public virtual bool SendCollisions()
192 { 318 {
193 bool ret = true; 319 bool ret = true;
320
194 // If the 'no collision' call, force it to happen right now so quick collision_end 321 // If the 'no collision' call, force it to happen right now so quick collision_end
195 bool force = CollisionCollection.Count == 0; 322 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0);
196 323
197 // throttle the collisions to the number of milliseconds specified in the subscription 324 // throttle the collisions to the number of milliseconds specified in the subscription
198 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 325 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
@@ -207,11 +334,16 @@ public abstract class BSPhysObject : PhysicsActor
207 ret = false; 334 ret = false;
208 } 335 }
209 336
210 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); 337 DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
211 base.SendCollisionUpdate(CollisionCollection); 338 base.SendCollisionUpdate(CollisionCollection);
212 339
213 // The collisionCollection structure is passed around in the simulator. 340 // Remember the collisions from this tick for some collision specific processing.
341 CollisionsLastTick = CollisionCollection;
342
343 // The CollisionCollection instance is passed around in the simulator.
214 // Make sure we don't have a handle to that one and that a new one is used for next time. 344 // Make sure we don't have a handle to that one and that a new one is used for next time.
345 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
346 // a race condition is created for the other users of this instance.
215 CollisionCollection = new CollisionEventUpdate(); 347 CollisionCollection = new CollisionEventUpdate();
216 } 348 }
217 return ret; 349 return ret;
@@ -229,7 +361,8 @@ public abstract class BSPhysObject : PhysicsActor
229 361
230 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 362 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
231 { 363 {
232 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 364 if (PhysBody.HasPhysicalBody)
365 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
233 }); 366 });
234 } 367 }
235 else 368 else
@@ -243,7 +376,9 @@ public abstract class BSPhysObject : PhysicsActor
243 SubscribedEventsMs = 0; 376 SubscribedEventsMs = 0;
244 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 377 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
245 { 378 {
246 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 379 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
380 if (PhysBody.HasPhysicalBody)
381 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
247 }); 382 });
248 } 383 }
249 // Return 'true' if the simulator wants collision events 384 // Return 'true' if the simulator wants collision events
@@ -253,11 +388,66 @@ public abstract class BSPhysObject : PhysicsActor
253 388
254 #endregion // Collisions 389 #endregion // Collisions
255 390
391 #region Per Simulation Step actions
392 // There are some actions that must be performed for a physical object before each simulation step.
393 // These actions are optional so, rather than scanning all the physical objects and asking them
394 // if they have anything to do, a physical object registers for an event call before the step is performed.
395 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
396 private Dictionary<string, BSScene.PreStepAction> RegisteredActions = new Dictionary<string, BSScene.PreStepAction>();
397 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
398 {
399 string identifier = op + "-" + id.ToString();
400
401 lock (RegisteredActions)
402 {
403 // Clean out any existing action
404 UnRegisterPreStepAction(op, id);
405
406 RegisteredActions[identifier] = actn;
407 }
408 PhysicsScene.BeforeStep += actn;
409 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
410 }
411
412 // Unregister a pre step action. Safe to call if the action has not been registered.
413 protected void UnRegisterPreStepAction(string op, uint id)
414 {
415 string identifier = op + "-" + id.ToString();
416 bool removed = false;
417 lock (RegisteredActions)
418 {
419 if (RegisteredActions.ContainsKey(identifier))
420 {
421 PhysicsScene.BeforeStep -= RegisteredActions[identifier];
422 RegisteredActions.Remove(identifier);
423 removed = true;
424 }
425 }
426 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
427 }
428
429 protected void UnRegisterAllPreStepActions()
430 {
431 lock (RegisteredActions)
432 {
433 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
434 {
435 PhysicsScene.BeforeStep -= kvp.Value;
436 }
437 RegisteredActions.Clear();
438 }
439 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
440 }
441
442
443 #endregion // Per Simulation Step actions
444
256 // High performance detailed logging routine used by the physical objects. 445 // High performance detailed logging routine used by the physical objects.
257 protected void DetailLog(string msg, params Object[] args) 446 protected void DetailLog(string msg, params Object[] args)
258 { 447 {
259 if (PhysicsScene.PhysicsLogging.Enabled) 448 if (PhysicsScene.PhysicsLogging.Enabled)
260 PhysicsScene.DetailLog(msg, args); 449 PhysicsScene.DetailLog(msg, args);
261 } 450 }
451
262} 452}
263} 453}