예제 #1
0
/**
 * \brief BMESH RADIAL REMOVE LOOP
 *
 * Removes a loop from an radial cycle. If edge e is non-NULL
 * it should contain the radial cycle, and it will also get
 * updated (in the case that the edge's link into the radial
 * cycle was the loop which is being removed from the cycle).
 */
void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e)
{
	/* if e is non-NULL, l must be in the radial cycle of e */
	if (UNLIKELY(e && e != l->e)) {
		BMESH_ASSERT(0);
	}

	if (l->radial_next != l) {
		if (e && l == e->l)
			e->l = l->radial_next;

		l->radial_next->radial_prev = l->radial_prev;
		l->radial_prev->radial_next = l->radial_next;
	}
	else {
		if (e) {
			if (l == e->l) {
				e->l = NULL;
			}
			else {
				BMESH_ASSERT(0);
			}
		}
	}

	/* l is no longer in a radial cycle; empty the links
	 * to the cycle and the link back to an edge */
	l->radial_next = l->radial_prev = NULL;
	l->e = NULL;
}
예제 #2
0
/*****radial cycle functions, e.g. loops surrounding edges**** */
bool bmesh_radial_validate(int radlen, BMLoop *l)
{
	BMLoop *l_iter = l;
	int i = 0;
	
	if (bmesh_radial_length(l) != radlen)
		return false;

	do {
		if (UNLIKELY(!l_iter)) {
			BMESH_ASSERT(0);
			return false;
		}
		
		if (l_iter->e != l->e)
			return false;
		if (l_iter->v != l->e->v1 && l_iter->v != l->e->v2)
			return false;
		
		if (UNLIKELY(i > BM_LOOP_RADIAL_MAX)) {
			BMESH_ASSERT(0);
			return false;
		}
		
		i++;
	} while ((l_iter = l_iter->radial_next) != l);

	return true;
}
예제 #3
0
int bmesh_radial_length(const BMLoop *l)
{
	const BMLoop *l_iter = l;
	int i = 0;

	if (!l)
		return 0;

	do {
		if (UNLIKELY(!l_iter)) {
			/* radial cycle is broken (not a circulat loop) */
			BMESH_ASSERT(0);
			return 0;
		}
		
		i++;
		if (UNLIKELY(i >= BM_LOOP_RADIAL_MAX)) {
			BMESH_ASSERT(0);
			return -1;
		}
	} while ((l_iter = l_iter->radial_next) != l);

	return i;
}
예제 #4
0
/**
 * \brief Init Walker
 *
 * Allocates and returns a new mesh walker of
 * a given type. The elements visited are filtered
 * by the bitmask 'searchmask'.
 */
void BMW_init(BMWalker *walker, BMesh *bm, int type,
              short mask_vert, short mask_edge, short mask_face,
              BMWFlag flag,
              int layer)
{
	memset(walker, 0, sizeof(BMWalker));

	walker->layer = layer;
	walker->flag = flag;
	walker->bm = bm;

	walker->mask_vert = mask_vert;
	walker->mask_edge = mask_edge;
	walker->mask_face = mask_face;

	walker->visithash = BLI_ghash_ptr_new("bmesh walkers 1");
	walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers sec 1");

	if (UNLIKELY(type >= BMW_MAXWALKERS || type < 0)) {
		fprintf(stderr,
		        "Invalid walker type in BMW_init; type: %d, "
		        "searchmask: (v:%d, e:%d, f:%d), flag: %d, layer: %d\n",
		        type, mask_vert, mask_edge, mask_face, flag, layer);
		BMESH_ASSERT(0);
	}
	
	if (type != BMW_CUSTOM) {
		walker->begin = bm_walker_types[type]->begin;
		walker->yield = bm_walker_types[type]->yield;
		walker->step = bm_walker_types[type]->step;
		walker->structsize = bm_walker_types[type]->structsize;
		walker->order = bm_walker_types[type]->order;
		walker->valid_mask = bm_walker_types[type]->valid_mask;

		/* safety checks */
		/* if this raises an error either the caller is wrong or
		 * 'bm_walker_types' needs updating */
		BLI_assert(mask_vert == 0 || (walker->valid_mask & BM_VERT));
		BLI_assert(mask_edge == 0 || (walker->valid_mask & BM_EDGE));
		BLI_assert(mask_face == 0 || (walker->valid_mask & BM_FACE));
	}
	
	walker->worklist = BLI_mempool_create(walker->structsize, 100, 100, BLI_MEMPOOL_SYSMALLOC);
	walker->states.first = walker->states.last = NULL;
}
예제 #5
0
void bmesh_radial_append(BMEdge *e, BMLoop *l)
{
	if (e->l == NULL) {
		e->l = l;
		l->radial_next = l->radial_prev = l;
	}
	else {
		l->radial_prev = e->l;
		l->radial_next = e->l->radial_next;

		e->l->radial_next->radial_prev = l;
		e->l->radial_next = l;

		e->l = l;
	}

	if (UNLIKELY(l->e && l->e != e)) {
		/* l is already in a radial cycle for a different edge */
		BMESH_ASSERT(0);
	}
	
	l->e = e;
}
예제 #6
0
/**
 * <pre>
 *            v8--v7-v6--v5
 *            |     s    |
 *            |v9 s     s|v4
 * first line |          |   last line
 *            |v10s s   s|v3
 *            v11-v0--v1-v2
 *
 *            it goes from bottom up
 * </pre>
 */
static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
                                 const SubDParams *params)
{
	BMFace *f_new;
	BMVert *v, *v1, *v2;
	BMEdge *e, *e_new, e_tmp;
	BMVert **lines;
	int numcuts = params->numcuts;
	int i, j, a, b, s = numcuts + 2 /* , totv = numcuts * 4 + 4 */;

	lines = MEM_callocN(sizeof(BMVert *) * (numcuts + 2) * (numcuts + 2), "q_4edge_split");
	/* build a 2-dimensional array of verts,
	 * containing every vert (and all new ones)
	 * in the face */

	/* first line */
	for (i = 0; i < numcuts + 2; i++) {
		lines[i] = verts[numcuts * 3 + 2 + (numcuts - i + 1)];
	}

	/* last line */
	for (i = 0; i < numcuts + 2; i++) {
		lines[(s - 1) * s + i] = verts[numcuts + i];
	}
	
	/* first and last members of middle lines */
	for (i = 0; i < numcuts; i++) {
		a = i;
		b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
		
		e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
		if (!e)
			continue;

		BMO_elem_flag_enable(bm, e, ELE_INNER);
		BMO_elem_flag_enable(bm, f_new, ELE_INNER);

		
		v1 = lines[(i + 1) * s] = verts[a];
		v2 = lines[(i + 1) * s + s - 1] = verts[b];
		
		e_tmp = *e;
		for (a = 0; a < numcuts; a++) {
			v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new,
			                     v1, v2);

			BMESH_ASSERT(v != NULL);

			BMO_elem_flag_enable(bm, e_new, ELE_INNER);
			lines[(i + 1) * s + a + 1] = v;
		}
	}

	for (i = 1; i < numcuts + 2; i++) {
		for (j = 1; j <= numcuts; j++) {
			a = i * s + j;
			b = (i - 1) * s + j;
			e = connect_smallest_face(bm, lines[a], lines[b], &f_new);
			if (!e)
				continue;

			BMO_elem_flag_enable(bm, e, ELE_INNER);
			BMO_elem_flag_enable(bm, f_new, ELE_INNER);
		}
	}

	MEM_freeN(lines);
}