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 /OpenSim/Region/Physics/BulletSPlugin | |
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.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-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 |