private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { IntPtr hullPtr; HullDesc hullDesc; if (Hulls.TryGetValue(newHullKey, out hullDesc)) { // If the hull shape already is created, just use it. hullPtr = hullDesc.ptr; } else { // Build a new hull in the physical world // Pass false for physicalness as this creates some sort of bounding box which we don't need IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 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)); } // setup and do convex hull conversion m_hulls = new List <ConvexResult>(); DecompDesc dcomp = new DecompDesc(); dcomp.mIndices = convIndices; dcomp.mVertices = convVertices; ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); // create the hull into the _hulls variable convexBuilder.process(dcomp); // 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 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); newShape.shapeKey = newHullKey; return(newShape); // 'true' means a new shape has been added to this prim }