Example #1
0
/* Builds a bvh tree where nodes are the vertices of the given dm */
BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BVHTree *tree;
	MVert *vert;
	bool vert_allocated;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
	BLI_rw_mutex_unlock(&cache_rwlock);

	vert = DM_get_vert_array(dm, &vert_allocated);

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
		if (tree == NULL) {
			tree = bvhtree_from_mesh_verts_create_tree(epsilon, tree_type, axis, vert, dm->getNumVerts(dm), NULL, -1);
			if (tree) {
				/* Save on cache for later use */
				/* printf("BVHTree built and saved on cache\n"); */
				bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTS);
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
		/* printf("BVHTree is already build, using cached tree\n"); */
	}

	/* Setup BVHTreeFromMesh */
	bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated);

	return data->tree;
}
Example #2
0
/* Builds a bvh tree where nodes are the tesselated faces of the given dm */
BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BMEditMesh *em = data->em_evil;
	const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES;
	BVHTree *tree;
	MVert *vert = NULL;
	MFace *face = NULL;
	bool vert_allocated = false, face_allocated = false;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
	BLI_rw_mutex_unlock(&cache_rwlock);

	if (em == NULL) {
		vert = DM_get_vert_array(dm, &vert_allocated);
		face = DM_get_tessface_array(dm, &face_allocated);
	}

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
		if (tree == NULL) {
			int numFaces;

			/* BMESH specific check that we have tessfaces,
			 * we _could_ tessellate here but rather not - campbell
			 *
			 * this assert checks we have tessfaces,
			 * if not caller should use DM_ensure_tessface() */
			if (em) {
				numFaces = em->tottri;
			}
			else {
				numFaces = dm->getNumTessFaces(dm);
				BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
			}

			tree = bvhtree_from_mesh_faces_create_tree(epsilon, tree_type, axis, em, vert, face, numFaces, NULL, -1);
			if (tree) {
				/* Save on cache for later use */
				/* printf("BVHTree built and saved on cache\n"); */
				bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
		/* printf("BVHTree is already build, using cached tree\n"); */
	}

	/* Setup BVHTreeFromMesh */
	bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, em, vert, vert_allocated, face, face_allocated);

	return data->tree;
}
Example #3
0
// Builds a bvh tree.. where nodes are the faces of the given mesh.
BVHTree* bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
{
	BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_EDGES);

	//Not in cache
	if(tree == NULL)
	{
		int i;
		int numEdges= mesh->getNumEdges(mesh);
		MVert *vert	= mesh->getVertDataArray(mesh, CD_MVERT);
		MEdge *edge = mesh->getEdgeDataArray(mesh, CD_MEDGE);

		if(vert != NULL && edge != NULL)
		{
			/* Create a bvh-tree of the given target */
			tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
			if(tree != NULL)
			{
				for(i = 0; i < numEdges; i++)
				{
					float co[4][3];
					VECCOPY(co[0], vert[ edge[i].v1 ].co);
					VECCOPY(co[1], vert[ edge[i].v2 ].co);
			
					BLI_bvhtree_insert(tree, i, co[0], 2);
				}
				BLI_bvhtree_balance(tree);

				//Save on cache for later use
//				printf("BVHTree built and saved on cache\n");
				bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_EDGES);
			}
		}
	}
	else
	{
//		printf("BVHTree is already build, using cached tree\n");
	}


	//Setup BVHTreeFromMesh
	memset(data, 0, sizeof(*data));
	data->tree = tree;

	if(data->tree)
	{
		data->cached = TRUE;

		data->nearest_callback = mesh_edges_nearest_point;
		data->raycast_callback = NULL;

		data->mesh = mesh;
		data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
		data->edge = mesh->getEdgeDataArray(mesh, CD_MEDGE);

		data->sphere_radius = epsilon;
	}
	return data->tree;

}
Example #4
0
// Builds a bvh tree.. where nodes are the vertexs of the given mesh
BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
{
	BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_VERTICES);

	//Not in cache
	if(tree == NULL)
	{
		int i;
		int numVerts= mesh->getNumVerts(mesh);
		MVert *vert	= mesh->getVertDataArray(mesh, CD_MVERT);

		if(vert != NULL)
		{
			tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);

			if(tree != NULL)
			{
				for(i = 0; i < numVerts; i++)
					BLI_bvhtree_insert(tree, i, vert[i].co, 1);

				BLI_bvhtree_balance(tree);

				//Save on cache for later use
//				printf("BVHTree built and saved on cache\n");
				bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_VERTICES);
			}
		}
	}
	else
	{
//		printf("BVHTree is already build, using cached tree\n");
	}


	//Setup BVHTreeFromMesh
	memset(data, 0, sizeof(*data));
	data->tree = tree;

	if(data->tree)
	{
		data->cached = TRUE;

		//a NULL nearest callback works fine
		//remeber the min distance to point is the same as the min distance to BV of point
		data->nearest_callback = NULL;
		data->raycast_callback = NULL;

		data->mesh = mesh;
		data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
		data->face = mesh->getFaceDataArray(mesh, CD_MFACE);

		data->sphere_radius = epsilon;
	}

	return data->tree;
}
Example #5
0
void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type)
{
	BVHCacheItem *item = NULL;

	assert(tree != NULL);
	assert(bvhcache_find(cache, type) == NULL);

	item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem");
	assert(item != NULL);

	item->type = type;
	item->tree = tree;

	BLI_linklist_prepend(cache, item);
}
Example #6
0
/**
 * Builds a bvh tree where nodes are the looptri faces of the given dm
 *
 * \note for editmesh this is currently a duplicate of bvhtree_from_mesh_faces
 */
BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BMEditMesh *em = data->em_evil;
	const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_LOOPTRI;
	BVHTree *tree;
	MVert *mvert = NULL;
	MLoop *mloop = NULL;
	const MLoopTri *looptri = NULL;
	bool vert_allocated = false;
	bool loop_allocated = false;
	bool looptri_allocated = false;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
	BLI_rw_mutex_unlock(&cache_rwlock);

	if (em == NULL) {
		MPoly *mpoly;
		bool poly_allocated = false;

		mvert = DM_get_vert_array(dm, &vert_allocated);
		mpoly = DM_get_poly_array(dm, &poly_allocated);

		mloop = DM_get_loop_array(dm, &loop_allocated);
		looptri = DM_get_looptri_array(
		        dm,
		        mvert,
		        mpoly, dm->getNumPolys(dm),
		        mloop, dm->getNumLoops(dm),
		        &looptri_allocated);

		if (poly_allocated) {
			MEM_freeN(mpoly);
		}

	}

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
		if (tree == NULL) {
			int looptri_num;

			/* BMESH specific check that we have tessfaces,
			 * we _could_ tessellate here but rather not - campbell
			 *
			 * this assert checks we have tessfaces,
			 * if not caller should use DM_ensure_tessface() */
			if (em) {
				looptri_num = em->tottri;
			}
			else {
				looptri_num = dm->getNumLoopTri(dm);
				BLI_assert(!(looptri_num == 0 && dm->getNumPolys(dm) != 0));
			}

			tree = bvhtree_from_mesh_looptri_create_tree(
			        epsilon, tree_type, axis, em,
			        mvert, mloop, looptri, looptri_num, NULL, -1);
			if (tree) {
				/* Save on cache for later use */
				/* printf("BVHTree built and saved on cache\n"); */
				bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
		/* printf("BVHTree is already build, using cached tree\n"); */
	}

	/* Setup BVHTreeFromMesh */
	bvhtree_from_mesh_looptri_setup_data(
	        data, tree, true, epsilon, em,
	        mvert, vert_allocated,
	        mloop, loop_allocated,
	        looptri, looptri_allocated);

	return data->tree;
}
Example #7
0
/* Builds a bvh tree where nodes are the edges of the given dm */
BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BVHTree *tree;
	MVert *vert;
	MEdge *edge;
	bool vert_allocated, edge_allocated;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES);
	BLI_rw_mutex_unlock(&cache_rwlock);

	vert = DM_get_vert_array(dm, &vert_allocated);
	edge = DM_get_edge_array(dm, &edge_allocated);

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES);
		if (tree == NULL) {
			int i;
			int numEdges = dm->getNumEdges(dm);

			if (vert != NULL && edge != NULL) {
				/* Create a bvh-tree of the given target */
				tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
				if (tree != NULL) {
					for (i = 0; i < numEdges; i++) {
						float co[4][3];
						copy_v3_v3(co[0], vert[edge[i].v1].co);
						copy_v3_v3(co[1], vert[edge[i].v2].co);

						BLI_bvhtree_insert(tree, i, co[0], 2);
					}
					BLI_bvhtree_balance(tree);

					/* Save on cache for later use */
					/* printf("BVHTree built and saved on cache\n"); */
					bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
				}
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
		/* printf("BVHTree is already build, using cached tree\n"); */
	}


	/* Setup BVHTreeFromMesh */
	memset(data, 0, sizeof(*data));
	data->tree = tree;

	if (data->tree) {
		data->cached = true;

		data->nearest_callback = mesh_edges_nearest_point;
		data->raycast_callback = mesh_edges_spherecast;

		data->vert = vert;
		data->vert_allocated = vert_allocated;
		data->edge = edge;
		data->edge_allocated = edge_allocated;

		data->sphere_radius = epsilon;
	}
	else {
		if (vert_allocated) {
			MEM_freeN(vert);
		}
		if (edge_allocated) {
			MEM_freeN(edge);
		}
	}
	return data->tree;
}
Example #8
0
/* Builds a bvh tree.. where nodes are the faces of the given dm. */
BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BVHTree *tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_FACES);
	BMEditMesh *em = data->em_evil;

	/* Not in cache */
	if (tree == NULL) {
		int i;
		int numFaces;

		/* BMESH specific check that we have tessfaces,
		 * we _could_ tessellate here but rather not - campbell
		 *
		 * this assert checks we have tessfaces,
		 * if not caller should use DM_ensure_tessface() */
		if (em) {
			numFaces = em->tottri;
		}
		else {
			numFaces = dm->getNumTessFaces(dm);
			BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
		}

		if (numFaces != 0) {
			/* Create a bvh-tree of the given target */
			// printf("%s: building BVH, total=%d\n", __func__, numFaces);
			tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
			if (tree != NULL) {
				if (em) {
					const struct BMLoop *(*looptris)[3] = (void *)em->looptris;

					/* avoid double-up on face searches for quads-ngons */
					bool insert_prev = false;
					BMFace *f_prev = NULL;

					/* data->em_evil is only set for snapping, and only for the mesh of the object
					 * which is currently open in edit mode. When set, the bvhtree should not contain
					 * faces that will interfere with snapping (e.g. faces that are hidden/selected
					 * or faces that have selected verts).*/

					/* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
					 * and/or selected. Even if the faces themselves are not selected for the snapped
					 * transform, having a vertex selected means the face (and thus it's tessellated
					 * triangles) will be moving and will not be a good snap targets.*/
					for (i = 0; i < em->tottri; i++) {
						const BMLoop **ltri = looptris[i];
						BMFace *f = ltri[0]->f;
						bool insert;

						/* Start with the assumption the triangle should be included for snapping. */
						if (f == f_prev) {
							insert = insert_prev;
						}
						else {
							if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
								/* Don't insert triangles tessellated from faces that are hidden
								 * or selected*/
								insert = false;
							}
							else {
								BMLoop *l_iter, *l_first;
								insert = true;
								l_iter = l_first = BM_FACE_FIRST_LOOP(f);
								do {
									if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
										/* Don't insert triangles tessellated from faces that have
										 * any selected verts.*/
										insert = false;
										break;
									}
								} while ((l_iter = l_iter->next) != l_first);
							}

							/* skip if face doesn't change */
							f_prev = f;
							insert_prev = insert;
						}

						if (insert) {
							/* No reason found to block hit-testing the triangle for snap,
							 * so insert it now.*/
							float co[3][3];
							copy_v3_v3(co[0], ltri[0]->v->co);
							copy_v3_v3(co[1], ltri[1]->v->co);
							copy_v3_v3(co[2], ltri[2]->v->co);
					
							BLI_bvhtree_insert(tree, i, co[0], 3);
						}
					}
				}
				else {
					MVert *vert = dm->getVertDataArray(dm, CD_MVERT);
					MFace *face = dm->getTessFaceDataArray(dm, CD_MFACE);

					if (vert != NULL && face != NULL) {
						for (i = 0; i < numFaces; i++) {
							float co[4][3];
							copy_v3_v3(co[0], vert[face[i].v1].co);
							copy_v3_v3(co[1], vert[face[i].v2].co);
							copy_v3_v3(co[2], vert[face[i].v3].co);
							if (face[i].v4)
								copy_v3_v3(co[3], vert[face[i].v4].co);
					
							BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
						}
					}
				}
				BLI_bvhtree_balance(tree);

				/* Save on cache for later use */
//				printf("BVHTree built and saved on cache\n");
				bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_FACES);
			}
		}
	}
	else {
//		printf("BVHTree is already build, using cached tree\n");
	}


	/* Setup BVHTreeFromMesh */
	memset(data, 0, sizeof(*data));
	data->tree = tree;
	data->em_evil = em;

	if (data->tree) {
		data->cached = true;

		if (em) {
			data->nearest_callback = editmesh_faces_nearest_point;
			data->raycast_callback = editmesh_faces_spherecast;
		}
		else {
			data->nearest_callback = mesh_faces_nearest_point;
			data->raycast_callback = mesh_faces_spherecast;

			data->vert = dm->getVertDataArray(dm, CD_MVERT);
			data->face = dm->getTessFaceDataArray(dm, CD_MFACE);
		}

		data->sphere_radius = epsilon;
	}
	return data->tree;

}
Example #9
0
/* Builds a bvh tree.. where nodes are the vertexs of the given mesh */
BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
	BVHTree *tree;
	MVert *vert;
	bool vert_allocated;

	BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
	tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES);
	BLI_rw_mutex_unlock(&cache_rwlock);

	vert = DM_get_vert_array(dm, &vert_allocated);

	/* Not in cache */
	if (tree == NULL) {
		BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
		tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES);
		if (tree == NULL) {
			int i;
			int numVerts = dm->getNumVerts(dm);

			if (vert != NULL) {
				tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);

				if (tree != NULL) {
					for (i = 0; i < numVerts; i++) {
						BLI_bvhtree_insert(tree, i, vert[i].co, 1);
					}

					BLI_bvhtree_balance(tree);

					/* Save on cache for later use */
//					printf("BVHTree built and saved on cache\n");
					bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTICES);
				}
			}
		}
		BLI_rw_mutex_unlock(&cache_rwlock);
	}
	else {
//		printf("BVHTree is already build, using cached tree\n");
	}


	/* Setup BVHTreeFromMesh */
	memset(data, 0, sizeof(*data));
	data->tree = tree;

	if (data->tree) {
		data->cached = true;

		/* a NULL nearest callback works fine
		 * remember the min distance to point is the same as the min distance to BV of point */
		data->nearest_callback = NULL;
		data->raycast_callback = NULL;

		data->vert = vert;
		data->vert_allocated = vert_allocated;
		data->face = DM_get_tessface_array(dm, &data->face_allocated);

		data->sphere_radius = epsilon;
	}
	else {
		if (vert_allocated) {
			MEM_freeN(vert);
		}
	}

	return data->tree;
}
Example #10
0
// Builds a bvh tree.. where nodes are the faces of the given mesh.
BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
{
	BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_FACES);

	//Not in cache
	if(tree == NULL)
	{
		int i;
		int numFaces= mesh->getNumFaces(mesh);
		MVert *vert	= mesh->getVertDataArray(mesh, CD_MVERT);
		MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);

		if(vert != NULL && face != NULL)
		{
			/* Create a bvh-tree of the given target */
			tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
			if(tree != NULL)
			{
				/* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */
				EditMesh *em= data->em_evil;
				if(em) {
					EditFace *efa= em->faces.first;
					for(i = 0; i < numFaces; i++, efa= efa->next) {
						if(!(efa->f & 1) && efa->h==0 && !((efa->v1->f&1)+(efa->v2->f&1)+(efa->v3->f&1)+(efa->v4?efa->v4->f&1:0))) {
							float co[4][3];
							VECCOPY(co[0], vert[ face[i].v1 ].co);
							VECCOPY(co[1], vert[ face[i].v2 ].co);
							VECCOPY(co[2], vert[ face[i].v3 ].co);
							if(face[i].v4)
								VECCOPY(co[3], vert[ face[i].v4 ].co);
					
							BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
						}
					}
				}
				else {
					for(i = 0; i < numFaces; i++) {
						float co[4][3];
						VECCOPY(co[0], vert[ face[i].v1 ].co);
						VECCOPY(co[1], vert[ face[i].v2 ].co);
						VECCOPY(co[2], vert[ face[i].v3 ].co);
						if(face[i].v4)
							VECCOPY(co[3], vert[ face[i].v4 ].co);
				
						BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
					}
				}
				BLI_bvhtree_balance(tree);

				//Save on cache for later use
//				printf("BVHTree built and saved on cache\n");
				bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_FACES);
			}
		}
	}
	else
	{
//		printf("BVHTree is already build, using cached tree\n");
	}


	//Setup BVHTreeFromMesh
	memset(data, 0, sizeof(*data));
	data->tree = tree;

	if(data->tree)
	{
		data->cached = TRUE;

		data->nearest_callback = mesh_faces_nearest_point;
		data->raycast_callback = mesh_faces_spherecast;

		data->mesh = mesh;
		data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
		data->face = mesh->getFaceDataArray(mesh, CD_MFACE);

		data->sphere_radius = epsilon;
	}
	return data->tree;

}