Example #1
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 #2
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;
}