//********************************************************************* //********************************************************************* //******** HullLib header //********************************************************************* //********************************************************************* //********************************************************************* //********************************************************************* //******** HullLib implementation //********************************************************************* //********************************************************************* public HullError CreateConvexHull(HullDesc desc, // describes the input request HullResult result) // contains the resulst { HullError ret = HullError.QE_FAIL; PHullResult hr = new PHullResult(); int vcount = desc.mVcount; if (vcount < 8) { vcount = 8; } IList<IndexedVector3> vertexSource = new List<IndexedVector3>((int)vcount); for (int i = 0; i < vcount; ++i) { vertexSource.Add(IndexedVector3.Zero); } IndexedVector3 scale = new IndexedVector3(1); int ovcount = 0; bool ok = CleanupVertices(desc.mVcount, desc.mVertices, desc.mVertexStride, ref ovcount, vertexSource, desc.mNormalEpsilon, ref scale); // normalize point cloud, remove duplicates! if (ok) { // if ( 1 ) // scale vertices back to their original size. { for (int i = 0; i < ovcount; i++) { IndexedVector3 v = vertexSource[i]; v.X *= scale.X; v.Y *= scale.Y; v.Z *= scale.Z; vertexSource[i] = v; } } ok = ComputeHull(ovcount, vertexSource, hr, desc.mMaxVertices); if (ok) { // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. IList<IndexedVector3> vertexScratch = new ObjectArray<IndexedVector3>((int)hr.mVcount); BringOutYourDead(hr.mVertices, hr.mVcount, vertexScratch, ref ovcount, hr.m_Indices, hr.mIndexCount); ret = HullError.QE_OK; if (desc.HasHullFlag(HullFlag.QF_TRIANGLES)) // if he wants the results as triangle! { result.mPolygons = false; result.mNumOutputVertices = ovcount; //result.m_OutputVertices.resize(ovcount); result.m_OutputVertices.Clear(); result.mNumFaces = hr.mFaceCount; result.mNumIndices = hr.mIndexCount; //result.m_Indices.resize(hr.mIndexCount); result.m_Indices.Clear(); for (int i = 0; i < ovcount; ++i) { result.m_OutputVertices.Add(vertexScratch[i]); } //memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(IndexedVector3) * ovcount); if (desc.HasHullFlag(HullFlag.QF_REVERSE_ORDER)) { IList<int> source = hr.m_Indices; IList<int> dest = result.m_Indices; for (int i = 0; i < hr.mFaceCount; i++) { int index = (i * 3); //dest[index + 0] = source[index + 2]; //dest[index + 1] = source[index + 1]; //dest[index + 2] = source[index + 0]; dest.Add(source[index + 2]); dest.Add(source[index + 1]); dest.Add(source[index + 0]); } } else { for (int i = 0; i < hr.mIndexCount; ++i) { //result.m_Indices[i] = hr.m_Indices[i]; result.m_Indices.Add(hr.m_Indices[i]); } //memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(int) * hr.mIndexCount); } } else { result.mPolygons = true; result.mNumOutputVertices = ovcount; //result.m_OutputVertices.resize(ovcount); result.m_OutputVertices.Clear(); result.mNumFaces = hr.mFaceCount; result.mNumIndices = hr.mIndexCount + hr.mFaceCount; //result.m_Indices.resize(result.mNumIndices); result.m_Indices.Clear(); for (int i = 0; i < ovcount; ++i) { result.m_OutputVertices.Add(vertexScratch[i]); } //memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(IndexedVector3) * ovcount); // if ( 1 ) { IList<int> source = hr.m_Indices; IList<int> dest = result.m_Indices; for (int i = 0; i < hr.mFaceCount; i++) { int destIndex = (i * 4); int srcIndex = (i * 3); dest[0] = 3; if (desc.HasHullFlag(HullFlag.QF_REVERSE_ORDER)) { dest.Add(source[srcIndex + 2]); dest.Add(source[srcIndex + 1]); dest.Add(source[srcIndex + 0]); } else { dest.Add(source[srcIndex + 0]); dest.Add(source[srcIndex + 1]); dest.Add(source[srcIndex + 2]); } } } } ReleaseHull(hr); } } return ret; }
public bool BuildHull(float margin) { int numSampleDirections = NUM_UNITSPHERE_POINTS; { int numPDA = m_shape.GetNumPreferredPenetrationDirections(); if (numPDA != 0) { for (int i=0;i<numPDA;i++) { IndexedVector3 norm; m_shape.GetPreferredPenetrationDirection(i, out norm); UnitSpherePoints[numSampleDirections] = norm; numSampleDirections++; } } } IndexedVector3[] supportPoints = new IndexedVector3[NUM_UNITSPHERE_POINTS+ConvexShape.MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; for (int i = 0; i < numSampleDirections; i++) { supportPoints[i] = m_shape.LocalGetSupportingVertex(ref UnitSpherePoints[i]); } HullDesc hd = new HullDesc(); hd.mFlags = HullFlag.QF_TRIANGLES; hd.mVcount = numSampleDirections; for (int i = 0; i < numSampleDirections; ++i) { hd.mVertices.Add(supportPoints[i]); } HullLibrary hl = new HullLibrary(); HullResult hr = new HullResult(); if (hl.CreateConvexHull (hd, hr) == HullError.QE_FAIL) { return false; } for (int i = 0; i < hr.mNumOutputVertices; i++) { m_vertices[i] = hr.m_OutputVertices[i]; } int numIndices = hr.mNumIndices; for (int i = 0; i < numIndices; i++) { m_indices[i] = hr.m_Indices[i]; } // free temporary hull result that we just copied hl.ReleaseResult (hr); #if DEBUG if (BulletGlobals.g_streamWriter != null && BulletGlobals.debugShapeHull) { BulletGlobals.g_streamWriter.WriteLine("buildHull"); BulletGlobals.g_streamWriter.WriteLine("Vertices"); for (int i = 0; i < m_vertices.Count; ++i) { MathUtil.PrintVector3(BulletGlobals.g_streamWriter,m_vertices[i]); } BulletGlobals.g_streamWriter.WriteLine("Indices"); for (int i = 0; i < m_indices.Count/3; ++i) { int indexer = i*3; BulletGlobals.g_streamWriter.WriteLine(String.Format("{0},{1},{2}", m_indices[indexer], m_indices[indexer + 1], m_indices[indexer + 2])); } } #endif return true; }