diff options
author | Robert Adams | 2012-09-13 08:11:54 -0700 |
---|---|---|
committer | Robert Adams | 2012-09-15 15:31:29 -0700 |
commit | 2c5ff9399063080276a23bcd06fb696d653bef2e (patch) | |
tree | 3428eaff2697b562880c75f5f83eafcbb855c93e /OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |
parent | Add basic asset connector tests to check behaviour for normal, local and temp... (diff) | |
download | opensim-SC-2c5ff9399063080276a23bcd06fb696d653bef2e.zip opensim-SC-2c5ff9399063080276a23bcd06fb696d653bef2e.tar.gz opensim-SC-2c5ff9399063080276a23bcd06fb696d653bef2e.tar.bz2 opensim-SC-2c5ff9399063080276a23bcd06fb696d653bef2e.tar.xz |
BulletSim: Way too many changes in one commit.
Many changes to BSDynamic for readability and commentary.
Linkset hacking for vehicles: don't over mass the root prim.
Add parameter for link constraint solver iterations.
Correct uses of timestep in timescale calculations for vehicles.
Reorganize code/logic for making objects static and dynamic for readability
and use of API2.
Changed most calls in BSPrim to use API2 calls (the new way).
Avatars do not generate default Bullet collision events but do call up
to the simulator for every avatar. Reduces overhead.
Objects added to collision list only if they are processing collisions.
Reduces overhead especially for large numbers of avatars.
Generalize call for water height to GetWaterHeightAtXYZ().
Catch and correct exception getting terrain height when out of bounds.
Correct race condition in Terrain Manager where creation wasn't at taint-time.
Add API calls for constructing compound shapes.
Move NeedsMeshing() logic into object class.
Reorganize logic for object meshing to reduce rebuilding of meshs/hulls.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 196 |
1 files changed, 118 insertions, 78 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6d0af63..481a8db 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 | } |
@@ -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,12 +522,12 @@ 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); |
526 | // Mass is zero which disables a bunch of physics stuff in Bullet | 533 | // Mass is zero which disables a bunch of physics stuff in Bullet |
@@ -533,12 +540,11 @@ public sealed class BSPrim : BSPhysObject | |||
533 | else | 540 | else |
534 | { | 541 | { |
535 | // Not a Bullet static object | 542 | // Not a Bullet static object |
536 | BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); | 543 | m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); |
537 | // A dynamic object has mass | 544 | // 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); | 545 | IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); |
541 | BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero); | 546 | OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass); |
547 | BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia); | ||
542 | // Inertia is based on our new mass | 548 | // Inertia is based on our new mass |
543 | BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); | 549 | BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); |
544 | // Force activation of the object so Bullet will act on it. | 550 | // Force activation of the object so Bullet will act on it. |
@@ -546,8 +552,31 @@ public sealed class BSPrim : BSPhysObject | |||
546 | } | 552 | } |
547 | } | 553 | } |
548 | 554 | ||
549 | private void MakeSolid() | 555 | // "Making solid" means that other object will not pass through this object. |
556 | private void MakeSolid(bool makeSolid) | ||
550 | { | 557 | { |
558 | if (makeSolid) | ||
559 | { | ||
560 | // Easy in Bullet -- just remove the object flag that controls collision response | ||
561 | m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
562 | } | ||
563 | else | ||
564 | { | ||
565 | m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
566 | } | ||
567 | } | ||
568 | |||
569 | // Turn on or off the flag controlling whether collision events are returned to the simulator. | ||
570 | private void EnableCollisions(bool wantsCollisionEvents) | ||
571 | { | ||
572 | if (wantsCollisionEvents) | ||
573 | { | ||
574 | m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
575 | } | ||
576 | else | ||
577 | { | ||
578 | m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
579 | } | ||
551 | } | 580 | } |
552 | 581 | ||
553 | // prims don't fly | 582 | // prims don't fly |
@@ -607,7 +636,7 @@ public sealed class BSPrim : BSPhysObject | |||
607 | _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() | 636 | _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() |
608 | { | 637 | { |
609 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | 638 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); |
610 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); | 639 | BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity); |
611 | }); | 640 | }); |
612 | } | 641 | } |
613 | } | 642 | } |
@@ -624,7 +653,10 @@ public sealed class BSPrim : BSPhysObject | |||
624 | _scene.TaintedObject("BSPrim.setBuoyancy", delegate() | 653 | _scene.TaintedObject("BSPrim.setBuoyancy", delegate() |
625 | { | 654 | { |
626 | DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 655 | DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
627 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); | 656 | // Buoyancy is faked by changing the gravity applied to the object |
657 | float grav = Scene.Params.gravity * (1f - _buoyancy); | ||
658 | BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav)); | ||
659 | // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); | ||
628 | }); | 660 | }); |
629 | } | 661 | } |
630 | } | 662 | } |
@@ -686,8 +718,8 @@ public sealed class BSPrim : BSPhysObject | |||
686 | } | 718 | } |
687 | m_accumulatedForces.Clear(); | 719 | m_accumulatedForces.Clear(); |
688 | } | 720 | } |
689 | DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); | 721 | DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); |
690 | // For unknown reason, "ApplyCentralForce" is really additive. | 722 | // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. |
691 | BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); | 723 | BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); |
692 | }); | 724 | }); |
693 | } | 725 | } |
@@ -1030,29 +1062,36 @@ public sealed class BSPrim : BSPhysObject | |||
1030 | // Returns 'true' if the geometry was rebuilt | 1062 | // Returns 'true' if the geometry was rebuilt |
1031 | private bool CreateGeom(bool forceRebuild) | 1063 | private bool CreateGeom(bool forceRebuild) |
1032 | { | 1064 | { |
1033 | // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. | ||
1034 | bool ret = false; | 1065 | bool ret = false; |
1035 | if (!_scene.NeedsMeshing(_pbs)) | 1066 | bool haveShape = false; |
1067 | |||
1068 | // If the prim attributes are simple, this could be a simple Bullet native shape | ||
1069 | if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim) | ||
1070 | || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0 | ||
1071 | && _pbs.ProfileHollow == 0 | ||
1072 | && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0 | ||
1073 | && _pbs.PathBegin == 0 && _pbs.PathEnd == 0 | ||
1074 | && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0 | ||
1075 | && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100 | ||
1076 | && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) ) | ||
1036 | { | 1077 | { |
1037 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) | 1078 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) |
1038 | { | 1079 | { |
1039 | // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) | 1080 | haveShape = true; |
1040 | // { | 1081 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) |
1041 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); | 1082 | { |
1042 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) | 1083 | DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); |
1043 | { | 1084 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; |
1044 | DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); | 1085 | // Bullet native objects are scaled by the Bullet engine so pass the size in |
1045 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; | 1086 | _scale = _size; |
1046 | // Bullet native objects are scaled by the Bullet engine so pass the size in | 1087 | // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? |
1047 | _scale = _size; | 1088 | ret = true; |
1048 | // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? | 1089 | } |
1049 | ret = true; | ||
1050 | } | ||
1051 | // } | ||
1052 | } | 1090 | } |
1053 | else | 1091 | else |
1054 | { | 1092 | { |
1055 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); | 1093 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); |
1094 | haveShape = true; | ||
1056 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) | 1095 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) |
1057 | { | 1096 | { |
1058 | DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); | 1097 | DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); |
@@ -1063,16 +1102,16 @@ public sealed class BSPrim : BSPhysObject | |||
1063 | } | 1102 | } |
1064 | } | 1103 | } |
1065 | } | 1104 | } |
1066 | else | 1105 | // If a simple shape isn't happening, create a mesh and possibly a hull |
1106 | if (!haveShape) | ||
1067 | { | 1107 | { |
1068 | if (IsPhysical) | 1108 | if (IsPhysical) |
1069 | { | 1109 | { |
1070 | if (forceRebuild || _hullKey == 0) | 1110 | if (forceRebuild || _hullKey == 0) |
1071 | { | 1111 | { |
1072 | // physical objects require a hull for interaction. | 1112 | // physical objects require a hull for interaction. |
1073 | // This will create the mesh if it doesn't already exist | 1113 | // This also creates the mesh if it doesn't already exist |
1074 | CreateGeomHull(); | 1114 | ret = CreateGeomHull(); |
1075 | ret = true; | ||
1076 | } | 1115 | } |
1077 | } | 1116 | } |
1078 | else | 1117 | else |
@@ -1080,8 +1119,7 @@ public sealed class BSPrim : BSPhysObject | |||
1080 | if (forceRebuild || _meshKey == 0) | 1119 | if (forceRebuild || _meshKey == 0) |
1081 | { | 1120 | { |
1082 | // Static (non-physical) objects only need a mesh for bumping into | 1121 | // Static (non-physical) objects only need a mesh for bumping into |
1083 | CreateGeomMesh(); | 1122 | ret = CreateGeomMesh(); |
1084 | ret = true; | ||
1085 | } | 1123 | } |
1086 | } | 1124 | } |
1087 | } | 1125 | } |
@@ -1089,7 +1127,8 @@ public sealed class BSPrim : BSPhysObject | |||
1089 | } | 1127 | } |
1090 | 1128 | ||
1091 | // No locking here because this is done when we know physics is not simulating | 1129 | // No locking here because this is done when we know physics is not simulating |
1092 | private void CreateGeomMesh() | 1130 | // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). |
1131 | private bool CreateGeomMesh() | ||
1093 | { | 1132 | { |
1094 | // level of detail based on size and type of the object | 1133 | // level of detail based on size and type of the object |
1095 | float lod = _scene.MeshLOD; | 1134 | float lod = _scene.MeshLOD; |
@@ -1103,7 +1142,7 @@ public sealed class BSPrim : BSPhysObject | |||
1103 | // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); | 1142 | // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); |
1104 | 1143 | ||
1105 | // if this new shape is the same as last time, don't recreate the mesh | 1144 | // if this new shape is the same as last time, don't recreate the mesh |
1106 | if (_meshKey == newMeshKey) return; | 1145 | if (_meshKey == newMeshKey) return false; |
1107 | 1146 | ||
1108 | DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); | 1147 | DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); |
1109 | // Since we're recreating new, get rid of any previously generated shape | 1148 | // Since we're recreating new, get rid of any previously generated shape |
@@ -1140,19 +1179,19 @@ public sealed class BSPrim : BSPhysObject | |||
1140 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; | 1179 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; |
1141 | // meshes are already scaled by the meshmerizer | 1180 | // meshes are already scaled by the meshmerizer |
1142 | _scale = new OMV.Vector3(1f, 1f, 1f); | 1181 | _scale = new OMV.Vector3(1f, 1f, 1f); |
1143 | DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); | 1182 | return true; |
1144 | return; | ||
1145 | } | 1183 | } |
1146 | 1184 | ||
1147 | // No locking here because this is done when we know physics is not simulating | 1185 | // No locking here because this is done when we know physics is not simulating |
1148 | private void CreateGeomHull() | 1186 | // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). |
1187 | private bool CreateGeomHull() | ||
1149 | { | 1188 | { |
1150 | float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; | 1189 | float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; |
1151 | ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); | 1190 | ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); |
1152 | // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); | 1191 | // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); |
1153 | 1192 | ||
1154 | // if the hull hasn't changed, don't rebuild it | 1193 | // if the hull hasn't changed, don't rebuild it |
1155 | if (newHullKey == _hullKey) return; | 1194 | if (newHullKey == _hullKey) return false; |
1156 | 1195 | ||
1157 | DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); | 1196 | DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); |
1158 | 1197 | ||
@@ -1255,7 +1294,7 @@ public sealed class BSPrim : BSPhysObject | |||
1255 | // meshes are already scaled by the meshmerizer | 1294 | // meshes are already scaled by the meshmerizer |
1256 | _scale = new OMV.Vector3(1f, 1f, 1f); | 1295 | _scale = new OMV.Vector3(1f, 1f, 1f); |
1257 | DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); | 1296 | DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); |
1258 | return; | 1297 | return true; |
1259 | } | 1298 | } |
1260 | 1299 | ||
1261 | // Callback from convex hull creater with a newly created hull. | 1300 | // Callback from convex hull creater with a newly created hull. |
@@ -1268,20 +1307,12 @@ public sealed class BSPrim : BSPhysObject | |||
1268 | 1307 | ||
1269 | private void VerifyCorrectPhysicalShape() | 1308 | private void VerifyCorrectPhysicalShape() |
1270 | { | 1309 | { |
1271 | if (IsStatic) | 1310 | 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 | { | 1311 | { |
1281 | // if not static, it will need a hull to efficiently collide with things | 1312 | // if not static, it will need a hull to efficiently collide with things |
1282 | if (_hullKey == 0) | 1313 | if (_hullKey == 0) |
1283 | { | 1314 | { |
1284 | RecreateGeomAndObject(); | 1315 | CreateGeomAndObject(false); |
1285 | } | 1316 | } |
1286 | 1317 | ||
1287 | } | 1318 | } |
@@ -1300,8 +1331,9 @@ public sealed class BSPrim : BSPhysObject | |||
1300 | // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); | 1331 | // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); |
1301 | bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); | 1332 | bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); |
1302 | 1333 | ||
1303 | // the CreateObject() may have recreated the rigid body. Make sure we have the latest. | 1334 | // 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)); | 1335 | BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); |
1336 | BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); | ||
1305 | 1337 | ||
1306 | return ret; | 1338 | return ret; |
1307 | } | 1339 | } |
@@ -1325,15 +1357,20 @@ public sealed class BSPrim : BSPhysObject | |||
1325 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; | 1357 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; |
1326 | } | 1358 | } |
1327 | 1359 | ||
1328 | |||
1329 | // Rebuild the geometry and object. | 1360 | // Rebuild the geometry and object. |
1330 | // This is called when the shape changes so we need to recreate the mesh/hull. | 1361 | // 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 | 1362 | // No locking here because this is done when the physics engine is not simulating |
1332 | private void RecreateGeomAndObject() | 1363 | private void CreateGeomAndObject(bool forceRebuild) |
1333 | { | 1364 | { |
1334 | // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); | 1365 | // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild); |
1335 | if (CreateGeom(true)) | 1366 | // Create the geometry that will make up the object |
1367 | if (CreateGeom(forceRebuild)) | ||
1368 | { | ||
1369 | // Create the object and place it into the world | ||
1336 | CreateObject(); | 1370 | CreateObject(); |
1371 | // Make sure the properties are set on the new object | ||
1372 | UpdatePhysicalParameters(); | ||
1373 | } | ||
1337 | return; | 1374 | return; |
1338 | } | 1375 | } |
1339 | 1376 | ||
@@ -1430,9 +1467,10 @@ public sealed class BSPrim : BSPhysObject | |||
1430 | // I've collided with something | 1467 | // I've collided with something |
1431 | // Called at taint time from within the Step() function | 1468 | // Called at taint time from within the Step() function |
1432 | CollisionEventUpdate collisionCollection; | 1469 | CollisionEventUpdate collisionCollection; |
1433 | public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | 1470 | public override bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) |
1434 | { | 1471 | { |
1435 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); | 1472 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); |
1473 | bool ret = false; | ||
1436 | 1474 | ||
1437 | // The following lines make IsColliding() and IsCollidingGround() work | 1475 | // The following lines make IsColliding() and IsCollidingGround() work |
1438 | _collidingStep = _scene.SimulationStep; | 1476 | _collidingStep = _scene.SimulationStep; |
@@ -1446,7 +1484,7 @@ public sealed class BSPrim : BSPhysObject | |||
1446 | // prims in the same linkset cannot collide with each other | 1484 | // prims in the same linkset cannot collide with each other |
1447 | if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) | 1485 | if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) |
1448 | { | 1486 | { |
1449 | return; | 1487 | return ret; |
1450 | } | 1488 | } |
1451 | 1489 | ||
1452 | // if someone has subscribed for collision events.... | 1490 | // if someone has subscribed for collision events.... |
@@ -1459,8 +1497,10 @@ public sealed class BSPrim : BSPhysObject | |||
1459 | if (collisionCollection == null) | 1497 | if (collisionCollection == null) |
1460 | collisionCollection = new CollisionEventUpdate(); | 1498 | collisionCollection = new CollisionEventUpdate(); |
1461 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | 1499 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); |
1500 | ret = true; | ||
1462 | } | 1501 | } |
1463 | } | 1502 | } |
1503 | return ret; | ||
1464 | } | 1504 | } |
1465 | 1505 | ||
1466 | // The scene is telling us it's time to pass our collected collisions into the simulator | 1506 | // The scene is telling us it's time to pass our collected collisions into the simulator |