Blender  V2.93
bmo_fill_edgeloop.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include "MEM_guardedalloc.h"
24 
25 #include "BLI_listbase.h"
26 
27 #include "bmesh.h"
28 
29 #include "intern/bmesh_operators_private.h" /* own include */
30 
31 #define VERT_USED 1
32 #define EDGE_MARK 2
33 #define ELE_OUT 4
34 
36 {
37  /* first collect an array of unique from the edges */
38  const int tote = BMO_slot_buffer_count(op->slots_in, "edges");
39  const int totv = tote; /* these should be the same */
40  BMVert **verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
41 
42  BMVert *v;
43  BMEdge *e;
44  int i;
45  bool ok = true;
46 
47  BMOIter oiter;
48 
49  const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
50  const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
51 
52  /* 'VERT_USED' will be disabled, so enable and fill the array */
53  i = 0;
54  BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
55  BMIter viter;
57  BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
58  if (BMO_vert_flag_test(bm, v, VERT_USED) == false) {
59  if (i == tote) {
60  goto cleanup;
61  }
62 
64  verts[i++] = v;
65  }
66  }
67  }
68 
69  /* we have a different number of verts to edges */
70  if (i != tote) {
71  goto cleanup;
72  }
73 
74  /* loop over connected flagged edges and fill in faces, this is made slightly more
75  * complicated because there may be multiple disconnected loops to fill. */
76 
77  /* sanity check - that each vertex has 2 edge users */
78  for (i = 0; i < totv; i++) {
79  v = verts[i];
80  /* count how many flagged edges this vertex uses */
82  ok = false;
83  break;
84  }
85  }
86 
87  if (ok) {
88  /* note: in the case of multiple loops, this over-allocs (which is fine) */
89  BMVert **f_verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
90  BMIter eiter;
91 
92  /* build array of connected verts and edges */
93  BMEdge *e_prev = NULL;
94  BMEdge *e_next = NULL;
95  int totv_used = 0;
96 
97  while (totv_used < totv) {
98  for (i = 0; i < totv; i++) {
99  v = verts[i];
100  if (BMO_vert_flag_test(bm, v, VERT_USED)) {
101  break;
102  }
103  }
104 
105  /* this should never fail, as long as (totv_used < totv)
106  * we should have marked verts available */
108 
109  /* watch it, 'i' is used for final face length */
110  i = 0;
111  do {
112  /* we know that there are 2 edges per vertex so no need to check */
113  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
114  if (BMO_edge_flag_test(bm, e, EDGE_MARK)) {
115  if (e != e_prev) {
116  e_next = e;
117  break;
118  }
119  }
120  }
121 
122  /* fill in the array */
123  f_verts[i] = v;
125  totv_used++;
126 
127  /* step over the edges */
128  v = BM_edge_other_vert(e_next, v);
129  e_prev = e_next;
130  i++;
131  } while ((v != f_verts[0]));
132 
133  if (!BM_face_exists(f_verts, i)) {
134  BMFace *f;
135 
136  /* don't use calc_edges option because we already have the edges */
137  f = BM_face_create_ngon_verts(bm, f_verts, i, NULL, BM_CREATE_NOP, true, false);
139  f->mat_nr = mat_nr;
140  if (use_smooth) {
142  }
143  }
144  }
145  MEM_freeN(f_verts);
146 
148  }
149 
150 cleanup:
151  MEM_freeN(verts);
152 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
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:27
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
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)
#define BMO_face_flag_enable(bm, e, oflag)
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
#define BMO_vert_flag_test(bm, e, oflag)
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
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:2070
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:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
short mat_nr
Definition: bmesh_class.h:281
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]