Blender  V3.3
bmesh_mesh_tessellate.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
12 #include "DNA_meshdata_types.h"
13 
14 #include "MEM_guardedalloc.h"
15 
16 #include "BLI_alloca.h"
17 #include "BLI_heap.h"
18 #include "BLI_linklist.h"
19 #include "BLI_math.h"
20 #include "BLI_memarena.h"
21 #include "BLI_polyfill_2d.h"
23 #include "BLI_task.h"
24 
25 #include "bmesh.h"
26 #include "bmesh_tools.h"
27 
35 #define BM_FACE_TESSELLATE_THREADED_LIMIT 1024
36 
37 /* -------------------------------------------------------------------- */
45  BMFace *efa,
46  MemArena **pf_arena_p,
47  const bool face_normal)
48 {
49 #ifdef DEBUG
50  /* The face normal is used for projecting faces into 2D space for tessellation.
51  * Invalid normals may result in invalid tessellation.
52  * Either `face_normal` should be true or normals should be updated first. */
53  BLI_assert(face_normal || BM_face_is_normal_valid(efa));
54 #endif
55 
56  switch (efa->len) {
57  case 3: {
58  /* `0 1 2` -> `0 1 2` */
59  BMLoop *l;
60  BMLoop **l_ptr = looptris[0];
61  l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
62  l_ptr[1] = l = l->next;
63  l_ptr[2] = l->next;
64  if (face_normal) {
65  normal_tri_v3(efa->no, l_ptr[0]->v->co, l_ptr[1]->v->co, l_ptr[2]->v->co);
66  }
67  break;
68  }
69  case 4: {
70  /* `0 1 2 3` -> (`0 1 2`, `0 2 3`) */
71  BMLoop *l;
72  BMLoop **l_ptr_a = looptris[0];
73  BMLoop **l_ptr_b = looptris[1];
74  (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
75  (l_ptr_a[1] = l = l->next);
76  (l_ptr_a[2] = l_ptr_b[1] = l = l->next);
77  (l_ptr_b[2] = l->next);
78 
79  if (face_normal) {
81  efa->no, l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co);
82  }
83 
85  l_ptr_a[1]->v->co,
86  l_ptr_a[2]->v->co,
87  l_ptr_b[2]->v->co,
88  efa->no))) {
89  /* Flip out of degenerate 0-2 state. */
90  l_ptr_a[2] = l_ptr_b[2];
91  l_ptr_b[0] = l_ptr_a[1];
92  }
93  break;
94  }
95  default: {
96  if (face_normal) {
97  BM_face_calc_normal(efa, efa->no);
98  }
99 
100  BMLoop *l_iter, *l_first;
101  BMLoop **l_arr;
102 
103  float axis_mat[3][3];
104  float(*projverts)[2];
105  uint(*tris)[3];
106 
107  const int tris_len = efa->len - 2;
108 
109  MemArena *pf_arena = *pf_arena_p;
110  if (UNLIKELY(pf_arena == NULL)) {
111  pf_arena = *pf_arena_p = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
112  }
113 
114  tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * tris_len);
115  l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len);
116  projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len);
117 
118  axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
119 
120  int i = 0;
121  l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
122  do {
123  l_arr[i] = l_iter;
124  mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
125  i++;
126  } while ((l_iter = l_iter->next) != l_first);
127 
128  BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena);
129 
130  for (i = 0; i < tris_len; i++) {
131  BMLoop **l_ptr = looptris[i];
132  uint *tri = tris[i];
133 
134  l_ptr[0] = l_arr[tri[0]];
135  l_ptr[1] = l_arr[tri[1]];
136  l_ptr[2] = l_arr[tri[2]];
137  }
138 
139  BLI_memarena_clear(pf_arena);
140  break;
141  }
142  }
143 }
144 
145 static void bmesh_calc_tessellation_for_face(BMLoop *(*looptris)[3],
146  BMFace *efa,
147  MemArena **pf_arena_p)
148 {
149  bmesh_calc_tessellation_for_face_impl(looptris, efa, pf_arena_p, false);
150 }
151 
153  BMFace *efa,
154  MemArena **pf_arena_p)
155 {
156  bmesh_calc_tessellation_for_face_impl(looptris, efa, pf_arena_p, true);
157 }
158 
166  BMLoop *(*looptris)[3],
167  const char face_normals)
168 {
169 #ifndef NDEBUG
170  const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
171 #endif
172 
173  BMIter iter;
174  BMFace *efa;
175  int i = 0;
176 
177  MemArena *pf_arena = NULL;
178 
179  if (face_normals) {
180  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
181  BLI_assert(efa->len >= 3);
182  BM_face_calc_normal(efa, efa->no);
183  bmesh_calc_tessellation_for_face_with_normal(looptris + i, efa, &pf_arena);
184  i += efa->len - 2;
185  }
186  }
187  else {
188  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
189  BLI_assert(efa->len >= 3);
190  bmesh_calc_tessellation_for_face(looptris + i, efa, &pf_arena);
191  i += efa->len - 2;
192  }
193  }
194 
195  if (pf_arena) {
196  BLI_memarena_free(pf_arena);
197  pf_arena = NULL;
198  }
199 
200  BLI_assert(i <= looptris_tot);
201 }
202 
203 struct TessellationUserTLS {
205 };
206 
207 static void bmesh_calc_tessellation_for_face_fn(void *__restrict userdata,
208  MempoolIterData *mp_f,
209  const TaskParallelTLS *__restrict tls)
210 {
211  struct TessellationUserTLS *tls_data = tls->userdata_chunk;
212  BMLoop *(*looptris)[3] = userdata;
213  BMFace *f = (BMFace *)mp_f;
215  const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2);
216  bmesh_calc_tessellation_for_face(looptris + offset, f, &tls_data->pf_arena);
217 }
218 
219 static void bmesh_calc_tessellation_for_face_with_normals_fn(void *__restrict userdata,
220  MempoolIterData *mp_f,
221  const TaskParallelTLS *__restrict tls)
222 {
223  struct TessellationUserTLS *tls_data = tls->userdata_chunk;
224  BMLoop *(*looptris)[3] = userdata;
225  BMFace *f = (BMFace *)mp_f;
227  const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2);
229 }
230 
231 static void bmesh_calc_tessellation_for_face_free_fn(const void *__restrict UNUSED(userdata),
232  void *__restrict tls_v)
233 {
234  struct TessellationUserTLS *tls_data = tls_v;
235  if (tls_data->pf_arena) {
236  BLI_memarena_free(tls_data->pf_arena);
237  }
238 }
239 
241  BMLoop *(*looptris)[3],
242  const char face_normals)
243 {
245 
246  TaskParallelSettings settings;
247  struct TessellationUserTLS tls_dummy = {NULL};
249  settings.userdata_chunk = &tls_dummy;
250  settings.userdata_chunk_size = sizeof(tls_dummy);
252  BM_iter_parallel(bm,
256  looptris,
257  &settings);
258 }
259 
261  BMLoop *(*looptris)[3],
262  const struct BMeshCalcTessellation_Params *params)
263 {
265  bm_mesh_calc_tessellation__single_threaded(bm, looptris, params->face_normals);
266  }
267  else {
268  bm_mesh_calc_tessellation__multi_threaded(bm, looptris, params->face_normals);
269  }
270 }
271 
272 void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3])
273 {
275  looptris,
276  &(const struct BMeshCalcTessellation_Params){
277  .face_normals = false,
278  });
279 }
280 
283 /* -------------------------------------------------------------------- */
289  BMLoop *(*looptris)[3];
290 };
291 
294 };
295 
296 static void bmesh_calc_tessellation_for_face_partial_fn(void *__restrict userdata,
297  const int index,
298  const TaskParallelTLS *__restrict tls)
299 {
300  struct PartialTessellationUserTLS *tls_data = tls->userdata_chunk;
301  struct PartialTessellationUserData *data = userdata;
302  BMFace *f = data->faces[index];
304  const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2);
305  bmesh_calc_tessellation_for_face(data->looptris + offset, f, &tls_data->pf_arena);
306 }
307 
309  void *__restrict userdata, const int index, const TaskParallelTLS *__restrict tls)
310 {
311  struct PartialTessellationUserTLS *tls_data = tls->userdata_chunk;
312  struct PartialTessellationUserData *data = userdata;
313  BMFace *f = data->faces[index];
315  const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2);
317 }
318 
320  const void *__restrict UNUSED(userdata), void *__restrict tls_v)
321 {
322  struct PartialTessellationUserTLS *tls_data = tls_v;
323  if (tls_data->pf_arena) {
324  BLI_memarena_free(tls_data->pf_arena);
325  }
326 }
327 
329  BMLoop *(*looptris)[3],
330  const BMPartialUpdate *bmpinfo,
331  const struct BMeshCalcTessellation_Params *params)
332 {
333  const int faces_len = bmpinfo->faces_len;
334  BMFace **faces = bmpinfo->faces;
335 
337  .faces = faces,
338  .looptris = looptris,
339  };
340  struct PartialTessellationUserTLS tls_dummy = {NULL};
341  TaskParallelSettings settings;
343  settings.use_threading = true;
344  settings.userdata_chunk = &tls_dummy;
345  settings.userdata_chunk_size = sizeof(tls_dummy);
347 
349  faces_len,
350  &data,
351  params->face_normals ?
354  &settings);
355 }
356 
358  BMLoop *(*looptris)[3],
359  const BMPartialUpdate *bmpinfo,
360  const struct BMeshCalcTessellation_Params *params)
361 {
362  const int faces_len = bmpinfo->faces_len;
363  BMFace **faces = bmpinfo->faces;
364 
366 
367  if (params->face_normals) {
368  for (int index = 0; index < faces_len; index++) {
369  BMFace *f = faces[index];
371  const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2);
373  }
374  }
375  else {
376  for (int index = 0; index < faces_len; index++) {
377  BMFace *f = faces[index];
379  const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2);
381  }
382  }
383 
384  if (pf_arena) {
386  }
387 }
388 
390  BMLoop *(*looptris)[3],
391  const BMPartialUpdate *bmpinfo,
392  const struct BMeshCalcTessellation_Params *params)
393 {
394  BLI_assert(bmpinfo->params.do_tessellate);
395  /* While harmless, exit early if there is nothing to do (avoids ensuring the index). */
396  if (UNLIKELY(bmpinfo->faces_len == 0)) {
397  return;
398  }
399 
401 
404  }
405  else {
407  }
408 }
409 
411  BMLoop *(*looptris)[3],
412  const BMPartialUpdate *bmpinfo)
413 {
414  BM_mesh_calc_tessellation_with_partial_ex(bm, looptris, bmpinfo, false);
415 }
416 
419 /* -------------------------------------------------------------------- */
426  BMFace *efa,
427  MemArena **pf_arena_p,
428  Heap **pf_heap_p)
429 {
430  switch (efa->len) {
431  case 3: {
432  BMLoop *l;
433  BMLoop **l_ptr = looptris[0];
434  l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
435  l_ptr[1] = l = l->next;
436  l_ptr[2] = l->next;
437  return 1;
438  }
439  case 4: {
440  BMLoop *l_v1 = BM_FACE_FIRST_LOOP(efa);
441  BMLoop *l_v2 = l_v1->next;
442  BMLoop *l_v3 = l_v2->next;
443  BMLoop *l_v4 = l_v1->prev;
444 
445  /* #BM_verts_calc_rotate_beauty performs excessive checks we don't need!
446  * It's meant for rotating edges, it also calculates a new normal.
447  *
448  * Use #BLI_polyfill_beautify_quad_rotate_calc since we have the normal.
449  */
450 #if 0
451  const bool split_13 = (BM_verts_calc_rotate_beauty(
452  l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) < 0.0f);
453 #else
454  float axis_mat[3][3], v_quad[4][2];
455  axis_dominant_v3_to_m3(axis_mat, efa->no);
456  mul_v2_m3v3(v_quad[0], axis_mat, l_v1->v->co);
457  mul_v2_m3v3(v_quad[1], axis_mat, l_v2->v->co);
458  mul_v2_m3v3(v_quad[2], axis_mat, l_v3->v->co);
459  mul_v2_m3v3(v_quad[3], axis_mat, l_v4->v->co);
460 
461  const bool split_13 = BLI_polyfill_beautify_quad_rotate_calc(
462  v_quad[0], v_quad[1], v_quad[2], v_quad[3]) < 0.0f;
463 #endif
464 
465  BMLoop **l_ptr_a = looptris[0];
466  BMLoop **l_ptr_b = looptris[1];
467  if (split_13) {
468  l_ptr_a[0] = l_v1;
469  l_ptr_a[1] = l_v2;
470  l_ptr_a[2] = l_v3;
471 
472  l_ptr_b[0] = l_v1;
473  l_ptr_b[1] = l_v3;
474  l_ptr_b[2] = l_v4;
475  }
476  else {
477  l_ptr_a[0] = l_v1;
478  l_ptr_a[1] = l_v2;
479  l_ptr_a[2] = l_v4;
480 
481  l_ptr_b[0] = l_v2;
482  l_ptr_b[1] = l_v3;
483  l_ptr_b[2] = l_v4;
484  }
485  return 2;
486  }
487  default: {
488  MemArena *pf_arena = *pf_arena_p;
489  Heap *pf_heap = *pf_heap_p;
490  if (UNLIKELY(pf_arena == NULL)) {
491  pf_arena = *pf_arena_p = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
492  pf_heap = *pf_heap_p = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
493  }
494 
495  BMLoop *l_iter, *l_first;
496  BMLoop **l_arr;
497 
498  float axis_mat[3][3];
499  float(*projverts)[2];
500  uint(*tris)[3];
501 
502  const int tris_len = efa->len - 2;
503 
504  tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * tris_len);
505  l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len);
506  projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len);
507 
508  axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
509 
510  int i = 0;
511  l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
512  do {
513  l_arr[i] = l_iter;
514  mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
515  i++;
516  } while ((l_iter = l_iter->next) != l_first);
517 
518  BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena);
519 
520  BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap);
521 
522  for (i = 0; i < tris_len; i++) {
523  BMLoop **l_ptr = looptris[i];
524  uint *tri = tris[i];
525 
526  l_ptr[0] = l_arr[tri[0]];
527  l_ptr[1] = l_arr[tri[1]];
528  l_ptr[2] = l_arr[tri[2]];
529  }
530 
532 
533  return tris_len;
534  }
535  }
536 }
537 
539 {
540 #ifndef NDEBUG
541  const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
542 #endif
543 
544  BMIter iter;
545  BMFace *efa;
546  int i = 0;
547 
549 
550  /* use_beauty */
551  Heap *pf_heap = NULL;
552 
553  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
554  BLI_assert(efa->len >= 3);
555  i += bmesh_calc_tessellation_for_face_beauty(looptris + i, efa, &pf_arena, &pf_heap);
556  }
557 
558  if (pf_arena) {
560 
561  BLI_heap_free(pf_heap, NULL);
562  }
563 
564  BLI_assert(i <= looptris_tot);
565 }
566 
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
A min-heap / priority queue ADT.
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1)
Definition: BLI_heap.c:202
Heap * BLI_heap_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT
Definition: BLI_heap.c:182
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:50
bool is_quad_flip_v3_first_third_fast_with_normal(const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float normal[3])
Definition: math_geom.c:5882
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
Definition: math_geom.c:3544
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
Definition: math_geom.c:3527
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
Definition: math_matrix.c:917
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:94
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:64
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:20
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:116
void void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:208
void BLI_polyfill_calc_arena(const float(*coords)[2], unsigned int coords_num, int coords_sign, unsigned int(*r_tris)[3], struct MemArena *arena)
Definition: polyfill_2d.c:830
#define BLI_POLYFILL_ALLOC_NGON_RESERVE
#define BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4)
void BLI_polyfill_beautify(const float(*coords)[2], unsigned int coords_num, unsigned int(*tris)[3], struct MemArena *arena, struct Heap *eheap)
unsigned int uint
Definition: BLI_sys_types.h:67
struct MempoolIterData MempoolIterData
Definition: BLI_task.h:272
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
BLI_INLINE void BLI_parallel_mempool_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:301
#define UNUSED(x)
#define UNLIKELY(x)
Read Guarded memory(de)allocation.
float BM_verts_calc_rotate_beauty(const BMVert *v1, const BMVert *v2, const BMVert *v3, const BMVert *v4, const short flag, const short method)
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:446
BLI_INLINE void bmesh_calc_tessellation_for_face_impl(BMLoop *(*looptris)[3], BMFace *efa, MemArena **pf_arena_p, const bool face_normal)
static void bmesh_calc_tessellation_for_face_with_normal(BMLoop *(*looptris)[3], BMFace *efa, MemArena **pf_arena_p)
static int bmesh_calc_tessellation_for_face_beauty(BMLoop *(*looptris)[3], BMFace *efa, MemArena **pf_arena_p, Heap **pf_heap_p)
static void bm_mesh_calc_tessellation__single_threaded(BMesh *bm, BMLoop *(*looptris)[3], const char face_normals)
BM_mesh_calc_tessellation get the looptris and its number from a certain bmesh.
static void bmesh_calc_tessellation_for_face_partial_with_normals_fn(void *__restrict userdata, const int index, const TaskParallelTLS *__restrict tls)
static void bm_mesh_calc_tessellation__multi_threaded(BMesh *bm, BMLoop *(*looptris)[3], const char face_normals)
static void bm_mesh_calc_tessellation_with_partial__multi_threaded(BMLoop *(*looptris)[3], const BMPartialUpdate *bmpinfo, const struct BMeshCalcTessellation_Params *params)
void BM_mesh_calc_tessellation_with_partial(BMesh *bm, BMLoop *(*looptris)[3], const BMPartialUpdate *bmpinfo)
void BM_mesh_calc_tessellation_ex(BMesh *bm, BMLoop *(*looptris)[3], const struct BMeshCalcTessellation_Params *params)
static void bmesh_calc_tessellation_for_face(BMLoop *(*looptris)[3], BMFace *efa, MemArena **pf_arena_p)
static void bm_mesh_calc_tessellation_with_partial__single_threaded(BMLoop *(*looptris)[3], const BMPartialUpdate *bmpinfo, const struct BMeshCalcTessellation_Params *params)
#define BM_FACE_TESSELLATE_THREADED_LIMIT
void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3])
static void bmesh_calc_tessellation_for_face_partial_free_fn(const void *__restrict UNUSED(userdata), void *__restrict tls_v)
void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3])
static void bmesh_calc_tessellation_for_face_with_normals_fn(void *__restrict userdata, MempoolIterData *mp_f, const TaskParallelTLS *__restrict tls)
static void bmesh_calc_tessellation_for_face_free_fn(const void *__restrict UNUSED(userdata), void *__restrict tls_v)
void BM_mesh_calc_tessellation_with_partial_ex(BMesh *bm, BMLoop *(*looptris)[3], const BMPartialUpdate *bmpinfo, const struct BMeshCalcTessellation_Params *params)
static void bmesh_calc_tessellation_for_face_fn(void *__restrict userdata, MempoolIterData *mp_f, const TaskParallelTLS *__restrict tls)
static void bmesh_calc_tessellation_for_face_partial_fn(void *__restrict userdata, const int index, const TaskParallelTLS *__restrict tls)
float BM_face_calc_normal(const BMFace *f, float r_no[3])
BMESH UPDATE FACE NORMAL.
bool BM_face_is_normal_valid(const BMFace *f)
Definition: bmesh_query.c:2033
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
static char faces[256]
int len
Definition: bmesh_class.h:267
float no[3]
Definition: bmesh_class.h:271
struct BMVert * v
Definition: bmesh_class.h:153
struct BMLoop * prev
Definition: bmesh_class.h:233
struct BMLoop * next
Definition: bmesh_class.h:233
BMPartialUpdate_Params params
float co[3]
Definition: bmesh_class.h:87
int totloop
Definition: bmesh_class.h:297
int totface
Definition: bmesh_class.h:297
Definition: BLI_heap.c:43
TaskParallelFreeFunc func_free
Definition: BLI_task.h:183
size_t userdata_chunk_size
Definition: BLI_task.h:169