Blender  V2.93
bmo_connect_concave.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 
31 #include "MEM_guardedalloc.h"
32 
33 #include "BLI_alloca.h"
34 #include "BLI_heap.h"
35 #include "BLI_linklist.h"
36 #include "BLI_math.h"
37 #include "BLI_memarena.h"
38 #include "BLI_polyfill_2d.h"
40 #include "BLI_utildefines.h"
41 
42 #include "bmesh.h"
43 
44 #include "intern/bmesh_operators_private.h" /* own include */
45 
46 #define EDGE_OUT (1 << 0)
47 #define FACE_OUT (1 << 1)
48 
49 static int bm_edge_length_cmp(const void *a_, const void *b_)
50 {
51  const BMEdge *e_a = *(const void **)a_;
52  const BMEdge *e_b = *(const void **)b_;
53 
54  int e_a_concave = ((BM_elem_flag_test(e_a->v1, BM_ELEM_TAG)) &&
56  int e_b_concave = ((BM_elem_flag_test(e_b->v1, BM_ELEM_TAG)) &&
58 
59  /* merge edges between concave edges last since these
60  * are most likely to remain and be the main dividers */
61  if (e_a_concave < e_b_concave) {
62  return -1;
63  }
64  if (e_a_concave > e_b_concave) {
65  return 1;
66  }
67 
68  /* otherwise shortest edges last */
69  const float e_a_len = BM_edge_calc_length_squared(e_a);
70  const float e_b_len = BM_edge_calc_length_squared(e_b);
71  if (e_a_len < e_b_len) {
72  return 1;
73  }
74  if (e_a_len > e_b_len) {
75  return -1;
76  }
77  return 0;
78 }
79 
81  BMFace *f_base,
82  const float eps,
83 
84  MemArena *pf_arena,
85  struct Heap *pf_heap)
86 {
87  const int f_base_len = f_base->len;
88  int faces_array_tot = f_base_len - 3;
89  int edges_array_tot = f_base_len - 3;
90  BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
91  BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot);
92  const int quad_method = 0, ngon_method = 0; /* beauty */
93  LinkNode *faces_double = NULL;
94 
95  float normal[3];
96  BLI_assert(f_base->len > 3);
97 
98  copy_v3_v3(normal, f_base->no);
99 
101  f_base,
102  faces_array,
103  &faces_array_tot,
104  edges_array,
105  &edges_array_tot,
106  &faces_double,
107  quad_method,
108  ngon_method,
109  false,
110  pf_arena,
111  pf_heap);
112 
113  BLI_assert(edges_array_tot <= f_base_len - 3);
114 
115  if (faces_array_tot) {
116  int i;
117  for (i = 0; i < faces_array_tot; i++) {
118  BMFace *f = faces_array[i];
120  }
121  }
122  BMO_face_flag_enable(bm, f_base, FACE_OUT);
123 
124  if (edges_array_tot) {
125  int i;
126 
127  qsort(edges_array, edges_array_tot, sizeof(*edges_array), bm_edge_length_cmp);
128 
129  for (i = 0; i < edges_array_tot; i++) {
130  BMLoop *l_pair[2];
131  BMEdge *e = edges_array[i];
133 
134  if (BM_edge_is_contiguous(e) && BM_edge_loop_pair(e, &l_pair[0], &l_pair[1])) {
135  bool ok = true;
136  int j;
137  for (j = 0; j < 2; j++) {
138  BMLoop *l = l_pair[j];
139 
140  /* check that merging the edge (on this side)
141  * wouldn't result in a convex face-loop.
142  *
143  * This is the (l->next, l->prev) we would have once joined.
144  */
145  float cross[3];
146  cross_tri_v3(cross, l->v->co, l->radial_next->next->next->v->co, l->prev->v->co);
147 
148  if (dot_v3v3(cross, normal) <= eps) {
149  ok = false;
150  break;
151  }
152  }
153 
154  if (ok) {
155  BMFace *f_new, *f_pair[2] = {l_pair[0]->f, l_pair[1]->f};
156  f_new = BM_faces_join(bm, f_pair, 2, true);
157  if (f_new) {
159  }
160  }
161  }
162  }
163  }
164 
165  BLI_heap_clear(pf_heap, NULL);
166 
167  while (faces_double) {
168  LinkNode *next = faces_double->next;
169  BM_face_kill(bm, faces_double->link);
170  MEM_freeN(faces_double);
171  faces_double = next;
172  }
173 
174  return true;
175 }
176 
178 {
179  bool is_concave = false;
180  if (f->len > 3) {
181  const BMLoop *l_iter, *l_first;
182 
183  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
184  do {
185  if (BM_loop_is_convex(l_iter) == false) {
186  is_concave = true;
188  }
189  else {
191  }
192  } while ((l_iter = l_iter->next) != l_first);
193  }
194  return is_concave;
195 }
196 
198 {
199  BMOIter siter;
200  BMFace *f;
201  bool changed = false;
202 
203  MemArena *pf_arena;
204  Heap *pf_heap;
205 
206  pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
208 
209  BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
210  if (f->len > 3 && bm_face_convex_tag_verts(f)) {
211  if (bm_face_split_by_concave(bm, f, FLT_EPSILON, pf_arena, pf_heap)) {
212  changed = true;
213  }
214  }
215  }
216 
217  if (changed) {
220  }
221 
222  BLI_memarena_free(pf_arena);
223  BLI_heap_free(pf_heap, NULL);
224 }
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:58
A min-heap / priority queue ADT.
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1)
Definition: BLI_heap.c:221
Heap * BLI_heap_new_ex(unsigned int tot_reserve) ATTR_WARN_UNUSED_RESULT
Definition: BLI_heap.c:201
void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1)
Definition: BLI_heap.c:243
void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:36
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 BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
#define BLI_POLYFILL_ARENA_SIZE
#define BLI_POLYFILL_ALLOC_NGON_RESERVE
Read Guarded memory(de)allocation.
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
BMFace * BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
Join Connected Faces.
Definition: bmesh_core.c:1209
void BM_face_kill(BMesh *bm, BMFace *f)
Definition: bmesh_core.c:881
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:29
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
ATTR_WARN_UNUSED_RESULT BMesh * bm
#define BMO_edge_flag_enable(bm, e, oflag)
#define BMO_face_flag_enable(bm, e, oflag)
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **r_faces_new, int *r_faces_new_tot, BMEdge **r_edges_new, int *r_edges_new_tot, LinkNode **r_faces_double, const int quad_method, const int ngon_method, const bool use_tag, MemArena *pf_arena, struct Heap *pf_heap)
BMESH TRIANGULATE FACE.
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
Definition: bmesh_query.c:753
float BM_edge_calc_length_squared(const BMEdge *e)
Definition: bmesh_query.c:721
bool BM_loop_is_convex(const BMLoop *l)
Definition: bmesh_query.c:1513
BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
static bool bm_face_convex_tag_verts(BMFace *f)
#define FACE_OUT
#define EDGE_OUT
void bmo_connect_verts_concave_exec(BMesh *bm, BMOperator *op)
static bool bm_face_split_by_concave(BMesh *bm, BMFace *f_base, const float eps, MemArena *pf_arena, struct Heap *pf_heap)
static int bm_edge_length_cmp(const void *a_, const void *b_)
IconTextureDrawCall normal
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static ulong * next
const btScalar eps
Definition: poly34.cpp:11
BMVert * v1
Definition: bmesh_class.h:134
BMVert * v2
Definition: bmesh_class.h:134
int len
Definition: bmesh_class.h:279
float no[3]
Definition: bmesh_class.h:280
struct BMVert * v
Definition: bmesh_class.h:165
struct BMLoop * radial_next
Definition: bmesh_class.h:216
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
float co[3]
Definition: bmesh_class.h:99
Definition: BLI_heap.c:57
void * link
Definition: BLI_linklist.h:40
struct LinkNode * next
Definition: BLI_linklist.h:39
__forceinline avxf cross(const avxf &a, const avxf &b)
Definition: util_avxf.h:119