Ejemplo n.º 1
0
    public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
    {
        float lod;

        System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);

        physicsScene.DetailLog("{0},BSShapeMesh,getReference,newKey={1},size={2},lod={3}",
                               prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);

        BSShapeConvexHull retConvexHull = null;

        lock (ConvexHulls)
        {
            if (ConvexHulls.TryGetValue(newMeshKey, out retConvexHull))
            {
                // The mesh has already been created. Return a new reference to same.
                retConvexHull.IncrementReference();
            }
            else
            {
                retConvexHull = new BSShapeConvexHull(new BulletShape());
                BulletShape convexShape = null;

                // Get a handle to a mesh to build the hull from
                BSShape baseMesh = BSShapeMesh.GetReference(physicsScene, false /* forceRebuild */, prim);
                if (baseMesh.physShapeInfo.isNativeShape)
                {
                    // We get here if the mesh was not creatable. Could be waiting for an asset from the disk.
                    // In the short term, we return the native shape and a later ForceBodyShapeRebuild should
                    //     get back to this code with a buildable mesh.
                    // TODO: not sure the temp native shape is freed when the mesh is rebuilt. When does this get freed?
                    convexShape = baseMesh.physShapeInfo;
                }
                else
                {
                    convexShape          = physicsScene.PE.BuildConvexHullShapeFromMesh(physicsScene.World, baseMesh.physShapeInfo);
                    convexShape.shapeKey = newMeshKey;
                    ConvexHulls.Add(convexShape.shapeKey, retConvexHull);
                }

                // Done with the base mesh
                baseMesh.Dereference(physicsScene);

                retConvexHull.physShapeInfo = convexShape;
            }
        }
        return(retConvexHull);
    }
Ejemplo 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;
                    }
                }
            }
        }
Ejemplo n.º 3
0
    // Loop through all the known meshes and return the description based on the physical address.
    public static bool TryGetMeshByPtr(BulletShape pShape, out BSShapeMesh outMesh)
    {
        bool        ret       = false;
        BSShapeMesh foundDesc = null;

        lock (Meshes)
        {
            foreach (BSShapeMesh sm in Meshes.Values)
            {
                if (sm.physShapeInfo.ReferenceSame(pShape))
                {
                    foundDesc = sm;
                    ret       = true;
                    break;
                }
            }
        }
        outMesh = foundDesc;
        return(ret);
    }
Ejemplo n.º 4
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);
                        }
                    }
                }
            }
        }
    }
Ejemplo n.º 5
0
    public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
    {
        float lod;

        System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);

        BSShapeMesh retMesh = null;

        lock (Meshes)
        {
            if (Meshes.TryGetValue(newMeshKey, out retMesh))
            {
                // The mesh has already been created. Return a new reference to same.
                retMesh.IncrementReference();
            }
            else
            {
                retMesh = new BSShapeMesh(new BulletShape());
                // An instance of this mesh has not been created. Build and remember same.
                BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);

                // Check to see if mesh was created (might require an asset).
                newShape = VerifyMeshCreated(physicsScene, newShape, prim);
                if (!newShape.isNativeShape || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
                {
                    // If a mesh was what was created, remember the built shape for later sharing.
                    // Also note that if meshing failed we put it in the mesh list as there is nothing else to do about the mesh.
                    Meshes.Add(newMeshKey, retMesh);
                }

                retMesh.physShapeInfo = newShape;
            }
        }
        physicsScene.DetailLog("{0},BSShapeMesh,getReference,mesh={1},size={2},lod={3}", prim.LocalID, retMesh, prim.Size, lod);
        return(retMesh);
    }
Ejemplo n.º 6
0
        // return 'true' if the prim's shape was changed.
        private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback 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)
            {
                // Use a simple, single mesh convex hull shape if the object is simple enough
                BSShape potentialHull = null;

                PrimitiveBaseShape pbs = prim.BaseShape;
                // Use a simple, one section convex shape for prims that are probably convex (no cuts or twists)
                if (BSParam.ShouldUseSingleConvexHullForPrims &&
                    pbs != null &&
                    !pbs.SculptEntry &&
                    PrimHasNoCuts(pbs)
                    )
                {
                    potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
                }
                // Use the GImpact shape if it is a prim that has some concaveness
                if (potentialHull == null &&
                    BSParam.ShouldUseGImpactShapeForPrims &&
                    pbs != null &&
                    !pbs.SculptEntry
                    )
                {
                    potentialHull = BSShapeGImpact.GetReference(m_physicsScene, false /* forceRebuild */, prim);
                }
                // If not any of the simple cases, just make a hull
                if (potentialHull == null)
                {
                    potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
                }

                // If the current shape is not what is on the prim at the moment, time to change.
                if (!prim.PhysShape.HasPhysicalShape ||
                    potentialHull.ShapeType != prim.PhysShape.ShapeType ||
                    potentialHull.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
                {
                    DereferenceExistingShape(prim, shapeCallback);
                    prim.PhysShape = potentialHull;
                    ret            = true;
                }
                else
                {
                    // The current shape on the prim is the correct one. We don't need the potential reference.
                    potentialHull.Dereference(m_physicsScene);
                }
                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1}", prim.LocalID, prim.PhysShape);
                }
            }
            else
            {
                // Non-physical objects should be just meshes.
                BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
                // If the current shape is not what is on the prim at the moment, time to change.
                if (!prim.PhysShape.HasPhysicalShape ||
                    potentialMesh.ShapeType != prim.PhysShape.ShapeType ||
                    potentialMesh.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
                {
                    DereferenceExistingShape(prim, shapeCallback);
                    prim.PhysShape = potentialMesh;
                    ret            = true;
                }
                else
                {
                    // We don't need this reference to the mesh that is already being using.
                    potentialMesh.Dereference(m_physicsScene);
                }
                if (DDetail)
                {
                    DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
                }
            }
            return(ret);
        }
Ejemplo n.º 7
0
    private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
                                           PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
    {
        BulletShape newShape = new BulletShape();
        IntPtr      hullPtr  = IntPtr.Zero;

        if (BSParam.ShouldUseBulletHACD)
        {
            // Build the hull shape from an existing mesh shape.
            // The mesh should have already been created in Bullet.
            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
            BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);

            if (meshShape.physShapeInfo.HasPhysicalShape)
            {
                HACDParams parms;
                parms.maxVerticesPerHull          = BSParam.BHullMaxVerticesPerHull;
                parms.minClusters                 = BSParam.BHullMinClusters;
                parms.compacityWeight             = BSParam.BHullCompacityWeight;
                parms.volumeWeight                = BSParam.BHullVolumeWeight;
                parms.concavity                   = BSParam.BHullConcavity;
                parms.addExtraDistPoints          = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
                parms.addNeighboursDistPoints     = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
                parms.addFacesPoints              = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
                parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);

                physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
                newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
                physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);

                // Now done with the mesh shape.
                meshShape.Dereference(physicsScene);
            }
            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
        }
        if (!newShape.HasPhysicalShape)
        {
            // Build a new hull in the physical world using the C# HACD algorigthm.
            // Pass true for physicalness as this prevents the creation of bounding box which is not needed
            IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
            if (meshData != null)
            {
                if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
                {
                    // Release the fetched asset data once it has been used.
                    pbs.SculptData      = new byte[0];
                    prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
                }

                int[] indices = meshData.getIndexListAsInt();
                List <OMV.Vector3> vertices = meshData.getVertexList();

                //format conversion from IMesh format to DecompDesc format
                List <int>    convIndices  = new List <int>();
                List <float3> convVertices = new List <float3>();
                for (int ii = 0; ii < indices.GetLength(0); ii++)
                {
                    convIndices.Add(indices[ii]);
                }
                foreach (OMV.Vector3 vv in vertices)
                {
                    convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
                }

                uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
                if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
                {
                    // Simple primitive shapes we know are convex so they are better implemented with
                    //    fewer hulls.
                    // Check for simple shape (prim without cuts) and reduce split parameter if so.
                    if (BSShapeCollection.PrimHasNoCuts(pbs))
                    {
                        maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
                    }
                }

                // setup and do convex hull conversion
                m_hulls = new List <ConvexResult>();
                DecompDesc dcomp = new DecompDesc();
                dcomp.mIndices     = convIndices;
                dcomp.mVertices    = convVertices;
                dcomp.mDepth       = maxDepthSplit;
                dcomp.mCpercent    = BSParam.CSHullConcavityThresholdPercent;
                dcomp.mPpercent    = BSParam.CSHullVolumeConservationThresholdPercent;
                dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
                dcomp.mSkinWidth   = BSParam.CSHullMaxSkinWidth;
                ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
                // create the hull into the _hulls variable
                convexBuilder.process(dcomp);

                physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
                                       BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);

                // Convert the vertices and indices for passing to unmanaged.
                // The hull information is passed as a large floating point array.
                // The format is:
                //  convHulls[0] = number of hulls
                //  convHulls[1] = number of vertices in first hull
                //  convHulls[2] = hull centroid X coordinate
                //  convHulls[3] = hull centroid Y coordinate
                //  convHulls[4] = hull centroid Z coordinate
                //  convHulls[5] = first hull vertex X
                //  convHulls[6] = first hull vertex Y
                //  convHulls[7] = first hull vertex Z
                //  convHulls[8] = second hull vertex X
                //  ...
                //  convHulls[n] = number of vertices in second hull
                //  convHulls[n+1] = second hull centroid X coordinate
                //  ...
                //
                // TODO: is is very inefficient. Someday change the convex hull generator to return
                //   data structures that do not need to be converted in order to pass to Bullet.
                //   And maybe put the values directly into pinned memory rather than marshaling.
                int hullCount     = m_hulls.Count;
                int totalVertices = 1;          // include one for the count of the hulls
                foreach (ConvexResult cr in m_hulls)
                {
                    totalVertices += 4;                         // add four for the vertex count and centroid
                    totalVertices += cr.HullIndices.Count * 3;  // we pass just triangles
                }
                float[] convHulls = new float[totalVertices];

                convHulls[0] = (float)hullCount;
                int jj = 1;
                foreach (ConvexResult cr in m_hulls)
                {
                    // copy vertices for index access
                    float3[] verts = new float3[cr.HullVertices.Count];
                    int      kk    = 0;
                    foreach (float3 ff in cr.HullVertices)
                    {
                        verts[kk++] = ff;
                    }

                    // add to the array one hull's worth of data
                    convHulls[jj++] = cr.HullIndices.Count;
                    convHulls[jj++] = 0f;   // centroid x,y,z
                    convHulls[jj++] = 0f;
                    convHulls[jj++] = 0f;
                    foreach (int ind in cr.HullIndices)
                    {
                        convHulls[jj++] = verts[ind].x;
                        convHulls[jj++] = verts[ind].y;
                        convHulls[jj++] = verts[ind].z;
                    }
                }
                // create the hull data structure in Bullet
                newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
            }
            newShape.shapeKey = newHullKey;
        }
        return(newShape);
    }