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