Exemplo n.º 1
0
/**
 * Assuming we have 2 triangles sharing an edge (2 - 4),
 * check if the edge running from (1 - 3) gives better results.
 *
 * \return (negative number means the edge can be rotated, lager == better).
 */
float BM_verts_calc_rotate_beauty(
        const BMVert *v1, const BMVert *v2, const BMVert *v3, const BMVert *v4,
        const short flag, const short method)
{
	/* not a loop (only to be able to break out) */
	do {
		if (flag & VERT_RESTRICT_TAG) {
			const BMVert *v_a = v1, *v_b = v3;
			if (BM_elem_flag_test(v_a, BM_ELEM_TAG) ==  BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
				break;
			}
		}

		if (UNLIKELY(v1 == v3)) {
			// printf("This should never happen, but does sometimes!\n");
			break;
		}

		switch (method) {
			case 0:
				return bm_edge_calc_rotate_beauty__area(v1->co, v2->co, v3->co, v4->co);
			default:
				return bm_edge_calc_rotate_beauty__angle(v1->co, v2->co, v3->co, v4->co);
		}
	} while (false);

	return FLT_MAX;
}
Exemplo n.º 2
0
bool BM_elem_cb_check_hflag_ex(BMElem *ele, void *user_data)
{
	const uint hflag_pair = GET_INT_FROM_POINTER(user_data);
	const char hflag_p = (hflag_pair & 0xff);
	const char hflag_n = (hflag_pair >> 8);

	return ((BM_elem_flag_test(ele, hflag_p) != 0) &&
	        (BM_elem_flag_test(ele, hflag_n) == 0));
}
Exemplo n.º 3
0
static bool bm_edge_is_snap_target(BMEdge *e, void *UNUSED(user_data))
{
	if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) ||
	    BM_elem_flag_test(e->v1, BM_ELEM_SELECT) ||
	    BM_elem_flag_test(e->v2, BM_ELEM_SELECT))
	{
		return false;
	}

	return true;
}
Exemplo n.º 4
0
static void partialvis_update_bmesh_verts(BMesh *bm,
                                          GSet *verts,
                                          PartialVisAction action,
                                          PartialVisArea area,
                                          float planes[4][4],
                                          bool *any_changed,
                                          bool *any_visible)
{
	GSetIterator gs_iter;

	GSET_ITER (gs_iter, verts) {
		BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
		float *vmask = CustomData_bmesh_get(&bm->vdata,
		                                    v->head.data,
		                                    CD_PAINT_MASK);

		/* hide vertex if in the hide volume */
		if (is_effected(area, planes, v->co, *vmask)) {
			if (action == PARTIALVIS_HIDE)
				BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
			else
				BM_elem_flag_disable(v, BM_ELEM_HIDDEN);
			(*any_changed) = true;
		}

		if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
			(*any_visible) = true;
	}
Exemplo n.º 5
0
static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int index)
{
	drawEMTFMapped_userData *data = userData;
	BMEditMesh *em = data->em;
	BMFace *efa;

	if (UNLIKELY(index >= em->bm->totface))
		return DM_DRAW_OPTION_NORMAL;

	efa = BM_face_at_index(em->bm, index);

	if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
		return DM_DRAW_OPTION_SKIP;
	}
	else {
		MTFace mtf = {{{0}}};
		int matnr = efa->mat_nr;

		if (data->has_mtface) {
			MTexPoly *tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
			ME_MTEXFACE_CPY(&mtf, tpoly);
		}

		return draw_tface__set_draw_legacy(data->has_mtface ? &mtf : NULL,
		                                   data->has_mcol, matnr);
	}
}
Exemplo n.º 6
0
static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data))
{
	if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
		return false;
	}

	BMLoop *l_iter, *l_first;
	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
	do {
		if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
			return false;
		}
	} while ((l_iter = l_iter->next) != l_first);

	return true;
}
Exemplo n.º 7
0
static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3])
{
	foreachScreenEdge_userData *data = userData;
	BMEdge *eed = EDBM_edge_at_index(data->vc.em, index);

	if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
		float screen_co_a[2];
		float screen_co_b[2];
		eV3DProjTest clip_flag_nowin = data->clip_flag &= ~V3D_PROJ_TEST_CLIP_WIN;

		if (ED_view3d_project_float_object(data->vc.ar, v0co, screen_co_a, clip_flag_nowin) != V3D_PROJ_RET_OK) {
			return;
		}
		if (ED_view3d_project_float_object(data->vc.ar, v1co, screen_co_b, clip_flag_nowin) != V3D_PROJ_RET_OK) {
			return;
		}

		if (data->clip_flag & V3D_PROJ_TEST_CLIP_WIN) {
			if (!BLI_rctf_isect_segment(&data->win_rect, screen_co_a, screen_co_b)) {
				return;
			}
		}

		data->func(data->userData, eed, screen_co_a, screen_co_b, index);
	}
}
Exemplo n.º 8
0
static int tex_mat_set_face_editmesh_cb(void *userData, int index)
{
	/* editmode face hiding */
	TexMatCallback *data = (TexMatCallback *)userData;
	Mesh *me = (Mesh *)data->me;
	BMFace *efa = EDBM_face_at_index(me->edit_btmesh, index);

	return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
}
Exemplo n.º 9
0
static void vert_dissolve_add(
        struct ISectState *s,
        BMVert *v)
{
	BLI_assert(v->head.htype == BM_VERT);
	BLI_assert(!BM_elem_flag_test(v, BM_ELEM_TAG));
	BLI_assert(BLI_linklist_index(s->vert_dissolve, v) == -1);

	BM_elem_flag_enable(v, BM_ELEM_TAG);
	BLI_linklist_prepend_arena(&s->vert_dissolve, v, s->mem_arena);
}
Exemplo n.º 10
0
static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
{
	foreachScreenFace_userData *data = userData;
	BMFace *efa = EDBM_face_at_index(data->vc.em, index);

	if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
		float screen_co[2];
		if (ED_view3d_project_float_object(data->vc.ar, cent, screen_co, data->clip_flag) == V3D_PROJ_RET_OK) {
			data->func(data->userData, efa, screen_co, index);
		}
	}
}
Exemplo n.º 11
0
/**
 * Copies attributes, e.g. customdata, header flags, etc, from one element
 * to another of the same type.
 */
void BM_elem_attrs_copy_ex(
        BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
        const char hflag_mask, const uint64_t cd_mask)
{
	const BMHeader *ele_src = ele_src_v;
	BMHeader *ele_dst = ele_dst_v;

	BLI_assert(ele_src->htype == ele_dst->htype);
	BLI_assert(ele_src != ele_dst);

	/* Only support normal layer at the moment. */
	BLI_assert((cd_mask & ~CD_MASK_NORMAL) == 0);

	if ((hflag_mask & BM_ELEM_SELECT) == 0) {
		/* First we copy select */
		if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) {
			BM_elem_select_set(bm_dst, (BMElem *)ele_dst, true);
		}
	}

	/* Now we copy flags */
	if (hflag_mask == 0) {
		ele_dst->hflag = ele_src->hflag;
	}
	else if (hflag_mask == 0xff) {
		/* pass */
	}
	else {
		ele_dst->hflag = ((ele_dst->hflag & hflag_mask) | (ele_src->hflag & ~hflag_mask));
	}

	/* Copy specific attributes */
	switch (ele_dst->htype) {
		case BM_VERT:
			bm_vert_attrs_copy(bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask);
			break;
		case BM_EDGE:
			bm_edge_attrs_copy(bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask);
			break;
		case BM_LOOP:
			bm_loop_attrs_copy(bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask);
			break;
		case BM_FACE:
			bm_face_attrs_copy(bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask);
			break;
		default:
			BLI_assert(0);
			break;
	}
}
Exemplo n.º 12
0
/* Return TRUE if all vertices in the face are visible, FALSE otherwise */
int paint_is_bmesh_face_hidden(BMFace *f)
{
	BMLoop *l_iter;
	BMLoop *l_first;

	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
	do {
		if (BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN)) {
			return true;
		}
	} while ((l_iter = l_iter->next) != l_first);

	return false;
}
Exemplo n.º 13
0
static bool tex_mat_set_face_editmesh_cb(void *userData, int index)
{
	/* editmode face hiding */
	TexMatCallback *data = (TexMatCallback *)userData;
	Mesh *me = (Mesh *)data->me;
	BMEditMesh *em = me->edit_btmesh;
	BMFace *efa;

	if (UNLIKELY(index >= em->bm->totface))
		return DM_DRAW_OPTION_NORMAL;

	efa = BM_face_at_index(em->bm, index);

	return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
}
Exemplo n.º 14
0
static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
                                            const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
	foreachScreenVert_userData *data = userData;
	BMVert *eve = EDBM_vert_at_index(data->vc.em, index);

	if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
		float screen_co[2];

		if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != V3D_PROJ_RET_OK) {
			return;
		}

		data->func(data->userData, eve, screen_co, index);
	}
}
static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int origindex, int mat_nr)
{
	drawEMTFMapped_userData *data = userData;
	BMEditMesh *em = data->em;
	BMFace *efa;

	if (UNLIKELY(origindex >= em->bm->totface))
		return DM_DRAW_OPTION_NORMAL;

	efa = BM_face_at_index(em->bm, origindex);

	if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
		return DM_DRAW_OPTION_SKIP;
	}
	else {
		MTexPoly *mtexpoly = (data->cd_poly_tex_offset != -1) ?
		        BM_ELEM_CD_GET_VOID_P(efa, data->cd_poly_tex_offset) : NULL;
		int matnr = (mat_nr != -1) ? mat_nr : efa->mat_nr;

		return draw_tface__set_draw_legacy(mtexpoly, data->has_mcol, matnr);
	}
}
Exemplo n.º 16
0
static bool bm_face_is_not_hidden(BMFace *f, void *UNUSED(user_data))
{
	return (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == 0);
}
Exemplo n.º 17
0
BMBVHTree *BKE_bmbvh_new(BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free)
{
	/* could become argument */
	const float epsilon = FLT_EPSILON * 2.0f;

	struct BMLoop *(*looptris)[3] = em->looptris;
	BMBVHTree *bmtree = MEM_callocN(sizeof(*bmtree), "BMBVHTree");
	float cos[3][3];
	int i;
	int tottri;

	/* BKE_editmesh_tessface_calc() must be called already */
	BLI_assert(em->tottri != 0 || em->bm->totface == 0);

	if (cos_cage) {
		BM_mesh_elem_index_ensure(em->bm, BM_VERT);
	}

	bmtree->em = em;
	bmtree->bm = em->bm;
	bmtree->cos_cage = cos_cage;
	bmtree->cos_cage_free = cos_cage_free;
	bmtree->flag = flag;

	if (flag & (BMBVH_RESPECT_SELECT)) {
		tottri = 0;
		for (i = 0; i < em->tottri; i++) {
			if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) {
				tottri++;
			}
		}
	}
	else if (flag & (BMBVH_RESPECT_HIDDEN)) {
		tottri = 0;
		for (i = 0; i < em->tottri; i++) {
			if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
				tottri++;
			}
		}
	}
	else {
		tottri = em->tottri;
	}

	bmtree->tree = BLI_bvhtree_new(tottri, epsilon, 8, 8);

	for (i = 0; i < em->tottri; i++) {

		if (flag & BMBVH_RESPECT_SELECT) {
			/* note, the arrays wont align now! take care */
			if (!BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_SELECT)) {
				continue;
			}
		}
		else if (flag & BMBVH_RESPECT_HIDDEN) {
			/* note, the arrays wont align now! take care */
			if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
				continue;
			}
		}

		if (cos_cage) {
			copy_v3_v3(cos[0], cos_cage[BM_elem_index_get(looptris[i][0]->v)]);
			copy_v3_v3(cos[1], cos_cage[BM_elem_index_get(looptris[i][1]->v)]);
			copy_v3_v3(cos[2], cos_cage[BM_elem_index_get(looptris[i][2]->v)]);
		}
		else {
			copy_v3_v3(cos[0], looptris[i][0]->v->co);
			copy_v3_v3(cos[1], looptris[i][1]->v->co);
			copy_v3_v3(cos[2], looptris[i][2]->v->co);
		}

		BLI_bvhtree_insert(bmtree->tree, i, (float *)cos, 3);
	}
	
	BLI_bvhtree_balance(bmtree->tree);
	
	return bmtree;
}
Exemplo n.º 18
0
bool BM_elem_cb_check_hflag_disabled(BMElem *ele, void *user_data)
{
	const char hflag = GET_INT_FROM_POINTER(user_data);

	return (BM_elem_flag_test(ele, hflag) == 0);
}
Exemplo n.º 19
0
static BVHTree *bvhtree_from_mesh_looptri_create_tree(
        float epsilon, int tree_type, int axis,
        BMEditMesh *em, const MVert *vert, const MLoop *mloop, const MLoopTri *looptri, const int looptri_num,
        BLI_bitmap *mask, int looptri_num_active)
{
	BVHTree *tree = NULL;
	int i;

	if (looptri_num) {
		if (mask && looptri_num_active < 0) {
			looptri_num_active = 0;
			for (i = 0; i < looptri_num; i++) {
				if (BLI_BITMAP_TEST_BOOL(mask, i)) {
					looptri_num_active++;
				}
			}
		}
		else if (!mask) {
			looptri_num_active = looptri_num;
		}

		/* Create a bvh-tree of the given target */
		/* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
		tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis);
		if (tree) {
			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 < looptri_num; i++) {
					const BMLoop **ltri = looptris[i];
					BMFace *f = ltri[0]->f;
					bool insert = mask ? BLI_BITMAP_TEST_BOOL(mask, i) : true;

					/* Start with the assumption the triangle should be included for snapping. */
					if (f == f_prev) {
						insert = insert_prev;
					}
					else if (insert) {
						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;
							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 {
				if (vert && looptri) {
					for (i = 0; i < looptri_num; i++) {
						float co[4][3];
						if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
							continue;
						}

						copy_v3_v3(co[0], vert[mloop[looptri[i].tri[0]].v].co);
						copy_v3_v3(co[1], vert[mloop[looptri[i].tri[1]].v].co);
						copy_v3_v3(co[2], vert[mloop[looptri[i].tri[2]].v].co);

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

	return tree;
}
Exemplo n.º 20
0
static bool bm_face_is_select(BMFace *f, void *UNUSED(user_data))
{
	return (BM_elem_flag_test(f, BM_ELEM_SELECT) != 0);
}
Exemplo n.º 21
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;

}