Blender  V2.93
bmo_connect_pair.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_heap_simple.h"
26 #include "BLI_math.h"
27 #include "BLI_utildefines.h"
28 
29 #include "bmesh.h"
30 
31 #include "intern/bmesh_operators_private.h" /* own include */
32 
33 #include "BLI_mempool.h"
34 
54 #define CONNECT_EPS 0.0001f
55 #define VERT_OUT 1
56 #define VERT_EXCLUDE 2
57 
58 /* typically hidden faces */
59 #define FACE_EXCLUDE 2
60 
61 /* any element we've walked over (only do it once!) */
62 #define ELE_TOUCHED 4
63 
64 #define FACE_WALK_TEST(f) \
65  (CHECK_TYPE_INLINE(f, BMFace *), BMO_face_flag_test(pc->bm_bmoflag, f, FACE_EXCLUDE) == 0)
66 #define VERT_WALK_TEST(v) \
67  (CHECK_TYPE_INLINE(v, BMVert *), BMO_vert_flag_test(pc->bm_bmoflag, v, VERT_EXCLUDE) == 0)
68 
69 #if 0
70 # define ELE_TOUCH_TEST(e) \
71  (CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *), \
72  BMO_elem_flag_test(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED))
73 #endif
74 #define ELE_TOUCH_MARK(e) \
75  { \
76  CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *); \
77  BMO_elem_flag_enable(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED); \
78  } \
79  ((void)0)
80 
81 #define ELE_TOUCH_TEST_VERT(v) BMO_vert_flag_test(pc->bm_bmoflag, v, ELE_TOUCHED)
82 // #define ELE_TOUCH_MARK_VERT(v) BMO_vert_flag_enable(pc->bm_bmoflag, (BMElemF *)v, ELE_TOUCHED)
83 
84 #define ELE_TOUCH_TEST_EDGE(e) BMO_edge_flag_test(pc->bm_bmoflag, e, ELE_TOUCHED)
85 // #define ELE_TOUCH_MARK_EDGE(e) BMO_edge_flag_enable(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED)
86 
87 // #define ELE_TOUCH_TEST_FACE(f) BMO_face_flag_test(pc->bm_bmoflag, f, ELE_TOUCHED)
88 // #define ELE_TOUCH_MARK_FACE(f) BMO_face_flag_enable(pc->bm_bmoflag, (BMElemF *)f, ELE_TOUCHED)
89 
90 // #define DEBUG_PRINT
91 
92 typedef struct PathContext {
94  float matrix[3][3];
95  float axis_sep;
96 
97  /* only to access BMO flags */
99 
101 
104 
108 typedef struct PathLink {
109  struct PathLink *next;
110  BMElem *ele; /* edge or vert */
111  BMElem *ele_from; /* edge or face we came from (not 'next->ele') */
113 
114 typedef struct PathLinkState {
115  /* chain of links */
117 
118  /* length along links */
119  float dist;
120  float co_prev[3];
122 
138 typedef struct MinDistDir {
139  /* distance in both directions (FLT_MAX == uninitialized) */
140  float dist_min[2];
141  /* direction of the first intersection found */
142  float dir[3];
144 
145 #define MIN_DIST_DIR_INIT \
146  { \
147  { \
148  FLT_MAX, FLT_MAX \
149  } \
150  }
151 
152 static int min_dist_dir_test(MinDistDir *mddir, const float dist_dir[3], const float dist_sq)
153 {
154 
155  if (mddir->dist_min[0] == FLT_MAX) {
156  return 0;
157  }
158  if (dot_v3v3(dist_dir, mddir->dir) > 0.0f) {
159  if (dist_sq < mddir->dist_min[0]) {
160  return 0;
161  }
162  }
163  else {
164  if (dist_sq < mddir->dist_min[1]) {
165  return 1;
166  }
167  }
168 
169  return -1;
170 }
171 
172 static void min_dist_dir_update(MinDistDir *dist, const float dist_dir[3])
173 {
174  if (dist->dist_min[0] == FLT_MAX) {
175  copy_v3_v3(dist->dir, dist_dir);
176  }
177 }
178 
181 static int state_isect_co_pair(const PathContext *pc, const float co_a[3], const float co_b[3])
182 {
183  const float diff_a = dot_m3_v3_row_x((float(*)[3])pc->matrix, co_a) - pc->axis_sep;
184  const float diff_b = dot_m3_v3_row_x((float(*)[3])pc->matrix, co_b) - pc->axis_sep;
185 
186  const int test_a = (fabsf(diff_a) < CONNECT_EPS) ? 0 : (diff_a < 0.0f) ? -1 : 1;
187  const int test_b = (fabsf(diff_b) < CONNECT_EPS) ? 0 : (diff_b < 0.0f) ? -1 : 1;
188 
189  if ((test_a && test_b) && (test_a != test_b)) {
190  return 1; /* on either side */
191  }
192  return 0;
193 }
194 
195 static int state_isect_co_exact(const PathContext *pc, const float co[3])
196 {
197  const float diff = dot_m3_v3_row_x((float(*)[3])pc->matrix, co) - pc->axis_sep;
198  return (fabsf(diff) <= CONNECT_EPS);
199 }
200 
201 static float state_calc_co_pair_fac(const PathContext *pc,
202  const float co_a[3],
203  const float co_b[3])
204 {
205  float diff_a, diff_b, diff_tot;
206 
207  diff_a = fabsf(dot_m3_v3_row_x((float(*)[3])pc->matrix, co_a) - pc->axis_sep);
208  diff_b = fabsf(dot_m3_v3_row_x((float(*)[3])pc->matrix, co_b) - pc->axis_sep);
209  diff_tot = (diff_a + diff_b);
210  return (diff_tot > FLT_EPSILON) ? (diff_a / diff_tot) : 0.5f;
211 }
212 
213 static void state_calc_co_pair(const PathContext *pc,
214  const float co_a[3],
215  const float co_b[3],
216  float r_co[3])
217 {
218  const float fac = state_calc_co_pair_fac(pc, co_a, co_b);
219  interp_v3_v3v3(r_co, co_a, co_b, fac);
220 }
221 
222 #ifndef NDEBUG
227 static bool state_link_find(const PathLinkState *state, BMElem *ele)
228 {
229  PathLink *link = state->link_last;
231  if (link) {
232  do {
233  if (link->ele == ele) {
234  return true;
235  }
236  } while ((link = link->next));
237  }
238  return false;
239 }
240 #endif
241 
242 static void state_link_add(PathContext *pc, PathLinkState *state, BMElem *ele, BMElem *ele_from)
243 {
244  PathLink *step_new = BLI_mempool_alloc(pc->link_pool);
245  BLI_assert(ele != ele_from);
246  BLI_assert(state_link_find(state, ele) == false);
247 
248  /* never walk onto this again */
249  ELE_TOUCH_MARK(ele);
250 
251 #ifdef DEBUG_PRINT
252  printf("%s: adding to state %p, %.4f - ", __func__, state, state->dist);
253  if (ele->head.htype == BM_VERT) {
254  printf("vert %d, ", BM_elem_index_get(ele));
255  }
256  else if (ele->head.htype == BM_EDGE) {
257  printf("edge %d, ", BM_elem_index_get(ele));
258  }
259  else {
260  BLI_assert(0);
261  }
262 
263  if (ele_from == NULL) {
264  printf("from NULL\n");
265  }
266  else if (ele_from->head.htype == BM_EDGE) {
267  printf("from edge %d\n", BM_elem_index_get(ele_from));
268  }
269  else if (ele_from->head.htype == BM_FACE) {
270  printf("from face %d\n", BM_elem_index_get(ele_from));
271  }
272  else {
273  BLI_assert(0);
274  }
275 #endif
276 
277  /* track distance */
278  {
279  float co[3];
280  if (ele->head.htype == BM_VERT) {
281  copy_v3_v3(co, ((BMVert *)ele)->co);
282  }
283  else if (ele->head.htype == BM_EDGE) {
284  state_calc_co_pair(pc, ((BMEdge *)ele)->v1->co, ((BMEdge *)ele)->v2->co, co);
285  }
286  else {
287  BLI_assert(0);
288  }
289 
290  /* tally distance */
291  if (ele_from) {
292  state->dist += len_v3v3(state->co_prev, co);
293  }
294  copy_v3_v3(state->co_prev, co);
295  }
296 
297  step_new->ele = ele;
298  step_new->ele_from = ele_from;
299  step_new->next = state->link_last;
300  state->link_last = step_new;
301 }
302 
304 {
305  state = MEM_mallocN(sizeof(*state), __func__);
306  *state = *state_orig;
307  return state;
308 }
309 
312  const PathLinkState *state_orig,
313  BMElem *ele,
314  BMElem *ele_from)
315 {
316  const bool is_new = (state_orig->link_last != state->link_last);
317  if (is_new) {
318  state = state_dupe_add(state, state_orig);
319  }
320 
321  state_link_add(pc, state, ele, ele_from);
322 
323  /* after adding a link so we use the updated 'state->dist' */
324  if (is_new) {
326  }
327 
328  return state;
329 }
330 
331 /* walk around the face edges */
334  const PathLinkState *state_orig,
335  BMLoop *l_iter,
336  BMLoop *l_last,
337  MinDistDir *mddir)
338 {
339 
340  BMLoop *l_iter_best[2] = {NULL, NULL};
341  int i;
342 
343  do {
344  if (state_isect_co_pair(pc, l_iter->v->co, l_iter->next->v->co)) {
345  float dist_test;
346  float co_isect[3];
347  float dist_dir[3];
348  int index;
349 
350  state_calc_co_pair(pc, l_iter->v->co, l_iter->next->v->co, co_isect);
351 
352  sub_v3_v3v3(dist_dir, co_isect, state_orig->co_prev);
353  dist_test = len_squared_v3(dist_dir);
354  if ((index = min_dist_dir_test(mddir, dist_dir, dist_test)) != -1) {
355  BMElem *ele_next = (BMElem *)l_iter->e;
356  BMElem *ele_next_from = (BMElem *)l_iter->f;
357 
358  if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
359  (ELE_TOUCH_TEST_EDGE((BMEdge *)ele_next) == false)) {
360  min_dist_dir_update(mddir, dist_dir);
361  mddir->dist_min[index] = dist_test;
362  l_iter_best[index] = l_iter;
363  }
364  }
365  }
366  } while ((l_iter = l_iter->next) != l_last);
367 
368  for (i = 0; i < 2; i++) {
369  if ((l_iter = l_iter_best[i])) {
370  BMElem *ele_next = (BMElem *)l_iter->e;
371  BMElem *ele_next_from = (BMElem *)l_iter->f;
372  state = state_link_add_test(pc, state, state_orig, ele_next, ele_next_from);
373  }
374  }
375 
376  return state;
377 }
378 
379 /* walk around the face verts */
382  const PathLinkState *state_orig,
383  BMLoop *l_iter,
384  BMLoop *l_last,
385  MinDistDir *mddir)
386 {
387  BMLoop *l_iter_best[2] = {NULL, NULL};
388  int i;
389 
390  do {
391  if (state_isect_co_exact(pc, l_iter->v->co)) {
392  float dist_test;
393  const float *co_isect = l_iter->v->co;
394  float dist_dir[3];
395  int index;
396 
397  sub_v3_v3v3(dist_dir, co_isect, state_orig->co_prev);
398  dist_test = len_squared_v3(dist_dir);
399  if ((index = min_dist_dir_test(mddir, dist_dir, dist_test)) != -1) {
400  BMElem *ele_next = (BMElem *)l_iter->v;
401  BMElem *ele_next_from = (BMElem *)l_iter->f;
402 
403  if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
404  (ELE_TOUCH_TEST_VERT((BMVert *)ele_next) == false)) {
405  min_dist_dir_update(mddir, dist_dir);
406  mddir->dist_min[index] = dist_test;
407  l_iter_best[index] = l_iter;
408  }
409  }
410  }
411  } while ((l_iter = l_iter->next) != l_last);
412 
413  for (i = 0; i < 2; i++) {
414  if ((l_iter = l_iter_best[i])) {
415  BMElem *ele_next = (BMElem *)l_iter->v;
416  BMElem *ele_next_from = (BMElem *)l_iter->f;
417  state = state_link_add_test(pc, state, state_orig, ele_next, ele_next_from);
418  }
419  }
420 
421  return state;
422 }
423 
425 {
426  PathLinkState state_orig = *state;
427  BMElem *ele = state->link_last->ele;
428  const void *ele_from = state->link_last->ele_from;
429 
430  if (ele->head.htype == BM_EDGE) {
431  BMEdge *e = (BMEdge *)ele;
432 
433  BMIter liter;
434  BMLoop *l_start;
435 
436  BM_ITER_ELEM (l_start, &liter, e, BM_LOOPS_OF_EDGE) {
437  if ((l_start->f != ele_from) && FACE_WALK_TEST(l_start->f)) {
439  /* very similar to block below */
440  state = state_step__face_edges(pc, state, &state_orig, l_start->next, l_start, &mddir);
442  pc, state, &state_orig, l_start->next->next, l_start, &mddir);
443  }
444  }
445  }
446  else if (ele->head.htype == BM_VERT) {
447  BMVert *v = (BMVert *)ele;
448 
449  /* vert loops */
450  {
451  BMIter liter;
452  BMLoop *l_start;
453 
454  BM_ITER_ELEM (l_start, &liter, v, BM_LOOPS_OF_VERT) {
455  if ((l_start->f != ele_from) && FACE_WALK_TEST(l_start->f)) {
457  /* very similar to block above */
459  pc, state, &state_orig, l_start->next, l_start->prev, &mddir);
460  if (l_start->f->len > 3) {
461  /* adjacent verts are handled in state_step__vert_edges */
463  pc, state, &state_orig, l_start->next->next, l_start->prev, &mddir);
464  }
465  }
466  }
467  }
468 
469  /* vert edges */
470  {
471  BMIter eiter;
472  BMEdge *e;
473  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
474  BMVert *v_other = BM_edge_other_vert(e, v);
475  if (((BMElem *)e != ele_from) && VERT_WALK_TEST(v_other)) {
476  if (state_isect_co_exact(pc, v_other->co)) {
477  BMElem *ele_next = (BMElem *)v_other;
478  BMElem *ele_next_from = (BMElem *)e;
479  if (ELE_TOUCH_TEST_VERT((BMVert *)ele_next) == false) {
480  state = state_link_add_test(pc, state, &state_orig, ele_next, ele_next_from);
481  }
482  }
483  }
484  }
485  }
486  }
487  else {
488  BLI_assert(0);
489  }
490  return (state_orig.link_last != state->link_last);
491 }
492 
496 static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
497 {
498  const float eps = 1e-8f;
499 
500  float basis_dir[3];
501  float basis_tmp[3];
502  float basis_nor[3];
503 
504  sub_v3_v3v3(basis_dir, v_pair[0]->co, v_pair[1]->co);
505  normalize_v3(basis_dir);
506 
507 #if 0
508  add_v3_v3v3(basis_nor, v_pair[0]->no, v_pair[1]->no);
509  cross_v3_v3v3(basis_tmp, basis_nor, basis_dir);
510  cross_v3_v3v3(basis_nor, basis_tmp, basis_dir);
511 #else
512  /* align both normals to the directions before combining */
513  {
514  float basis_nor_a[3];
515  float basis_nor_b[3];
516 
517  /* align normal to direction */
518  project_plane_normalized_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir);
519  project_plane_normalized_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir);
520 
521  /* Don't normalize before combining so as normals approach the direction,
522  * they have less effect (T46784). */
523 
524  /* combine the normals */
525  /* for flipped faces */
526  if (dot_v3v3(basis_nor_a, basis_nor_b) < 0.0f) {
527  negate_v3(basis_nor_b);
528  }
529  add_v3_v3v3(basis_nor, basis_nor_a, basis_nor_b);
530  }
531 #endif
532 
533  /* get third axis */
534  normalize_v3(basis_nor);
535  cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
536 
537  /* Try get the axis from surrounding faces, fallback to 'ortho_v3_v3' */
538  if (UNLIKELY(normalize_v3(basis_tmp) < eps)) {
539  /* vertex normals are directly opposite */
540 
541  /* find the loop with the lowest angle */
542  struct {
543  float nor[3];
544  float angle_cos;
545  } axis_pair[2];
546  int i;
547 
548  for (i = 0; i < 2; i++) {
549  BMIter liter;
550  BMLoop *l;
551 
552  zero_v2(axis_pair[i].nor);
553  axis_pair[i].angle_cos = -FLT_MAX;
554 
555  BM_ITER_ELEM (l, &liter, v_pair[i], BM_LOOPS_OF_VERT) {
556  float basis_dir_proj[3];
557  float angle_cos_test;
558 
559  /* project basis dir onto the normal to find its closest angle */
560  project_plane_normalized_v3_v3v3(basis_dir_proj, basis_dir, l->f->no);
561 
562  if (normalize_v3(basis_dir_proj) > eps) {
563  angle_cos_test = dot_v3v3(basis_dir_proj, basis_dir);
564 
565  if (angle_cos_test > axis_pair[i].angle_cos) {
566  axis_pair[i].angle_cos = angle_cos_test;
567  copy_v3_v3(axis_pair[i].nor, basis_dir_proj);
568  }
569  }
570  }
571  }
572 
573  /* create a new 'basis_nor' from the best direction.
574  * note: we could add the directions,
575  * but this more often gives 45d rotated matrix, so just use the best one. */
576  copy_v3_v3(basis_nor, axis_pair[axis_pair[0].angle_cos < axis_pair[1].angle_cos].nor);
577  project_plane_normalized_v3_v3v3(basis_nor, basis_nor, basis_dir);
578 
579  cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
580 
581  /* last resort, pick _any_ ortho axis */
582  if (UNLIKELY(normalize_v3(basis_tmp) < eps)) {
583  ortho_v3_v3(basis_nor, basis_dir);
584  normalize_v3(basis_nor);
585  cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
586  normalize_v3(basis_tmp);
587  }
588  }
589 
590  copy_v3_v3(r_unit_mat[0], basis_tmp);
591  copy_v3_v3(r_unit_mat[1], basis_dir);
592  copy_v3_v3(r_unit_mat[2], basis_nor);
593  if (invert_m3(r_unit_mat) == false) {
594  unit_m3(r_unit_mat);
595  }
596 }
597 
599 {
600  BMOpSlot *op_verts_slot = BMO_slot_get(op->slots_in, "verts");
601 
602  PathContext pc;
603  PathLinkState state_best = {NULL};
604 
605  if (op_verts_slot->len != 2) {
606  /* fail! */
607  return;
608  }
609 
610  pc.bm_bmoflag = bm;
611  pc.v_a = ((BMVert **)op_verts_slot->data.p)[0];
612  pc.v_b = ((BMVert **)op_verts_slot->data.p)[1];
613 
614  /* fail! */
615  if (!(pc.v_a && pc.v_b)) {
616  return;
617  }
618 
619 #ifdef DEBUG_PRINT
620  printf("%s: v_a: %d\n", __func__, BM_elem_index_get(pc.v_a));
621  printf("%s: v_b: %d\n", __func__, BM_elem_index_get(pc.v_b));
622 #endif
623 
624  /* tag so we won't touch ever (typically hidden faces) */
627 
628  /* setup context */
629  {
630  pc.states = BLI_heapsimple_new();
631  pc.link_pool = BLI_mempool_create(sizeof(PathLink), 0, 512, BLI_MEMPOOL_NOP);
632  }
633 
634  /* calculate matrix */
635  {
637  pc.axis_sep = dot_m3_v3_row_x(pc.matrix, pc.v_a->co);
638  }
639 
640  /* add first vertex */
641  {
643  state = MEM_callocN(sizeof(*state), __func__);
644  state_link_add(&pc, state, (BMElem *)pc.v_a, NULL);
646  }
647 
648  while (!BLI_heapsimple_is_empty(pc.states)) {
649 
650 #ifdef DEBUG_PRINT
651  printf("\n%s: stepping %u\n", __func__, BLI_heapsimple_len(pc.states));
652 #endif
653 
654  while (!BLI_heapsimple_is_empty(pc.states)) {
656 
657  /* either we insert this into 'pc.states' or its freed */
658  bool continue_search;
659 
660  if (state->link_last->ele == (BMElem *)pc.v_b) {
661  /* pass, wait until all are found */
662 #ifdef DEBUG_PRINT
663  printf("%s: state %p loop found %.4f\n", __func__, state, state->dist);
664 #endif
665  state_best = *state;
666 
667  /* we're done, exit all loops */
669  continue_search = false;
670  }
671  else if (state_step(&pc, state)) {
672  continue_search = true;
673  }
674  else {
675  /* didn't reach the end, remove it,
676  * links are shared between states so just free the link_pool at the end */
677 
678 #ifdef DEBUG_PRINT
679  printf("%s: state %p removed\n", __func__, state);
680 #endif
681  continue_search = false;
682  }
683 
684  if (continue_search) {
686  }
687  else {
688  MEM_freeN(state);
689  }
690  }
691  }
692 
693  if (state_best.link_last) {
694  PathLink *link;
695 
696  /* find the best state */
697  link = state_best.link_last;
698  do {
699  if (link->ele->head.htype == BM_EDGE) {
700  BMEdge *e = (BMEdge *)link->ele;
701  BMVert *v_new;
702  float e_fac = state_calc_co_pair_fac(&pc, e->v1->co, e->v2->co);
703  v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac);
705  }
706  else if (link->ele->head.htype == BM_VERT) {
707  BMVert *v = (BMVert *)link->ele;
709  }
710  else {
711  BLI_assert(0);
712  }
713  } while ((link = link->next));
714  }
715 
718 
720 
722 
723 #if 1
724  if (state_best.link_last) {
727  &op_sub,
728  0,
729  "connect_verts verts=%fv faces_exclude=%s check_degenerate=%b",
730  VERT_OUT,
731  op,
732  "faces_exclude",
733  true);
734  BMO_op_exec(bm, &op_sub);
735  BMO_slot_copy(&op_sub, slots_out, "edges.out", op, slots_out, "edges.out");
737  }
738 #endif
739 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
A min-heap / priority queue ADT.
void BLI_heapsimple_clear(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1)
void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1)
HeapSimple * BLI_heapsimple_new(void) ATTR_WARN_UNUSED_RESULT
void * BLI_heapsimple_pop_min(HeapSimple *heap) ATTR_NONNULL(1)
bool BLI_heapsimple_is_empty(const HeapSimple *heap) ATTR_NONNULL(1)
uint BLI_heapsimple_len(const HeapSimple *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_heapsimple_insert(HeapSimple *heap, float value, void *ptr) ATTR_NONNULL(1)
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
bool invert_m3(float R[3][3])
Definition: math_matrix.c:1152
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
Definition: math_vector.c:757
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
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])
void ortho_v3_v3(float out[3], const float v[3])
Definition: math_vector.c:875
MINLINE void negate_v3(float r[3])
MINLINE void zero_v2(float r[2])
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:77
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int totelem, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_mempool.c:268
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mempool.c:334
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:757
#define UNLIKELY(x)
#define ELEM(...)
_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.
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_EDGE
@ BM_EDGES_OF_VERT
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMVert * BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
Edge Split.
Definition: bmesh_mods.c:591
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.
#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_slot_copy(op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst)
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.
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define ELE_TOUCH_TEST_VERT(v)
static int state_isect_co_exact(const PathContext *pc, const float co[3])
#define CONNECT_EPS
struct MinDistDir MinDistDir
#define VERT_EXCLUDE
static PathLinkState * state_dupe_add(PathLinkState *state, const PathLinkState *state_orig)
struct PathContext PathContext
#define FACE_WALK_TEST(f)
static int min_dist_dir_test(MinDistDir *mddir, const float dist_dir[3], const float dist_sq)
static PathLinkState * state_link_add_test(PathContext *pc, PathLinkState *state, const PathLinkState *state_orig, BMElem *ele, BMElem *ele_from)
#define VERT_OUT
#define VERT_WALK_TEST(v)
#define FACE_EXCLUDE
static bool state_step(PathContext *pc, PathLinkState *state)
static PathLinkState * state_step__face_edges(PathContext *pc, PathLinkState *state, const PathLinkState *state_orig, BMLoop *l_iter, BMLoop *l_last, MinDistDir *mddir)
void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
struct PathLinkState PathLinkState
static PathLinkState * state_step__face_verts(PathContext *pc, PathLinkState *state, const PathLinkState *state_orig, BMLoop *l_iter, BMLoop *l_last, MinDistDir *mddir)
static float state_calc_co_pair_fac(const PathContext *pc, const float co_a[3], const float co_b[3])
static void min_dist_dir_update(MinDistDir *dist, const float dist_dir[3])
static bool state_link_find(const PathLinkState *state, BMElem *ele)
#define ELE_TOUCH_MARK(e)
#define ELE_TOUCH_TEST_EDGE(e)
static int state_isect_co_pair(const PathContext *pc, const float co_a[3], const float co_b[3])
struct PathLink PathLink
static void state_link_add(PathContext *pc, PathLinkState *state, BMElem *ele, BMElem *ele_from)
static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
#define MIN_DIST_DIR_INIT
static void state_calc_co_pair(const PathContext *pc, const float co_a[3], const float co_b[3], float r_co[3])
static double op_sub(double a, double b)
uint nor
#define fabsf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong state[N]
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
const btScalar eps
Definition: poly34.cpp:11
BMHeader head
Definition: bmesh_class.h:255
int len
Definition: bmesh_class.h:279
float no[3]
Definition: bmesh_class.h:280
char htype
Definition: bmesh_class.h:76
struct BMVert * v
Definition: bmesh_class.h:165
struct BMEdge * e
Definition: bmesh_class.h:176
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
union BMOpSlot::@139 data
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
float co[3]
Definition: bmesh_class.h:99
float dist_min[2]
BLI_mempool * link_pool
float matrix[3][3]
BMesh * bm_bmoflag
HeapSimple * states
struct PathLink * link_last