HullError ReleaseResult( HullResult result) // release memory allocated for this result, we are done with it. { if( result.m_OutputVertices.Count != 0 ) { result.mNumOutputVertices = 0; result.m_OutputVertices.Clear(); } if( result.m_Indices.Count > 0 ) { result.mNumIndices = 0; result.m_Indices.Clear(); } return HullError.QE_OK; }
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); }
//***************************** //***************************** //*[]* HullLib header //***************************** //***************************** //***************************** //***************************** //*[]* HullLib implementation //***************************** //***************************** 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; btList<btVector3> vertexSource = new btList<btVector3>(); vertexSource.Count = vertexSource.Capacity = ( (int)vcount ); btVector3 scale = btVector3.Zero; int ovcount; bool ok = CleanupVertices( desc.mVcount, desc.mVertices.InternalArray, desc.mVertexStride , out ovcount, vertexSource, desc.mNormalEpsilon, ref scale ); // normalize point cloud, remove duplicates! if( ok ) { // if ( 1 ) // scale vertices back to their original size. { for( uint i = 0; i < ovcount; i++ ) { btVector3 v = vertexSource[(int)( i )]; v[0] = scale[0]; v[1] = scale[1]; v[2] = scale[2]; } } ok = ComputeHull( ovcount, vertexSource.InternalArray, hr, desc.mMaxVertices ); if( ok ) { // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. btList<btVector3> vertexScratch = new btList<btVector3>( (int)hr.mVcount ); BringOutYourDead( hr.mVertices, hr.mVcount, vertexScratch, out 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.Count = result.m_OutputVertices.Capacity = ovcount; result.mNumFaces = hr.mFaceCount; result.mNumIndices = hr.mIndexCount; result.m_Indices.Count = result.m_Indices.Capacity = hr.mIndexCount; for( int j = 0; j < ovcount; j++ ) result.m_OutputVertices[j] = vertexScratch[j]; //memcpy( result.m_OutputVertices, vertexScratch, sizeof( btVector3 ) * ovcount ); uint[] source = hr.m_Indices.InternalArray; uint[] dest = result.m_Indices.InternalArray; if( desc.HasHullFlag( HullFlag.QF_REVERSE_ORDER ) ) { for( uint i = 0; i < hr.mFaceCount; i++ ) { //dest = source; dest[i*3+0] = source[i*3+2]; dest[i * 3 + 1] = source[i * 3 + 1]; dest[i * 3 + 2] = source[i * 3 + 0]; //dest += 3; //source += 3; } } else { for( int i = 0; i < 3*hr.mIndexCount; i++ ) dest[i] = source[i]; //memcpy( result.m_Indices, hr.m_Indices, sizeof( uint ) * hr.mIndexCount ); } } else { result.mPolygons = true; result.mNumOutputVertices = ovcount; result.m_OutputVertices.Count = result.m_OutputVertices.Capacity = ovcount; result.mNumFaces = hr.mFaceCount; result.mNumIndices = hr.mIndexCount + hr.mFaceCount; result.m_Indices.Count = result.m_Indices.Capacity = ( result.mNumIndices ); { btVector3[] dest = result.m_OutputVertices.InternalArray; btVector3[] source = vertexScratch.InternalArray; for( int i = 0; i < 3 * hr.mIndexCount; i++ ) dest[i] = source[i]; } //memcpy( result.m_OutputVertices, vertexScratch, sizeof( btVector3 ) * ovcount ); // if ( 1 ) { uint[] source = hr.m_Indices.InternalArray; uint[] dest = result.m_Indices.InternalArray; for( uint i = 0; i < hr.mFaceCount; i++ ) { dest[i*4 + 0] = 3; if( desc.HasHullFlag( HullFlag.QF_REVERSE_ORDER ) ) { dest[i * 4 + 1] = source[i * 3 + 2]; dest[i * 4 + 2] = source[i * 3 + 1]; dest[i * 4 + 3] = source[i * 3 + 0]; } else { dest[i * 4 + 1] = source[i * 3 + 0]; dest[i * 4 + 2] = source[i * 3 + 1]; dest[i * 4 + 3] = source[i*3+2]; } //dest += 4; //source += 3; } } } ReleaseHull( hr ); } } return ret; }