aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs385
1 files changed, 189 insertions, 196 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 6bb88c7..0704591 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -38,12 +38,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
38 * Class to wrap all objects. 38 * Class to wrap all objects.
39 * The rest of BulletSim doesn't need to keep checking for avatars or prims 39 * The rest of BulletSim doesn't need to keep checking for avatars or prims
40 * unless the difference is significant. 40 * unless the difference is significant.
41 * 41 *
42 * Variables in the physicsl objects are in three forms: 42 * Variables in the physicsl objects are in three forms:
43 * VariableName: used by the simulator and performs taint operations, etc 43 * VariableName: used by the simulator and performs taint operations, etc
44 * RawVariableName: direct reference to the BulletSim storage for the variable value 44 * RawVariableName: direct reference to the BulletSim storage for the variable value
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 one should only be referenced in taint-time.
47 */ 47 */
48 48
49/* 49/*
@@ -52,7 +52,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce 52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse 53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v 54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque 55 * BS.ApplyCentralForce BS.ApplyTorque
56 */ 56 */
57 57
58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc. 58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc.
@@ -72,19 +72,25 @@ public abstract class BSPhysObject : PhysicsActor
72 } 72 }
73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) 73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
74 { 74 {
75 PhysicsScene = parentScene; 75 PhysScene = parentScene;
76 LocalID = localID; 76 LocalID = localID;
77 PhysObjectName = name; 77 PhysObjectName = name;
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate. 78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
79 TypeName = typeName; 79 TypeName = typeName;
80 80
81 // The collection of things that push me around
82 PhysicalActors = new BSActorCollection(PhysScene);
83
81 // Initialize variables kept in base. 84 // Initialize variables kept in base.
82 GravModifier = 1.0f; 85 GravModifier = 1.0f;
83 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); 86 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
87 HoverActive = false;
84 88
85 // We don't have any physical representation yet. 89 // We don't have any physical representation yet.
86 PhysBody = new BulletBody(localID); 90 PhysBody = new BulletBody(localID);
87 PhysShape = new BulletShape(); 91 PhysShape = new BSShapeNull();
92
93 UserSetCenterOfMassDisplacement = null;
88 94
89 PrimAssetState = PrimAssetCondition.Unknown; 95 PrimAssetState = PrimAssetCondition.Unknown;
90 96
@@ -92,26 +98,34 @@ public abstract class BSPhysObject : PhysicsActor
92 SetMaterial((int)MaterialAttributes.Material.Wood); 98 SetMaterial((int)MaterialAttributes.Material.Wood);
93 99
94 CollisionCollection = new CollisionEventUpdate(); 100 CollisionCollection = new CollisionEventUpdate();
95 CollisionsLastTick = CollisionCollection; 101 CollisionsLastReported = CollisionCollection;
102 CollisionsLastTick = new CollisionEventUpdate();
103 CollisionsLastTickStep = -1;
104
96 SubscribedEventsMs = 0; 105 SubscribedEventsMs = 0;
97 CollidingStep = 0; 106 // Crazy values that will never be true
98 CollidingGroundStep = 0; 107 CollidingStep = BSScene.NotASimulationStep;
99 CollisionAccumulation = 0; 108 CollidingGroundStep = BSScene.NotASimulationStep;
109 CollisionAccumulation = BSScene.NotASimulationStep;
100 ColliderIsMoving = false; 110 ColliderIsMoving = false;
101 CollisionScore = 0; 111 CollisionScore = 0;
102 112
103 // All axis free. 113 // All axis free.
104 LockedAxis = LockedAxisFree; 114 LockedLinearAxis = LockedAxisFree;
115 LockedAngularAxis = LockedAxisFree;
105 } 116 }
106 117
107 // Tell the object to clean up. 118 // Tell the object to clean up.
108 public virtual void Destroy() 119 public virtual void Destroy()
109 { 120 {
110 UnRegisterAllPreStepActions(); 121 PhysicalActors.Enable(false);
111 UnRegisterAllPostStepActions(); 122 PhysScene.TaintedObject("BSPhysObject.Destroy", delegate()
123 {
124 PhysicalActors.Dispose();
125 });
112 } 126 }
113 127
114 public BSScene PhysicsScene { get; protected set; } 128 public BSScene PhysScene { get; protected set; }
115 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 129 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
116 public string PhysObjectName { get; protected set; } 130 public string PhysObjectName { get; protected set; }
117 public string TypeName { get; protected set; } 131 public string TypeName { get; protected set; }
@@ -131,26 +145,19 @@ public abstract class BSPhysObject : PhysicsActor
131 // Reference to the physical body (btCollisionObject) of this object 145 // Reference to the physical body (btCollisionObject) of this object
132 public BulletBody PhysBody; 146 public BulletBody PhysBody;
133 // Reference to the physical shape (btCollisionShape) of this object 147 // Reference to the physical shape (btCollisionShape) of this object
134 public BulletShape PhysShape; 148 public BSShape PhysShape;
135 149
136 // The physical representation of the prim might require an asset fetch. 150 // The physical representation of the prim might require an asset fetch.
137 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'. 151 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
138 public enum PrimAssetCondition 152 public enum PrimAssetCondition
139 { 153 {
140 Unknown, Waiting, Failed, Fetched 154 Unknown, Waiting, FailedAssetFetch, FailedMeshing, Fetched
141 } 155 }
142 public PrimAssetCondition PrimAssetState { get; set; } 156 public PrimAssetCondition PrimAssetState { get; set; }
143 157
144 // The objects base shape information. Null if not a prim type shape. 158 // The objects base shape information. Null if not a prim type shape.
145 public PrimitiveBaseShape BaseShape { get; protected set; } 159 public PrimitiveBaseShape BaseShape { get; protected set; }
146 160
147 // Some types of objects have preferred physical representations.
148 // Returns SHAPE_UNKNOWN if there is no preference.
149 public virtual BSPhysicsShapeType PreferredPhysicalShape
150 {
151 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
152 }
153
154 // When the physical properties are updated, an EntityProperty holds the update values. 161 // When the physical properties are updated, an EntityProperty holds the update values.
155 // Keep the current and last EntityProperties to enable computation of differences 162 // Keep the current and last EntityProperties to enable computation of differences
156 // between the current update and the previous values. 163 // between the current update and the previous values.
@@ -176,11 +183,25 @@ public abstract class BSPhysObject : PhysicsActor
176 Material = (MaterialAttributes.Material)material; 183 Material = (MaterialAttributes.Material)material;
177 184
178 // Setting the material sets the material attributes also. 185 // Setting the material sets the material attributes also.
186 // TODO: decide if this is necessary -- the simulator does this.
179 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); 187 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
180 Friction = matAttrib.friction; 188 Friction = matAttrib.friction;
181 Restitution = matAttrib.restitution; 189 Restitution = matAttrib.restitution;
182 Density = matAttrib.density / BSParam.DensityScaleFactor; 190 Density = matAttrib.density;
183 DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density); 191 // DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
192 }
193
194 public override float Density
195 {
196 get
197 {
198 return base.Density;
199 }
200 set
201 {
202 DetailLog("{0},BSPhysObject.Density,set,den={1}", LocalID, value);
203 base.Density = value;
204 }
184 } 205 }
185 206
186 // Stop all physical motion. 207 // Stop all physical motion.
@@ -190,21 +211,55 @@ public abstract class BSPhysObject : PhysicsActor
190 // Update the physical location and motion of the object. Called with data from Bullet. 211 // Update the physical location and motion of the object. Called with data from Bullet.
191 public abstract void UpdateProperties(EntityProperties entprop); 212 public abstract void UpdateProperties(EntityProperties entprop);
192 213
193 public abstract OMV.Vector3 RawPosition { get; set; } 214 public virtual OMV.Vector3 RawPosition { get; set; }
194 public abstract OMV.Vector3 ForcePosition { get; set; } 215 public abstract OMV.Vector3 ForcePosition { get; set; }
195 216
196 public abstract OMV.Quaternion RawOrientation { get; set; } 217 public virtual OMV.Quaternion RawOrientation { get; set; }
197 public abstract OMV.Quaternion ForceOrientation { get; set; } 218 public abstract OMV.Quaternion ForceOrientation { get; set; }
198 219
199 public abstract OMV.Vector3 RawVelocity { get; set; } 220 public OMV.Vector3 RawVelocity { get; set; }
200 public abstract OMV.Vector3 ForceVelocity { get; set; } 221 public abstract OMV.Vector3 ForceVelocity { get; set; }
201 222
223 public OMV.Vector3 RawForce { get; set; }
224 public OMV.Vector3 RawTorque { get; set; }
225 public override void AddAngularForce(OMV.Vector3 force, bool pushforce)
226 {
227 AddAngularForce(force, pushforce, false);
228 }
229 public abstract void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
230 public abstract void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
231
202 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 232 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
203 233
204 public abstract float ForceBuoyancy { get; set; } 234 public abstract float ForceBuoyancy { get; set; }
205 235
206 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 236 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
207 237
238 public override bool PIDActive { set { MoveToTargetActive = value; } }
239 public override OMV.Vector3 PIDTarget { set { MoveToTargetTarget = value; } }
240 public override float PIDTau { set { MoveToTargetTau = value; } }
241
242 public bool MoveToTargetActive { get; set; }
243 public OMV.Vector3 MoveToTargetTarget { get; set; }
244 public float MoveToTargetTau { get; set; }
245
246 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
247 public override bool PIDHoverActive { set { HoverActive = value; } }
248 public override float PIDHoverHeight { set { HoverHeight = value; } }
249 public override PIDHoverType PIDHoverType { set { HoverType = value; } }
250 public override float PIDHoverTau { set { HoverTau = value; } }
251
252 public bool HoverActive { get; set; }
253 public float HoverHeight { get; set; }
254 public PIDHoverType HoverType { get; set; }
255 public float HoverTau { get; set; }
256
257 // For RotLookAt
258 public override OMV.Quaternion APIDTarget { set { return; } }
259 public override bool APIDActive { set { return; } }
260 public override float APIDStrength { set { return; } }
261 public override float APIDDamping { set { return; } }
262
208 // The current velocity forward 263 // The current velocity forward
209 public virtual float ForwardSpeed 264 public virtual float ForwardSpeed
210 { 265 {
@@ -226,10 +281,58 @@ public abstract class BSPhysObject : PhysicsActor
226 281
227 // The user can optionally set the center of mass. The user's setting will override any 282 // The user can optionally set the center of mass. The user's setting will override any
228 // computed center-of-mass (like in linksets). 283 // computed center-of-mass (like in linksets).
229 public OMV.Vector3? UserSetCenterOfMass { get; set; } 284 // Note this is a displacement from the root's coordinates. Zero means use the root prim as center-of-mass.
285 public OMV.Vector3? UserSetCenterOfMassDisplacement { get; set; }
286
287 public OMV.Vector3 LockedLinearAxis { get; set; } // zero means locked. one means free.
288 public OMV.Vector3 LockedAngularAxis { get; set; } // zero means locked. one means free.
289 public const float FreeAxis = 1f;
290 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(FreeAxis, FreeAxis, FreeAxis); // All axis are free
291
292 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
293 // they need waking up when parameters are changed.
294 // Called in taint-time!!
295 public void ActivateIfPhysical(bool forceIt)
296 {
297 if (IsPhysical && PhysBody.HasPhysicalBody)
298 PhysScene.PE.Activate(PhysBody, forceIt);
299 }
230 300
231 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 301 // 'actors' act on the physical object to change or constrain its motion. These can range from
232 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free 302 // hovering to complex vehicle motion.
303 // May be called at non-taint time as this just adds the actor to the action list and the real
304 // work is done during the simulation step.
305 // Note that, if the actor is already in the list and we are disabling same, the actor is just left
306 // in the list disabled.
307 public delegate BSActor CreateActor();
308 public void EnableActor(bool enableActor, string actorName, CreateActor creator)
309 {
310 lock (PhysicalActors)
311 {
312 BSActor theActor;
313 if (PhysicalActors.TryGetActor(actorName, out theActor))
314 {
315 // The actor already exists so just turn it on or off
316 DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
317 theActor.Enabled = enableActor;
318 }
319 else
320 {
321 // The actor does not exist. If it should, create it.
322 if (enableActor)
323 {
324 DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
325 theActor = creator();
326 PhysicalActors.Add(actorName, theActor);
327 theActor.Enabled = true;
328 }
329 else
330 {
331 DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
332 }
333 }
334 }
335 }
233 336
234 #region Collisions 337 #region Collisions
235 338
@@ -247,64 +350,80 @@ public abstract class BSPhysObject : PhysicsActor
247 protected CollisionFlags CurrentCollisionFlags { get; set; } 350 protected CollisionFlags CurrentCollisionFlags { get; set; }
248 // On a collision, check the collider and remember if the last collider was moving 351 // On a collision, check the collider and remember if the last collider was moving
249 // Used to modify the standing of avatars (avatars on stationary things stand still) 352 // Used to modify the standing of avatars (avatars on stationary things stand still)
250 protected bool ColliderIsMoving; 353 public bool ColliderIsMoving;
354 // Used by BSCharacter to manage standing (and not slipping)
355 public bool IsStationary;
251 356
252 // Count of collisions for this object 357 // Count of collisions for this object
253 protected long CollisionAccumulation { get; set; } 358 protected long CollisionAccumulation { get; set; }
254 359
255 public override bool IsColliding { 360 public override bool IsColliding {
256 get { return (CollidingStep == PhysicsScene.SimulationStep); } 361 get { return (CollidingStep == PhysScene.SimulationStep); }
257 set { 362 set {
258 if (value) 363 if (value)
259 CollidingStep = PhysicsScene.SimulationStep; 364 CollidingStep = PhysScene.SimulationStep;
260 else 365 else
261 CollidingStep = 0; 366 CollidingStep = BSScene.NotASimulationStep;
262 } 367 }
263 } 368 }
369 // Complex objects (like linksets) need to know if there is a collision on any part of
370 // their shape. 'IsColliding' has an existing definition of reporting a collision on
371 // only this specific prim or component of linksets.
372 // 'HasSomeCollision' is defined as reporting if there is a collision on any part of
373 // the complex body that this prim is the root of.
374 public virtual bool HasSomeCollision
375 {
376 get { return IsColliding; }
377 set { IsColliding = value; }
378 }
264 public override bool CollidingGround { 379 public override bool CollidingGround {
265 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 380 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
266 set 381 set
267 { 382 {
268 if (value) 383 if (value)
269 CollidingGroundStep = PhysicsScene.SimulationStep; 384 CollidingGroundStep = PhysScene.SimulationStep;
270 else 385 else
271 CollidingGroundStep = 0; 386 CollidingGroundStep = BSScene.NotASimulationStep;
272 } 387 }
273 } 388 }
274 public override bool CollidingObj { 389 public override bool CollidingObj {
275 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 390 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
276 set { 391 set {
277 if (value) 392 if (value)
278 CollidingObjectStep = PhysicsScene.SimulationStep; 393 CollidingObjectStep = PhysScene.SimulationStep;
279 else 394 else
280 CollidingObjectStep = 0; 395 CollidingObjectStep = BSScene.NotASimulationStep;
281 } 396 }
282 } 397 }
283 398
284 // The collisions that have been collected this tick 399 // The collisions that have been collected for the next collision reporting (throttled by subscription)
285 protected CollisionEventUpdate CollisionCollection; 400 protected CollisionEventUpdate CollisionCollection;
286 // Remember collisions from last tick for fancy collision based actions 401 // This is the collision collection last reported to the Simulator.
402 public CollisionEventUpdate CollisionsLastReported;
403 // Remember the collisions recorded in the last tick for fancy collision checking
287 // (like a BSCharacter walking up stairs). 404 // (like a BSCharacter walking up stairs).
288 protected CollisionEventUpdate CollisionsLastTick; 405 public CollisionEventUpdate CollisionsLastTick;
406 private long CollisionsLastTickStep = -1;
289 407
290 // The simulation step is telling this object about a collision. 408 // The simulation step is telling this object about a collision.
291 // Return 'true' if a collision was processed and should be sent up. 409 // Return 'true' if a collision was processed and should be sent up.
292 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision. 410 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
293 // Called at taint time from within the Step() function 411 // Called at taint time from within the Step() function
412 public delegate bool CollideCall(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
294 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 413 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
295 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 414 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
296 { 415 {
297 bool ret = false; 416 bool ret = false;
298 417
299 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 418 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
300 CollidingStep = PhysicsScene.SimulationStep; 419 CollidingStep = PhysScene.SimulationStep;
301 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 420 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
302 { 421 {
303 CollidingGroundStep = PhysicsScene.SimulationStep; 422 CollidingGroundStep = PhysScene.SimulationStep;
304 } 423 }
305 else 424 else
306 { 425 {
307 CollidingObjectStep = PhysicsScene.SimulationStep; 426 CollidingObjectStep = PhysScene.SimulationStep;
308 } 427 }
309 428
310 CollisionAccumulation++; 429 CollisionAccumulation++;
@@ -312,6 +431,15 @@ public abstract class BSPhysObject : PhysicsActor
312 // For movement tests, remember if we are colliding with an object that is moving. 431 // For movement tests, remember if we are colliding with an object that is moving.
313 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false; 432 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
314 433
434 // Make a collection of the collisions that happened the last simulation tick.
435 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
436 if (CollisionsLastTickStep != PhysScene.SimulationStep)
437 {
438 CollisionsLastTick = new CollisionEventUpdate();
439 CollisionsLastTickStep = PhysScene.SimulationStep;
440 }
441 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
442
315 // If someone has subscribed for collision events log the collision so it will be reported up 443 // If someone has subscribed for collision events log the collision so it will be reported up
316 if (SubscribedEvents()) { 444 if (SubscribedEvents()) {
317 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 445 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
@@ -332,12 +460,12 @@ public abstract class BSPhysObject : PhysicsActor
332 bool ret = true; 460 bool ret = true;
333 461
334 // If the 'no collision' call, force it to happen right now so quick collision_end 462 // If the 'no collision' call, force it to happen right now so quick collision_end
335 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0); 463 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
336 464
337 // throttle the collisions to the number of milliseconds specified in the subscription 465 // throttle the collisions to the number of milliseconds specified in the subscription
338 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 466 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
339 { 467 {
340 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 468 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
341 469
342 // We are called if we previously had collisions. If there are no collisions 470 // We are called if we previously had collisions. If there are no collisions
343 // this time, send up one last empty event so OpenSim can sense collision end. 471 // this time, send up one last empty event so OpenSim can sense collision end.
@@ -351,11 +479,11 @@ public abstract class BSPhysObject : PhysicsActor
351 base.SendCollisionUpdate(CollisionCollection); 479 base.SendCollisionUpdate(CollisionCollection);
352 480
353 // Remember the collisions from this tick for some collision specific processing. 481 // Remember the collisions from this tick for some collision specific processing.
354 CollisionsLastTick = CollisionCollection; 482 CollisionsLastReported = CollisionCollection;
355 483
356 // The CollisionCollection instance is passed around in the simulator. 484 // The CollisionCollection instance is passed around in the simulator.
357 // Make sure we don't have a handle to that one and that a new one is used for next time. 485 // Make sure we don't have a handle to that one and that a new one is used for next time.
358 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, 486 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
359 // a race condition is created for the other users of this instance. 487 // a race condition is created for the other users of this instance.
360 CollisionCollection = new CollisionEventUpdate(); 488 CollisionCollection = new CollisionEventUpdate();
361 } 489 }
@@ -372,10 +500,10 @@ public abstract class BSPhysObject : PhysicsActor
372 // make sure first collision happens 500 // make sure first collision happens
373 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 501 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
374 502
375 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 503 PhysScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
376 { 504 {
377 if (PhysBody.HasPhysicalBody) 505 if (PhysBody.HasPhysicalBody)
378 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 506 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
379 }); 507 });
380 } 508 }
381 else 509 else
@@ -387,11 +515,11 @@ public abstract class BSPhysObject : PhysicsActor
387 public override void UnSubscribeEvents() { 515 public override void UnSubscribeEvents() {
388 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 516 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
389 SubscribedEventsMs = 0; 517 SubscribedEventsMs = 0;
390 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 518 PhysScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
391 { 519 {
392 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 520 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
393 if (PhysBody.HasPhysicalBody) 521 if (PhysBody.HasPhysicalBody)
394 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 522 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
395 }); 523 });
396 } 524 }
397 // Return 'true' if the simulator wants collision events 525 // Return 'true' if the simulator wants collision events
@@ -405,7 +533,7 @@ public abstract class BSPhysObject : PhysicsActor
405 { 533 {
406 // Scale the collision count by the time since the last collision. 534 // Scale the collision count by the time since the last collision.
407 // The "+1" prevents dividing by zero. 535 // The "+1" prevents dividing by zero.
408 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1; 536 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
409 CollisionScore = CollisionAccumulation / timeAgo; 537 CollisionScore = CollisionAccumulation / timeAgo;
410 } 538 }
411 public override float CollisionScore { get; set; } 539 public override float CollisionScore { get; set; }
@@ -413,103 +541,8 @@ public abstract class BSPhysObject : PhysicsActor
413 #endregion // Collisions 541 #endregion // Collisions
414 542
415 #region Per Simulation Step actions 543 #region Per Simulation Step actions
416 // There are some actions that must be performed for a physical object before each simulation step.
417 // These actions are optional so, rather than scanning all the physical objects and asking them
418 // if they have anything to do, a physical object registers for an event call before the step is performed.
419 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
420 private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>();
421 private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>();
422 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
423 {
424 string identifier = op + "-" + id.ToString();
425 544
426 lock (RegisteredPrestepActions) 545 public BSActorCollection PhysicalActors;
427 {
428 // Clean out any existing action
429 UnRegisterPreStepAction(op, id);
430 RegisteredPrestepActions[identifier] = actn;
431 PhysicsScene.BeforeStep += actn;
432 }
433 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
434 }
435
436 // Unregister a pre step action. Safe to call if the action has not been registered.
437 // Returns 'true' if an action was actually removed
438 protected bool UnRegisterPreStepAction(string op, uint id)
439 {
440 string identifier = op + "-" + id.ToString();
441 bool removed = false;
442 lock (RegisteredPrestepActions)
443 {
444 if (RegisteredPrestepActions.ContainsKey(identifier))
445 {
446 PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier];
447 RegisteredPrestepActions.Remove(identifier);
448 removed = true;
449 }
450 }
451 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
452 return removed;
453 }
454
455 protected void UnRegisterAllPreStepActions()
456 {
457 lock (RegisteredPrestepActions)
458 {
459 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions)
460 {
461 PhysicsScene.BeforeStep -= kvp.Value;
462 }
463 RegisteredPrestepActions.Clear();
464 }
465 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
466 }
467
468 protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn)
469 {
470 string identifier = op + "-" + id.ToString();
471
472 lock (RegisteredPoststepActions)
473 {
474 // Clean out any existing action
475 UnRegisterPostStepAction(op, id);
476 RegisteredPoststepActions[identifier] = actn;
477 PhysicsScene.AfterStep += actn;
478 }
479 DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
480 }
481
482 // Unregister a pre step action. Safe to call if the action has not been registered.
483 // Returns 'true' if an action was actually removed.
484 protected bool UnRegisterPostStepAction(string op, uint id)
485 {
486 string identifier = op + "-" + id.ToString();
487 bool removed = false;
488 lock (RegisteredPoststepActions)
489 {
490 if (RegisteredPoststepActions.ContainsKey(identifier))
491 {
492 PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier];
493 RegisteredPoststepActions.Remove(identifier);
494 removed = true;
495 }
496 }
497 DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed);
498 return removed;
499 }
500
501 protected void UnRegisterAllPostStepActions()
502 {
503 lock (RegisteredPoststepActions)
504 {
505 foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions)
506 {
507 PhysicsScene.AfterStep -= kvp.Value;
508 }
509 RegisteredPoststepActions.Clear();
510 }
511 DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
512 }
513 546
514 // When an update to the physical properties happens, this event is fired to let 547 // When an update to the physical properties happens, this event is fired to let
515 // different actors to modify the update before it is passed around 548 // different actors to modify the update before it is passed around
@@ -522,53 +555,13 @@ public abstract class BSPhysObject : PhysicsActor
522 actions(ref entprop); 555 actions(ref entprop);
523 } 556 }
524 557
525 private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>();
526 public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn)
527 {
528 lock (RegisteredPreUpdatePropertyActions)
529 {
530 // Clean out any existing action
531 UnRegisterPreUpdatePropertyAction(identifier);
532 RegisteredPreUpdatePropertyActions[identifier] = actn;
533 OnPreUpdateProperty += actn;
534 }
535 DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier);
536 }
537 public bool UnRegisterPreUpdatePropertyAction(string identifier)
538 {
539 bool removed = false;
540 lock (RegisteredPreUpdatePropertyActions)
541 {
542 if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier))
543 {
544 OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier];
545 RegisteredPreUpdatePropertyActions.Remove(identifier);
546 removed = true;
547 }
548 }
549 DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed);
550 return removed;
551 }
552 public void UnRegisterAllPreUpdatePropertyActions()
553 {
554 lock (RegisteredPreUpdatePropertyActions)
555 {
556 foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions)
557 {
558 OnPreUpdateProperty -= kvp.Value;
559 }
560 RegisteredPreUpdatePropertyActions.Clear();
561 }
562 DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID);
563 }
564
565 #endregion // Per Simulation Step actions 558 #endregion // Per Simulation Step actions
566 559
567 // High performance detailed logging routine used by the physical objects. 560 // High performance detailed logging routine used by the physical objects.
568 protected void DetailLog(string msg, params Object[] args) 561 protected void DetailLog(string msg, params Object[] args)
569 { 562 {
570 if (PhysicsScene.PhysicsLogging.Enabled) 563 if (PhysScene.PhysicsLogging.Enabled)
571 PhysicsScene.DetailLog(msg, args); 564 PhysScene.DetailLog(msg, args);
572 } 565 }
573 566
574} 567}