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 ); */

}
Example #2
0
// -----------------------------------------------------------------------
// 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;
}
Example #3
0
// 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;
}