From e5582939fd8d78b61c6f1eeda6de45d94f4b4926 Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Sun, 28 Apr 2013 14:44:21 -0700
Subject: BulletSim: massive refactor of shape classes. Removed shape specific
 code from BSShapeCollection. Using BSShape* classes to hold references to
 shape. Simplified shape dependency callbacks. Remove 'PreferredShape' methods
 and have each class specify shape type. Disable compound shape linkset for a
 later commit that will simplify linkset implementation.

---
 OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs |   6 +-
 OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs   |   4 +-
 .../Physics/BulletSPlugin/BSActorAvatarMove.cs     |   4 +-
 .../Region/Physics/BulletSPlugin/BSActorHover.cs   |   4 +-
 .../Physics/BulletSPlugin/BSActorLockAxis.cs       |   4 +-
 .../Physics/BulletSPlugin/BSActorMoveToTarget.cs   |   4 +-
 .../Physics/BulletSPlugin/BSActorSetForce.cs       |   4 +-
 .../Physics/BulletSPlugin/BSActorSetTorque.cs      |   4 +-
 OpenSim/Region/Physics/BulletSPlugin/BSActors.cs   |   6 +-
 .../Region/Physics/BulletSPlugin/BSCharacter.cs    |  19 +-
 OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs |   4 +-
 OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs  |   9 +-
 .../Physics/BulletSPlugin/BSLinksetCompound.cs     |  35 +-
 .../Physics/BulletSPlugin/BSLinksetConstraints.cs  |   4 +-
 .../Region/Physics/BulletSPlugin/BSPhysObject.cs   |  11 +-
 OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs     |  34 +-
 .../Region/Physics/BulletSPlugin/BSPrimLinkable.cs |   9 +-
 .../Physics/BulletSPlugin/BSShapeCollection.cs     | 966 ++-------------------
 OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs   | 203 +++--
 .../Region/Physics/BulletSPlugin/BulletSimData.cs  |   6 +-
 20 files changed, 290 insertions(+), 1050 deletions(-)

diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index fdf2cb9..8a22bc7 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -79,7 +79,7 @@ private sealed class BulletShapeUnman : BulletShape
         : base()
     {
         ptr = xx;
-        type = typ;
+        shapeType = typ;
     }
     public override bool HasPhysicalShape
     {
@@ -91,7 +91,7 @@ private sealed class BulletShapeUnman : BulletShape
     }
     public override BulletShape Clone()
     {
-        return new BulletShapeUnman(ptr, type);
+        return new BulletShapeUnman(ptr, shapeType);
     }
     public override bool ReferenceSame(BulletShape other)
     {
@@ -375,7 +375,7 @@ public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletSha
 {
     BulletWorldUnman worldu = world as BulletWorldUnman;
     BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman;
-    return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type);
+    return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.shapeType);
 }
 
 public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index b37265a..1ef8b17 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -85,7 +85,7 @@ private sealed class BulletShapeXNA : BulletShape
         : base()
     {
         shape = xx;
-        type = typ;
+        shapeType = typ;
     }
     public override bool HasPhysicalShape
     {
@@ -97,7 +97,7 @@ private sealed class BulletShapeXNA : BulletShape
     }
     public override BulletShape Clone()
     {
-        return new BulletShapeXNA(shape, type);
+        return new BulletShapeXNA(shape, shapeType);
     }
     public override bool ReferenceSame(BulletShape other)
     {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index bd5ee0b1..ac05979 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -87,8 +87,8 @@ public class BSActorAvatarMove : BSActor
     // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
     //     Register a prestep action to restore physical requirements before the next simulation step.
     // Called at taint-time.
-    // BSActor.RemoveBodyDependencies()
-    public override void RemoveBodyDependencies()
+    // BSActor.RemoveDependencies()
+    public override void RemoveDependencies()
     {
         // Nothing to do for the hoverer since it is all software at pre-step action time.
     }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
index 92ace66..3630ca8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
@@ -87,8 +87,8 @@ public class BSActorHover : BSActor
     // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
     //     Register a prestep action to restore physical requirements before the next simulation step.
     // Called at taint-time.
-    // BSActor.RemoveBodyDependencies()
-    public override void RemoveBodyDependencies()
+    // BSActor.RemoveDependencies()
+    public override void RemoveDependencies()
     {
         // Nothing to do for the hoverer since it is all software at pre-step action time.
     }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
index 09ee32b..6059af5 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
@@ -85,8 +85,8 @@ public class BSActorLockAxis : BSActor
     // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
     //     Register a prestep action to restore physical requirements before the next simulation step.
     // Called at taint-time.
-    // BSActor.RemoveBodyDependencies()
-    public override void RemoveBodyDependencies()
+    // BSActor.RemoveDependencies()
+    public override void RemoveDependencies()
     {
         if (LockAxisConstraint != null)
         {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
index 56aacc5..1b598fd 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
@@ -88,8 +88,8 @@ public class BSActorMoveToTarget : BSActor
     // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
     //     Register a prestep action to restore physical requirements before the next simulation step.
     // Called at taint-time.
-    // BSActor.RemoveBodyDependencies()
-    public override void RemoveBodyDependencies()
+    // BSActor.RemoveDependencies()
+    public override void RemoveDependencies()
     {
         // Nothing to do for the moveToTarget since it is all software at pre-step action time.
     }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
index 3ad138d..c0f40fd 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
@@ -89,8 +89,8 @@ public class BSActorSetForce : BSActor
     // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
     //     Register a prestep action to restore physical requirements before the next simulation step.
     // Called at taint-time.
-    // BSActor.RemoveBodyDependencies()
-    public override void RemoveBodyDependencies()
+    // BSActor.RemoveDependencies()
+    public override void RemoveDependencies()
     {
         // Nothing to do for the hoverer since it is all software at pre-step action time.
     }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
index 7a791ec..b3806e1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
@@ -89,8 +89,8 @@ public class BSActorSetTorque : BSActor
     // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
     //     Register a prestep action to restore physical requirements before the next simulation step.
     // Called at taint-time.
-    // BSActor.RemoveBodyDependencies()
-    public override void RemoveBodyDependencies()
+    // BSActor.RemoveDependencies()
+    public override void RemoveDependencies()
     {
         // Nothing to do for the hoverer since it is all software at pre-step action time.
     }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
index 12a8817..5e3f1c4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
@@ -106,9 +106,9 @@ public class BSActorCollection
     {
         ForEachActor(a => a.Refresh());
     }
-    public void RemoveBodyDependencies()
+    public void RemoveDependencies()
     {
-        ForEachActor(a => a.RemoveBodyDependencies());
+        ForEachActor(a => a.RemoveDependencies());
     }
 }
 
@@ -154,7 +154,7 @@ public abstract class BSActor
     public abstract void Refresh();
     // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
     //     Register a prestep action to restore physical requirements before the next simulation step.
-    public abstract void RemoveBodyDependencies();
+    public abstract void RemoveDependencies();
 
 }
 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index a0d58d3..da23a262 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -123,8 +123,8 @@ public sealed class BSCharacter : BSPhysObject
         {
             PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
             PhysBody.Clear();
-            PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */);
-            PhysShape.Clear();
+            PhysShape.Dereference(PhysicsScene);
+            PhysShape = new BSShapeNull();
         });
     }
 
@@ -146,8 +146,8 @@ public sealed class BSCharacter : BSPhysObject
         Flying = _flying;
 
         PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
-        PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin);
-        PhysicsScene.PE.SetLocalScaling(PhysShape, Scale);
+        PhysicsScene.PE.SetMargin(PhysShape.physShapeInfo, PhysicsScene.Params.collisionMargin);
+        PhysicsScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
         PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
         if (BSParam.CcdMotionThreshold > 0f)
         {
@@ -205,9 +205,9 @@ public sealed class BSCharacter : BSPhysObject
 
             PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
             {
-                if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
+                if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
                 {
-                    PhysicsScene.PE.SetLocalScaling(PhysShape, Scale);
+                    PhysicsScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
                     UpdatePhysicalMassProperties(RawMass, true);
                     // Make sure this change appears as a property update event
                     PhysicsScene.PE.PushUpdate(PhysBody);
@@ -221,11 +221,6 @@ public sealed class BSCharacter : BSPhysObject
     {
         set { BaseShape = value; }
     }
-    // I want the physics engine to make an avatar capsule
-    public override BSPhysicsShapeType PreferredPhysicalShape
-    {
-        get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
-    }
 
     public override bool Grabbed {
         set { _grabbed = value; }
@@ -381,7 +376,7 @@ public sealed class BSCharacter : BSPhysObject
     }
     public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
     {
-        OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass);
+        OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
         PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia);
     }
 
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 612c68b..e2e807e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -625,7 +625,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
                 // Vehicles report collision events so we know when it's on the ground
                 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
 
-                ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape, m_vehicleMass);
+                ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
                 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
                 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
 
@@ -649,7 +649,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
         }
 
         // BSActor.RemoveBodyDependencies
-        public override void RemoveBodyDependencies()
+        public override void RemoveDependencies()
         {
             Refresh();
         }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 4ece1eb..df1dd34 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -93,13 +93,6 @@ public abstract class BSLinkset
     //    to the physical representation is done via the tainting mechenism.
     protected object m_linksetActivityLock = new Object();
 
-    // Some linksets have a preferred physical shape.
-    // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
-    public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
-    {
-        return BSPhysicsShapeType.SHAPE_UNKNOWN;
-    }
-
     // We keep the prim's mass in the linkset structure since it could be dependent on other prims
     public float LinksetMass { get; protected set; }
 
@@ -263,7 +256,7 @@ public abstract class BSLinkset
     // This is called when the root body is changing.
     // Returns 'true' of something was actually removed and would need restoring
     // Called at taint-time!!
-    public abstract bool RemoveBodyDependencies(BSPrimLinkable child);
+    public abstract bool RemoveDependencies(BSPrimLinkable child);
 
     // ================================================================
     protected virtual float ComputeLinksetMass()
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index e05562a..a20bbc3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -98,19 +98,6 @@ public sealed class BSLinksetCompound : BSLinkset
     {
     }
 
-    // For compound implimented linksets, if there are children, use compound shape for the root.
-    public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
-    { 
-        // Returning 'unknown' means we don't have a preference.
-        BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
-        if (IsRoot(requestor) && HasAnyChildren)
-        {
-            ret = BSPhysicsShapeType.SHAPE_COMPOUND;
-        }
-        // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
-        return ret;
-    }
-
     // When physical properties are changed the linkset needs to recalculate
     //   its internal properties.
     public override void Refresh(BSPrimLinkable requestor)
@@ -218,22 +205,22 @@ public sealed class BSLinksetCompound : BSLinkset
             //     and that is caused by us updating the object.
             if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
             {
-                    // Find the physical instance of the child 
-                if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
+                // Find the physical instance of the child 
+                if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
                 {
                     // It is possible that the linkset is still under construction and the child is not yet
                     //    inserted into the compound shape. A rebuild of the linkset in a pre-step action will
                     //    build the whole thing with the new position or rotation.
                     // The index must be checked because Bullet references the child array but does no validity
                     //    checking of the child index passed.
-                    int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
+                    int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
                     if (updated.LinksetChildIndex < numLinksetChildren)
                     {
-                        BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex);
+                        BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex);
                         if (linksetChildShape.HasPhysicalShape)
                         {
                             // Found the child shape within the compound shape
-                            PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex,
+                            PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex,
                                                                         updated.RawPosition - LinksetRoot.RawPosition,
                                                                         updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
                                                                         true /* shouldRecalculateLocalAabb */);
@@ -278,7 +265,7 @@ public sealed class BSLinksetCompound : BSLinkset
     // Since we don't keep in world relationships, do nothing unless it's a child changing.
     // Returns 'true' of something was actually removed and would need restoring
     // Called at taint-time!!
-    public override bool RemoveBodyDependencies(BSPrimLinkable child)
+    public override bool RemoveDependencies(BSPrimLinkable child)
     {
         bool ret = false;
 
@@ -404,11 +391,12 @@ public sealed class BSLinksetCompound : BSLinkset
     {
         try
         {
+            /*
             // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
             Rebuilding = true;
 
             // Cause the root shape to be rebuilt as a compound object with just the root in it
-            LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */);
+            LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime );
 
             // The center of mass for the linkset is the geometric center of the group.
             // Compute a displacement for each component so it is relative to the center-of-mass.
@@ -430,10 +418,10 @@ public sealed class BSLinksetCompound : BSLinkset
             LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
 
             // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
-            PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */,
+            PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, 0 /* childIndex ,
                                                 -centerDisplacement,
                                                 OMV.Quaternion.Identity, // LinksetRoot.RawOrientation,
-                                                false /* shouldRecalculateLocalAabb (is done later after linkset built) */);
+                                                false /* shouldRecalculateLocalAabb (is done later after linkset built) );
 
             DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
                                     LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement);
@@ -501,6 +489,7 @@ public sealed class BSLinksetCompound : BSLinkset
 
             // Enable the physical position updator to return the position and rotation of the root shape
             PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
+            */
         }
         finally
         {
@@ -508,7 +497,7 @@ public sealed class BSLinksetCompound : BSLinkset
         }
 
         // See that the Aabb surrounds the new shape
-        PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
+        PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
     }
 }
 }
\ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 6d252ca..1811772 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -93,11 +93,11 @@ public sealed class BSLinksetConstraints : BSLinkset
     //     up to rebuild the constraints before the next simulation step.
     // Returns 'true' of something was actually removed and would need restoring
     // Called at taint-time!!
-    public override bool RemoveBodyDependencies(BSPrimLinkable child)
+    public override bool RemoveDependencies(BSPrimLinkable child)
     {
         bool ret = false;
 
-        DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
+        DetailLog("{0},BSLinksetConstraint.RemoveDependencies,removeChildrenForRoot,rID={1},rBody={2}",
                                     child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
 
         lock (m_linksetActivityLock)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 309d004..b6eb619 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -88,7 +88,7 @@ public abstract class BSPhysObject : PhysicsActor
 
         // We don't have any physical representation yet.
         PhysBody = new BulletBody(localID);
-        PhysShape = new BulletShape();
+        PhysShape = new BSShapeNull();
 
         PrimAssetState = PrimAssetCondition.Unknown;
 
@@ -138,7 +138,7 @@ public abstract class BSPhysObject : PhysicsActor
     // Reference to the physical body (btCollisionObject) of this object
     public BulletBody PhysBody;
     // Reference to the physical shape (btCollisionShape) of this object
-    public BulletShape PhysShape;
+    public BSShape PhysShape;
 
     // The physical representation of the prim might require an asset fetch.
     // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
@@ -151,13 +151,6 @@ public abstract class BSPhysObject : PhysicsActor
     // The objects base shape information. Null if not a prim type shape.
     public PrimitiveBaseShape BaseShape { get; protected set; }
 
-    // Some types of objects have preferred physical representations.
-    // Returns SHAPE_UNKNOWN if there is no preference.
-    public virtual BSPhysicsShapeType PreferredPhysicalShape
-    {
-        get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
-    }
-
     // When the physical properties are updated, an EntityProperty holds the update values.
     // Keep the current and last EntityProperties to enable computation of differences
     //      between the current update and the previous values.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 4bc266b..5d12338 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -134,8 +134,8 @@ public class BSPrim : BSPhysObject
             // If there are physical body and shape, release my use of same.
             PhysicsScene.Shapes.DereferenceBody(PhysBody, null);
             PhysBody.Clear();
-            PhysicsScene.Shapes.DereferenceShape(PhysShape, null);
-            PhysShape.Clear();
+            PhysShape.Dereference(PhysicsScene);
+            PhysShape = new BSShapeNull();
         });
     }
 
@@ -161,25 +161,13 @@ public class BSPrim : BSPhysObject
             ForceBodyShapeRebuild(false);
         }
     }
-    // 'unknown' says to choose the best type
-    public override BSPhysicsShapeType PreferredPhysicalShape
-        { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
-
     public override bool ForceBodyShapeRebuild(bool inTaintTime)
     {
-        if (inTaintTime)
+        PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
         {
             _mass = CalculateMass();   // changing the shape changes the mass
             CreateGeomAndObject(true);
-        }
-        else
-        {
-            PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
-            {
-                _mass = CalculateMass();   // changing the shape changes the mass
-                CreateGeomAndObject(true);
-            });
-        }
+        });
         return true;
     }
     public override bool Grabbed {
@@ -462,7 +450,7 @@ public class BSPrim : BSPhysObject
                 Gravity = ComputeGravity(Buoyancy);
                 PhysicsScene.PE.SetGravity(PhysBody, Gravity);
 
-                Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass);
+                Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
                 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia);
                 PhysicsScene.PE.UpdateInertiaTensor(PhysBody);
 
@@ -805,7 +793,8 @@ public class BSPrim : BSPhysObject
         PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody);
 
         DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
-                        LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
+                                    LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(),
+                                    CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
     }
 
     // "Making dynamic" means changing to and from static.
@@ -1463,12 +1452,13 @@ public class BSPrim : BSPhysObject
         // Create the correct physical representation for this type of object.
         // Updates base.PhysBody and base.PhysShape with the new information.
         // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
-        PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody)
+        PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, delegate(BulletBody pBody, BulletShape pShape)
         {
             // Called if the current prim body is about to be destroyed.
             // Remove all the physical dependencies on the old body.
             // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
-            RemoveBodyDependencies();
+            // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints.
+            RemoveDependencies();
         });
 
         // Make sure the properties are set on the new object
@@ -1477,9 +1467,9 @@ public class BSPrim : BSPhysObject
     }
 
     // Called at taint-time
-    protected virtual void RemoveBodyDependencies()
+    protected virtual void RemoveDependencies()
     {
-        PhysicalActors.RemoveBodyDependencies();
+        PhysicalActors.RemoveDependencies();
     }
 
     // The physics engine says that properties have updated. Update same and inform
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index 28242d4..81104ec 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -61,9 +61,6 @@ public class BSPrimLinkable : BSPrimDisplaced
         base.Destroy();
     }
 
-    public override BSPhysicsShapeType PreferredPhysicalShape
-        { get { return Linkset.PreferredPhysicalShape(this); } }
-
     public override void link(Manager.PhysicsActor obj)
     {
         BSPrimLinkable parent = obj as BSPrimLinkable;
@@ -149,10 +146,10 @@ public class BSPrimLinkable : BSPrimDisplaced
     }
 
     // Body is being taken apart. Remove physical dependencies and schedule a rebuild.
-    protected override void RemoveBodyDependencies()
+    protected override void RemoveDependencies()
     {
-        Linkset.RemoveBodyDependencies(this);
-        base.RemoveBodyDependencies();
+        Linkset.RemoveDependencies(this);
+        base.RemoveDependencies();
     }
 
     public override void UpdateProperties(EntityProperties entprop)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 0f9b3c3..3c23509 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -38,38 +38,15 @@ public sealed class BSShapeCollection : IDisposable
 {
     private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
 
-    private BSScene PhysicsScene { get; set; }
+    private BSScene m_physicsScene { get; set; }
 
     private Object m_collectionActivityLock = new Object();
 
-    // Description of a Mesh
-    private struct MeshDesc
-    {
-        public BulletShape shape;
-        public int referenceCount;
-        public DateTime lastReferenced;
-        public UInt64 shapeKey;
-    }
-
-    // Description of a hull.
-    // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
-    private struct HullDesc
-    {
-        public BulletShape shape;
-        public int referenceCount;
-        public DateTime lastReferenced;
-        public UInt64 shapeKey;
-    }
-
-    // The sharable set of meshes and hulls. Indexed by their shape hash.
-    private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
-    private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
-
     private bool DDetail = false;
 
     public BSShapeCollection(BSScene physScene)
     {
-        PhysicsScene = physScene;
+        m_physicsScene = physScene;
         // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
         // While detailed debugging is still active, this is better than commenting out all the
         //     DetailLog statements. When debugging slows down, this and the protected logging
@@ -86,22 +63,18 @@ public sealed class BSShapeCollection : IDisposable
     // Mostly used for changing bodies out from under Linksets.
     // Useful for other cases where parameters need saving.
     // Passing 'null' says no callback.
-    public delegate void ShapeDestructionCallback(BulletShape shape);
-    public delegate void BodyDestructionCallback(BulletBody body);
+    public delegate void PhysicalDestructionCallback(BulletBody pBody, BulletShape pShape);
 
     // Called to update/change the body and shape for an object.
-    // First checks the shape and updates that if necessary then makes
-    //    sure the body is of the right type.
+    // The object has some shape and body on it. Here we decide if that is the correct shape
+    //    for the current state of the object (static/dynamic/...).
+    // If bodyCallback is not null, it is called if either the body or the shape are changed
+    //    so dependencies (like constraints) can be removed before the physical object is dereferenced.
     // Return 'true' if either the body or the shape changed.
-    // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before
-    //    the current shape or body is destroyed. This allows the caller to remove any
-    //    higher level dependencies on the shape or body. Mostly used for LinkSets to
-    //    remove the physical constraints before the body is destroyed.
-    // Called at taint-time!!
-    public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
-                    ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
+    // Called at taint-time.
+    public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback)
     {
-        PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
+        m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
 
         bool ret = false;
 
@@ -111,12 +84,12 @@ public sealed class BSShapeCollection : IDisposable
             // Do we have the correct geometry for this type of object?
             // Updates prim.BSShape with information/pointers to shape.
             // Returns 'true' of BSShape is changed to a new shape.
-            bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback);
+            bool newGeom = CreateGeom(forceRebuild, prim, bodyCallback);
             // If we had to select a new shape geometry for the object,
             //    rebuild the body around it.
             // Updates prim.BSBody with information/pointers to requested body
             // Returns 'true' if BSBody was changed.
-            bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback);
+            bool newBody = CreateBody((newGeom || forceRebuild), prim, m_physicsScene.World, bodyCallback);
             ret = newGeom || newBody;
         }
         DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
@@ -127,271 +100,20 @@ public sealed class BSShapeCollection : IDisposable
 
     public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
     {
-        return GetBodyAndShape(forceRebuild, sim, prim, null, null);
-    }
-
-    // Track another user of a body.
-    // We presume the caller has allocated the body.
-    // Bodies only have one user so the body is just put into the world if not already there.
-    private void ReferenceBody(BulletBody body)
-    {
-        lock (m_collectionActivityLock)
-        {
-            if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
-            if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
-            {
-                PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
-                if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
-            }
-        }
-    }
-
-    // Release the usage of a body.
-    // Called when releasing use of a BSBody. BSShape is handled separately.
-    // Called in taint time.
-    public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback )
-    {
-        if (!body.HasPhysicalBody)
-            return;
-
-        PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
-
-        lock (m_collectionActivityLock)
-        {
-            if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
-            // If the caller needs to know the old body is going away, pass the event up.
-            if (bodyCallback != null) bodyCallback(body);
-
-            // Removing an object not in the world is a NOOP
-            PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
-
-            // Zero any reference to the shape so it is not freed when the body is deleted.
-            PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
-            PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
-        }
-    }
-
-    // Track the datastructures and use count for a shape.
-    // When creating a hull, this is called first to reference the mesh
-    //     and then again to reference the hull.
-    // Meshes and hulls for the same shape have the same hash key.
-    // NOTE that native shapes are not added to the mesh list or removed.
-    // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
-    public bool ReferenceShape(BulletShape shape)
-    {
-        bool ret = false;
-        switch (shape.type)
-        {
-            case BSPhysicsShapeType.SHAPE_MESH:
-                MeshDesc meshDesc;
-                if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
-                {
-                    // There is an existing instance of this mesh.
-                    meshDesc.referenceCount++;
-                    if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
-                                BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
-                }
-                else
-                {
-                    // This is a new reference to a mesh
-                    meshDesc.shape = shape.Clone();
-                    meshDesc.shapeKey = shape.shapeKey;
-                    // We keep a reference to the underlying IMesh data so a hull can be built
-                    meshDesc.referenceCount = 1;
-                    if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
-                                BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
-                    ret = true;
-                }
-                meshDesc.lastReferenced = System.DateTime.Now;
-                Meshes[shape.shapeKey] = meshDesc;
-                break;
-            case BSPhysicsShapeType.SHAPE_HULL:
-                HullDesc hullDesc;
-                if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
-                {
-                    // There is an existing instance of this hull.
-                    hullDesc.referenceCount++;
-                    if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
-                                BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
-                }
-                else
-                {
-                    // This is a new reference to a hull
-                    hullDesc.shape = shape.Clone();
-                    hullDesc.shapeKey = shape.shapeKey;
-                    hullDesc.referenceCount = 1;
-                    if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
-                                BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
-                    ret = true;
-
-                }
-                hullDesc.lastReferenced = System.DateTime.Now;
-                Hulls[shape.shapeKey] = hullDesc;
-                break;
-            case BSPhysicsShapeType.SHAPE_UNKNOWN:
-                break;
-            default:
-                // Native shapes are not tracked and they don't go into any list
-                break;
-        }
-        return ret;
-    }
-
-    // Release the usage of a shape.
-    public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback)
-    {
-        if (!shape.HasPhysicalShape)
-            return;
-
-        PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape");
-
-        if (shape.HasPhysicalShape)
-        {
-            if (shape.isNativeShape)
-            {
-                // Native shapes are not tracked and are released immediately
-                if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}",
-                                    BSScene.DetailLogZero, shape.AddrString);
-                if (shapeCallback != null) shapeCallback(shape);
-                PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
-            }
-            else
-            {
-                switch (shape.type)
-                {
-                    case BSPhysicsShapeType.SHAPE_HULL:
-                        DereferenceHull(shape, shapeCallback);
-                        break;
-                    case BSPhysicsShapeType.SHAPE_MESH:
-                        DereferenceMesh(shape, shapeCallback);
-                        break;
-                    case BSPhysicsShapeType.SHAPE_COMPOUND:
-                        DereferenceCompound(shape, shapeCallback);
-                        break;
-                    case BSPhysicsShapeType.SHAPE_UNKNOWN:
-                        break;
-                    default:
-                        break;
-                }
-            }
-        }
-    }
-
-    // Count down the reference count for a mesh shape
-    // Called at taint-time.
-    private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
-    {
-        MeshDesc meshDesc;
-        if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
-        {
-            meshDesc.referenceCount--;
-            // TODO: release the Bullet storage
-            if (shapeCallback != null) shapeCallback(shape);
-            meshDesc.lastReferenced = System.DateTime.Now;
-            Meshes[shape.shapeKey] = meshDesc;
-            if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
-                                BSScene.DetailLogZero, shape, meshDesc.referenceCount);
-
-        }
+        return GetBodyAndShape(forceRebuild, sim, prim, null);
     }
 
-    // Count down the reference count for a hull shape
-    // Called at taint-time.
-    private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
+    // If the existing prim's shape is to be replaced, remove the tie to the existing shape
+    //     before replacing it.
+    private void DereferenceExistingShape(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
     {
-        HullDesc hullDesc;
-        if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
+        if (prim.PhysShape.HasPhysicalShape)
         {
-            hullDesc.referenceCount--;
-            // TODO: release the Bullet storage (aging old entries?)
-
-            // Tell upper layers that, if they have dependencies on this shape, this link is going away
-            if (shapeCallback != null) shapeCallback(shape);
-
-            hullDesc.lastReferenced = System.DateTime.Now;
-            Hulls[shape.shapeKey] = hullDesc;
-            if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
-                    BSScene.DetailLogZero, shape, hullDesc.referenceCount);
-        }
-    }
-
-    // Remove a reference to a compound shape.
-    // Taking a compound shape apart is a little tricky because if you just delete the
-    //      physical shape, it will free all the underlying children. We can't do that because
-    //      they could be shared. So, this removes each of the children from the compound and
-    //      dereferences them separately before destroying the compound collision object itself.
-    // Called at taint-time.
-    private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
-    {
-        if (!PhysicsScene.PE.IsCompound(shape))
-        {
-            // Failed the sanity check!!
-            PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
-                                        LogHeader, shape.type, shape.AddrString);
-            if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
-                                        BSScene.DetailLogZero, shape.type, shape.AddrString);
-            return;
-        }
-
-        int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape);
-        if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
-
-        for (int ii = numChildren - 1; ii >= 0; ii--)
-        {
-            BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii);
-            DereferenceAnonCollisionShape(childShape);
-        }
-        PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
-    }
-
-    // Sometimes we have a pointer to a collision shape but don't know what type it is.
-    // Figure out type and call the correct dereference routine.
-    // Called at taint-time.
-    private void DereferenceAnonCollisionShape(BulletShape shapeInfo)
-    {
-        MeshDesc meshDesc;
-        HullDesc hullDesc;
-
-        if (TryGetMeshByPtr(shapeInfo, out meshDesc))
-        {
-            shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
-            shapeInfo.shapeKey = meshDesc.shapeKey;
-        }
-        else
-        {
-            if (TryGetHullByPtr(shapeInfo, out hullDesc))
-            {
-                shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
-                shapeInfo.shapeKey = hullDesc.shapeKey;
-            }
-            else
-            {
-                if (PhysicsScene.PE.IsCompound(shapeInfo))
-                {
-                    shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
-                }
-                else
-                {
-                    if (PhysicsScene.PE.IsNativeShape(shapeInfo))
-                    {
-                        shapeInfo.isNativeShape = true;
-                        shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
-                    }
-                }
-            }
-        }
-
-        if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
-
-        if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
-        {
-            DereferenceShape(shapeInfo, null);
-        }
-        else
-        {
-            PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
-                                    LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString);
+            if (shapeCallback != null)
+                shapeCallback(prim.PhysBody, prim.PhysShape.physShapeInfo);
+            prim.PhysShape.Dereference(m_physicsScene);
         }
+        prim.PhysShape = new BSShapeNull();
     }
 
     // Create the geometry information in Bullet for later use.
@@ -402,40 +124,7 @@ public sealed class BSShapeCollection : IDisposable
     // Info in prim.BSShape is updated to the new shape.
     // Returns 'true' if the geometry was rebuilt.
     // Called at taint-time!
-    private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
-    {
-        bool ret = false;
-        bool haveShape = false;
-
-        if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
-        {
-            // an avatar capsule is close to a native shape (it is not shared)
-            GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback);
-            if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
-            ret = true;
-            haveShape = true;
-        }
-
-        // Compound shapes are handled special as they are rebuilt from scratch.
-        // This isn't too great a hardship since most of the child shapes will have already been created.
-        if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
-        {
-            ret = GetReferenceToCompoundShape(prim, shapeCallback);
-            if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
-            haveShape = true;
-        }
-
-        if (!haveShape)
-        {
-            ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
-        }
-
-        return ret;
-    }
-
-    // Create a mesh, hull or native shape.
-    // Return 'true' if the prim's shape was changed.
-    public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
+    private bool CreateGeom(bool forceRebuild, BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
     {
         bool ret = false;
         bool haveShape = false;
@@ -443,19 +132,21 @@ public sealed class BSShapeCollection : IDisposable
         PrimitiveBaseShape pbs = prim.BaseShape;
 
         // If the prim attributes are simple, this could be a simple Bullet native shape
+        // Native shapes work whether to object is static or physical.
         if (!haveShape
                 && nativeShapePossible
                 && pbs != null
-                && !pbs.SculptEntry
-                && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) )
+                && PrimHasNoCuts(pbs)
+                && ( !pbs.SculptEntry || (pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) )
+            )
         {
             // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
             OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
             if (prim.PhysShape.HasPhysicalShape)
-                scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape);
+                scaleOfExistingShape = m_physicsScene.PE.GetLocalScaling(prim.PhysShape.physShapeInfo);
 
             if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
-                        prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type);
+                        prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.physShapeInfo.shapeType);
 
             // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
             if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -463,26 +154,28 @@ public sealed class BSShapeCollection : IDisposable
             {
                 haveShape = true;
                 if (forceRebuild
-                        || prim.Scale != scaleOfExistingShape
-                        || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
-                        )
+                        || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_SPHERE
+                    )
                 {
-                    ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
-                                            FixedShapeKey.KEY_SPHERE, shapeCallback);
+                    DereferenceExistingShape(prim, shapeCallback);
+                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
+                                            BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE);
                 }
                 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
                                         prim.LocalID, forceRebuild, ret, prim.PhysShape);
             }
+            // If we didn't make a sphere, maybe a box will work.
             if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
             {
                 haveShape = true;
                 if (forceRebuild
                         || prim.Scale != scaleOfExistingShape
-                        || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
+                        || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_BOX
                         )
                 {
-                    ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
-                                            FixedShapeKey.KEY_BOX, shapeCallback);
+                    DereferenceExistingShape(prim, shapeCallback);
+                    prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
+                                            BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
                 }
                 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
                                         prim.LocalID, forceRebuild, ret, prim.PhysShape);
@@ -511,7 +204,7 @@ public sealed class BSShapeCollection : IDisposable
     }
 
     // return 'true' if the prim's shape was changed.
-    public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
+    private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
     {
 
         bool ret = false;
@@ -520,537 +213,70 @@ public sealed class BSShapeCollection : IDisposable
         if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
         {
             // Update prim.BSShape to reference a hull of this shape.
-            ret = GetReferenceToHull(prim, shapeCallback);
+            DereferenceExistingShape(prim, shapeCallback);
+            prim.PhysShape = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
             if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
-                                    prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
+                                    prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"));
         }
         else
         {
-            ret = GetReferenceToMesh(prim, shapeCallback);
+            // Update prim.BSShape to reference a mesh of this shape.
+            DereferenceExistingShape(prim, shapeCallback);
+            prim.PhysShape = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
             if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
-                                    prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
+                                    prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"));
         }
         return ret;
     }
 
-    // Creates a native shape and assignes it to prim.BSShape.
-    // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
-    private bool GetReferenceToNativeShape(BSPhysObject prim,
-                            BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
-                            ShapeDestructionCallback shapeCallback)
-    {
-        // release any previous shape
-        DereferenceShape(prim.PhysShape, shapeCallback);
-
-        BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
-
-        // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
-        if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
-                                prim.LocalID, newShape, prim.Scale);
-
-        // native shapes are scaled by Bullet
-        prim.PhysShape = newShape;
-        return true;
-    }
-
-    private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
-                                    FixedShapeKey shapeKey)
-    {
-        BulletShape newShape;
-        // Need to make sure the passed shape information is for the native type.
-        ShapeData nativeShapeData = new ShapeData();
-        nativeShapeData.Type = shapeType;
-        nativeShapeData.ID = prim.LocalID;
-        nativeShapeData.Scale = prim.Scale;
-        nativeShapeData.Size = prim.Scale;  // unneeded, I think.
-        nativeShapeData.MeshKey = (ulong)shapeKey;
-        nativeShapeData.HullKey = (ulong)shapeKey;
-
-        if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
-        {
-
-            newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale);
-            if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
-        }
-        else
-        {
-            // Native shapes are scaled in Bullet so set the scaling to the size
-            newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData);
-
-        }
-        if (!newShape.HasPhysicalShape)
-        {
-            PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
-                                    LogHeader, prim.LocalID, shapeType);
-        }
-        newShape.shapeKey = (System.UInt64)shapeKey;
-        newShape.isNativeShape = true;
-
-        return newShape;
-    }
-
-    // Builds a mesh shape in the physical world and updates prim.BSShape.
-    // Dereferences previous shape in BSShape and adds a reference for this new shape.
-    // Returns 'true' of a mesh was actually built. Otherwise .
-    // Called at taint-time!
-    private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
-    {
-        BulletShape newShape = new BulletShape();
-
-        float lod;
-        System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
-
-        // if this new shape is the same as last time, don't recreate the mesh
-        if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
-            return false;
-
-        if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
-                                prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
-
-        // Since we're recreating new, get rid of the reference to the previous shape
-        DereferenceShape(prim.PhysShape, shapeCallback);
-
-        newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
-        // Take evasive action if the mesh was not constructed.
-        newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
-
-        ReferenceShape(newShape);
-
-        prim.PhysShape = newShape;
-
-        return true;        // 'true' means a new shape has been added to this prim
-    }
-
-    private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
+    // Track another user of a body.
+    // We presume the caller has allocated the body.
+    // Bodies only have one user so the body is just put into the world if not already there.
+    private void ReferenceBody(BulletBody body)
     {
-        BulletShape newShape = new BulletShape();
-
-        MeshDesc meshDesc;
-        if (Meshes.TryGetValue(newMeshKey, out meshDesc))
-        {
-            // If the mesh has already been built just use it.
-            newShape = meshDesc.shape.Clone();
-        }
-        else
+        lock (m_collectionActivityLock)
         {
-            IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, 
-                                        false,  // say it is not physical so a bounding box is not built
-                                        false   // do not cache the mesh and do not use previously built versions
-                                        );
-
-            if (meshData != null)
+            if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
+            if (!m_physicsScene.PE.IsInWorld(m_physicsScene.World, body))
             {
-
-                int[] indices = meshData.getIndexListAsInt();
-                int realIndicesIndex = indices.Length;
-                float[] verticesAsFloats = meshData.getVertexListAsFloat();
-
-                if (BSParam.ShouldRemoveZeroWidthTriangles)
-                {
-                    // Remove degenerate triangles. These are triangles with two of the vertices
-                    //    are the same. This is complicated by the problem that vertices are not
-                    //    made unique in sculpties so we have to compare the values in the vertex.
-                    realIndicesIndex = 0;
-                    for (int tri = 0; tri < indices.Length; tri += 3)
-                    {
-                        // Compute displacements into vertex array for each vertex of the triangle
-                        int v1 = indices[tri + 0] * 3;
-                        int v2 = indices[tri + 1] * 3;
-                        int v3 = indices[tri + 2] * 3;
-                        // Check to see if any two of the vertices are the same
-                        if (!( (  verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
-                               && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
-                               && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
-                            || (  verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
-                               && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
-                               && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
-                            || (  verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
-                               && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
-                               && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
-                        )
-                        {
-                            // None of the vertices of the triangles are the same. This is a good triangle;
-                            indices[realIndicesIndex + 0] = indices[tri + 0];
-                            indices[realIndicesIndex + 1] = indices[tri + 1];
-                            indices[realIndicesIndex + 2] = indices[tri + 2];
-                            realIndicesIndex += 3;
-                        }
-                    }
-                }
-                DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
-                            BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
-
-                if (realIndicesIndex != 0)
-                {
-                    newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
-                                        realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
-                }
-                else
-                {
-                    PhysicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
-                                        LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
-                }
+                m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, body);
+                if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
             }
         }
-        newShape.shapeKey = newMeshKey;
-
-        return newShape;
-    }
-
-    // See that hull shape exists in the physical world and update prim.BSShape.
-    // We could be creating the hull because scale changed or whatever.
-    // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
-    private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
-    {
-        BulletShape newShape;
-
-        float lod;
-        System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
-
-        // if the hull hasn't changed, don't rebuild it
-        if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
-            return false;
-
-        if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
-                        prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
-
-        // Remove usage of the previous shape.
-        DereferenceShape(prim.PhysShape, shapeCallback);
-
-        newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
-        // It might not have been created if we're waiting for an asset.
-        newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
-
-        ReferenceShape(newShape);
-
-        prim.PhysShape = newShape;
-        return true;        // 'true' means a new shape has been added to this prim
     }
 
-    List<ConvexResult> m_hulls;
-    private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
+    // Release the usage of a body.
+    // Called when releasing use of a BSBody. BSShape is handled separately.
+    // Called in taint time.
+    public void DereferenceBody(BulletBody body, PhysicalDestructionCallback bodyCallback )
     {
+        if (!body.HasPhysicalBody)
+            return;
 
-        BulletShape newShape = new BulletShape();
-        IntPtr hullPtr = IntPtr.Zero;
+        m_physicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
 
-        HullDesc hullDesc;
-        if (Hulls.TryGetValue(newHullKey, out hullDesc))
-        {
-            // If the hull shape already has been created, just use the one shared instance.
-            newShape = hullDesc.shape.Clone();
-        }
-        else
+        lock (m_collectionActivityLock)
         {
-            if (BSParam.ShouldUseBulletHACD)
-            {
-                DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
-                MeshDesc meshDesc;
-                if (!Meshes.TryGetValue(newHullKey, out meshDesc))
-                {
-                    // That's odd because the mesh should have been created before the hull
-                    //     but, since it doesn't exist, create it.
-                    newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod);
-                    DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
-
-                    if (newShape.HasPhysicalShape)
-                    {
-                        ReferenceShape(newShape);
-                        Meshes.TryGetValue(newHullKey, out meshDesc);
-                    }
-                }
-                if (meshDesc.shape.HasPhysicalShape)
-                {
-                    HACDParams parms;
-                    parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
-                    parms.minClusters = BSParam.BHullMinClusters;
-                    parms.compacityWeight = BSParam.BHullCompacityWeight;
-                    parms.volumeWeight = BSParam.BHullVolumeWeight;
-                    parms.concavity = BSParam.BHullConcavity;
-                	parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
-                	parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
-                	parms.addFacesPoints =  BSParam.NumericBool(BSParam.BHullAddFacesPoints);
-                    parms.shouldAdjustCollisionMargin =  BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
-
-                    DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
-                    newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms);
-                    DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
-                }
-                DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
-            }
-            if (!newShape.HasPhysicalShape)
-            {
-                // Build a new hull in the physical world.
-                // Pass true for physicalness as this prevents the creation of bounding box which is not needed
-                IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
-                if (meshData != null)
-                {
-                    int[] indices = meshData.getIndexListAsInt();
-                    List<OMV.Vector3> vertices = meshData.getVertexList();
-
-                    //format conversion from IMesh format to DecompDesc format
-                    List<int> convIndices = new List<int>();
-                    List<float3> convVertices = new List<float3>();
-                    for (int ii = 0; ii < indices.GetLength(0); ii++)
-                    {
-                        convIndices.Add(indices[ii]);
-                    }
-                    foreach (OMV.Vector3 vv in vertices)
-                    {
-                        convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
-                    }
-
-                    uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
-                    if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
-                    {
-                        // Simple primitive shapes we know are convex so they are better implemented with
-                        //    fewer hulls.
-                        // Check for simple shape (prim without cuts) and reduce split parameter if so.
-                        if (PrimHasNoCuts(pbs))
-                        {
-                            maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
-                        }
-                    }
-
-                    // setup and do convex hull conversion
-                    m_hulls = new List<ConvexResult>();
-                    DecompDesc dcomp = new DecompDesc();
-                    dcomp.mIndices = convIndices;
-                    dcomp.mVertices = convVertices;
-                    dcomp.mDepth = maxDepthSplit;
-                    dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
-                    dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
-                    dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
-                    dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
-                    ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
-                    // create the hull into the _hulls variable
-                    convexBuilder.process(dcomp);
-
-                    DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
-                                        BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
-
-                    // Convert the vertices and indices for passing to unmanaged.
-                    // The hull information is passed as a large floating point array.
-                    // The format is:
-                    //  convHulls[0] = number of hulls
-                    //  convHulls[1] = number of vertices in first hull
-                    //  convHulls[2] = hull centroid X coordinate
-                    //  convHulls[3] = hull centroid Y coordinate
-                    //  convHulls[4] = hull centroid Z coordinate
-                    //  convHulls[5] = first hull vertex X
-                    //  convHulls[6] = first hull vertex Y
-                    //  convHulls[7] = first hull vertex Z
-                    //  convHulls[8] = second hull vertex X
-                    //  ...
-                    //  convHulls[n] = number of vertices in second hull
-                    //  convHulls[n+1] = second hull centroid X coordinate
-                    //  ...
-                    //
-                    // TODO: is is very inefficient. Someday change the convex hull generator to return
-                    //   data structures that do not need to be converted in order to pass to Bullet.
-                    //   And maybe put the values directly into pinned memory rather than marshaling.
-                    int hullCount = m_hulls.Count;
-                    int totalVertices = 1;          // include one for the count of the hulls
-                    foreach (ConvexResult cr in m_hulls)
-                    {
-                        totalVertices += 4;                         // add four for the vertex count and centroid
-                        totalVertices += cr.HullIndices.Count * 3;  // we pass just triangles
-                    }
-                    float[] convHulls = new float[totalVertices];
-
-                    convHulls[0] = (float)hullCount;
-                    int jj = 1;
-                    foreach (ConvexResult cr in m_hulls)
-                    {
-                        // copy vertices for index access
-                        float3[] verts = new float3[cr.HullVertices.Count];
-                        int kk = 0;
-                        foreach (float3 ff in cr.HullVertices)
-                        {
-                            verts[kk++] = ff;
-                        }
-
-                        // add to the array one hull's worth of data
-                        convHulls[jj++] = cr.HullIndices.Count;
-                        convHulls[jj++] = 0f;   // centroid x,y,z
-                        convHulls[jj++] = 0f;
-                        convHulls[jj++] = 0f;
-                        foreach (int ind in cr.HullIndices)
-                        {
-                            convHulls[jj++] = verts[ind].x;
-                            convHulls[jj++] = verts[ind].y;
-                            convHulls[jj++] = verts[ind].z;
-                        }
-                    }
-                    // create the hull data structure in Bullet
-                    newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
-                }
-            }
-            newShape.shapeKey = newHullKey;
-        }
-
-        return newShape;
-    }
-
-    // Callback from convex hull creater with a newly created hull.
-    // Just add it to our collection of hulls for this shape.
-    private void HullReturn(ConvexResult result)
-    {
-        m_hulls.Add(result);
-        return;
-    }
-
-    // Compound shapes are always built from scratch.
-    // This shouldn't be to bad since most of the parts will be meshes that had been built previously.
-    private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
-    {
-        // Remove reference to the old shape
-        // Don't need to do this as the shape is freed when the new root shape is created below.
-        // DereferenceShape(prim.PhysShape, true, shapeCallback);
-
-        BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false);
-
-        // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
-        CreateGeomMeshOrHull(prim, shapeCallback);
-        PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity);
-        if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
-                                    prim.LocalID, cShape, prim.PhysShape);
-
-        prim.PhysShape = cShape;
-
-        return true;
-    }
-
-    // Create a hash of all the shape parameters to be used as a key
-    //    for this particular shape.
-    public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
-    {
-        // level of detail based on size and type of the object
-        float lod = BSParam.MeshLOD;
-
-        // prims with curvy internal cuts need higher lod
-        if (pbs.HollowShape == HollowShape.Circle)
-            lod = BSParam.MeshCircularLOD;
-
-        if (pbs.SculptEntry)
-            lod = BSParam.SculptLOD;
-
-        // Mega prims usually get more detail because one can interact with shape approximations at this size.
-        float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
-        if (maxAxis > BSParam.MeshMegaPrimThreshold)
-            lod = BSParam.MeshMegaPrimLOD;
-
-        retLod = lod;
-        return pbs.GetMeshKey(size, lod);
-    }
-    // For those who don't want the LOD
-    public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
-    {
-        float lod;
-        return ComputeShapeKey(size, pbs, out lod);
-    }
-
-    // The creation of a mesh or hull can fail if an underlying asset is not available.
-    // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
-    //     and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
-    //     The first case causes the asset to be fetched. The second case requires
-    //     us to not loop forever.
-    // Called after creating a physical mesh or hull. If the physical shape was created,
-    //     just return.
-    public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
-    {
-        // If the shape was successfully created, nothing more to do
-        if (newShape.HasPhysicalShape)
-            return newShape;
+            if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
+            // If the caller needs to know the old body is going away, pass the event up.
+            if (bodyCallback != null)
+                bodyCallback(body, null);
 
-        // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
-        //    fetched but we end up here again, the meshing of the asset must have failed.
-        // Prevent trying to keep fetching the mesh by declaring failure.
-        if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
-        {
-            prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
-            physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
-                                            LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
-        }
-        else
-        {
-            // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
-            if (prim.BaseShape.SculptEntry 
-                && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed
-                && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
-                && prim.BaseShape.SculptTexture != OMV.UUID.Zero
-                )
-            {
-                physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
-                // Multiple requestors will know we're waiting for this asset
-                prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
+            // Removing an object not in the world is a NOOP
+            m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, body);
 
-                BSPhysObject xprim = prim;
-                Util.FireAndForget(delegate
-                    {
-                        RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
-                        if (assetProvider != null)
-                        {
-                            BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
-                            assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
-                            {
-                                bool assetFound = false;
-                                string mismatchIDs = String.Empty;  // DEBUG DEBUG
-                                if (asset != null && yprim.BaseShape.SculptEntry)
-                                {
-                                    if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
-                                    {
-                                        yprim.BaseShape.SculptData = asset.Data;
-                                        // This will cause the prim to see that the filler shape is not the right
-                                        //    one and try again to build the object.
-                                        // No race condition with the normal shape setting since the rebuild is at taint time.
-                                        yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
-                                        assetFound = true;
-                                    }
-                                    else
-                                    {
-                                        mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
-                                    }
-                                }
-                                if (assetFound)
-                                    yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
-                                else
-                                    yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
-                                physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
-                                            yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
+            // Zero any reference to the shape so it is not freed when the body is deleted.
+            m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, body, null);
 
-                            });
-                        }
-                        else
-                        {
-                            xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
-                            physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
-                                                        LogHeader, physicsScene.Name);
-                        }
-                    });
-            }
-            else
-            {
-                if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
-                {
-                    physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
-                                                LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
-                }
-            }
+            m_physicsScene.PE.DestroyObject(m_physicsScene.World, body);
         }
-
-        // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
-        BulletShape fillinShape = physicsScene.Shapes.BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
-        physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
-
-        return fillinShape;
     }
 
     // Create a body object in Bullet.
     // Updates prim.BSBody with the information about the new body if one is created.
     // Returns 'true' if an object was actually created.
     // Called at taint-time.
-    private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback)
+    private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, PhysicalDestructionCallback bodyCallback)
     {
         bool ret = false;
 
@@ -1061,7 +287,7 @@ public sealed class BSShapeCollection : IDisposable
         // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
         if (!mustRebuild)
         {
-            CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody);
+            CollisionObjectTypes bodyType = (CollisionObjectTypes)m_physicsScene.PE.GetBodyType(prim.PhysBody);
             if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
                 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
             {
@@ -1079,12 +305,12 @@ public sealed class BSShapeCollection : IDisposable
             BulletBody aBody;
             if (prim.IsSolid)
             {
-                aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation);
+                aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
                 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody);
             }
             else
             {
-                aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation);
+                aBody = m_physicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
                 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
             }
 
@@ -1098,46 +324,10 @@ public sealed class BSShapeCollection : IDisposable
         return ret;
     }
 
-    private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc)
-    {
-        bool ret = false;
-        MeshDesc foundDesc = new MeshDesc();
-        foreach (MeshDesc md in Meshes.Values)
-        {
-            if (md.shape.ReferenceSame(shape))
-            {
-                foundDesc = md;
-                ret = true;
-                break;
-            }
-
-        }
-        outDesc = foundDesc;
-        return ret;
-    }
-
-    private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc)
-    {
-        bool ret = false;
-        HullDesc foundDesc = new HullDesc();
-        foreach (HullDesc hd in Hulls.Values)
-        {
-            if (hd.shape.ReferenceSame(shape))
-            {
-                foundDesc = hd;
-                ret = true;
-                break;
-            }
-
-        }
-        outDesc = foundDesc;
-        return ret;
-    }
-
     private void DetailLog(string msg, params Object[] args)
     {
-        if (PhysicsScene.PhysicsLogging.Enabled)
-            PhysicsScene.DetailLog(msg, args);
+        if (m_physicsScene.PhysicsLogging.Enabled)
+            m_physicsScene.DetailLog(msg, args);
     }
 }
 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index e427dbc..a7b3f02 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 {
 public abstract class BSShape
 {
+    private static string LogHeader = "[BULLETSIM SHAPE]";
+
     public int referenceCount { get; set; }
     public DateTime lastReferenced { get; set; }
     public BulletShape physShapeInfo { get; set; }
@@ -56,49 +58,6 @@ public abstract class BSShape
         physShapeInfo = pShape;
     }
 
-    // Get a reference to a physical shape. Create if it doesn't exist
-    public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
-    {
-        BSShape ret = null;
-
-        if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
-        {
-            // an avatar capsule is close to a native shape (it is not shared)
-            ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
-                                        FixedShapeKey.KEY_CAPSULE);
-            physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
-        }
-
-        // Compound shapes are handled special as they are rebuilt from scratch.
-        // This isn't too great a hardship since most of the child shapes will have already been created.
-        if (ret == null  && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
-        {
-            // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
-            ret = BSShapeCompound.GetReference(physicsScene, prim);
-            physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
-        }
-
-        // Avatars have their own unique shape
-        if (ret == null  && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR)
-        {
-            // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
-            ret = BSShapeAvatar.GetReference(prim);
-            physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret);
-        }
-
-        if (ret == null)
-            ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
-
-        return ret;
-    }
-    private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
-    {
-        // TODO: work needed here!!
-        BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
-        BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
-        return null;
-    }
-
     // Called when this shape is being used again.
     public virtual void IncrementReference()
     {
@@ -116,6 +75,27 @@ public abstract class BSShape
     // Release the use of a physical shape.
     public abstract void Dereference(BSScene physicsScene);
 
+    // Return 'true' if there is an allocated physics physical shape under this class instance.
+    public virtual bool HasPhysicalShape
+    {
+        get
+        {
+            if (physShapeInfo != null)
+                return physShapeInfo.HasPhysicalShape;
+            return false;
+        }
+    }
+    public virtual BSPhysicsShapeType ShapeType
+    {
+        get
+        {
+            BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
+            if (physShapeInfo != null && physShapeInfo.HasPhysicalShape)
+                ret = physShapeInfo.shapeType;
+            return ret;
+        }
+    }
+
     // Returns a string for debugging that uniquily identifies the memory used by this instance
     public virtual string AddrString
     {
@@ -132,6 +112,119 @@ public abstract class BSShape
         buff.Append(">");
         return buff.ToString();
     }
+
+    // Create a hash of all the shape parameters to be used as a key for this particular shape.
+    public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
+    {
+        // level of detail based on size and type of the object
+        float lod = BSParam.MeshLOD;
+        if (pbs.SculptEntry)
+            lod = BSParam.SculptLOD;
+
+        // Mega prims usually get more detail because one can interact with shape approximations at this size.
+        float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
+        if (maxAxis > BSParam.MeshMegaPrimThreshold)
+            lod = BSParam.MeshMegaPrimLOD;
+
+        retLod = lod;
+        return pbs.GetMeshKey(size, lod);
+    }
+
+    // The creation of a mesh or hull can fail if an underlying asset is not available.
+    // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
+    //     and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
+    //     The first case causes the asset to be fetched. The second case requires
+    //     us to not loop forever.
+    // Called after creating a physical mesh or hull. If the physical shape was created,
+    //     just return.
+    public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
+    {
+        // If the shape was successfully created, nothing more to do
+        if (newShape.HasPhysicalShape)
+            return newShape;
+ 
+        // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
+        //    fetched but we end up here again, the meshing of the asset must have failed.
+        // Prevent trying to keep fetching the mesh by declaring failure.
+        if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
+        {
+            prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
+            physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
+                                            LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
+        }
+        else
+        {
+            // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
+            if (prim.BaseShape.SculptEntry 
+                && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed
+                && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
+                && prim.BaseShape.SculptTexture != OMV.UUID.Zero
+                )
+            {
+                physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
+                // Multiple requestors will know we're waiting for this asset
+                prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
+ 
+                BSPhysObject xprim = prim;
+                Util.FireAndForget(delegate
+                    {
+                        RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
+                        if (assetProvider != null)
+                        {
+                            BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
+                            assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
+                            {
+                                bool assetFound = false;
+                                string mismatchIDs = String.Empty;  // DEBUG DEBUG
+                                if (asset != null && yprim.BaseShape.SculptEntry)
+                                {
+                                    if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
+                                    {
+                                        yprim.BaseShape.SculptData = asset.Data;
+                                        // This will cause the prim to see that the filler shape is not the right
+                                        //    one and try again to build the object.
+                                        // No race condition with the normal shape setting since the rebuild is at taint time.
+                                        yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
+                                        assetFound = true;
+                                    }
+                                    else
+                                    {
+                                        mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
+                                    }
+                                }
+                                if (assetFound)
+                                    yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
+                                else
+                                    yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
+                                physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
+                                            yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
+                            });
+                        }
+                        else
+                        {
+                            xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
+                            physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
+                                                        LogHeader, physicsScene.Name);
+                        }
+                    });
+            }
+            else
+            {
+                if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
+                {
+                    physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
+                                                LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
+                }
+            }
+         }
+
+        // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
+        BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
+        physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
+
+        return fillShape.physShapeInfo;
+     }
+
 }
 
 // ============================================================================================================
@@ -199,7 +292,7 @@ public class BSShapeNative : BSShape
             physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
                                     LogHeader, prim.LocalID, shapeType);
         }
-        newShape.type = shapeType;
+        newShape.shapeType = shapeType;
         newShape.isNativeShape = true;
         newShape.shapeKey = (UInt64)shapeKey;
         return newShape;
@@ -219,10 +312,11 @@ public class BSShapeMesh : BSShape
     public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
     {
         float lod;
-        System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
+        System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
 
         physicsScene.DetailLog("{0},BSShapeMesh,getReference,oldKey={1},newKey={2},size={3},lod={4}",
-                                prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
+                                prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"),
+                                newMeshKey.ToString("X"), prim.Size, lod);
 
         BSShapeMesh retMesh = new BSShapeMesh(new BulletShape());
         lock (Meshes)
@@ -238,8 +332,8 @@ public class BSShapeMesh : BSShape
                 BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
 
                 // Check to see if mesh was created (might require an asset).
-                newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
-                if (newShape.type == BSPhysicsShapeType.SHAPE_MESH)
+                newShape = VerifyMeshCreated(physicsScene, newShape, prim);
+                if (newShape.shapeType == BSPhysicsShapeType.SHAPE_MESH)
                 {
                     // If a mesh was what was created, remember the built shape for later sharing.
                     Meshes.Add(newMeshKey, retMesh);
@@ -360,10 +454,10 @@ public class BSShapeHull : BSShape
     public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
     {
         float lod;
-        System.UInt64 newHullKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
+        System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
 
         physicsScene.DetailLog("{0},BSShapeHull,getReference,oldKey={1},newKey={2},size={3},lod={4}",
-                                prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod);
+                                prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod);
 
         BSShapeHull retHull = new BSShapeHull(new BulletShape());
         lock (Hulls)
@@ -379,8 +473,8 @@ public class BSShapeHull : BSShape
                 BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);
 
                 // Check to see if mesh was created (might require an asset).
-                newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
-                if (newShape.type == BSPhysicsShapeType.SHAPE_MESH)
+                newShape = VerifyMeshCreated(physicsScene, newShape, prim);
+                if (newShape.shapeType == BSPhysicsShapeType.SHAPE_MESH)
                 {
                     // If a mesh was what was created, remember the built shape for later sharing.
                     Hulls.Add(newHullKey, retHull);
@@ -569,7 +663,6 @@ public class BSShapeHull : BSShape
     }
 }
 
-
 // ============================================================================================================
 public class BSShapeCompound : BSShape
 {
@@ -589,9 +682,9 @@ public class BSShapeCompound : BSShape
         {
             // Failed the sanity check!!
             physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
-                                        LogHeader, physShapeInfo.type, physShapeInfo.AddrString);
+                                        LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString);
             physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
-                                        BSScene.DetailLogZero, physShapeInfo.type, physShapeInfo.AddrString);
+                                        BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString);
             return;
         }
 
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
index 8012d91..906e4f9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
@@ -104,11 +104,11 @@ public class BulletShape
 {
     public BulletShape()
     {
-        type = BSPhysicsShapeType.SHAPE_UNKNOWN;
+        shapeType = BSPhysicsShapeType.SHAPE_UNKNOWN;
         shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
         isNativeShape = false;
     }
-    public BSPhysicsShapeType type;
+    public BSPhysicsShapeType shapeType;
     public System.UInt64 shapeKey;
     public bool isNativeShape;
 
@@ -133,7 +133,7 @@ public class BulletShape
         buff.Append("<p=");
         buff.Append(AddrString);
         buff.Append(",s=");
-        buff.Append(type.ToString());
+        buff.Append(shapeType.ToString());
         buff.Append(",k=");
         buff.Append(shapeKey.ToString("X"));
         buff.Append(",n=");
-- 
cgit v1.1