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.cs194
1 files changed, 184 insertions, 10 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index f6a890e..821f470 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
48public abstract class BSPhysObject : PhysicsActor 58public abstract class BSPhysObject : PhysicsActor
49{ 59{
50 protected BSPhysObject() 60 protected BSPhysObject()
@@ -57,26 +67,45 @@ 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);
76 PositionDisplacement = OMV.Vector3.Zero;
77
61 LastAssetBuildFailed = false; 78 LastAssetBuildFailed = false;
62 79
80 // Default material type
81 Material = MaterialAttributes.Material.Wood;
82
63 CollisionCollection = new CollisionEventUpdate(); 83 CollisionCollection = new CollisionEventUpdate();
84 CollisionsLastTick = CollisionCollection;
64 SubscribedEventsMs = 0; 85 SubscribedEventsMs = 0;
65 CollidingStep = 0; 86 CollidingStep = 0;
66 CollidingGroundStep = 0; 87 CollidingGroundStep = 0;
67 } 88 }
68 89
90 // Tell the object to clean up.
91 public virtual void Destroy()
92 {
93 UnRegisterAllPreStepActions();
94 }
95
69 public BSScene PhysicsScene { get; protected set; } 96 public BSScene PhysicsScene { get; protected set; }
70 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 97 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
71 public string PhysObjectName { get; protected set; } 98 public string PhysObjectName { get; protected set; }
72 public string TypeName { get; protected set; } 99 public string TypeName { get; protected set; }
73 100
74 public BSLinkset Linkset { get; set; } 101 public BSLinkset Linkset { get; set; }
102 public BSLinksetInfo LinksetInfo { get; set; }
75 103
76 // Return the object mass without calculating it or having side effects 104 // Return the object mass without calculating it or having side effects
77 public abstract float RawMass { get; } 105 public abstract float RawMass { get; }
78 // Set the raw mass but also update physical mass properties (inertia, ...) 106 // Set the raw mass but also update physical mass properties (inertia, ...)
79 public abstract void UpdatePhysicalMassProperties(float mass); 107 // 'inWorld' true if the object has already been added to the dynamic world.
108 public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld);
80 109
81 // The last value calculated for the prim's inertia 110 // The last value calculated for the prim's inertia
82 public OMV.Vector3 Inertia { get; set; } 111 public OMV.Vector3 Inertia { get; set; }
@@ -105,9 +134,17 @@ public abstract class BSPhysObject : PhysicsActor
105 public EntityProperties CurrentEntityProperties { get; set; } 134 public EntityProperties CurrentEntityProperties { get; set; }
106 public EntityProperties LastEntityProperties { get; set; } 135 public EntityProperties LastEntityProperties { get; set; }
107 136
108 public abstract OMV.Vector3 Scale { get; set; } 137 public virtual OMV.Vector3 Scale { get; set; }
109 public abstract bool IsSolid { get; } 138 public abstract bool IsSolid { get; }
110 public abstract bool IsStatic { get; } 139 public abstract bool IsStatic { get; }
140 public abstract bool IsSelected { get; }
141
142 // Materialness
143 public MaterialAttributes.Material Material { get; private set; }
144 public override void SetMaterial(int material)
145 {
146 Material = (MaterialAttributes.Material)material;
147 }
111 148
112 // Stop all physical motion. 149 // Stop all physical motion.
113 public abstract void ZeroMotion(bool inTaintTime); 150 public abstract void ZeroMotion(bool inTaintTime);
@@ -119,15 +156,41 @@ public abstract class BSPhysObject : PhysicsActor
119 // Update the physical location and motion of the object. Called with data from Bullet. 156 // Update the physical location and motion of the object. Called with data from Bullet.
120 public abstract void UpdateProperties(EntityProperties entprop); 157 public abstract void UpdateProperties(EntityProperties entprop);
121 158
122 // Tell the object to clean up.
123 public abstract void Destroy();
124
125 public abstract OMV.Vector3 RawPosition { get; set; } 159 public abstract OMV.Vector3 RawPosition { get; set; }
126 public abstract OMV.Vector3 ForcePosition { get; set; } 160 public abstract OMV.Vector3 ForcePosition { get; set; }
127 161
162 // Position is what the simulator thinks the positions of the prim is.
163 // Because Bullet needs the zero coordinate to be the center of mass of the linkset,
164 // sometimes it is necessary to displace the position the physics engine thinks
165 // the position is. PositionDisplacement must be added and removed from the
166 // position as the simulator position is stored and fetched from the physics
167 // engine.
168 public virtual OMV.Vector3 PositionDisplacement { get; set; }
169
128 public abstract OMV.Quaternion RawOrientation { get; set; } 170 public abstract OMV.Quaternion RawOrientation { get; set; }
129 public abstract OMV.Quaternion ForceOrientation { get; set; } 171 public abstract OMV.Quaternion ForceOrientation { get; set; }
130 172
173 // The system is telling us the velocity it wants to move at.
174 // Velocity in world coordinates.
175 // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor
176 public override OMV.Vector3 TargetVelocity
177 {
178 get { return m_targetVelocity; }
179 set
180 {
181 m_targetVelocity = value;
182 Velocity = value;
183 }
184 }
185 public virtual float TargetSpeed
186 {
187 get
188 {
189 OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
190 return characterOrientedVelocity.X;
191 }
192 }
193 public abstract OMV.Vector3 RawVelocity { get; set; }
131 public abstract OMV.Vector3 ForceVelocity { get; set; } 194 public abstract OMV.Vector3 ForceVelocity { get; set; }
132 195
133 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 196 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
@@ -136,6 +199,15 @@ public abstract class BSPhysObject : PhysicsActor
136 199
137 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 200 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
138 201
202 public virtual float ForwardSpeed
203 {
204 get
205 {
206 OMV.Vector3 characterOrientedVelocity = RawVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
207 return characterOrientedVelocity.X;
208 }
209 }
210
139 #region Collisions 211 #region Collisions
140 212
141 // Requested number of milliseconds between collision events. Zero means disabled. 213 // Requested number of milliseconds between collision events. Zero means disabled.
@@ -146,26 +218,65 @@ public abstract class BSPhysObject : PhysicsActor
146 protected long CollidingStep { get; set; } 218 protected long CollidingStep { get; set; }
147 // The simulation step that last had a collision with the ground 219 // The simulation step that last had a collision with the ground
148 protected long CollidingGroundStep { get; set; } 220 protected long CollidingGroundStep { get; set; }
221 // The simulation step that last collided with an object
222 protected long CollidingObjectStep { get; set; }
149 // The collision flags we think are set in Bullet 223 // The collision flags we think are set in Bullet
150 protected CollisionFlags CurrentCollisionFlags { get; set; } 224 protected CollisionFlags CurrentCollisionFlags { get; set; }
151 225
226 public override bool IsColliding {
227 get { return (CollidingStep == PhysicsScene.SimulationStep); }
228 set {
229 if (value)
230 CollidingStep = PhysicsScene.SimulationStep;
231 else
232 CollidingStep = 0;
233 }
234 }
235 public override bool CollidingGround {
236 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
237 set
238 {
239 if (value)
240 CollidingGroundStep = PhysicsScene.SimulationStep;
241 else
242 CollidingGroundStep = 0;
243 }
244 }
245 public override bool CollidingObj {
246 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); }
247 set {
248 if (value)
249 CollidingObjectStep = PhysicsScene.SimulationStep;
250 else
251 CollidingObjectStep = 0;
252 }
253 }
254
152 // The collisions that have been collected this tick 255 // The collisions that have been collected this tick
153 protected CollisionEventUpdate CollisionCollection; 256 protected CollisionEventUpdate CollisionCollection;
257 // Remember collisions from last tick for fancy collision based actions
258 // (like a BSCharacter walking up stairs).
259 protected CollisionEventUpdate CollisionsLastTick;
154 260
155 // The simulation step is telling this object about a collision. 261 // The simulation step is telling this object about a collision.
156 // Return 'true' if a collision was processed and should be sent up. 262 // Return 'true' if a collision was processed and should be sent up.
263 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
157 // Called at taint time from within the Step() function 264 // Called at taint time from within the Step() function
158 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 265 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
159 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 266 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
160 { 267 {
161 bool ret = false; 268 bool ret = false;
162 269
163 // The following lines make IsColliding() and IsCollidingGround() work 270 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
164 CollidingStep = PhysicsScene.SimulationStep; 271 CollidingStep = PhysicsScene.SimulationStep;
165 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 272 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
166 { 273 {
167 CollidingGroundStep = PhysicsScene.SimulationStep; 274 CollidingGroundStep = PhysicsScene.SimulationStep;
168 } 275 }
276 else
277 {
278 CollidingObjectStep = PhysicsScene.SimulationStep;
279 }
169 280
170 // prims in the same linkset cannot collide with each other 281 // prims in the same linkset cannot collide with each other
171 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) 282 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
@@ -192,7 +303,7 @@ public abstract class BSPhysObject : PhysicsActor
192 { 303 {
193 bool ret = true; 304 bool ret = true;
194 // If the 'no collision' call, force it to happen right now so quick collision_end 305 // If the 'no collision' call, force it to happen right now so quick collision_end
195 bool force = CollisionCollection.Count == 0; 306 bool force = (CollisionCollection.Count == 0);
196 307
197 // throttle the collisions to the number of milliseconds specified in the subscription 308 // throttle the collisions to the number of milliseconds specified in the subscription
198 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 309 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
@@ -210,8 +321,13 @@ public abstract class BSPhysObject : PhysicsActor
210 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); 321 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
211 base.SendCollisionUpdate(CollisionCollection); 322 base.SendCollisionUpdate(CollisionCollection);
212 323
213 // The collisionCollection structure is passed around in the simulator. 324 // Remember the collisions from this tick for some collision specific processing.
325 CollisionsLastTick = CollisionCollection;
326
327 // 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. 328 // Make sure we don't have a handle to that one and that a new one is used for next time.
329 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
330 // a race condition is created for the other users of this instance.
215 CollisionCollection = new CollisionEventUpdate(); 331 CollisionCollection = new CollisionEventUpdate();
216 } 332 }
217 return ret; 333 return ret;
@@ -229,7 +345,8 @@ public abstract class BSPhysObject : PhysicsActor
229 345
230 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 346 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
231 { 347 {
232 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 348 if (PhysBody.HasPhysicalBody)
349 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
233 }); 350 });
234 } 351 }
235 else 352 else
@@ -243,7 +360,9 @@ public abstract class BSPhysObject : PhysicsActor
243 SubscribedEventsMs = 0; 360 SubscribedEventsMs = 0;
244 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 361 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
245 { 362 {
246 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 363 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
364 if (PhysBody.HasPhysicalBody)
365 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
247 }); 366 });
248 } 367 }
249 // Return 'true' if the simulator wants collision events 368 // Return 'true' if the simulator wants collision events
@@ -253,11 +372,66 @@ public abstract class BSPhysObject : PhysicsActor
253 372
254 #endregion // Collisions 373 #endregion // Collisions
255 374
375 #region Per Simulation Step actions
376 // There are some actions that must be performed for a physical object before each simulation step.
377 // These actions are optional so, rather than scanning all the physical objects and asking them
378 // if they have anything to do, a physical object registers for an event call before the step is performed.
379 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
380 private Dictionary<string, BSScene.PreStepAction> RegisteredActions = new Dictionary<string, BSScene.PreStepAction>();
381 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
382 {
383 string identifier = op + "-" + id.ToString();
384
385 lock (RegisteredActions)
386 {
387 // Clean out any existing action
388 UnRegisterPreStepAction(op, id);
389
390 RegisteredActions[identifier] = actn;
391 }
392 PhysicsScene.BeforeStep += actn;
393 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
394 }
395
396 // Unregister a pre step action. Safe to call if the action has not been registered.
397 protected void UnRegisterPreStepAction(string op, uint id)
398 {
399 string identifier = op + "-" + id.ToString();
400 bool removed = false;
401 lock (RegisteredActions)
402 {
403 if (RegisteredActions.ContainsKey(identifier))
404 {
405 PhysicsScene.BeforeStep -= RegisteredActions[identifier];
406 RegisteredActions.Remove(identifier);
407 removed = true;
408 }
409 }
410 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
411 }
412
413 protected void UnRegisterAllPreStepActions()
414 {
415 lock (RegisteredActions)
416 {
417 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
418 {
419 PhysicsScene.BeforeStep -= kvp.Value;
420 }
421 RegisteredActions.Clear();
422 }
423 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
424 }
425
426
427 #endregion // Per Simulation Step actions
428
256 // High performance detailed logging routine used by the physical objects. 429 // High performance detailed logging routine used by the physical objects.
257 protected void DetailLog(string msg, params Object[] args) 430 protected void DetailLog(string msg, params Object[] args)
258 { 431 {
259 if (PhysicsScene.PhysicsLogging.Enabled) 432 if (PhysicsScene.PhysicsLogging.Enabled)
260 PhysicsScene.DetailLog(msg, args); 433 PhysicsScene.DetailLog(msg, args);
261 } 434 }
435
262} 436}
263} 437}