示例#1
0
        // 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.
        // 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)
        {
            PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");

            bool ret = false;

            // This lock could probably be pushed down lower but building shouldn't take long
            lock (m_collectionActivityLock)
            {
                // 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);
                // 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,
                                          prim.PhysShape, bodyCallback);
                ret = newGeom || newBody;
            }
            DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
                      prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape);

            return(ret);
        }
示例#2
0
        // 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 (!BulletSimAPI.IsCompound2(shape.ptr))
            {
                // 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.ptr.ToString());
                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
                              BSScene.DetailLogZero, shape.type, shape.ptr.ToString());
                }
                return;
            }

            int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);

            if (DDetail)
            {
                DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
            }

            for (int ii = numChildren - 1; ii >= 0; ii--)
            {
                Object childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii);
                DereferenceAnonCollisionShape(childShape);
            }
            BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
        }
示例#3
0
        // See that hull shape exists in the physical world and update prim.BSShape.
        // We could be creating the hull because scale changed or whatever.
        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, true, shapeCallback);

            newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
            newShape = VerifyMeshCreated(newShape, prim);

            ReferenceShape(newShape);

            prim.PhysShape = newShape;
            return(true);   // 'true' means a new shape has been added to this prim
        }
示例#4
0
        public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
        {
            bool ret = false;

            // Note that if it's a native shape, the check for physical/non-physical is not
            //     made. Native shapes work in either case.
            if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
            {
                // Update prim.BSShape to reference a hull of this shape.
                ret = GetReferenceToHull(prim, shapeCallback);
                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
                              prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
                }
            }
            else
            {
                ret = GetReferenceToMesh(prim, shapeCallback);
                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
                              prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
                }
            }
            return(ret);
        }
示例#5
0
        // 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}",
                          prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
            }

            // Since we're recreating new, get rid of the reference to the previous shape
            DereferenceShape(prim.PhysShape, true, shapeCallback);

            newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod);
            // Take evasive action if the mesh was not constructed.
            newShape = VerifyMeshCreated(newShape, prim);

            ReferenceShape(newShape);

            prim.PhysShape = newShape;

            return(true);   // 'true' means a new shape has been added to this prim
        }
示例#6
0
        // Creates a native shape and assignes it to prim.BSShape
        private bool GetReferenceToNativeShape(BSPrim prim, ShapeData shapeData,
                                               ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
                                               ShapeDestructionCallback shapeCallback)
        {
            BulletShape newShape;

            shapeData.Type = shapeType;
            // Bullet native objects are scaled by the Bullet engine so pass the size in
            prim.Scale      = shapeData.Size;
            shapeData.Scale = shapeData.Size;

            // release any previous shape
            DereferenceShape(prim.BSShape, true, shapeCallback);

            // Native shapes are always built independently.
            newShape               = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
            newShape.shapeKey      = (ulong)shapeKey;
            newShape.isNativeShape = true;

            // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked.
            // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape);

            prim.BSShape = newShape;
            return(true);
        }
示例#7
0
        // See that hull shape exists in the physical world and update prim.BSShape.
        // We could be creating the hull because scale changed or whatever.
        private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs,
                                        ShapeDestructionCallback shapeCallback)
        {
            BulletShape newShape;

            float lod;
            ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod);

            // if the hull hasn't changed, don't rebuild it
            if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
            {
                return(false);
            }

            DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
                      prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));

            // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull.
            DereferenceShape(prim.BSShape, true, shapeCallback);

            newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);

            ReferenceShape(newShape);

            // hulls are already scaled by the meshmerizer
            prim.Scale   = new OMV.Vector3(1f, 1f, 1f);
            prim.BSShape = newShape;
            return(true);   // 'true' means a new shape has been added to this prim
        }
示例#8
0
        // 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(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs,
                                        ShapeDestructionCallback shapeCallback)
        {
            BulletShape newShape = new BulletShape(IntPtr.Zero);

            float lod;
            ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);

            // if this new shape is the same as last time, don't recreate the mesh
            if (prim.BSShape.shapeKey == newMeshKey)
            {
                return(false);
            }

            DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}",
                      prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));

            // Since we're recreating new, get rid of the reference to the previous shape
            DereferenceShape(prim.BSShape, true, shapeCallback);

            newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod);

            ReferenceShape(newShape);

            // meshes are already scaled by the meshmerizer
            prim.Scale   = new OMV.Vector3(1f, 1f, 1f);
            prim.BSShape = newShape;

            return(true);   // 'true' means a new shape has been added to this prim
        }
示例#9
0
        // Release the usage of a shape.
        public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
        {
            if (!shape.HasPhysicalShape)
            {
                return;
            }

            PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
            {
                if (shape.HasPhysicalShape)
                {
                    if (shape.isNativeShape)
                    {
                        // Native shapes are not tracked and are released immediately
                        if (DDetail)
                        {
                            DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
                                      BSScene.DetailLogZero, shape.ptr.ToString(), inTaintTime);
                        }
                        if (shapeCallback != null)
                        {
                            shapeCallback(shape);
                        }
                        BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
                    }
                    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;
                        }
                    }
                }
            });
        }
示例#10
0
        // Release the usage of a shape.
        // The collisionObject is released since it is a copy of the real collision shape.
        public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback)
        {
            if (shape.ptr == IntPtr.Zero)
            {
                return;
            }

            BSScene.TaintCallback dereferenceOperation = delegate()
            {
                switch (shape.type)
                {
                case ShapeData.PhysicsShapeType.SHAPE_HULL:
                    DereferenceHull(shape, shapeCallback);
                    break;

                case ShapeData.PhysicsShapeType.SHAPE_MESH:
                    DereferenceMesh(shape, shapeCallback);
                    break;

                case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
                    break;

                default:
                    // Native shapes are not tracked and are released immediately
                    if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
                    {
                        DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
                                  BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime);
                        if (shapeCallback != null)
                        {
                            shapeCallback(shape);
                        }
                        BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
                    }
                    break;
                }
            };
            if (atTaintTime)
            {
                lock (m_collectionActivityLock)
                {
                    dereferenceOperation();
                }
            }
            else
            {
                PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation);
            }
        }
示例#11
0
        // 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;
                DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}",
                          BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
            }
        }
示例#12
0
        // Count down the reference count for a hull shape
        // Called at taint-time.
        private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
        {
            HullDesc hullDesc;

            if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
            {
                hullDesc.referenceCount--;
                // TODO: release the Bullet storage (aging old entries?)
                if (shapeCallback != null)
                {
                    shapeCallback(shape);
                }
                hullDesc.lastReferenced = System.DateTime.Now;
                Hulls[shape.shapeKey]   = hullDesc;
                DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}",
                          BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
            }
        }
示例#13
0
        // 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, true, 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);
        }
示例#14
0
        // 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 = new BulletShape(
                BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND);

            // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
            CreateGeomMeshOrHull(prim, shapeCallback);
            BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, 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);
        }
示例#15
0
        // 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.
        // Return 'true' if either the body or the shape changed.
        // Called at taint-time!!
        public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim,
                                    ShapeData shapeData, PrimitiveBaseShape pbs,
                                    ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
        {
            bool ret = false;

            // This lock could probably be pushed down lower but building shouldn't take long
            lock (m_collectionActivityLock)
            {
                // Do we have the correct geometry for this type of object?
                // Updates prim.BSShape with information/pointers to requested shape
                bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback);
                // 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
                bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback);
                ret = newGeom || newBody;
            }
            DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}",
                      prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape);

            return(ret);
        }
示例#16
0
        // Create the geometry information in Bullet for later use.
        // The objects needs a hull if it's physical otherwise a mesh is enough.
        // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls,
        //     shared geometries will be used. If the parameters of the existing shape are the same
        //     as this request, the shape is not rebuilt.
        // 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);
        }
示例#17
0
        // Count down the reference count for a hull shape
        // Called at taint-time.
        private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
        {
            HullDesc hullDesc;

            if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
            {
                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);
                }
            }
        }
示例#18
0
    // See that hull shape exists in the physical world and update prim.BSShape.
    // We could be creating the hull because scale changed or whatever.
    private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs,
                                ShapeDestructionCallback shapeCallback)
    {
        BulletShape newShape;

        float lod;
        ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod);

        // if the hull hasn't changed, don't rebuild it
        if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
            return false;

        DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
                        prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));

        // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull.
        DereferenceShape(prim.BSShape, true, shapeCallback);

        newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);

        ReferenceShape(newShape);

        // hulls are already scaled by the meshmerizer
        prim.Scale = new OMV.Vector3(1f, 1f, 1f);
        prim.BSShape = newShape;
        return true;        // 'true' means a new shape has been added to this prim
    }
示例#19
0
    // 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(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs,
                                ShapeDestructionCallback shapeCallback)
    {
        BulletShape newShape = new BulletShape(IntPtr.Zero);

        float lod;
        ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);

        // if this new shape is the same as last time, don't recreate the mesh
        if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
            return false;

        DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}",
                                prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));

        // Since we're recreating new, get rid of the reference to the previous shape
        DereferenceShape(prim.BSShape, true, shapeCallback);

        newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod);

        ReferenceShape(newShape);

        // meshes are already scaled by the meshmerizer
        prim.Scale = new OMV.Vector3(1f, 1f, 1f);
        prim.BSShape = newShape;

        return true;        // 'true' means a new shape has been added to this prim
    }
 // return 'true' if the prim's shape was changed.
 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
 {
     bool ret = false;
     // Note that if it's a native shape, the check for physical/non-physical is not
     //     made. Native shapes work in either case.
     if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
     {
     // Update prim.BSShape to reference a hull of this shape.
     ret = GetReferenceToHull(prim, shapeCallback);
     if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
                             prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
     }
     else
     {
     ret = GetReferenceToMesh(prim, shapeCallback);
     if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
                             prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
     }
     return ret;
 }
示例#21
0
    // 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.
    // Return 'true' if either the body or the shape changed.
    // Called at taint-time!!
    public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, 
                    ShapeData shapeData, PrimitiveBaseShape pbs,
                    ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
    {
        bool ret = false;

        // This lock could probably be pushed down lower but building shouldn't take long
        lock (m_collectionActivityLock)
        {
            // Do we have the correct geometry for this type of object?
            // Updates prim.BSShape with information/pointers to requested shape
            bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback);
            // 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
            bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, 
                                    prim.BSShape, shapeData, bodyCallback);
            ret = newGeom || newBody;
        }
        DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}",
                                prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape);

        return ret;
    }
        // 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);

            }
        }
        // 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)
        {
            bool ret = false;
            bool haveShape = false;
            bool nativeShapePossible = true;
            PrimitiveBaseShape pbs = prim.BaseShape;

            // If the prim attributes are simple, this could be a simple Bullet native shape
            if (!haveShape
                && nativeShapePossible
                && pbs != null
                && !pbs.SculptEntry
                && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) )
            {
            // 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);

            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);

            // 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)
                                && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
            {
                haveShape = true;
                if (forceRebuild
                        || prim.Scale != scaleOfExistingShape
                        || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
                        )
                {
                    ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
                                            FixedShapeKey.KEY_SPHERE, shapeCallback);
                }
                if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
                                        prim.LocalID, forceRebuild, ret, prim.PhysShape);
            }
            if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
            {
                haveShape = true;
                if (forceRebuild
                        || prim.Scale != scaleOfExistingShape
                        || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
                        )
                {
                    ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
                                            FixedShapeKey.KEY_BOX, shapeCallback);
                }
                if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
                                        prim.LocalID, forceRebuild, ret, prim.PhysShape);
            }
            }

            // If a simple shape is not happening, create a mesh and possibly a hull.
            if (!haveShape && pbs != null)
            {
            ret = CreateGeomMeshOrHull(prim, shapeCallback);
            }

            return ret;
        }
示例#24
0
 // Count down the reference count for a hull shape
 // Called at taint-time.
 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
 {
     HullDesc hullDesc;
     if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
     {
         hullDesc.referenceCount--;
         // TODO: release the Bullet storage (aging old entries?)
         if (shapeCallback != null) shapeCallback(shape);
         hullDesc.lastReferenced = System.DateTime.Now;
         Hulls[shape.shapeKey] = hullDesc;
         DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}",
                 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
     }
 }
示例#25
0
    // Release the usage of a shape.
    // The collisionObject is released since it is a copy of the real collision shape.
    public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback)
    {
        if (shape.ptr == IntPtr.Zero)
            return;

        BSScene.TaintCallback dereferenceOperation = delegate()
        {
            switch (shape.type)
            {
                case ShapeData.PhysicsShapeType.SHAPE_HULL:
                    DereferenceHull(shape, shapeCallback);
                    break;
                case ShapeData.PhysicsShapeType.SHAPE_MESH:
                    DereferenceMesh(shape, shapeCallback);
                    break;
                case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
                    break;
                default:
                    // Native shapes are not tracked and are released immediately
                    if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
                    {
                        DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
                                        BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime);
                        if (shapeCallback != null) shapeCallback(shape);
                        BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
                    }
                    break;
            }
        };
        if (atTaintTime)
        {
            lock (m_collectionActivityLock)
            {
                dereferenceOperation();
            }
        }
        else
        {
            PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation);
        }
    }
        // 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.
        // 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)
        {
            PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");

            bool ret = false;

            // This lock could probably be pushed down lower but building shouldn't take long
            lock (m_collectionActivityLock)
            {
            // 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);
            // 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);
            ret = newGeom || newBody;
            }
            DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
                                prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape);

            return ret;
        }
示例#27
0
    // Creates a native shape and assignes it to prim.BSShape
    private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData,
                            ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
                            ShapeDestructionCallback shapeCallback)
    {
        BulletShape newShape;

        shapeData.Type = shapeType;
        // Bullet native objects are scaled by the Bullet engine so pass the size in
        prim.Scale = shapeData.Size;
        shapeData.Scale = shapeData.Size;

        // release any previous shape
        DereferenceShape(prim.BSShape, true, shapeCallback);

        // Native shapes are always built independently.
        newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
        newShape.shapeKey = (ulong)shapeKey;
        newShape.isNativeShape = true;

        // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked.
        // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape);

        prim.BSShape = newShape;
        return true;
    }
        // Create the geometry information in Bullet for later use.
        // The objects needs a hull if it's physical otherwise a mesh is enough.
        // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls,
        //     shared geometries will be used. If the parameters of the existing shape are the same
        //     as this request, the shape is not rebuilt.
        // 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;
        }
示例#29
0
    // 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, ShapeData shapeData,
                            ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
                            ShapeDestructionCallback shapeCallback)
    {
        // release any previous shape
        DereferenceShape(prim.BSShape, true, shapeCallback);

        shapeData.Type = shapeType;
        // Bullet native objects are scaled by the Bullet engine so pass the size in
        prim.Scale = shapeData.Size;
        shapeData.Scale = shapeData.Size;

        BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey);

        // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
        DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
                                shapeData.ID, newShape, shapeData.Scale);

        prim.BSShape = newShape;
        return true;
    }
        // 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);
        }
        // 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.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
            // It might not have been created if we're waiting for an asset.
            newShape = VerifyMeshCreated(newShape, prim);

            ReferenceShape(newShape);

            prim.PhysShape = newShape;
            return true;        // 'true' means a new shape has been added to this prim
        }
        // 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;
        }
示例#33
0
    // Create the geometry information in Bullet for later use.
    // The objects needs a hull if it's physical otherwise a mesh is enough.
    // No locking here because this is done when we know physics is not simulating.
    // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
    // Returns 'true' if the geometry was rebuilt.
    // Called at taint-time!
    private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, 
                            PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback)
    {
        bool ret = false;
        bool haveShape = false;
        bool nativeShapePossible = true;

        // If the prim attributes are simple, this could be a simple Bullet native shape
        if (nativeShapePossible
                && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
                    || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
                        && pbs.ProfileHollow == 0
                        && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
                        && pbs.PathBegin == 0 && pbs.PathEnd == 0
                        && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
                        && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
                        && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
        {
            if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
            {
                haveShape = true;
                if (forceRebuild
                        || prim.Scale != shapeData.Size
                        || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE
                        )
                {
                    ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, 
                                            ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback);
                    DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
                                        prim.LocalID, forceRebuild, prim.BSShape);
                }
            }
            else
            {
                haveShape = true;
                if (forceRebuild
                        || prim.Scale != shapeData.Size
                        || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX
                        )
                {
                    ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, 
                                            ShapeData.FixedShapeKey.KEY_BOX, shapeCallback);
                    DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
                                        prim.LocalID, forceRebuild, prim.BSShape);
                }
            }
        }
        // If a simple shape is not happening, create a mesh and possibly a hull.
        // Note that if it's a native shape, the check for physical/non-physical is not
        //     made. Native shapes are best used in either case.
        if (!haveShape)
        {
            if (prim.IsPhysical)
            {
                // Update prim.BSShape to reference a hull of this shape.
                ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback);
                DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
                                        shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X"));
            }
            else
            {
                ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback);
                DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
                                        shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X"));
            }
        }
        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;
                }
            }
            }
        }
示例#35
0
        // Create the geometry information in Bullet for later use.
        // The objects needs a hull if it's physical otherwise a mesh is enough.
        // No locking here because this is done when we know physics is not simulating.
        // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
        // Returns 'true' if the geometry was rebuilt.
        // Called at taint-time!
        private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData,
                                PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback)
        {
            bool ret                 = false;
            bool haveShape           = false;
            bool nativeShapePossible = true;

            // If the prim attributes are simple, this could be a simple Bullet native shape
            if (nativeShapePossible &&
                ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) ||
                 (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 &&
                  pbs.ProfileHollow == 0 &&
                  pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 &&
                  pbs.PathBegin == 0 && pbs.PathEnd == 0 &&
                  pbs.PathTaperX == 0 && pbs.PathTaperY == 0 &&
                  pbs.PathScaleX == 100 && pbs.PathScaleY == 100 &&
                  pbs.PathShearX == 0 && pbs.PathShearY == 0)))
            {
                if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
                {
                    haveShape = true;
                    if (forceRebuild ||
                        prim.Scale != shapeData.Size ||
                        prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE
                        )
                    {
                        ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE,
                                                        ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback);
                        DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
                                  prim.LocalID, forceRebuild, prim.BSShape);
                    }
                }
                else
                {
                    haveShape = true;
                    if (forceRebuild ||
                        prim.Scale != shapeData.Size ||
                        prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX
                        )
                    {
                        ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX,
                                                        ShapeData.FixedShapeKey.KEY_BOX, shapeCallback);
                        DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
                                  prim.LocalID, forceRebuild, prim.BSShape);
                    }
                }
            }
            // If a simple shape is not happening, create a mesh and possibly a hull.
            // Note that if it's a native shape, the check for physical/non-physical is not
            //     made. Native shapes are best used in either case.
            if (!haveShape)
            {
                if (prim.IsPhysical)
                {
                    // Update prim.BSShape to reference a hull of this shape.
                    ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback);
                    DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
                              shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X"));
                }
                else
                {
                    ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback);
                    DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
                              shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X"));
                }
            }
            return(ret);
        }
示例#36
0
        // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'.
        public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
        {
            bool ret                 = false;
            bool haveShape           = false;
            bool nativeShapePossible = true;
            PrimitiveBaseShape pbs   = prim.BaseShape;

            // If the prim attributes are simple, this could be a simple Bullet native shape
            if (!haveShape &&
                pbs != null &&
                nativeShapePossible &&
                ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) ||
                 (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 &&
                  pbs.ProfileHollow == 0 &&
                  pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 &&
                  pbs.PathBegin == 0 && pbs.PathEnd == 0 &&
                  pbs.PathTaperX == 0 && pbs.PathTaperY == 0 &&
                  pbs.PathScaleX == 100 && pbs.PathScaleY == 100 &&
                  pbs.PathShearX == 0 && pbs.PathShearY == 0)))
            {
                // 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 = BulletSimAPI.GetLocalScaling2(prim.PhysShape.ptr);
                }

                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);
                }

                // It doesn't look like Bullet scales spheres so make sure the scales are all equal
                if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) &&
                    pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
                {
                    haveShape = true;
                    if (forceRebuild ||
                        prim.Scale != scaleOfExistingShape ||
                        prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
                        )
                    {
                        ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
                                                        FixedShapeKey.KEY_SPHERE, shapeCallback);
                        if (DDetail)
                        {
                            DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
                                      prim.LocalID, forceRebuild, prim.PhysShape);
                        }
                    }
                }
                if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
                {
                    haveShape = true;
                    if (forceRebuild ||
                        prim.Scale != scaleOfExistingShape ||
                        prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
                        )
                    {
                        ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX,
                                                        FixedShapeKey.KEY_BOX, shapeCallback);
                        if (DDetail)
                        {
                            DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
                                      prim.LocalID, forceRebuild, prim.PhysShape);
                        }
                    }
                }
            }

            // If a simple shape is not happening, create a mesh and possibly a hull.
            if (!haveShape && pbs != null)
            {
                ret = CreateGeomMeshOrHull(prim, shapeCallback);
            }

            return(ret);
        }
        // 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(newShape, prim);

            ReferenceShape(newShape);

            prim.PhysShape = newShape;

            return true;        // 'true' means a new shape has been added to this prim
        }
        // Count down the reference count for a hull shape
        // Called at taint-time.
        private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
        {
            HullDesc hullDesc;
            if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
            {
            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);
            }
        }
        // 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;
        }
    // Release the usage of a shape.
    public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
    {
        if (!shape.HasPhysicalShape)
            return;

        PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
        {
            if (shape.HasPhysicalShape)
            {
                if (shape.isNativeShape)
                {
                    // Native shapes are not tracked and are released immediately
                    if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
                                    BSScene.DetailLogZero, shape.ptr.ToString(), inTaintTime);
                    if (shapeCallback != null) shapeCallback(shape);
                    BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
                }
                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;
                    }
                }
            }
        });
    }