Blender  V3.3
bmo_fill_edgeloop.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "MEM_guardedalloc.h"
10 
11 #include "BLI_listbase.h"
12 
13 #include "bmesh.h"
14 
15 #include "intern/bmesh_operators_private.h" /* own include */
16 
17 #define VERT_USED 1
18 #define EDGE_MARK 2
19 #define ELE_OUT 4
20 
22 {
23  /* first collect an array of unique from the edges */
24  const int tote = BMO_slot_buffer_len(op->slots_in, "edges");
25  const int totv = tote; /* these should be the same */
26  BMVert **verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
27 
28  BMVert *v;
29  BMEdge *e;
30  int i;
31  bool ok = true;
32 
33  BMOIter oiter;
34 
35  const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
36  const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
37 
38  /* 'VERT_USED' will be disabled, so enable and fill the array */
39  i = 0;
40  BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
41  BMIter viter;
43  BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
44  if (BMO_vert_flag_test(bm, v, VERT_USED) == false) {
45  if (i == tote) {
46  goto cleanup;
47  }
48 
50  verts[i++] = v;
51  }
52  }
53  }
54 
55  /* we have a different number of verts to edges */
56  if (i != tote) {
57  goto cleanup;
58  }
59 
60  /* loop over connected flagged edges and fill in faces, this is made slightly more
61  * complicated because there may be multiple disconnected loops to fill. */
62 
63  /* sanity check - that each vertex has 2 edge users */
64  for (i = 0; i < totv; i++) {
65  v = verts[i];
66  /* count how many flagged edges this vertex uses */
68  ok = false;
69  break;
70  }
71  }
72 
73  if (ok) {
74  /* NOTE: in the case of multiple loops, this over-allocates (which is fine). */
75  BMVert **f_verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
76  BMIter eiter;
77 
78  /* build array of connected verts and edges */
79  BMEdge *e_prev = NULL;
80  BMEdge *e_next = NULL;
81  int totv_used = 0;
82 
83  while (totv_used < totv) {
84  for (i = 0; i < totv; i++) {
85  v = verts[i];
87  break;
88  }
89  }
90 
91  /* this should never fail, as long as (totv_used < totv)
92  * we should have marked verts available */
94 
95  /* watch it, 'i' is used for final face length */
96  i = 0;
97  do {
98  /* we know that there are 2 edges per vertex so no need to check */
99  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
100  if (BMO_edge_flag_test(bm, e, EDGE_MARK)) {
101  if (e != e_prev) {
102  e_next = e;
103  break;
104  }
105  }
106  }
107 
108  /* fill in the array */
109  f_verts[i] = v;
111  totv_used++;
112 
113  /* step over the edges */
114  v = BM_edge_other_vert(e_next, v);
115  e_prev = e_next;
116  i++;
117  } while ((v != f_verts[0]));
118 
119  if (!BM_face_exists(f_verts, i)) {
120  BMFace *f;
121 
122  /* don't use calc_edges option because we already have the edges */
123  f = BM_face_create_ngon_verts(bm, f_verts, i, NULL, BM_CREATE_NOP, true, false);
125  f->mat_nr = mat_nr;
126  if (use_smooth) {
128  }
129  }
130  }
131  MEM_freeN(f_verts);
132 
134  }
135 
136 cleanup:
137  MEM_freeN(verts);
138 }
#define BLI_assert(a)
Definition: BLI_assert.h:46
Read Guarded memory(de)allocation.
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_SMOOTH
Definition: bmesh_class.h:477
BMFace * BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool calc_winding, const bool create_edges)
@ BM_CREATE_NOP
Definition: bmesh_core.h:12
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:14
int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value)
Elem Iter Tool Flag Count.
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_VERTS_OF_EDGE
@ BM_EDGES_OF_VERT
ATTR_WARN_UNUSED_RESULT BMesh * bm
#define BMO_vert_flag_disable(bm, e, oflag)
#define BMO_edge_flag_test(bm, e, oflag)
#define BMO_edge_flag_enable(bm, e, oflag)
#define BMO_vert_flag_enable(bm, e, oflag)
void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, short oflag)
#define BMO_face_flag_enable(bm, e, oflag)
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
#define BMO_vert_flag_test(bm, e, oflag)
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
BMFace * BM_face_exists(BMVert **varr, int len)
Definition: bmesh_query.c:1612
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define ELE_OUT
void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
#define VERT_USED
#define EDGE_MARK
static float verts[][3]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
short mat_nr
Definition: bmesh_class.h:281
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]