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.cs405
1 files changed, 209 insertions, 196 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 6bb88c7..f89b376 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,27 @@ 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 IsInitialized = false;
76
77 PhysScene = parentScene;
76 LocalID = localID; 78 LocalID = localID;
77 PhysObjectName = name; 79 PhysObjectName = name;
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate. 80 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
79 TypeName = typeName; 81 TypeName = typeName;
80 82
83 // The collection of things that push me around
84 PhysicalActors = new BSActorCollection(PhysScene);
85
81 // Initialize variables kept in base. 86 // Initialize variables kept in base.
82 GravModifier = 1.0f; 87 GravModifier = 1.0f;
83 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); 88 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
89 HoverActive = false;
84 90
85 // We don't have any physical representation yet. 91 // We don't have any physical representation yet.
86 PhysBody = new BulletBody(localID); 92 PhysBody = new BulletBody(localID);
87 PhysShape = new BulletShape(); 93 PhysShape = new BSShapeNull();
94
95 UserSetCenterOfMassDisplacement = null;
88 96
89 PrimAssetState = PrimAssetCondition.Unknown; 97 PrimAssetState = PrimAssetCondition.Unknown;
90 98
@@ -92,30 +100,41 @@ public abstract class BSPhysObject : PhysicsActor
92 SetMaterial((int)MaterialAttributes.Material.Wood); 100 SetMaterial((int)MaterialAttributes.Material.Wood);
93 101
94 CollisionCollection = new CollisionEventUpdate(); 102 CollisionCollection = new CollisionEventUpdate();
95 CollisionsLastTick = CollisionCollection; 103 CollisionsLastReported = CollisionCollection;
104 CollisionsLastTick = new CollisionEventUpdate();
105 CollisionsLastTickStep = -1;
106
96 SubscribedEventsMs = 0; 107 SubscribedEventsMs = 0;
97 CollidingStep = 0; 108 // Crazy values that will never be true
98 CollidingGroundStep = 0; 109 CollidingStep = BSScene.NotASimulationStep;
99 CollisionAccumulation = 0; 110 CollidingGroundStep = BSScene.NotASimulationStep;
111 CollisionAccumulation = BSScene.NotASimulationStep;
100 ColliderIsMoving = false; 112 ColliderIsMoving = false;
101 CollisionScore = 0; 113 CollisionScore = 0;
102 114
103 // All axis free. 115 // All axis free.
104 LockedAxis = LockedAxisFree; 116 LockedLinearAxis = LockedAxisFree;
117 LockedAngularAxis = LockedAxisFree;
105 } 118 }
106 119
107 // Tell the object to clean up. 120 // Tell the object to clean up.
108 public virtual void Destroy() 121 public virtual void Destroy()
109 { 122 {
110 UnRegisterAllPreStepActions(); 123 PhysicalActors.Enable(false);
111 UnRegisterAllPostStepActions(); 124 PhysScene.TaintedObject(LocalID, "BSPhysObject.Destroy", delegate()
125 {
126 PhysicalActors.Dispose();
127 });
112 } 128 }
113 129
114 public BSScene PhysicsScene { get; protected set; } 130 public BSScene PhysScene { get; protected set; }
115 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 131 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
116 public string PhysObjectName { get; protected set; } 132 public string PhysObjectName { get; protected set; }
117 public string TypeName { get; protected set; } 133 public string TypeName { get; protected set; }
118 134
135 // Set to 'true' when the object is completely initialized.
136 // This mostly prevents property updates and collisions until the object is completely here.
137 public bool IsInitialized { get; protected set; }
119 138
120 // Return the object mass without calculating it or having side effects 139 // Return the object mass without calculating it or having side effects
121 public abstract float RawMass { get; } 140 public abstract float RawMass { get; }
@@ -131,26 +150,19 @@ public abstract class BSPhysObject : PhysicsActor
131 // Reference to the physical body (btCollisionObject) of this object 150 // Reference to the physical body (btCollisionObject) of this object
132 public BulletBody PhysBody; 151 public BulletBody PhysBody;
133 // Reference to the physical shape (btCollisionShape) of this object 152 // Reference to the physical shape (btCollisionShape) of this object
134 public BulletShape PhysShape; 153 public BSShape PhysShape;
135 154
136 // The physical representation of the prim might require an asset fetch. 155 // 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'. 156 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
138 public enum PrimAssetCondition 157 public enum PrimAssetCondition
139 { 158 {
140 Unknown, Waiting, Failed, Fetched 159 Unknown, Waiting, FailedAssetFetch, FailedMeshing, Fetched
141 } 160 }
142 public PrimAssetCondition PrimAssetState { get; set; } 161 public PrimAssetCondition PrimAssetState { get; set; }
143 162
144 // The objects base shape information. Null if not a prim type shape. 163 // The objects base shape information. Null if not a prim type shape.
145 public PrimitiveBaseShape BaseShape { get; protected set; } 164 public PrimitiveBaseShape BaseShape { get; protected set; }
146 165
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. 166 // When the physical properties are updated, an EntityProperty holds the update values.
155 // Keep the current and last EntityProperties to enable computation of differences 167 // Keep the current and last EntityProperties to enable computation of differences
156 // between the current update and the previous values. 168 // between the current update and the previous values.
@@ -168,6 +180,7 @@ public abstract class BSPhysObject : PhysicsActor
168 public abstract bool IsSolid { get; } 180 public abstract bool IsSolid { get; }
169 public abstract bool IsStatic { get; } 181 public abstract bool IsStatic { get; }
170 public abstract bool IsSelected { get; } 182 public abstract bool IsSelected { get; }
183 public abstract bool IsVolumeDetect { get; }
171 184
172 // Materialness 185 // Materialness
173 public MaterialAttributes.Material Material { get; private set; } 186 public MaterialAttributes.Material Material { get; private set; }
@@ -176,11 +189,25 @@ public abstract class BSPhysObject : PhysicsActor
176 Material = (MaterialAttributes.Material)material; 189 Material = (MaterialAttributes.Material)material;
177 190
178 // Setting the material sets the material attributes also. 191 // Setting the material sets the material attributes also.
192 // TODO: decide if this is necessary -- the simulator does this.
179 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); 193 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
180 Friction = matAttrib.friction; 194 Friction = matAttrib.friction;
181 Restitution = matAttrib.restitution; 195 Restitution = matAttrib.restitution;
182 Density = matAttrib.density / BSParam.DensityScaleFactor; 196 Density = matAttrib.density;
183 DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density); 197 // DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
198 }
199
200 public override float Density
201 {
202 get
203 {
204 return base.Density;
205 }
206 set
207 {
208 DetailLog("{0},BSPhysObject.Density,set,den={1}", LocalID, value);
209 base.Density = value;
210 }
184 } 211 }
185 212
186 // Stop all physical motion. 213 // Stop all physical motion.
@@ -190,21 +217,55 @@ public abstract class BSPhysObject : PhysicsActor
190 // Update the physical location and motion of the object. Called with data from Bullet. 217 // Update the physical location and motion of the object. Called with data from Bullet.
191 public abstract void UpdateProperties(EntityProperties entprop); 218 public abstract void UpdateProperties(EntityProperties entprop);
192 219
193 public abstract OMV.Vector3 RawPosition { get; set; } 220 public virtual OMV.Vector3 RawPosition { get; set; }
194 public abstract OMV.Vector3 ForcePosition { get; set; } 221 public abstract OMV.Vector3 ForcePosition { get; set; }
195 222
196 public abstract OMV.Quaternion RawOrientation { get; set; } 223 public virtual OMV.Quaternion RawOrientation { get; set; }
197 public abstract OMV.Quaternion ForceOrientation { get; set; } 224 public abstract OMV.Quaternion ForceOrientation { get; set; }
198 225
199 public abstract OMV.Vector3 RawVelocity { get; set; } 226 public OMV.Vector3 RawVelocity { get; set; }
200 public abstract OMV.Vector3 ForceVelocity { get; set; } 227 public abstract OMV.Vector3 ForceVelocity { get; set; }
201 228
229 public OMV.Vector3 RawForce { get; set; }
230 public OMV.Vector3 RawTorque { get; set; }
231 public override void AddAngularForce(OMV.Vector3 force, bool pushforce)
232 {
233 AddAngularForce(force, pushforce, false);
234 }
235 public abstract void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
236 public abstract void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
237
202 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 238 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
203 239
204 public abstract float ForceBuoyancy { get; set; } 240 public abstract float ForceBuoyancy { get; set; }
205 241
206 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 242 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
207 243
244 public override bool PIDActive { set { MoveToTargetActive = value; } }
245 public override OMV.Vector3 PIDTarget { set { MoveToTargetTarget = value; } }
246 public override float PIDTau { set { MoveToTargetTau = value; } }
247
248 public bool MoveToTargetActive { get; set; }
249 public OMV.Vector3 MoveToTargetTarget { get; set; }
250 public float MoveToTargetTau { get; set; }
251
252 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
253 public override bool PIDHoverActive { set { HoverActive = value; } }
254 public override float PIDHoverHeight { set { HoverHeight = value; } }
255 public override PIDHoverType PIDHoverType { set { HoverType = value; } }
256 public override float PIDHoverTau { set { HoverTau = value; } }
257
258 public bool HoverActive { get; set; }
259 public float HoverHeight { get; set; }
260 public PIDHoverType HoverType { get; set; }
261 public float HoverTau { get; set; }
262
263 // For RotLookAt
264 public override OMV.Quaternion APIDTarget { set { return; } }
265 public override bool APIDActive { set { return; } }
266 public override float APIDStrength { set { return; } }
267 public override float APIDDamping { set { return; } }
268
208 // The current velocity forward 269 // The current velocity forward
209 public virtual float ForwardSpeed 270 public virtual float ForwardSpeed
210 { 271 {
@@ -226,10 +287,69 @@ public abstract class BSPhysObject : PhysicsActor
226 287
227 // The user can optionally set the center of mass. The user's setting will override any 288 // The user can optionally set the center of mass. The user's setting will override any
228 // computed center-of-mass (like in linksets). 289 // computed center-of-mass (like in linksets).
229 public OMV.Vector3? UserSetCenterOfMass { get; set; } 290 // Note this is a displacement from the root's coordinates. Zero means use the root prim as center-of-mass.
291 public OMV.Vector3? UserSetCenterOfMassDisplacement { get; set; }
292
293 public OMV.Vector3 LockedLinearAxis { get; set; } // zero means locked. one means free.
294 public OMV.Vector3 LockedAngularAxis { get; set; } // zero means locked. one means free.
295 public const float FreeAxis = 1f;
296 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(FreeAxis, FreeAxis, FreeAxis); // All axis are free
297
298 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
299 // they need waking up when parameters are changed.
300 // Called in taint-time!!
301 public void ActivateIfPhysical(bool forceIt)
302 {
303 if (PhysBody.HasPhysicalBody)
304 {
305 if (IsPhysical)
306 {
307 // Physical objects might need activating
308 PhysScene.PE.Activate(PhysBody, forceIt);
309 }
310 else
311 {
312 // Clear the collision cache since we've changed some properties.
313 PhysScene.PE.ClearCollisionProxyCache(PhysScene.World, PhysBody);
314 }
315 }
316 }
230 317
231 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 318 // '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 319 // hovering to complex vehicle motion.
320 // May be called at non-taint time as this just adds the actor to the action list and the real
321 // work is done during the simulation step.
322 // Note that, if the actor is already in the list and we are disabling same, the actor is just left
323 // in the list disabled.
324 public delegate BSActor CreateActor();
325 public void EnableActor(bool enableActor, string actorName, CreateActor creator)
326 {
327 lock (PhysicalActors)
328 {
329 BSActor theActor;
330 if (PhysicalActors.TryGetActor(actorName, out theActor))
331 {
332 // The actor already exists so just turn it on or off
333 DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
334 theActor.Enabled = enableActor;
335 }
336 else
337 {
338 // The actor does not exist. If it should, create it.
339 if (enableActor)
340 {
341 DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
342 theActor = creator();
343 PhysicalActors.Add(actorName, theActor);
344 theActor.Enabled = true;
345 }
346 else
347 {
348 DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
349 }
350 }
351 }
352 }
233 353
234 #region Collisions 354 #region Collisions
235 355
@@ -247,70 +367,98 @@ public abstract class BSPhysObject : PhysicsActor
247 protected CollisionFlags CurrentCollisionFlags { get; set; } 367 protected CollisionFlags CurrentCollisionFlags { get; set; }
248 // On a collision, check the collider and remember if the last collider was moving 368 // 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) 369 // Used to modify the standing of avatars (avatars on stationary things stand still)
250 protected bool ColliderIsMoving; 370 public bool ColliderIsMoving;
371 // 'true' if the last collider was a volume detect object
372 public bool ColliderIsVolumeDetect;
373 // Used by BSCharacter to manage standing (and not slipping)
374 public bool IsStationary;
251 375
252 // Count of collisions for this object 376 // Count of collisions for this object
253 protected long CollisionAccumulation { get; set; } 377 protected long CollisionAccumulation { get; set; }
254 378
255 public override bool IsColliding { 379 public override bool IsColliding {
256 get { return (CollidingStep == PhysicsScene.SimulationStep); } 380 get { return (CollidingStep == PhysScene.SimulationStep); }
257 set { 381 set {
258 if (value) 382 if (value)
259 CollidingStep = PhysicsScene.SimulationStep; 383 CollidingStep = PhysScene.SimulationStep;
260 else 384 else
261 CollidingStep = 0; 385 CollidingStep = BSScene.NotASimulationStep;
262 } 386 }
263 } 387 }
388 // Complex objects (like linksets) need to know if there is a collision on any part of
389 // their shape. 'IsColliding' has an existing definition of reporting a collision on
390 // only this specific prim or component of linksets.
391 // 'HasSomeCollision' is defined as reporting if there is a collision on any part of
392 // the complex body that this prim is the root of.
393 public virtual bool HasSomeCollision
394 {
395 get { return IsColliding; }
396 set { IsColliding = value; }
397 }
264 public override bool CollidingGround { 398 public override bool CollidingGround {
265 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 399 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
266 set 400 set
267 { 401 {
268 if (value) 402 if (value)
269 CollidingGroundStep = PhysicsScene.SimulationStep; 403 CollidingGroundStep = PhysScene.SimulationStep;
270 else 404 else
271 CollidingGroundStep = 0; 405 CollidingGroundStep = BSScene.NotASimulationStep;
272 } 406 }
273 } 407 }
274 public override bool CollidingObj { 408 public override bool CollidingObj {
275 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 409 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
276 set { 410 set {
277 if (value) 411 if (value)
278 CollidingObjectStep = PhysicsScene.SimulationStep; 412 CollidingObjectStep = PhysScene.SimulationStep;
279 else 413 else
280 CollidingObjectStep = 0; 414 CollidingObjectStep = BSScene.NotASimulationStep;
281 } 415 }
282 } 416 }
283 417
284 // The collisions that have been collected this tick 418 // The collisions that have been collected for the next collision reporting (throttled by subscription)
285 protected CollisionEventUpdate CollisionCollection; 419 protected CollisionEventUpdate CollisionCollection;
286 // Remember collisions from last tick for fancy collision based actions 420 // This is the collision collection last reported to the Simulator.
421 public CollisionEventUpdate CollisionsLastReported;
422 // Remember the collisions recorded in the last tick for fancy collision checking
287 // (like a BSCharacter walking up stairs). 423 // (like a BSCharacter walking up stairs).
288 protected CollisionEventUpdate CollisionsLastTick; 424 public CollisionEventUpdate CollisionsLastTick;
425 private long CollisionsLastTickStep = -1;
289 426
290 // The simulation step is telling this object about a collision. 427 // The simulation step is telling this object about a collision.
291 // Return 'true' if a collision was processed and should be sent up. 428 // 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. 429 // 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 430 // Called at taint time from within the Step() function
431 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, 432 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
295 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 433 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
296 { 434 {
297 bool ret = false; 435 bool ret = false;
298 436
299 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 437 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
300 CollidingStep = PhysicsScene.SimulationStep; 438 CollidingStep = PhysScene.SimulationStep;
301 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 439 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
302 { 440 {
303 CollidingGroundStep = PhysicsScene.SimulationStep; 441 CollidingGroundStep = PhysScene.SimulationStep;
304 } 442 }
305 else 443 else
306 { 444 {
307 CollidingObjectStep = PhysicsScene.SimulationStep; 445 CollidingObjectStep = PhysScene.SimulationStep;
308 } 446 }
309 447
310 CollisionAccumulation++; 448 CollisionAccumulation++;
311 449
312 // For movement tests, remember if we are colliding with an object that is moving. 450 // For movement tests, remember if we are colliding with an object that is moving.
313 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false; 451 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
452 ColliderIsVolumeDetect = collidee != null ? (collidee.IsVolumeDetect) : false;
453
454 // Make a collection of the collisions that happened the last simulation tick.
455 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
456 if (CollisionsLastTickStep != PhysScene.SimulationStep)
457 {
458 CollisionsLastTick = new CollisionEventUpdate();
459 CollisionsLastTickStep = PhysScene.SimulationStep;
460 }
461 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
314 462
315 // If someone has subscribed for collision events log the collision so it will be reported up 463 // If someone has subscribed for collision events log the collision so it will be reported up
316 if (SubscribedEvents()) { 464 if (SubscribedEvents()) {
@@ -332,12 +480,12 @@ public abstract class BSPhysObject : PhysicsActor
332 bool ret = true; 480 bool ret = true;
333 481
334 // If the 'no collision' call, force it to happen right now so quick collision_end 482 // If the 'no collision' call, force it to happen right now so quick collision_end
335 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0); 483 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
336 484
337 // throttle the collisions to the number of milliseconds specified in the subscription 485 // throttle the collisions to the number of milliseconds specified in the subscription
338 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 486 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
339 { 487 {
340 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 488 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
341 489
342 // We are called if we previously had collisions. If there are no collisions 490 // 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. 491 // this time, send up one last empty event so OpenSim can sense collision end.
@@ -351,11 +499,11 @@ public abstract class BSPhysObject : PhysicsActor
351 base.SendCollisionUpdate(CollisionCollection); 499 base.SendCollisionUpdate(CollisionCollection);
352 500
353 // Remember the collisions from this tick for some collision specific processing. 501 // Remember the collisions from this tick for some collision specific processing.
354 CollisionsLastTick = CollisionCollection; 502 CollisionsLastReported = CollisionCollection;
355 503
356 // The CollisionCollection instance is passed around in the simulator. 504 // 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. 505 // 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, 506 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
359 // a race condition is created for the other users of this instance. 507 // a race condition is created for the other users of this instance.
360 CollisionCollection = new CollisionEventUpdate(); 508 CollisionCollection = new CollisionEventUpdate();
361 } 509 }
@@ -372,10 +520,10 @@ public abstract class BSPhysObject : PhysicsActor
372 // make sure first collision happens 520 // make sure first collision happens
373 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 521 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
374 522
375 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 523 PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate()
376 { 524 {
377 if (PhysBody.HasPhysicalBody) 525 if (PhysBody.HasPhysicalBody)
378 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 526 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
379 }); 527 });
380 } 528 }
381 else 529 else
@@ -387,11 +535,11 @@ public abstract class BSPhysObject : PhysicsActor
387 public override void UnSubscribeEvents() { 535 public override void UnSubscribeEvents() {
388 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 536 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
389 SubscribedEventsMs = 0; 537 SubscribedEventsMs = 0;
390 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 538 PhysScene.TaintedObject(LocalID, TypeName+".UnSubscribeEvents", delegate()
391 { 539 {
392 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 540 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
393 if (PhysBody.HasPhysicalBody) 541 if (PhysBody.HasPhysicalBody)
394 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 542 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
395 }); 543 });
396 } 544 }
397 // Return 'true' if the simulator wants collision events 545 // Return 'true' if the simulator wants collision events
@@ -405,7 +553,7 @@ public abstract class BSPhysObject : PhysicsActor
405 { 553 {
406 // Scale the collision count by the time since the last collision. 554 // Scale the collision count by the time since the last collision.
407 // The "+1" prevents dividing by zero. 555 // The "+1" prevents dividing by zero.
408 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1; 556 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
409 CollisionScore = CollisionAccumulation / timeAgo; 557 CollisionScore = CollisionAccumulation / timeAgo;
410 } 558 }
411 public override float CollisionScore { get; set; } 559 public override float CollisionScore { get; set; }
@@ -413,103 +561,8 @@ public abstract class BSPhysObject : PhysicsActor
413 #endregion // Collisions 561 #endregion // Collisions
414 562
415 #region Per Simulation Step actions 563 #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 564
426 lock (RegisteredPrestepActions) 565 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 566
514 // When an update to the physical properties happens, this event is fired to let 567 // 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 568 // different actors to modify the update before it is passed around
@@ -522,53 +575,13 @@ public abstract class BSPhysObject : PhysicsActor
522 actions(ref entprop); 575 actions(ref entprop);
523 } 576 }
524 577
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 578 #endregion // Per Simulation Step actions
566 579
567 // High performance detailed logging routine used by the physical objects. 580 // High performance detailed logging routine used by the physical objects.
568 protected void DetailLog(string msg, params Object[] args) 581 protected void DetailLog(string msg, params Object[] args)
569 { 582 {
570 if (PhysicsScene.PhysicsLogging.Enabled) 583 if (PhysScene.PhysicsLogging.Enabled)
571 PhysicsScene.DetailLog(msg, args); 584 PhysScene.DetailLog(msg, args);
572 } 585 }
573 586
574} 587}