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.cs404
1 files changed, 203 insertions, 201 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 98ea833..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,22 +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
81 // The collection of things that push me around 83 // The collection of things that push me around
82 PhysicalActors = new BSActorCollection(PhysicsScene); 84 PhysicalActors = new BSActorCollection(PhysScene);
83 85
84 // Initialize variables kept in base. 86 // Initialize variables kept in base.
85 GravModifier = 1.0f; 87 GravModifier = 1.0f;
86 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); 88 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
89 HoverActive = false;
87 90
88 // We don't have any physical representation yet. 91 // We don't have any physical representation yet.
89 PhysBody = new BulletBody(localID); 92 PhysBody = new BulletBody(localID);
90 PhysShape = new BulletShape(); 93 PhysShape = new BSShapeNull();
94
95 UserSetCenterOfMassDisplacement = null;
91 96
92 PrimAssetState = PrimAssetCondition.Unknown; 97 PrimAssetState = PrimAssetCondition.Unknown;
93 98
@@ -95,34 +100,41 @@ public abstract class BSPhysObject : PhysicsActor
95 SetMaterial((int)MaterialAttributes.Material.Wood); 100 SetMaterial((int)MaterialAttributes.Material.Wood);
96 101
97 CollisionCollection = new CollisionEventUpdate(); 102 CollisionCollection = new CollisionEventUpdate();
98 CollisionsLastTick = CollisionCollection; 103 CollisionsLastReported = CollisionCollection;
104 CollisionsLastTick = new CollisionEventUpdate();
105 CollisionsLastTickStep = -1;
106
99 SubscribedEventsMs = 0; 107 SubscribedEventsMs = 0;
100 CollidingStep = 0; 108 // Crazy values that will never be true
101 CollidingGroundStep = 0; 109 CollidingStep = BSScene.NotASimulationStep;
102 CollisionAccumulation = 0; 110 CollidingGroundStep = BSScene.NotASimulationStep;
111 CollisionAccumulation = BSScene.NotASimulationStep;
103 ColliderIsMoving = false; 112 ColliderIsMoving = false;
104 CollisionScore = 0; 113 CollisionScore = 0;
105 114
106 // All axis free. 115 // All axis free.
107 LockedAxis = LockedAxisFree; 116 LockedLinearAxis = LockedAxisFree;
117 LockedAngularAxis = LockedAxisFree;
108 } 118 }
109 119
110 // Tell the object to clean up. 120 // Tell the object to clean up.
111 public virtual void Destroy() 121 public virtual void Destroy()
112 { 122 {
113 UnRegisterAllPreStepActions(); 123 PhysicalActors.Enable(false);
114 UnRegisterAllPostStepActions(); 124 PhysScene.TaintedObject(LocalID, "BSPhysObject.Destroy", delegate()
115 PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate()
116 { 125 {
117 PhysicalActors.Release(); 126 PhysicalActors.Dispose();
118 }); 127 });
119 } 128 }
120 129
121 public BSScene PhysicsScene { get; protected set; } 130 public BSScene PhysScene { get; protected set; }
122 // 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
123 public string PhysObjectName { get; protected set; } 132 public string PhysObjectName { get; protected set; }
124 public string TypeName { get; protected set; } 133 public string TypeName { get; protected set; }
125 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; }
126 138
127 // Return the object mass without calculating it or having side effects 139 // Return the object mass without calculating it or having side effects
128 public abstract float RawMass { get; } 140 public abstract float RawMass { get; }
@@ -138,26 +150,19 @@ public abstract class BSPhysObject : PhysicsActor
138 // Reference to the physical body (btCollisionObject) of this object 150 // Reference to the physical body (btCollisionObject) of this object
139 public BulletBody PhysBody; 151 public BulletBody PhysBody;
140 // Reference to the physical shape (btCollisionShape) of this object 152 // Reference to the physical shape (btCollisionShape) of this object
141 public BulletShape PhysShape; 153 public BSShape PhysShape;
142 154
143 // The physical representation of the prim might require an asset fetch. 155 // The physical representation of the prim might require an asset fetch.
144 // 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'.
145 public enum PrimAssetCondition 157 public enum PrimAssetCondition
146 { 158 {
147 Unknown, Waiting, Failed, Fetched 159 Unknown, Waiting, FailedAssetFetch, FailedMeshing, Fetched
148 } 160 }
149 public PrimAssetCondition PrimAssetState { get; set; } 161 public PrimAssetCondition PrimAssetState { get; set; }
150 162
151 // 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.
152 public PrimitiveBaseShape BaseShape { get; protected set; } 164 public PrimitiveBaseShape BaseShape { get; protected set; }
153 165
154 // Some types of objects have preferred physical representations.
155 // Returns SHAPE_UNKNOWN if there is no preference.
156 public virtual BSPhysicsShapeType PreferredPhysicalShape
157 {
158 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
159 }
160
161 // 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.
162 // Keep the current and last EntityProperties to enable computation of differences 167 // Keep the current and last EntityProperties to enable computation of differences
163 // between the current update and the previous values. 168 // between the current update and the previous values.
@@ -175,6 +180,7 @@ public abstract class BSPhysObject : PhysicsActor
175 public abstract bool IsSolid { get; } 180 public abstract bool IsSolid { get; }
176 public abstract bool IsStatic { get; } 181 public abstract bool IsStatic { get; }
177 public abstract bool IsSelected { get; } 182 public abstract bool IsSelected { get; }
183 public abstract bool IsVolumeDetect { get; }
178 184
179 // Materialness 185 // Materialness
180 public MaterialAttributes.Material Material { get; private set; } 186 public MaterialAttributes.Material Material { get; private set; }
@@ -183,13 +189,27 @@ public abstract class BSPhysObject : PhysicsActor
183 Material = (MaterialAttributes.Material)material; 189 Material = (MaterialAttributes.Material)material;
184 190
185 // 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.
186 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); 193 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
187 Friction = matAttrib.friction; 194 Friction = matAttrib.friction;
188 Restitution = matAttrib.restitution; 195 Restitution = matAttrib.restitution;
189 Density = matAttrib.density / BSParam.DensityScaleFactor; 196 Density = matAttrib.density;
190 // 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);
191 } 198 }
192 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 }
211 }
212
193 // Stop all physical motion. 213 // Stop all physical motion.
194 public abstract void ZeroMotion(bool inTaintTime); 214 public abstract void ZeroMotion(bool inTaintTime);
195 public abstract void ZeroAngularMotion(bool inTaintTime); 215 public abstract void ZeroAngularMotion(bool inTaintTime);
@@ -197,21 +217,55 @@ public abstract class BSPhysObject : PhysicsActor
197 // 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.
198 public abstract void UpdateProperties(EntityProperties entprop); 218 public abstract void UpdateProperties(EntityProperties entprop);
199 219
200 public abstract OMV.Vector3 RawPosition { get; set; } 220 public virtual OMV.Vector3 RawPosition { get; set; }
201 public abstract OMV.Vector3 ForcePosition { get; set; } 221 public abstract OMV.Vector3 ForcePosition { get; set; }
202 222
203 public abstract OMV.Quaternion RawOrientation { get; set; } 223 public virtual OMV.Quaternion RawOrientation { get; set; }
204 public abstract OMV.Quaternion ForceOrientation { get; set; } 224 public abstract OMV.Quaternion ForceOrientation { get; set; }
205 225
206 public abstract OMV.Vector3 RawVelocity { get; set; } 226 public OMV.Vector3 RawVelocity { get; set; }
207 public abstract OMV.Vector3 ForceVelocity { get; set; } 227 public abstract OMV.Vector3 ForceVelocity { get; set; }
208 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
209 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 238 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
210 239
211 public abstract float ForceBuoyancy { get; set; } 240 public abstract float ForceBuoyancy { get; set; }
212 241
213 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 242 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
214 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
215 // The current velocity forward 269 // The current velocity forward
216 public virtual float ForwardSpeed 270 public virtual float ForwardSpeed
217 { 271 {
@@ -233,11 +287,69 @@ public abstract class BSPhysObject : PhysicsActor
233 287
234 // 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
235 // computed center-of-mass (like in linksets). 289 // computed center-of-mass (like in linksets).
236 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 }
237 317
238 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
239 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free 319 // hovering to complex vehicle motion.
240 public readonly String LockedAxisActorName = "BSPrim.LockedAxis"; 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 }
241 353
242 #region Collisions 354 #region Collisions
243 355
@@ -255,70 +367,98 @@ public abstract class BSPhysObject : PhysicsActor
255 protected CollisionFlags CurrentCollisionFlags { get; set; } 367 protected CollisionFlags CurrentCollisionFlags { get; set; }
256 // 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
257 // 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)
258 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;
259 375
260 // Count of collisions for this object 376 // Count of collisions for this object
261 protected long CollisionAccumulation { get; set; } 377 protected long CollisionAccumulation { get; set; }
262 378
263 public override bool IsColliding { 379 public override bool IsColliding {
264 get { return (CollidingStep == PhysicsScene.SimulationStep); } 380 get { return (CollidingStep == PhysScene.SimulationStep); }
265 set { 381 set {
266 if (value) 382 if (value)
267 CollidingStep = PhysicsScene.SimulationStep; 383 CollidingStep = PhysScene.SimulationStep;
268 else 384 else
269 CollidingStep = 0; 385 CollidingStep = BSScene.NotASimulationStep;
270 } 386 }
271 } 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 }
272 public override bool CollidingGround { 398 public override bool CollidingGround {
273 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 399 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
274 set 400 set
275 { 401 {
276 if (value) 402 if (value)
277 CollidingGroundStep = PhysicsScene.SimulationStep; 403 CollidingGroundStep = PhysScene.SimulationStep;
278 else 404 else
279 CollidingGroundStep = 0; 405 CollidingGroundStep = BSScene.NotASimulationStep;
280 } 406 }
281 } 407 }
282 public override bool CollidingObj { 408 public override bool CollidingObj {
283 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 409 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
284 set { 410 set {
285 if (value) 411 if (value)
286 CollidingObjectStep = PhysicsScene.SimulationStep; 412 CollidingObjectStep = PhysScene.SimulationStep;
287 else 413 else
288 CollidingObjectStep = 0; 414 CollidingObjectStep = BSScene.NotASimulationStep;
289 } 415 }
290 } 416 }
291 417
292 // The collisions that have been collected this tick 418 // The collisions that have been collected for the next collision reporting (throttled by subscription)
293 protected CollisionEventUpdate CollisionCollection; 419 protected CollisionEventUpdate CollisionCollection;
294 // 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
295 // (like a BSCharacter walking up stairs). 423 // (like a BSCharacter walking up stairs).
296 protected CollisionEventUpdate CollisionsLastTick; 424 public CollisionEventUpdate CollisionsLastTick;
425 private long CollisionsLastTickStep = -1;
297 426
298 // The simulation step is telling this object about a collision. 427 // The simulation step is telling this object about a collision.
299 // 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.
300 // 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.
301 // 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);
302 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 432 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
303 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 433 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
304 { 434 {
305 bool ret = false; 435 bool ret = false;
306 436
307 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 437 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
308 CollidingStep = PhysicsScene.SimulationStep; 438 CollidingStep = PhysScene.SimulationStep;
309 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 439 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
310 { 440 {
311 CollidingGroundStep = PhysicsScene.SimulationStep; 441 CollidingGroundStep = PhysScene.SimulationStep;
312 } 442 }
313 else 443 else
314 { 444 {
315 CollidingObjectStep = PhysicsScene.SimulationStep; 445 CollidingObjectStep = PhysScene.SimulationStep;
316 } 446 }
317 447
318 CollisionAccumulation++; 448 CollisionAccumulation++;
319 449
320 // 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.
321 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));
322 462
323 // 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
324 if (SubscribedEvents()) { 464 if (SubscribedEvents()) {
@@ -340,12 +480,12 @@ public abstract class BSPhysObject : PhysicsActor
340 bool ret = true; 480 bool ret = true;
341 481
342 // 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
343 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0); 483 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
344 484
345 // 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
346 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 486 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
347 { 487 {
348 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 488 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
349 489
350 // 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
351 // 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.
@@ -359,11 +499,11 @@ public abstract class BSPhysObject : PhysicsActor
359 base.SendCollisionUpdate(CollisionCollection); 499 base.SendCollisionUpdate(CollisionCollection);
360 500
361 // Remember the collisions from this tick for some collision specific processing. 501 // Remember the collisions from this tick for some collision specific processing.
362 CollisionsLastTick = CollisionCollection; 502 CollisionsLastReported = CollisionCollection;
363 503
364 // The CollisionCollection instance is passed around in the simulator. 504 // The CollisionCollection instance is passed around in the simulator.
365 // 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.
366 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, 506 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
367 // 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.
368 CollisionCollection = new CollisionEventUpdate(); 508 CollisionCollection = new CollisionEventUpdate();
369 } 509 }
@@ -380,10 +520,10 @@ public abstract class BSPhysObject : PhysicsActor
380 // make sure first collision happens 520 // make sure first collision happens
381 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 521 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
382 522
383 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 523 PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate()
384 { 524 {
385 if (PhysBody.HasPhysicalBody) 525 if (PhysBody.HasPhysicalBody)
386 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 526 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
387 }); 527 });
388 } 528 }
389 else 529 else
@@ -395,11 +535,11 @@ public abstract class BSPhysObject : PhysicsActor
395 public override void UnSubscribeEvents() { 535 public override void UnSubscribeEvents() {
396 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 536 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
397 SubscribedEventsMs = 0; 537 SubscribedEventsMs = 0;
398 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 538 PhysScene.TaintedObject(LocalID, TypeName+".UnSubscribeEvents", delegate()
399 { 539 {
400 // 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.
401 if (PhysBody.HasPhysicalBody) 541 if (PhysBody.HasPhysicalBody)
402 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 542 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
403 }); 543 });
404 } 544 }
405 // Return 'true' if the simulator wants collision events 545 // Return 'true' if the simulator wants collision events
@@ -413,7 +553,7 @@ public abstract class BSPhysObject : PhysicsActor
413 { 553 {
414 // Scale the collision count by the time since the last collision. 554 // Scale the collision count by the time since the last collision.
415 // The "+1" prevents dividing by zero. 555 // The "+1" prevents dividing by zero.
416 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1; 556 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
417 CollisionScore = CollisionAccumulation / timeAgo; 557 CollisionScore = CollisionAccumulation / timeAgo;
418 } 558 }
419 public override float CollisionScore { get; set; } 559 public override float CollisionScore { get; set; }
@@ -424,104 +564,6 @@ public abstract class BSPhysObject : PhysicsActor
424 564
425 public BSActorCollection PhysicalActors; 565 public BSActorCollection PhysicalActors;
426 566
427 // There are some actions that must be performed for a physical object before each simulation step.
428 // These actions are optional so, rather than scanning all the physical objects and asking them
429 // if they have anything to do, a physical object registers for an event call before the step is performed.
430 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
431 private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>();
432 private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>();
433 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
434 {
435 string identifier = op + "-" + id.ToString();
436
437 lock (RegisteredPrestepActions)
438 {
439 // Clean out any existing action
440 UnRegisterPreStepAction(op, id);
441 RegisteredPrestepActions[identifier] = actn;
442 PhysicsScene.BeforeStep += actn;
443 }
444 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
445 }
446
447 // Unregister a pre step action. Safe to call if the action has not been registered.
448 // Returns 'true' if an action was actually removed
449 protected bool UnRegisterPreStepAction(string op, uint id)
450 {
451 string identifier = op + "-" + id.ToString();
452 bool removed = false;
453 lock (RegisteredPrestepActions)
454 {
455 if (RegisteredPrestepActions.ContainsKey(identifier))
456 {
457 PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier];
458 RegisteredPrestepActions.Remove(identifier);
459 removed = true;
460 }
461 }
462 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
463 return removed;
464 }
465
466 protected void UnRegisterAllPreStepActions()
467 {
468 lock (RegisteredPrestepActions)
469 {
470 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions)
471 {
472 PhysicsScene.BeforeStep -= kvp.Value;
473 }
474 RegisteredPrestepActions.Clear();
475 }
476 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
477 }
478
479 protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn)
480 {
481 string identifier = op + "-" + id.ToString();
482
483 lock (RegisteredPoststepActions)
484 {
485 // Clean out any existing action
486 UnRegisterPostStepAction(op, id);
487 RegisteredPoststepActions[identifier] = actn;
488 PhysicsScene.AfterStep += actn;
489 }
490 DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
491 }
492
493 // Unregister a pre step action. Safe to call if the action has not been registered.
494 // Returns 'true' if an action was actually removed.
495 protected bool UnRegisterPostStepAction(string op, uint id)
496 {
497 string identifier = op + "-" + id.ToString();
498 bool removed = false;
499 lock (RegisteredPoststepActions)
500 {
501 if (RegisteredPoststepActions.ContainsKey(identifier))
502 {
503 PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier];
504 RegisteredPoststepActions.Remove(identifier);
505 removed = true;
506 }
507 }
508 DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed);
509 return removed;
510 }
511
512 protected void UnRegisterAllPostStepActions()
513 {
514 lock (RegisteredPoststepActions)
515 {
516 foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions)
517 {
518 PhysicsScene.AfterStep -= kvp.Value;
519 }
520 RegisteredPoststepActions.Clear();
521 }
522 DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
523 }
524
525 // 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
526 // different actors to modify the update before it is passed around 568 // different actors to modify the update before it is passed around
527 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); 569 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
@@ -533,53 +575,13 @@ public abstract class BSPhysObject : PhysicsActor
533 actions(ref entprop); 575 actions(ref entprop);
534 } 576 }
535 577
536 private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>();
537 public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn)
538 {
539 lock (RegisteredPreUpdatePropertyActions)
540 {
541 // Clean out any existing action
542 UnRegisterPreUpdatePropertyAction(identifier);
543 RegisteredPreUpdatePropertyActions[identifier] = actn;
544 OnPreUpdateProperty += actn;
545 }
546 DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier);
547 }
548 public bool UnRegisterPreUpdatePropertyAction(string identifier)
549 {
550 bool removed = false;
551 lock (RegisteredPreUpdatePropertyActions)
552 {
553 if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier))
554 {
555 OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier];
556 RegisteredPreUpdatePropertyActions.Remove(identifier);
557 removed = true;
558 }
559 }
560 DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed);
561 return removed;
562 }
563 public void UnRegisterAllPreUpdatePropertyActions()
564 {
565 lock (RegisteredPreUpdatePropertyActions)
566 {
567 foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions)
568 {
569 OnPreUpdateProperty -= kvp.Value;
570 }
571 RegisteredPreUpdatePropertyActions.Clear();
572 }
573 DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID);
574 }
575
576 #endregion // Per Simulation Step actions 578 #endregion // Per Simulation Step actions
577 579
578 // High performance detailed logging routine used by the physical objects. 580 // High performance detailed logging routine used by the physical objects.
579 protected void DetailLog(string msg, params Object[] args) 581 protected void DetailLog(string msg, params Object[] args)
580 { 582 {
581 if (PhysicsScene.PhysicsLogging.Enabled) 583 if (PhysScene.PhysicsLogging.Enabled)
582 PhysicsScene.DetailLog(msg, args); 584 PhysScene.DetailLog(msg, args);
583 } 585 }
584 586
585} 587}