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