예제 #1
0
    // 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 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(prim);
            physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
        }

        if (ret == null)
            ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);

        return ret;
    }
        private bool UseBulletSimRootOffsetHack = false; // Attempt to have Bullet track the coords of root compound shape
        private void RecomputeLinksetCompound()
        {
            try
            {
                Rebuilding = true;

                // No matter what is being done, force the root prim's PhysBody and PhysShape to get set
                //     to what they should be as if the root was not in a linkset.
                // Not that bad since we only get into this routine if there are children in the linkset and
                //     something has been updated/changed.
                // Have to do the rebuild before checking for physical because this might be a linkset
                //     being destructed and going non-physical.
                LinksetRoot.ForceBodyShapeRebuild(true);

                // There is no reason to build all this physical stuff for a non-physical linkset.
                if (!LinksetRoot.IsPhysicallyActive)
                {
                    DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID);
                    return; // Note the 'finally' clause at the botton which will get executed.
                }

                // Get a new compound shape to build the linkset shape in.
                BSShape linksetShape = BSShapeCompound.GetReference(m_physicsScene);

                // Compute a displacement for each component so it is relative to the center-of-mass.
                // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
                OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass();

                OMV.Quaternion invRootOrientation = OMV.Quaternion.Normalize(OMV.Quaternion.Inverse(LinksetRoot.RawOrientation));
                OMV.Vector3    origRootPosition   = LinksetRoot.RawPosition;

                // 'centerDisplacementV' is the vehicle relative distance from the simulator root position to the center-of-mass
                OMV.Vector3 centerDisplacementV = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
                if (UseBulletSimRootOffsetHack || !BSParam.LinksetOffsetCenterOfMass)
                {
                    // Zero everything if center-of-mass displacement is not being done.
                    centerDisplacementV = OMV.Vector3.Zero;
                    LinksetRoot.ClearDisplacement();
                }
                else
                {
                    // The actual center-of-mass could have been set by the user.
                    centerDisplacementV = LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacementV);
                }

                DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}",
                          LinksetRoot.LocalID, origRootPosition, centerOfMassW, centerDisplacementV);

                // Add the shapes of all the components of the linkset
                int memberIndex = 1;
                ForEachMember((cPrim) =>
                {
                    if (IsRoot(cPrim))
                    {
                        // Root shape is always index zero.
                        cPrim.LinksetChildIndex = 0;
                    }
                    else
                    {
                        cPrim.LinksetChildIndex = memberIndex;
                        memberIndex++;
                    }

                    // Get a reference to the shape of the child for adding of that shape to the linkset compound shape
                    BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim);

                    // Offset the child shape from the center-of-mass and rotate it to vehicle relative.
                    OMV.Vector3 offsetPos    = (cPrim.RawPosition - origRootPosition) * invRootOrientation - centerDisplacementV;
                    OMV.Quaternion offsetRot = OMV.Quaternion.Normalize(cPrim.RawOrientation) * invRootOrientation;

                    // Add the child shape to the compound shape being built
                    m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot);
                    DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}",
                              LinksetRoot.LocalID, cPrim.LinksetChildIndex, childShape, offsetPos, offsetRot);

                    // Since we are borrowing the shape of the child, disable the origional child body
                    if (!IsRoot(cPrim))
                    {
                        m_physicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
                        m_physicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION);
                        // We don't want collisions from the old linkset children.
                        m_physicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
                        cPrim.PhysBody.collisionType = CollisionType.LinksetChild;
                    }

                    return(false); // 'false' says to move onto the next child in the list
                });

                // Replace the root shape with the built compound shape.
                // Object removed and added to world to get collision cache rebuilt for new shape.
                LinksetRoot.PhysShape.Dereference(m_physicsScene);
                LinksetRoot.PhysShape = linksetShape;
                m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, LinksetRoot.PhysBody);
                m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo);
                m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody);
                DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}",
                          LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape);

                // With all of the linkset packed into the root prim, it has the mass of everyone.
                LinksetMass = ComputeLinksetMass();
                LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);

                if (UseBulletSimRootOffsetHack)
                {
                    // Enable the physical position updator to return the position and rotation of the root shape.
                    // This enables a feature in the C++ code to return the world coordinates of the first shape in the
                    //     compound shape. This aleviates the need to offset the returned physical position by the
                    //     center-of-mass offset.
                    // TODO: either debug this feature or remove it.
                    m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
                }
            }
            finally
            {
                Rebuilding = false;
            }

            // See that the Aabb surrounds the new shape
            m_physicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
        }
예제 #3
0
 public static bool TryGetCompoundByPtr(BulletShape pShape, out BSShapeCompound outCompound)
 {
     lock (CompoundShapes)
     {
         string addr = pShape.AddrString;
         return CompoundShapes.TryGetValue(addr, out outCompound);
     }
 }
예제 #4
0
 public static BSShape GetReference(BSScene physicsScene)
 {
     // Base compound shapes are not shared so this returns a raw shape.
     // A built compound shape can be reused in linksets.
     BSShapeCompound ret = new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene));
     CompoundShapes.Add(ret.AddrString, ret);
     return ret;
 }
예제 #5
0
 // 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(BSScene physicsScene, BulletShape pShape)
 {
     BSShapeMesh meshDesc;
     if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
     {
         meshDesc.Dereference(physicsScene);
     }
     else
     {
         BSShapeHull hullDesc;
         if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc))
         {
             hullDesc.Dereference(physicsScene);
         }
         else
         {
             BSShapeConvexHull chullDesc;
             if (BSShapeConvexHull.TryGetHullByPtr(pShape, out chullDesc))
             {
                 chullDesc.Dereference(physicsScene);
             }
             else
             {
                 if (physicsScene.PE.IsCompound(pShape))
                 {
                     BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
                     recursiveCompound.Dereference(physicsScene);
                 }
                 else
                 {
                     if (physicsScene.PE.IsNativeShape(pShape))
                     {
                         BSShapeNative nativeShape = new BSShapeNative(pShape);
                         nativeShape.Dereference(physicsScene);
                     }
                 }
             }
         }
     }
 }
예제 #6
0
 // 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(BSScene physicsScene, BulletShape pShape)
 {
     // TODO: figure a better way to go through all the shape types and find a possible instance.
     BSShapeMesh meshDesc;
     if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
     {
         meshDesc.Dereference(physicsScene);
     }
     else
     {
         BSShapeHull hullDesc;
         if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc))
         {
             hullDesc.Dereference(physicsScene);
         }
         else
         {
             BSShapeConvexHull chullDesc;
             if (BSShapeConvexHull.TryGetHullByPtr(pShape, out chullDesc))
             {
                 chullDesc.Dereference(physicsScene);
             }
             else
             {
                 BSShapeGImpact gImpactDesc;
                 if (BSShapeGImpact.TryGetGImpactByPtr(pShape, out gImpactDesc))
                 {
                     gImpactDesc.Dereference(physicsScene);
                 }
                 else
                 {
                     // Didn't find it in the lists of specific types. It could be compound.
                     if (physicsScene.PE.IsCompound(pShape))
                     {
                         BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
                         recursiveCompound.Dereference(physicsScene);
                     }
                     else
                     {
                         // If none of the above, maybe it is a simple native shape.
                         if (physicsScene.PE.IsNativeShape(pShape))
                         {
                             BSShapeNative nativeShape = new BSShapeNative(pShape);
                             nativeShape.Dereference(physicsScene);
                         }
                     }
                 }
             }
         }
     }
 }