diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 147 |
1 files changed, 137 insertions, 10 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index f6a890e..534f929 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -45,6 +45,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
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 two (and certainly the last one) should be referenced only in taint-time. |
47 | */ | 47 | */ |
48 | |||
49 | /* | ||
50 | * As of 20121221, the following are the call sequences (going down) for different script physical functions: | ||
51 | * llApplyImpulse llApplyRotImpulse llSetTorque llSetForce | ||
52 | * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce | ||
53 | * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse | ||
54 | * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v | ||
55 | * BS.ApplyCentralForce BS.ApplyTorque | ||
56 | */ | ||
57 | |||
48 | public abstract class BSPhysObject : PhysicsActor | 58 | public abstract class BSPhysObject : PhysicsActor |
49 | { | 59 | { |
50 | protected BSPhysObject() | 60 | protected BSPhysObject() |
@@ -57,26 +67,42 @@ public abstract class BSPhysObject : PhysicsActor | |||
57 | PhysObjectName = name; | 67 | PhysObjectName = name; |
58 | TypeName = typeName; | 68 | TypeName = typeName; |
59 | 69 | ||
70 | // We don't have any physical representation yet. | ||
71 | PhysBody = new BulletBody(localID); | ||
72 | PhysShape = new BulletShape(); | ||
73 | |||
74 | // A linkset of just me | ||
60 | Linkset = BSLinkset.Factory(PhysicsScene, this); | 75 | Linkset = BSLinkset.Factory(PhysicsScene, this); |
61 | LastAssetBuildFailed = false; | 76 | LastAssetBuildFailed = false; |
62 | 77 | ||
78 | // Default material type | ||
79 | Material = MaterialAttributes.Material.Wood; | ||
80 | |||
63 | CollisionCollection = new CollisionEventUpdate(); | 81 | CollisionCollection = new CollisionEventUpdate(); |
64 | SubscribedEventsMs = 0; | 82 | SubscribedEventsMs = 0; |
65 | CollidingStep = 0; | 83 | CollidingStep = 0; |
66 | CollidingGroundStep = 0; | 84 | CollidingGroundStep = 0; |
67 | } | 85 | } |
68 | 86 | ||
87 | // Tell the object to clean up. | ||
88 | public virtual void Destroy() | ||
89 | { | ||
90 | UnRegisterAllPreStepActions(); | ||
91 | } | ||
92 | |||
69 | public BSScene PhysicsScene { get; protected set; } | 93 | public BSScene PhysicsScene { get; protected set; } |
70 | // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor | 94 | // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor |
71 | public string PhysObjectName { get; protected set; } | 95 | public string PhysObjectName { get; protected set; } |
72 | public string TypeName { get; protected set; } | 96 | public string TypeName { get; protected set; } |
73 | 97 | ||
74 | public BSLinkset Linkset { get; set; } | 98 | public BSLinkset Linkset { get; set; } |
99 | public BSLinksetInfo LinksetInfo { get; set; } | ||
75 | 100 | ||
76 | // Return the object mass without calculating it or having side effects | 101 | // Return the object mass without calculating it or having side effects |
77 | public abstract float RawMass { get; } | 102 | public abstract float RawMass { get; } |
78 | // Set the raw mass but also update physical mass properties (inertia, ...) | 103 | // Set the raw mass but also update physical mass properties (inertia, ...) |
79 | public abstract void UpdatePhysicalMassProperties(float mass); | 104 | // 'inWorld' true if the object has already been added to the dynamic world. |
105 | public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld); | ||
80 | 106 | ||
81 | // The last value calculated for the prim's inertia | 107 | // The last value calculated for the prim's inertia |
82 | public OMV.Vector3 Inertia { get; set; } | 108 | public OMV.Vector3 Inertia { get; set; } |
@@ -105,10 +131,17 @@ public abstract class BSPhysObject : PhysicsActor | |||
105 | public EntityProperties CurrentEntityProperties { get; set; } | 131 | public EntityProperties CurrentEntityProperties { get; set; } |
106 | public EntityProperties LastEntityProperties { get; set; } | 132 | public EntityProperties LastEntityProperties { get; set; } |
107 | 133 | ||
108 | public abstract OMV.Vector3 Scale { get; set; } | 134 | public virtual OMV.Vector3 Scale { get; set; } |
109 | public abstract bool IsSolid { get; } | 135 | public abstract bool IsSolid { get; } |
110 | public abstract bool IsStatic { get; } | 136 | public abstract bool IsStatic { get; } |
111 | 137 | ||
138 | // Materialness | ||
139 | public MaterialAttributes.Material Material { get; private set; } | ||
140 | public override void SetMaterial(int material) | ||
141 | { | ||
142 | Material = (MaterialAttributes.Material)material; | ||
143 | } | ||
144 | |||
112 | // Stop all physical motion. | 145 | // Stop all physical motion. |
113 | public abstract void ZeroMotion(bool inTaintTime); | 146 | public abstract void ZeroMotion(bool inTaintTime); |
114 | public abstract void ZeroAngularMotion(bool inTaintTime); | 147 | public abstract void ZeroAngularMotion(bool inTaintTime); |
@@ -119,15 +152,23 @@ public abstract class BSPhysObject : PhysicsActor | |||
119 | // Update the physical location and motion of the object. Called with data from Bullet. | 152 | // Update the physical location and motion of the object. Called with data from Bullet. |
120 | public abstract void UpdateProperties(EntityProperties entprop); | 153 | public abstract void UpdateProperties(EntityProperties entprop); |
121 | 154 | ||
122 | // Tell the object to clean up. | ||
123 | public abstract void Destroy(); | ||
124 | |||
125 | public abstract OMV.Vector3 RawPosition { get; set; } | 155 | public abstract OMV.Vector3 RawPosition { get; set; } |
126 | public abstract OMV.Vector3 ForcePosition { get; set; } | 156 | public abstract OMV.Vector3 ForcePosition { get; set; } |
127 | 157 | ||
128 | public abstract OMV.Quaternion RawOrientation { get; set; } | 158 | public abstract OMV.Quaternion RawOrientation { get; set; } |
129 | public abstract OMV.Quaternion ForceOrientation { get; set; } | 159 | public abstract OMV.Quaternion ForceOrientation { get; set; } |
130 | 160 | ||
161 | // The system is telling us the velocity it wants to move at. | ||
162 | // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor | ||
163 | public override OMV.Vector3 TargetVelocity | ||
164 | { | ||
165 | get { return m_targetVelocity; } | ||
166 | set | ||
167 | { | ||
168 | m_targetVelocity = value; | ||
169 | Velocity = value; | ||
170 | } | ||
171 | } | ||
131 | public abstract OMV.Vector3 ForceVelocity { get; set; } | 172 | public abstract OMV.Vector3 ForceVelocity { get; set; } |
132 | 173 | ||
133 | public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } | 174 | public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } |
@@ -146,9 +187,40 @@ public abstract class BSPhysObject : PhysicsActor | |||
146 | protected long CollidingStep { get; set; } | 187 | protected long CollidingStep { get; set; } |
147 | // The simulation step that last had a collision with the ground | 188 | // The simulation step that last had a collision with the ground |
148 | protected long CollidingGroundStep { get; set; } | 189 | protected long CollidingGroundStep { get; set; } |
190 | // The simulation step that last collided with an object | ||
191 | protected long CollidingObjectStep { get; set; } | ||
149 | // The collision flags we think are set in Bullet | 192 | // The collision flags we think are set in Bullet |
150 | protected CollisionFlags CurrentCollisionFlags { get; set; } | 193 | protected CollisionFlags CurrentCollisionFlags { get; set; } |
151 | 194 | ||
195 | public override bool IsColliding { | ||
196 | get { return (CollidingStep == PhysicsScene.SimulationStep); } | ||
197 | set { | ||
198 | if (value) | ||
199 | CollidingStep = PhysicsScene.SimulationStep; | ||
200 | else | ||
201 | CollidingStep = 0; | ||
202 | } | ||
203 | } | ||
204 | public override bool CollidingGround { | ||
205 | get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } | ||
206 | set | ||
207 | { | ||
208 | if (value) | ||
209 | CollidingGroundStep = PhysicsScene.SimulationStep; | ||
210 | else | ||
211 | CollidingGroundStep = 0; | ||
212 | } | ||
213 | } | ||
214 | public override bool CollidingObj { | ||
215 | get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } | ||
216 | set { | ||
217 | if (value) | ||
218 | CollidingObjectStep = PhysicsScene.SimulationStep; | ||
219 | else | ||
220 | CollidingObjectStep = 0; | ||
221 | } | ||
222 | } | ||
223 | |||
152 | // The collisions that have been collected this tick | 224 | // The collisions that have been collected this tick |
153 | protected CollisionEventUpdate CollisionCollection; | 225 | protected CollisionEventUpdate CollisionCollection; |
154 | 226 | ||
@@ -160,12 +232,16 @@ public abstract class BSPhysObject : PhysicsActor | |||
160 | { | 232 | { |
161 | bool ret = false; | 233 | bool ret = false; |
162 | 234 | ||
163 | // The following lines make IsColliding() and IsCollidingGround() work | 235 | // The following lines make IsColliding(), CollidingGround() and CollidingObj work |
164 | CollidingStep = PhysicsScene.SimulationStep; | 236 | CollidingStep = PhysicsScene.SimulationStep; |
165 | if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) | 237 | if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) |
166 | { | 238 | { |
167 | CollidingGroundStep = PhysicsScene.SimulationStep; | 239 | CollidingGroundStep = PhysicsScene.SimulationStep; |
168 | } | 240 | } |
241 | else | ||
242 | { | ||
243 | CollidingObjectStep = PhysicsScene.SimulationStep; | ||
244 | } | ||
169 | 245 | ||
170 | // prims in the same linkset cannot collide with each other | 246 | // prims in the same linkset cannot collide with each other |
171 | if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) | 247 | if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) |
@@ -192,7 +268,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
192 | { | 268 | { |
193 | bool ret = true; | 269 | bool ret = true; |
194 | // If the 'no collision' call, force it to happen right now so quick collision_end | 270 | // If the 'no collision' call, force it to happen right now so quick collision_end |
195 | bool force = CollisionCollection.Count == 0; | 271 | bool force = (CollisionCollection.Count == 0); |
196 | 272 | ||
197 | // throttle the collisions to the number of milliseconds specified in the subscription | 273 | // throttle the collisions to the number of milliseconds specified in the subscription |
198 | if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) | 274 | if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) |
@@ -210,8 +286,10 @@ public abstract class BSPhysObject : PhysicsActor | |||
210 | // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); | 286 | // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); |
211 | base.SendCollisionUpdate(CollisionCollection); | 287 | base.SendCollisionUpdate(CollisionCollection); |
212 | 288 | ||
213 | // The collisionCollection structure is passed around in the simulator. | 289 | // The CollisionCollection instance is passed around in the simulator. |
214 | // Make sure we don't have a handle to that one and that a new one is used for next time. | 290 | // 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, | ||
292 | // a race condition is created for the other users of this instance. | ||
215 | CollisionCollection = new CollisionEventUpdate(); | 293 | CollisionCollection = new CollisionEventUpdate(); |
216 | } | 294 | } |
217 | return ret; | 295 | return ret; |
@@ -229,7 +307,8 @@ public abstract class BSPhysObject : PhysicsActor | |||
229 | 307 | ||
230 | PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() | 308 | PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() |
231 | { | 309 | { |
232 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 310 | if (PhysBody.HasPhysicalBody) |
311 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
233 | }); | 312 | }); |
234 | } | 313 | } |
235 | else | 314 | else |
@@ -243,7 +322,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
243 | SubscribedEventsMs = 0; | 322 | SubscribedEventsMs = 0; |
244 | PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() | 323 | PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() |
245 | { | 324 | { |
246 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 325 | // Make sure there is a body there because sometimes destruction happens in an un-ideal order. |
326 | if (PhysBody.HasPhysicalBody) | ||
327 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
247 | }); | 328 | }); |
248 | } | 329 | } |
249 | // Return 'true' if the simulator wants collision events | 330 | // Return 'true' if the simulator wants collision events |
@@ -253,11 +334,57 @@ public abstract class BSPhysObject : PhysicsActor | |||
253 | 334 | ||
254 | #endregion // Collisions | 335 | #endregion // Collisions |
255 | 336 | ||
337 | #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 | |||
347 | // Clean out any existing action | ||
348 | UnRegisterPreStepAction(op, id); | ||
349 | |||
350 | RegisteredActions[identifier] = actn; | ||
351 | PhysicsScene.BeforeStep += actn; | ||
352 | DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); | ||
353 | } | ||
354 | |||
355 | // Unregister a pre step action. Safe to call if the action has not been registered. | ||
356 | protected void UnRegisterPreStepAction(string op, uint id) | ||
357 | { | ||
358 | string identifier = op + "-" + id.ToString(); | ||
359 | bool removed = false; | ||
360 | if (RegisteredActions.ContainsKey(identifier)) | ||
361 | { | ||
362 | PhysicsScene.BeforeStep -= RegisteredActions[identifier]; | ||
363 | RegisteredActions.Remove(identifier); | ||
364 | removed = true; | ||
365 | } | ||
366 | DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed); | ||
367 | } | ||
368 | |||
369 | protected void UnRegisterAllPreStepActions() | ||
370 | { | ||
371 | foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions) | ||
372 | { | ||
373 | PhysicsScene.BeforeStep -= kvp.Value; | ||
374 | } | ||
375 | RegisteredActions.Clear(); | ||
376 | DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID); | ||
377 | } | ||
378 | |||
379 | |||
380 | #endregion // Per Simulation Step actions | ||
381 | |||
256 | // High performance detailed logging routine used by the physical objects. | 382 | // High performance detailed logging routine used by the physical objects. |
257 | protected void DetailLog(string msg, params Object[] args) | 383 | protected void DetailLog(string msg, params Object[] args) |
258 | { | 384 | { |
259 | if (PhysicsScene.PhysicsLogging.Enabled) | 385 | if (PhysicsScene.PhysicsLogging.Enabled) |
260 | PhysicsScene.DetailLog(msg, args); | 386 | PhysicsScene.DetailLog(msg, args); |
261 | } | 387 | } |
388 | |||
262 | } | 389 | } |
263 | } | 390 | } |