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.cs250
1 files changed, 158 insertions, 92 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 6d0af63..26a581f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -136,11 +136,11 @@ public sealed class BSPrim : BSPhysObject
136 Linkset = new BSLinkset(Scene, this); // a linkset of one 136 Linkset = new BSLinkset(Scene, this); // a linkset of one
137 _vehicle = new BSDynamics(Scene, this); // add vehicleness 137 _vehicle = new BSDynamics(Scene, this); // add vehicleness
138 _mass = CalculateMass(); 138 _mass = CalculateMass();
139 // do the actual object creation at taint time
140 DetailLog("{0},BSPrim.constructor,call", LocalID); 139 DetailLog("{0},BSPrim.constructor,call", LocalID);
140 // do the actual object creation at taint time
141 _scene.TaintedObject("BSPrim.create", delegate() 141 _scene.TaintedObject("BSPrim.create", delegate()
142 { 142 {
143 RecreateGeomAndObject(); 143 CreateGeomAndObject(true);
144 144
145 // Get the pointer to the physical body for this object. 145 // Get the pointer to the physical body for this object.
146 // 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
@@ -186,9 +186,10 @@ public sealed class BSPrim : BSPhysObject
186 _scene.TaintedObject("BSPrim.setSize", delegate() 186 _scene.TaintedObject("BSPrim.setSize", delegate()
187 { 187 {
188 _mass = CalculateMass(); // changing size changes the mass 188 _mass = CalculateMass(); // changing size changes the mass
189 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
190 DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); 190 // scale and margins are set.
191 RecreateGeomAndObject(); 191 CreateGeomAndObject(true);
192 DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical);
192 }); 193 });
193 } 194 }
194 } 195 }
@@ -198,7 +199,7 @@ public sealed class BSPrim : BSPhysObject
198 _scene.TaintedObject("BSPrim.setShape", delegate() 199 _scene.TaintedObject("BSPrim.setShape", delegate()
199 { 200 {
200 _mass = CalculateMass(); // changing the shape changes the mass 201 _mass = CalculateMass(); // changing the shape changes the mass
201 RecreateGeomAndObject(); 202 CreateGeomAndObject(false);
202 }); 203 });
203 } 204 }
204 } 205 }
@@ -279,7 +280,7 @@ public sealed class BSPrim : BSPhysObject
279 get { 280 get {
280 if (!Linkset.IsRoot(this)) 281 if (!Linkset.IsRoot(this))
281 // 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
282 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 283 _position = BulletSimAPI.GetPosition2(BSBody.Ptr);
283 284
284 // 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
285 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 286 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
@@ -291,7 +292,7 @@ public sealed class BSPrim : BSPhysObject
291 _scene.TaintedObject("BSPrim.setPosition", delegate() 292 _scene.TaintedObject("BSPrim.setPosition", delegate()
292 { 293 {
293 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);
294 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 295 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
295 }); 296 });
296 } 297 }
297 } 298 }
@@ -302,7 +303,8 @@ public sealed class BSPrim : BSPhysObject
302 { 303 {
303 get 304 get
304 { 305 {
305 return Linkset.LinksetMass; 306 // return Linkset.LinksetMass;
307 return _mass;
306 } 308 }
307 } 309 }
308 310
@@ -328,7 +330,6 @@ public sealed class BSPrim : BSPhysObject
328 _scene.TaintedObject("BSPrim.setForce", delegate() 330 _scene.TaintedObject("BSPrim.setForce", delegate()
329 { 331 {
330 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 332 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
331 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
332 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); 333 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
333 }); 334 });
334 } 335 }
@@ -345,7 +346,7 @@ public sealed class BSPrim : BSPhysObject
345 { 346 {
346 // Done at taint time so we're sure the physics engine is not using the variables 347 // Done at taint time so we're sure the physics engine is not using the variables
347 // Vehicle code changes the parameters for this vehicle type. 348 // Vehicle code changes the parameters for this vehicle type.
348 _vehicle.ProcessTypeChange(type, Scene.LastSimulatedTimestep); 349 _vehicle.ProcessTypeChange(type);
349 // Tell the scene about the vehicle so it will get processing each frame. 350 // Tell the scene about the vehicle so it will get processing each frame.
350 _scene.VehicleInSceneTypeChanged(this, type); 351 _scene.VehicleInSceneTypeChanged(this, type);
351 }); 352 });
@@ -355,14 +356,14 @@ public sealed class BSPrim : BSPhysObject
355 { 356 {
356 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 357 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
357 { 358 {
358 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 359 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
359 }); 360 });
360 } 361 }
361 public override void VehicleVectorParam(int param, OMV.Vector3 value) 362 public override void VehicleVectorParam(int param, OMV.Vector3 value)
362 { 363 {
363 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 364 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
364 { 365 {
365 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
366 }); 367 });
367 } 368 }
368 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 369 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
@@ -406,7 +407,7 @@ public sealed class BSPrim : BSPhysObject
406 _scene.TaintedObject("BSPrim.setVelocity", delegate() 407 _scene.TaintedObject("BSPrim.setVelocity", delegate()
407 { 408 {
408 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 409 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
409 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 410 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity);
410 }); 411 });
411 } 412 }
412 } 413 }
@@ -430,7 +431,7 @@ public sealed class BSPrim : BSPhysObject
430 if (!Linkset.IsRoot(this)) 431 if (!Linkset.IsRoot(this))
431 { 432 {
432 // Children move around because tied to parent. Get a fresh value. 433 // Children move around because tied to parent. Get a fresh value.
433 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); 434 _orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr);
434 } 435 }
435 return _orientation; 436 return _orientation;
436 } 437 }
@@ -441,7 +442,7 @@ public sealed class BSPrim : BSPhysObject
441 { 442 {
442 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 443 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
443 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);
444 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 445 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
445 }); 446 });
446 } 447 }
447 } 448 }
@@ -483,31 +484,37 @@ public sealed class BSPrim : BSPhysObject
483 { 484 {
484 // If it's becoming dynamic, it will need hullness 485 // If it's becoming dynamic, it will need hullness
485 VerifyCorrectPhysicalShape(); 486 VerifyCorrectPhysicalShape();
487 UpdatePhysicalParameters();
488 }
486 489
490 private void UpdatePhysicalParameters()
491 {
492 /*
487 // Bullet wants static objects to have a mass of zero 493 // Bullet wants static objects to have a mass of zero
488 float mass = IsStatic ? 0f : _mass; 494 float mass = IsStatic ? 0f : _mass;
489 495
490 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
491 /* 497 */
492 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr); 498 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr);
493 499
494 // Set up the object physicalness (static or dynamic) 500 // Set up the object physicalness (does gravity and collisions move this object)
495 MakeDynamic(); 501 MakeDynamic(IsStatic);
496 502
497 // Make solid or not and arrange for collisions, etc 503 // Make solid or not (do things bounce off or pass through this object)
498 MakeSolid(); 504 MakeSolid(IsSolid);
499 505
500 m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); 506 // Arrange for collisions events if the simulator wants them
507 EnableCollisions(SubscribedEvents());
501 508
502 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); 509 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr);
503 */
504 510
505 // Recompute any linkset parameters. 511 // Recompute any linkset parameters.
506 // When going from non-physical to physical, this re-enables the constraints that 512 // When going from non-physical to physical, this re-enables the constraints that
507 // had been automatically disabled when the mass was set to zero. 513 // had been automatically disabled when the mass was set to zero.
508 Linkset.Refresh(this); 514 Linkset.Refresh(this);
509 515
510 DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, m_currentCollisionFlags); 516 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}",
517 LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags);
511 } 518 }
512 519
513 // "Making dynamic" means changing to and from static. 520 // "Making dynamic" means changing to and from static.
@@ -515,39 +522,84 @@ public sealed class BSPrim : BSPhysObject
515 // When dynamic, the object can fall and be pushed by others. 522 // When dynamic, the object can fall and be pushed by others.
516 // This is independent of its 'solidness' which controls what passes through 523 // This is independent of its 'solidness' which controls what passes through
517 // this object and what interacts with it. 524 // this object and what interacts with it.
518 private void MakeDynamic() 525 private void MakeDynamic(bool makeStatic)
519 { 526 {
520 if (IsStatic) 527 if (makeStatic)
521 { 528 {
522 // Become a Bullet 'static' object type 529 // Become a Bullet 'static' object type
523 BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); 530 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
524 // Stop all movement 531 // Stop all movement
525 BulletSimAPI.ClearAllForces2(BSBody.Ptr); 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);
526 // Mass is zero which disables a bunch of physics stuff in Bullet 535 // Mass is zero which disables a bunch of physics stuff in Bullet
527 BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero); 536 BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero);
528 // There is no inertia in a static object 537 // There is no inertia in a static object
529 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); 538 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
539 // There can be special things needed for implementing linksets
540 Linkset.MakeStatic(this);
530 // The activation state is 'sleeping' so Bullet will not try to act on it 541 // The activation state is 'sleeping' so Bullet will not try to act on it
531 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); 542 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING);
532 } 543 }
533 else 544 else
534 { 545 {
535 // Not a Bullet static object 546 // Not a Bullet static object
536 BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_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
537 // A dynamic object has mass 557 // A dynamic object has mass
538 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, OMV.Vector3.Zero);
539 // The shape is interesting and has mass and a center of gravity
540 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); 558 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr);
541 BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero); 559 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass);
560 BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia);
542 // Inertia is based on our new mass 561 // Inertia is based on our new mass
543 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); 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
544 // Force activation of the object so Bullet will act on it. 573 // Force activation of the object so Bullet will act on it.
545 BulletSimAPI.Activate2(BSBody.Ptr, true); 574 BulletSimAPI.Activate2(BSBody.Ptr, true);
546 } 575 }
547 } 576 }
548 577
549 private void MakeSolid() 578 // "Making solid" means that other object will not pass through this object.
579 private void MakeSolid(bool makeSolid)
550 { 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 }
551 } 603 }
552 604
553 // prims don't fly 605 // prims don't fly
@@ -607,7 +659,7 @@ public sealed class BSPrim : BSPhysObject
607 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 659 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
608 { 660 {
609 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 661 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
610 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 662 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity);
611 }); 663 });
612 } 664 }
613 } 665 }
@@ -624,7 +676,10 @@ public sealed class BSPrim : BSPhysObject
624 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 676 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
625 { 677 {
626 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 678 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
627 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);
628 }); 683 });
629 } 684 }
630 } 685 }
@@ -686,8 +741,8 @@ public sealed class BSPrim : BSPhysObject
686 } 741 }
687 m_accumulatedForces.Clear(); 742 m_accumulatedForces.Clear();
688 } 743 }
689 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 744 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
690 // For unknown reason, "ApplyCentralForce" is really additive. 745 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
691 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); 746 BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum);
692 }); 747 });
693 } 748 }
@@ -1023,36 +1078,44 @@ public sealed class BSPrim : BSPhysObject
1023 }// end CalculateMass 1078 }// end CalculateMass
1024 #endregion Mass Calculation 1079 #endregion Mass Calculation
1025 1080
1026 // Create the geometry information in Bullet for later use 1081 // Create the geometry information in Bullet for later use.
1027 // 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.
1028 // 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.
1029 // 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.
1030 // Returns 'true' if the geometry was rebuilt 1085 // Returns 'true' if the geometry was rebuilt.
1086 // Called at taint-time!
1031 private bool CreateGeom(bool forceRebuild) 1087 private bool CreateGeom(bool forceRebuild)
1032 { 1088 {
1033 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
1034 bool ret = false; 1089 bool ret = false;
1035 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) )
1036 { 1101 {
1037 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 1102 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1038 { 1103 {
1039 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 1104 haveShape = true;
1040 // { 1105 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
1041 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 1106 {
1042 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 1107 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
1043 { 1108 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
1044 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); 1109 // Bullet native objects are scaled by the Bullet engine so pass the size in
1045 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 1110 _scale = _size;
1046 // 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?
1047 _scale = _size; 1112 ret = true;
1048 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1113 }
1049 ret = true;
1050 }
1051 // }
1052 } 1114 }
1053 else 1115 else
1054 { 1116 {
1055 // 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;
1056 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1119 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1057 { 1120 {
1058 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); 1121 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
@@ -1063,16 +1126,16 @@ public sealed class BSPrim : BSPhysObject
1063 } 1126 }
1064 } 1127 }
1065 } 1128 }
1066 else 1129 // If a simple shape isn't happening, create a mesh and possibly a hull
1130 if (!haveShape)
1067 { 1131 {
1068 if (IsPhysical) 1132 if (IsPhysical)
1069 { 1133 {
1070 if (forceRebuild || _hullKey == 0) 1134 if (forceRebuild || _hullKey == 0)
1071 { 1135 {
1072 // physical objects require a hull for interaction. 1136 // physical objects require a hull for interaction.
1073 // This will create the mesh if it doesn't already exist 1137 // This also creates the mesh if it doesn't already exist
1074 CreateGeomHull(); 1138 ret = CreateGeomHull();
1075 ret = true;
1076 } 1139 }
1077 } 1140 }
1078 else 1141 else
@@ -1080,8 +1143,7 @@ public sealed class BSPrim : BSPhysObject
1080 if (forceRebuild || _meshKey == 0) 1143 if (forceRebuild || _meshKey == 0)
1081 { 1144 {
1082 // Static (non-physical) objects only need a mesh for bumping into 1145 // Static (non-physical) objects only need a mesh for bumping into
1083 CreateGeomMesh(); 1146 ret = CreateGeomMesh();
1084 ret = true;
1085 } 1147 }
1086 } 1148 }
1087 } 1149 }
@@ -1089,7 +1151,9 @@ public sealed class BSPrim : BSPhysObject
1089 } 1151 }
1090 1152
1091 // 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
1092 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()
1093 { 1157 {
1094 // level of detail based on size and type of the object 1158 // level of detail based on size and type of the object
1095 float lod = _scene.MeshLOD; 1159 float lod = _scene.MeshLOD;
@@ -1103,7 +1167,7 @@ public sealed class BSPrim : BSPhysObject
1103 // 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);
1104 1168
1105 // 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
1106 if (_meshKey == newMeshKey) return; 1170 if (_meshKey == newMeshKey) return false;
1107 1171
1108 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); 1172 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1109 // 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
@@ -1140,19 +1204,19 @@ public sealed class BSPrim : BSPhysObject
1140 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1204 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1141 // meshes are already scaled by the meshmerizer 1205 // meshes are already scaled by the meshmerizer
1142 _scale = new OMV.Vector3(1f, 1f, 1f); 1206 _scale = new OMV.Vector3(1f, 1f, 1f);
1143 DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); 1207 return true;
1144 return;
1145 } 1208 }
1146 1209
1147 // 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
1148 private void CreateGeomHull() 1211 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1212 private bool CreateGeomHull()
1149 { 1213 {
1150 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1214 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1151 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); 1215 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
1152 // 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);
1153 1217
1154 // if the hull hasn't changed, don't rebuild it 1218 // if the hull hasn't changed, don't rebuild it
1155 if (newHullKey == _hullKey) return; 1219 if (newHullKey == _hullKey) return false;
1156 1220
1157 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);
1158 1222
@@ -1255,7 +1319,7 @@ public sealed class BSPrim : BSPhysObject
1255 // meshes are already scaled by the meshmerizer 1319 // meshes are already scaled by the meshmerizer
1256 _scale = new OMV.Vector3(1f, 1f, 1f); 1320 _scale = new OMV.Vector3(1f, 1f, 1f);
1257 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); 1321 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1258 return; 1322 return true;
1259 } 1323 }
1260 1324
1261 // Callback from convex hull creater with a newly created hull. 1325 // Callback from convex hull creater with a newly created hull.
@@ -1268,20 +1332,12 @@ public sealed class BSPrim : BSPhysObject
1268 1332
1269 private void VerifyCorrectPhysicalShape() 1333 private void VerifyCorrectPhysicalShape()
1270 { 1334 {
1271 if (IsStatic) 1335 if (!IsStatic)
1272 {
1273 // if static, we don't need a hull so, if there is one, rebuild without it
1274 if (_hullKey != 0)
1275 {
1276 RecreateGeomAndObject();
1277 }
1278 }
1279 else
1280 { 1336 {
1281 // if not static, it will need a hull to efficiently collide with things 1337 // if not static, it will need a hull to efficiently collide with things
1282 if (_hullKey == 0) 1338 if (_hullKey == 0)
1283 { 1339 {
1284 RecreateGeomAndObject(); 1340 CreateGeomAndObject(false);
1285 } 1341 }
1286 1342
1287 } 1343 }
@@ -1300,8 +1356,9 @@ public sealed class BSPrim : BSPhysObject
1300 // 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);
1301 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1357 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1302 1358
1303 // 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.
1304 BSBody = 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));
1305 1362
1306 return ret; 1363 return ret;
1307 } 1364 }
@@ -1325,15 +1382,20 @@ public sealed class BSPrim : BSPhysObject
1325 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1382 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1326 } 1383 }
1327 1384
1328
1329 // Rebuild the geometry and object. 1385 // Rebuild the geometry and object.
1330 // 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.
1331 // 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
1332 private void RecreateGeomAndObject() 1388 private void CreateGeomAndObject(bool forceRebuild)
1333 { 1389 {
1334 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); 1390 // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild);
1335 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
1336 CreateObject(); 1395 CreateObject();
1396 // Make sure the properties are set on the new object
1397 UpdatePhysicalParameters();
1398 }
1337 return; 1399 return;
1338 } 1400 }
1339 1401
@@ -1414,12 +1476,14 @@ public sealed class BSPrim : BSPhysObject
1414 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1476 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1415 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1477 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1416 1478
1479 // BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr);
1480
1417 base.RequestPhysicsterseUpdate(); 1481 base.RequestPhysicsterseUpdate();
1418 } 1482 }
1419 /* 1483 /*
1420 else 1484 else
1421 { 1485 {
1422 // For debugging, we also report the movement of children 1486 // For debugging, we can also report the movement of children
1423 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}",
1424 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1488 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1425 entprop.Acceleration, entprop.RotationalVelocity); 1489 entprop.Acceleration, entprop.RotationalVelocity);
@@ -1430,15 +1494,15 @@ public sealed class BSPrim : BSPhysObject
1430 // I've collided with something 1494 // I've collided with something
1431 // Called at taint time from within the Step() function 1495 // Called at taint time from within the Step() function
1432 CollisionEventUpdate collisionCollection; 1496 CollisionEventUpdate collisionCollection;
1433 public override void Collide(uint collidingWith, BSPhysObject collidee, 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)
1434 { 1498 {
1435 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 1499 bool ret = false;
1436 1500
1437 // The following lines make IsColliding() and IsCollidingGround() work 1501 // The following lines make IsColliding() and IsCollidingGround() work
1438 _collidingStep = _scene.SimulationStep; 1502 _collidingStep = Scene.SimulationStep;
1439 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) 1503 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
1440 { 1504 {
1441 _collidingGroundStep = _scene.SimulationStep; 1505 _collidingGroundStep = Scene.SimulationStep;
1442 } 1506 }
1443 1507
1444 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); 1508 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
@@ -1446,21 +1510,23 @@ public sealed class BSPrim : BSPhysObject
1446 // prims in the same linkset cannot collide with each other 1510 // prims in the same linkset cannot collide with each other
1447 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) 1511 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
1448 { 1512 {
1449 return; 1513 return ret;
1450 } 1514 }
1451 1515
1452 // if someone has subscribed for collision events.... 1516 // if someone has subscribed for collision events....
1453 if (SubscribedEvents()) { 1517 if (SubscribedEvents()) {
1454 // 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
1455 int nowTime = _scene.SimulationNowTime; 1519 int nowTime = Scene.SimulationNowTime;
1456 if (nowTime >= _nextCollisionOkTime) { 1520 if (nowTime >= _nextCollisionOkTime) {
1457 _nextCollisionOkTime = nowTime + _subscribedEventsMs; 1521 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1458 1522
1459 if (collisionCollection == null) 1523 if (collisionCollection == null)
1460 collisionCollection = new CollisionEventUpdate(); 1524 collisionCollection = new CollisionEventUpdate();
1461 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 1525 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1526 ret = true;
1462 } 1527 }
1463 } 1528 }
1529 return ret;
1464 } 1530 }
1465 1531
1466 // 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