aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorRobert Adams2012-09-20 10:12:51 -0700
committerRobert Adams2012-09-27 22:01:26 -0700
commit22290ef35aa13edb1501c69b3cce63a885302563 (patch)
tree2c4762479fb5336c3338acdd2d761fc8c15a04e9 /OpenSim
parentBulletSim: add class and infrastructure for shape and object (diff)
downloadopensim-SC-22290ef35aa13edb1501c69b3cce63a885302563.zip
opensim-SC-22290ef35aa13edb1501c69b3cce63a885302563.tar.gz
opensim-SC-22290ef35aa13edb1501c69b3cce63a885302563.tar.bz2
opensim-SC-22290ef35aa13edb1501c69b3cce63a885302563.tar.xz
BulletSim: complete code for managed code shape and body tracking. Not debugged.
Eliminate some null exceptions created adding the above code. Add and remove some detailed logging statements.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs22
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs121
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs617
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs43
5 files changed, 675 insertions, 130 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 19eb1e6..014cd99 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -77,7 +77,7 @@ public class BSCharacter : BSPhysObject
77 77
78 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) 78 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
79 { 79 {
80 base.BaseInitialize(parent_scene, localID, avName); 80 base.BaseInitialize(parent_scene, localID, avName, "BSCharacter");
81 _physicsActorType = (int)ActorTypes.Agent; 81 _physicsActorType = (int)ActorTypes.Agent;
82 _position = pos; 82 _position = pos;
83 _size = size; 83 _size = size;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index b575e37..70a10b1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -39,11 +39,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
39// unless the difference is significant. 39// unless the difference is significant.
40public abstract class BSPhysObject : PhysicsActor 40public abstract class BSPhysObject : PhysicsActor
41{ 41{
42 protected void BaseInitialize(BSScene parentScene, uint localID, string name) 42 protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName)
43 { 43 {
44 PhysicsScene = parentScene; 44 PhysicsScene = parentScene;
45 LocalID = localID; 45 LocalID = localID;
46 PhysObjectName = name; 46 PhysObjectName = name;
47 TypeName = typeName;
47 48
48 Linkset = new BSLinkset(PhysicsScene, this); 49 Linkset = new BSLinkset(PhysicsScene, this);
49 50
@@ -56,6 +57,7 @@ public abstract class BSPhysObject : PhysicsActor
56 public BSScene PhysicsScene { get; protected set; } 57 public BSScene PhysicsScene { get; protected set; }
57 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 58 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
58 public string PhysObjectName { get; protected set; } 59 public string PhysObjectName { get; protected set; }
60 public string TypeName { get; protected set; }
59 61
60 public BSLinkset Linkset { get; set; } 62 public BSLinkset Linkset { get; set; }
61 63
@@ -63,9 +65,9 @@ public abstract class BSPhysObject : PhysicsActor
63 public abstract float MassRaw { get; } 65 public abstract float MassRaw { get; }
64 66
65 // Reference to the physical body (btCollisionObject) of this object 67 // Reference to the physical body (btCollisionObject) of this object
66 public BulletBody BSBody { get; protected set; } 68 public BulletBody BSBody;
67 // Reference to the physical shape (btCollisionShape) of this object 69 // Reference to the physical shape (btCollisionShape) of this object
68 public BulletShape BSShape { get; protected set; } 70 public BulletShape BSShape;
69 71
70 // Stop all physical motion. 72 // Stop all physical motion.
71 public abstract void ZeroMotion(); 73 public abstract void ZeroMotion();
@@ -116,13 +118,11 @@ public abstract class BSPhysObject : PhysicsActor
116 return ret; 118 return ret;
117 } 119 }
118 120
119 DetailLog("{0},BSPhysObject.Collison,call,with={1}", LocalID, collidingWith);
120
121 // if someone has subscribed for collision events.... 121 // if someone has subscribed for collision events....
122 if (SubscribedEvents()) { 122 if (SubscribedEvents()) {
123 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 123 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
124 DetailLog("{0},BSPhysObject.Collison.AddCollider,call,with={1},point={2},normal={3},depth={4}", 124 // DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
125 LocalID, collidingWith, contactPoint, contactNormal, pentrationDepth); 125 // LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
126 ret = true; 126 ret = true;
127 } 127 }
128 return ret; 128 return ret;
@@ -147,7 +147,7 @@ public abstract class BSPhysObject : PhysicsActor
147 if (CollisionCollection.Count == 0) 147 if (CollisionCollection.Count == 0)
148 PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); 148 PhysicsScene.ObjectsWithNoMoreCollisions.Add(this);
149 149
150 DetailLog("{0},SendCollisions.SendCollisionUpdate,call,numCollisions={1}", LocalID, CollisionCollection.Count); 150 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
151 base.SendCollisionUpdate(CollisionCollection); 151 base.SendCollisionUpdate(CollisionCollection);
152 152
153 // The collisionCollection structure is passed around in the simulator. 153 // The collisionCollection structure is passed around in the simulator.
@@ -164,9 +164,8 @@ public abstract class BSPhysObject : PhysicsActor
164 { 164 {
165 // make sure first collision happens 165 // make sure first collision happens
166 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 166 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
167 DetailLog("{0},SubscribeEvents,call,ms={1}", LocalID, SubscribedEventsMs);
168 167
169 PhysicsScene.TaintedObject("BSPhysObject.SubscribeEvents", delegate() 168 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
170 { 169 {
171 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 170 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
172 }); 171 });
@@ -179,8 +178,7 @@ public abstract class BSPhysObject : PhysicsActor
179 } 178 }
180 public override void UnSubscribeEvents() { 179 public override void UnSubscribeEvents() {
181 SubscribedEventsMs = 0; 180 SubscribedEventsMs = 0;
182 DetailLog("{0},UnSubscribeEvents,call", LocalID); 181 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
183 PhysicsScene.TaintedObject("BSPhysObject.UnSubscribeEvents", delegate()
184 { 182 {
185 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 183 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
186 }); 184 });
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 4d17e6c..4d2c70c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -96,7 +96,7 @@ public sealed class BSPrim : BSPhysObject
96 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 96 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
97 { 97 {
98 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 98 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
99 base.BaseInitialize(parent_scene, localID, primName); 99 base.BaseInitialize(parent_scene, localID, primName, "BSPrim");
100 _physicsActorType = (int)ActorTypes.Prim; 100 _physicsActorType = (int)ActorTypes.Prim;
101 _position = pos; 101 _position = pos;
102 _size = size; 102 _size = size;
@@ -115,17 +115,17 @@ public sealed class BSPrim : BSPhysObject
115 _restitution = PhysicsScene.Params.defaultRestitution; 115 _restitution = PhysicsScene.Params.defaultRestitution;
116 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness 116 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
117 _mass = CalculateMass(); 117 _mass = CalculateMass();
118
119 // No body or shape yet
120 BSBody = new BulletBody(LocalID, IntPtr.Zero);
121 BSShape = new BulletShape(IntPtr.Zero);
122
118 DetailLog("{0},BSPrim.constructor,call", LocalID); 123 DetailLog("{0},BSPrim.constructor,call", LocalID);
119 // do the actual object creation at taint time 124 // do the actual object creation at taint time
120 PhysicsScene.TaintedObject("BSPrim.create", delegate() 125 PhysicsScene.TaintedObject("BSPrim.create", delegate()
121 { 126 {
122 CreateGeomAndObject(true); 127 CreateGeomAndObject(true);
123 128
124 // Get the pointer to the physical body for this object.
125 // At the moment, we're still letting BulletSim manage the creation and destruction
126 // of the object. Someday we'll move that into the C# code.
127 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID));
128 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
129 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); 129 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr);
130 }); 130 });
131 } 131 }
@@ -168,17 +168,24 @@ public sealed class BSPrim : BSPhysObject
168 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct 168 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
169 // scale and margins are set. 169 // scale and margins are set.
170 CreateGeomAndObject(true); 170 CreateGeomAndObject(true);
171 DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical); 171 DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical);
172 }); 172 });
173 } 173 }
174 } 174 }
175 // Scale is what we set in the physics engine. It is different than 'size' in that
176 // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>.
177 public OMV.Vector3 Scale
178 {
179 get { return _scale; }
180 set { _scale = value; }
181 }
175 public override PrimitiveBaseShape Shape { 182 public override PrimitiveBaseShape Shape {
176 set { 183 set {
177 _pbs = value; 184 _pbs = value;
178 PhysicsScene.TaintedObject("BSPrim.setShape", delegate() 185 PhysicsScene.TaintedObject("BSPrim.setShape", delegate()
179 { 186 {
180 _mass = CalculateMass(); // changing the shape changes the mass 187 _mass = CalculateMass(); // changing the shape changes the mass
181 CreateGeomAndObject(false); 188 CreateGeomAndObject(true);
182 }); 189 });
183 } 190 }
184 } 191 }
@@ -191,7 +198,7 @@ public sealed class BSPrim : BSPhysObject
191 _isSelected = value; 198 _isSelected = value;
192 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 199 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
193 { 200 {
194 SetObjectDynamic(); 201 SetObjectDynamic(false);
195 }); 202 });
196 } 203 }
197 } 204 }
@@ -371,7 +378,7 @@ public sealed class BSPrim : BSPhysObject
371 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 378 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
372 { 379 {
373 DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); 380 DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
374 SetObjectDynamic(); 381 SetObjectDynamic(true);
375 }); 382 });
376 return; 383 return;
377 } 384 }
@@ -433,7 +440,7 @@ public sealed class BSPrim : BSPhysObject
433 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 440 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
434 { 441 {
435 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 442 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
436 SetObjectDynamic(); 443 SetObjectDynamic(true);
437 }); 444 });
438 } 445 }
439 } 446 }
@@ -445,7 +452,7 @@ public sealed class BSPrim : BSPhysObject
445 } 452 }
446 453
447 // An object is solid if it's not phantom and if it's not doing VolumeDetect 454 // An object is solid if it's not phantom and if it's not doing VolumeDetect
448 private bool IsSolid 455 public bool IsSolid
449 { 456 {
450 get { return !IsPhantom && !_isVolumeDetect; } 457 get { return !IsPhantom && !_isVolumeDetect; }
451 } 458 }
@@ -457,21 +464,23 @@ public sealed class BSPrim : BSPhysObject
457 // isSolid: other objects bounce off of this object 464 // isSolid: other objects bounce off of this object
458 // isVolumeDetect: other objects pass through but can generate collisions 465 // isVolumeDetect: other objects pass through but can generate collisions
459 // collisionEvents: whether this object returns collision events 466 // collisionEvents: whether this object returns collision events
460 private void SetObjectDynamic() 467 private void SetObjectDynamic(bool forceRebuild)
461 { 468 {
469#if CSHARP_BODY_MANAGEMENT
470 // Recreate the physical object if necessary
471 CreateGeomAndObject(forceRebuild);
472#else
462 // If it's becoming dynamic, it will need hullness 473 // If it's becoming dynamic, it will need hullness
463 VerifyCorrectPhysicalShape(); 474 VerifyCorrectPhysicalShape();
464 UpdatePhysicalParameters(); 475 UpdatePhysicalParameters();
476#endif // CSHARP_BODY_MANAGEMENT
465 } 477 }
466 478
467 private void UpdatePhysicalParameters() 479 private void UpdatePhysicalParameters()
468 { 480 {
469 /* 481 DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
470 // Bullet wants static objects to have a mass of zero
471 float mass = IsStatic ? 0f : _mass;
472 482
473 BulletSimAPI.SetObjectProperties(Scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 483 // Mangling all the physical properties requires the object to be out of the physical world
474 */
475 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); 484 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr);
476 485
477 // Make solid or not (do things bounce off or pass through this object) 486 // Make solid or not (do things bounce off or pass through this object)
@@ -517,8 +526,8 @@ public sealed class BSPrim : BSPhysObject
517 // There can be special things needed for implementing linksets 526 // There can be special things needed for implementing linksets
518 Linkset.MakeStatic(this); 527 Linkset.MakeStatic(this);
519 // The activation state is 'sleeping' so Bullet will not try to act on it 528 // The activation state is 'sleeping' so Bullet will not try to act on it
520 // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); 529 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING);
521 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION); 530 // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION);
522 } 531 }
523 else 532 else
524 { 533 {
@@ -560,8 +569,8 @@ public sealed class BSPrim : BSPhysObject
560 // the functions after this one set up the state of a possibly newly created collision body. 569 // the functions after this one set up the state of a possibly newly created collision body.
561 private void MakeSolid(bool makeSolid) 570 private void MakeSolid(bool makeSolid)
562 { 571 {
572#if !CSHARP_BODY_MANAGEMENT
563 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.Ptr); 573 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.Ptr);
564 /*
565 if (makeSolid) 574 if (makeSolid)
566 { 575 {
567 if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) 576 if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0)
@@ -569,11 +578,16 @@ public sealed class BSPrim : BSPhysObject
569 // Solid things are made out of rigid bodies. Remove this old body from the world 578 // Solid things are made out of rigid bodies. Remove this old body from the world
570 // and use this shape in a new rigid body. 579 // and use this shape in a new rigid body.
571 BulletBody oldBody = BSBody; 580 BulletBody oldBody = BSBody;
572 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); 581 // Zero out the pointer to the shape in the old body so the shape will not get freed
573 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); 582 BSShape.Ptr = BulletSimAPI.GetCollisionShape2(oldBody.Ptr);
583 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.Ptr, oldBody.Ptr, IntPtr.Zero);
584 // Get rid of the old body and remove it from BulletSim's object list
585 BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID);
586
587 // Create the new body with the shape
574 BSBody = new BulletBody(LocalID, BulletSimAPI.CreateBodyFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); 588 BSBody = new BulletBody(LocalID, BulletSimAPI.CreateBodyFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation));
575 BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, oldBody.Ptr); 589 BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
576 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); 590 DetailLog("{0},BSPrim.MakeSolid:rigidBody,body={1},shape={2}", LocalID, BSBody, BSShape);
577 } 591 }
578 } 592 }
579 else 593 else
@@ -583,23 +597,20 @@ public sealed class BSPrim : BSPhysObject
583 // Non-solid things are made out of ghost objects. Remove this old body from the world 597 // Non-solid things are made out of ghost objects. Remove this old body from the world
584 // and use this shape in a new rigid body. 598 // and use this shape in a new rigid body.
585 BulletBody oldBody = BSBody; 599 BulletBody oldBody = BSBody;
586 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); 600
587 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); 601 // Zero out the pointer to the shape in the old body so the shape will not get freed
602 BSShape.Ptr = BulletSimAPI.GetCollisionShape2(oldBody.Ptr);
603 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.Ptr, oldBody.Ptr, IntPtr.Zero);
604 // Get rid of the old body and remove it from BulletSim's object list
605 BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID);
606
588 BSBody = new BulletBody(LocalID, 607 BSBody = new BulletBody(LocalID,
589 BulletSimAPI.CreateGhostFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); 608 BulletSimAPI.CreateGhostFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation));
590 if (BSBody.Ptr == IntPtr.Zero) 609 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
591 { 610 DetailLog("{0},BSPrim.MakeGhostBody,body={1},shape={2}", LocalID, BSBody, BSShape);
592 m_log.ErrorFormat("{0} BSPrim.MakeSolid: failed creation of ghost object. LocalID=[1}", LogHeader, LocalID);
593 BSBody = oldBody;
594 }
595 else
596 {
597 BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, oldBody.Ptr);
598 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr);
599 }
600 } 611 }
601 } 612 }
602 */ 613#endif
603 } 614 }
604 615
605 // Turn on or off the flag controlling whether collision events are returned to the simulator. 616 // Turn on or off the flag controlling whether collision events are returned to the simulator.
@@ -1067,6 +1078,7 @@ public sealed class BSPrim : BSPhysObject
1067 }// end CalculateMass 1078 }// end CalculateMass
1068 #endregion Mass Calculation 1079 #endregion Mass Calculation
1069 1080
1081#if !CSHARP_BODY_MANAGEMENT
1070 // Create the geometry information in Bullet for later use. 1082 // Create the geometry information in Bullet for later use.
1071 // The objects needs a hull if it's physical otherwise a mesh is enough. 1083 // The objects needs a hull if it's physical otherwise a mesh is enough.
1072 // No locking here because this is done when we know physics is not simulating. 1084 // No locking here because this is done when we know physics is not simulating.
@@ -1095,6 +1107,7 @@ public sealed class BSPrim : BSPhysObject
1095 { 1107 {
1096 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); 1108 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
1097 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 1109 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
1110 _meshKey = (ulong)ShapeData.FixedShapeKey.KEY_SPHERE;
1098 // Bullet native objects are scaled by the Bullet engine so pass the size in 1111 // Bullet native objects are scaled by the Bullet engine so pass the size in
1099 _scale = _size; 1112 _scale = _size;
1100 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1113 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@@ -1109,6 +1122,7 @@ public sealed class BSPrim : BSPhysObject
1109 { 1122 {
1110 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); 1123 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
1111 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1124 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
1125 _meshKey = (ulong)ShapeData.FixedShapeKey.KEY_BOX;
1112 _scale = _size; 1126 _scale = _size;
1113 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1127 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1114 ret = true; 1128 ret = true;
@@ -1136,6 +1150,7 @@ public sealed class BSPrim : BSPhysObject
1136 } 1150 }
1137 } 1151 }
1138 } 1152 }
1153
1139 return ret; 1154 return ret;
1140 } 1155 }
1141 1156
@@ -1345,12 +1360,9 @@ public sealed class BSPrim : BSPhysObject
1345 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type); 1360 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type);
1346 bool ret = BulletSimAPI.CreateObject(PhysicsScene.WorldID, shape); 1361 bool ret = BulletSimAPI.CreateObject(PhysicsScene.WorldID, shape);
1347 1362
1348 // the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
1349 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID));
1350 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
1351
1352 return ret; 1363 return ret;
1353 } 1364 }
1365#endif // !CSHARP_BODY_MANAGEMENT
1354 1366
1355 // Copy prim's info into the BulletSim shape description structure 1367 // Copy prim's info into the BulletSim shape description structure
1356 public void FillShapeInfo(out ShapeData shape) 1368 public void FillShapeInfo(out ShapeData shape)
@@ -1369,22 +1381,45 @@ public sealed class BSPrim : BSPhysObject
1369 shape.Restitution = _restitution; 1381 shape.Restitution = _restitution;
1370 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; 1382 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
1371 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1383 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1384 shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue;
1385 shape.Size = _size;
1372 } 1386 }
1373
1374 // Rebuild the geometry and object. 1387 // Rebuild the geometry and object.
1375 // This is called when the shape changes so we need to recreate the mesh/hull. 1388 // This is called when the shape changes so we need to recreate the mesh/hull.
1376 // No locking here because this is done when the physics engine is not simulating 1389 // No locking here because this is done when the physics engine is not simulating
1377 private void CreateGeomAndObject(bool forceRebuild) 1390 private void CreateGeomAndObject(bool forceRebuild)
1378 { 1391 {
1392#if CSHARP_BODY_MANAGEMENT
1393 ShapeData shapeData;
1394 FillShapeInfo(out shapeData);
1395
1396 // Create the correct physical representation for this type of object.
1397 // Updates BSBody and BSShape with the new information.
1398 if (PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs))
1399 {
1400 // Make sure the properties are set on the new object
1401 UpdatePhysicalParameters();
1402 }
1403#else
1379 // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, LocalID, forceRebuild); 1404 // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, LocalID, forceRebuild);
1380 // Create the geometry that will make up the object 1405 // Create the geometry that will make up the object
1381 if (CreateGeom(forceRebuild)) 1406 if (CreateGeom(forceRebuild))
1382 { 1407 {
1383 // Create the object and place it into the world 1408 // Create the object and place it into the world
1384 CreateObject(); 1409 CreateObject();
1410
1411 // the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
1412 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID));
1413 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr), _shapeType);
1414 BSShape.shapeKey = _meshKey;
1415 DetailLog("{0},BSPrim.CreateGeomAndObject,body={1},shape={2}", LocalID, BSBody, BSShape);
1416
1385 // Make sure the properties are set on the new object 1417 // Make sure the properties are set on the new object
1386 UpdatePhysicalParameters(); 1418 UpdatePhysicalParameters();
1387 } 1419 }
1420
1421
1422#endif // CSHARP_BODY_MANAGEMENT
1388 return; 1423 return;
1389 } 1424 }
1390 1425
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index eb4b2ad..7470d23 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -1,70 +1,547 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD 9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30using OMV = OpenMetaverse; 30using OMV = OpenMetaverse;
31 31using OpenSim.Framework;
32namespace OpenSim.Region.Physics.BulletSPlugin 32using OpenSim.Region.Physics.Manager;
33{ 33using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34public class BSShapeCollection : IDisposable 34
35{ 35namespace OpenSim.Region.Physics.BulletSPlugin
36 protected BSScene PhysicsScene { get; set; } 36{
37 37public class BSShapeCollection : IDisposable
38 public BSShapeCollection(BSScene physScene) 38{
39 { 39 protected BSScene PhysicsScene { get; set; }
40 PhysicsScene = physScene; 40
41 } 41 private Object m_shapeActivityLock = new Object();
42 42
43 public void Dispose() 43 private struct MeshDesc
44 { 44 {
45 } 45 public IntPtr Ptr;
46 46 public int referenceCount;
47 // Track another user of a body 47 public DateTime lastReferenced;
48 public void ReferenceBody(BulletBody shape) 48 public IMesh meshData;
49 { 49 }
50 } 50
51 51 private struct HullDesc
52 // Release the usage of a body 52 {
53 public void DereferenceBody(BulletBody shape) 53 public IntPtr Ptr;
54 { 54 public int referenceCount;
55 } 55 public DateTime lastReferenced;
56 56 }
57 // Track another user of the shape 57
58 public void ReferenceShape(BulletShape shape) 58 private Dictionary<ulong, MeshDesc> Meshes = new Dictionary<ulong, MeshDesc>();
59 { 59 private Dictionary<ulong, HullDesc> Hulls = new Dictionary<ulong, HullDesc>();
60 } 60
61 61 public BSShapeCollection(BSScene physScene)
62 // Release the usage of a shape 62 {
63 public void DereferenceShape(BulletShape shape) 63 PhysicsScene = physScene;
64 { 64 }
65 } 65
66 66 public void Dispose()
67 67 {
68 68 }
69} 69
70} 70 // Called to update/change the body and shape for an object.
71 // First checks the shape and updates that if necessary then makes
72 // sure the body is of the right type.
73 // Return 'true' if either the body or the shape changed.
74 // Called at taint-time!!
75 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
76 {
77 bool ret = false;
78
79 // Do we have the correct geometry for this type of object?
80 if (CreateGeom(forceRebuild, prim, shapeData, pbs))
81 {
82 // If we had to select a new shape geometry for the object,
83 // rebuild the body around it.
84 CreateObject(true, prim, PhysicsScene.World, prim.BSShape, shapeData);
85 ret = true;
86 }
87
88 return ret;
89 }
90
91 // Track another user of a body
92 public void ReferenceBody(BulletBody shape)
93 {
94 }
95
96 // Release the usage of a body
97 public void DereferenceBody(BulletBody shape)
98 {
99 }
100
101 // Track another user of the shape
102 public void ReferenceShape(BulletShape shape)
103 {
104 ReferenceShape(shape, null);
105 }
106
107 // Track the datastructures and use count for a shape.
108 // When creating a hull, this is called first to reference the mesh
109 // and then again to reference the hull.
110 // Meshes and hulls for the same shape have the same hash key.
111 private void ReferenceShape(BulletShape shape, IMesh meshData)
112 {
113 switch (shape.type)
114 {
115 case ShapeData.PhysicsShapeType.SHAPE_MESH:
116 MeshDesc meshDesc;
117 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
118 {
119 // There is an existing instance of this mesh.
120 meshDesc.referenceCount++;
121 }
122 else
123 {
124 // This is a new reference to a mesh
125 meshDesc.Ptr = shape.Ptr;
126 meshDesc.meshData = meshData;
127 meshDesc.referenceCount = 1;
128
129 }
130 meshDesc.lastReferenced = System.DateTime.Now;
131 Meshes[shape.shapeKey] = meshDesc;
132 break;
133 case ShapeData.PhysicsShapeType.SHAPE_HULL:
134 HullDesc hullDesc;
135 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
136 {
137 // There is an existing instance of this mesh.
138 hullDesc.referenceCount++;
139 }
140 else
141 {
142 // This is a new reference to a mesh
143 hullDesc.Ptr = shape.Ptr;
144 hullDesc.referenceCount = 1;
145
146 }
147 hullDesc.lastReferenced = System.DateTime.Now;
148 Hulls[shape.shapeKey] = hullDesc;
149 break;
150 default:
151 break;
152 }
153 }
154
155 // Release the usage of a shape
156 public void DereferenceShape(BulletShape shape)
157 {
158 switch (shape.type)
159 {
160 case ShapeData.PhysicsShapeType.SHAPE_HULL:
161 DereferenceHull(shape);
162 // Hulls also include a mesh
163 DereferenceMesh(shape);
164 break;
165 case ShapeData.PhysicsShapeType.SHAPE_MESH:
166 DereferenceMesh(shape);
167 break;
168 default:
169 break;
170 }
171 }
172
173 // Count down the reference count for a mesh shape
174 private void DereferenceMesh(BulletShape shape)
175 {
176 MeshDesc meshDesc;
177 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
178 {
179 meshDesc.referenceCount--;
180 // TODO: release the Bullet storage
181 meshDesc.lastReferenced = System.DateTime.Now;
182 Meshes[shape.shapeKey] = meshDesc;
183 }
184 }
185
186 // Count down the reference count for a hull shape
187 private void DereferenceHull(BulletShape shape)
188 {
189 HullDesc hullDesc;
190 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
191 {
192 hullDesc.referenceCount--;
193 // TODO: release the Bullet storage (aging old entries?)
194 hullDesc.lastReferenced = System.DateTime.Now;
195 Hulls[shape.shapeKey] = hullDesc;
196 }
197 }
198
199 // Create the geometry information in Bullet for later use.
200 // The objects needs a hull if it's physical otherwise a mesh is enough.
201 // No locking here because this is done when we know physics is not simulating.
202 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
203 // Returns 'true' if the geometry was rebuilt.
204 // Called at taint-time!
205 private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
206 {
207 bool ret = false;
208 bool haveShape = false;
209 bool nativeShapePossible = true;
210
211 BulletShape newShape = new BulletShape(IntPtr.Zero);
212
213 // If the object is dynamic, it must have a hull shape
214 if (prim.IsPhysical)
215 nativeShapePossible = false;
216
217 // If the prim attributes are simple, this could be a simple Bullet native shape
218 if (nativeShapePossible
219 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
220 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
221 && pbs.ProfileHollow == 0
222 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
223 && pbs.PathBegin == 0 && pbs.PathEnd == 0
224 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
225 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
226 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
227 {
228 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
229 {
230 haveShape = true;
231 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
232 {
233 DetailLog("{0},BSShapeCollection.CreateGeom,sphere (force={1}", prim.LocalID, forceRebuild);
234 newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE);
235
236 ret = true;
237 }
238 }
239 else
240 {
241 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
242 haveShape = true;
243 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX))
244 {
245 DetailLog("{0},BSShapeCollection.CreateGeom,box (force={1})", prim.LocalID, forceRebuild);
246 newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX);
247
248 ret = true;
249 }
250 }
251 }
252 // If a simple shape isn't happening, create a mesh and possibly a hull
253 if (!haveShape)
254 {
255 if (prim.IsPhysical)
256 {
257 if (forceRebuild || !Hulls.ContainsKey(prim.BSShape.shapeKey))
258 {
259 // physical objects require a hull for interaction.
260 // This also creates the mesh if it doesn't already exist
261 ret = CreateGeomHull(prim, shapeData, pbs);
262 }
263 }
264 else
265 {
266 if (forceRebuild || !Meshes.ContainsKey(prim.BSShape.shapeKey))
267 {
268 // Static (non-physical) objects only need a mesh for bumping into
269 ret = CreateGeomMesh(prim, shapeData, pbs);
270 }
271 }
272 }
273 return ret;
274 }
275
276 private BulletShape AddNativeShapeToPrim(BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType)
277 {
278 BulletShape newShape;
279
280 // Bullet native objects are scaled by the Bullet engine so pass the size in
281 prim.Scale = shapeData.Size;
282
283 // release any previous shape
284 DereferenceShape(prim.BSShape);
285
286 MeshDesc existingShapeDesc;
287 if (Meshes.TryGetValue(shapeData.MeshKey, out existingShapeDesc))
288 {
289 // If there is an existing allocated shape, use it
290 newShape = new BulletShape(existingShapeDesc.Ptr, shapeType);
291 }
292 else
293 {
294 // Shape of this discriptioin is not allocated. Create new.
295 newShape = new BulletShape(
296 BulletSimAPI.BuildNativeShape2(PhysicsScene.World.Ptr,
297 (float)shapeType,
298 PhysicsScene.Params.collisionMargin,
299 prim.Scale),
300 shapeType);
301 }
302 newShape.shapeKey = shapeData.MeshKey;
303 ReferenceShape(newShape);
304 prim.BSShape = newShape;
305 return newShape;
306 }
307
308 // No locking here because this is done when we know physics is not simulating
309 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
310 // Called at taint-time!
311 private bool CreateGeomMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
312 {
313 BulletShape newShape = new BulletShape(IntPtr.Zero);
314
315 // level of detail based on size and type of the object
316 float lod = PhysicsScene.MeshLOD;
317 if (pbs.SculptEntry)
318 lod = PhysicsScene.SculptLOD;
319
320 float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
321 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
322 lod = PhysicsScene.MeshMegaPrimLOD;
323
324 ulong newMeshKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod);
325 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _meshKey, newMeshKey);
326
327 // if this new shape is the same as last time, don't recreate the mesh
328 if (prim.BSShape.shapeKey == newMeshKey) return false;
329
330 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,key={1}", prim.LocalID, newMeshKey);
331
332 // Since we're recreating new, get rid of the reference to the previous shape
333 DereferenceShape(prim.BSShape);
334
335 IMesh meshData = null;
336 IntPtr meshPtr;
337 MeshDesc meshDesc;
338 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
339 {
340 // If the mesh has already been built just use it.
341 meshPtr = meshDesc.Ptr;
342 }
343 else
344 {
345 // always pass false for physicalness as this creates some sort of bounding box which we don't need
346 meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, shapeData.Size, lod, false);
347
348 int[] indices = meshData.getIndexListAsInt();
349 List<OMV.Vector3> vertices = meshData.getVertexList();
350
351 float[] verticesAsFloats = new float[vertices.Count * 3];
352 int vi = 0;
353 foreach (OMV.Vector3 vv in vertices)
354 {
355 verticesAsFloats[vi++] = vv.X;
356 verticesAsFloats[vi++] = vv.Y;
357 verticesAsFloats[vi++] = vv.Z;
358 }
359
360 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
361 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
362
363 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.Ptr,
364 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
365 }
366 newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
367 newShape.shapeKey = newMeshKey;
368
369 ReferenceShape(newShape, meshData);
370
371 // meshes are already scaled by the meshmerizer
372 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
373 prim.BSShape = newShape;
374 return true; // 'true' means a new shape has been added to this prim
375 }
376
377 // No locking here because this is done when we know physics is not simulating
378 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
379 List<ConvexResult> m_hulls;
380 private bool CreateGeomHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
381 {
382 BulletShape newShape;
383
384 float lod = pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD;
385 ulong newHullKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod);
386 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _hullKey, newHullKey);
387
388 // if the hull hasn't changed, don't rebuild it
389 if (newHullKey == prim.BSShape.shapeKey) return false;
390
391 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, newHullKey, newHullKey);
392
393 // remove references to any previous shape
394 DereferenceShape(prim.BSShape);
395
396 // Make sure the underlying mesh exists and is correct
397 // Since we're in the hull code, we know CreateGeomMesh() will not create a native shape.
398 CreateGeomMesh(prim, shapeData, pbs);
399 MeshDesc meshDesc = Meshes[newHullKey];
400
401 IntPtr hullPtr;
402 HullDesc hullDesc;
403 if (Hulls.TryGetValue(newHullKey, out hullDesc))
404 {
405 hullPtr = hullDesc.Ptr;
406 }
407 else
408 {
409 int[] indices = meshDesc.meshData.getIndexListAsInt();
410 List<OMV.Vector3> vertices = meshDesc.meshData.getVertexList();
411
412 //format conversion from IMesh format to DecompDesc format
413 List<int> convIndices = new List<int>();
414 List<float3> convVertices = new List<float3>();
415 for (int ii = 0; ii < indices.GetLength(0); ii++)
416 {
417 convIndices.Add(indices[ii]);
418 }
419 foreach (OMV.Vector3 vv in vertices)
420 {
421 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
422 }
423
424 // setup and do convex hull conversion
425 m_hulls = new List<ConvexResult>();
426 DecompDesc dcomp = new DecompDesc();
427 dcomp.mIndices = convIndices;
428 dcomp.mVertices = convVertices;
429 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
430 // create the hull into the _hulls variable
431 convexBuilder.process(dcomp);
432
433 // Convert the vertices and indices for passing to unmanaged.
434 // The hull information is passed as a large floating point array.
435 // The format is:
436 // convHulls[0] = number of hulls
437 // convHulls[1] = number of vertices in first hull
438 // convHulls[2] = hull centroid X coordinate
439 // convHulls[3] = hull centroid Y coordinate
440 // convHulls[4] = hull centroid Z coordinate
441 // convHulls[5] = first hull vertex X
442 // convHulls[6] = first hull vertex Y
443 // convHulls[7] = first hull vertex Z
444 // convHulls[8] = second hull vertex X
445 // ...
446 // convHulls[n] = number of vertices in second hull
447 // convHulls[n+1] = second hull centroid X coordinate
448 // ...
449 //
450 // TODO: is is very inefficient. Someday change the convex hull generator to return
451 // data structures that do not need to be converted in order to pass to Bullet.
452 // And maybe put the values directly into pinned memory rather than marshaling.
453 int hullCount = m_hulls.Count;
454 int totalVertices = 1; // include one for the count of the hulls
455 foreach (ConvexResult cr in m_hulls)
456 {
457 totalVertices += 4; // add four for the vertex count and centroid
458 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
459 }
460 float[] convHulls = new float[totalVertices];
461
462 convHulls[0] = (float)hullCount;
463 int jj = 1;
464 foreach (ConvexResult cr in m_hulls)
465 {
466 // copy vertices for index access
467 float3[] verts = new float3[cr.HullVertices.Count];
468 int kk = 0;
469 foreach (float3 ff in cr.HullVertices)
470 {
471 verts[kk++] = ff;
472 }
473
474 // add to the array one hull's worth of data
475 convHulls[jj++] = cr.HullIndices.Count;
476 convHulls[jj++] = 0f; // centroid x,y,z
477 convHulls[jj++] = 0f;
478 convHulls[jj++] = 0f;
479 foreach (int ind in cr.HullIndices)
480 {
481 convHulls[jj++] = verts[ind].x;
482 convHulls[jj++] = verts[ind].y;
483 convHulls[jj++] = verts[ind].z;
484 }
485 }
486 // create the hull data structure in Bullet
487 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount);
488 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.Ptr, hullCount, convHulls);
489 }
490 newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
491 newShape.shapeKey = newHullKey;
492
493 ReferenceShape(newShape);
494
495 // meshes are already scaled by the meshmerizer
496 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
497 prim.BSShape = newShape;
498 return true; // 'true' means a new shape has been added to this prim
499 }
500
501 // Callback from convex hull creater with a newly created hull.
502 // Just add it to the collection of hulls for this shape.
503 private void HullReturn(ConvexResult result)
504 {
505 m_hulls.Add(result);
506 return;
507 }
508
509 // Create an object in Bullet if it has not already been created
510 // No locking here because this is done when the physics engine is not simulating
511 // Returns 'true' if an object was actually created.
512 private bool CreateObject(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData)
513 {
514 // the mesh or hull must have already been created in Bullet
515 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type);
516
517 DereferenceBody(prim.BSBody);
518
519 BulletBody aBody;
520 IntPtr bodyPtr = IntPtr.Zero;
521 if (prim.IsSolid)
522 {
523 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation);
524 }
525 else
526 {
527 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation);
528 }
529 aBody = new BulletBody(shapeData.ID, bodyPtr);
530
531 ReferenceBody(aBody);
532
533 prim.BSBody = aBody;
534 return true;
535 }
536
537 private void DetailLog(string msg, params Object[] args)
538 {
539 PhysicsScene.PhysicsLogging.Write(msg, args);
540 }
541
542
543
544
545
546}
547}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 52c8a24..47875b0 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -40,7 +40,9 @@ public struct BulletSim
40{ 40{
41 public BulletSim(uint worldId, BSScene bss, IntPtr xx) 41 public BulletSim(uint worldId, BSScene bss, IntPtr xx)
42 { 42 {
43 worldID = worldId; scene = bss; Ptr = xx; 43 worldID = worldId;
44 scene = bss;
45 Ptr = xx;
44 } 46 }
45 public uint worldID; 47 public uint worldID;
46 // The scene is only in here so very low level routines have a handle to print debug/error messages 48 // The scene is only in here so very low level routines have a handle to print debug/error messages
@@ -58,6 +60,16 @@ public struct BulletBody
58 } 60 }
59 public IntPtr Ptr; 61 public IntPtr Ptr;
60 public uint ID; 62 public uint ID;
63 public override string ToString()
64 {
65 StringBuilder buff = new StringBuilder();
66 buff.Append("<id=");
67 buff.Append(ID.ToString());
68 buff.Append(",p=");
69 buff.Append(Ptr.ToString("X"));
70 buff.Append(">");
71 return buff.ToString();
72 }
61} 73}
62 74
63public struct BulletShape 75public struct BulletShape
@@ -66,17 +78,29 @@ public struct BulletShape
66 { 78 {
67 Ptr = xx; 79 Ptr = xx;
68 type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 80 type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
69 hashKey = 0; 81 shapeKey = 0;
70 } 82 }
71 public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) 83 public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ)
72 { 84 {
73 Ptr = xx; 85 Ptr = xx;
74 type = typ; 86 type = typ;
75 hashKey = 0; 87 shapeKey = 0;
76 } 88 }
77 public IntPtr Ptr; 89 public IntPtr Ptr;
78 public ShapeData.PhysicsShapeType type; 90 public ShapeData.PhysicsShapeType type;
79 public ulong hashKey; 91 public ulong shapeKey;
92 public override string ToString()
93 {
94 StringBuilder buff = new StringBuilder();
95 buff.Append("<p=");
96 buff.Append(Ptr.ToString("X"));
97 buff.Append(",s=");
98 buff.Append(type.ToString());
99 buff.Append(",k=");
100 buff.Append(shapeKey.ToString("X"));
101 buff.Append(">");
102 return buff.ToString();
103 }
80} 104}
81 105
82// An allocated Bullet btConstraint 106// An allocated Bullet btConstraint
@@ -155,10 +179,21 @@ public struct ShapeData
155 public float Restitution; 179 public float Restitution;
156 public float Collidable; // true of things bump into this 180 public float Collidable; // true of things bump into this
157 public float Static; // true if a static object. Otherwise gravity, etc. 181 public float Static; // true if a static object. Otherwise gravity, etc.
182 public float Solid; // true if object cannot be passed through
183 public Vector3 Size;
158 184
159 // note that bools are passed as floats since bool size changes by language and architecture 185 // note that bools are passed as floats since bool size changes by language and architecture
160 public const float numericTrue = 1f; 186 public const float numericTrue = 1f;
161 public const float numericFalse = 0f; 187 public const float numericFalse = 0f;
188
189 // The native shapes have predefined shape hash keys
190 public enum FixedShapeKey : ulong
191 {
192 KEY_BOX = 1,
193 KEY_SPHERE = 2,
194 KEY_CONE = 3,
195 KEY_CYLINDER = 4,
196 }
162} 197}
163[StructLayout(LayoutKind.Sequential)] 198[StructLayout(LayoutKind.Sequential)]
164public struct SweepHit 199public struct SweepHit