HaF32 canMerge(ChUll *a,ChUll *b) { if ( !a->overlap(*b) ) return 0; // if their AABB's (with a little slop) don't overlap, then return. // ok..we are going to combine both meshes into a single mesh // and then we are going to compute the concavity... HaF32 ret = 0; HaU32 combinedVertexCount = a->mVertexCount + b->mVertexCount; HaF32 *combinedVertices = (HaF32 *)HACD_ALLOC(combinedVertexCount*sizeof(HaF32)*3); HaF32 *dest = combinedVertices; memcpy(dest,a->mVertices, sizeof(HaF32)*3*a->mVertexCount); dest+=a->mVertexCount*3; memcpy(dest,b->mVertices,sizeof(HaF32)*3*b->mVertexCount); HullResult hresult; HullLibrary hl; HullDesc desc; desc.mVcount = combinedVertexCount; desc.mVertices = combinedVertices; desc.mVertexStride = sizeof(hacd::HaF32)*3; desc.mUseWuQuantizer = true; HullError hret = hl.CreateConvexHull(desc,hresult); HACD_ASSERT( hret == QE_OK ); if ( hret == QE_OK ) { ret = fm_computeMeshVolume( hresult.mOutputVertices, hresult.mNumTriangles, hresult.mIndices ); } HACD_FREE(combinedVertices); hl.ReleaseResult(hresult); return ret; }
float generateHull(void) { release(); if ( mPoints.size() >= 3 ) // must have at least 3 vertices to create a hull. { // now generate the convex hull. HullDesc desc((uint32_t)mPoints.size(),&mPoints[0].x, sizeof(float)*3); desc.mMaxVertices = 32; desc.mSkinWidth = 0.001f; HullLibrary h; HullResult result; HullError e = h.CreateConvexHull(desc,result); if ( e == QE_OK ) { mTriCount = result.mNumTriangles; mIndices = (uint32_t *)HACD_ALLOC(sizeof(uint32_t)*mTriCount*3); memcpy(mIndices,result.mIndices,sizeof(uint32_t)*mTriCount*3); mVertexCount = result.mNumOutputVertices; mVertices = (float *)HACD_ALLOC(sizeof(float)*mVertexCount*3); memcpy(mVertices,result.mOutputVertices,sizeof(float)*mVertexCount*3); mValidHull = true; mMeshVolume = fm_computeMeshVolume( mVertices, mTriCount, mIndices ); // compute the volume of this mesh. h.ReleaseResult(result); } } return mMeshVolume; }
ChUll(HaU32 vcount,const HaF32 *vertices,HaU32 tcount,const HaU32 *indices,HaU32 guid) { mGuid = guid; mVertexCount = vcount; mTriangleCount = tcount; mVertices = (HaF32 *)HACD_ALLOC(sizeof(HaF32)*3*vcount); memcpy(mVertices,vertices,sizeof(HaF32)*3*vcount); mIndices = (HaU32 *)HACD_ALLOC(sizeof(HaU32)*3*tcount); memcpy(mIndices,indices,sizeof(HaU32)*3*tcount); mVolume = fm_computeMeshVolume( mVertices, mTriangleCount, mIndices); mDiagonal = fm_computeBestFitAABB( mVertexCount, mVertices, sizeof(hacd::HaF32)*3, mMin, mMax ); hacd::HaF32 dx = mMax[0] - mMin[0]; hacd::HaF32 dy = mMax[1] - mMin[1]; hacd::HaF32 dz = mMax[2] - mMin[2]; dx*=0.1f; // inflate 1/10th on each edge dy*=0.1f; // inflate 1/10th on each edge dz*=0.1f; // inflate 1/10th on each edge mMin[0]-=dx; mMin[1]-=dy; mMin[2]-=dz; mMax[0]+=dx; mMax[1]+=dy; mMax[2]+=dz; }
NxF32 computeConcavityVolume(NxU32 vcount_hull, const NxF32 *vertices_hull, NxU32 tcount_hull, const NxU32 *indices_hull, NxU32 vcount_mesh, const NxF32 *vertices_mesh, NxU32 tcount_mesh, const NxU32 *indices_mesh) { NxF32 total_volume = 0; #if SHOW_DEBUG NVSHARE::gRenderDebug->pushRenderState(); NVSHARE::gRenderDebug->setCurrentDisplayTime(150.0f); #endif iRayCast *cast_hull = createRayCast(vertices_hull,tcount_hull,indices_hull); iRayCast *cast_mesh = createRayCast(vertices_mesh,tcount_mesh,indices_mesh); const NxU32 *indices = indices_mesh; #if 0 static NxU32 index = 0; NxU32 i = index++; indices = &indices[i*3]; #else for (NxU32 i=0; i<tcount_mesh; i++) #endif { NxU32 i1 = indices[0]; NxU32 i2 = indices[1]; NxU32 i3 = indices[2]; const NxF32 *p1 = &vertices_mesh[i1*3]; const NxF32 *p2 = &vertices_mesh[i2*3]; const NxF32 *p3 = &vertices_mesh[i3*3]; NxF32 normal[3]; NxF32 d = fm_computePlane(p3,p2,p1,normal); NxF32 vertices[6*3]; vertices[0] = p1[0]; vertices[1] = p1[1]; vertices[2] = p1[2]; vertices[3] = p2[0]; vertices[4] = p2[1]; vertices[5] = p2[2]; vertices[6] = p3[0]; vertices[7] = p3[1]; vertices[8] = p3[2]; NxF32 midPoint[3]; midPoint[0] = (p1[0]+p2[0]+p3[0])/3; midPoint[1] = (p1[1]+p2[1]+p3[1])/3; midPoint[2] = (p1[2]+p2[2]+p3[2])/3; fm_lerp(midPoint,p1,&vertices[0],0.9999f); fm_lerp(midPoint,p2,&vertices[3],0.9999f); fm_lerp(midPoint,p3,&vertices[6],0.9999f); NxF32 *_p1 = &vertices[3*3]; NxF32 *_p2 = &vertices[4*3]; NxF32 *_p3 = &vertices[5*3]; NxU32 hitCount = 0; if ( raycast(&vertices[0],normal, _p1,cast_hull,cast_mesh) ) hitCount++; if ( raycast(&vertices[3],normal, _p2,cast_hull,cast_mesh) ) hitCount++; if ( raycast(&vertices[6],normal, _p3,cast_hull,cast_mesh) ) hitCount++; // form triangle mesh! if ( hitCount == 3 ) { NxU32 tcount = 0; NxU32 tindices[8*3]; addTri(tindices,2,1,0,tcount); addTri(tindices,3,4,5,tcount); addTri(tindices,0,3,2,tcount); addTri(tindices,2,3,5,tcount); addTri(tindices,1,3,0,tcount); addTri(tindices,4,3,1,tcount); addTri(tindices,5,4,1,tcount); addTri(tindices,2,5,1,tcount); NxF32 volume = fm_computeMeshVolume(vertices,tcount,tindices); total_volume+=volume; #if SHOW_DEBUG NVSHARE::gRenderDebug->setCurrentColor(0x0000FF,0xFFFFFF); NVSHARE::gRenderDebug->addToCurrentState(NVSHARE::DebugRenderState::SolidWireShaded); for (NxU32 i=0; i<tcount; i++) { NxU32 i1 = tindices[i*3+0]; NxU32 i2 = tindices[i*3+1]; NxU32 i3 = tindices[i*3+2]; const NxF32 *p1 = &vertices[i1*3]; const NxF32 *p2 = &vertices[i2*3]; const NxF32 *p3 = &vertices[i3*3]; NVSHARE::gRenderDebug->DebugTri(p1,p2,p3); } #endif } indices+=3; } #if SHOW_DEBUG NVSHARE::gRenderDebug->popRenderState(); #endif releaseRayCast(cast_hull); releaseRayCast(cast_mesh); return total_volume; }