aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs928
1 files changed, 302 insertions, 626 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 26a581f..a0e627e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -24,6 +24,9 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
28// Uncomment this it enable code to do all shape an body memory management
29// in the C# code.
27using System; 30using System;
28using System.Reflection; 31using System.Reflection;
29using System.Collections.Generic; 32using System.Collections.Generic;
@@ -36,6 +39,7 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
36 39
37namespace OpenSim.Region.Physics.BulletSPlugin 40namespace OpenSim.Region.Physics.BulletSPlugin
38{ 41{
42
39 [Serializable] 43 [Serializable]
40public sealed class BSPrim : BSPhysObject 44public sealed class BSPrim : BSPhysObject
41{ 45{
@@ -49,11 +53,6 @@ public sealed class BSPrim : BSPhysObject
49 private ulong _hullKey; 53 private ulong _hullKey;
50 private List<ConvexResult> _hulls; 54 private List<ConvexResult> _hulls;
51 55
52 private BSScene _scene;
53 public BSScene Scene { get { return _scene; } }
54 private String _avName;
55 private uint _localID = 0;
56
57 // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. 56 // _size is what the user passed. _scale is what we pass to the physics engine with the mesh.
58 // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. 57 // Often _scale is unity because the meshmerizer will apply _size when creating the mesh.
59 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 58 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
@@ -87,18 +86,6 @@ public sealed class BSPrim : BSPhysObject
87 private bool _kinematic; 86 private bool _kinematic;
88 private float _buoyancy; 87 private float _buoyancy;
89 88
90 // Membership in a linkset is controlled by this class.
91 public override BSLinkset Linkset { get; set; }
92
93 private int _subscribedEventsMs = 0;
94 private int _nextCollisionOkTime = 0;
95 long _collidingStep;
96 long _collidingGroundStep;
97 CollisionFlags m_currentCollisionFlags = 0;
98
99 public override BulletBody BSBody { get; set; }
100 public override BulletShape BSShape { get; set; }
101
102 private BSDynamics _vehicle; 89 private BSDynamics _vehicle;
103 90
104 private OMV.Vector3 _PIDTarget; 91 private OMV.Vector3 _PIDTarget;
@@ -113,10 +100,8 @@ public sealed class BSPrim : BSPhysObject
113 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 100 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
114 { 101 {
115 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 102 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
116 _localID = localID; 103 base.BaseInitialize(parent_scene, localID, primName, "BSPrim");
117 _avName = primName;
118 _physicsActorType = (int)ActorTypes.Prim; 104 _physicsActorType = (int)ActorTypes.Prim;
119 _scene = parent_scene;
120 _position = pos; 105 _position = pos;
121 _size = size; 106 _size = size;
122 _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type 107 _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type
@@ -129,25 +114,23 @@ public sealed class BSPrim : BSPhysObject
129 _pbs = pbs; 114 _pbs = pbs;
130 _isPhysical = pisPhysical; 115 _isPhysical = pisPhysical;
131 _isVolumeDetect = false; 116 _isVolumeDetect = false;
132 _subscribedEventsMs = 0; 117 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material
133 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 118 _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material
134 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 119 _restitution = PhysicsScene.Params.defaultRestitution;
135 _restitution = _scene.Params.defaultRestitution; 120 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
136 Linkset = new BSLinkset(Scene, this); // a linkset of one
137 _vehicle = new BSDynamics(Scene, this); // add vehicleness
138 _mass = CalculateMass(); 121 _mass = CalculateMass();
122
123 // No body or shape yet
124 BSBody = new BulletBody(LocalID, IntPtr.Zero);
125 BSShape = new BulletShape(IntPtr.Zero);
126
139 DetailLog("{0},BSPrim.constructor,call", LocalID); 127 DetailLog("{0},BSPrim.constructor,call", LocalID);
140 // do the actual object creation at taint time 128 // do the actual object creation at taint time
141 _scene.TaintedObject("BSPrim.create", delegate() 129 PhysicsScene.TaintedObject("BSPrim.create", delegate()
142 { 130 {
143 CreateGeomAndObject(true); 131 CreateGeomAndObject(true);
144 132
145 // Get the pointer to the physical body for this object. 133 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.ptr);
146 // At the moment, we're still letting BulletSim manage the creation and destruction
147 // of the object. Someday we'll move that into the C# code.
148 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
149 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
150 m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr);
151 }); 134 });
152 } 135 }
153 136
@@ -168,57 +151,62 @@ public sealed class BSPrim : BSPhysObject
168 // Undo any vehicle properties 151 // Undo any vehicle properties
169 this.VehicleType = (int)Vehicle.TYPE_NONE; 152 this.VehicleType = (int)Vehicle.TYPE_NONE;
170 153
171 _scene.TaintedObject("BSPrim.destroy", delegate() 154 PhysicsScene.TaintedObject("BSPrim.destroy", delegate()
172 { 155 {
173 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 156 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
174 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 157 // If there are physical body and shape, release my use of same.
175 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 158 PhysicsScene.Shapes.DereferenceBody(BSBody, true, null);
159 PhysicsScene.Shapes.DereferenceShape(BSShape, true, null);
176 }); 160 });
177 } 161 }
178 162
179 public override bool Stopped { 163 public override bool Stopped {
180 get { return _stopped; } 164 get { return _stopped; }
181 } 165 }
182 public override OMV.Vector3 Size { 166 public override OMV.Vector3 Size {
183 get { return _size; } 167 get { return _size; }
184 set { 168 set {
185 _size = value; 169 _size = value;
186 _scene.TaintedObject("BSPrim.setSize", delegate() 170 PhysicsScene.TaintedObject("BSPrim.setSize", delegate()
187 { 171 {
188 _mass = CalculateMass(); // changing size changes the mass 172 _mass = CalculateMass(); // changing size changes the mass
189 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct 173 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
190 // scale and margins are set. 174 // scale and margins are set.
191 CreateGeomAndObject(true); 175 CreateGeomAndObject(true);
192 DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical); 176 // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical);
193 }); 177 });
194 } 178 }
195 } 179 }
196 public override PrimitiveBaseShape Shape { 180 // Scale is what we set in the physics engine. It is different than 'size' in that
181 // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>.
182 public OMV.Vector3 Scale
183 {
184 get { return _scale; }
185 set { _scale = value; }
186 }
187 public override PrimitiveBaseShape Shape {
197 set { 188 set {
198 _pbs = value; 189 _pbs = value;
199 _scene.TaintedObject("BSPrim.setShape", delegate() 190 PhysicsScene.TaintedObject("BSPrim.setShape", delegate()
200 { 191 {
201 _mass = CalculateMass(); // changing the shape changes the mass 192 _mass = CalculateMass(); // changing the shape changes the mass
202 CreateGeomAndObject(false); 193 CreateGeomAndObject(true);
203 }); 194 });
204 } 195 }
205 }
206 public override uint LocalID {
207 set { _localID = value; }
208 get { return _localID; }
209 } 196 }
210 public override bool Grabbed { 197 public override bool Grabbed {
211 set { _grabbed = value; 198 set { _grabbed = value;
212 } 199 }
213 } 200 }
214 public override bool Selected { 201 public override bool Selected {
215 set { 202 set {
216 _isSelected = value; 203 _isSelected = value;
217 _scene.TaintedObject("BSPrim.setSelected", delegate() 204 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
218 { 205 {
219 SetObjectDynamic(); 206 // DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
207 SetObjectDynamic(false);
220 }); 208 });
221 } 209 }
222 } 210 }
223 public override void CrossingFailure() { return; } 211 public override void CrossingFailure() { return; }
224 212
@@ -232,10 +220,10 @@ public sealed class BSPrim : BSPhysObject
232 220
233 Linkset = parent.Linkset.AddMeToLinkset(this); 221 Linkset = parent.Linkset.AddMeToLinkset(this);
234 222
235 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 223 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
236 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 224 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
237 } 225 }
238 return; 226 return;
239 } 227 }
240 228
241 // delink me from my linkset 229 // delink me from my linkset
@@ -245,12 +233,12 @@ public sealed class BSPrim : BSPhysObject
245 233
246 BSPhysObject parentBefore = Linkset.LinksetRoot; 234 BSPhysObject parentBefore = Linkset.LinksetRoot;
247 int childrenBefore = Linkset.NumberOfChildren; 235 int childrenBefore = Linkset.NumberOfChildren;
248 236
249 Linkset = Linkset.RemoveMeFromLinkset(this); 237 Linkset = Linkset.RemoveMeFromLinkset(this);
250 238
251 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 239 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
252 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 240 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
253 return; 241 return;
254 } 242 }
255 243
256 // Set motion values to zero. 244 // Set motion values to zero.
@@ -264,43 +252,40 @@ public sealed class BSPrim : BSPhysObject
264 _rotationalVelocity = OMV.Vector3.Zero; 252 _rotationalVelocity = OMV.Vector3.Zero;
265 253
266 // Zero some other properties directly into the physics engine 254 // Zero some other properties directly into the physics engine
267 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); 255 BulletSimAPI.ClearForces2(BSBody.ptr);
268 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
269 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
270 BulletSimAPI.ClearForces2(BSBody.Ptr);
271 } 256 }
272 257
273 public override void LockAngularMotion(OMV.Vector3 axis) 258 public override void LockAngularMotion(OMV.Vector3 axis)
274 { 259 {
275 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 260 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
276 return; 261 return;
277 } 262 }
278 263
279 public override OMV.Vector3 Position { 264 public override OMV.Vector3 Position {
280 get { 265 get {
281 if (!Linkset.IsRoot(this)) 266 if (!Linkset.IsRoot(this))
282 // child prims move around based on their parent. Need to get the latest location 267 // child prims move around based on their parent. Need to get the latest location
283 _position = BulletSimAPI.GetPosition2(BSBody.Ptr); 268 _position = BulletSimAPI.GetPosition2(BSBody.ptr);
284 269
285 // don't do the GetObjectPosition for root elements because this function is called a zillion times 270 // don't do the GetObjectPosition for root elements because this function is called a zillion times
286 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 271 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
287 return _position; 272 return _position;
288 } 273 }
289 set { 274 set {
290 _position = value; 275 _position = value;
291 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 276 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
292 _scene.TaintedObject("BSPrim.setPosition", delegate() 277 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
293 { 278 {
294 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 279 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
295 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); 280 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
296 }); 281 });
297 } 282 }
298 } 283 }
299 284
300 // Return the effective mass of the object. 285 // Return the effective mass of the object.
301 // If there are multiple items in the linkset, add them together for the root 286 // If there are multiple items in the linkset, add them together for the root
302 public override float Mass 287 public override float Mass
303 { 288 {
304 get 289 get
305 { 290 {
306 // return Linkset.LinksetMass; 291 // return Linkset.LinksetMass;
@@ -323,59 +308,59 @@ public sealed class BSPrim : BSPhysObject
323 get { return Linkset.GeometricCenter; } 308 get { return Linkset.GeometricCenter; }
324 } 309 }
325 310
326 public override OMV.Vector3 Force { 311 public override OMV.Vector3 Force {
327 get { return _force; } 312 get { return _force; }
328 set { 313 set {
329 _force = value; 314 _force = value;
330 _scene.TaintedObject("BSPrim.setForce", delegate() 315 PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
331 { 316 {
332 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 317 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
333 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); 318 BulletSimAPI.SetObjectForce2(BSBody.ptr, _force);
334 }); 319 });
335 } 320 }
336 } 321 }
337 322
338 public override int VehicleType { 323 public override int VehicleType {
339 get { 324 get {
340 return (int)_vehicle.Type; // if we are a vehicle, return that type 325 return (int)_vehicle.Type; // if we are a vehicle, return that type
341 } 326 }
342 set { 327 set {
343 Vehicle type = (Vehicle)value; 328 Vehicle type = (Vehicle)value;
344 BSPrim vehiclePrim = this; 329 BSPrim vehiclePrim = this;
345 _scene.TaintedObject("setVehicleType", delegate() 330 PhysicsScene.TaintedObject("setVehicleType", delegate()
346 { 331 {
347 // Done at taint time so we're sure the physics engine is not using the variables 332 // Done at taint time so we're sure the physics engine is not using the variables
348 // Vehicle code changes the parameters for this vehicle type. 333 // Vehicle code changes the parameters for this vehicle type.
349 _vehicle.ProcessTypeChange(type); 334 _vehicle.ProcessTypeChange(type);
350 // Tell the scene about the vehicle so it will get processing each frame. 335 // Tell the scene about the vehicle so it will get processing each frame.
351 _scene.VehicleInSceneTypeChanged(this, type); 336 PhysicsScene.VehicleInSceneTypeChanged(this, type);
352 }); 337 });
353 } 338 }
354 } 339 }
355 public override void VehicleFloatParam(int param, float value) 340 public override void VehicleFloatParam(int param, float value)
356 { 341 {
357 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 342 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
358 { 343 {
359 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 344 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
360 }); 345 });
361 } 346 }
362 public override void VehicleVectorParam(int param, OMV.Vector3 value) 347 public override void VehicleVectorParam(int param, OMV.Vector3 value)
363 { 348 {
364 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 349 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
365 { 350 {
366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 351 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
367 }); 352 });
368 } 353 }
369 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 354 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
370 { 355 {
371 _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 356 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
372 { 357 {
373 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 358 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
374 }); 359 });
375 } 360 }
376 public override void VehicleFlags(int param, bool remove) 361 public override void VehicleFlags(int param, bool remove)
377 { 362 {
378 _scene.TaintedObject("BSPrim.VehicleFlags", delegate() 363 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
379 { 364 {
380 _vehicle.ProcessVehicleFlags(param, remove); 365 _vehicle.ProcessVehicleFlags(param, remove);
381 }); 366 });
@@ -392,73 +377,81 @@ public sealed class BSPrim : BSPhysObject
392 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 377 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
393 public override void SetVolumeDetect(int param) { 378 public override void SetVolumeDetect(int param) {
394 bool newValue = (param != 0); 379 bool newValue = (param != 0);
395 _isVolumeDetect = newValue; 380 if (_isVolumeDetect != newValue)
396 _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
397 { 381 {
398 SetObjectDynamic(); 382 _isVolumeDetect = newValue;
399 }); 383 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
400 return; 384 {
385 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
386 SetObjectDynamic(true);
387 });
388 }
389 return;
401 } 390 }
402 391
403 public override OMV.Vector3 Velocity { 392 public override OMV.Vector3 Velocity {
404 get { return _velocity; } 393 get { return _velocity; }
405 set { 394 set {
406 _velocity = value; 395 _velocity = value;
407 _scene.TaintedObject("BSPrim.setVelocity", delegate() 396 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
408 { 397 {
409 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 398 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
410 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity); 399 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
411 }); 400 });
412 } 401 }
413 } 402 }
414 public override OMV.Vector3 Torque { 403 public override OMV.Vector3 Torque {
415 get { return _torque; } 404 get { return _torque; }
416 set { _torque = value; 405 set { _torque = value;
417 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 406 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
418 } 407 }
419 } 408 }
420 public override float CollisionScore { 409 public override float CollisionScore {
421 get { return _collisionScore; } 410 get { return _collisionScore; }
422 set { _collisionScore = value; 411 set { _collisionScore = value;
423 } 412 }
424 } 413 }
425 public override OMV.Vector3 Acceleration { 414 public override OMV.Vector3 Acceleration {
426 get { return _acceleration; } 415 get { return _acceleration; }
427 set { _acceleration = value; } 416 set { _acceleration = value; }
428 } 417 }
429 public override OMV.Quaternion Orientation { 418 public override OMV.Quaternion Orientation {
430 get { 419 get {
431 if (!Linkset.IsRoot(this)) 420 if (!Linkset.IsRoot(this))
432 { 421 {
433 // Children move around because tied to parent. Get a fresh value. 422 // Children move around because tied to parent. Get a fresh value.
434 _orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr); 423 _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
435 } 424 }
436 return _orientation; 425 return _orientation;
437 } 426 }
438 set { 427 set {
439 _orientation = value; 428 _orientation = value;
440 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 429 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
441 _scene.TaintedObject("BSPrim.setOrientation", delegate() 430 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
442 { 431 {
443 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 432 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
444 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 433 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
445 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); 434 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
446 }); 435 });
447 } 436 }
448 } 437 }
449 public override int PhysicsActorType { 438 public override int PhysicsActorType {
450 get { return _physicsActorType; } 439 get { return _physicsActorType; }
451 set { _physicsActorType = value; } 440 set { _physicsActorType = value; }
452 } 441 }
453 public override bool IsPhysical { 442 public override bool IsPhysical {
454 get { return _isPhysical; } 443 get { return _isPhysical; }
455 set { 444 set {
456 _isPhysical = value; 445 if (_isPhysical != value)
457 _scene.TaintedObject("BSPrim.setIsPhysical", delegate()
458 { 446 {
459 SetObjectDynamic(); 447 _isPhysical = value;
460 }); 448 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
461 } 449 {
450 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
451 SetObjectDynamic(true);
452 });
453 }
454 }
462 } 455 }
463 456
464 // An object is static (does not move) if selected or not physical 457 // An object is static (does not move) if selected or not physical
@@ -468,53 +461,64 @@ public sealed class BSPrim : BSPhysObject
468 } 461 }
469 462
470 // An object is solid if it's not phantom and if it's not doing VolumeDetect 463 // An object is solid if it's not phantom and if it's not doing VolumeDetect
471 private bool IsSolid 464 public bool IsSolid
472 { 465 {
473 get { return !IsPhantom && !_isVolumeDetect; } 466 get { return !IsPhantom && !_isVolumeDetect; }
474 } 467 }
475 468
476 // Make gravity work if the object is physical and not selected 469 // Make gravity work if the object is physical and not selected
477 // No locking here because only called when it is safe 470 // Called at taint-time!!
471 private void SetObjectDynamic(bool forceRebuild)
472 {
473 // Recreate the physical object if necessary
474 CreateGeomAndObject(forceRebuild);
475 }
476
477 // Convert the simulator's physical properties into settings on BulletSim objects.
478 // There are four flags we're interested in: 478 // There are four flags we're interested in:
479 // IsStatic: Object does not move, otherwise the object has mass and moves 479 // IsStatic: Object does not move, otherwise the object has mass and moves
480 // isSolid: other objects bounce off of this object 480 // isSolid: other objects bounce off of this object
481 // isVolumeDetect: other objects pass through but can generate collisions 481 // isVolumeDetect: other objects pass through but can generate collisions
482 // collisionEvents: whether this object returns collision events 482 // collisionEvents: whether this object returns collision events
483 private void SetObjectDynamic()
484 {
485 // If it's becoming dynamic, it will need hullness
486 VerifyCorrectPhysicalShape();
487 UpdatePhysicalParameters();
488 }
489
490 private void UpdatePhysicalParameters() 483 private void UpdatePhysicalParameters()
491 { 484 {
492 /* 485 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
493 // Bullet wants static objects to have a mass of zero 486
494 float mass = IsStatic ? 0f : _mass; 487 // Mangling all the physical properties requires the object not be in the physical world.
488 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
489 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
495 490
496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
497 */
498 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr);
499 491
500 // Set up the object physicalness (does gravity and collisions move this object) 492 // Set up the object physicalness (does gravity and collisions move this object)
501 MakeDynamic(IsStatic); 493 MakeDynamic(IsStatic);
502 494
503 // Make solid or not (do things bounce off or pass through this object) 495 // Do any vehicle stuff
504 MakeSolid(IsSolid); 496 _vehicle.Refresh();
505 497
506 // Arrange for collisions events if the simulator wants them 498 // Arrange for collision events if the simulator wants them
507 EnableCollisions(SubscribedEvents()); 499 EnableCollisions(SubscribedEvents());
508 500
509 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); 501 // Make solid or not (do things bounce off or pass through this object).
502 MakeSolid(IsSolid);
503
504 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr);
505
506 // Rebuild its shape
507 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr);
508
509 // Collision filter can be set only when the object is in the world
510 if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0)
511 {
512 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask);
513 }
510 514
511 // Recompute any linkset parameters. 515 // Recompute any linkset parameters.
512 // When going from non-physical to physical, this re-enables the constraints that 516 // When going from non-physical to physical, this re-enables the constraints that
513 // had been automatically disabled when the mass was set to zero. 517 // had been automatically disabled when the mass was set to zero.
514 Linkset.Refresh(this); 518 Linkset.Refresh(this);
515 519
516 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}", 520 DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
517 LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags); 521 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape);
518 } 522 }
519 523
520 // "Making dynamic" means changing to and from static. 524 // "Making dynamic" means changing to and from static.
@@ -527,65 +531,86 @@ public sealed class BSPrim : BSPhysObject
527 if (makeStatic) 531 if (makeStatic)
528 { 532 {
529 // Become a Bullet 'static' object type 533 // Become a Bullet 'static' object type
530 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); 534 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
531 // Stop all movement 535 // Stop all movement
532 BulletSimAPI.ClearAllForces2(BSBody.Ptr); 536 BulletSimAPI.ClearAllForces2(BSBody.ptr);
533 // Center of mass is at the center of the object 537 // Center of mass is at the center of the object
534 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.Ptr, _position, _orientation); 538 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation);
535 // Mass is zero which disables a bunch of physics stuff in Bullet 539 // Mass is zero which disables a bunch of physics stuff in Bullet
536 BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero); 540 BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero);
537 // There is no inertia in a static object 541 // There is no inertia in a static object
538 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); 542 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
539 // There can be special things needed for implementing linksets 543 // There can be special things needed for implementing linksets
540 Linkset.MakeStatic(this); 544 Linkset.MakeStatic(this);
541 // The activation state is 'sleeping' so Bullet will not try to act on it 545 // The activation state is 'disabled' so Bullet will not try to act on it
542 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); 546 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION);
547
548 BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
549 BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
543 } 550 }
544 else 551 else
545 { 552 {
546 // Not a Bullet static object 553 // Not a Bullet static object
547 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); 554 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
555
556 // Set various physical properties so internal dynamic properties will get computed correctly as they are set
557 BulletSimAPI.SetFriction2(BSBody.ptr, PhysicsScene.Params.defaultFriction);
558 BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution);
548 559
549 // Set various physical properties so internal things will get computed correctly as they are set
550 BulletSimAPI.SetFriction2(BSBody.Ptr, Scene.Params.defaultFriction);
551 BulletSimAPI.SetRestitution2(BSBody.Ptr, Scene.Params.defaultRestitution);
552 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 560 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
553 BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); 561 BulletSimAPI.ClearAllForces2(BSBody.ptr);
554 BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
555 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
556 562
557 // A dynamic object has mass 563 // A dynamic object has mass
558 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); 564 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr);
559 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass); 565 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
560 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia); 566 // OMV.Vector3 inertia = OMV.Vector3.Zero;
561 // Inertia is based on our new mass 567 BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia);
562 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); 568 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
563 569
564 // Various values for simulation limits 570 // Various values for simulation limits
565 BulletSimAPI.SetDamping2(BSBody.Ptr, Scene.Params.linearDamping, Scene.Params.angularDamping); 571 BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping);
566 BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, Scene.Params.deactivationTime); 572 BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime);
567 BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, Scene.Params.linearSleepingThreshold, Scene.Params.angularSleepingThreshold); 573 BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
568 BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, Scene.Params.contactProcessingThreshold); 574 BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
569 575
570 // There can be special things needed for implementing linksets 576 // There can be special things needed for implementing linksets.
571 Linkset.MakeDynamic(this); 577 Linkset.MakeDynamic(this);
572 578
573 // Force activation of the object so Bullet will act on it. 579 // Force activation of the object so Bullet will act on it.
574 BulletSimAPI.Activate2(BSBody.Ptr, true); 580 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
581 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
582 BulletSimAPI.Activate2(BSBody.ptr, true);
583
584 BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
585 BSBody.collisionMask = CollisionFilterGroups.ObjectMask;
575 } 586 }
576 } 587 }
577 588
578 // "Making solid" means that other object will not pass through this object. 589 // "Making solid" means that other object will not pass through this object.
590 // To make transparent, we create a Bullet ghost object.
591 // Note: This expects to be called from the UpdatePhysicalParameters() routine as
592 // the functions after this one set up the state of a possibly newly created collision body.
579 private void MakeSolid(bool makeSolid) 593 private void MakeSolid(bool makeSolid)
580 { 594 {
595 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr);
581 if (makeSolid) 596 if (makeSolid)
582 { 597 {
583 // Easy in Bullet -- just remove the object flag that controls collision response 598 // Verify the previous code created the correct shape for this type of thing.
584 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 599 if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0)
600 {
601 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
602 }
603 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
585 } 604 }
586 else 605 else
587 { 606 {
588 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 607 if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0)
608 {
609 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
610 }
611 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
612 BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
613 BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
589 } 614 }
590 } 615 }
591 616
@@ -594,40 +619,40 @@ public sealed class BSPrim : BSPhysObject
594 { 619 {
595 if (wantsCollisionEvents) 620 if (wantsCollisionEvents)
596 { 621 {
597 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 622 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
598 } 623 }
599 else 624 else
600 { 625 {
601 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 626 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
602 } 627 }
603 } 628 }
604 629
605 // prims don't fly 630 // prims don't fly
606 public override bool Flying { 631 public override bool Flying {
607 get { return _flying; } 632 get { return _flying; }
608 set { 633 set {
609 _flying = value; 634 _flying = value;
610 } 635 }
611 } 636 }
612 public override bool SetAlwaysRun { 637 public override bool SetAlwaysRun {
613 get { return _setAlwaysRun; } 638 get { return _setAlwaysRun; }
614 set { _setAlwaysRun = value; } 639 set { _setAlwaysRun = value; }
615 } 640 }
616 public override bool ThrottleUpdates { 641 public override bool ThrottleUpdates {
617 get { return _throttleUpdates; } 642 get { return _throttleUpdates; }
618 set { _throttleUpdates = value; } 643 set { _throttleUpdates = value; }
619 } 644 }
620 public override bool IsColliding { 645 public override bool IsColliding {
621 get { return (_collidingStep == _scene.SimulationStep); } 646 get { return (CollidingStep == PhysicsScene.SimulationStep); }
622 set { _isColliding = value; } 647 set { _isColliding = value; }
623 } 648 }
624 public override bool CollidingGround { 649 public override bool CollidingGround {
625 get { return (_collidingGroundStep == _scene.SimulationStep); } 650 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
626 set { _collidingGround = value; } 651 set { _collidingGround = value; }
627 } 652 }
628 public override bool CollidingObj { 653 public override bool CollidingObj {
629 get { return _collidingObj; } 654 get { return _collidingObj; }
630 set { _collidingObj = value; } 655 set { _collidingObj = value; }
631 } 656 }
632 public bool IsPhantom { 657 public bool IsPhantom {
633 get { 658 get {
@@ -637,10 +662,10 @@ public sealed class BSPrim : BSPhysObject
637 return false; 662 return false;
638 } 663 }
639 } 664 }
640 public override bool FloatOnWater { 665 public override bool FloatOnWater {
641 set { _floatOnWater = value; } 666 set { _floatOnWater = value; }
642 } 667 }
643 public override OMV.Vector3 RotationalVelocity { 668 public override OMV.Vector3 RotationalVelocity {
644 get { 669 get {
645 /* 670 /*
646 OMV.Vector3 pv = OMV.Vector3.Zero; 671 OMV.Vector3 pv = OMV.Vector3.Zero;
@@ -652,61 +677,60 @@ public sealed class BSPrim : BSPhysObject
652 */ 677 */
653 678
654 return _rotationalVelocity; 679 return _rotationalVelocity;
655 } 680 }
656 set { 681 set {
657 _rotationalVelocity = value; 682 _rotationalVelocity = value;
658 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 683 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
659 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 684 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
660 { 685 {
661 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 686 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
662 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity); 687 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity);
663 }); 688 });
664 } 689 }
665 } 690 }
666 public override bool Kinematic { 691 public override bool Kinematic {
667 get { return _kinematic; } 692 get { return _kinematic; }
668 set { _kinematic = value; 693 set { _kinematic = value;
669 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); 694 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic);
670 } 695 }
671 } 696 }
672 public override float Buoyancy { 697 public override float Buoyancy {
673 get { return _buoyancy; } 698 get { return _buoyancy; }
674 set { 699 set {
675 _buoyancy = value; 700 _buoyancy = value;
676 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 701 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate()
677 { 702 {
678 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 703 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
679 // Buoyancy is faked by changing the gravity applied to the object 704 // Buoyancy is faked by changing the gravity applied to the object
680 float grav = Scene.Params.gravity * (1f - _buoyancy); 705 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
681 BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav)); 706 BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav));
682 // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
683 }); 707 });
684 } 708 }
685 } 709 }
686 710
687 // Used for MoveTo 711 // Used for MoveTo
688 public override OMV.Vector3 PIDTarget { 712 public override OMV.Vector3 PIDTarget {
689 set { _PIDTarget = value; } 713 set { _PIDTarget = value; }
690 } 714 }
691 public override bool PIDActive { 715 public override bool PIDActive {
692 set { _usePID = value; } 716 set { _usePID = value; }
693 } 717 }
694 public override float PIDTau { 718 public override float PIDTau {
695 set { _PIDTau = value; } 719 set { _PIDTau = value; }
696 } 720 }
697 721
698 // Used for llSetHoverHeight and maybe vehicle height 722 // Used for llSetHoverHeight and maybe vehicle height
699 // Hover Height will override MoveTo target's Z 723 // Hover Height will override MoveTo target's Z
700 public override bool PIDHoverActive { 724 public override bool PIDHoverActive {
701 set { _useHoverPID = value; } 725 set { _useHoverPID = value; }
702 } 726 }
703 public override float PIDHoverHeight { 727 public override float PIDHoverHeight {
704 set { _PIDHoverHeight = value; } 728 set { _PIDHoverHeight = value; }
705 } 729 }
706 public override PIDHoverType PIDHoverType { 730 public override PIDHoverType PIDHoverType {
707 set { _PIDHoverType = value; } 731 set { _PIDHoverType = value; }
708 } 732 }
709 public override float PIDHoverTau { 733 public override float PIDHoverTau {
710 set { _PIDHoverTao = value; } 734 set { _PIDHoverTao = value; }
711 } 735 }
712 736
@@ -730,7 +754,7 @@ public sealed class BSPrim : BSPhysObject
730 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 754 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
731 return; 755 return;
732 } 756 }
733 _scene.TaintedObject("BSPrim.AddForce", delegate() 757 PhysicsScene.TaintedObject("BSPrim.AddForce", delegate()
734 { 758 {
735 OMV.Vector3 fSum = OMV.Vector3.Zero; 759 OMV.Vector3 fSum = OMV.Vector3.Zero;
736 lock (m_accumulatedForces) 760 lock (m_accumulatedForces)
@@ -741,43 +765,19 @@ public sealed class BSPrim : BSPhysObject
741 } 765 }
742 m_accumulatedForces.Clear(); 766 m_accumulatedForces.Clear();
743 } 767 }
744 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); 768 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
745 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. 769 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
746 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); 770 BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum);
747 }); 771 });
748 } 772 }
749 773
750 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 774 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
751 DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 775 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
752 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 776 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
753 } 777 }
754 public override void SetMomentum(OMV.Vector3 momentum) { 778 public override void SetMomentum(OMV.Vector3 momentum) {
755 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 779 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
756 } 780 }
757 public override void SubscribeEvents(int ms) {
758 _subscribedEventsMs = ms;
759 if (ms > 0)
760 {
761 // make sure first collision happens
762 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
763
764 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
765 {
766 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
767 });
768 }
769 }
770 public override void UnSubscribeEvents() {
771 _subscribedEventsMs = 0;
772 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
773 {
774 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
775 });
776 }
777 public override bool SubscribedEvents() {
778 return (_subscribedEventsMs > 0);
779 }
780
781 #region Mass Calculation 781 #region Mass Calculation
782 782
783 private float CalculateMass() 783 private float CalculateMass()
@@ -787,8 +787,8 @@ public sealed class BSPrim : BSPhysObject
787 787
788 float returnMass = 0; 788 float returnMass = 0;
789 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; 789 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
790 float hollowVolume = hollowAmount * hollowAmount; 790 float hollowVolume = hollowAmount * hollowAmount;
791 791
792 switch (_pbs.ProfileShape) 792 switch (_pbs.ProfileShape)
793 { 793 {
794 case ProfileShape.Square: 794 case ProfileShape.Square:
@@ -824,16 +824,16 @@ public sealed class BSPrim : BSPhysObject
824 824
825 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 825 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
826 { 826 {
827 //a tube 827 //a tube
828 828
829 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); 829 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
830 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); 830 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY);
831 volume -= volume*tmp*tmp; 831 volume -= volume*tmp*tmp;
832 832
833 if (hollowAmount > 0.0) 833 if (hollowAmount > 0.0)
834 { 834 {
835 hollowVolume *= hollowAmount; 835 hollowVolume *= hollowAmount;
836 836
837 switch (_pbs.HollowShape) 837 switch (_pbs.HollowShape)
838 { 838 {
839 case HollowShape.Square: 839 case HollowShape.Square:
@@ -892,7 +892,7 @@ public sealed class BSPrim : BSPhysObject
892 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); 892 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
893 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 893 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
894 volume *= (1.0f - tmp * tmp); 894 volume *= (1.0f - tmp * tmp);
895 895
896 if (hollowAmount > 0.0) 896 if (hollowAmount > 0.0)
897 { 897 {
898 898
@@ -1071,302 +1071,17 @@ public sealed class BSPrim : BSPhysObject
1071 if (returnMass <= 0) 1071 if (returnMass <= 0)
1072 returnMass = 0.0001f; 1072 returnMass = 0.0001f;
1073 1073
1074 if (returnMass > _scene.MaximumObjectMass) 1074 if (returnMass > PhysicsScene.MaximumObjectMass)
1075 returnMass = _scene.MaximumObjectMass; 1075 returnMass = PhysicsScene.MaximumObjectMass;
1076 1076
1077 return returnMass; 1077 return returnMass;
1078 }// end CalculateMass 1078 }// end CalculateMass
1079 #endregion Mass Calculation 1079 #endregion Mass Calculation
1080 1080
1081 // Create the geometry information in Bullet for later use.
1082 // The objects needs a hull if it's physical otherwise a mesh is enough.
1083 // No locking here because this is done when we know physics is not simulating.
1084 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
1085 // Returns 'true' if the geometry was rebuilt.
1086 // Called at taint-time!
1087 private bool CreateGeom(bool forceRebuild)
1088 {
1089 bool ret = false;
1090 bool haveShape = false;
1091
1092 // If the prim attributes are simple, this could be a simple Bullet native shape
1093 if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim)
1094 || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0
1095 && _pbs.ProfileHollow == 0
1096 && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0
1097 && _pbs.PathBegin == 0 && _pbs.PathEnd == 0
1098 && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0
1099 && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100
1100 && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) )
1101 {
1102 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1103 {
1104 haveShape = true;
1105 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
1106 {
1107 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
1108 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
1109 // Bullet native objects are scaled by the Bullet engine so pass the size in
1110 _scale = _size;
1111 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1112 ret = true;
1113 }
1114 }
1115 else
1116 {
1117 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1118 haveShape = true;
1119 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1120 {
1121 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
1122 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
1123 _scale = _size;
1124 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1125 ret = true;
1126 }
1127 }
1128 }
1129 // If a simple shape isn't happening, create a mesh and possibly a hull
1130 if (!haveShape)
1131 {
1132 if (IsPhysical)
1133 {
1134 if (forceRebuild || _hullKey == 0)
1135 {
1136 // physical objects require a hull for interaction.
1137 // This also creates the mesh if it doesn't already exist
1138 ret = CreateGeomHull();
1139 }
1140 }
1141 else
1142 {
1143 if (forceRebuild || _meshKey == 0)
1144 {
1145 // Static (non-physical) objects only need a mesh for bumping into
1146 ret = CreateGeomMesh();
1147 }
1148 }
1149 }
1150 return ret;
1151 }
1152
1153 // No locking here because this is done when we know physics is not simulating
1154 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1155 // Called at taint-time!
1156 private bool CreateGeomMesh()
1157 {
1158 // level of detail based on size and type of the object
1159 float lod = _scene.MeshLOD;
1160 if (_pbs.SculptEntry)
1161 lod = _scene.SculptLOD;
1162 float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z));
1163 if (maxAxis > _scene.MeshMegaPrimThreshold)
1164 lod = _scene.MeshMegaPrimLOD;
1165
1166 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
1167 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
1168
1169 // if this new shape is the same as last time, don't recreate the mesh
1170 if (_meshKey == newMeshKey) return false;
1171
1172 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1173 // Since we're recreating new, get rid of any previously generated shape
1174 if (_meshKey != 0)
1175 {
1176 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1177 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1178 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1179 _mesh = null;
1180 _meshKey = 0;
1181 }
1182
1183 _meshKey = newMeshKey;
1184 // always pass false for physicalness as this creates some sort of bounding box which we don't need
1185 _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false);
1186
1187 int[] indices = _mesh.getIndexListAsInt();
1188 List<OMV.Vector3> vertices = _mesh.getVertexList();
1189
1190 float[] verticesAsFloats = new float[vertices.Count * 3];
1191 int vi = 0;
1192 foreach (OMV.Vector3 vv in vertices)
1193 {
1194 verticesAsFloats[vi++] = vv.X;
1195 verticesAsFloats[vi++] = vv.Y;
1196 verticesAsFloats[vi++] = vv.Z;
1197 }
1198
1199 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
1200 // LogHeader, _localID, _meshKey, indices.Length, vertices.Count);
1201 BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices,
1202 vertices.Count, verticesAsFloats);
1203
1204 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1205 // meshes are already scaled by the meshmerizer
1206 _scale = new OMV.Vector3(1f, 1f, 1f);
1207 return true;
1208 }
1209
1210 // No locking here because this is done when we know physics is not simulating
1211 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1212 private bool CreateGeomHull()
1213 {
1214 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1215 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
1216 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
1217
1218 // if the hull hasn't changed, don't rebuild it
1219 if (newHullKey == _hullKey) return false;
1220
1221 DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1222
1223 // Since we're recreating new, get rid of any previously generated shape
1224 if (_hullKey != 0)
1225 {
1226 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1227 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1228 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1229 _hullKey = 0;
1230 }
1231
1232 _hullKey = newHullKey;
1233
1234 // Make sure the underlying mesh exists and is correct
1235 CreateGeomMesh();
1236
1237 int[] indices = _mesh.getIndexListAsInt();
1238 List<OMV.Vector3> vertices = _mesh.getVertexList();
1239
1240 //format conversion from IMesh format to DecompDesc format
1241 List<int> convIndices = new List<int>();
1242 List<float3> convVertices = new List<float3>();
1243 for (int ii = 0; ii < indices.GetLength(0); ii++)
1244 {
1245 convIndices.Add(indices[ii]);
1246 }
1247 foreach (OMV.Vector3 vv in vertices)
1248 {
1249 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
1250 }
1251
1252 // setup and do convex hull conversion
1253 _hulls = new List<ConvexResult>();
1254 DecompDesc dcomp = new DecompDesc();
1255 dcomp.mIndices = convIndices;
1256 dcomp.mVertices = convVertices;
1257 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
1258 // create the hull into the _hulls variable
1259 convexBuilder.process(dcomp);
1260
1261 // Convert the vertices and indices for passing to unmanaged.
1262 // The hull information is passed as a large floating point array.
1263 // The format is:
1264 // convHulls[0] = number of hulls
1265 // convHulls[1] = number of vertices in first hull
1266 // convHulls[2] = hull centroid X coordinate
1267 // convHulls[3] = hull centroid Y coordinate
1268 // convHulls[4] = hull centroid Z coordinate
1269 // convHulls[5] = first hull vertex X
1270 // convHulls[6] = first hull vertex Y
1271 // convHulls[7] = first hull vertex Z
1272 // convHulls[8] = second hull vertex X
1273 // ...
1274 // convHulls[n] = number of vertices in second hull
1275 // convHulls[n+1] = second hull centroid X coordinate
1276 // ...
1277 //
1278 // TODO: is is very inefficient. Someday change the convex hull generator to return
1279 // data structures that do not need to be converted in order to pass to Bullet.
1280 // And maybe put the values directly into pinned memory rather than marshaling.
1281 int hullCount = _hulls.Count;
1282 int totalVertices = 1; // include one for the count of the hulls
1283 foreach (ConvexResult cr in _hulls)
1284 {
1285 totalVertices += 4; // add four for the vertex count and centroid
1286 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
1287 }
1288 float[] convHulls = new float[totalVertices];
1289
1290 convHulls[0] = (float)hullCount;
1291 int jj = 1;
1292 foreach (ConvexResult cr in _hulls)
1293 {
1294 // copy vertices for index access
1295 float3[] verts = new float3[cr.HullVertices.Count];
1296 int kk = 0;
1297 foreach (float3 ff in cr.HullVertices)
1298 {
1299 verts[kk++] = ff;
1300 }
1301
1302 // add to the array one hull's worth of data
1303 convHulls[jj++] = cr.HullIndices.Count;
1304 convHulls[jj++] = 0f; // centroid x,y,z
1305 convHulls[jj++] = 0f;
1306 convHulls[jj++] = 0f;
1307 foreach (int ind in cr.HullIndices)
1308 {
1309 convHulls[jj++] = verts[ind].x;
1310 convHulls[jj++] = verts[ind].y;
1311 convHulls[jj++] = verts[ind].z;
1312 }
1313 }
1314
1315 // create the hull definition in Bullet
1316 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
1317 BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
1318 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1319 // meshes are already scaled by the meshmerizer
1320 _scale = new OMV.Vector3(1f, 1f, 1f);
1321 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1322 return true;
1323 }
1324
1325 // Callback from convex hull creater with a newly created hull.
1326 // Just add it to the collection of hulls for this shape.
1327 private void HullReturn(ConvexResult result)
1328 {
1329 _hulls.Add(result);
1330 return;
1331 }
1332
1333 private void VerifyCorrectPhysicalShape()
1334 {
1335 if (!IsStatic)
1336 {
1337 // if not static, it will need a hull to efficiently collide with things
1338 if (_hullKey == 0)
1339 {
1340 CreateGeomAndObject(false);
1341 }
1342
1343 }
1344 }
1345
1346 // Create an object in Bullet if it has not already been created
1347 // No locking here because this is done when the physics engine is not simulating
1348 // Returns 'true' if an object was actually created.
1349 private bool CreateObject()
1350 {
1351 // this routine is called when objects are rebuilt.
1352
1353 // the mesh or hull must have already been created in Bullet
1354 ShapeData shape;
1355 FillShapeInfo(out shape);
1356 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1357 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1358
1359 // the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
1360 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1361 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
1362
1363 return ret;
1364 }
1365
1366 // Copy prim's info into the BulletSim shape description structure 1081 // Copy prim's info into the BulletSim shape description structure
1367 public void FillShapeInfo(out ShapeData shape) 1082 public void FillShapeInfo(out ShapeData shape)
1368 { 1083 {
1369 shape.ID = _localID; 1084 shape.ID = LocalID;
1370 shape.Type = _shapeType; 1085 shape.Type = _shapeType;
1371 shape.Position = _position; 1086 shape.Position = _position;
1372 shape.Rotation = _orientation; 1087 shape.Rotation = _orientation;
@@ -1380,22 +1095,39 @@ public sealed class BSPrim : BSPhysObject
1380 shape.Restitution = _restitution; 1095 shape.Restitution = _restitution;
1381 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; 1096 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
1382 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1097 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1098 shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue;
1099 shape.Size = _size;
1383 } 1100 }
1384
1385 // Rebuild the geometry and object. 1101 // Rebuild the geometry and object.
1386 // This is called when the shape changes so we need to recreate the mesh/hull. 1102 // This is called when the shape changes so we need to recreate the mesh/hull.
1387 // No locking here because this is done when the physics engine is not simulating 1103 // Called at taint-time!!!
1388 private void CreateGeomAndObject(bool forceRebuild) 1104 private void CreateGeomAndObject(bool forceRebuild)
1389 { 1105 {
1390 // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild); 1106 ShapeData shapeData;
1391 // Create the geometry that will make up the object 1107 FillShapeInfo(out shapeData);
1392 if (CreateGeom(forceRebuild)) 1108
1109 // If this prim is part of a linkset, we must remove and restore the physical
1110 // links of the body is rebuilt.
1111 bool needToRestoreLinkset = false;
1112
1113 // Create the correct physical representation for this type of object.
1114 // Updates BSBody and BSShape with the new information.
1115 PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs,
1116 null, delegate(BulletBody dBody)
1117 {
1118 // Called if the current prim body is about to be destroyed.
1119 // Remove all the physical dependencies on the old body.
1120 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
1121 });
1122
1123 if (needToRestoreLinkset)
1393 { 1124 {
1394 // Create the object and place it into the world 1125 // If physical body dependencies were removed, restore them
1395 CreateObject(); 1126 Linkset.RestoreBodyDependencies(this);
1396 // Make sure the properties are set on the new object
1397 UpdatePhysicalParameters();
1398 } 1127 }
1128
1129 // Make sure the properties are set on the new object
1130 UpdatePhysicalParameters();
1399 return; 1131 return;
1400 } 1132 }
1401 1133
@@ -1485,66 +1217,10 @@ public sealed class BSPrim : BSPhysObject
1485 { 1217 {
1486 // For debugging, we can also report the movement of children 1218 // For debugging, we can also report the movement of children
1487 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1219 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1488 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1220 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1489 entprop.Acceleration, entprop.RotationalVelocity); 1221 entprop.Acceleration, entprop.RotationalVelocity);
1490 } 1222 }
1491 */ 1223 */
1492 } 1224 }
1493
1494 // I've collided with something
1495 // Called at taint time from within the Step() function
1496 CollisionEventUpdate collisionCollection;
1497 public override bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1498 {
1499 bool ret = false;
1500
1501 // The following lines make IsColliding() and IsCollidingGround() work
1502 _collidingStep = Scene.SimulationStep;
1503 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
1504 {
1505 _collidingGroundStep = Scene.SimulationStep;
1506 }
1507
1508 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1509
1510 // prims in the same linkset cannot collide with each other
1511 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
1512 {
1513 return ret;
1514 }
1515
1516 // if someone has subscribed for collision events....
1517 if (SubscribedEvents()) {
1518 // throttle the collisions to the number of milliseconds specified in the subscription
1519 int nowTime = Scene.SimulationNowTime;
1520 if (nowTime >= _nextCollisionOkTime) {
1521 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1522
1523 if (collisionCollection == null)
1524 collisionCollection = new CollisionEventUpdate();
1525 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1526 ret = true;
1527 }
1528 }
1529 return ret;
1530 }
1531
1532 // The scene is telling us it's time to pass our collected collisions into the simulator
1533 public override void SendCollisions()
1534 {
1535 if (collisionCollection != null && collisionCollection.Count > 0)
1536 {
1537 base.SendCollisionUpdate(collisionCollection);
1538 // The collisionCollection structure is passed around in the simulator.
1539 // Make sure we don't have a handle to that one and that a new one is used next time.
1540 collisionCollection = null;
1541 }
1542 }
1543
1544 // Invoke the detailed logger and output something if it's enabled.
1545 private void DetailLog(string msg, params Object[] args)
1546 {
1547 Scene.PhysicsLogging.Write(msg, args);
1548 }
1549} 1225}
1550} 1226}