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.cs450
1 files changed, 299 insertions, 151 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 9c20004..26a581f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -37,13 +37,11 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
37namespace OpenSim.Region.Physics.BulletSPlugin 37namespace OpenSim.Region.Physics.BulletSPlugin
38{ 38{
39 [Serializable] 39 [Serializable]
40public sealed class BSPrim : PhysicsActor 40public sealed class BSPrim : BSPhysObject
41{ 41{
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
44 44
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); }
46
47 private IMesh _mesh; 45 private IMesh _mesh;
48 private PrimitiveBaseShape _pbs; 46 private PrimitiveBaseShape _pbs;
49 private ShapeData.PhysicsShapeType _shapeType; 47 private ShapeData.PhysicsShapeType _shapeType;
@@ -90,23 +88,16 @@ public sealed class BSPrim : PhysicsActor
90 private float _buoyancy; 88 private float _buoyancy;
91 89
92 // Membership in a linkset is controlled by this class. 90 // Membership in a linkset is controlled by this class.
93 private BSLinkset _linkset; 91 public override BSLinkset Linkset { get; set; }
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
99 92
100 private int _subscribedEventsMs = 0; 93 private int _subscribedEventsMs = 0;
101 private int _nextCollisionOkTime = 0; 94 private int _nextCollisionOkTime = 0;
102 long _collidingStep; 95 long _collidingStep;
103 long _collidingGroundStep; 96 long _collidingGroundStep;
97 CollisionFlags m_currentCollisionFlags = 0;
104 98
105 private BulletBody m_body; 99 public override BulletBody BSBody { get; set; }
106 public BulletBody Body { 100 public override BulletShape BSShape { get; set; }
107 get { return m_body; }
108 set { m_body = value; }
109 }
110 101
111 private BSDynamics _vehicle; 102 private BSDynamics _vehicle;
112 103
@@ -124,6 +115,7 @@ public sealed class BSPrim : PhysicsActor
124 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 115 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
125 _localID = localID; 116 _localID = localID;
126 _avName = primName; 117 _avName = primName;
118 _physicsActorType = (int)ActorTypes.Prim;
127 _scene = parent_scene; 119 _scene = parent_scene;
128 _position = pos; 120 _position = pos;
129 _size = size; 121 _size = size;
@@ -141,35 +133,37 @@ public sealed class BSPrim : PhysicsActor
141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 133 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 134 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
143 _restitution = _scene.Params.defaultRestitution; 135 _restitution = _scene.Params.defaultRestitution;
144 _linkset = new BSLinkset(_scene, this); // a linkset of one 136 Linkset = new BSLinkset(Scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness 137 _vehicle = new BSDynamics(Scene, this); // add vehicleness
146 _mass = CalculateMass(); 138 _mass = CalculateMass();
147 // do the actual object creation at taint time
148 DetailLog("{0},BSPrim.constructor,call", LocalID); 139 DetailLog("{0},BSPrim.constructor,call", LocalID);
140 // do the actual object creation at taint time
149 _scene.TaintedObject("BSPrim.create", delegate() 141 _scene.TaintedObject("BSPrim.create", delegate()
150 { 142 {
151 RecreateGeomAndObject(); 143 CreateGeomAndObject(true);
152 144
153 // Get the pointer to the physical body for this object. 145 // Get the pointer to the physical body for this object.
154 // At the moment, we're still letting BulletSim manage the creation and destruction 146 // At the moment, we're still letting BulletSim manage the creation and destruction
155 // of the object. Someday we'll move that into the C# code. 147 // of the object. Someday we'll move that into the C# code.
156 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 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);
157 }); 151 });
158 } 152 }
159 153
160 // called when this prim is being destroyed and we should free all the resources 154 // called when this prim is being destroyed and we should free all the resources
161 public void Destroy() 155 public override void Destroy()
162 { 156 {
163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 157 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
164 158
165 // Undo any links between me and any other object 159 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.LinksetRoot; 160 BSPhysObject parentBefore = Linkset.LinksetRoot;
167 int childrenBefore = _linkset.NumberOfChildren; 161 int childrenBefore = Linkset.NumberOfChildren;
168 162
169 _linkset = _linkset.RemoveMeFromLinkset(this); 163 Linkset = Linkset.RemoveMeFromLinkset(this);
170 164
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", 165 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 166 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
173 167
174 // Undo any vehicle properties 168 // Undo any vehicle properties
175 this.VehicleType = (int)Vehicle.TYPE_NONE; 169 this.VehicleType = (int)Vehicle.TYPE_NONE;
@@ -192,9 +186,10 @@ public sealed class BSPrim : PhysicsActor
192 _scene.TaintedObject("BSPrim.setSize", delegate() 186 _scene.TaintedObject("BSPrim.setSize", delegate()
193 { 187 {
194 _mass = CalculateMass(); // changing size changes the mass 188 _mass = CalculateMass(); // changing size changes the mass
195 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); 189 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
196 // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); 190 // scale and margins are set.
197 RecreateGeomAndObject(); 191 CreateGeomAndObject(true);
192 DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical);
198 }); 193 });
199 } 194 }
200 } 195 }
@@ -204,7 +199,7 @@ public sealed class BSPrim : PhysicsActor
204 _scene.TaintedObject("BSPrim.setShape", delegate() 199 _scene.TaintedObject("BSPrim.setShape", delegate()
205 { 200 {
206 _mass = CalculateMass(); // changing the shape changes the mass 201 _mass = CalculateMass(); // changing the shape changes the mass
207 RecreateGeomAndObject(); 202 CreateGeomAndObject(false);
208 }); 203 });
209 } 204 }
210 } 205 }
@@ -232,14 +227,13 @@ public sealed class BSPrim : PhysicsActor
232 BSPrim parent = obj as BSPrim; 227 BSPrim parent = obj as BSPrim;
233 if (parent != null) 228 if (parent != null)
234 { 229 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); 230 BSPhysObject parentBefore = Linkset.LinksetRoot;
236 BSPrim parentBefore = _linkset.LinksetRoot; 231 int childrenBefore = Linkset.NumberOfChildren;
237 int childrenBefore = _linkset.NumberOfChildren;
238 232
239 _linkset = parent.Linkset.AddMeToLinkset(this); 233 Linkset = parent.Linkset.AddMeToLinkset(this);
240 234
241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 235 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 236 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
243 } 237 }
244 return; 238 return;
245 } 239 }
@@ -248,16 +242,14 @@ public sealed class BSPrim : PhysicsActor
248 public override void delink() { 242 public override void delink() {
249 // TODO: decide if this parent checking needs to happen at taint time 243 // TODO: decide if this parent checking needs to happen at taint time
250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 244 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
252 _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
253 245
254 BSPrim parentBefore = _linkset.LinksetRoot; 246 BSPhysObject parentBefore = Linkset.LinksetRoot;
255 int childrenBefore = _linkset.NumberOfChildren; 247 int childrenBefore = Linkset.NumberOfChildren;
256 248
257 _linkset = _linkset.RemoveMeFromLinkset(this); 249 Linkset = Linkset.RemoveMeFromLinkset(this);
258 250
259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 251 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 252 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
261 return; 253 return;
262 } 254 }
263 255
@@ -265,30 +257,30 @@ public sealed class BSPrim : PhysicsActor
265 // Do it to the properties so the values get set in the physics engine. 257 // Do it to the properties so the values get set in the physics engine.
266 // Push the setting of the values to the viewer. 258 // Push the setting of the values to the viewer.
267 // Called at taint time! 259 // Called at taint time!
268 public void ZeroMotion() 260 public override void ZeroMotion()
269 { 261 {
270 _velocity = OMV.Vector3.Zero; 262 _velocity = OMV.Vector3.Zero;
271 _acceleration = OMV.Vector3.Zero; 263 _acceleration = OMV.Vector3.Zero;
272 _rotationalVelocity = OMV.Vector3.Zero; 264 _rotationalVelocity = OMV.Vector3.Zero;
273 265
274 // Zero some other properties directly into the physics engine 266 // Zero some other properties directly into the physics engine
275 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); 267 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
276 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); 268 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
277 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); 269 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
278 BulletSimAPI.ClearForces2(Body.Ptr); 270 BulletSimAPI.ClearForces2(BSBody.Ptr);
279 } 271 }
280 272
281 public override void LockAngularMotion(OMV.Vector3 axis) 273 public override void LockAngularMotion(OMV.Vector3 axis)
282 { 274 {
283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 275 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
284 return; 276 return;
285 } 277 }
286 278
287 public override OMV.Vector3 Position { 279 public override OMV.Vector3 Position {
288 get { 280 get {
289 if (!_linkset.IsRoot(this)) 281 if (!Linkset.IsRoot(this))
290 // child prims move around based on their parent. Need to get the latest location 282 // child prims move around based on their parent. Need to get the latest location
291 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 283 _position = BulletSimAPI.GetPosition2(BSBody.Ptr);
292 284
293 // don't do the GetObjectPosition for root elements because this function is called a zillion times 285 // don't do the GetObjectPosition for root elements because this function is called a zillion times
294 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 286 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
@@ -299,8 +291,8 @@ public sealed class BSPrim : PhysicsActor
299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 291 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
300 _scene.TaintedObject("BSPrim.setPosition", delegate() 292 _scene.TaintedObject("BSPrim.setPosition", delegate()
301 { 293 {
302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 294 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 295 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
304 }); 296 });
305 } 297 }
306 } 298 }
@@ -311,23 +303,24 @@ public sealed class BSPrim : PhysicsActor
311 { 303 {
312 get 304 get
313 { 305 {
314 return _linkset.LinksetMass; 306 // return Linkset.LinksetMass;
307 return _mass;
315 } 308 }
316 } 309 }
317 310
318 // used when we only want this prim's mass and not the linkset thing 311 // used when we only want this prim's mass and not the linkset thing
319 public float MassRaw { get { return _mass; } } 312 public override float MassRaw { get { return _mass; } }
320 313
321 // Is this used? 314 // Is this used?
322 public override OMV.Vector3 CenterOfMass 315 public override OMV.Vector3 CenterOfMass
323 { 316 {
324 get { return _linkset.CenterOfMass; } 317 get { return Linkset.CenterOfMass; }
325 } 318 }
326 319
327 // Is this used? 320 // Is this used?
328 public override OMV.Vector3 GeometricCenter 321 public override OMV.Vector3 GeometricCenter
329 { 322 {
330 get { return _linkset.GeometricCenter; } 323 get { return Linkset.GeometricCenter; }
331 } 324 }
332 325
333 public override OMV.Vector3 Force { 326 public override OMV.Vector3 Force {
@@ -336,9 +329,8 @@ public sealed class BSPrim : PhysicsActor
336 _force = value; 329 _force = value;
337 _scene.TaintedObject("BSPrim.setForce", delegate() 330 _scene.TaintedObject("BSPrim.setForce", delegate()
338 { 331 {
339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 332 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 333 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
342 }); 334 });
343 } 335 }
344 } 336 }
@@ -364,14 +356,14 @@ public sealed class BSPrim : PhysicsActor
364 { 356 {
365 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 357 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
366 { 358 {
367 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 359 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
368 }); 360 });
369 } 361 }
370 public override void VehicleVectorParam(int param, OMV.Vector3 value) 362 public override void VehicleVectorParam(int param, OMV.Vector3 value)
371 { 363 {
372 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 364 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
373 { 365 {
374 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
375 }); 367 });
376 } 368 }
377 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 369 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
@@ -391,7 +383,7 @@ public sealed class BSPrim : PhysicsActor
391 383
392 // Called each simulation step to advance vehicle characteristics. 384 // Called each simulation step to advance vehicle characteristics.
393 // Called from Scene when doing simulation step so we're in taint processing time. 385 // Called from Scene when doing simulation step so we're in taint processing time.
394 public void StepVehicle(float timeStep) 386 public override void StepVehicle(float timeStep)
395 { 387 {
396 if (IsPhysical) 388 if (IsPhysical)
397 _vehicle.Step(timeStep); 389 _vehicle.Step(timeStep);
@@ -414,15 +406,15 @@ public sealed class BSPrim : PhysicsActor
414 _velocity = value; 406 _velocity = value;
415 _scene.TaintedObject("BSPrim.setVelocity", delegate() 407 _scene.TaintedObject("BSPrim.setVelocity", delegate()
416 { 408 {
417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 409 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 410 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity);
419 }); 411 });
420 } 412 }
421 } 413 }
422 public override OMV.Vector3 Torque { 414 public override OMV.Vector3 Torque {
423 get { return _torque; } 415 get { return _torque; }
424 set { _torque = value; 416 set { _torque = value;
425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 417 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
426 } 418 }
427 } 419 }
428 public override float CollisionScore { 420 public override float CollisionScore {
@@ -436,10 +428,10 @@ public sealed class BSPrim : PhysicsActor
436 } 428 }
437 public override OMV.Quaternion Orientation { 429 public override OMV.Quaternion Orientation {
438 get { 430 get {
439 if (!_linkset.IsRoot(this)) 431 if (!Linkset.IsRoot(this))
440 { 432 {
441 // Children move around because tied to parent. Get a fresh value. 433 // Children move around because tied to parent. Get a fresh value.
442 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); 434 _orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr);
443 } 435 }
444 return _orientation; 436 return _orientation;
445 } 437 }
@@ -449,15 +441,14 @@ public sealed class BSPrim : PhysicsActor
449 _scene.TaintedObject("BSPrim.setOrientation", delegate() 441 _scene.TaintedObject("BSPrim.setOrientation", delegate()
450 { 442 {
451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 443 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 444 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 445 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
454 }); 446 });
455 } 447 }
456 } 448 }
457 public override int PhysicsActorType { 449 public override int PhysicsActorType {
458 get { return _physicsActorType; } 450 get { return _physicsActorType; }
459 set { _physicsActorType = value; 451 set { _physicsActorType = value; }
460 }
461 } 452 }
462 public override bool IsPhysical { 453 public override bool IsPhysical {
463 get { return _isPhysical; } 454 get { return _isPhysical; }
@@ -484,30 +475,139 @@ public sealed class BSPrim : PhysicsActor
484 475
485 // Make gravity work if the object is physical and not selected 476 // Make gravity work if the object is physical and not selected
486 // No locking here because only called when it is safe 477 // No locking here because only called when it is safe
478 // There are four flags we're interested in:
479 // IsStatic: Object does not move, otherwise the object has mass and moves
480 // isSolid: other objects bounce off of this object
481 // isVolumeDetect: other objects pass through but can generate collisions
482 // collisionEvents: whether this object returns collision events
487 private void SetObjectDynamic() 483 private void SetObjectDynamic()
488 { 484 {
489 // RA: remove this for the moment. 485 // If it's becoming dynamic, it will need hullness
490 // The problem is that dynamic objects are hulls so if we are becoming physical 486 VerifyCorrectPhysicalShape();
491 // the shape has to be checked and possibly built. 487 UpdatePhysicalParameters();
492 // Maybe a VerifyCorrectPhysicalShape() routine? 488 }
493 // RecreateGeomAndObject();
494 489
490 private void UpdatePhysicalParameters()
491 {
492 /*
495 // Bullet wants static objects to have a mass of zero 493 // Bullet wants static objects to have a mass of zero
496 float mass = IsStatic ? 0f : _mass; 494 float mass = IsStatic ? 0f : _mass;
497 495
498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
497 */
498 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr);
499
500 // Set up the object physicalness (does gravity and collisions move this object)
501 MakeDynamic(IsStatic);
502
503 // Make solid or not (do things bounce off or pass through this object)
504 MakeSolid(IsSolid);
505
506 // Arrange for collisions events if the simulator wants them
507 EnableCollisions(SubscribedEvents());
508
509 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr);
499 510
500 // recompute any linkset parameters 511 // Recompute any linkset parameters.
501 _linkset.Refresh(this); 512 // 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.
514 Linkset.Refresh(this);
502 515
503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); 516 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}",
504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); 517 LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags);
518 }
519
520 // "Making dynamic" means changing to and from static.
521 // When static, gravity does not effect the object and it is fixed in space.
522 // When dynamic, the object can fall and be pushed by others.
523 // This is independent of its 'solidness' which controls what passes through
524 // this object and what interacts with it.
525 private void MakeDynamic(bool makeStatic)
526 {
527 if (makeStatic)
528 {
529 // Become a Bullet 'static' object type
530 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
531 // Stop all movement
532 BulletSimAPI.ClearAllForces2(BSBody.Ptr);
533 // Center of mass is at the center of the object
534 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.Ptr, _position, _orientation);
535 // Mass is zero which disables a bunch of physics stuff in Bullet
536 BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero);
537 // There is no inertia in a static object
538 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
539 // There can be special things needed for implementing linksets
540 Linkset.MakeStatic(this);
541 // The activation state is 'sleeping' so Bullet will not try to act on it
542 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING);
543 }
544 else
545 {
546 // Not a Bullet static object
547 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
548
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
553 BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
554 BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
555 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
556
557 // A dynamic object has mass
558 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr);
559 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass);
560 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia);
561 // Inertia is based on our new mass
562 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
563
564 // Various values for simulation limits
565 BulletSimAPI.SetDamping2(BSBody.Ptr, Scene.Params.linearDamping, Scene.Params.angularDamping);
566 BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, Scene.Params.deactivationTime);
567 BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, Scene.Params.linearSleepingThreshold, Scene.Params.angularSleepingThreshold);
568 BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, Scene.Params.contactProcessingThreshold);
569
570 // There can be special things needed for implementing linksets
571 Linkset.MakeDynamic(this);
572
573 // Force activation of the object so Bullet will act on it.
574 BulletSimAPI.Activate2(BSBody.Ptr, true);
575 }
576 }
577
578 // "Making solid" means that other object will not pass through this object.
579 private void MakeSolid(bool makeSolid)
580 {
581 if (makeSolid)
582 {
583 // Easy in Bullet -- just remove the object flag that controls collision response
584 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
585 }
586 else
587 {
588 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
589 }
590 }
591
592 // Turn on or off the flag controlling whether collision events are returned to the simulator.
593 private void EnableCollisions(bool wantsCollisionEvents)
594 {
595 if (wantsCollisionEvents)
596 {
597 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
598 }
599 else
600 {
601 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
602 }
505 } 603 }
506 604
507 // prims don't fly 605 // prims don't fly
508 public override bool Flying { 606 public override bool Flying {
509 get { return _flying; } 607 get { return _flying; }
510 set { _flying = value; } 608 set {
609 _flying = value;
610 }
511 } 611 }
512 public override bool SetAlwaysRun { 612 public override bool SetAlwaysRun {
513 get { return _setAlwaysRun; } 613 get { return _setAlwaysRun; }
@@ -558,8 +658,8 @@ public sealed class BSPrim : PhysicsActor
558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 658 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 659 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
560 { 660 {
561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 661 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 662 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity);
563 }); 663 });
564 } 664 }
565 } 665 }
@@ -575,8 +675,11 @@ public sealed class BSPrim : PhysicsActor
575 _buoyancy = value; 675 _buoyancy = value;
576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 676 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
577 { 677 {
578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 678 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 679 // Buoyancy is faked by changing the gravity applied to the object
680 float grav = Scene.Params.gravity * (1f - _buoyancy);
681 BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav));
682 // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
580 }); 683 });
581 } 684 }
582 } 685 }
@@ -624,7 +727,7 @@ public sealed class BSPrim : PhysicsActor
624 } 727 }
625 else 728 else
626 { 729 {
627 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 730 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
628 return; 731 return;
629 } 732 }
630 _scene.TaintedObject("BSPrim.AddForce", delegate() 733 _scene.TaintedObject("BSPrim.AddForce", delegate()
@@ -638,17 +741,18 @@ public sealed class BSPrim : PhysicsActor
638 } 741 }
639 m_accumulatedForces.Clear(); 742 m_accumulatedForces.Clear();
640 } 743 }
641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 744 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); 745 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
746 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum);
643 }); 747 });
644 } 748 }
645 749
646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 750 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 751 DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
648 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 752 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
649 } 753 }
650 public override void SetMomentum(OMV.Vector3 momentum) { 754 public override void SetMomentum(OMV.Vector3 momentum) {
651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 755 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
652 } 756 }
653 public override void SubscribeEvents(int ms) { 757 public override void SubscribeEvents(int ms) {
654 _subscribedEventsMs = ms; 758 _subscribedEventsMs = ms;
@@ -659,7 +763,7 @@ public sealed class BSPrim : PhysicsActor
659 763
660 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() 764 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
661 { 765 {
662 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 766 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
663 }); 767 });
664 } 768 }
665 } 769 }
@@ -667,7 +771,7 @@ public sealed class BSPrim : PhysicsActor
667 _subscribedEventsMs = 0; 771 _subscribedEventsMs = 0;
668 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() 772 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
669 { 773 {
670 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 774 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
671 }); 775 });
672 } 776 }
673 public override bool SubscribedEvents() { 777 public override bool SubscribedEvents() {
@@ -974,39 +1078,47 @@ public sealed class BSPrim : PhysicsActor
974 }// end CalculateMass 1078 }// end CalculateMass
975 #endregion Mass Calculation 1079 #endregion Mass Calculation
976 1080
977 // Create the geometry information in Bullet for later use 1081 // Create the geometry information in Bullet for later use.
978 // The objects needs a hull if it's physical otherwise a mesh is enough 1082 // The objects needs a hull if it's physical otherwise a mesh is enough.
979 // No locking here because this is done when we know physics is not simulating 1083 // No locking here because this is done when we know physics is not simulating.
980 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used 1084 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
981 // Returns 'true' if the geometry was rebuilt 1085 // Returns 'true' if the geometry was rebuilt.
1086 // Called at taint-time!
982 private bool CreateGeom(bool forceRebuild) 1087 private bool CreateGeom(bool forceRebuild)
983 { 1088 {
984 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
985 bool ret = false; 1089 bool ret = false;
986 if (!_scene.NeedsMeshing(_pbs)) 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) )
987 { 1101 {
988 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 1102 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
989 { 1103 {
990 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 1104 haveShape = true;
991 // { 1105 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
992 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 1106 {
993 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 1107 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
994 { 1108 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
995 // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); 1109 // Bullet native objects are scaled by the Bullet engine so pass the size in
996 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 1110 _scale = _size;
997 // Bullet native objects are scaled by the Bullet engine so pass the size in 1111 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
998 _scale = _size; 1112 ret = true;
999 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1113 }
1000 ret = true;
1001 }
1002 // }
1003 } 1114 }
1004 else 1115 else
1005 { 1116 {
1006 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1117 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1118 haveShape = true;
1007 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1119 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1008 { 1120 {
1009 // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); 1121 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
1010 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1122 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
1011 _scale = _size; 1123 _scale = _size;
1012 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1124 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@@ -1014,16 +1126,16 @@ public sealed class BSPrim : PhysicsActor
1014 } 1126 }
1015 } 1127 }
1016 } 1128 }
1017 else 1129 // If a simple shape isn't happening, create a mesh and possibly a hull
1130 if (!haveShape)
1018 { 1131 {
1019 if (IsPhysical) 1132 if (IsPhysical)
1020 { 1133 {
1021 if (forceRebuild || _hullKey == 0) 1134 if (forceRebuild || _hullKey == 0)
1022 { 1135 {
1023 // physical objects require a hull for interaction. 1136 // physical objects require a hull for interaction.
1024 // This will create the mesh if it doesn't already exist 1137 // This also creates the mesh if it doesn't already exist
1025 CreateGeomHull(); 1138 ret = CreateGeomHull();
1026 ret = true;
1027 } 1139 }
1028 } 1140 }
1029 else 1141 else
@@ -1031,8 +1143,7 @@ public sealed class BSPrim : PhysicsActor
1031 if (forceRebuild || _meshKey == 0) 1143 if (forceRebuild || _meshKey == 0)
1032 { 1144 {
1033 // Static (non-physical) objects only need a mesh for bumping into 1145 // Static (non-physical) objects only need a mesh for bumping into
1034 CreateGeomMesh(); 1146 ret = CreateGeomMesh();
1035 ret = true;
1036 } 1147 }
1037 } 1148 }
1038 } 1149 }
@@ -1040,21 +1151,30 @@ public sealed class BSPrim : PhysicsActor
1040 } 1151 }
1041 1152
1042 // No locking here because this is done when we know physics is not simulating 1153 // No locking here because this is done when we know physics is not simulating
1043 private void CreateGeomMesh() 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()
1044 { 1157 {
1045 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 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
1046 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); 1166 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
1047 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); 1167 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
1048 1168
1049 // if this new shape is the same as last time, don't recreate the mesh 1169 // if this new shape is the same as last time, don't recreate the mesh
1050 if (_meshKey == newMeshKey) return; 1170 if (_meshKey == newMeshKey) return false;
1051 1171
1052 // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); 1172 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1053 // Since we're recreating new, get rid of any previously generated shape 1173 // Since we're recreating new, get rid of any previously generated shape
1054 if (_meshKey != 0) 1174 if (_meshKey != 0)
1055 { 1175 {
1056 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1176 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1057 // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1177 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1058 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1178 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1059 _mesh = null; 1179 _mesh = null;
1060 _meshKey = 0; 1180 _meshKey = 0;
@@ -1084,27 +1204,27 @@ public sealed class BSPrim : PhysicsActor
1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1204 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1085 // meshes are already scaled by the meshmerizer 1205 // meshes are already scaled by the meshmerizer
1086 _scale = new OMV.Vector3(1f, 1f, 1f); 1206 _scale = new OMV.Vector3(1f, 1f, 1f);
1087 // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); 1207 return true;
1088 return;
1089 } 1208 }
1090 1209
1091 // No locking here because this is done when we know physics is not simulating 1210 // No locking here because this is done when we know physics is not simulating
1092 private void CreateGeomHull() 1211 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1212 private bool CreateGeomHull()
1093 { 1213 {
1094 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1214 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1095 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); 1215 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
1096 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); 1216 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
1097 1217
1098 // if the hull hasn't changed, don't rebuild it 1218 // if the hull hasn't changed, don't rebuild it
1099 if (newHullKey == _hullKey) return; 1219 if (newHullKey == _hullKey) return false;
1100 1220
1101 // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); 1221 DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1102 1222
1103 // Since we're recreating new, get rid of any previously generated shape 1223 // Since we're recreating new, get rid of any previously generated shape
1104 if (_hullKey != 0) 1224 if (_hullKey != 0)
1105 { 1225 {
1106 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1226 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1107 // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); 1227 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1108 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1228 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1109 _hullKey = 0; 1229 _hullKey = 0;
1110 } 1230 }
@@ -1198,8 +1318,8 @@ public sealed class BSPrim : PhysicsActor
1198 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1318 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1199 // meshes are already scaled by the meshmerizer 1319 // meshes are already scaled by the meshmerizer
1200 _scale = new OMV.Vector3(1f, 1f, 1f); 1320 _scale = new OMV.Vector3(1f, 1f, 1f);
1201 // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); 1321 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1202 return; 1322 return true;
1203 } 1323 }
1204 1324
1205 // Callback from convex hull creater with a newly created hull. 1325 // Callback from convex hull creater with a newly created hull.
@@ -1210,6 +1330,19 @@ public sealed class BSPrim : PhysicsActor
1210 return; 1330 return;
1211 } 1331 }
1212 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
1213 // Create an object in Bullet if it has not already been created 1346 // Create an object in Bullet if it has not already been created
1214 // No locking here because this is done when the physics engine is not simulating 1347 // No locking here because this is done when the physics engine is not simulating
1215 // Returns 'true' if an object was actually created. 1348 // Returns 'true' if an object was actually created.
@@ -1223,8 +1356,9 @@ public sealed class BSPrim : PhysicsActor
1223 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); 1356 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1224 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1357 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1225 1358
1226 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1359 // the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
1227 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 1360 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1361 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
1228 1362
1229 return ret; 1363 return ret;
1230 } 1364 }
@@ -1248,15 +1382,20 @@ public sealed class BSPrim : PhysicsActor
1248 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1382 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1249 } 1383 }
1250 1384
1251
1252 // Rebuild the geometry and object. 1385 // Rebuild the geometry and object.
1253 // This is called when the shape changes so we need to recreate the mesh/hull. 1386 // This is called when the shape changes so we need to recreate the mesh/hull.
1254 // No locking here because this is done when the physics engine is not simulating 1387 // No locking here because this is done when the physics engine is not simulating
1255 private void RecreateGeomAndObject() 1388 private void CreateGeomAndObject(bool forceRebuild)
1256 { 1389 {
1257 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); 1390 // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild);
1258 if (CreateGeom(true)) 1391 // Create the geometry that will make up the object
1392 if (CreateGeom(forceRebuild))
1393 {
1394 // Create the object and place it into the world
1259 CreateObject(); 1395 CreateObject();
1396 // Make sure the properties are set on the new object
1397 UpdatePhysicalParameters();
1398 }
1260 return; 1399 return;
1261 } 1400 }
1262 1401
@@ -1277,7 +1416,7 @@ public sealed class BSPrim : PhysicsActor
1277 const float ACCELERATION_TOLERANCE = 0.01f; 1416 const float ACCELERATION_TOLERANCE = 0.01f;
1278 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1417 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1279 1418
1280 public void UpdateProperties(EntityProperties entprop) 1419 public override void UpdateProperties(EntityProperties entprop)
1281 { 1420 {
1282 /* 1421 /*
1283 UpdatedProperties changed = 0; 1422 UpdatedProperties changed = 0;
@@ -1325,7 +1464,7 @@ public sealed class BSPrim : PhysicsActor
1325 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1464 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1326 1465
1327 // Updates only for individual prims and for the root object of a linkset. 1466 // Updates only for individual prims and for the root object of a linkset.
1328 if (_linkset.IsRoot(this)) 1467 if (Linkset.IsRoot(this))
1329 { 1468 {
1330 // Assign to the local variables so the normal set action does not happen 1469 // Assign to the local variables so the normal set action does not happen
1331 _position = entprop.Position; 1470 _position = entprop.Position;
@@ -1334,17 +1473,17 @@ public sealed class BSPrim : PhysicsActor
1334 _acceleration = entprop.Acceleration; 1473 _acceleration = entprop.Acceleration;
1335 _rotationalVelocity = entprop.RotationalVelocity; 1474 _rotationalVelocity = entprop.RotationalVelocity;
1336 1475
1337 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1476 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1477 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1339 // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1478
1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1479 // BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr);
1341 1480
1342 base.RequestPhysicsterseUpdate(); 1481 base.RequestPhysicsterseUpdate();
1343 } 1482 }
1344 /* 1483 /*
1345 else 1484 else
1346 { 1485 {
1347 // For debugging, we also report the movement of children 1486 // For debugging, we can also report the movement of children
1348 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1487 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1349 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1488 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1350 entprop.Acceleration, entprop.RotationalVelocity); 1489 entprop.Acceleration, entprop.RotationalVelocity);
@@ -1353,36 +1492,45 @@ public sealed class BSPrim : PhysicsActor
1353 } 1492 }
1354 1493
1355 // I've collided with something 1494 // I've collided with something
1495 // Called at taint time from within the Step() function
1356 CollisionEventUpdate collisionCollection; 1496 CollisionEventUpdate collisionCollection;
1357 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 1497 public override bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1358 { 1498 {
1359 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 1499 bool ret = false;
1360 1500
1361 // The following lines make IsColliding() and IsCollidingGround() work 1501 // The following lines make IsColliding() and IsCollidingGround() work
1362 _collidingStep = _scene.SimulationStep; 1502 _collidingStep = Scene.SimulationStep;
1363 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) 1503 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
1364 { 1504 {
1365 _collidingGroundStep = _scene.SimulationStep; 1505 _collidingGroundStep = Scene.SimulationStep;
1366 } 1506 }
1367 1507
1368 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); 1508 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1369 1509
1370 // if someone is subscribed to collision events.... 1510 // prims in the same linkset cannot collide with each other
1371 if (_subscribedEventsMs != 0) { 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()) {
1372 // throttle the collisions to the number of milliseconds specified in the subscription 1518 // throttle the collisions to the number of milliseconds specified in the subscription
1373 int nowTime = _scene.SimulationNowTime; 1519 int nowTime = Scene.SimulationNowTime;
1374 if (nowTime >= _nextCollisionOkTime) { 1520 if (nowTime >= _nextCollisionOkTime) {
1375 _nextCollisionOkTime = nowTime + _subscribedEventsMs; 1521 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1376 1522
1377 if (collisionCollection == null) 1523 if (collisionCollection == null)
1378 collisionCollection = new CollisionEventUpdate(); 1524 collisionCollection = new CollisionEventUpdate();
1379 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 1525 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1526 ret = true;
1380 } 1527 }
1381 } 1528 }
1529 return ret;
1382 } 1530 }
1383 1531
1384 // The scene is telling us it's time to pass our collected collisions into the simulator 1532 // The scene is telling us it's time to pass our collected collisions into the simulator
1385 public void SendCollisions() 1533 public override void SendCollisions()
1386 { 1534 {
1387 if (collisionCollection != null && collisionCollection.Count > 0) 1535 if (collisionCollection != null && collisionCollection.Count > 0)
1388 { 1536 {