Blender  V3.3
bmo_subdivide.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_array.h"
12 #include "BLI_math.h"
13 #include "BLI_noise.h"
14 #include "BLI_rand.h"
15 #include "BLI_stack.h"
16 
17 #include "BKE_customdata.h"
18 
19 #include "bmesh.h"
21 #include "intern/bmesh_private.h"
22 
23 typedef struct SubDParams {
24  int numcuts;
25  float smooth;
27  float fractal;
28  float along_normal;
29  // int beauty;
30  bool use_smooth;
32  bool use_sphere;
34  int seed;
36  BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */
37  BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */
38  float fractal_ofs[3];
39 
40  /* Runtime storage for shape key. */
41  struct {
44  int totlayer;
45 
46  /* Shape-key holding displaced vertex coordinates for current geometry. */
47  int tmpkey;
49 
51 
53 {
54  const int skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1;
55  params->shape_info.tmpkey = skey;
56  params->shape_info.cd_vert_shape_offset = CustomData_get_offset(&bm->vdata, CD_SHAPEKEY);
57  params->shape_info.cd_vert_shape_offset_tmp = CustomData_get_n_offset(
58  &bm->vdata, CD_SHAPEKEY, skey);
59  params->shape_info.totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY);
60 }
61 
63  BMFace *face,
64  BMVert **verts,
65  const SubDParams *params);
66 
67 /*
68  * NOTE: this is a pattern-based edge subdivider.
69  * it tries to match a pattern to edge selections on faces,
70  * then executes functions to cut them.
71  */
72 typedef struct SubDPattern {
73  int seledges[20]; /* selected edges mask, for splitting */
74 
75  /* verts starts at the first new vert cut, not the first vert in the face */
77  int len; /* total number of verts, before any subdivision */
79 
80 /* generic subdivision rules:
81  *
82  * - two selected edges in a face should make a link
83  * between them.
84  *
85  * - one edge should do, what? make pretty topology, or just
86  * split the edge only?
87  */
88 
89 /* flags for all elements share a common bitfield space */
90 #define SUBD_SPLIT 1
91 
92 #define EDGE_PERCENT 2
93 
94 /* I don't think new faces are flagged, currently, but
95  * better safe than sorry. */
96 #define FACE_CUSTOMFILL 4
97 #define ELE_INNER 8
98 #define ELE_SPLIT 16
99 
100 /* see bug T32665, 0.00005 means a we get face splits at a little under 1.0 degrees */
101 #define FLT_FACE_SPLIT_EPSILON 0.00005f
102 
103 /*
104  * NOTE: beauty has been renamed to flag!
105  */
106 
107 /* generic subdivision rules:
108  *
109  * - two selected edges in a face should make a link
110  * between them.
111  *
112  * - one edge should do, what? make pretty topology, or just
113  * split the edge only?
114  */
115 
116 /* connects face with smallest len, which I think should always be correct for
117  * edge subdivision */
118 static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace **r_f_new)
119 {
120  BMLoop *l_a, *l_b;
121  BMFace *f;
122 
123  /* this isn't the best thing in the world. it doesn't handle cases where there's
124  * multiple faces yet. that might require a convexity test to figure out which
125  * face is "best" and who knows what for non-manifold conditions.
126  *
127  * NOTE: we allow adjacent here, since there's no chance this happens.
128  */
129  f = BM_vert_pair_share_face_by_len(v_a, v_b, &l_a, &l_b, true);
130 
131  if (f) {
132  BMFace *f_new;
133  BMLoop *l_new;
134 
136 
137  f_new = BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
138 
139  if (r_f_new) {
140  *r_f_new = f_new;
141  }
142  return l_new ? l_new->e : NULL;
143  }
144 
145  return NULL;
146 }
147 
152  const float co_a[3],
153  const float no_a[3],
154  const float co_b[3],
155  const float no_b[3],
156  const float no_dir[3], /* caller already knows, avoid normalize */
157  float fac,
158  float r_co[3])
159 {
160  /* center of the sphere defined by both normals */
161  float center[3];
162 
163  BLI_assert(len_squared_v3v3(no_a, no_b) != 0);
164 
165  /* calculate sphere 'center' */
166  {
167  /* use point on plane to */
168  float no_mid[3], no_ortho[3];
169  /* pass this as an arg instead */
170 #if 0
171  float no_dir[3];
172 #endif
173 
174  add_v3_v3v3(no_mid, no_a, no_b);
175  normalize_v3(no_mid);
176 
177 #if 0
178  sub_v3_v3v3(no_dir, co_a, co_b);
179  normalize_v3(no_dir);
180 #endif
181 
182  /* axis of slerp */
183  bool center_ok = false;
184  cross_v3_v3v3(no_ortho, no_mid, no_dir);
185  if (normalize_v3(no_ortho) != 0.0f) {
186  float plane_a[4], plane_b[4], plane_c[4];
187  float v_a_no_ortho[3], v_b_no_ortho[3];
188 
189  /* create planes */
190  cross_v3_v3v3(v_a_no_ortho, no_ortho, no_a);
191  cross_v3_v3v3(v_b_no_ortho, no_ortho, no_b);
192  project_v3_plane(v_a_no_ortho, no_ortho, v_a_no_ortho);
193  project_v3_plane(v_b_no_ortho, no_ortho, v_b_no_ortho);
194 
195  plane_from_point_normal_v3(plane_a, co_a, v_a_no_ortho);
196  plane_from_point_normal_v3(plane_b, co_b, v_b_no_ortho);
197  plane_from_point_normal_v3(plane_c, co_b, no_ortho);
198 
199  /* find the sphere center from 3 planes */
200  if (isect_plane_plane_plane_v3(plane_a, plane_b, plane_c, center)) {
201  center_ok = true;
202  }
203  }
204  if (center_ok == false) {
205  mid_v3_v3v3(center, co_a, co_b);
206  }
207  }
208 
209  /* calculate the final output 'r_co' */
210  {
211  float ofs_a[3], ofs_b[3], ofs_slerp[3];
212  float dist_a, dist_b;
213 
214  sub_v3_v3v3(ofs_a, co_a, center);
215  sub_v3_v3v3(ofs_b, co_b, center);
216 
217  dist_a = normalize_v3(ofs_a);
218  dist_b = normalize_v3(ofs_b);
219 
220  if (interp_v3_v3v3_slerp(ofs_slerp, ofs_a, ofs_b, fac)) {
221  madd_v3_v3v3fl(r_co, center, ofs_slerp, interpf(dist_b, dist_a, fac));
222  }
223  else {
224  interp_v3_v3v3(r_co, co_a, co_b, fac);
225  }
226  }
227 }
228 
229 /* Calculates offset for co, based on fractal, sphere or smooth settings. */
230 static void alter_co(BMVert *v,
231  BMEdge *UNUSED(e_orig),
232  const SubDParams *params,
233  const float perc,
234  const BMVert *v_a,
235  const BMVert *v_b)
236 {
237  float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
238  int i;
239 
240  copy_v3_v3(co, v->co);
241 
242  if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */
243  normalize_v3_length(co, params->smooth);
244  }
245  else if (params->use_smooth) {
246  /* calculating twice and blending gives smoother results,
247  * removing visible seams. */
248 #define USE_SPHERE_DUAL_BLEND
249 
250  const float eps_unit_vec = 1e-5f;
251  float smooth;
252  float no_dir[3];
253 
254 #ifdef USE_SPHERE_DUAL_BLEND
255  float no_reflect[3], co_a[3], co_b[3];
256 #endif
257 
258  sub_v3_v3v3(no_dir, v_a->co, v_b->co);
259  normalize_v3(no_dir);
260 
261 #ifndef USE_SPHERE_DUAL_BLEND
262  if (len_squared_v3v3(v_a->no, v_b->no) < eps_unit_vec) {
263  interp_v3_v3v3(co, v_a->co, v_b->co, perc);
264  }
265  else {
266  interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, v_b->no, no_dir, perc, co);
267  }
268 #else
269  /* sphere-a */
270  reflect_v3_v3v3(no_reflect, v_a->no, no_dir);
271  if (len_squared_v3v3(v_a->no, no_reflect) < eps_unit_vec) {
272  interp_v3_v3v3(co_a, v_a->co, v_b->co, perc);
273  }
274  else {
275  interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, no_reflect, no_dir, perc, co_a);
276  }
277 
278  /* sphere-b */
279  reflect_v3_v3v3(no_reflect, v_b->no, no_dir);
280  if (len_squared_v3v3(v_b->no, no_reflect) < eps_unit_vec) {
281  interp_v3_v3v3(co_b, v_a->co, v_b->co, perc);
282  }
283  else {
284  interp_slerp_co_no_v3(v_a->co, no_reflect, v_b->co, v_b->no, no_dir, perc, co_b);
285  }
286 
287  /* blend both spheres */
288  interp_v3_v3v3(co, co_a, co_b, perc);
289 #endif /* USE_SPHERE_DUAL_BLEND */
290 
291  /* apply falloff */
292  if (params->smooth_falloff == SUBD_FALLOFF_LIN) {
293  smooth = 1.0f;
294  }
295  else {
296  smooth = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
297  smooth = 1.0f + bmesh_subd_falloff_calc(params->smooth_falloff, smooth);
298  }
299 
300  if (params->use_smooth_even) {
302  }
303 
304  smooth *= params->smooth;
305  if (smooth != 1.0f) {
306  float co_flat[3];
307  interp_v3_v3v3(co_flat, v_a->co, v_b->co, perc);
308  interp_v3_v3v3(co, co_flat, co, smooth);
309  }
310 
311 #undef USE_SPHERE_DUAL_BLEND
312  }
313 
314  if (params->use_fractal) {
315  float normal[3], co2[3], base1[3], base2[3], tvec[3];
316  const float len = len_v3v3(v_a->co, v_b->co);
317  float fac;
318 
319  fac = params->fractal * len;
320 
321  mid_v3_v3v3(normal, v_a->no, v_b->no);
322  ortho_basis_v3v3_v3(base1, base2, normal);
323 
324  add_v3_v3v3(co2, v->co, params->fractal_ofs);
325  mul_v3_fl(co2, 10.0f);
326 
327  tvec[0] = fac * (BLI_noise_generic_turbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
328  tvec[1] = fac * (BLI_noise_generic_turbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f);
329  tvec[2] = fac * (BLI_noise_generic_turbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f);
330 
331  /* add displacement */
332  madd_v3_v3fl(co, normal, tvec[0]);
333  madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal));
334  madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal));
335  }
336 
337  /* apply the new difference to the rest of the shape keys,
338  * note that this doesn't take rotations into account, we _could_ support
339  * this by getting the normals and coords for each shape key and
340  * re-calculate the smooth value for each but this is quite involved.
341  * for now its ok to simply apply the difference IMHO - campbell */
342 
343  if (params->shape_info.totlayer > 1) {
344  float tvec[3];
345 
346  sub_v3_v3v3(tvec, v->co, co);
347 
348  /* skip the last layer since its the temp */
349  i = params->shape_info.totlayer - 1;
350  co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
351  while (i--) {
352  BLI_assert(co != BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp));
353  sub_v3_v3(co += 3, tvec);
354  }
355  }
356 }
357 
358 /* assumes in the edge is the correct interpolated vertices already */
359 /* percent defines the interpolation, rad and flag are for special options */
360 /* results in new vertex with correct coordinate, vertex normal and weight group info */
362  BMEdge *edge,
363  BMEdge *e_orig,
364  const SubDParams *params,
365  const float factor_edge_split,
366  const float factor_subd,
367  BMVert *v_a,
368  BMVert *v_b,
369  BMEdge **r_edge)
370 {
371  BMVert *v_new;
372 
373  v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split);
374 
376 
377  /* offset for smooth or sphere or fractal */
378  alter_co(v_new, e_orig, params, factor_subd, v_a, v_b);
379 
380 #if 0 // BMESH_TODO
381  /* clip if needed by mirror modifier */
382  if (edge->v1->f2) {
383  if (edge->v1->f2 & edge->v2->f2 & 1) {
384  co[0] = 0.0f;
385  }
386  if (edge->v1->f2 & edge->v2->f2 & 2) {
387  co[1] = 0.0f;
388  }
389  if (edge->v1->f2 & edge->v2->f2 & 4) {
390  co[2] = 0.0f;
391  }
392  }
393 #endif
394 
395  interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd);
396  normalize_v3(v_new->no);
397 
398  return v_new;
399 }
400 
402  BMEdge *edge,
403  BMEdge *e_orig,
404  int curpoint,
405  int totpoint,
406  const SubDParams *params,
407  BMVert *v_a,
408  BMVert *v_b,
409  BMEdge **r_edge)
410 {
411  BMVert *v_new;
412  float factor_edge_split, factor_subd;
413 
414  if (BMO_edge_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) {
415  factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge);
416  factor_subd = 0.0f;
417  }
418  else {
419  factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint);
420  factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1);
421  }
422 
424  bm, edge, e_orig, params, factor_edge_split, factor_subd, v_a, v_b, r_edge);
425  return v_new;
426 }
427 
429  BMesh *bm, BMEdge *edge, const SubDParams *params, BMVert *v_a, BMVert *v_b)
430 {
431  BMEdge *eed = edge, *e_new, e_tmp = *edge;
432  BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
433  int i, numcuts = params->numcuts;
434 
435  e_tmp.v1 = &v1_tmp;
436  e_tmp.v2 = &v2_tmp;
437 
438  for (i = 0; i < numcuts; i++) {
439  v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new);
440 
444 
446  if (v->e) {
447  BM_CHECK_ELEMENT(v->e);
448  }
449  if (v->e && v->e->l) {
450  BM_CHECK_ELEMENT(v->e->l->f);
451  }
452  }
453 
454  alter_co(v1, &e_tmp, params, 0, &v1_tmp, &v2_tmp);
455  alter_co(v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp);
456 }
457 
458 /* NOTE: the patterns are rotated as necessary to
459  * match the input geometry. they're based on the
460  * pre-split state of the face */
461 
472 static void quad_1edge_split(BMesh *bm,
473  BMFace *UNUSED(face),
474  BMVert **verts,
475  const SubDParams *params)
476 {
477  BMFace *f_new;
478  int i, add, numcuts = params->numcuts;
479 
480  /* if it's odd, the middle face is a quad, otherwise it's a triangle */
481  if ((numcuts % 2) == 0) {
482  add = 2;
483  for (i = 0; i < numcuts; i++) {
484  if (i == numcuts / 2) {
485  add -= 1;
486  }
487  connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
488  }
489  }
490  else {
491  add = 2;
492  for (i = 0; i < numcuts; i++) {
493  connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
494  if (i == numcuts / 2) {
495  add -= 1;
496  connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
497  }
498  }
499  }
500 }
501 
502 static const SubDPattern quad_1edge = {
503  {1, 0, 0, 0},
505  4,
506 };
507 
519  BMFace *UNUSED(face),
520  BMVert **verts,
521  const SubDParams *params)
522 {
523  BMFace *f_new;
524  int i, numcuts = params->numcuts;
525 
526  for (i = 0; i < numcuts; i++) {
527  connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
528  }
529  connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &f_new);
530 }
531 
532 static const SubDPattern quad_2edge_path = {
533  {1, 1, 0, 0},
535  4,
536 };
537 
549  BMFace *UNUSED(face),
550  BMVert **verts,
551  const SubDParams *params)
552 {
553  BMFace *f_new;
554  BMVert *v, *v_last;
555  BMEdge *e, *e_new, e_tmp;
556  int i, numcuts = params->numcuts;
557 
558  v_last = verts[numcuts];
559 
560  for (i = numcuts - 1; i >= 0; i--) {
561  e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
562 
563  e_tmp = *e;
564  v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new);
565 
566  if (i != numcuts - 1) {
567  connect_smallest_face(bm, v_last, v, &f_new);
568  }
569 
570  v_last = v;
571  }
572 
573  connect_smallest_face(bm, v_last, verts[numcuts * 2 + 2], &f_new);
574 }
575 
577  {1, 1, 0, 0},
579  4,
580 };
581 
593  BMFace *UNUSED(face),
594  BMVert **verts,
595  const SubDParams *params)
596 {
597  BMFace *f_new;
598  /* BMVert *v; */ /* UNUSED */
599  /* BMVert *v_last = verts[2]; */ /* UNUSED */
600  /* BMEdge *e, *e_new; */ /* UNUSED */
601  int i, numcuts = params->numcuts;
602 
603  for (i = 0; i < numcuts; i++) {
604  connect_smallest_face(bm, verts[i], verts[numcuts * 2 + 2], &f_new);
605  connect_smallest_face(bm, verts[numcuts + (numcuts - i)], verts[numcuts * 2 + 2], &f_new);
606  }
607 }
608 
609 static const SubDPattern quad_2edge_fan = {
610  {1, 1, 0, 0},
612  4,
613 };
614 
627 static void quad_3edge_split(BMesh *bm,
628  BMFace *UNUSED(face),
629  BMVert **verts,
630  const SubDParams *params)
631 {
632  BMFace *f_new;
633  int i, add = 0, numcuts = params->numcuts;
634 
635  for (i = 0; i < numcuts; i++) {
636  if (i == numcuts / 2) {
637  if (numcuts % 2 != 0) {
638  connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new);
639  }
640  add = numcuts * 2 + 2;
641  }
642  connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new);
643  }
644 
645  for (i = 0; i < numcuts / 2 + 1; i++) {
646  connect_smallest_face(bm, verts[i], verts[(numcuts - i) + numcuts * 2 + 1], &f_new);
647  }
648 }
649 
650 static const SubDPattern quad_3edge = {
651  {1, 1, 1, 0},
653  4,
654 };
655 
669  BMFace *UNUSED(face),
670  BMVert **verts,
671  const SubDParams *params)
672 {
673  BMFace *f_new;
674  BMVert *v, *v1, *v2;
675  BMEdge *e, *e_new, e_tmp;
676  BMVert **lines;
677  int numcuts = params->numcuts;
678  int i, j, a, b, s = numcuts + 2 /* , totv = numcuts * 4 + 4 */;
679 
680  lines = MEM_callocN(sizeof(BMVert *) * (numcuts + 2) * (numcuts + 2), "q_4edge_split");
681  /* build a 2-dimensional array of verts,
682  * containing every vert (and all new ones)
683  * in the face */
684 
685  /* first line */
686  for (i = 0; i < numcuts + 2; i++) {
687  lines[i] = verts[numcuts * 3 + 2 + (numcuts - i + 1)];
688  }
689 
690  /* last line */
691  for (i = 0; i < numcuts + 2; i++) {
692  lines[(s - 1) * s + i] = verts[numcuts + i];
693  }
694 
695  /* first and last members of middle lines */
696  for (i = 0; i < numcuts; i++) {
697  a = i;
698  b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
699 
700  e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
701  if (!e) {
702  continue;
703  }
704 
707 
708  v1 = lines[(i + 1) * s] = verts[a];
709  v2 = lines[(i + 1) * s + s - 1] = verts[b];
710 
711  e_tmp = *e;
712  for (a = 0; a < numcuts; a++) {
713  v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new);
714 
715  BMESH_ASSERT(v != NULL);
716 
718  lines[(i + 1) * s + a + 1] = v;
719  }
720  }
721 
722  for (i = 1; i < numcuts + 2; i++) {
723  for (j = 1; j <= numcuts; j++) {
724  a = i * s + j;
725  b = (i - 1) * s + j;
726  e = connect_smallest_face(bm, lines[a], lines[b], &f_new);
727  if (!e) {
728  continue;
729  }
730 
733  }
734  }
735 
736  MEM_freeN(lines);
737 }
738 
751 static void tri_1edge_split(BMesh *bm,
752  BMFace *UNUSED(face),
753  BMVert **verts,
754  const SubDParams *params)
755 {
756  BMFace *f_new;
757  int i, numcuts = params->numcuts;
758 
759  for (i = 0; i < numcuts; i++) {
760  connect_smallest_face(bm, verts[i], verts[numcuts + 1], &f_new);
761  }
762 }
763 
764 static const SubDPattern tri_1edge = {
765  {1, 0, 0},
767  3,
768 };
769 
783  BMFace *UNUSED(face),
784  BMVert **verts,
785  const SubDParams *params)
786 {
787  BMFace *f_new;
788  BMEdge *e, *e_new, e_tmp;
789  BMVert ***lines, *v, v1_tmp, v2_tmp;
790  void *stackarr[1];
791  int i, j, a, b, numcuts = params->numcuts;
792 
793  /* number of verts in each lin */
794  lines = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table");
795 
796  lines[0] = (BMVert **)stackarr;
797  lines[0][0] = verts[numcuts * 2 + 1];
798 
799  lines[numcuts + 1] = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table 2");
800  for (i = 0; i < numcuts; i++) {
801  lines[numcuts + 1][i + 1] = verts[i];
802  }
803  lines[numcuts + 1][0] = verts[numcuts * 3 + 2];
804  lines[numcuts + 1][numcuts + 1] = verts[numcuts];
805 
806  for (i = 0; i < numcuts; i++) {
807  lines[i + 1] = MEM_callocN(sizeof(void *) * (2 + i), "triangle vert table row");
808  a = numcuts * 2 + 2 + i;
809  b = numcuts + numcuts - i;
810  e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
811  if (!e) {
812  goto cleanup;
813  }
814 
817 
818  lines[i + 1][0] = verts[a];
819  lines[i + 1][i + 1] = verts[b];
820 
821  e_tmp = *e;
822  v1_tmp = *verts[a];
823  v2_tmp = *verts[b];
824  e_tmp.v1 = &v1_tmp;
825  e_tmp.v2 = &v2_tmp;
826  for (j = 0; j < i; j++) {
827  v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new);
828  lines[i + 1][j + 1] = v;
829 
831  }
832  }
833 
846  for (i = 1; i <= numcuts; i++) {
847  for (j = 0; j < i; j++) {
848  e = connect_smallest_face(bm, lines[i][j], lines[i + 1][j + 1], &f_new);
849 
852 
853  e = connect_smallest_face(bm, lines[i][j + 1], lines[i + 1][j + 1], &f_new);
854 
857  }
858  }
859 
860 cleanup:
861  for (i = 1; i < numcuts + 2; i++) {
862  if (lines[i]) {
863  MEM_freeN(lines[i]);
864  }
865  }
866 
867  MEM_freeN(lines);
868 }
869 
870 static const SubDPattern tri_3edge = {
871  {1, 1, 1},
873  3,
874 };
875 
876 static const SubDPattern quad_4edge = {
877  {1, 1, 1, 1},
879  4,
880 };
881 
882 static const SubDPattern *patterns[] = {
883  NULL, /* quad single edge pattern is inserted here */
884  NULL, /* quad corner vert pattern is inserted here */
885  NULL, /* tri single edge pattern is inserted here */
886  NULL,
887  &quad_3edge,
888  NULL,
889 };
890 
891 #define PATTERNS_TOT ARRAY_SIZE(patterns)
892 
893 typedef struct SubDFaceData {
895  const SubDPattern *pat;
896  int totedgesel; /* only used if pat was NULL, e.g. no pattern was found */
899 
901 {
902  BMOpSlot *einput;
903  const SubDPattern *pat;
905  BLI_Stack *facedata;
906  BMIter viter, fiter, liter;
907  BMVert *v, **verts = NULL;
908  BMEdge *edge;
909  BMEdge **edges = NULL;
910  BLI_array_declare(edges);
911  BMLoop *(*loops_split)[2] = NULL;
912  BLI_array_declare(loops_split);
913  BMLoop **loops = NULL;
914  BLI_array_declare(loops);
915  BMLoop *l_new, *l;
916  BMFace *face;
918  float smooth, fractal, along_normal;
919  bool use_sphere, use_single_edge, use_grid_fill, use_only_quads;
920  int cornertype, seed, i, j, a, b, numcuts, totesel, smooth_falloff;
921 
923 
924  numcuts = BMO_slot_int_get(op->slots_in, "cuts");
925  seed = BMO_slot_int_get(op->slots_in, "seed");
926  smooth = BMO_slot_float_get(op->slots_in, "smooth");
927  smooth_falloff = BMO_slot_int_get(op->slots_in, "smooth_falloff");
928  fractal = BMO_slot_float_get(op->slots_in, "fractal");
929  along_normal = BMO_slot_float_get(op->slots_in, "along_normal");
930  cornertype = BMO_slot_int_get(op->slots_in, "quad_corner_type");
931 
932  use_single_edge = BMO_slot_bool_get(op->slots_in, "use_single_edge");
933  use_grid_fill = BMO_slot_bool_get(op->slots_in, "use_grid_fill");
934  use_only_quads = BMO_slot_bool_get(op->slots_in, "use_only_quads");
935  use_sphere = BMO_slot_bool_get(op->slots_in, "use_sphere");
936 
937  patterns[1] = NULL;
938  /* straight cut is patterns[1] == NULL */
939  switch (cornertype) {
940  case SUBD_CORNER_PATH:
942  break;
945  break;
946  case SUBD_CORNER_FAN:
947  patterns[1] = &quad_2edge_fan;
948  break;
949  }
950 
951  if (use_single_edge) {
952  patterns[0] = &quad_1edge;
953  patterns[2] = &tri_1edge;
954  }
955  else {
956  patterns[0] = NULL;
957  patterns[2] = NULL;
958  }
959 
960  if (use_grid_fill) {
961  patterns[3] = &quad_4edge;
962  patterns[5] = &tri_3edge;
963  }
964  else {
965  patterns[3] = NULL;
966  patterns[5] = NULL;
967  }
968 
969  /* add a temporary shapekey layer to store displacements on current geometry */
971 
973 
974  BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
975  float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
976  copy_v3_v3(co, v->co);
977  }
978 
979  /* first go through and tag edges */
981 
982  params.numcuts = numcuts;
983  params.op = op;
984  params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents");
985  params.slot_custom_patterns = BMO_slot_get(op->slots_in, "custom_patterns");
986  params.smooth = smooth;
987  params.smooth_falloff = smooth_falloff;
988  params.seed = seed;
989  params.fractal = fractal;
990  params.along_normal = along_normal;
991  params.use_smooth = (smooth != 0.0f);
992  params.use_smooth_even = BMO_slot_bool_get(op->slots_in, "use_smooth_even");
993  params.use_fractal = (fractal != 0.0f);
994  params.use_sphere = use_sphere;
995 
996  if (params.use_fractal) {
997  RNG *rng = BLI_rng_new_srandom(seed);
998 
999  params.fractal_ofs[0] = BLI_rng_get_float(rng) * 200.0f;
1000  params.fractal_ofs[1] = BLI_rng_get_float(rng) * 200.0f;
1001  params.fractal_ofs[2] = BLI_rng_get_float(rng) * 200.0f;
1002 
1003  BLI_rng_free(rng);
1004  }
1005 
1006  BMO_slot_map_to_flag(bm, op->slots_in, "custom_patterns", BM_FACE, FACE_CUSTOMFILL);
1007 
1008  BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents", BM_EDGE, EDGE_PERCENT);
1009 
1010  facedata = BLI_stack_new(sizeof(SubDFaceData), __func__);
1011 
1012  BM_ITER_MESH (face, &fiter, bm, BM_FACES_OF_MESH) {
1013  BMEdge *e1 = NULL, *e2 = NULL;
1014  float vec1[3], vec2[3];
1015  bool matched = false;
1016 
1017  /* skip non-quads if requested */
1018  if (use_only_quads && face->len != 4) {
1019  continue;
1020  }
1021 
1022  /* figure out which pattern to use */
1023 
1024  BLI_array_clear(edges);
1026 
1027  BLI_array_grow_items(edges, face->len);
1028  BLI_array_grow_items(verts, face->len);
1029 
1030  totesel = 0;
1031  BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, i) {
1032  edges[i] = l_new->e;
1033  verts[i] = l_new->v;
1034 
1035  if (BMO_edge_flag_test(bm, edges[i], SUBD_SPLIT)) {
1036  if (!e1) {
1037  e1 = edges[i];
1038  }
1039  else {
1040  e2 = edges[i];
1041  }
1042 
1043  totesel++;
1044  }
1045  }
1046 
1047  /* make sure the two edges have a valid angle to each other */
1048  if (totesel == 2 && BM_edge_share_vert_check(e1, e2)) {
1049  sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co);
1050  sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co);
1051  normalize_v3(vec1);
1052  normalize_v3(vec2);
1053 
1054  if (fabsf(dot_v3v3(vec1, vec2)) > 1.0f - FLT_FACE_SPLIT_EPSILON) {
1055  totesel = 0;
1056  }
1057  }
1058 
1059  if (BMO_face_flag_test(bm, face, FACE_CUSTOMFILL)) {
1060  pat = *BMO_slot_map_data_get(params.slot_custom_patterns, face);
1061  for (i = 0; i < pat->len; i++) {
1062  matched = 1;
1063  for (j = 0; j < pat->len; j++) {
1064  a = (j + i) % pat->len;
1065  if ((!!BMO_edge_flag_test(bm, edges[a], SUBD_SPLIT)) != (!!pat->seledges[j])) {
1066  matched = 0;
1067  break;
1068  }
1069  }
1070  if (matched) {
1071  SubDFaceData *fd;
1072 
1073  fd = BLI_stack_push_r(facedata);
1074  fd->pat = pat;
1075  fd->start = verts[i];
1076  fd->face = face;
1077  fd->totedgesel = totesel;
1079  break;
1080  }
1081  }
1082 
1083  /* Obviously don't test for other patterns matching. */
1084  continue;
1085  }
1086 
1087  for (i = 0; i < PATTERNS_TOT; i++) {
1088  pat = patterns[i];
1089  if (!pat) {
1090  continue;
1091  }
1092 
1093  if (pat->len == face->len) {
1094  for (a = 0; a < pat->len; a++) {
1095  matched = 1;
1096  for (b = 0; b < pat->len; b++) {
1097  j = (b + a) % pat->len;
1098  if ((!!BMO_edge_flag_test(bm, edges[j], SUBD_SPLIT)) != (!!pat->seledges[b])) {
1099  matched = 0;
1100  break;
1101  }
1102  }
1103  if (matched) {
1104  break;
1105  }
1106  }
1107  if (matched) {
1108  SubDFaceData *fd;
1109 
1111 
1112  fd = BLI_stack_push_r(facedata);
1113  fd->pat = pat;
1114  fd->start = verts[a];
1115  fd->face = face;
1116  fd->totedgesel = totesel;
1117  break;
1118  }
1119  }
1120  }
1121 
1122  if (!matched && totesel) {
1123  SubDFaceData *fd;
1124 
1126 
1127  /* must initialize all members here */
1128  fd = BLI_stack_push_r(facedata);
1129  fd->start = NULL;
1130  fd->pat = NULL;
1131  fd->totedgesel = totesel;
1132  fd->face = face;
1133  }
1134  }
1135 
1136  einput = BMO_slot_get(op->slots_in, "edges");
1137 
1138  /* go through and split edges */
1139  for (i = 0; i < einput->len; i++) {
1140  edge = einput->data.buf[i];
1141  bm_subdivide_multicut(bm, edge, &params, edge->v1, edge->v2);
1142  }
1143 
1144  /* copy original-geometry displacements to current coordinates */
1145  BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
1146  const float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
1147  copy_v3_v3(v->co, co);
1148  }
1149 
1150  for (; !BLI_stack_is_empty(facedata); BLI_stack_discard(facedata)) {
1151  SubDFaceData *fd = BLI_stack_peek(facedata);
1152 
1153  face = fd->face;
1154 
1155  /* figure out which pattern to use */
1157 
1158  pat = fd->pat;
1159 
1160  if (!pat && fd->totedgesel == 2) {
1161  int vlen;
1162 
1163  /* ok, no pattern. we still may be able to do something */
1164  BLI_array_clear(loops);
1165  BLI_array_clear(loops_split);
1166 
1167  /* for case of two edges, connecting them shouldn't be too hard */
1168  BLI_array_grow_items(loops, face->len);
1169  BM_ITER_ELEM_INDEX (l, &liter, face, BM_LOOPS_OF_FACE, a) {
1170  loops[a] = l;
1171  }
1172 
1173  vlen = BLI_array_len(loops);
1174 
1175  /* find the boundary of one of the split edges */
1176  for (a = 0; a < vlen; a++) {
1177  if (!BMO_vert_flag_test(bm, loops[a ? (a - 1) : (vlen - 1)]->v, ELE_INNER) &&
1178  BMO_vert_flag_test(bm, loops[a]->v, ELE_INNER)) {
1179  break;
1180  }
1181  }
1182  /* Failure to break means there is an internal error. */
1183  BLI_assert(a < vlen);
1184 
1185  if (BMO_vert_flag_test(bm, loops[(a + numcuts + 1) % vlen]->v, ELE_INNER)) {
1186  b = (a + numcuts + 1) % vlen;
1187  }
1188  else {
1189  /* find the boundary of the other edge. */
1190  for (j = 0; j < vlen; j++) {
1191  b = (j + a + numcuts + 1) % vlen;
1192  if (!BMO_vert_flag_test(bm, loops[b == 0 ? vlen - 1 : b - 1]->v, ELE_INNER) &&
1193  BMO_vert_flag_test(bm, loops[b]->v, ELE_INNER)) {
1194  break;
1195  }
1196  }
1197  }
1198 
1199  b += numcuts - 1;
1200 
1201  BLI_array_grow_items(loops_split, numcuts);
1202  for (j = 0; j < numcuts; j++) {
1203  bool ok = true;
1204 
1205  /* Check for special case, see: T32500.
1206  * This edge pair could be used by more than one face,
1207  * in this case it used to (2.63), split both faces along the same verts
1208  * while it could be calculated which face should do the split,
1209  * it's ambiguous, so in this case we're better off to skip them as exceptional cases
1210  * and not try to be clever guessing which face to cut up.
1211  *
1212  * To avoid this case we need to check:
1213  * Do the verts of each share a face besides the one we are subdividing,
1214  * (but not connect to make an edge of that face).
1215  */
1216  {
1217  BMLoop *other_loop;
1218  BMIter other_fiter;
1219  BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
1220  if (other_loop->f != face) {
1221  if (BM_vert_in_face(loops[b]->v, other_loop->f)) {
1222  /* we assume that these verts are not making an edge in the face */
1223  BLI_assert(other_loop->prev->v != loops[a]->v);
1224  BLI_assert(other_loop->next->v != loops[a]->v);
1225 
1226  ok = false;
1227  break;
1228  }
1229  }
1230  }
1231  }
1232 
1233  if (ok == true) {
1234  loops_split[j][0] = loops[a];
1235  loops_split[j][1] = loops[b];
1236  }
1237  else {
1238  loops_split[j][0] = NULL;
1239  loops_split[j][1] = NULL;
1240  }
1241 
1242  b = (b - 1) % vlen;
1243  a = (a + 1) % vlen;
1244  }
1245 
1246  /* Since these are newly created vertices, we don't need to worry about them being legal,
1247  * ... though there are some cases we _should_ check for
1248  * - concave corner of an ngon.
1249  * - 2 edges being used in 2+ ngons.
1250  */
1251  // BM_face_splits_check_legal(bm, face, loops_split, BLI_array_len(loops_split));
1252 
1253  for (j = 0; j < BLI_array_len(loops_split); j++) {
1254  if (loops_split[j][0]) {
1255  BMFace *f_new;
1256  BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL);
1257  f_new = BM_face_split(
1258  bm, face, loops_split[j][0], loops_split[j][1], &l_new, NULL, false);
1259  if (f_new) {
1260  BMO_edge_flag_enable(bm, l_new->e, ELE_INNER);
1261  }
1262  }
1263  }
1264 
1265  continue;
1266  }
1267  if (!pat) {
1268  continue;
1269  }
1270 
1271  a = 0;
1272  BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) {
1273  if (l_new->v == fd->start) {
1274  a = j + 1;
1275  break;
1276  }
1277  }
1278 
1279  BLI_array_grow_items(verts, face->len);
1280 
1281  BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) {
1282  b = (j - a + face->len) % face->len;
1283  verts[b] = l_new->v;
1284  }
1285 
1286  BM_CHECK_ELEMENT(face);
1287  pat->connectexec(bm, face, verts, &params);
1288  }
1289 
1290  /* copy original-geometry displacements to current coordinates */
1291  BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
1292  const float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
1293  copy_v3_v3(v->co, co);
1294  }
1295 
1296  BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey);
1297 
1298  BLI_stack_free(facedata);
1299  if (edges) {
1300  BLI_array_free(edges);
1301  }
1302  if (verts) {
1304  }
1305  BLI_array_free(loops_split);
1306  BLI_array_free(loops);
1307 
1309  bm, op, op->slots_out, "geom_inner.out", BM_ALL_NOLOOP, ELE_INNER);
1311  bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT);
1312 
1314  bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_INNER | ELE_SPLIT | SUBD_SPLIT);
1315 }
1316 
1317 /* editmesh-emulating function */
1319  const char edge_hflag,
1320  const float smooth,
1321  const short smooth_falloff,
1322  const bool use_smooth_even,
1323  const float fractal,
1324  const float along_normal,
1325  const int numcuts,
1326  const int seltype,
1327  const int cornertype,
1328  const short use_single_edge,
1329  const short use_grid_fill,
1330  const short use_only_quads,
1331  const int seed)
1332 {
1333  BMOperator op;
1334 
1335  /* `use_sphere` isn't exposed here since its only used for new primitives. */
1336  BMO_op_initf(bm,
1337  &op,
1339  "subdivide_edges edges=%he "
1340  "smooth=%f smooth_falloff=%i use_smooth_even=%b "
1341  "fractal=%f along_normal=%f "
1342  "cuts=%i "
1343  "quad_corner_type=%i "
1344  "use_single_edge=%b use_grid_fill=%b "
1345  "use_only_quads=%b "
1346  "seed=%i",
1347  edge_hflag,
1348  smooth,
1349  smooth_falloff,
1350  use_smooth_even,
1351  fractal,
1352  along_normal,
1353  numcuts,
1354  cornertype,
1355  use_single_edge,
1356  use_grid_fill,
1357  use_only_quads,
1358  seed);
1359 
1360  BMO_op_exec(bm, &op);
1361 
1362  switch (seltype) {
1363  case SUBDIV_SELECT_NONE:
1364  break;
1365  case SUBDIV_SELECT_ORIG:
1366  /* set the newly created data to be selected */
1368  bm, op.slots_out, "geom_inner.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
1370  break;
1371  case SUBDIV_SELECT_INNER:
1373  bm, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT, BM_ELEM_SELECT, true);
1374  break;
1375  case SUBDIV_SELECT_LOOPCUT:
1376  /* deselect input */
1379  bm, op.slots_out, "geom_inner.out", BM_EDGE, BM_ELEM_SELECT, true);
1380  break;
1381  }
1382 
1383  BMO_op_finish(bm, &op);
1384 }
1385 
1387 {
1388  BMOIter siter;
1389  BMEdge *e;
1390  SubDParams params = {0};
1391 
1392  params.numcuts = BMO_slot_int_get(op->slots_in, "cuts");
1393  params.op = op;
1394  params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents");
1395 
1397 
1399 
1400  /* tag edges in map */
1401  BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents", BM_EDGE, EDGE_PERCENT);
1402 
1403  /* go through and split edges */
1404  BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
1405  bm_subdivide_multicut(bm, e, &params, e->v1, e->v2);
1406  }
1407 
1409  bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT);
1410 
1411  BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey);
1412 }
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
int CustomData_number_of_layers(const struct CustomData *data, int type)
int CustomData_get_n_offset(const struct CustomData *data, int type, int n)
int CustomData_get_offset(const struct CustomData *data, int type)
A (mainly) macro array library.
#define BLI_array_grow_items(arr, num)
Definition: BLI_array.h:91
#define BLI_array_declare(arr)
Definition: BLI_array.h:50
#define BLI_array_len(arr)
Definition: BLI_array.h:63
#define BLI_array_clear(arr)
Definition: BLI_array.h:128
#define BLI_array_free(arr)
Definition: BLI_array.h:113
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE float interpf(float a, float b, float t)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:209
MINLINE float shell_v3v3_mid_normalized_to_dist(const float a[3], const float b[3])
bool isect_plane_plane_plane_v3(const float plane_a[4], const float plane_b[4], const float plane_c[4], float r_isect_co[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_geom.c:2101
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
void reflect_v3_v3v3(float out[3], const float vec[3], const float normal[3])
Definition: math_vector.c:691
bool interp_v3_v3v3_slerp(float target[3], const float a[3], const float b[3], float t) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:48
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3])
Definition: math_vector.c:668
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_length(float r[3], float unit_scale)
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3])
Definition: math_vector.c:707
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
float BLI_noise_generic_turbulence(float noisesize, float x, float y, float z, int oct, bool hard, int noisebasis)
Definition: noise.c:1207
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition: rand.cc:58
struct RNG * BLI_rng_new_srandom(unsigned int seed)
Definition: rand.cc:46
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: rand.cc:93
void * BLI_stack_push_r(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:101
void * BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:166
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:247
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:94
void BLI_stack_discard(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:173
#define BLI_stack_new(esize, descr)
#define UNUSED(x)
#define UNLIKELY(x)
@ CD_SHAPEKEY
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
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
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BMESH_ASSERT(a)
Definition: bmesh_error.h:80
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
Definition: bmesh_interp.c:922
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:839
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_FACE
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_select_flush(BMesh *bm)
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
BMVert * BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
Edge Split.
Definition: bmesh_mods.c:448
BMFace * BM_face_split(BMesh *bm, BMFace *f, BMLoop *l_a, BMLoop *l_b, BMLoop **r_l, BMEdge *example, const bool no_double)
Face Split.
Definition: bmesh_mods.c:179
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.
void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, char hflag, bool do_flush)
BMO_FLAG_BUFFER.
#define BMO_edge_flag_test(bm, e, oflag)
void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, short oflag)
#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.
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)
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.
BMOpSlot * BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK GET SLOT.
#define BMO_FLAG_DEFAULTS
#define BMO_face_flag_test(bm, e, oflag)
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
@ SUBDIV_SELECT_ORIG
@ SUBDIV_SELECT_INNER
@ SUBDIV_SELECT_LOOPCUT
@ SUBDIV_SELECT_NONE
@ SUBD_CORNER_FAN
@ SUBD_CORNER_PATH
@ SUBD_CORNER_INNERVERT
@ SUBD_FALLOFF_LIN
#define BM_CHECK_ELEMENT(el)
Definition: bmesh_private.h:32
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
float bmesh_subd_falloff_calc(const int falloff, float val)
Definition: bmesh_query.c:2452
bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1074
bool BM_vert_in_face(BMVert *v, BMFace *f)
Definition: bmesh_query.c:306
BMFace * BM_vert_pair_share_face_by_len(BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
Definition: bmesh_query.c:165
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, const float smooth, const short smooth_falloff, const bool use_smooth_even, const float fractal, const float along_normal, const int numcuts, const int seltype, const int cornertype, const short use_single_edge, const short use_grid_fill, const short use_only_quads, const int seed)
static BMEdge * connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace **r_f_new)
static BMVert * subdivide_edge_num(BMesh *bm, BMEdge *edge, BMEdge *e_orig, int curpoint, int totpoint, const SubDParams *params, BMVert *v_a, BMVert *v_b, BMEdge **r_edge)
#define EDGE_PERCENT
Definition: bmo_subdivide.c:92
static void interp_slerp_co_no_v3(const float co_a[3], const float no_a[3], const float co_b[3], const float no_b[3], const float no_dir[3], float fac, float r_co[3])
static const SubDPattern quad_1edge
struct SubDParams SubDParams
static const SubDPattern * patterns[]
#define FLT_FACE_SPLIT_EPSILON
void(* subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, const SubDParams *params)
Definition: bmo_subdivide.c:62
struct SubDPattern SubDPattern
static const SubDPattern quad_2edge_fan
static const SubDPattern quad_4edge
static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params)
static const SubDPattern quad_3edge
static void alter_co(BMVert *v, BMEdge *UNUSED(e_orig), const SubDParams *params, const float perc, const BMVert *v_a, const BMVert *v_b)
#define FACE_CUSTOMFILL
Definition: bmo_subdivide.c:96
struct SubDFaceData SubDFaceData
static const SubDPattern quad_2edge_path
void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
static BMVert * bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *e_orig, const SubDParams *params, const float factor_edge_split, const float factor_subd, BMVert *v_a, BMVert *v_b, BMEdge **r_edge)
void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op)
static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params)
static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params)
#define ELE_INNER
Definition: bmo_subdivide.c:97
static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params)
static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params)
static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params)
#define SUBD_SPLIT
Definition: bmo_subdivide.c:90
static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params)
static const SubDPattern tri_1edge
static void bmo_subd_init_shape_info(BMesh *bm, SubDParams *params)
Definition: bmo_subdivide.c:52
static const SubDPattern tri_3edge
static const SubDPattern quad_2edge_innervert
#define ELE_SPLIT
Definition: bmo_subdivide.c:98
static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params, BMVert *v_a, BMVert *v_b)
static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params)
#define PATTERNS_TOT
static unsigned long seed
Definition: btSoftBody.h:39
SyclQueue void void size_t num_bytes void
int len
Definition: draw_manager.c:108
static float verts[][3]
IconTextureDrawCall normal
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned a[3]
Definition: RandGen.cpp:78
bool add(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
smooth(Type::FLOAT, "mask_weight")
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 * prev
Definition: bmesh_class.h:233
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
struct BMEdge * e
Definition: bmesh_class.h:97
float no[3]
Definition: bmesh_class.h:88
CustomData vdata
Definition: bmesh_class.h:337
Definition: rand.cc:33
BMVert * start
BMFace * face
const SubDPattern * pat
bool use_sphere
Definition: bmo_subdivide.c:32
float fractal
Definition: bmo_subdivide.c:27
bool use_smooth_even
Definition: bmo_subdivide.c:31
float fractal_ofs[3]
Definition: bmo_subdivide.c:38
BMOpSlot * slot_custom_patterns
Definition: bmo_subdivide.c:37
int cd_vert_shape_offset
Definition: bmo_subdivide.c:42
struct SubDParams::@166 shape_info
BMOperator * op
Definition: bmo_subdivide.c:35
bool use_fractal
Definition: bmo_subdivide.c:33
int cd_vert_shape_offset_tmp
Definition: bmo_subdivide.c:43
float smooth
Definition: bmo_subdivide.c:25
bool use_smooth
Definition: bmo_subdivide.c:30
int smooth_falloff
Definition: bmo_subdivide.c:26
float along_normal
Definition: bmo_subdivide.c:28
BMOpSlot * slot_edge_percents
Definition: bmo_subdivide.c:36
subd_pattern_fill_fp connectexec
Definition: bmo_subdivide.c:76
int seledges[20]
Definition: bmo_subdivide.c:73