void _SnacRemesher_InterpolateElements( void* _context ) { Snac_Context* context = (Snac_Context*)_context; SnacRemesher_Context* contextExt = ExtensionManager_Get( context->extensionMgr, context, SnacRemesher_ContextHandle ); Mesh* mesh = context->mesh; SnacRemesher_Mesh* meshExt = ExtensionManager_Get( context->meshExtensionMgr, mesh, SnacRemesher_MeshHandle ); HexaMD* decomp = (HexaMD*)mesh->layout->decomp; Element_LocalIndex element_lI; Tetrahedra_Index tet_I; Element_DomainIndex neldI = decomp->elementDomain3DCounts[0]; Element_DomainIndex neldJ = decomp->elementDomain3DCounts[1]; Element_DomainIndex neldK = decomp->elementDomain3DCounts[2]; void createBarycenterGrids( void* _context ); void computeCoefficients( void* _context ); void computeBaryCoords( void* _context ); unsigned int have_xneg_shadow, have_xpos_shadow; unsigned int have_yneg_shadow, have_ypos_shadow; unsigned int have_zneg_shadow, have_zpos_shadow; int rankPartition[3]; /* Decompose rank into partitions in each axis */ rankPartition[2] = context->rank/(decomp->partition3DCounts[0]*decomp->partition3DCounts[1]); rankPartition[1] = (context->rank-rankPartition[2]*decomp->partition3DCounts[0]*decomp->partition3DCounts[1]) / decomp->partition3DCounts[0]; rankPartition[0] = context->rank-rankPartition[2]*decomp->partition3DCounts[0]*decomp->partition3DCounts[1] - rankPartition[1] * decomp->partition3DCounts[0]; have_xneg_shadow = (((decomp->partition3DCounts[0]>1)&&(rankPartition[0]>0))?1:0); have_xpos_shadow = (((decomp->partition3DCounts[0]>1)&&(rankPartition[0]<(decomp->partition3DCounts[0]-1)))?1:0); have_yneg_shadow = (((decomp->partition3DCounts[1]>1)&&(rankPartition[1]>0))?1:0); have_ypos_shadow = (((decomp->partition3DCounts[1]>1)&&(rankPartition[1]<(decomp->partition3DCounts[1]-1)))?1:0); have_zneg_shadow = (((decomp->partition3DCounts[2]>1)&&(rankPartition[2]>0))?1:0); have_zpos_shadow = (((decomp->partition3DCounts[2]>1)&&(rankPartition[2]<(decomp->partition3DCounts[2]-1)))?1:0); meshExt->local_range_min[0] = (have_xneg_shadow?decomp->shadowDepth:0); meshExt->local_range_max[0] = (have_xpos_shadow?(neldI-1-decomp->shadowDepth):(neldI-1)); meshExt->local_range_min[1] = (have_yneg_shadow?decomp->shadowDepth:0); meshExt->local_range_max[1] = (have_ypos_shadow?(neldJ-1-decomp->shadowDepth):(neldJ-1)); meshExt->local_range_min[2] = (have_zneg_shadow?decomp->shadowDepth:0); meshExt->local_range_max[2] = (have_zpos_shadow?(neldK-1-decomp->shadowDepth):(neldK-1)); /* Create old and new grids of barycenters */ createBarycenterGrids( context ); /* ** Free any owned arrays that may still exist from the last node interpolation. */ FreeArray( meshExt->externalElements ); meshExt->nExternalElements = 0; /* Compute coefficients for barycentric coordinates. */ computeCoefficients( context ); /* Compute barycentric coordinates of a new local grid w.r.t. the old domain grid. */ computeBaryCoords( context ); /* Finally, interpolate on each node in the new local barycenter mesh. */ for( element_lI = 0; element_lI < mesh->elementLocalCount; element_lI++ ) for(tet_I=0;tet_I<Tetrahedra_Count;tet_I++) SnacRemesher_InterpolateElement( context, contextExt, element_lI, tet_I, meshExt->newElements, meshExt->barcord[element_lI].elnum, meshExt->barcord[element_lI].tetnum ); /* Copy interpolated element variables stored in newElements to the origianl element array. */ for( element_lI = 0; element_lI < mesh->elementLocalCount; element_lI++ ) for(tet_I=0;tet_I<Tetrahedra_Count;tet_I++) SnacRemesher_CopyElement( context, contextExt, element_lI, tet_I, meshExt->newElements ); /* _SnacRemesher_CopyElement( context, element_lI, tet_I, */ /* meshExt->newElements ); */ }
// ----------------------------------------------------------------------- // compute the links between the surface mesh and tetrahedras void ObjMesh::buildTetraLinks(const NxVec3 *vertices, const NxU32 *indices, const NxU32 numTets) { if(!mTetraLinks.empty()) return; mTetraLinks.clear(); MeshHash* hash = new MeshHash(); // hash tetrahedra for faster search hash->setGridSpacing(mBounds.min.distance(mBounds.max) * 0.1f); for (NxU32 i = 0; i < numTets; i++) { const NxU32 *ix = &indices[4*i]; NxBounds3 tetraBounds; tetraBounds.setEmpty(); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); hash->add(tetraBounds, i); } for (NxU32 i = 0; i < mVertices.size(); i++) { // prepare datastructure for drained tetras mDrainedTriVertices.push_back(false); ObjMeshTetraLink tmpLink; NxVec3 triVert = mVertices[i]; std::vector<int> itemIndices; hash->queryUnique(triVert, itemIndices); NxReal minDist = 0.0f; NxVec3 b; int num, isize; num = isize = itemIndices.size(); if (num == 0) num = numTets; for (int i = 0; i < num; i++) { int j = i; if (isize > 0) j = itemIndices[i]; const NxU32 *ix = &indices[j*4]; const NxVec3 &p0 = vertices[*ix++]; const NxVec3 &p1 = vertices[*ix++]; const NxVec3 &p2 = vertices[*ix++]; const NxVec3 &p3 = vertices[*ix++]; NxVec3 b = computeBaryCoords(triVert, p0, p1, p2, p3); // is the vertex inside the tetrahedron? If yes we take it if (b.x >= 0.0f && b.y >= 0.0f && b.z >= 0.0f && (b.x + b.y + b.z) <= 1.0f) { tmpLink.barycentricCoords = b; tmpLink.tetraNr = j; break; } // otherwise, if we are not in any tetrahedron we take the closest one NxReal dist = 0.0f; if (b.x + b.y + b.z > 1.0f) dist = b.x + b.y + b.z - 1.0f; if (b.x < 0.0f) dist = (-b.x < dist) ? dist : -b.x; if (b.y < 0.0f) dist = (-b.y < dist) ? dist : -b.y; if (b.z < 0.0f) dist = (-b.z < dist) ? dist : -b.z; if (i == 0 || dist < minDist) { minDist = dist; tmpLink.barycentricCoords = b; tmpLink.tetraNr = j; } } mTetraLinks.push_back(tmpLink); } delete hash; }
// to attach to tetra mesh void TetraMeshHelper::buildTetraLinks(const NxSoftBodyMeshDesc& desc) { const NxVec3 *vertices = (const NxVec3 *) desc.vertices; const void *tetIndices = desc.tetrahedra; bool is32Bits = !(desc.flags & NX_SOFTBODY_MESH_16_BIT_INDICES); const NxU32 numTets = desc.numTetrahedra; mTetraLinks.clear(); MeshHash* hash = new MeshHash(); // hash tetrahedra for faster search hash->setGridSpacing(mBounds.min.distance(mBounds.max) * 0.1f); NxU8* startIndex = (NxU8*) tetIndices; if(is32Bits) { for (NxU32 i = 0; i < numTets; i++) { const NxU32 *ix = ((NxU32*) startIndex) + 4*i; NxBounds3 tetraBounds; tetraBounds.setEmpty(); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); hash->add(tetraBounds, i); } for (NxU32 i = 0; i < maxMesh.numVerts; i++) { MeshTetraLink tmpLink; NxVec3 triVert(maxMesh.verts[i].x, maxMesh.verts[i].y, maxMesh.verts[i].z); std::vector<int> itemIndices; hash->queryUnique(triVert, itemIndices); NxReal minDist = 0.0f; NxVec3 b; int num, isize; num = isize = itemIndices.size(); if (num == 0) num = numTets; for (int i = 0; i < num; i++) { int j = i; if (isize > 0) j = itemIndices[i]; const NxU32 *ix = ((NxU32*) startIndex) + 4*j; const NxVec3 &p0 = vertices[*ix++]; const NxVec3 &p1 = vertices[*ix++]; const NxVec3 &p2 = vertices[*ix++]; const NxVec3 &p3 = vertices[*ix++]; NxVec3 b = computeBaryCoords(triVert, p0, p1, p2, p3); // is the vertex inside the tetrahedron? If yes we take it if (b.x >= 0.0f && b.y >= 0.0f && b.z >= 0.0f && (b.x + b.y + b.z) <= 1.0f) { tmpLink.barycentricCoords = b; tmpLink.tetraNr = j; break; } // otherwise, if we are not in any tetrahedron we take the closest one NxReal dist = 0.0f; if (b.x + b.y + b.z > 1.0f) dist = b.x + b.y + b.z - 1.0f; if (b.x < 0.0f) dist = (-b.x < dist) ? dist : -b.x; if (b.y < 0.0f) dist = (-b.y < dist) ? dist : -b.y; if (b.z < 0.0f) dist = (-b.z < dist) ? dist : -b.z; if (i == 0 || dist < minDist) { minDist = dist; tmpLink.barycentricCoords = b; tmpLink.tetraNr = j; } } mTetraLinks.push_back(tmpLink); } } else { for (NxU32 i = 0; i < numTets; i++) { const NxU16 *ix = ((NxU16*) startIndex) + 4*i; NxBounds3 tetraBounds; tetraBounds.setEmpty(); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); tetraBounds.include(vertices[*ix++]); hash->add(tetraBounds, i); } for (NxU32 i = 0; i < maxMesh.numVerts; i++) { MeshTetraLink tmpLink; NxVec3 triVert(maxMesh.verts[i].x, maxMesh.verts[i].y, maxMesh.verts[i].z); std::vector<int> itemIndices; hash->queryUnique(triVert, itemIndices); NxReal minDist = 0.0f; NxVec3 b; int num, isize; num = isize = itemIndices.size(); if (num == 0) num = numTets; for (int i = 0; i < num; i++) { int j = i; if (isize > 0) j = itemIndices[i]; const NxU16 *ix = ((NxU16*) startIndex) + 4*j; const NxVec3 &p0 = vertices[*ix++]; const NxVec3 &p1 = vertices[*ix++]; const NxVec3 &p2 = vertices[*ix++]; const NxVec3 &p3 = vertices[*ix++]; NxVec3 b = computeBaryCoords(triVert, p0, p1, p2, p3); // is the vertex inside the tetrahedron? If yes we take it if (b.x >= 0.0f && b.y >= 0.0f && b.z >= 0.0f && (b.x + b.y + b.z) <= 1.0f) { tmpLink.barycentricCoords = b; tmpLink.tetraNr = j; break; } // otherwise, if we are not in any tetrahedron we take the closest one NxReal dist = 0.0f; if (b.x + b.y + b.z > 1.0f) dist = b.x + b.y + b.z - 1.0f; if (b.x < 0.0f) dist = (-b.x < dist) ? dist : -b.x; if (b.y < 0.0f) dist = (-b.y < dist) ? dist : -b.y; if (b.z < 0.0f) dist = (-b.z < dist) ? dist : -b.z; if (i == 0 || dist < minDist) { minDist = dist; tmpLink.barycentricCoords = b; tmpLink.tetraNr = j; } } mTetraLinks.push_back(tmpLink); } } delete hash; }