diff options
author | Robert Adams | 2012-09-20 10:12:51 -0700 |
---|---|---|
committer | Robert Adams | 2012-09-27 22:01:26 -0700 |
commit | 22290ef35aa13edb1501c69b3cce63a885302563 (patch) | |
tree | 2c4762479fb5336c3338acdd2d761fc8c15a04e9 | |
parent | BulletSim: add class and infrastructure for shape and object (diff) | |
download | opensim-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.
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 22 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 121 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 617 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 43 |
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. |
40 | public abstract class BSPhysObject : PhysicsActor | 40 | public 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 | */ |
27 | using System; | 27 | using System; |
28 | using System.Collections.Generic; | 28 | using System.Collections.Generic; |
29 | using System.Text; | 29 | using System.Text; |
30 | using OMV = OpenMetaverse; | 30 | using OMV = OpenMetaverse; |
31 | 31 | using OpenSim.Framework; | |
32 | namespace OpenSim.Region.Physics.BulletSPlugin | 32 | using OpenSim.Region.Physics.Manager; |
33 | { | 33 | using OpenSim.Region.Physics.ConvexDecompositionDotNet; |
34 | public class BSShapeCollection : IDisposable | 34 | |
35 | { | 35 | namespace OpenSim.Region.Physics.BulletSPlugin |
36 | protected BSScene PhysicsScene { get; set; } | 36 | { |
37 | 37 | public 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 | ||
63 | public struct BulletShape | 75 | public 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)] |
164 | public struct SweepHit | 199 | public struct SweepHit |