aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-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