Blender  V3.3
bmo_dupe.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_alloca.h"
12 #include "BLI_math.h"
13 
14 #include "bmesh.h"
15 
16 #include "intern/bmesh_operators_private.h" /* own include */
17 
18 /* local flag define */
19 #define DUPE_INPUT 1 /* input from operator */
20 #define DUPE_NEW 2
21 #define DUPE_DONE 4
22 // #define DUPE_MAPPED 8 // UNUSED
23 
30  BMOpSlot *slot_vertmap_out,
31  BMesh *bm_dst,
32  BMesh *bm_src,
33  BMVert *v_src,
34  GHash *vhash)
35 {
36  BMVert *v_dst;
37 
38  /* Create a new vertex */
39  v_dst = BM_vert_create(bm_dst, v_src->co, NULL, BM_CREATE_SKIP_CD);
40  BMO_slot_map_elem_insert(op, slot_vertmap_out, v_src, v_dst);
41  BMO_slot_map_elem_insert(op, slot_vertmap_out, v_dst, v_src);
42 
43  /* Insert new vertex into the vert hash */
44  BLI_ghash_insert(vhash, v_src, v_dst);
45 
46  /* Copy attributes */
47  BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst);
48 
49  /* Mark the vert for output */
50  BMO_vert_flag_enable(bm_dst, v_dst, DUPE_NEW);
51 
52  return v_dst;
53 }
54 
61  BMOpSlot *slot_edgemap_out,
62  BMOpSlot *slot_boundarymap_out,
63  BMesh *bm_dst,
64  BMesh *bm_src,
65  BMEdge *e_src,
66  GHash *vhash,
67  GHash *ehash,
68  const bool use_edge_flip_from_face)
69 {
70  BMEdge *e_dst;
71  BMVert *e_dst_v1, *e_dst_v2;
72  uint rlen;
73 
74  /* see if any of the neighboring faces are
75  * not being duplicated. in that case,
76  * add it to the new/old map. */
77  /* lookup edge */
78  rlen = 0;
79  if (e_src->l) {
80  BMLoop *l_iter_src, *l_first_src;
81  l_iter_src = l_first_src = e_src->l;
82  do {
83  if (BMO_face_flag_test(bm_src, l_iter_src->f, DUPE_INPUT)) {
84  rlen++;
85  }
86  } while ((l_iter_src = l_iter_src->radial_next) != l_first_src);
87  }
88 
89  /* Lookup v1 and v2 */
90  e_dst_v1 = BLI_ghash_lookup(vhash, e_src->v1);
91  e_dst_v2 = BLI_ghash_lookup(vhash, e_src->v2);
92 
93  /* Create a new edge */
94  e_dst = BM_edge_create(bm_dst, e_dst_v1, e_dst_v2, NULL, BM_CREATE_SKIP_CD);
95  BMO_slot_map_elem_insert(op, slot_edgemap_out, e_src, e_dst);
96  BMO_slot_map_elem_insert(op, slot_edgemap_out, e_dst, e_src);
97 
98  /* Add to new/old edge map if necessary. */
99  if (rlen < 2) {
100  /* not sure what non-manifold cases of greater than three
101  * radial should do. */
102  BMO_slot_map_elem_insert(op, slot_boundarymap_out, e_src, e_dst);
103  }
104 
105  /* Insert new edge into the edge hash */
106  BLI_ghash_insert(ehash, e_src, e_dst);
107 
108  /* Copy attributes */
109  BM_elem_attrs_copy(bm_src, bm_dst, e_src, e_dst);
110 
111  /* Mark the edge for output */
112  BMO_edge_flag_enable(bm_dst, e_dst, DUPE_NEW);
113 
114  if (use_edge_flip_from_face) {
115  /* Take winding from previous face (if we had one),
116  * otherwise extruding a duplicated edges gives bad normals, see: T62487. */
117  if (BM_edge_is_boundary(e_src) && (e_src->l->v == e_src->v1)) {
118  BM_edge_verts_swap(e_dst);
119  }
120  }
121 
122  return e_dst;
123 }
124 
131  BMOpSlot *slot_facemap_out,
132  BMesh *bm_dst,
133  BMesh *bm_src,
134  BMFace *f_src,
135  GHash *vhash,
136  GHash *ehash)
137 {
138  BMFace *f_dst;
139  BMVert **vtar = BLI_array_alloca(vtar, f_src->len);
140  BMEdge **edar = BLI_array_alloca(edar, f_src->len);
141  BMLoop *l_iter_src, *l_iter_dst, *l_first_src;
142  int i;
143 
144  l_first_src = BM_FACE_FIRST_LOOP(f_src);
145 
146  /* lookup edge */
147  l_iter_src = l_first_src;
148  i = 0;
149  do {
150  vtar[i] = BLI_ghash_lookup(vhash, l_iter_src->v);
151  edar[i] = BLI_ghash_lookup(ehash, l_iter_src->e);
152  i++;
153  } while ((l_iter_src = l_iter_src->next) != l_first_src);
154 
155  /* create new face */
156  f_dst = BM_face_create(bm_dst, vtar, edar, f_src->len, NULL, BM_CREATE_SKIP_CD);
157  BMO_slot_map_elem_insert(op, slot_facemap_out, f_src, f_dst);
158  BMO_slot_map_elem_insert(op, slot_facemap_out, f_dst, f_src);
159 
160  /* Copy attributes */
161  BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst);
162 
163  /* copy per-loop custom data */
164  l_iter_src = l_first_src;
165  l_iter_dst = BM_FACE_FIRST_LOOP(f_dst);
166  do {
167  BM_elem_attrs_copy(bm_src, bm_dst, l_iter_src, l_iter_dst);
168  } while ((void)(l_iter_dst = l_iter_dst->next), (l_iter_src = l_iter_src->next) != l_first_src);
169 
170  /* Mark the face for output */
171  BMO_face_flag_enable(bm_dst, f_dst, DUPE_NEW);
172 
173  return f_dst;
174 }
175 
181 static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
182 {
183  const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
184  const bool use_edge_flip_from_face = BMO_slot_bool_get(op->slots_in, "use_edge_flip_from_face");
185 
186  BMVert *v = NULL, *v2;
187  BMEdge *e = NULL;
188  BMFace *f = NULL;
189 
190  BMIter viter, eiter, fiter;
191  GHash *vhash, *ehash;
192 
193  BMOpSlot *slot_boundary_map_out = BMO_slot_get(op->slots_out, "boundary_map.out");
194  BMOpSlot *slot_isovert_map_out = BMO_slot_get(op->slots_out, "isovert_map.out");
195 
196  BMOpSlot *slot_vert_map_out = BMO_slot_get(op->slots_out, "vert_map.out");
197  BMOpSlot *slot_edge_map_out = BMO_slot_get(op->slots_out, "edge_map.out");
198  BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out");
199 
200  /* initialize pointer hashes */
201  vhash = BLI_ghash_ptr_new("bmesh dupeops v");
202  ehash = BLI_ghash_ptr_new("bmesh dupeops e");
203 
204  /* duplicate flagged vertices */
205  BM_ITER_MESH (v, &viter, bm_src, BM_VERTS_OF_MESH) {
206  if (BMO_vert_flag_test(bm_src, v, DUPE_INPUT) &&
207  BMO_vert_flag_test(bm_src, v, DUPE_DONE) == false) {
208  BMIter iter;
209  bool isolated = true;
210 
211  v2 = bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
212 
213  BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
214  if (BMO_face_flag_test(bm_src, f, DUPE_INPUT)) {
215  isolated = false;
216  break;
217  }
218  }
219 
220  if (isolated) {
221  BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
222  if (BMO_edge_flag_test(bm_src, e, DUPE_INPUT)) {
223  isolated = false;
224  break;
225  }
226  }
227  }
228 
229  if (isolated) {
230  BMO_slot_map_elem_insert(op, slot_isovert_map_out, v, v2);
231  }
232 
233  BMO_vert_flag_enable(bm_src, v, DUPE_DONE);
234  }
235  }
236 
237  /* now we dupe all the edges */
238  BM_ITER_MESH (e, &eiter, bm_src, BM_EDGES_OF_MESH) {
239  if (BMO_edge_flag_test(bm_src, e, DUPE_INPUT) &&
240  BMO_edge_flag_test(bm_src, e, DUPE_DONE) == false) {
241  /* make sure that verts are copied */
242  if (!BMO_vert_flag_test(bm_src, e->v1, DUPE_DONE)) {
243  bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v1, vhash);
244  BMO_vert_flag_enable(bm_src, e->v1, DUPE_DONE);
245  }
246  if (!BMO_vert_flag_test(bm_src, e->v2, DUPE_DONE)) {
247  bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v2, vhash);
248  BMO_vert_flag_enable(bm_src, e->v2, DUPE_DONE);
249  }
250  /* now copy the actual edge */
251  bmo_edge_copy(op,
252  slot_edge_map_out,
253  slot_boundary_map_out,
254  bm_dst,
255  bm_src,
256  e,
257  vhash,
258  ehash,
259  use_edge_flip_from_face);
260  BMO_edge_flag_enable(bm_src, e, DUPE_DONE);
261  }
262  }
263 
264  /* first we dupe all flagged faces and their elements from source */
265  BM_ITER_MESH (f, &fiter, bm_src, BM_FACES_OF_MESH) {
266  if (BMO_face_flag_test(bm_src, f, DUPE_INPUT)) {
267  /* vertex pass */
268  BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
269  if (!BMO_vert_flag_test(bm_src, v, DUPE_DONE)) {
270  bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
271  BMO_vert_flag_enable(bm_src, v, DUPE_DONE);
272  }
273  }
274 
275  /* edge pass */
276  BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) {
277  if (!BMO_edge_flag_test(bm_src, e, DUPE_DONE)) {
278  bmo_edge_copy(op,
279  slot_edge_map_out,
280  slot_boundary_map_out,
281  bm_dst,
282  bm_src,
283  e,
284  vhash,
285  ehash,
286  use_edge_flip_from_face);
287  BMO_edge_flag_enable(bm_src, e, DUPE_DONE);
288  }
289  }
290 
291  bmo_face_copy(op, slot_face_map_out, bm_dst, bm_src, f, vhash, ehash);
292  BMO_face_flag_enable(bm_src, f, DUPE_DONE);
293  }
294  }
295 
296  /* free pointer hashes */
297  BLI_ghash_free(vhash, NULL, NULL);
298  BLI_ghash_free(ehash, NULL, NULL);
299 
300  if (use_select_history) {
301  BLI_assert(bm_src == bm_dst);
303  bm_dst, slot_vert_map_out, slot_edge_map_out, slot_face_map_out, false);
304  }
305 }
306 
328 {
329  BMOperator *dupeop = op;
330  BMesh *bm_dst = BMO_slot_ptr_get(op->slots_in, "dest");
331 
332  if (!bm_dst) {
333  bm_dst = bm;
334  }
335 
336  /* flag input */
338 
339  /* use the internal copy function */
340  bmo_mesh_copy(dupeop, bm_dst, bm);
341 
342  /* Output */
343  /* First copy the input buffers to output buffers - original data */
344  BMO_slot_copy(dupeop, slots_in, "geom", dupeop, slots_out, "geom_orig.out");
345 
346  /* Now alloc the new output buffers */
348  bm, dupeop, dupeop->slots_out, "geom.out", BM_ALL_NOLOOP, DUPE_NEW);
349 }
350 
351 #if 0 /* UNUSED */
358 void BMO_dupe_from_flag(BMesh *bm, int htype, const char hflag)
359 {
360  BMOperator dupeop;
361 
362  BMO_op_init(bm, &dupeop, "duplicate");
363  BMO_slot_buffer_from_enabled_hflag(bm, &dupeop, "geom", htype, hflag);
364 
365  BMO_op_exec(bm, &dupeop);
366  BMO_op_finish(bm, &dupeop);
367 }
368 #endif
369 
391 {
392 #define SPLIT_INPUT 1
393 
394  BMOperator *splitop = op;
395  BMOperator dupeop;
396  const bool use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces");
397 
398  /* initialize our sub-operator */
399  BMO_op_init(bm, &dupeop, op->flag, "duplicate");
400 
401  BMO_slot_copy(splitop, slots_in, "geom", &dupeop, slots_in, "geom");
402  BMO_op_exec(bm, &dupeop);
403 
405 
406  if (use_only_faces) {
407  BMVert *v;
408  BMEdge *e;
409  BMFace *f;
410  BMIter iter, iter2;
411 
412  /* make sure to remove edges and verts we don't need */
413  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
414  bool found = false;
415  BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
416  if (!BMO_face_flag_test(bm, f, SPLIT_INPUT)) {
417  found = true;
418  break;
419  }
420  }
421  if (found == false) {
423  }
424  }
425 
426  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
427  bool found = false;
428  BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
430  found = true;
431  break;
432  }
433  }
434  if (found == false) {
436  }
437  }
438  }
439 
440  /* connect outputs of dupe to delete, excluding keep geometry */
442 
443  /* now we make our outputs by copying the dupe output */
444  BMO_slot_copy(&dupeop, slots_out, "geom.out", splitop, slots_out, "geom.out");
445 
446  /* cleanup */
447  BMO_op_finish(bm, &dupeop);
448 
449 #undef SPLIT_INPUT
450 }
451 
453 {
454 #define DEL_INPUT 1
455 
456  BMOperator *delop = op;
457 
458  /* Mark Buffer */
460 
462 
463 #undef DEL_INPUT
464 }
465 
473 {
474  BMOperator dupop, extop;
475  float cent[3], dvec[3];
476  float axis[3];
477  float rmat[3][3];
478  float phi;
479  int steps, do_dupli, a;
480  bool use_dvec;
481 
482  BMO_slot_vec_get(op->slots_in, "cent", cent);
483  BMO_slot_vec_get(op->slots_in, "axis", axis);
484  normalize_v3(axis);
485  BMO_slot_vec_get(op->slots_in, "dvec", dvec);
486  use_dvec = !is_zero_v3(dvec);
487  steps = BMO_slot_int_get(op->slots_in, "steps");
488  phi = BMO_slot_float_get(op->slots_in, "angle") / steps;
489  do_dupli = BMO_slot_bool_get(op->slots_in, "use_duplicate");
490  const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
491  /* Caller needs to perform other sanity checks (such as the spin being 360d). */
492  const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge") && steps >= 3;
493 
494  axis_angle_normalized_to_mat3(rmat, axis, phi);
495 
496  BMVert **vtable = NULL;
497  if (use_merge) {
498  vtable = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
499  int i = 0;
500  BMIter iter;
501  BMVert *v;
502  BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
503  vtable[i] = v;
504  /* Evil! store original index in normal,
505  * this is duplicated into every other vertex.
506  * So we can read the original from the final.
507  *
508  * The normals must be recalculated anyway. */
509  *((int *)&v->no[0]) = i;
510  }
511  }
512 
513  BMO_slot_copy(op, slots_in, "geom", op, slots_out, "geom_last.out");
514  for (a = 0; a < steps; a++) {
515  if (do_dupli) {
516  BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%S", op, "geom_last.out");
517  BMO_op_exec(bm, &dupop);
519  op->flag,
520  "rotate cent=%v matrix=%m3 space=%s verts=%S",
521  cent,
522  rmat,
523  op,
524  "space",
525  &dupop,
526  "geom.out");
527  BMO_slot_copy(&dupop, slots_out, "geom.out", op, slots_out, "geom_last.out");
528  BMO_op_finish(bm, &dupop);
529  }
530  else {
532  &extop,
533  op->flag,
534  "extrude_face_region "
535  "geom=%S "
536  "use_keep_orig=%b "
537  "use_normal_flip=%b "
538  "use_normal_from_adjacent=%b",
539  op,
540  "geom_last.out",
541  use_merge,
542  use_normal_flip && (a == 0),
543  (a != 0));
544  BMO_op_exec(bm, &extop);
545  if ((use_merge && (a == steps - 1)) == false) {
547  op->flag,
548  "rotate cent=%v matrix=%m3 space=%s verts=%S",
549  cent,
550  rmat,
551  op,
552  "space",
553  &extop,
554  "geom.out");
555  BMO_slot_copy(&extop, slots_out, "geom.out", op, slots_out, "geom_last.out");
556  }
557  else {
558  /* Merge first/last vertices and edges (maintaining 'geom.out' state). */
559  BMOpSlot *slot_geom_out = BMO_slot_get(extop.slots_out, "geom.out");
560  BMElem **elem_array = (BMElem **)slot_geom_out->data.buf;
561  int elem_array_len = slot_geom_out->len;
562  for (int i = 0; i < elem_array_len;) {
563  if (elem_array[i]->head.htype == BM_VERT) {
564  BMVert *v_src = (BMVert *)elem_array[i];
565  BMVert *v_dst = vtable[*((const int *)&v_src->no[0])];
566  BM_vert_splice(bm, v_dst, v_src);
567  elem_array_len--;
568  elem_array[i] = elem_array[elem_array_len];
569  }
570  else {
571  i++;
572  }
573  }
574  for (int i = 0; i < elem_array_len;) {
575  if (elem_array[i]->head.htype == BM_EDGE) {
576  BMEdge *e_src = (BMEdge *)elem_array[i];
577  BMEdge *e_dst = BM_edge_find_double(e_src);
578  if (e_dst != NULL) {
579  BM_edge_splice(bm, e_dst, e_src);
580  elem_array_len--;
581  elem_array[i] = elem_array[elem_array_len];
582  continue;
583  }
584  }
585  i++;
586  }
587  /* Full copies of faces may cause overlap. */
588  for (int i = 0; i < elem_array_len;) {
589  if (elem_array[i]->head.htype == BM_FACE) {
590  BMFace *f_src = (BMFace *)elem_array[i];
591  BMFace *f_dst = BM_face_find_double(f_src);
592  if (f_dst != NULL) {
593  BM_face_kill(bm, f_src);
594  elem_array_len--;
595  elem_array[i] = elem_array[elem_array_len];
596  continue;
597  }
598  }
599  i++;
600  }
601  slot_geom_out->len = elem_array_len;
602  }
603  BMO_op_finish(bm, &extop);
604  }
605 
606  if (use_dvec) {
607  mul_m3_v3(rmat, dvec);
609  op->flag,
610  "translate vec=%v space=%s verts=%S",
611  dvec,
612  op,
613  "space",
614  op,
615  "geom_last.out");
616  }
617  }
618 
619  if (vtable) {
620  MEM_freeN(vtable);
621  }
622 }
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:734
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
MINLINE float normalize_v3(float r[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:67
Read Guarded memory(de)allocation.
#define BM_ALL_NOLOOP
Definition: bmesh_class.h:411
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
Splice Edge.
Definition: bmesh_core.c:2332
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
Definition: bmesh_core.c:41
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
Splice Vert.
Definition: bmesh_core.c:2046
void BM_face_kill(BMesh *bm, BMFace *f)
Definition: bmesh_core.c:828
BMFace * BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const BMFace *f_example, const eBMCreateFlag create_flag)
Definition: bmesh_core.c:395
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
Definition: bmesh_core.c:123
@ BM_CREATE_SKIP_CD
Definition: bmesh_core.h:20
void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type)
Definition: bmesh_delete.c:86
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_FACES_OF_EDGE
@ BM_FACES_OF_VERT
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_VERTS_OF_FACE
@ BM_FACES_OF_MESH
@ BM_EDGES_OF_VERT
@ BM_EDGES_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_edge_verts_swap(BMEdge *e)
Definition: bmesh_mods.c:580
void BMO_slot_buffer_flag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, short oflag)
BMO_FLAG_BUFFER.
#define BMO_edge_flag_test(bm, e, oflag)
void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3])
#define BMO_edge_flag_enable(bm, e, oflag)
@ DEL_FACES
void BMO_mesh_selected_remap(BMesh *bm, BMOpSlot *slot_vert_map, BMOpSlot *slot_edge_map, BMOpSlot *slot_face_map, bool check_select)
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, char hflag)
#define BMO_vert_flag_enable(bm, e, oflag)
void BMO_op_exec(BMesh *bm, BMOperator *op)
BMESH OPSTACK EXEC OP.
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_slot_copy(op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst)
void BMO_op_init(BMesh *bm, BMOperator *op, int flag, const char *opname)
BMESH OPSTACK INIT OP.
#define BMO_vert_flag_test(bm, e, oflag)
bool BMO_op_initf(BMesh *bm, BMOperator *op, int flag, const char *fmt,...)
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_op_finish(BMesh *bm, BMOperator *op)
BMESH OPSTACK FINISH OP.
bool BMO_op_callf(BMesh *bm, int flag, const char *fmt,...)
BMOpSlot * BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK GET SLOT.
void * BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
#define BMO_face_flag_test(bm, e, oflag)
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val)
BMEdge * BM_edge_find_double(BMEdge *e)
Definition: bmesh_query.c:1581
BMFace * BM_face_find_double(BMFace *f)
Definition: bmesh_query.c:1660
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define DUPE_NEW
Definition: bmo_dupe.c:20
#define DUPE_INPUT
Definition: bmo_dupe.c:19
#define SPLIT_INPUT
void bmo_split_exec(BMesh *bm, BMOperator *op)
Definition: bmo_dupe.c:390
static BMEdge * bmo_edge_copy(BMOperator *op, BMOpSlot *slot_edgemap_out, BMOpSlot *slot_boundarymap_out, BMesh *bm_dst, BMesh *bm_src, BMEdge *e_src, GHash *vhash, GHash *ehash, const bool use_edge_flip_from_face)
Definition: bmo_dupe.c:60
static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
Definition: bmo_dupe.c:181
#define DUPE_DONE
Definition: bmo_dupe.c:21
#define DEL_INPUT
static BMFace * bmo_face_copy(BMOperator *op, BMOpSlot *slot_facemap_out, BMesh *bm_dst, BMesh *bm_src, BMFace *f_src, GHash *vhash, GHash *ehash)
Definition: bmo_dupe.c:130
void bmo_duplicate_exec(BMesh *bm, BMOperator *op)
Definition: bmo_dupe.c:327
void bmo_spin_exec(BMesh *bm, BMOperator *op)
Definition: bmo_dupe.c:472
static BMVert * bmo_vert_copy(BMOperator *op, BMOpSlot *slot_vertmap_out, BMesh *bm_dst, BMesh *bm_src, BMVert *v_src, GHash *vhash)
Definition: bmo_dupe.c:29
void bmo_delete_exec(BMesh *bm, BMOperator *op)
Definition: bmo_dupe.c:452
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static unsigned a[3]
Definition: RandGen.cpp:78
static const int steps
Definition: sky_nishita.cpp:19
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
struct BMLoop * l
Definition: bmesh_class.h:128
int len
Definition: bmesh_class.h:267
struct BMVert * v
Definition: bmesh_class.h:153
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMLoop * radial_next
Definition: bmesh_class.h:204
struct BMFace * f
Definition: bmesh_class.h:171
struct BMLoop * next
Definition: bmesh_class.h:233
union BMOpSlot::@145 data
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
int totvert
Definition: bmesh_class.h:297