aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
diff options
context:
space:
mode:
authorRobert Adams2013-05-08 06:02:12 -0700
committerRobert Adams2013-05-08 06:02:12 -0700
commiteb0687f5af127ad6195b95965ce31346f2bc0a24 (patch)
tree8888b8d4c45874c646da0b475d09bd051b33e1cc /OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
parentAdd regression test for inventory item give, reject and subsequent trash fold... (diff)
downloadopensim-SC_OLD-eb0687f5af127ad6195b95965ce31346f2bc0a24.zip
opensim-SC_OLD-eb0687f5af127ad6195b95965ce31346f2bc0a24.tar.gz
opensim-SC_OLD-eb0687f5af127ad6195b95965ce31346f2bc0a24.tar.bz2
opensim-SC_OLD-eb0687f5af127ad6195b95965ce31346f2bc0a24.tar.xz
vh: update BulletSim (OpenSim/Region/Physics/BulletSPlugin
and DLL/SO) to ac6dcd35fb77f118fc6c3d72cb029591306c7e99 (Mon May 6 21:10:02 2013 -0400) on top of 0.7.5-postfixes.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs351
1 files changed, 252 insertions, 99 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index e7cb3e0..cca887a 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,9 +52,19 @@ 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.
59public enum UpdatedProperties : uint
60{
61 Position = 1 << 0,
62 Orientation = 1 << 1,
63 Velocity = 1 << 2,
64 Acceleration = 1 << 3,
65 RotationalVelocity = 1 << 4,
66 EntPropUpdates = Position | Orientation | Velocity | Acceleration | RotationalVelocity,
67}
58public abstract class BSPhysObject : PhysicsActor 68public abstract class BSPhysObject : PhysicsActor
59{ 69{
60 protected BSPhysObject() 70 protected BSPhysObject()
@@ -62,41 +72,61 @@ public abstract class BSPhysObject : PhysicsActor
62 } 72 }
63 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) 73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
64 { 74 {
65 PhysicsScene = parentScene; 75 PhysScene = parentScene;
66 LocalID = localID; 76 LocalID = localID;
67 PhysObjectName = name; 77 PhysObjectName = name;
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
68 TypeName = typeName; 79 TypeName = typeName;
69 80
81 // The collection of things that push me around
82 PhysicalActors = new BSActorCollection(PhysScene);
83
84 // Initialize variables kept in base.
85 GravModifier = 1.0f;
86 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
87 HoverActive = false;
88
70 // We don't have any physical representation yet. 89 // We don't have any physical representation yet.
71 PhysBody = new BulletBody(localID); 90 PhysBody = new BulletBody(localID);
72 PhysShape = new BulletShape(); 91 PhysShape = new BSShapeNull();
73 92
74 // A linkset of just me 93 PrimAssetState = PrimAssetCondition.Unknown;
75 Linkset = BSLinkset.Factory(PhysicsScene, this);
76 LastAssetBuildFailed = false;
77 94
78 // Default material type 95 // Default material type. Also sets Friction, Restitution and Density.
79 Material = MaterialAttributes.Material.Wood; 96 SetMaterial((int)MaterialAttributes.Material.Wood);
80 97
81 CollisionCollection = new CollisionEventUpdate(); 98 CollisionCollection = new CollisionEventUpdate();
99 CollisionsLastReported = CollisionCollection;
100 CollisionsLastTick = new CollisionEventUpdate();
101 CollisionsLastTickStep = -1;
102
82 SubscribedEventsMs = 0; 103 SubscribedEventsMs = 0;
83 CollidingStep = 0; 104 CollidingStep = 0;
84 CollidingGroundStep = 0; 105 CollidingGroundStep = 0;
106 CollisionAccumulation = 0;
107 ColliderIsMoving = false;
108 CollisionScore = 0;
109
110 // All axis free.
111 LockedLinearAxis = LockedAxisFree;
112 LockedAngularAxis = LockedAxisFree;
85 } 113 }
86 114
87 // Tell the object to clean up. 115 // Tell the object to clean up.
88 public virtual void Destroy() 116 public virtual void Destroy()
89 { 117 {
90 UnRegisterAllPreStepActions(); 118 PhysicalActors.Enable(false);
119 PhysScene.TaintedObject("BSPhysObject.Destroy", delegate()
120 {
121 PhysicalActors.Dispose();
122 });
91 } 123 }
92 124
93 public BSScene PhysicsScene { get; protected set; } 125 public BSScene PhysScene { get; protected set; }
94 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 126 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
95 public string PhysObjectName { get; protected set; } 127 public string PhysObjectName { get; protected set; }
96 public string TypeName { get; protected set; } 128 public string TypeName { get; protected set; }
97 129
98 public BSLinkset Linkset { get; set; }
99 public BSLinksetInfo LinksetInfo { get; set; }
100 130
101 // Return the object mass without calculating it or having side effects 131 // Return the object mass without calculating it or having side effects
102 public abstract float RawMass { get; } 132 public abstract float RawMass { get; }
@@ -104,26 +134,26 @@ public abstract class BSPhysObject : PhysicsActor
104 // 'inWorld' true if the object has already been added to the dynamic world. 134 // 'inWorld' true if the object has already been added to the dynamic world.
105 public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld); 135 public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld);
106 136
137 // The gravity being applied to the object. A function of default grav, GravityModifier and Buoyancy.
138 public virtual OMV.Vector3 Gravity { get; set; }
107 // The last value calculated for the prim's inertia 139 // The last value calculated for the prim's inertia
108 public OMV.Vector3 Inertia { get; set; } 140 public OMV.Vector3 Inertia { get; set; }
109 141
110 // Reference to the physical body (btCollisionObject) of this object 142 // Reference to the physical body (btCollisionObject) of this object
111 public BulletBody PhysBody; 143 public BulletBody PhysBody;
112 // Reference to the physical shape (btCollisionShape) of this object 144 // Reference to the physical shape (btCollisionShape) of this object
113 public BulletShape PhysShape; 145 public BSShape PhysShape;
114 146
115 // 'true' if the mesh's underlying asset failed to build. 147 // The physical representation of the prim might require an asset fetch.
116 // This will keep us from looping after the first time the build failed. 148 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
117 public bool LastAssetBuildFailed { get; set; } 149 public enum PrimAssetCondition
150 {
151 Unknown, Waiting, Failed, Fetched
152 }
153 public PrimAssetCondition PrimAssetState { get; set; }
118 154
119 // The objects base shape information. Null if not a prim type shape. 155 // The objects base shape information. Null if not a prim type shape.
120 public PrimitiveBaseShape BaseShape { get; protected set; } 156 public PrimitiveBaseShape BaseShape { get; protected set; }
121 // Some types of objects have preferred physical representations.
122 // Returns SHAPE_UNKNOWN if there is no preference.
123 public virtual BSPhysicsShapeType PreferredPhysicalShape
124 {
125 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
126 }
127 157
128 // When the physical properties are updated, an EntityProperty holds the update values. 158 // When the physical properties are updated, an EntityProperty holds the update values.
129 // Keep the current and last EntityProperties to enable computation of differences 159 // Keep the current and last EntityProperties to enable computation of differences
@@ -132,23 +162,35 @@ public abstract class BSPhysObject : PhysicsActor
132 public EntityProperties LastEntityProperties { get; set; } 162 public EntityProperties LastEntityProperties { get; set; }
133 163
134 public virtual OMV.Vector3 Scale { get; set; } 164 public virtual OMV.Vector3 Scale { get; set; }
165
166 // It can be confusing for an actor to know if it should move or update an object
167 // depeneding on the setting of 'selected', 'physical, ...
168 // This flag is the true test -- if true, the object is being acted on in the physical world
169 public abstract bool IsPhysicallyActive { get; }
170
171 // Detailed state of the object.
135 public abstract bool IsSolid { get; } 172 public abstract bool IsSolid { get; }
136 public abstract bool IsStatic { get; } 173 public abstract bool IsStatic { get; }
174 public abstract bool IsSelected { get; }
137 175
138 // Materialness 176 // Materialness
139 public MaterialAttributes.Material Material { get; private set; } 177 public MaterialAttributes.Material Material { get; private set; }
140 public override void SetMaterial(int material) 178 public override void SetMaterial(int material)
141 { 179 {
142 Material = (MaterialAttributes.Material)material; 180 Material = (MaterialAttributes.Material)material;
181
182 // Setting the material sets the material attributes also.
183 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
184 Friction = matAttrib.friction;
185 Restitution = matAttrib.restitution;
186 Density = matAttrib.density / BSParam.DensityScaleFactor;
187 // DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
143 } 188 }
144 189
145 // Stop all physical motion. 190 // Stop all physical motion.
146 public abstract void ZeroMotion(bool inTaintTime); 191 public abstract void ZeroMotion(bool inTaintTime);
147 public abstract void ZeroAngularMotion(bool inTaintTime); 192 public abstract void ZeroAngularMotion(bool inTaintTime);
148 193
149 // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured.
150 public virtual void StepVehicle(float timeStep) { }
151
152 // Update the physical location and motion of the object. Called with data from Bullet. 194 // Update the physical location and motion of the object. Called with data from Bullet.
153 public abstract void UpdateProperties(EntityProperties entprop); 195 public abstract void UpdateProperties(EntityProperties entprop);
154 196
@@ -158,18 +200,16 @@ public abstract class BSPhysObject : PhysicsActor
158 public abstract OMV.Quaternion RawOrientation { get; set; } 200 public abstract OMV.Quaternion RawOrientation { get; set; }
159 public abstract OMV.Quaternion ForceOrientation { get; set; } 201 public abstract OMV.Quaternion ForceOrientation { get; set; }
160 202
161 // The system is telling us the velocity it wants to move at. 203 public OMV.Vector3 RawVelocity { get; set; }
162 // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor 204 public abstract OMV.Vector3 ForceVelocity { get; set; }
163 public override OMV.Vector3 TargetVelocity 205
206 public OMV.Vector3 RawForce { get; set; }
207 public OMV.Vector3 RawTorque { get; set; }
208 public override void AddAngularForce(OMV.Vector3 force, bool pushforce)
164 { 209 {
165 get { return m_targetVelocity; } 210 AddAngularForce(force, pushforce, false);
166 set
167 {
168 m_targetVelocity = value;
169 Velocity = value;
170 }
171 } 211 }
172 public abstract OMV.Vector3 ForceVelocity { get; set; } 212 public abstract void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
173 213
174 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 214 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
175 215
@@ -177,6 +217,105 @@ public abstract class BSPhysObject : PhysicsActor
177 217
178 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 218 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
179 219
220 public override bool PIDActive { set { MoveToTargetActive = value; } }
221 public override OMV.Vector3 PIDTarget { set { MoveToTargetTarget = value; } }
222 public override float PIDTau { set { MoveToTargetTau = value; } }
223
224 public bool MoveToTargetActive { get; set; }
225 public OMV.Vector3 MoveToTargetTarget { get; set; }
226 public float MoveToTargetTau { get; set; }
227
228 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
229 public override bool PIDHoverActive { set { HoverActive = value; } }
230 public override float PIDHoverHeight { set { HoverHeight = value; } }
231 public override PIDHoverType PIDHoverType { set { HoverType = value; } }
232 public override float PIDHoverTau { set { HoverTau = value; } }
233
234 public bool HoverActive { get; set; }
235 public float HoverHeight { get; set; }
236 public PIDHoverType HoverType { get; set; }
237 public float HoverTau { get; set; }
238
239 // For RotLookAt
240 public override OMV.Quaternion APIDTarget { set { return; } }
241 public override bool APIDActive { set { return; } }
242 public override float APIDStrength { set { return; } }
243 public override float APIDDamping { set { return; } }
244
245 // The current velocity forward
246 public virtual float ForwardSpeed
247 {
248 get
249 {
250 OMV.Vector3 characterOrientedVelocity = RawVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
251 return characterOrientedVelocity.X;
252 }
253 }
254 // The forward speed we are trying to achieve (TargetVelocity)
255 public virtual float TargetVelocitySpeed
256 {
257 get
258 {
259 OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
260 return characterOrientedVelocity.X;
261 }
262 }
263
264 // The user can optionally set the center of mass. The user's setting will override any
265 // computed center-of-mass (like in linksets).
266 // Note this is a displacement from the root's coordinates. Zero means use the root prim as center-of-mass.
267 public OMV.Vector3? UserSetCenterOfMassDisplacement { get; set; }
268
269 public OMV.Vector3 LockedLinearAxis { get; set; } // zero means locked. one means free.
270 public OMV.Vector3 LockedAngularAxis { get; set; } // zero means locked. one means free.
271 public const float FreeAxis = 1f;
272 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(FreeAxis, FreeAxis, FreeAxis); // All axis are free
273
274 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
275 // they need waking up when parameters are changed.
276 // Called in taint-time!!
277 public void ActivateIfPhysical(bool forceIt)
278 {
279 if (IsPhysical && PhysBody.HasPhysicalBody)
280 PhysScene.PE.Activate(PhysBody, forceIt);
281 }
282
283 // 'actors' act on the physical object to change or constrain its motion. These can range from
284 // hovering to complex vehicle motion.
285 // May be called at non-taint time as this just adds the actor to the action list and the real
286 // work is done during the simulation step.
287 // Note that, if the actor is already in the list and we are disabling same, the actor is just left
288 // in the list disabled.
289 public delegate BSActor CreateActor();
290 public void EnableActor(bool enableActor, string actorName, CreateActor creator)
291 {
292 lock (PhysicalActors)
293 {
294 BSActor theActor;
295 if (PhysicalActors.TryGetActor(actorName, out theActor))
296 {
297 // The actor already exists so just turn it on or off
298 DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
299 theActor.Enabled = enableActor;
300 }
301 else
302 {
303 // The actor does not exist. If it should, create it.
304 if (enableActor)
305 {
306 DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
307 theActor = creator();
308 PhysicalActors.Add(actorName, theActor);
309 theActor.Enabled = true;
310 }
311 else
312 {
313 DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
314 }
315 }
316 }
317 }
318
180 #region Collisions 319 #region Collisions
181 320
182 // Requested number of milliseconds between collision events. Zero means disabled. 321 // Requested number of milliseconds between collision events. Zero means disabled.
@@ -191,41 +330,56 @@ public abstract class BSPhysObject : PhysicsActor
191 protected long CollidingObjectStep { get; set; } 330 protected long CollidingObjectStep { get; set; }
192 // The collision flags we think are set in Bullet 331 // The collision flags we think are set in Bullet
193 protected CollisionFlags CurrentCollisionFlags { get; set; } 332 protected CollisionFlags CurrentCollisionFlags { get; set; }
333 // On a collision, check the collider and remember if the last collider was moving
334 // Used to modify the standing of avatars (avatars on stationary things stand still)
335 public bool ColliderIsMoving;
336 // Used by BSCharacter to manage standing (and not slipping)
337 public bool IsStationary;
338
339 // Count of collisions for this object
340 protected long CollisionAccumulation { get; set; }
194 341
195 public override bool IsColliding { 342 public override bool IsColliding {
196 get { return (CollidingStep == PhysicsScene.SimulationStep); } 343 get { return (CollidingStep == PhysScene.SimulationStep); }
197 set { 344 set {
198 if (value) 345 if (value)
199 CollidingStep = PhysicsScene.SimulationStep; 346 CollidingStep = PhysScene.SimulationStep;
200 else 347 else
201 CollidingStep = 0; 348 CollidingStep = 0;
202 } 349 }
203 } 350 }
204 public override bool CollidingGround { 351 public override bool CollidingGround {
205 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 352 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
206 set 353 set
207 { 354 {
208 if (value) 355 if (value)
209 CollidingGroundStep = PhysicsScene.SimulationStep; 356 CollidingGroundStep = PhysScene.SimulationStep;
210 else 357 else
211 CollidingGroundStep = 0; 358 CollidingGroundStep = 0;
212 } 359 }
213 } 360 }
214 public override bool CollidingObj { 361 public override bool CollidingObj {
215 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 362 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
216 set { 363 set {
217 if (value) 364 if (value)
218 CollidingObjectStep = PhysicsScene.SimulationStep; 365 CollidingObjectStep = PhysScene.SimulationStep;
219 else 366 else
220 CollidingObjectStep = 0; 367 CollidingObjectStep = 0;
221 } 368 }
222 } 369 }
223 370
224 // The collisions that have been collected this tick 371 // The collisions that have been collected for the next collision reporting (throttled by subscription)
225 protected CollisionEventUpdate CollisionCollection; 372 protected CollisionEventUpdate CollisionCollection;
373 // This is the collision collection last reported to the Simulator.
374 public CollisionEventUpdate CollisionsLastReported;
375 // Remember the collisions recorded in the last tick for fancy collision checking
376 // (like a BSCharacter walking up stairs).
377 public CollisionEventUpdate CollisionsLastTick;
378 private long CollisionsLastTickStep = -1;
226 379
227 // The simulation step is telling this object about a collision. 380 // The simulation step is telling this object about a collision.
228 // Return 'true' if a collision was processed and should be sent up. 381 // Return 'true' if a collision was processed and should be sent up.
382 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
229 // Called at taint time from within the Step() function 383 // Called at taint time from within the Step() function
230 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 384 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
231 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 385 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
@@ -233,27 +387,35 @@ public abstract class BSPhysObject : PhysicsActor
233 bool ret = false; 387 bool ret = false;
234 388
235 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 389 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
236 CollidingStep = PhysicsScene.SimulationStep; 390 CollidingStep = PhysScene.SimulationStep;
237 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 391 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
238 { 392 {
239 CollidingGroundStep = PhysicsScene.SimulationStep; 393 CollidingGroundStep = PhysScene.SimulationStep;
240 } 394 }
241 else 395 else
242 { 396 {
243 CollidingObjectStep = PhysicsScene.SimulationStep; 397 CollidingObjectStep = PhysScene.SimulationStep;
244 } 398 }
245 399
246 // prims in the same linkset cannot collide with each other 400 CollisionAccumulation++;
247 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) 401
402 // For movement tests, remember if we are colliding with an object that is moving.
403 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
404
405 // Make a collection of the collisions that happened the last simulation tick.
406 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
407 if (CollisionsLastTickStep != PhysScene.SimulationStep)
248 { 408 {
249 return ret; 409 CollisionsLastTick = new CollisionEventUpdate();
410 CollisionsLastTickStep = PhysScene.SimulationStep;
250 } 411 }
412 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
251 413
252 // if someone has subscribed for collision events.... 414 // If someone has subscribed for collision events log the collision so it will be reported up
253 if (SubscribedEvents()) { 415 if (SubscribedEvents()) {
254 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 416 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
255 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", 417 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5},colliderMoving={6}",
256 LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); 418 LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth, ColliderIsMoving);
257 419
258 ret = true; 420 ret = true;
259 } 421 }
@@ -267,13 +429,14 @@ public abstract class BSPhysObject : PhysicsActor
267 public virtual bool SendCollisions() 429 public virtual bool SendCollisions()
268 { 430 {
269 bool ret = true; 431 bool ret = true;
432
270 // If the 'no collision' call, force it to happen right now so quick collision_end 433 // If the 'no collision' call, force it to happen right now so quick collision_end
271 bool force = (CollisionCollection.Count == 0); 434 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
272 435
273 // throttle the collisions to the number of milliseconds specified in the subscription 436 // throttle the collisions to the number of milliseconds specified in the subscription
274 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 437 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
275 { 438 {
276 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 439 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
277 440
278 // We are called if we previously had collisions. If there are no collisions 441 // We are called if we previously had collisions. If there are no collisions
279 // this time, send up one last empty event so OpenSim can sense collision end. 442 // this time, send up one last empty event so OpenSim can sense collision end.
@@ -283,12 +446,15 @@ public abstract class BSPhysObject : PhysicsActor
283 ret = false; 446 ret = false;
284 } 447 }
285 448
286 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); 449 DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
287 base.SendCollisionUpdate(CollisionCollection); 450 base.SendCollisionUpdate(CollisionCollection);
288 451
452 // Remember the collisions from this tick for some collision specific processing.
453 CollisionsLastReported = CollisionCollection;
454
289 // The CollisionCollection instance is passed around in the simulator. 455 // The CollisionCollection instance is passed around in the simulator.
290 // Make sure we don't have a handle to that one and that a new one is used for next time. 456 // Make sure we don't have a handle to that one and that a new one is used for next time.
291 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, 457 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
292 // a race condition is created for the other users of this instance. 458 // a race condition is created for the other users of this instance.
293 CollisionCollection = new CollisionEventUpdate(); 459 CollisionCollection = new CollisionEventUpdate();
294 } 460 }
@@ -305,10 +471,10 @@ public abstract class BSPhysObject : PhysicsActor
305 // make sure first collision happens 471 // make sure first collision happens
306 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 472 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
307 473
308 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 474 PhysScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
309 { 475 {
310 if (PhysBody.HasPhysicalBody) 476 if (PhysBody.HasPhysicalBody)
311 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 477 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
312 }); 478 });
313 } 479 }
314 else 480 else
@@ -320,66 +486,53 @@ public abstract class BSPhysObject : PhysicsActor
320 public override void UnSubscribeEvents() { 486 public override void UnSubscribeEvents() {
321 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 487 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
322 SubscribedEventsMs = 0; 488 SubscribedEventsMs = 0;
323 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 489 PhysScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
324 { 490 {
325 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 491 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
326 if (PhysBody.HasPhysicalBody) 492 if (PhysBody.HasPhysicalBody)
327 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 493 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
328 }); 494 });
329 } 495 }
330 // Return 'true' if the simulator wants collision events 496 // Return 'true' if the simulator wants collision events
331 public override bool SubscribedEvents() { 497 public override bool SubscribedEvents() {
332 return (SubscribedEventsMs > 0); 498 return (SubscribedEventsMs > 0);
333 } 499 }
500 // Because 'CollisionScore' is called many times while sorting, it should not be recomputed
501 // each time called. So this is built to be light weight for each collision and to do
502 // all the processing when the user asks for the info.
503 public void ComputeCollisionScore()
504 {
505 // Scale the collision count by the time since the last collision.
506 // The "+1" prevents dividing by zero.
507 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
508 CollisionScore = CollisionAccumulation / timeAgo;
509 }
510 public override float CollisionScore { get; set; }
334 511
335 #endregion // Collisions 512 #endregion // Collisions
336 513
337 #region Per Simulation Step actions 514 #region Per Simulation Step actions
338 // There are some actions that must be performed for a physical object before each simulation step.
339 // These actions are optional so, rather than scanning all the physical objects and asking them
340 // if they have anything to do, a physical object registers for an event call before the step is performed.
341 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
342 private Dictionary<string, BSScene.PreStepAction> RegisteredActions = new Dictionary<string, BSScene.PreStepAction>();
343 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
344 {
345 string identifier = op + "-" + id.ToString();
346 RegisteredActions[identifier] = actn;
347 PhysicsScene.BeforeStep += actn;
348 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
349 }
350 515
351 // Unregister a pre step action. Safe to call if the action has not been registered. 516 public BSActorCollection PhysicalActors;
352 protected void UnRegisterPreStepAction(string op, uint id)
353 {
354 string identifier = op + "-" + id.ToString();
355 bool removed = false;
356 if (RegisteredActions.ContainsKey(identifier))
357 {
358 PhysicsScene.BeforeStep -= RegisteredActions[identifier];
359 RegisteredActions.Remove(identifier);
360 removed = true;
361 }
362 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
363 }
364 517
365 protected void UnRegisterAllPreStepActions() 518 // When an update to the physical properties happens, this event is fired to let
519 // different actors to modify the update before it is passed around
520 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
521 public event PreUpdatePropertyAction OnPreUpdateProperty;
522 protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop)
366 { 523 {
367 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions) 524 PreUpdatePropertyAction actions = OnPreUpdateProperty;
368 { 525 if (actions != null)
369 PhysicsScene.BeforeStep -= kvp.Value; 526 actions(ref entprop);
370 }
371 RegisteredActions.Clear();
372 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
373 } 527 }
374 528
375
376 #endregion // Per Simulation Step actions 529 #endregion // Per Simulation Step actions
377 530
378 // High performance detailed logging routine used by the physical objects. 531 // High performance detailed logging routine used by the physical objects.
379 protected void DetailLog(string msg, params Object[] args) 532 protected void DetailLog(string msg, params Object[] args)
380 { 533 {
381 if (PhysicsScene.PhysicsLogging.Enabled) 534 if (PhysScene.PhysicsLogging.Enabled)
382 PhysicsScene.DetailLog(msg, args); 535 PhysScene.DetailLog(msg, args);
383 } 536 }
384 537
385} 538}