Blender  V2.93
bmesh_intersect_edges.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  * The Original Code is Copyright (C) 2019 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_math.h"
27 #include "BLI_sort.h"
28 #include "BLI_stack.h"
29 
30 #include "BKE_bvhutils.h"
31 
32 #include "atomic_ops.h"
33 
34 #include "bmesh.h"
35 
36 #include "bmesh_intersect_edges.h" /* own include */
37 
38 //#define INTERSECT_EDGES_DEBUG
39 
40 #define KDOP_TREE_TYPE 4
41 #define KDOP_AXIS_LEN 14
42 #define BLI_STACK_PAIR_LEN (2 * KDOP_TREE_TYPE)
43 
44 /* -------------------------------------------------------------------- */
50 /* Callbacks for `BM_vert_pair_shared_face_cb` */
51 
55 
62 };
63 
65  BMLoop *l_a,
66  BMLoop *l_b,
67  void *userdata)
68 {
69  struct EDBMSplitBestFaceData *data = userdata;
70  float no[3];
71  copy_v3_v3(no, f->no);
72 
73  float min = dot_v3v3(l_a->v->co, no);
74  float max = dot_v3v3(l_b->v->co, no);
75  if (min > max) {
76  SWAP(float, min, max);
77  }
78 
79  BMEdge **e_iter = &data->edgenet[0];
80  BMEdge *e_next = data->edgenet[1];
81  BMVert *v_test = ELEM((*e_iter)->v1, e_next->v1, e_next->v2) ? (*e_iter)->v2 : (*e_iter)->v1;
82 
83  int verts_len = data->edgenet_len - 1;
84  for (int i = verts_len; i--; e_iter++) {
85  v_test = BM_edge_other_vert(*e_iter, v_test);
86  BLI_assert(v_test != NULL);
87  if (!BM_face_point_inside_test(f, v_test->co)) {
88  return false;
89  }
90  float dot = dot_v3v3(v_test->co, no);
91  if (dot < min) {
92  min = dot;
93  }
94  if (dot > max) {
95  max = dot;
96  }
97  }
98 
99  const float test_edgenet_range_on_face_normal = max - min;
100  if (test_edgenet_range_on_face_normal < data->best_edgenet_range_on_face_normal) {
101  data->best_edgenet_range_on_face_normal = test_edgenet_range_on_face_normal;
102  data->r_best_face = f;
103  }
104 
105  return false;
106 }
107 
108 /* find the best splittable face between the two vertices. */
110  BMLoop *l_a,
111  BMLoop *l_b,
112  void *userdata)
113 {
114  float(*data)[3] = userdata;
115  float *v_a_co = data[0];
116  float *v_a_b_dir = data[1];
117  const float range_min = -FLT_EPSILON;
118  const float range_max = 1.0f + FLT_EPSILON;
119 
120  float co[3];
121  float dir[3];
122  float lambda_b;
123 
124  copy_v3_v3(co, l_a->prev->v->co);
125  sub_v3_v3v3(dir, l_a->next->v->co, co);
126  if (isect_ray_ray_v3(v_a_co, v_a_b_dir, co, dir, NULL, &lambda_b)) {
127  if (IN_RANGE(lambda_b, range_min, range_max)) {
128  return true;
129  }
130  copy_v3_v3(co, l_b->prev->v->co);
131  sub_v3_v3v3(dir, l_b->next->v->co, co);
132  if (isect_ray_ray_v3(v_a_co, v_a_b_dir, co, dir, NULL, &lambda_b)) {
133  return IN_RANGE(lambda_b, range_min, range_max);
134  }
135  }
136  return false;
137 }
138 
140  BMVert *v_a, BMVert *v_b, BMEdge **edgenet, const int edgenet_len, const float epsilon)
141 {
143 
144  BLI_assert(v_a != v_b);
145 
146  BMLoop *dummy;
147  if (edgenet_len == 1) {
148  float data[2][3];
149  copy_v3_v3(data[0], v_b->co);
150  sub_v3_v3v3(data[1], v_a->co, data[0]);
152  v_a, v_b, false, bm_vert_pair_share_splittable_face_cb, &data, &dummy, &dummy);
154  }
155  else {
156  struct EDBMSplitBestFaceData data = {
157  .edgenet = edgenet,
158  .edgenet_len = edgenet_len,
159  .best_edgenet_range_on_face_normal = FLT_MAX,
160  .r_best_face = NULL,
161  };
163  v_a, v_b, true, bm_vert_pair_share_best_splittable_face_cb, &data, &dummy, &dummy);
164 
165  if (data.r_best_face) {
166  /* Check if the edgenet's range is smaller than the face's range. */
167  float no[3], min = FLT_MAX, max = -FLT_MAX;
168  copy_v3_v3(no, data.r_best_face->no);
169  BMVert *v_test;
170  BMIter f_iter;
171  BM_ITER_ELEM (v_test, &f_iter, data.r_best_face, BM_VERTS_OF_FACE) {
172  float dot = dot_v3v3(v_test->co, no);
173  if (dot < min) {
174  min = dot;
175  }
176  if (dot > max) {
177  max = dot;
178  }
179  }
180  float face_range_on_normal = max - min + 2 * epsilon;
181  if (face_range_on_normal < data.best_edgenet_range_on_face_normal) {
182  data.r_best_face = NULL;
183  }
184  }
185  r_best_face = data.r_best_face;
186  }
187 
188  return r_best_face;
189 }
190 
193 /* -------------------------------------------------------------------- */
200  union {
203  struct {
205  float lambda;
206  };
207  };
208 };
209 
210 /* -------------------------------------------------------------------- */
211 /* Overlap Callbacks */
212 
217  float dist_sq;
218  float dist_sq_sq;
219 };
220 
221 /* Utils */
222 
223 static void bm_vert_pair_elem_setup_ex(BMVert *v, struct EDBMSplitElem *r_pair_elem)
224 {
225  r_pair_elem->vert = v;
226 }
227 
229  float lambda,
230  int *r_data_cut_edges_len,
231  struct EDBMSplitElem *r_pair_elem)
232 {
233  r_pair_elem->edge = e;
234  r_pair_elem->lambda = lambda;
235 
236  /* Even though we have multiple atomic operations, this is fine here, since
237  * there is no dependency on order.
238  * The `e->head.index` check + atomic increment will ever be true once, as
239  * expected. We don't care which instance of the code actually ends up
240  * incrementing `r_data_cut_edge_len`, so there is no race condition here. */
241  if (atomic_fetch_and_add_int32(&e->head.index, 1) == 0) {
242  atomic_fetch_and_add_int32(r_data_cut_edges_len, 1);
243  }
244 }
245 
246 /* Util for Vert x Edge and Edge x Edge callbacks */
248  BMEdge *e,
249  const float co[3],
250  const float dir[3],
251  float lambda,
252  float data_dist_sq,
253  int *data_cut_edges_len,
254  struct EDBMSplitElem r_pair[2])
255 {
256  BMVert *e_v;
257  float dist_sq_vert_factor;
258 
259  if (!IN_RANGE_INCL(lambda, 0.0f, 1.0f)) {
260  /* Vert x Vert is already handled elsewhere. */
261  return false;
262  }
263 
264  if (lambda < 0.5f) {
265  e_v = e->v1;
266  dist_sq_vert_factor = lambda;
267  }
268  else {
269  e_v = e->v2;
270  dist_sq_vert_factor = 1.0f - lambda;
271  }
272 
273  if (v != e_v) {
274  float dist_sq_vert = square_f(dist_sq_vert_factor) * len_squared_v3(dir);
275  if (dist_sq_vert < data_dist_sq) {
276  /* Vert x Vert is already handled elsewhere. */
277  return false;
278  }
279 
280  float closest[3];
281  madd_v3_v3v3fl(closest, co, dir, lambda);
282 
283  float dist_sq = len_squared_v3v3(v->co, closest);
284  if (dist_sq < data_dist_sq) {
285  bm_edge_pair_elem_setup(e, lambda, data_cut_edges_len, &r_pair[0]);
286  bm_vert_pair_elem_setup_ex(v, &r_pair[1]);
287  return true;
288  }
289  }
290 
291  return false;
292 }
293 
294 /* Vertex x Vertex Callback */
295 
296 static bool bm_vertxvert_isect_cb(void *userdata, int index_a, int index_b, int thread)
297 {
298  struct EDBMSplitData *data = userdata;
299  BMVert *v_a = BM_vert_at_index(data->bm, index_a);
300  BMVert *v_b = BM_vert_at_index(data->bm, index_b);
301 
302  struct EDBMSplitElem *pair = BLI_stack_push_r(data->pair_stack[thread]);
303 
304  bm_vert_pair_elem_setup_ex(v_a, &pair[0]);
305  bm_vert_pair_elem_setup_ex(v_b, &pair[1]);
306 
307  return true;
308 }
309 
310 static bool bm_vertxvert_self_isect_cb(void *userdata, int index_a, int index_b, int thread)
311 {
312  if (index_a < index_b) {
313  return bm_vertxvert_isect_cb(userdata, index_a, index_b, thread);
314  }
315  return false;
316 }
317 
318 /* Vertex x Edge and Edge x Vertex Callbacks */
319 
320 static bool bm_edgexvert_isect_cb(void *userdata, int index_a, int index_b, int thread)
321 {
322  struct EDBMSplitData *data = userdata;
323  BMEdge *e = BM_edge_at_index(data->bm, index_a);
324  BMVert *v = BM_vert_at_index(data->bm, index_b);
325 
326  float co[3], dir[3], lambda;
327  copy_v3_v3(co, e->v1->co);
328  sub_v3_v3v3(dir, e->v2->co, co);
329  lambda = ray_point_factor_v3_ex(v->co, co, dir, 0.0f, -1.0f);
330 
331  struct EDBMSplitElem pair_tmp[2];
333  v, e, co, dir, lambda, data->dist_sq, &data->cut_edges_len, pair_tmp)) {
334  struct EDBMSplitElem *pair = BLI_stack_push_r(data->pair_stack[thread]);
335  pair[0] = pair_tmp[0];
336  pair[1] = pair_tmp[1];
337  }
338 
339  /* Always return false with edges. */
340  return false;
341 }
342 
343 /* Edge x Edge Callbacks */
344 
346  BMEdge *e_a,
347  BMEdge *e_b,
348  const float co_a[3],
349  const float dir_a[3],
350  const float co_b[3],
351  const float dir_b[3],
352  float lambda_a,
353  float lambda_b,
354  struct EDBMSplitElem r_pair[2])
355 {
356  float dist_sq_va_factor, dist_sq_vb_factor;
357  BMVert *e_a_v, *e_b_v;
358  if (lambda_a < 0.5f) {
359  e_a_v = e_a->v1;
360  dist_sq_va_factor = lambda_a;
361  }
362  else {
363  e_a_v = e_a->v2;
364  dist_sq_va_factor = 1.0f - lambda_a;
365  }
366 
367  if (lambda_b < 0.5f) {
368  e_b_v = e_b->v1;
369  dist_sq_vb_factor = lambda_b;
370  }
371  else {
372  e_b_v = e_b->v2;
373  dist_sq_vb_factor = 1.0f - lambda_b;
374  }
375 
376  if (e_a_v != e_b_v) {
377  if (!IN_RANGE_INCL(lambda_a, 0.0f, 1.0f) || !IN_RANGE_INCL(lambda_b, 0.0f, 1.0f)) {
378  /* Vert x Edge is already handled elsewhere. */
379  return false;
380  }
381 
382  float dist_sq_va = square_f(dist_sq_va_factor) * len_squared_v3(dir_a);
383  float dist_sq_vb = square_f(dist_sq_vb_factor) * len_squared_v3(dir_b);
384 
385  if (dist_sq_va < data->dist_sq || dist_sq_vb < data->dist_sq) {
386  /* Vert x Edge is already handled elsewhere. */
387  return false;
388  }
389 
390  float near_a[3], near_b[3];
391  madd_v3_v3v3fl(near_a, co_a, dir_a, lambda_a);
392  madd_v3_v3v3fl(near_b, co_b, dir_b, lambda_b);
393 
394  float dist_sq = len_squared_v3v3(near_a, near_b);
395  if (dist_sq < data->dist_sq) {
396  bm_edge_pair_elem_setup(e_a, lambda_a, &data->cut_edges_len, &r_pair[0]);
397  bm_edge_pair_elem_setup(e_b, lambda_b, &data->cut_edges_len, &r_pair[1]);
398  return true;
399  }
400  }
401  return false;
402 }
403 
404 static bool bm_edgexedge_isect_cb(void *userdata, int index_a, int index_b, int thread)
405 {
406  struct EDBMSplitData *data = userdata;
407  BMEdge *e_a = BM_edge_at_index(data->bm, index_a);
408  BMEdge *e_b = BM_edge_at_index(data->bm, index_b);
409 
410  if (BM_edge_share_vert_check(e_a, e_b)) {
411  /* The other vertices may intersect but Vert x Edge is already handled elsewhere. */
412  return false;
413  }
414 
415  float co_a[3], dir_a[3], co_b[3], dir_b[3];
416  copy_v3_v3(co_a, e_a->v1->co);
417  sub_v3_v3v3(dir_a, e_a->v2->co, co_a);
418 
419  copy_v3_v3(co_b, e_b->v1->co);
420  sub_v3_v3v3(dir_b, e_b->v2->co, co_b);
421 
422  float lambda_a, lambda_b;
423  /* Using with dist^4 as `epsilon` is not the best solution, but it fits in most cases. */
424  if (isect_ray_ray_epsilon_v3(co_a, dir_a, co_b, dir_b, data->dist_sq_sq, &lambda_a, &lambda_b)) {
425  struct EDBMSplitElem pair_tmp[2];
427  data, e_a, e_b, co_a, dir_a, co_b, dir_b, lambda_a, lambda_b, pair_tmp)) {
428  struct EDBMSplitElem *pair = BLI_stack_push_r(data->pair_stack[thread]);
429  pair[0] = pair_tmp[0];
430  pair[1] = pair_tmp[1];
431  }
432  }
433 
434  /* Edge x Edge returns always false. */
435  return false;
436 }
437 
438 static bool bm_edgexedge_self_isect_cb(void *userdata, int index_a, int index_b, int thread)
439 {
440  if (index_a < index_b) {
441  return bm_edgexedge_isect_cb(userdata, index_a, index_b, thread);
442  }
443  return false;
444 }
445 
446 /* -------------------------------------------------------------------- */
447 /* BVHTree Overlap Function */
448 
449 static void bm_elemxelem_bvhtree_overlap(const BVHTree *tree1,
450  const BVHTree *tree2,
452  struct EDBMSplitData *data,
453  BLI_Stack **pair_stack)
454 {
455  int parallel_tasks_num = BLI_bvhtree_overlap_thread_num(tree1);
456  for (int i = 0; i < parallel_tasks_num; i++) {
457  if (pair_stack[i] == NULL) {
458  pair_stack[i] = BLI_stack_new(sizeof(const struct EDBMSplitElem[2]), __func__);
459  }
460  }
461  data->pair_stack = pair_stack;
463 }
464 
465 /* -------------------------------------------------------------------- */
466 /* Callbacks for `BLI_qsort_r` */
467 
468 static int sort_cmp_by_lambda_cb(const void *index1_v, const void *index2_v, void *keys_v)
469 {
470  const struct EDBMSplitElem *pair_flat = keys_v;
471  const int index1 = *(int *)index1_v;
472  const int index2 = *(int *)index2_v;
473 
474  if (pair_flat[index1].lambda > pair_flat[index2].lambda) {
475  return 1;
476  }
477  return -1;
478 }
479 
480 /* -------------------------------------------------------------------- */
481 /* Main API */
482 
483 #define INTERSECT_EDGES
484 
486  BMesh *bm, const char hflag, const float dist, const bool split_faces, GHash *r_targetmap)
487 {
488  bool ok = false;
489 
490  BMIter iter;
491  BMVert *v;
492  BMEdge *e;
493  int i;
494 
495  /* Store all intersections in this array. */
496  struct EDBMSplitElem(*pair_iter)[2], (*pair_array)[2] = NULL;
497  int pair_len = 0;
498 
499  BLI_Stack *pair_stack[BLI_STACK_PAIR_LEN] = {NULL};
500  BLI_Stack **pair_stack_vertxvert = pair_stack;
501  BLI_Stack **pair_stack_edgexelem = &pair_stack[KDOP_TREE_TYPE];
502 
503  const float dist_sq = square_f(dist);
504  const float dist_half = dist / 2;
505 
506  struct EDBMSplitData data = {
507  .bm = bm,
508  .pair_stack = pair_stack,
509  .cut_edges_len = 0,
510  .dist_sq = dist_sq,
511  .dist_sq_sq = square_f(dist_sq),
512  };
513 
515 
516  /* tag and count the verts to be tested. */
517  int verts_act_len = 0, verts_remain_len = 0;
518  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
519  if (BM_elem_flag_test(v, hflag)) {
521  verts_act_len++;
522  }
523  else {
526  verts_remain_len++;
527  }
528  }
529 
530  /* The index will indicate which cut in pair_array this vertex belongs to. */
531  BM_elem_index_set(v, -1);
532  }
534 
535  /* Start the creation of BVHTrees. */
536  BVHTree *tree_verts_act = NULL, *tree_verts_remain = NULL;
537  if (verts_act_len) {
538  tree_verts_act = BLI_bvhtree_new(verts_act_len, dist_half, KDOP_TREE_TYPE, KDOP_AXIS_LEN);
539  }
540  if (verts_remain_len) {
541  tree_verts_remain = BLI_bvhtree_new(
542  verts_remain_len, dist_half, KDOP_TREE_TYPE, KDOP_AXIS_LEN);
543  }
544 
545  if (tree_verts_act || tree_verts_remain) {
546  BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
548  if (tree_verts_act) {
549  BLI_bvhtree_insert(tree_verts_act, i, v->co, 1);
550  }
551  }
552  else if (tree_verts_remain && !BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
553  BLI_bvhtree_insert(tree_verts_remain, i, v->co, 1);
554  }
555  }
556 
557  if (tree_verts_act) {
558  BLI_bvhtree_balance(tree_verts_act);
559  /* First pair search. */
561  tree_verts_act, tree_verts_act, bm_vertxvert_self_isect_cb, &data, pair_stack_vertxvert);
562  }
563 
564  if (tree_verts_remain) {
565  BLI_bvhtree_balance(tree_verts_remain);
566  }
567 
568  if (tree_verts_act && tree_verts_remain) {
570  tree_verts_remain, tree_verts_act, bm_vertxvert_isect_cb, &data, pair_stack_vertxvert);
571  }
572  }
573 
574  for (i = KDOP_TREE_TYPE; i--;) {
575  if (pair_stack_vertxvert[i]) {
576  pair_len += BLI_stack_count(pair_stack_vertxvert[i]);
577  }
578  }
579 
580 #ifdef INTERSECT_EDGES
581  uint vertxvert_pair_len = pair_len;
582 
583 # define EDGE_ACT_TO_TEST 1
584 # define EDGE_REMAIN_TO_TEST 2
585  /* Tag and count the edges. */
586  int edges_act_len = 0, edges_remain_len = 0;
587  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
589  (len_squared_v3v3(e->v1->co, e->v2->co) < dist_sq)) {
590  /* Don't test hidden edges or smaller than the minimum distance.
591  * These have already been handled in the vertices overlap. */
592  BM_elem_index_set(e, 0);
593  if (split_faces) {
594  /* Tag to be ignored. */
596  }
597  continue;
598  }
599 
602  edges_act_len++;
603  }
604  else {
606  edges_remain_len++;
607  if (split_faces) {
608  /* Tag to be ignored. */
610  }
611  }
612  }
613 
614  BVHTree *tree_edges_act = NULL, *tree_edges_remain = NULL;
615  if (edges_act_len) {
616  tree_edges_act = BLI_bvhtree_new(edges_act_len, dist_half, KDOP_TREE_TYPE, KDOP_AXIS_LEN);
617  }
618 
619  if (edges_remain_len && (tree_edges_act || tree_verts_act)) {
620  tree_edges_remain = BLI_bvhtree_new(
621  edges_remain_len, dist_half, KDOP_TREE_TYPE, KDOP_AXIS_LEN);
622  }
623 
624  if (tree_edges_act || tree_edges_remain) {
625  BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
626  int edge_test = BM_elem_index_get(e);
627  float co[2][3];
628  if (edge_test == EDGE_ACT_TO_TEST) {
629  BLI_assert(tree_edges_act);
630  e->head.index = 0;
631  copy_v3_v3(co[0], e->v1->co);
632  copy_v3_v3(co[1], e->v2->co);
633  BLI_bvhtree_insert(tree_edges_act, i, co[0], 2);
634  }
635  else if (edge_test == EDGE_REMAIN_TO_TEST) {
636  BLI_assert(tree_edges_remain);
637  e->head.index = 0;
638  copy_v3_v3(co[0], e->v1->co);
639  copy_v3_v3(co[1], e->v2->co);
640  BLI_bvhtree_insert(tree_edges_remain, i, co[0], 2);
641  }
642 # ifdef INTERSECT_EDGES_DEBUG
643  else {
644  e->head.index = 0;
645  }
646 # endif
647  /* Tag used when converting pairs to vert x vert. */
649  }
650 # undef EDGE_ACT_TO_TEST
651 # undef EDGE_REMAIN_TO_TEST
652 
653  /* Use `e->head.index` to count intersections. */
655 
656  if (tree_edges_act) {
657  BLI_bvhtree_balance(tree_edges_act);
658  }
659 
660  if (tree_edges_remain) {
661  BLI_bvhtree_balance(tree_edges_remain);
662  }
663 
664  int edgexedge_pair_len = 0;
665  if (tree_edges_act) {
666  /* Edge x Edge */
668  tree_edges_act, tree_edges_act, bm_edgexedge_self_isect_cb, &data, pair_stack_edgexelem);
669 
670  if (tree_edges_remain) {
672  tree_edges_remain, tree_edges_act, bm_edgexedge_isect_cb, &data, pair_stack_edgexelem);
673  }
674 
675  for (i = KDOP_TREE_TYPE; i--;) {
676  if (pair_stack_edgexelem[i]) {
677  edgexedge_pair_len += BLI_stack_count(pair_stack_edgexelem[i]);
678  }
679  }
680 
681  if (tree_verts_act) {
682  /* Edge v Vert */
684  tree_edges_act, tree_verts_act, bm_edgexvert_isect_cb, &data, pair_stack_edgexelem);
685  }
686 
687  if (tree_verts_remain) {
688  /* Edge v Vert */
690  tree_edges_act, tree_verts_remain, bm_edgexvert_isect_cb, &data, pair_stack_edgexelem);
691  }
692 
693  BLI_bvhtree_free(tree_edges_act);
694  }
695 
696  if (tree_verts_act && tree_edges_remain) {
697  /* Edge v Vert */
699  tree_edges_remain, tree_verts_act, bm_edgexvert_isect_cb, &data, pair_stack_edgexelem);
700  }
701 
702  BLI_bvhtree_free(tree_edges_remain);
703 
704  int edgexelem_pair_len = 0;
705  for (i = KDOP_TREE_TYPE; i--;) {
706  if (pair_stack_edgexelem[i]) {
707  edgexelem_pair_len += BLI_stack_count(pair_stack_edgexelem[i]);
708  }
709  }
710 
711  pair_len += edgexelem_pair_len;
712  int edgexvert_pair_len = edgexelem_pair_len - edgexedge_pair_len;
713 
714  if (edgexelem_pair_len) {
715  pair_array = MEM_mallocN(sizeof(*pair_array) * pair_len, __func__);
716 
717  pair_iter = pair_array;
718  for (i = 0; i < BLI_STACK_PAIR_LEN; i++) {
719  if (pair_stack[i]) {
721  BLI_stack_pop_n_reverse(pair_stack[i], pair_iter, count);
722  pair_iter += count;
723  }
724  }
725 
726  /* Map intersections per edge. */
727  union {
728  struct {
729  int cuts_len;
730  int cuts_index[];
731  };
732  int as_int[0];
733  } * e_map_iter, *e_map;
734 
735 # ifdef INTERSECT_EDGES_DEBUG
736  int cut_edges_len = 0;
737  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
738  if (e->head.index != 0) {
739  cut_edges_len++;
740  }
741  }
742  BLI_assert(cut_edges_len == data.cut_edges_len);
743 # endif
744 
745  size_t e_map_size = (data.cut_edges_len * sizeof(*e_map)) +
746  (((size_t)2 * edgexedge_pair_len + edgexvert_pair_len) *
747  sizeof(*(e_map->cuts_index)));
748 
749  e_map = MEM_mallocN(e_map_size, __func__);
750  int map_len = 0;
751 
752  /* Convert every pair to Vert x Vert. */
753 
754  /* The list of pairs starts with [vert x vert] followed by [edge x edge]
755  * and finally [edge x vert].
756  * Ignore the [vert x vert] pairs */
757  struct EDBMSplitElem *pair_flat, *pair_flat_iter;
758  pair_flat = (struct EDBMSplitElem *)&pair_array[vertxvert_pair_len];
759  pair_flat_iter = &pair_flat[0];
760  uint pair_flat_len = 2 * edgexelem_pair_len;
761  for (i = 0; i < pair_flat_len; i++, pair_flat_iter++) {
762  if (pair_flat_iter->elem->head.htype != BM_EDGE) {
763  continue;
764  }
765 
766  e = pair_flat_iter->edge;
769  int e_cuts_len = e->head.index;
770 
771  e_map_iter = (void *)&e_map->as_int[map_len];
772  e_map_iter->cuts_len = e_cuts_len;
773  e_map_iter->cuts_index[0] = i;
774 
775  /* Use `e->head.index` to indicate which slot to fill with the `cut` index. */
776  e->head.index = map_len + 1;
777  map_len += 1 + e_cuts_len;
778  }
779  else {
780  e_map->as_int[++e->head.index] = i;
781  }
782  }
783 
784  /* Split Edges A to set all Vert x Edge. */
785  for (i = 0; i < map_len;
786  e_map_iter = (void *)&e_map->as_int[i], i += 1 + e_map_iter->cuts_len) {
787 
788  /* sort by lambda. */
789  BLI_qsort_r(e_map_iter->cuts_index,
790  e_map_iter->cuts_len,
791  sizeof(*(e_map->cuts_index)),
793  pair_flat);
794 
795  float lambda, lambda_prev = 0.0f;
796  for (int j = 0; j < e_map_iter->cuts_len; j++) {
797  uint index = e_map_iter->cuts_index[j];
798 
799  struct EDBMSplitElem *pair_elem = &pair_flat[index];
800  lambda = (pair_elem->lambda - lambda_prev) / (1.0f - lambda_prev);
801  lambda_prev = pair_elem->lambda;
802  e = pair_elem->edge;
803  if (split_faces) {
804  /* Tagged edges are ignored when split faces.
805  * Un-tag these. */
807  }
808 
809  BMVert *v_new = BM_edge_split(bm, e, e->v1, NULL, lambda);
810  pair_elem->vert = v_new;
811  }
812  }
813 
814  MEM_freeN(e_map);
815  }
816  }
817 #endif
818 
819  BLI_bvhtree_free(tree_verts_act);
820  BLI_bvhtree_free(tree_verts_remain);
821 
822  if (r_targetmap) {
823  if (pair_len && pair_array == NULL) {
824  pair_array = MEM_mallocN(sizeof(*pair_array) * pair_len, __func__);
825  pair_iter = pair_array;
826  for (i = 0; i < BLI_STACK_PAIR_LEN; i++) {
827  if (pair_stack[i]) {
828  uint count = (uint)BLI_stack_count(pair_stack[i]);
829  BLI_stack_pop_n_reverse(pair_stack[i], pair_iter, count);
830  pair_iter += count;
831  }
832  }
833  }
834 
835  if (pair_array) {
836  BMVert *v_key, *v_val;
837  pair_iter = &pair_array[0];
838  for (i = 0; i < pair_len; i++, pair_iter++) {
839  BLI_assert((*pair_iter)[0].elem->head.htype == BM_VERT);
840  BLI_assert((*pair_iter)[1].elem->head.htype == BM_VERT);
841  BLI_assert((*pair_iter)[0].elem != (*pair_iter)[1].elem);
842  v_key = (*pair_iter)[0].vert;
843  v_val = (*pair_iter)[1].vert;
844  BLI_ghash_insert(r_targetmap, v_key, v_val);
845  }
846 
855  pair_iter = &pair_array[0];
856  for (i = 0; i < pair_len; i++, pair_iter++) {
857  v_key = (*pair_iter)[0].vert;
858  v_val = (*pair_iter)[1].vert;
859  BMVert *v_target;
860  while ((v_target = BLI_ghash_lookup(r_targetmap, v_val))) {
861  v_val = v_target;
862  }
863  if (v_val != (*pair_iter)[1].vert) {
864  BMVert **v_val_p = (BMVert **)BLI_ghash_lookup_p(r_targetmap, v_key);
865  *v_val_p = (*pair_iter)[1].vert = v_val;
866  }
867  if (split_faces) {
868  /* The vertex index indicates its position in the pair_array flat. */
869  BM_elem_index_set(v_key, i * 2);
870  BM_elem_index_set(v_val, i * 2 + 1);
871  }
872  }
873 
874  if (split_faces) {
875  BMEdge **edgenet = NULL;
876  int edgenet_alloc_len = 0;
877 
878  struct EDBMSplitElem *pair_flat = (struct EDBMSplitElem *)&pair_array[0];
879  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
881  /* Edge out of context or already tested. */
882  continue;
883  }
884 
885  BMVert *va, *vb, *va_dest = NULL;
886  va = e->v1;
887  vb = e->v2;
888 
889  int v_cut = BM_elem_index_get(va);
890  int v_cut_other = BM_elem_index_get(vb);
891  if (v_cut == -1 && v_cut_other == -1) {
893  /* Edge out of context. */
895  }
896  continue;
897  }
898 
899  /* Tag to avoid testing again. */
901 
902  if (v_cut == -1) {
903  SWAP(BMVert *, va, vb);
904  v_cut = v_cut_other;
905  v_cut_other = -1;
906  }
907 
908  /* `v_cut` indicates the other vertex within the `pair_array`. */
909  v_cut += v_cut % 2 ? -1 : 1;
910  va_dest = pair_flat[v_cut].vert;
911 
912  if (BM_vert_pair_share_face_check(va, va_dest)) {
913  /* Vert par acts on the same face.
914  * Although there are cases like this where the face can be split,
915  * for efficiency it is better to ignore then. */
916  continue;
917  }
918 
919  BMFace *best_face = NULL;
920  BMVert *v_other_dest, *v_other = vb;
921  BMEdge *e_net = e;
922  int edgenet_len = 0;
923  while (true) {
924  if (v_cut_other != -1) {
925  v_cut_other += v_cut_other % 2 ? -1 : 1;
926  v_other_dest = pair_flat[v_cut_other].vert;
927 
928  if (BM_vert_pair_share_face_check(v_other, v_other_dest)) {
929  /* Vert par acts on the same face.
930  * Although there are cases like this where the face can be split,
931  * for efficiency and to avoid complications, it is better to ignore these cases.
932  */
933  break;
934  }
935  }
936  else {
937  v_other_dest = v_other;
938  }
939 
940  if (va_dest == v_other_dest) {
941  /* Edge/Edgenet to vertex - we can't split the face. */
942  break;
943  }
944  if (edgenet_len == 0 && BM_edge_exists(va_dest, v_other_dest)) {
945  /* Edge to edge - no need to detect face. */
946  break;
947  }
948 
949  if (edgenet_alloc_len == edgenet_len) {
950  edgenet_alloc_len = (edgenet_alloc_len + 1) * 2;
951  edgenet = MEM_reallocN(edgenet, (edgenet_alloc_len) * sizeof(*edgenet));
952  }
953  edgenet[edgenet_len++] = e_net;
954 
955  best_face = bm_vert_pair_best_face_get(
956  va_dest, v_other_dest, edgenet, edgenet_len, dist);
957 
958  if (best_face) {
959  if ((va_dest != va) && !BM_edge_exists(va_dest, va)) {
967  e_net = edgenet[0];
968  if (edgenet_len > 1) {
969  vb = BM_edge_other_vert(e_net, va);
970  }
971  else {
972  vb = v_other_dest;
973  }
974  edgenet[0] = BM_edge_create(bm, va_dest, vb, e_net, BM_CREATE_NOP);
975  }
976  if ((edgenet_len > 1) && (v_other_dest != v_other) &&
977  !BM_edge_exists(v_other_dest, v_other)) {
985  e_net = edgenet[edgenet_len - 1];
986  edgenet[edgenet_len - 1] = BM_edge_create(
987  bm, v_other_dest, BM_edge_other_vert(e_net, v_other), e_net, BM_CREATE_NOP);
988  }
989  break;
990  }
991 
992  BMEdge *e_test = e_net, *e_next = NULL;
993  while ((e_test = BM_DISK_EDGE_NEXT(e_test, v_other)) != (e_net)) {
994  if (!BM_edge_is_wire(e_test)) {
995  if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) {
996  continue;
997  }
998  if (!BM_elem_flag_test(e_test->v1, BM_ELEM_TAG) &&
999  !BM_elem_flag_test(e_test->v2, BM_ELEM_TAG)) {
1000  continue;
1001  }
1002  /* Avoids endless loop. */
1004  }
1005  else if (!BM_edge_is_wire(e_net)) {
1006  continue;
1007  }
1008  e_next = e_test;
1009  break;
1010  }
1011 
1012  if (e_next == NULL) {
1013  break;
1014  }
1015 
1016  e_net = e_next;
1017  v_other = BM_edge_other_vert(e_net, v_other);
1018  if (v_other == va) {
1019  /* Endless loop. */
1020  break;
1021  }
1022  v_cut_other = BM_elem_index_get(v_other);
1023  }
1024 
1025  if (best_face) {
1026  BMFace **face_arr = NULL;
1027  int face_arr_len = 0;
1028  BM_face_split_edgenet(bm, best_face, edgenet, edgenet_len, &face_arr, &face_arr_len);
1029  if (face_arr) {
1030  /* Update the new faces normal.
1031  * Normal is necessary to obtain the best face for edgenet */
1032  while (face_arr_len--) {
1033  BM_face_normal_update(face_arr[face_arr_len]);
1034  }
1035  MEM_freeN(face_arr);
1036  }
1037  }
1038  }
1039 
1040  if (edgenet) {
1041  MEM_freeN(edgenet);
1042  }
1043  }
1044  ok = true;
1045  }
1046  }
1047 
1048  for (i = BLI_STACK_PAIR_LEN; i--;) {
1049  if (pair_stack[i]) {
1050  BLI_stack_free(pair_stack[i]);
1051  }
1052  }
1053  if (pair_array) {
1054  MEM_freeN(pair_array);
1055  }
1056 
1057  return ok;
1058 }
1059 
typedef float(TangentPoint)[2]
#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_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:830
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
@ BVH_OVERLAP_USE_THREADING
Definition: BLI_kdopbvh.h:93
BVHTreeOverlap * BLI_bvhtree_overlap_ex(const BVHTree *tree1, const BVHTree *tree2, uint *r_overlap_tot, BVHTree_OverlapCallback callback, void *userdata, const uint max_interactions, const int flag)
Definition: BLI_kdopbvh.c:1301
void BLI_bvhtree_balance(BVHTree *tree)
Definition: BLI_kdopbvh.c:956
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
Definition: BLI_kdopbvh.c:873
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:945
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
Definition: BLI_kdopbvh.c:998
int BLI_bvhtree_overlap_thread_num(const BVHTree *tree)
Definition: BLI_kdopbvh.c:1272
bool(* BVHTree_OverlapCallback)(void *userdata, int index_a, int index_b, int thread)
Definition: BLI_kdopbvh.h:120
MINLINE float square_f(float a)
bool isect_ray_ray_v3(const float ray_origin_a[3], const float ray_direction_a[3], const float ray_origin_b[3], const float ray_direction_b[3], float *r_lambda_a, float *r_lambda_b)
Definition: math_geom.c:3210
bool isect_ray_ray_epsilon_v3(const float ray_origin_a[3], const float ray_direction_a[3], const float ray_origin_b[3], const float ray_direction_b[3], const float epsilon, float *r_lambda_a, float *r_lambda_b)
Definition: math_geom.c:3174
float ray_point_factor_v3_ex(const float p[3], const float ray_origin[3], const float ray_direction[3], const float epsilon, const float fallback)
Definition: math_geom.c:3408
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
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])
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
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
void BLI_qsort_r(void *a, size_t n, size_t es, BLI_sort_cmp_t cmp, void *thunk)
Definition: sort.c:95
void BLI_stack_pop_n_reverse(BLI_Stack *stack, void *dst, unsigned int n) ATTR_NONNULL()
Definition: stack.c:208
void * BLI_stack_push_r(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:127
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:285
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:114
#define BLI_stack_new(esize, descr)
unsigned int uint
Definition: BLI_sys_types.h:83
#define SWAP(type, a, b)
#define IN_RANGE(a, b, c)
#define UNUSED(x)
#define ELEM(...)
#define IN_RANGE_INCL(a, b, c)
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x)
#define BM_DISK_EDGE_NEXT(e, v)
Definition: bmesh_class.h:556
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
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_NOP
Definition: bmesh_core.h:27
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:29
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:125
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
#define KDOP_TREE_TYPE
bool BM_mesh_intersect_edges(BMesh *bm, const char hflag, const float dist, const bool split_faces, GHash *r_targetmap)
static bool bm_vertxvert_self_isect_cb(void *userdata, int index_a, int index_b, int thread)
static void bm_vert_pair_elem_setup_ex(BMVert *v, struct EDBMSplitElem *r_pair_elem)
static bool bm_edgexvert_isect_impl(BMVert *v, BMEdge *e, const float co[3], const float dir[3], float lambda, float data_dist_sq, int *data_cut_edges_len, struct EDBMSplitElem r_pair[2])
static bool bm_vert_pair_share_best_splittable_face_cb(BMFace *f, BMLoop *l_a, BMLoop *l_b, void *userdata)
static bool bm_edgexedge_self_isect_cb(void *userdata, int index_a, int index_b, int thread)
static bool bm_edgexedge_isect_impl(struct EDBMSplitData *data, BMEdge *e_a, BMEdge *e_b, const float co_a[3], const float dir_a[3], const float co_b[3], const float dir_b[3], float lambda_a, float lambda_b, struct EDBMSplitElem r_pair[2])
#define KDOP_AXIS_LEN
static bool bm_vert_pair_share_splittable_face_cb(BMFace *UNUSED(f), BMLoop *l_a, BMLoop *l_b, void *userdata)
static int sort_cmp_by_lambda_cb(const void *index1_v, const void *index2_v, void *keys_v)
#define EDGE_REMAIN_TO_TEST
#define BLI_STACK_PAIR_LEN
static bool bm_vertxvert_isect_cb(void *userdata, int index_a, int index_b, int thread)
#define EDGE_ACT_TO_TEST
static BMFace * bm_vert_pair_best_face_get(BMVert *v_a, BMVert *v_b, BMEdge **edgenet, const int edgenet_len, const float epsilon)
static bool bm_edgexedge_isect_cb(void *userdata, int index_a, int index_b, int thread)
static bool bm_edgexvert_isect_cb(void *userdata, int index_a, int index_b, int thread)
static void bm_elemxelem_bvhtree_overlap(const BVHTree *tree1, const BVHTree *tree2, BVHTree_OverlapCallback callback, struct EDBMSplitData *data, BLI_Stack **pair_stack)
static void bm_edge_pair_elem_setup(BMEdge *e, float lambda, int *r_data_cut_edges_len, struct EDBMSplitElem *r_pair_elem)
#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_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_VERTS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2276
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:104
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:98
BMVert * BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
Edge Split.
Definition: bmesh_mods.c:591
bool BM_face_point_inside_test(const BMFace *f, const float co[3])
void BM_face_normal_update(BMFace *f)
bool BM_face_split_edgenet(BMesh *bm, BMFace *f, BMEdge **edge_net, const int edge_net_len, BMFace ***r_face_arr, int *r_face_arr_len)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1995
bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:193
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
Definition: bmesh_query.c:555
bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1358
BMFace * BM_vert_pair_shared_face_cb(BMVert *v_a, BMVert *v_b, const bool allow_adjacent, bool(*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata), void *user_data, BMLoop **r_l_a, BMLoop **r_l_b)
Definition: bmesh_query.c:230
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
ATTR_WARN_UNUSED_RESULT const BMVert * v
bool closest(btVector3 &v)
DEGForeachIDComponentCallback callback
int count
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static double epsilon
#define min(a, b)
Definition: sort.c:51
BMVert * v1
Definition: bmesh_class.h:134
BMVert * v2
Definition: bmesh_class.h:134
BMHeader head
Definition: bmesh_class.h:255
float no[3]
Definition: bmesh_class.h:280
char htype
Definition: bmesh_class.h:76
int index
Definition: bmesh_class.h:73
struct BMVert * v
Definition: bmesh_class.h:165
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
BMHeader head
Definition: bmesh_class.h:97
char elem_index_dirty
Definition: bmesh_class.h:305
BLI_Stack ** pair_stack
float max
ccl_device_inline int as_int(uint i)
Definition: util_math.h:172
ccl_device_inline float dot(const float2 &a, const float2 &b)