HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request HullResult &result) // contains the resulst { HullError ret = QE_FAIL; PHullResult hr; unsigned int vcount = desc.mVcount; if ( vcount < 8 ) vcount = 8; btAlignedObjectArray<btVector3> vertexSource; vertexSource.resize(static_cast<int>(vcount)); btVector3 scale; unsigned int ovcount; bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates! if ( ok ) { // if ( 1 ) // scale vertices back to their original size. { for (unsigned int i=0; i<ovcount; i++) { btVector3& v = vertexSource[static_cast<int>(i)]; v[0]*=scale[0]; v[1]*=scale[1]; v[2]*=scale[2]; } } ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices); if ( ok ) { // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. btAlignedObjectArray<btVector3> vertexScratch; vertexScratch.resize(static_cast<int>(hr.mVcount)); BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount ); ret = QE_OK; if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle! { result.mPolygons = false; result.mNumOutputVertices = ovcount; result.m_OutputVertices.resize(static_cast<int>(ovcount)); result.mNumFaces = hr.mFaceCount; result.mNumIndices = hr.mIndexCount; result.m_Indices.resize(static_cast<int>(hr.mIndexCount)); memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); if ( desc.HasHullFlag(QF_REVERSE_ORDER) ) { const unsigned int *source = &hr.m_Indices[0]; unsigned int *dest = &result.m_Indices[0]; for (unsigned int i=0; i<hr.mFaceCount; i++) { dest[0] = source[2]; dest[1] = source[1]; dest[2] = source[0]; dest+=3; source+=3; } } else { memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int)*hr.mIndexCount); } } else { result.mPolygons = true; result.mNumOutputVertices = ovcount; result.m_OutputVertices.resize(static_cast<int>(ovcount)); result.mNumFaces = hr.mFaceCount; result.mNumIndices = hr.mIndexCount+hr.mFaceCount; result.m_Indices.resize(static_cast<int>(result.mNumIndices)); memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); // if ( 1 ) { const unsigned int *source = &hr.m_Indices[0]; unsigned int *dest = &result.m_Indices[0]; for (unsigned int i=0; i<hr.mFaceCount; i++) { dest[0] = 3; if ( desc.HasHullFlag(QF_REVERSE_ORDER) ) { dest[1] = source[2]; dest[2] = source[1]; dest[3] = source[0]; } else { dest[1] = source[0]; dest[2] = source[1]; dest[3] = source[2]; } dest+=4; source+=3; } } } ReleaseHull(hr); } } return ret; }
HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request HullResult &result) // contains the resulst { HullError ret = QE_FAIL; uint32_t vcount = desc.mVcount; if ( vcount < 8 ) vcount = 8; float *vsource = (float *) HACD_ALLOC( sizeof(float)*vcount*3 ); float scale[3]; float center[3]; uint32_t ovcount; bool ok = NormalizeAndCleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, vsource, desc.mNormalEpsilon, scale, center, desc.mMaxVertices*2, desc.mUseWuQuantizer ); // normalize point cloud, remove duplicates! if ( ok ) { double *bigVertices = (double *)HACD_ALLOC(sizeof(double)*3*ovcount); for (uint32_t i=0; i<3*ovcount; i++) { bigVertices[i] = vsource[i]; } dgConvexHull3d convexHull(bigVertices,sizeof(double)*3,(int32_t)ovcount,0.0001f,(int32_t)desc.mMaxVertices); if ( convexHull.GetCount() ) { float *hullVertices = (float *)HACD_ALLOC( sizeof(float)*3*convexHull.GetVertexCount() ); float *dest = hullVertices; for (int32_t i=0; i<convexHull.GetVertexCount(); i++) { const dgBigVector &v = convexHull.GetVertex(i); dest[0] = (float)v.m_x*scale[0]+center[0]; dest[1] = (float)v.m_y*scale[1]+center[1]; dest[2] = (float)v.m_z*scale[2]+center[2]; dest+=3; } uint32_t triangleCount = (uint32_t)convexHull.GetCount(); uint32_t *indices = (uint32_t*)HACD_ALLOC(triangleCount*sizeof(uint32_t)*3); uint32_t *destIndices = indices; dgList<dgConvexHull3DFace>::Iterator iter(convexHull); uint32_t outCount = 0; for (iter.Begin(); iter; iter++) { dgConvexHull3DFace &face = (*iter); destIndices[0] = (uint32_t)face.m_index[0]; destIndices[1] = (uint32_t)face.m_index[1]; destIndices[2] = (uint32_t)face.m_index[2]; destIndices+=3; outCount++; } HACD_ASSERT( outCount == triangleCount ); // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. float *vscratch = (float *) HACD_ALLOC( sizeof(float)*convexHull.GetVertexCount()*3 ); BringOutYourDead(hullVertices,(uint32_t)convexHull.GetVertexCount(),vscratch, ovcount, indices, triangleCount*3 ); ret = QE_OK; result.mNumOutputVertices = ovcount; result.mOutputVertices = (float *)HACD_ALLOC( sizeof(float)*ovcount*3); result.mNumTriangles = triangleCount; result.mIndices = (uint32_t *) HACD_ALLOC( sizeof(uint32_t)*triangleCount*3); memcpy(result.mOutputVertices, vscratch, sizeof(float)*3*ovcount ); memcpy(result.mIndices, indices, sizeof(uint32_t)*triangleCount*3); HACD_FREE(indices); HACD_FREE(vscratch); HACD_FREE(hullVertices); } HACD_FREE(bigVertices); } HACD_FREE(vsource); return ret; }