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.cs394
1 files changed, 198 insertions, 196 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 6bb88c7..9dc52d5 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("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,58 @@ 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 (IsPhysical && PhysBody.HasPhysicalBody)
304 PhysScene.PE.Activate(PhysBody, forceIt);
305 }
230 306
231 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 307 // '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 308 // hovering to complex vehicle motion.
309 // May be called at non-taint time as this just adds the actor to the action list and the real
310 // work is done during the simulation step.
311 // Note that, if the actor is already in the list and we are disabling same, the actor is just left
312 // in the list disabled.
313 public delegate BSActor CreateActor();
314 public void EnableActor(bool enableActor, string actorName, CreateActor creator)
315 {
316 lock (PhysicalActors)
317 {
318 BSActor theActor;
319 if (PhysicalActors.TryGetActor(actorName, out theActor))
320 {
321 // The actor already exists so just turn it on or off
322 DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
323 theActor.Enabled = enableActor;
324 }
325 else
326 {
327 // The actor does not exist. If it should, create it.
328 if (enableActor)
329 {
330 DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
331 theActor = creator();
332 PhysicalActors.Add(actorName, theActor);
333 theActor.Enabled = true;
334 }
335 else
336 {
337 DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
338 }
339 }
340 }
341 }
233 342
234 #region Collisions 343 #region Collisions
235 344
@@ -247,70 +356,98 @@ public abstract class BSPhysObject : PhysicsActor
247 protected CollisionFlags CurrentCollisionFlags { get; set; } 356 protected CollisionFlags CurrentCollisionFlags { get; set; }
248 // On a collision, check the collider and remember if the last collider was moving 357 // 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) 358 // Used to modify the standing of avatars (avatars on stationary things stand still)
250 protected bool ColliderIsMoving; 359 public bool ColliderIsMoving;
360 // 'true' if the last collider was a volume detect object
361 public bool ColliderIsVolumeDetect;
362 // Used by BSCharacter to manage standing (and not slipping)
363 public bool IsStationary;
251 364
252 // Count of collisions for this object 365 // Count of collisions for this object
253 protected long CollisionAccumulation { get; set; } 366 protected long CollisionAccumulation { get; set; }
254 367
255 public override bool IsColliding { 368 public override bool IsColliding {
256 get { return (CollidingStep == PhysicsScene.SimulationStep); } 369 get { return (CollidingStep == PhysScene.SimulationStep); }
257 set { 370 set {
258 if (value) 371 if (value)
259 CollidingStep = PhysicsScene.SimulationStep; 372 CollidingStep = PhysScene.SimulationStep;
260 else 373 else
261 CollidingStep = 0; 374 CollidingStep = BSScene.NotASimulationStep;
262 } 375 }
263 } 376 }
377 // Complex objects (like linksets) need to know if there is a collision on any part of
378 // their shape. 'IsColliding' has an existing definition of reporting a collision on
379 // only this specific prim or component of linksets.
380 // 'HasSomeCollision' is defined as reporting if there is a collision on any part of
381 // the complex body that this prim is the root of.
382 public virtual bool HasSomeCollision
383 {
384 get { return IsColliding; }
385 set { IsColliding = value; }
386 }
264 public override bool CollidingGround { 387 public override bool CollidingGround {
265 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 388 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
266 set 389 set
267 { 390 {
268 if (value) 391 if (value)
269 CollidingGroundStep = PhysicsScene.SimulationStep; 392 CollidingGroundStep = PhysScene.SimulationStep;
270 else 393 else
271 CollidingGroundStep = 0; 394 CollidingGroundStep = BSScene.NotASimulationStep;
272 } 395 }
273 } 396 }
274 public override bool CollidingObj { 397 public override bool CollidingObj {
275 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 398 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
276 set { 399 set {
277 if (value) 400 if (value)
278 CollidingObjectStep = PhysicsScene.SimulationStep; 401 CollidingObjectStep = PhysScene.SimulationStep;
279 else 402 else
280 CollidingObjectStep = 0; 403 CollidingObjectStep = BSScene.NotASimulationStep;
281 } 404 }
282 } 405 }
283 406
284 // The collisions that have been collected this tick 407 // The collisions that have been collected for the next collision reporting (throttled by subscription)
285 protected CollisionEventUpdate CollisionCollection; 408 protected CollisionEventUpdate CollisionCollection;
286 // Remember collisions from last tick for fancy collision based actions 409 // This is the collision collection last reported to the Simulator.
410 public CollisionEventUpdate CollisionsLastReported;
411 // Remember the collisions recorded in the last tick for fancy collision checking
287 // (like a BSCharacter walking up stairs). 412 // (like a BSCharacter walking up stairs).
288 protected CollisionEventUpdate CollisionsLastTick; 413 public CollisionEventUpdate CollisionsLastTick;
414 private long CollisionsLastTickStep = -1;
289 415
290 // The simulation step is telling this object about a collision. 416 // The simulation step is telling this object about a collision.
291 // Return 'true' if a collision was processed and should be sent up. 417 // 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. 418 // 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 419 // Called at taint time from within the Step() function
420 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, 421 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
295 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 422 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
296 { 423 {
297 bool ret = false; 424 bool ret = false;
298 425
299 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 426 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
300 CollidingStep = PhysicsScene.SimulationStep; 427 CollidingStep = PhysScene.SimulationStep;
301 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 428 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
302 { 429 {
303 CollidingGroundStep = PhysicsScene.SimulationStep; 430 CollidingGroundStep = PhysScene.SimulationStep;
304 } 431 }
305 else 432 else
306 { 433 {
307 CollidingObjectStep = PhysicsScene.SimulationStep; 434 CollidingObjectStep = PhysScene.SimulationStep;
308 } 435 }
309 436
310 CollisionAccumulation++; 437 CollisionAccumulation++;
311 438
312 // For movement tests, remember if we are colliding with an object that is moving. 439 // For movement tests, remember if we are colliding with an object that is moving.
313 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false; 440 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
441 ColliderIsVolumeDetect = collidee != null ? (collidee.IsVolumeDetect) : false;
442
443 // Make a collection of the collisions that happened the last simulation tick.
444 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
445 if (CollisionsLastTickStep != PhysScene.SimulationStep)
446 {
447 CollisionsLastTick = new CollisionEventUpdate();
448 CollisionsLastTickStep = PhysScene.SimulationStep;
449 }
450 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
314 451
315 // If someone has subscribed for collision events log the collision so it will be reported up 452 // If someone has subscribed for collision events log the collision so it will be reported up
316 if (SubscribedEvents()) { 453 if (SubscribedEvents()) {
@@ -332,12 +469,12 @@ public abstract class BSPhysObject : PhysicsActor
332 bool ret = true; 469 bool ret = true;
333 470
334 // If the 'no collision' call, force it to happen right now so quick collision_end 471 // If the 'no collision' call, force it to happen right now so quick collision_end
335 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0); 472 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
336 473
337 // throttle the collisions to the number of milliseconds specified in the subscription 474 // throttle the collisions to the number of milliseconds specified in the subscription
338 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 475 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
339 { 476 {
340 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 477 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
341 478
342 // We are called if we previously had collisions. If there are no collisions 479 // 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. 480 // this time, send up one last empty event so OpenSim can sense collision end.
@@ -351,11 +488,11 @@ public abstract class BSPhysObject : PhysicsActor
351 base.SendCollisionUpdate(CollisionCollection); 488 base.SendCollisionUpdate(CollisionCollection);
352 489
353 // Remember the collisions from this tick for some collision specific processing. 490 // Remember the collisions from this tick for some collision specific processing.
354 CollisionsLastTick = CollisionCollection; 491 CollisionsLastReported = CollisionCollection;
355 492
356 // The CollisionCollection instance is passed around in the simulator. 493 // 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. 494 // 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, 495 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
359 // a race condition is created for the other users of this instance. 496 // a race condition is created for the other users of this instance.
360 CollisionCollection = new CollisionEventUpdate(); 497 CollisionCollection = new CollisionEventUpdate();
361 } 498 }
@@ -372,10 +509,10 @@ public abstract class BSPhysObject : PhysicsActor
372 // make sure first collision happens 509 // make sure first collision happens
373 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 510 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
374 511
375 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 512 PhysScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
376 { 513 {
377 if (PhysBody.HasPhysicalBody) 514 if (PhysBody.HasPhysicalBody)
378 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 515 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
379 }); 516 });
380 } 517 }
381 else 518 else
@@ -387,11 +524,11 @@ public abstract class BSPhysObject : PhysicsActor
387 public override void UnSubscribeEvents() { 524 public override void UnSubscribeEvents() {
388 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 525 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
389 SubscribedEventsMs = 0; 526 SubscribedEventsMs = 0;
390 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 527 PhysScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
391 { 528 {
392 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 529 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
393 if (PhysBody.HasPhysicalBody) 530 if (PhysBody.HasPhysicalBody)
394 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 531 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
395 }); 532 });
396 } 533 }
397 // Return 'true' if the simulator wants collision events 534 // Return 'true' if the simulator wants collision events
@@ -405,7 +542,7 @@ public abstract class BSPhysObject : PhysicsActor
405 { 542 {
406 // Scale the collision count by the time since the last collision. 543 // Scale the collision count by the time since the last collision.
407 // The "+1" prevents dividing by zero. 544 // The "+1" prevents dividing by zero.
408 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1; 545 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
409 CollisionScore = CollisionAccumulation / timeAgo; 546 CollisionScore = CollisionAccumulation / timeAgo;
410 } 547 }
411 public override float CollisionScore { get; set; } 548 public override float CollisionScore { get; set; }
@@ -413,103 +550,8 @@ public abstract class BSPhysObject : PhysicsActor
413 #endregion // Collisions 550 #endregion // Collisions
414 551
415 #region Per Simulation Step actions 552 #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
426 lock (RegisteredPrestepActions)
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 553
436 // Unregister a pre step action. Safe to call if the action has not been registered. 554 public BSActorCollection PhysicalActors;
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 555
514 // When an update to the physical properties happens, this event is fired to let 556 // 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 557 // different actors to modify the update before it is passed around
@@ -522,53 +564,13 @@ public abstract class BSPhysObject : PhysicsActor
522 actions(ref entprop); 564 actions(ref entprop);
523 } 565 }
524 566
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 567 #endregion // Per Simulation Step actions
566 568
567 // High performance detailed logging routine used by the physical objects. 569 // High performance detailed logging routine used by the physical objects.
568 protected void DetailLog(string msg, params Object[] args) 570 protected void DetailLog(string msg, params Object[] args)
569 { 571 {
570 if (PhysicsScene.PhysicsLogging.Enabled) 572 if (PhysScene.PhysicsLogging.Enabled)
571 PhysicsScene.DetailLog(msg, args); 573 PhysScene.DetailLog(msg, args);
572 } 574 }
573 575
574} 576}