Esempio n. 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);
        }
Esempio n. 2
0
        private void ReportShapeGeom(BSPrim prim)
        {
            if (prim != null)
            {
                if (prim.PhysShape.HasPhysicalShape)
                {
                    BSShape physShape = prim.PhysShape;
                    string  shapeType = physShape.GetType().ToString();
                    switch (shapeType)
                    {
                    case "OpenSim.Region.Physics.BulletSPlugin.BSShapeNative":
                        BSShapeNative nShape = physShape as BSShapeNative;
                        prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType);
                        break;

                    case "OpenSim.Region.Physics.BulletSPlugin.BSShapeMesh":
                        BSShapeMesh mShape = physShape as BSShapeMesh;
                        prim.PhysScene.DetailLog("{0}, mesh, shapeInfo={1}", prim.Name, mShape.shapeInfo);
                        break;

                    case "OpenSim.Region.Physics.BulletSPlugin.BSShapeHull":
                        // BSShapeHull hShape = physShape as BSShapeHull;
                        // prim.PhysScene.DetailLog("{0}, hull, shapeInfo={1}", prim.Name, hShape.shapeInfo);
                        break;

                    case "OpenSim.Region.Physics.BulletSPlugin.BSShapeConvexHull":
                        BSShapeConvexHull chShape = physShape as BSShapeConvexHull;
                        prim.PhysScene.DetailLog("{0}, convexHull, shapeInfo={1}", prim.Name, chShape.shapeInfo);
                        break;

                    case "OpenSim.Region.Physics.BulletSPlugin.BSShapeCompound":
                        BSShapeCompound cShape = physShape as BSShapeCompound;
                        prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType);
                        break;

                    default:
                        prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType);
                        break;
                    }
                }
            }
        }
Esempio n. 3
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);
                        }
                    }
                }
            }
        }
    }
        // Attempt to have Bullet track the coords of root compound shape

        void RecomputeLinksetCompound()
        {
            try
            {
                // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
                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 or empty linkset.
                if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
                {
                    DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysicalOrNoChildren",
                              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(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.RecumputeLinksetCompound,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(PhysicsScene, cPrim);

                    // Offset the child shape from the center-of-mass and rotate it to root 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 build
                    if (childShape.physShapeInfo.HasPhysicalShape)
                    {
                        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 original child body
                        if (!IsRoot(cPrim))
                        {
                            PhysicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
                            PhysicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION);

                            // We don't want collision from the old linkset children.
                            PhysicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody,
                                                                     CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
                            cPrim.PhysBody.collisionType = CollisionType.LinksetChild;
                        }
                    }
                    else
                    {
                        // The linkset must be in an intermediate state where all the children have not yet
                        //    been constructed. This sometimes happens on startup when everything is getting
                        //    built and some shapes have to wait for assets to be read in.
                        // Just skip this linkset for the moment and cause the shape to be rebuilt next tick.
                        // One problem might be that the shape is broken somehow and it never becomes completely
                        //    available. This might cause the rebuild to happen over and over.
                        InternalScheduleRebuild(LinksetRoot);
                        DetailLog(
                            "{0},BSLinksetCompound.RecomputeLinksetCompound,addChildWithNoShape,indx={1},cShape={2},offPos={3},offRot={4}",
                            LinksetRoot.LocalID, cPrim.LinksetChildIndex, childShape, offsetPos, offsetRot);
                        // Output an annoying warning. It should only happen once but if it keeps coming out,
                        //    the user knows there is something wrong and will report it.
                        PhysicsScene.Logger.WarnFormat(
                            "{0} Linkset rebuild warning. If this happens more than one or two times, please report in the issue tracker",
                            LogHeader);
                        PhysicsScene.Logger.WarnFormat("{0} pName={1}, childIdx={2}, shape={3}",
                                                       LogHeader, LinksetRoot.Name, cPrim.LinksetChildIndex, childShape);

                        // This causes the loop to bail on building the rest of this linkset.
                        // The rebuild operation will fix it up next tick or declare the object unbuildable.
                        return(true);
                    }
                    return(false); // 'false' says to move anto the nex 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(PhysicsScene);
                LinksetRoot.PhysShape = linksetShape;
                PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, LinksetRoot.PhysBody);
                PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo);
                PhysicsScene.PE.AddObjectToWorld(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.
                    PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody,
                                                        CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
                }
            }
            finally
            {
                Rebuilding = false;
            }

            // See that the Aabb surround the new shape
            PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
        }