Blender  V2.93
bmo_hull.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 #ifdef WITH_BULLET
24 
25 # include "MEM_guardedalloc.h"
26 
27 # include "BLI_array.h"
28 # include "BLI_listbase.h"
29 # include "BLI_math.h"
30 
31 # include "RBI_hull_api.h"
32 
33 /* XXX: using 128 for totelem and pchunk of mempool, no idea what good
34  * values would be though */
35 
36 # include "bmesh.h"
37 
38 # include "intern/bmesh_operators_private.h" /* own include */
39 
40 /* Internal operator flags */
41 typedef enum {
42  HULL_FLAG_INPUT = (1 << 0),
43 
44  HULL_FLAG_INTERIOR_ELE = (1 << 1),
45  HULL_FLAG_OUTPUT_GEOM = (1 << 2),
46 
47  HULL_FLAG_DEL = (1 << 3),
48  HULL_FLAG_HOLE = (1 << 4),
49 } HullFlags;
50 
51 /* Store hull triangles separate from BMesh faces until the end; this
52  * way we don't have to worry about cleaning up extraneous edges or
53  * incorrectly deleting existing geometry. */
54 typedef struct HullTriangle {
55  BMVert *v[3];
56  float no[3];
57  int skip;
58 } HullTriangle;
59 
60 /*************************** Hull Triangles ***************************/
61 
62 static void hull_add_triangle(
63  BMesh *bm, BLI_mempool *hull_triangles, BMVert *v1, BMVert *v2, BMVert *v3)
64 {
65  HullTriangle *t;
66  int i;
67 
68  t = BLI_mempool_calloc(hull_triangles);
69  t->v[0] = v1;
70  t->v[1] = v2;
71  t->v[2] = v3;
72 
73  /* Mark triangles vertices as not interior */
74  for (i = 0; i < 3; i++) {
75  BMO_vert_flag_disable(bm, t->v[i], HULL_FLAG_INTERIOR_ELE);
76  }
77 
78  normal_tri_v3(t->no, v1->co, v2->co, v3->co);
79 }
80 
81 static BMFace *hull_find_example_face(BMesh *bm, BMEdge *e)
82 {
83  BMIter iter;
84  BMFace *f;
85 
86  BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
87  if (BMO_face_flag_test(bm, f, HULL_FLAG_INPUT) ||
88  BMO_face_flag_test(bm, f, HULL_FLAG_OUTPUT_GEOM) == false) {
89  return f;
90  }
91  }
92 
93  return NULL;
94 }
95 
96 static void hull_output_triangles(BMesh *bm, BLI_mempool *hull_triangles)
97 {
98  BLI_mempool_iter iter;
99  BLI_mempool_iternew(hull_triangles, &iter);
100  HullTriangle *t;
101 
102  while ((t = BLI_mempool_iterstep(&iter))) {
103  int i;
104 
105  if (!t->skip) {
106  BMEdge *edges[3] = {
107  BM_edge_create(bm, t->v[0], t->v[1], NULL, BM_CREATE_NO_DOUBLE),
108  BM_edge_create(bm, t->v[1], t->v[2], NULL, BM_CREATE_NO_DOUBLE),
109  BM_edge_create(bm, t->v[2], t->v[0], NULL, BM_CREATE_NO_DOUBLE),
110  };
111  BMFace *f, *example = NULL;
112 
113  f = BM_face_exists(t->v, 3);
114  if (f != NULL) {
115  /* If the operator is run with "use_existing_faces"
116  * disabled, but an output face in the hull is the
117  * same as a face in the existing mesh, it should not
118  * be marked as unused or interior. */
119  BMO_face_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
120  BMO_face_flag_disable(bm, f, HULL_FLAG_HOLE);
121  BMO_face_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
122  }
123  else {
124  /* Look for an adjacent face that existed before the hull */
125  for (i = 0; i < 3; i++) {
126  if (!example) {
127  example = hull_find_example_face(bm, edges[i]);
128  }
129  }
130 
131  /* Create new hull face */
132  f = BM_face_create_verts(bm, t->v, 3, example, BM_CREATE_NO_DOUBLE, true);
134  }
135  /* Mark face for 'geom.out' slot and select */
136  BMO_face_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
137  BM_face_select_set(bm, f, true);
138 
139  /* Mark edges for 'geom.out' slot */
140  for (i = 0; i < 3; i++) {
141  BMO_edge_flag_enable(bm, edges[i], HULL_FLAG_OUTPUT_GEOM);
142  }
143  }
144  else {
145  /* Mark input edges for 'geom.out' slot */
146  for (i = 0; i < 3; i++) {
147  const int next = (i == 2 ? 0 : i + 1);
148  BMEdge *e = BM_edge_exists(t->v[i], t->v[next]);
149  if (e && BMO_edge_flag_test(bm, e, HULL_FLAG_INPUT) &&
150  !BMO_edge_flag_test(bm, e, HULL_FLAG_HOLE)) {
151  BMO_edge_flag_enable(bm, e, HULL_FLAG_OUTPUT_GEOM);
152  }
153  }
154  }
155 
156  /* Mark verts for 'geom.out' slot */
157  for (i = 0; i < 3; i++) {
158  BMO_vert_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM);
159  }
160  }
161 }
162 
163 /***************************** Final Edges ****************************/
164 
165 typedef struct {
166  GHash *edges;
167  BLI_mempool *base_pool, *link_pool;
168 } HullFinalEdges;
169 
170 static LinkData *final_edges_find_link(ListBase *adj, BMVert *v)
171 {
172  LinkData *link;
173 
174  for (link = adj->first; link; link = link->next) {
175  if (link->data == v) {
176  return link;
177  }
178  }
179 
180  return NULL;
181 }
182 
183 static int hull_final_edges_lookup(HullFinalEdges *final_edges, BMVert *v1, BMVert *v2)
184 {
185  ListBase *adj;
186 
187  /* Use lower vertex pointer for hash key */
188  if (v1 > v2) {
189  SWAP(BMVert *, v1, v2);
190  }
191 
192  adj = BLI_ghash_lookup(final_edges->edges, v1);
193  if (!adj) {
194  return false;
195  }
196 
197  return !!final_edges_find_link(adj, v2);
198 }
199 
200 /* Used for checking whether a pre-existing edge lies on the hull */
201 static HullFinalEdges *hull_final_edges(BLI_mempool *hull_triangles)
202 {
203  HullFinalEdges *final_edges;
204 
205  final_edges = MEM_callocN(sizeof(HullFinalEdges), "HullFinalEdges");
206  final_edges->edges = BLI_ghash_ptr_new("final edges ghash");
207  final_edges->base_pool = BLI_mempool_create(sizeof(ListBase), 0, 128, BLI_MEMPOOL_NOP);
208  final_edges->link_pool = BLI_mempool_create(sizeof(LinkData), 0, 128, BLI_MEMPOOL_NOP);
209 
210  BLI_mempool_iter iter;
211  BLI_mempool_iternew(hull_triangles, &iter);
212  HullTriangle *t;
213 
214  while ((t = BLI_mempool_iterstep(&iter))) {
215  LinkData *link;
216  int i;
217 
218  for (i = 0; i < 3; i++) {
219  BMVert *v1 = t->v[i];
220  BMVert *v2 = t->v[(i + 1) % 3];
221  ListBase *adj;
222 
223  /* Use lower vertex pointer for hash key */
224  if (v1 > v2) {
225  SWAP(BMVert *, v1, v2);
226  }
227 
228  adj = BLI_ghash_lookup(final_edges->edges, v1);
229  if (!adj) {
230  adj = BLI_mempool_calloc(final_edges->base_pool);
231  BLI_ghash_insert(final_edges->edges, v1, adj);
232  }
233 
234  if (!final_edges_find_link(adj, v2)) {
235  link = BLI_mempool_calloc(final_edges->link_pool);
236  link->data = v2;
237  BLI_addtail(adj, link);
238  }
239  }
240  }
241 
242  return final_edges;
243 }
244 
245 static void hull_final_edges_free(HullFinalEdges *final_edges)
246 {
247  BLI_ghash_free(final_edges->edges, NULL, NULL);
248  BLI_mempool_destroy(final_edges->base_pool);
249  BLI_mempool_destroy(final_edges->link_pool);
250  MEM_freeN(final_edges);
251 }
252 
253 /**************************** Final Output ****************************/
254 
255 static void hull_remove_overlapping(BMesh *bm,
256  BLI_mempool *hull_triangles,
257  HullFinalEdges *final_edges)
258 {
259  BLI_mempool_iter iter;
260  BLI_mempool_iternew(hull_triangles, &iter);
261  HullTriangle *t;
262 
263  while ((t = BLI_mempool_iterstep(&iter))) {
264  BMIter bm_iter1, bm_iter2;
265  BMFace *f;
266  bool f_on_hull;
267 
268  BM_ITER_ELEM (f, &bm_iter1, t->v[0], BM_FACES_OF_VERT) {
269  BMEdge *e;
270 
271  /* Check that all the face's edges are on the hull,
272  * otherwise can't reuse it */
273  f_on_hull = true;
274  BM_ITER_ELEM (e, &bm_iter2, f, BM_EDGES_OF_FACE) {
275  if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) {
276  f_on_hull = false;
277  break;
278  }
279  }
280 
281  /* Note: can't change ghash while iterating, so mark
282  * with 'skip' flag rather than deleting triangles */
283  if (BM_vert_in_face(t->v[1], f) && BM_vert_in_face(t->v[2], f) && f_on_hull) {
284  t->skip = true;
285  BMO_face_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
286  BMO_face_flag_enable(bm, f, HULL_FLAG_HOLE);
287  }
288  }
289  }
290 }
291 
292 static void hull_mark_interior_elements(BMesh *bm, BMOperator *op, HullFinalEdges *final_edges)
293 {
294  BMEdge *e;
295  BMFace *f;
296  BMOIter oiter;
297 
298  /* Check for interior edges too */
299  BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
300  if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) {
301  BMO_edge_flag_enable(bm, e, HULL_FLAG_INTERIOR_ELE);
302  }
303  }
304 
305  /* Mark all input faces as interior, some may be unmarked in
306  * hull_remove_overlapping() */
307  BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
308  BMO_face_flag_enable(bm, f, HULL_FLAG_INTERIOR_ELE);
309  }
310 }
311 
312 static void hull_tag_unused(BMesh *bm, BMOperator *op)
313 {
314  BMIter iter;
315  BMOIter oiter;
316  BMVert *v;
317  BMEdge *e;
318  BMFace *f;
319 
320  /* Mark vertices, edges, and faces that are already marked
321  * interior (i.e. were already part of the input, but not part of
322  * the hull), but that aren't also used by elements outside the
323  * input set */
324  BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
325  if (BMO_vert_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) {
326  bool del = true;
327 
328  BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
329  if (!BMO_edge_flag_test(bm, e, HULL_FLAG_INPUT)) {
330  del = false;
331  break;
332  }
333  }
334 
335  BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
336  if (!BMO_face_flag_test(bm, f, HULL_FLAG_INPUT)) {
337  del = false;
338  break;
339  }
340  }
341 
342  if (del) {
343  BMO_vert_flag_enable(bm, v, HULL_FLAG_DEL);
344  }
345  }
346  }
347 
348  BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
349  if (BMO_edge_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) {
350  bool del = true;
351 
352  BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
353  if (!BMO_face_flag_test(bm, f, HULL_FLAG_INPUT)) {
354  del = false;
355  break;
356  }
357  }
358 
359  if (del) {
360  BMO_edge_flag_enable(bm, e, HULL_FLAG_DEL);
361  }
362  }
363  }
364 
365  BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
366  if (BMO_face_flag_test(bm, f, HULL_FLAG_INTERIOR_ELE)) {
367  BMO_face_flag_enable(bm, f, HULL_FLAG_DEL);
368  }
369  }
370 }
371 
372 static void hull_tag_holes(BMesh *bm, BMOperator *op)
373 {
374  BMIter iter;
375  BMOIter oiter;
376  BMFace *f;
377  BMEdge *e;
378 
379  /* Unmark any hole faces if they are isolated or part of a
380  * border */
381  BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
382  if (BMO_face_flag_test(bm, f, HULL_FLAG_HOLE)) {
383  BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
384  if (BM_edge_is_boundary(e)) {
385  BMO_face_flag_disable(bm, f, HULL_FLAG_HOLE);
386  break;
387  }
388  }
389  }
390  }
391 
392  /* Mark edges too if all adjacent faces are holes and the edge is
393  * not already isolated */
394  BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
395  bool hole = true;
396  bool any_faces = false;
397 
398  BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
399  any_faces = true;
400  if (!BMO_face_flag_test(bm, f, HULL_FLAG_HOLE)) {
401  hole = false;
402  break;
403  }
404  }
405 
406  if (hole && any_faces) {
407  BMO_edge_flag_enable(bm, e, HULL_FLAG_HOLE);
408  }
409  }
410 }
411 
412 static int hull_input_vert_count(BMOperator *op)
413 {
414  BMOIter oiter;
415  BMVert *v;
416  int count = 0;
417 
418  BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
419  count++;
420  }
421 
422  return count;
423 }
424 
425 static BMVert **hull_input_verts_copy(BMOperator *op, const int num_input_verts)
426 {
427  BMOIter oiter;
428  BMVert *v;
429  BMVert **input_verts = MEM_callocN(sizeof(*input_verts) * num_input_verts, AT);
430  int i = 0;
431 
432  BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
433  input_verts[i++] = v;
434  }
435 
436  return input_verts;
437 }
438 
439 static float (*hull_verts_for_bullet(BMVert **input_verts, const int num_input_verts))[3]
440 {
441  float(*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, __func__);
442  int i;
443 
444  for (i = 0; i < num_input_verts; i++) {
445  copy_v3_v3(coords[i], input_verts[i]->co);
446  }
447 
448  return coords;
449 }
450 
451 static BMVert **hull_verts_from_bullet(plConvexHull hull,
452  BMVert **input_verts,
453  const int num_input_verts)
454 {
455  const int num_verts = plConvexHullNumVertices(hull);
456  BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) * num_verts, AT);
457  int i;
458 
459  for (i = 0; i < num_verts; i++) {
460  float co[3];
461  int original_index;
462  plConvexHullGetVertex(hull, i, co, &original_index);
463 
464  if (original_index >= 0 && original_index < num_input_verts) {
465  hull_verts[i] = input_verts[original_index];
466  }
467  else {
468  BLI_assert(!"Unexpected new vertex in hull output");
469  }
470  }
471 
472  return hull_verts;
473 }
474 
475 static void hull_from_bullet(BMesh *bm, BMOperator *op, BLI_mempool *hull_triangles)
476 {
477  int *fvi = NULL;
478  BLI_array_declare(fvi);
479 
480  BMVert **input_verts;
481  float(*coords)[3];
482  BMVert **hull_verts;
483 
484  plConvexHull hull;
485  int i, count = 0;
486 
487  const int num_input_verts = hull_input_vert_count(op);
488 
489  input_verts = hull_input_verts_copy(op, num_input_verts);
490  coords = hull_verts_for_bullet(input_verts, num_input_verts);
491 
492  hull = plConvexHullCompute(coords, num_input_verts);
493  hull_verts = hull_verts_from_bullet(hull, input_verts, num_input_verts);
494 
495  count = plConvexHullNumFaces(hull);
496  for (i = 0; i < count; i++) {
497  const int len = plConvexHullGetFaceSize(hull, i);
498 
499  if (len > 2) {
500  BMVert *fv[3];
501  int j;
502 
503  /* Get face vertex indices */
504  BLI_array_clear(fvi);
506  plConvexHullGetFaceVertices(hull, i, fvi);
507 
508  /* Note: here we throw away any NGons from Bullet and turn
509  * them into triangle fans. Would be nice to use these
510  * directly, but will have to wait until HullTriangle goes
511  * away (TODO) */
512  fv[0] = hull_verts[fvi[0]];
513  for (j = 2; j < len; j++) {
514  fv[1] = hull_verts[fvi[j - 1]];
515  fv[2] = hull_verts[fvi[j]];
516 
517  hull_add_triangle(bm, hull_triangles, fv[0], fv[1], fv[2]);
518  }
519  }
520  }
521 
522  BLI_array_free(fvi);
523 
524  plConvexHullDelete(hull);
525 
526  MEM_freeN(hull_verts);
527  MEM_freeN(coords);
528  MEM_freeN(input_verts);
529 }
530 
531 /* Check that there are at least three vertices in the input */
532 static bool hull_num_input_verts_is_ok(BMOperator *op)
533 {
534  BMOIter oiter;
535  BMVert *v;
536  int partial_num_verts = 0;
537 
538  BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
539  partial_num_verts++;
540  if (partial_num_verts >= 3) {
541  break;
542  }
543  }
544 
545  return (partial_num_verts >= 3);
546 }
547 
549 {
550  HullFinalEdges *final_edges;
551  BLI_mempool *hull_triangles;
552  BMElemF *ele;
553  BMOIter oiter;
554 
555  /* Verify that at least three verts in the input */
556  if (!hull_num_input_verts_is_ok(op)) {
557  BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED, "Requires at least three vertices");
558  return;
559  }
560 
561  /* Tag input elements */
562  BMO_ITER (ele, &oiter, op->slots_in, "input", BM_ALL) {
563 
564  /* Mark all vertices as interior to begin with */
565  if (ele->head.htype == BM_VERT) {
566  BMO_vert_flag_enable(bm, (BMVert *)ele, HULL_FLAG_INPUT | HULL_FLAG_INTERIOR_ELE);
567  }
568  else if (ele->head.htype == BM_EDGE) {
569  BMO_edge_flag_enable(bm, (BMEdge *)ele, HULL_FLAG_INPUT);
570  }
571  else {
572  BMO_face_flag_enable(bm, (BMFace *)ele, HULL_FLAG_INPUT);
573  }
574  }
575 
576  hull_triangles = BLI_mempool_create(sizeof(HullTriangle), 0, 128, BLI_MEMPOOL_ALLOW_ITER);
577 
578  hull_from_bullet(bm, op, hull_triangles);
579 
580  final_edges = hull_final_edges(hull_triangles);
581 
582  hull_mark_interior_elements(bm, op, final_edges);
583 
584  /* Remove hull triangles covered by an existing face */
585  if (BMO_slot_bool_get(op->slots_in, "use_existing_faces")) {
586  hull_remove_overlapping(bm, hull_triangles, final_edges);
587 
588  hull_tag_holes(bm, op);
589  }
590 
591  /* Done with edges */
592  hull_final_edges_free(final_edges);
593 
594  /* Convert hull triangles to BMesh faces */
595  hull_output_triangles(bm, hull_triangles);
596  BLI_mempool_destroy(hull_triangles);
597 
598  hull_tag_unused(bm, op);
599 
600  /* Output slot of input elements that ended up inside the hull
601  * rather than part of it */
603  bm, op, op->slots_out, "geom_interior.out", BM_ALL_NOLOOP, HULL_FLAG_INTERIOR_ELE);
604 
605  /* Output slot of input elements that ended up inside the hull and
606  * are are unused by other geometry. */
608  bm, op, op->slots_out, "geom_unused.out", BM_ALL_NOLOOP, HULL_FLAG_DEL);
609 
610  /* Output slot of faces and edges that were in the input and on
611  * the hull (useful for cases like bridging where you want to
612  * delete some input geometry) */
614  bm, op, op->slots_out, "geom_holes.out", BM_ALL_NOLOOP, HULL_FLAG_HOLE);
615 
616  /* Output slot of all hull vertices, faces, and edges */
618  bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, HULL_FLAG_OUTPUT_GEOM);
619 }
620 
621 #endif /* WITH_BULLET */
typedef float(TangentPoint)[2]
A (mainly) macro array library.
#define BLI_array_grow_items(arr, num)
Definition: BLI_array.h:99
#define BLI_array_declare(arr)
Definition: BLI_array.h:62
#define BLI_array_clear(arr)
Definition: BLI_array.h:130
#define BLI_array_free(arr)
Definition: BLI_array.h:116
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:51
MINLINE void copy_v3_v3(float r[3], const float a[3])
void * BLI_mempool_calloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mempool.c:362
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL()
Definition: BLI_mempool.c:537
@ BLI_MEMPOOL_ALLOW_ITER
Definition: BLI_mempool.h:85
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:77
void * BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_mempool.c:645
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_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:757
#define SWAP(type, a, b)
#define AT
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_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
#define BM_ALL
Definition: bmesh_class.h:410
void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data)
copies face loop data from shared adjacent faces.
BMFace * BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
Definition: bmesh_core.c:500
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_NO_DOUBLE
Definition: bmesh_core.h:29
@ BMERR_CONVEX_HULL_FAILED
Definition: bmesh_error.h:62
void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_FACES_OF_EDGE
@ BM_FACES_OF_VERT
@ BM_EDGES_OF_VERT
@ BM_EDGES_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
Select Face.
#define BMO_vert_flag_disable(bm, e, oflag)
#define BMO_edge_flag_test(bm, e, oflag)
#define BMO_edge_flag_enable(bm, e, oflag)
#define BMO_vert_flag_enable(bm, e, 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)
#define BMO_face_flag_disable(bm, e, oflag)
#define BMO_face_flag_test(bm, e, oflag)
void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void bmo_convex_hull_exec(BMesh *bm, BMOperator *op)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1995
BMFace * BM_face_exists(BMVert **varr, int len)
Definition: bmesh_query.c:2070
bool BM_vert_in_face(BMVert *v, BMFace *f)
Definition: bmesh_query.c:431
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
int count
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 * next
int plConvexHullGetFaceSize(plConvexHull hull, int n)
void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *original_index)
int plConvexHullNumVertices(plConvexHull hull)
plConvexHull plConvexHullCompute(float(*coords)[3], int count)
void plConvexHullDelete(plConvexHull hull)
int plConvexHullNumFaces(plConvexHull hull)
void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices)
BMHeader head
Definition: bmesh_class.h:250
char htype
Definition: bmesh_class.h:76
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
float co[3]
Definition: bmesh_class.h:99
void * data
Definition: DNA_listBase.h:42
struct LinkData * next
Definition: DNA_listBase.h:41
void * first
Definition: DNA_listBase.h:47
uint len