Blender  V3.3
bmesh_interp.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Blender Foundation. All rights reserved. */
3 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_meshdata_types.h"
13 
14 #include "BLI_alloca.h"
15 #include "BLI_linklist.h"
16 #include "BLI_math.h"
17 #include "BLI_memarena.h"
18 #include "BLI_task.h"
19 
20 #include "BKE_customdata.h"
21 #include "BKE_multires.h"
22 
23 #include "bmesh.h"
24 #include "intern/bmesh_private.h"
25 
26 /* edge and vertex share, currently there's no need to have different logic */
27 static void bm_data_interp_from_elem(CustomData *data_layer,
28  const BMElem *ele_src_1,
29  const BMElem *ele_src_2,
30  BMElem *ele_dst,
31  const float fac)
32 {
33  if (ele_src_1->head.data && ele_src_2->head.data) {
34  /* first see if we can avoid interpolation */
35  if (fac <= 0.0f) {
36  if (ele_src_1 == ele_dst) {
37  /* do nothing */
38  }
39  else {
40  CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
42  data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data);
43  }
44  }
45  else if (fac >= 1.0f) {
46  if (ele_src_2 == ele_dst) {
47  /* do nothing */
48  }
49  else {
50  CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
52  data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data);
53  }
54  }
55  else {
56  const void *src[2];
57  float w[2];
58 
59  src[0] = ele_src_1->head.data;
60  src[1] = ele_src_2->head.data;
61  w[0] = 1.0f - fac;
62  w[1] = fac;
63  CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data);
64  }
65  }
66 }
67 
69  BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
70 {
72  &bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac);
73 }
74 
76  BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac)
77 {
79  &bm->edata, (const BMElem *)e_src_1, (const BMElem *)e_src_2, (BMElem *)e_dst, fac);
80 }
81 
89 {
90  // BMIter iter;
91 }
92 
94  const BMVert *v_src_1,
95  const BMVert *UNUSED(v_src_2),
96  BMVert *v,
97  BMEdge *e,
98  const float fac)
99 {
100  float w[2];
101  BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL;
102  BMLoop *l_iter = NULL;
103 
104  if (!e->l) {
105  return;
106  }
107 
108  w[1] = 1.0f - fac;
109  w[0] = fac;
110 
111  l_iter = e->l;
112  do {
113  if (l_iter->v == v_src_1) {
114  l_v1 = l_iter;
115  l_v = l_v1->next;
116  l_v2 = l_v->next;
117  }
118  else if (l_iter->v == v) {
119  l_v1 = l_iter->next;
120  l_v = l_iter;
121  l_v2 = l_iter->prev;
122  }
123 
124  if (!l_v1 || !l_v2) {
125  return;
126  }
127 
128  const void *src[2];
129  src[0] = l_v1->head.data;
130  src[1] = l_v2->head.data;
131 
132  CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
133  } while ((l_iter = l_iter->radial_next) != e->l);
134 }
135 
137  BMFace *f_dst,
138  const BMFace *f_src,
139  const bool do_vertex,
140  const void **blocks_l,
141  const void **blocks_v,
142  float (*cos_2d)[2],
143  float axis_mat[3][3])
144 {
145  BMLoop *l_iter;
146  BMLoop *l_first;
147 
148  float *w = BLI_array_alloca(w, f_src->len);
149  float co[2];
150  int i;
151 
152  if (f_src != f_dst) {
153  BM_elem_attrs_copy(bm, bm, f_src, f_dst);
154  }
155 
156  /* interpolate */
157  i = 0;
158  l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
159  do {
160  mul_v2_m3v3(co, axis_mat, l_iter->v->co);
161  interp_weights_poly_v2(w, cos_2d, f_src->len, co);
162  CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data);
163  if (do_vertex) {
164  CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data);
165  }
166  } while ((void)i++, (l_iter = l_iter->next) != l_first);
167 }
168 
169 void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex)
170 {
171  BMLoop *l_iter;
172  BMLoop *l_first;
173 
174  const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len);
175  const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL;
176  float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
177  float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
178  int i;
179 
180  /* convert the 3d coords into 2d for projection */
182  axis_dominant_v3_to_m3(axis_mat, f_src->no);
183 
184  i = 0;
185  l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
186  do {
187  mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
188  blocks_l[i] = l_iter->head.data;
189  if (do_vertex) {
190  blocks_v[i] = l_iter->v->head.data;
191  }
192  } while ((void)i++, (l_iter = l_iter->next) != l_first);
193 
194  BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex, blocks_l, blocks_v, cos_2d, axis_mat);
195 }
196 
211 static int compute_mdisp_quad(const BMLoop *l,
212  const float l_f_center[3],
213  float v1[3],
214  float v2[3],
215  float v3[3],
216  float v4[3],
217  float e1[3],
218  float e2[3])
219 {
220  float n[3], p[3];
221 
222 #ifndef NDEBUG
223  {
224  float cent[3];
225  /* computer center */
227  BLI_assert(equals_v3v3(cent, l_f_center));
228  }
229 #endif
230 
231  mid_v3_v3v3(p, l->prev->v->co, l->v->co);
232  mid_v3_v3v3(n, l->next->v->co, l->v->co);
233 
234  copy_v3_v3(v1, l_f_center);
235  copy_v3_v3(v2, p);
236  copy_v3_v3(v3, l->v->co);
237  copy_v3_v3(v4, n);
238 
239  sub_v3_v3v3(e1, v2, v1);
240  sub_v3_v3v3(e2, v3, v4);
241 
242  return 1;
243 }
244 
245 static bool quad_co(const float v1[3],
246  const float v2[3],
247  const float v3[3],
248  const float v4[3],
249  const float p[3],
250  const float n[3],
251  float r_uv[2])
252 {
253  float projverts[5][3], n2[3];
254  const float origin[2] = {0.0f, 0.0f};
255  int i;
256 
257  /* project points into 2d along normal */
258  copy_v3_v3(projverts[0], v1);
259  copy_v3_v3(projverts[1], v2);
260  copy_v3_v3(projverts[2], v3);
261  copy_v3_v3(projverts[3], v4);
262  copy_v3_v3(projverts[4], p);
263 
264  normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]);
265 
266  if (dot_v3v3(n, n2) < -FLT_EPSILON) {
267  return false;
268  }
269 
270  /* rotate */
271  poly_rotate_plane(n, projverts, 5);
272 
273  /* subtract origin */
274  for (i = 0; i < 4; i++) {
275  sub_v2_v2(projverts[i], projverts[4]);
276  }
277 
278  if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) {
279  return false;
280  }
281 
282  resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]);
283 
284  return true;
285 }
286 
287 static void mdisp_axis_from_quad(const float v1[3],
288  const float v2[3],
289  float UNUSED(v3[3]),
290  const float v4[3],
291  float r_axis_x[3],
292  float r_axis_y[3])
293 {
294  sub_v3_v3v3(r_axis_x, v4, v1);
295  sub_v3_v3v3(r_axis_y, v2, v1);
296 
297  normalize_v3(r_axis_x);
298  normalize_v3(r_axis_y);
299 }
300 
307 static bool mdisp_in_mdispquad(BMLoop *l_src,
308  BMLoop *l_dst,
309  const float l_dst_f_center[3],
310  const float p[3],
311  int res,
312  float r_axis_x[3],
313  float r_axis_y[3],
314  float r_uv[2])
315 {
316  float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
317  float eps = FLT_EPSILON * 4000;
318 
319  if (is_zero_v3(l_src->v->no)) {
321  }
322  if (is_zero_v3(l_dst->v->no)) {
324  }
325 
326  compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2);
327 
328  /* expand quad a bit */
329  mid_v3_v3v3v3v3(c, v1, v2, v3, v4);
330 
331  sub_v3_v3(v1, c);
332  sub_v3_v3(v2, c);
333  sub_v3_v3(v3, c);
334  sub_v3_v3(v4, c);
335  mul_v3_fl(v1, 1.0f + eps);
336  mul_v3_fl(v2, 1.0f + eps);
337  mul_v3_fl(v3, 1.0f + eps);
338  mul_v3_fl(v4, 1.0f + eps);
339  add_v3_v3(v1, c);
340  add_v3_v3(v2, c);
341  add_v3_v3(v3, c);
342  add_v3_v3(v4, c);
343 
344  if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) {
345  return 0;
346  }
347 
348  mul_v2_fl(r_uv, (float)(res - 1));
349 
350  mdisp_axis_from_quad(v1, v2, v3, v4, r_axis_x, r_axis_y);
351 
352  return 1;
353 }
354 
355 static float bm_loop_flip_equotion(float mat[2][2],
356  float b[2],
357  const float target_axis_x[3],
358  const float target_axis_y[3],
359  const float coord[3],
360  int i,
361  int j)
362 {
363  mat[0][0] = target_axis_x[i];
364  mat[0][1] = target_axis_y[i];
365  mat[1][0] = target_axis_x[j];
366  mat[1][1] = target_axis_y[j];
367  b[0] = coord[i];
368  b[1] = coord[j];
369 
370  return cross_v2v2(mat[0], mat[1]);
371 }
372 
373 static void bm_loop_flip_disp(const float source_axis_x[3],
374  const float source_axis_y[3],
375  const float target_axis_x[3],
376  const float target_axis_y[3],
377  float disp[3])
378 {
379  float vx[3], vy[3], coord[3];
380  float n[3], vec[3];
381  float b[2], mat[2][2], d;
382 
383  mul_v3_v3fl(vx, source_axis_x, disp[0]);
384  mul_v3_v3fl(vy, source_axis_y, disp[1]);
385  add_v3_v3v3(coord, vx, vy);
386 
387  /* project displacement from source grid plane onto target grid plane */
388  cross_v3_v3v3(n, target_axis_x, target_axis_y);
389  project_v3_v3v3(vec, coord, n);
390  sub_v3_v3v3(coord, coord, vec);
391 
392  d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1);
393 
394  if (fabsf(d) < 1e-4f) {
395  d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2);
396  if (fabsf(d) < 1e-4f) {
397  d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2);
398  }
399  }
400 
401  disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d;
402  disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d;
403 }
404 
405 typedef struct BMLoopInterpMultiresData {
409 
411  const float *f_src_center;
412 
413  float *axis_x, *axis_y;
414  float *v1, *v4;
415  float *e1, *e2;
416 
417  int res;
418  float d;
420 
421 static void loop_interp_multires_cb(void *__restrict userdata,
422  const int ix,
423  const TaskParallelTLS *__restrict UNUSED(tls))
424 {
425  BMLoopInterpMultiresData *data = userdata;
426 
427  BMLoop *l_first = data->l_src_first;
428  BMLoop *l_dst = data->l_dst;
429  const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset;
430 
431  MDisps *md_dst = data->md_dst;
432  const float *f_src_center = data->f_src_center;
433 
434  float *axis_x = data->axis_x;
435  float *axis_y = data->axis_y;
436 
437  float *v1 = data->v1;
438  float *v4 = data->v4;
439  float *e1 = data->e1;
440  float *e2 = data->e2;
441 
442  const int res = data->res;
443  const float d = data->d;
444 
445  float x = d * ix, y;
446  int iy;
447  for (y = 0.0f, iy = 0; iy < res; y += d, iy++) {
448  BMLoop *l_iter = l_first;
449  float co1[3], co2[3], co[3];
450 
451  madd_v3_v3v3fl(co1, v1, e1, y);
452  madd_v3_v3v3fl(co2, v4, e2, y);
453  interp_v3_v3v3(co, co1, co2, x);
454 
455  do {
456  MDisps *md_src;
457  float src_axis_x[3], src_axis_y[3];
458  float uv[2];
459 
460  md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
461 
462  if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
463  old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
464  bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]);
465 
466  break;
467  }
468  } while ((l_iter = l_iter->next) != l_first);
469  }
470 }
471 
473  BMLoop *l_dst,
474  const BMFace *f_src,
475  const float f_dst_center[3],
476  const float f_src_center[3],
477  const int cd_loop_mdisp_offset)
478 {
479  MDisps *md_dst;
480  float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
481  float axis_x[3], axis_y[3];
482 
483  /* ignore 2-edged faces */
484  if (UNLIKELY(l_dst->f->len < 3)) {
485  return;
486  }
487 
488  md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset);
489  compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2);
490 
491  /* if no disps data allocate a new grid, the size of the first grid in f_src. */
492  if (!md_dst->totdisp) {
493  const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
494 
495  md_dst->totdisp = md_src->totdisp;
496  md_dst->level = md_src->level;
497  if (md_dst->totdisp) {
498  md_dst->disps = MEM_callocN(sizeof(float[3]) * md_dst->totdisp, __func__);
499  }
500  else {
501  return;
502  }
503  }
504 
505  mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
506 
507  const int res = (int)sqrt(md_dst->totdisp);
509  .l_dst = l_dst,
510  .l_src_first = BM_FACE_FIRST_LOOP(f_src),
511  .cd_loop_mdisp_offset = cd_loop_mdisp_offset,
512  .md_dst = md_dst,
513  .f_src_center = f_src_center,
514  .axis_x = axis_x,
515  .axis_y = axis_y,
516  .v1 = v1,
517  .v4 = v4,
518  .e1 = e1,
519  .e2 = e2,
520  .res = res,
521  .d = 1.0f / (float)(res - 1),
522  };
523  TaskParallelSettings settings;
525  settings.use_threading = (res > 5);
527 }
528 
529 void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
530 {
531  const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
532 
533  if (cd_loop_mdisp_offset != -1) {
534  float f_dst_center[3];
535  float f_src_center[3];
536 
537  BM_face_calc_center_median(l_dst->f, f_dst_center);
538  BM_face_calc_center_median(f_src, f_src_center);
539 
540  BM_loop_interp_multires_ex(bm, l_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
541  }
542 }
543 
545  BMFace *f_dst,
546  const BMFace *f_src,
547  const float f_dst_center[3],
548  const float f_src_center[3],
549  const int cd_loop_mdisp_offset)
550 {
551  BMLoop *l_iter, *l_first;
552  l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
553  do {
555  bm, l_iter, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
556  } while ((l_iter = l_iter->next) != l_first);
557 }
558 
559 void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src)
560 {
561  const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
562 
563  if (cd_loop_mdisp_offset != -1) {
564  float f_dst_center[3];
565  float f_src_center[3];
566 
567  BM_face_calc_center_median(f_dst, f_dst_center);
568  BM_face_calc_center_median(f_src, f_src_center);
569 
570  BM_face_interp_multires_ex(bm, f_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
571  }
572 }
573 
575 {
576  const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
577  BMLoop *l;
578  BMIter liter;
579 
580  if (cd_loop_mdisp_offset == -1) {
581  return;
582  }
583 
584  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
585  MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset);
586  MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
587  MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset);
588  float co1[3];
589  int sides;
590  int y;
591 
607  sides = (int)sqrt(mdp->totdisp);
608  for (y = 0; y < sides; y++) {
609  mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]);
610 
611  copy_v3_v3(mdn->disps[y * sides], co1);
612  copy_v3_v3(mdl->disps[y], co1);
613  }
614  }
615 
616  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
617  MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
618  MDisps *mdl2;
619  float co1[3], co2[3], co[3];
620  int sides;
621  int y;
622 
638  if (l->radial_next == l) {
639  continue;
640  }
641 
642  if (l->radial_next->v == l->v) {
643  mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset);
644  }
645  else {
646  mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset);
647  }
648 
649  sides = (int)sqrt(mdl1->totdisp);
650  for (y = 0; y < sides; y++) {
651  int a1, a2, o1, o2;
652 
653  if (l->v != l->radial_next->v) {
654  a1 = sides * y + sides - 2;
655  a2 = (sides - 2) * sides + y;
656 
657  o1 = sides * y + sides - 1;
658  o2 = (sides - 1) * sides + y;
659  }
660  else {
661  a1 = sides * y + sides - 2;
662  a2 = sides * y + sides - 2;
663  o1 = sides * y + sides - 1;
664  o2 = sides * y + sides - 1;
665  }
666 
667  /* magic blending numbers, hardcoded! */
668  add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]);
669  mul_v3_fl(co1, 0.18);
670 
671  add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
672  mul_v3_fl(co2, 0.32);
673 
674  add_v3_v3v3(co, co1, co2);
675 
676  copy_v3_v3(mdl1->disps[o1], co);
677  copy_v3_v3(mdl2->disps[o2], co);
678  }
679  }
680 }
681 
683  BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires)
684 {
685  BMLoop *l_iter;
686  BMLoop *l_first;
687  const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL;
688  const void **blocks = BLI_array_alloca(blocks, f_src->len);
689  float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
690  float *w = BLI_array_alloca(w, f_src->len);
691  float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
692  float co[2];
693  int i;
694 
695  /* Convert the 3d coords into 2d for projection. */
696  float axis_dominant[3];
697  if (!is_zero_v3(f_src->no)) {
699  copy_v3_v3(axis_dominant, f_src->no);
700  }
701  else {
702  /* Rare case in which all the vertices of the face are aligned.
703  * Get a random axis that is orthogonal to the tangent. */
704  float vec[3];
705  BM_face_calc_tangent_auto(f_src, vec);
706  ortho_v3_v3(axis_dominant, vec);
707  normalize_v3(axis_dominant);
708  }
709  axis_dominant_v3_to_m3(axis_mat, axis_dominant);
710 
711  i = 0;
712  l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
713  do {
714  mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
715  blocks[i] = l_iter->head.data;
716 
717  if (do_vertex) {
718  vblocks[i] = l_iter->v->head.data;
719  }
720  } while ((void)i++, (l_iter = l_iter->next) != l_first);
721 
722  mul_v2_m3v3(co, axis_mat, l_dst->v->co);
723 
724  /* interpolate */
725  interp_weights_poly_v2(w, cos_2d, f_src->len, co);
726  CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data);
727  if (do_vertex) {
728  CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data);
729  }
730 
731  if (do_multires) {
732  BM_loop_interp_multires(bm, l_dst, f_src);
733  }
734 }
735 
736 void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
737 {
738  BMLoop *l_iter;
739  BMLoop *l_first;
740  const void **blocks = BLI_array_alloca(blocks, f_src->len);
741  float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
742  float *w = BLI_array_alloca(w, f_src->len);
743  float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
744  float co[2];
745  int i;
746 
747  /* convert the 3d coords into 2d for projection */
749  axis_dominant_v3_to_m3(axis_mat, f_src->no);
750 
751  i = 0;
752  l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
753  do {
754  mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
755  blocks[i] = l_iter->v->head.data;
756  } while ((void)i++, (l_iter = l_iter->next) != l_first);
757 
758  mul_v2_m3v3(co, axis_mat, v_dst->co);
759 
760  /* interpolate */
761  interp_weights_poly_v2(w, cos_2d, f_src->len, co);
762  CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data);
763 }
764 
766 {
767  BMIter iter;
768  BLI_mempool *oldpool = olddata->pool;
769  void *block;
770 
771  if (data == &bm->vdata) {
772  BMVert *eve;
773 
775 
776  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
777  block = NULL;
779  CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
780  CustomData_bmesh_free_block(olddata, &eve->head.data);
781  eve->head.data = block;
782  }
783  }
784  else if (data == &bm->edata) {
785  BMEdge *eed;
786 
788 
789  BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
790  block = NULL;
792  CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
793  CustomData_bmesh_free_block(olddata, &eed->head.data);
794  eed->head.data = block;
795  }
796  }
797  else if (data == &bm->ldata) {
798  BMIter liter;
799  BMFace *efa;
800  BMLoop *l;
801 
803  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
804  BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
805  block = NULL;
807  CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
809  l->head.data = block;
810  }
811  }
812  }
813  else if (data == &bm->pdata) {
814  BMFace *efa;
815 
817 
818  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
819  block = NULL;
821  CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
822  CustomData_bmesh_free_block(olddata, &efa->head.data);
823  efa->head.data = block;
824  }
825  }
826  else {
827  /* should never reach this! */
828  BLI_assert(0);
829  }
830 
831  if (oldpool) {
832  /* this should never happen but can when dissolve fails - T28960. */
833  BLI_assert(data->pool != oldpool);
834 
835  BLI_mempool_destroy(oldpool);
836  }
837 }
838 
840 {
841  CustomData olddata;
842 
843  olddata = *data;
844  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
845 
846  /* the pool is now owned by olddata and must not be shared */
847  data->pool = NULL;
848 
850 
851  update_data_blocks(bm, &olddata, data);
852  if (olddata.layers) {
853  MEM_freeN(olddata.layers);
854  }
855 }
856 
857 void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
858 {
859  CustomData olddata;
860 
861  olddata = *data;
862  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
863 
864  /* the pool is now owned by olddata and must not be shared */
865  data->pool = NULL;
866 
868 
869  update_data_blocks(bm, &olddata, data);
870  if (olddata.layers) {
871  MEM_freeN(olddata.layers);
872  }
873 }
874 
876 {
877  CustomData olddata;
878  bool has_layer;
879 
880  olddata = *data;
881  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
882 
883  /* the pool is now owned by olddata and must not be shared */
884  data->pool = NULL;
885 
886  has_layer = CustomData_free_layer_active(data, type, 0);
887  /* Assert because its expensive to realloc - better not do if layer isn't present. */
888  BLI_assert(has_layer != false);
889  UNUSED_VARS_NDEBUG(has_layer);
890 
891  update_data_blocks(bm, &olddata, data);
892  if (olddata.layers) {
893  MEM_freeN(olddata.layers);
894  }
895 }
896 
897 bool BM_data_layer_free_named(BMesh *bm, CustomData *data, const char *name)
898 {
899  CustomData olddata = *data;
900  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
901 
902  /* the pool is now owned by olddata and must not be shared */
903  data->pool = NULL;
904 
905  const bool has_layer = CustomData_free_layer_named(data, name, 0);
906 
907  if (has_layer) {
908  update_data_blocks(bm, &olddata, data);
909  }
910  else {
911  /* Move pool ownership back to BMesh CustomData, no block reallocation. */
912  data->pool = olddata.pool;
913  }
914 
915  if (olddata.layers) {
916  MEM_freeN(olddata.layers);
917  }
918 
919  return has_layer;
920 }
921 
923 {
924  CustomData olddata;
925  bool has_layer;
926 
927  olddata = *data;
928  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
929 
930  /* the pool is now owned by olddata and must not be shared */
931  data->pool = NULL;
932 
934  /* Assert because its expensive to realloc - better not do if layer isn't present. */
935  BLI_assert(has_layer != false);
936  UNUSED_VARS_NDEBUG(has_layer);
937 
938  update_data_blocks(bm, &olddata, data);
939  if (olddata.layers) {
940  MEM_freeN(olddata.layers);
941  }
942 }
943 
944 void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n)
945 {
946  BMIter iter;
947 
948  if (&bm->vdata == data) {
949  BMVert *eve;
950 
951  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
952  void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n);
953  CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr);
954  }
955  }
956  else if (&bm->edata == data) {
957  BMEdge *eed;
958 
959  BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
960  void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n);
961  CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr);
962  }
963  }
964  else if (&bm->pdata == data) {
965  BMFace *efa;
966 
967  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
968  void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n);
969  CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr);
970  }
971  }
972  else if (&bm->ldata == data) {
973  BMIter liter;
974  BMFace *efa;
975  BMLoop *l;
976 
977  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
978  BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
979  void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n);
981  }
982  }
983  }
984  else {
985  /* should never reach this! */
986  BLI_assert(0);
987  }
988 }
989 
991 {
992  const float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
993  return f ? *f : 0.0f;
994 }
995 
996 void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
997 {
998  float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
999  if (f) {
1000  *f = val;
1001  }
1002 }
1003 
1004 /* -------------------------------------------------------------------- */
1023 struct LoopWalkCtx {
1024  /* same for all groups */
1025  int type;
1027  const float *loop_weights;
1029 
1030  /* --- Per loop fan vars --- */
1031 
1032  /* reference for this contiguous fan */
1033  const void *data_ref;
1035 
1036  /* accumulate 'LoopGroupCD.weight' to make unit length */
1038 
1039  /* both arrays the size of the 'BM_vert_face_count(v)'
1040  * each contiguous fan gets a slide of these arrays */
1041  void **data_array;
1044 };
1045 
1046 /* Store vars to pass into 'CustomData_bmesh_interp' */
1047 struct LoopGroupCD {
1048  /* direct customdata pointer array */
1049  void **data;
1050  /* weights (aligned with 'data') */
1052  /* index-in-face */
1054  /* number of loops in the fan */
1056 };
1057 
1058 static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l)
1059 {
1060  const int i = BM_elem_index_get(l);
1061  const float w = lwc->loop_weights[i];
1064  lwc->data_index_array[lwc->data_len] = i;
1065  lwc->weight_array[lwc->data_len] = w;
1066  lwc->weight_accum += w;
1067 
1068  lwc->data_len += 1;
1069 }
1070 
1076 static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk)
1077 {
1078  int i;
1079 
1081  lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset)));
1083 
1084  bm_loop_walk_add(lwc, l_walk);
1085 
1086  /* recurse around this loop-fan (in both directions) */
1087  for (i = 0; i < 2; i++) {
1088  BMLoop *l_other = ((i == 0) ? l_walk : l_walk->prev)->radial_next;
1089  if (l_other->radial_next != l_other) {
1090  if (l_other->v != l_walk->v) {
1091  l_other = l_other->next;
1092  }
1093  BLI_assert(l_other->v == l_walk->v);
1094  if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) {
1096  lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset))) {
1097  bm_loop_walk_data(lwc, l_other);
1098  }
1099  }
1100  }
1101  }
1102 }
1103 
1105  BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
1106 {
1107  struct LoopWalkCtx lwc;
1108  LinkNode *groups = NULL;
1109  BMLoop *l;
1110  BMIter liter;
1111  int loop_num;
1112 
1113  lwc.type = bm->ldata.layers[layer_n].type;
1114  lwc.cd_layer_offset = bm->ldata.layers[layer_n].offset;
1115  lwc.loop_weights = loop_weights;
1116  lwc.arena = arena;
1117 
1118  /* Enable 'BM_ELEM_INTERNAL_TAG', leaving the flag clean on completion. */
1119  loop_num = 0;
1120  BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
1122  BM_elem_index_set(l, loop_num); /* set_dirty! */
1123  loop_num++;
1124  }
1126 
1127  lwc.data_len = 0;
1128  lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num);
1129  lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num);
1130  lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num);
1131 
1132  BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
1134  struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf));
1135  int len_prev = lwc.data_len;
1136 
1138 
1139  /* assign len-last */
1140  lf->data = &lwc.data_array[lwc.data_len];
1141  lf->data_index = &lwc.data_index_array[lwc.data_len];
1142  lf->data_weights = &lwc.weight_array[lwc.data_len];
1143  lwc.weight_accum = 0.0f;
1144 
1145  /* new group */
1146  bm_loop_walk_data(&lwc, l);
1147  lf->data_len = lwc.data_len - len_prev;
1148 
1149  if (LIKELY(lwc.weight_accum != 0.0f)) {
1150  mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum);
1151  }
1152  else {
1153  copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len);
1154  }
1155 
1156  BLI_linklist_prepend_arena(&groups, lf, lwc.arena);
1157  }
1158  }
1159 
1160  BLI_assert(lwc.data_len == loop_num);
1161 
1162  return groups;
1163 }
1164 
1166  void *lf_p,
1167  int layer_n,
1168  void *data_tmp)
1169 {
1170  struct LoopGroupCD *lf = lf_p;
1171  const int type = bm->ldata.layers[layer_n].type;
1172  int i;
1173  const float *data_weights;
1174 
1175  data_weights = lf->data_weights;
1176 
1178  &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n);
1179 
1180  for (i = 0; i < lf->data_len; i++) {
1181  CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
1182  }
1183 }
1184 
1186  BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, const float *loop_weights)
1187 {
1188  struct LoopGroupCD *lf = lf_p;
1189  const int type = bm->ldata.layers[layer_n].type;
1190  int i;
1191  const float *data_weights;
1192 
1193  /* re-weight */
1194  float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len);
1195  float weight_accum = 0.0f;
1196 
1197  for (i = 0; i < lf->data_len; i++) {
1198  float w = loop_weights[lf->data_index[i]] * lf->data_weights[i];
1199  temp_weights[i] = w;
1200  weight_accum += w;
1201  }
1202 
1203  if (LIKELY(weight_accum != 0.0f)) {
1204  mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum);
1205  data_weights = temp_weights;
1206  }
1207  else {
1208  data_weights = lf->data_weights;
1209  }
1210 
1212  &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n);
1213 
1214  for (i = 0; i < lf->data_len; i++) {
1215  CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
1216  }
1217 }
1218 
1219 void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
1220 {
1221  const int type = bm->ldata.layers[layer_n].type;
1222  const int size = CustomData_sizeof(type);
1223  void *data_tmp = alloca(size);
1224 
1225  do {
1226  bm_vert_loop_groups_data_layer_merge__single(bm, groups->link, layer_n, data_tmp);
1227  } while ((groups = groups->next));
1228 }
1229 
1231  LinkNode *groups,
1232  const int layer_n,
1233  const float *loop_weights)
1234 {
1235  const int type = bm->ldata.layers[layer_n].type;
1236  const int size = CustomData_sizeof(type);
1237  void *data_tmp = alloca(size);
1238 
1239  do {
1241  bm, groups->link, layer_n, data_tmp, loop_weights);
1242  } while ((groups = groups->next));
1243 }
1244 
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_free_layer_named(struct CustomData *data, const char *name, const int totelem)
Definition: customdata.cc:2883
bool CustomData_free_layer_active(struct CustomData *data, int type, int totelem)
Definition: customdata.cc:2895
bool CustomData_free_layer(struct CustomData *data, int type, int totelem, int index)
Definition: customdata.cc:2831
@ CD_DEFAULT
void CustomData_bmesh_interp_n(struct CustomData *data, const void **src_blocks, const float *weights, const float *sub_weights, int count, void *dst_block_ofs, int n)
Definition: customdata.cc:4071
bool CustomData_data_equals(int type, const void *data1, const void *data2)
Definition: customdata.cc:3973
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n)
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.cc:2792
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, char htype)
Definition: customdata.cc:3541
void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n, const void *source)
Definition: customdata.cc:4037
void CustomData_bmesh_set_default(struct CustomData *data, void **block)
Definition: customdata.cc:3756
void CustomData_bmesh_copy_data(const struct CustomData *source, struct CustomData *dest, void *src_block, void **dest_block)
int CustomData_sizeof(int type)
Definition: customdata.cc:4268
void CustomData_bmesh_free_block_data(struct CustomData *data, void *block)
Definition: customdata.cc:3689
void * CustomData_bmesh_get(const struct CustomData *data, void *block, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count)
Definition: customdata.cc:3082
int CustomData_get_offset(const struct CustomData *data, int type)
void CustomData_bmesh_interp(struct CustomData *data, const void **src_blocks, const float *weights, const float *sub_weights, int count, void *dst_block)
Definition: customdata.cc:4088
void CustomData_bmesh_free_block(struct CustomData *data, void **block)
Definition: customdata.cc:3665
void * CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n)
void old_mdisps_bilinear(float out[3], float(*disps)[3], int st, float u, float v)
Definition: multires.c:1277
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
sqrt(x)+1/max(0
int isect_point_quad_v2(const float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
Definition: math_geom.c:1536
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
void resolve_quad_uv_v2(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
Definition: math_geom.c:4341
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
void interp_weights_poly_v2(float w[], float v[][2], int n, const float co[2])
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
Definition: math_matrix.c:917
void mid_v3_v3v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_vector.c:263
void mul_vn_fl(float *array_tar, int size, float f)
Definition: math_vector.c:1093
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void copy_vn_fl(float *array_tar, int size, float val)
Definition: math_vector.c:1259
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
Definition: math_vector.c:600
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
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:732
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
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 BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:707
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
#define UNUSED_FUNCTION(x)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define UNLIKELY(x)
#define LIKELY(x)
_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 y
_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 type
_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_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_INTERNAL_TAG
Definition: bmesh_class.h:496
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:15
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:111
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:14
LinkNode * BM_vert_loop_groups_data_layer_create(BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src)
Definition: bmesh_interp.c:559
static void mdisp_axis_from_quad(const float v1[3], const float v2[3], float UNUSED(v3[3]), const float v4[3], float r_axis_x[3], float r_axis_y[3])
Definition: bmesh_interp.c:287
static int compute_mdisp_quad(const BMLoop *l, const float l_f_center[3], float v1[3], float v2[3], float v3[3], float v4[3], float e1[3], float e2[3])
Multires Interpolation.
Definition: bmesh_interp.c:211
void BM_loop_interp_multires_ex(BMesh *UNUSED(bm), BMLoop *l_dst, const BMFace *f_src, const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset)
Definition: bmesh_interp.c:472
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
Definition: bmesh_interp.c:922
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:875
float BM_elem_float_data_get(CustomData *cd, void *element, int type)
Definition: bmesh_interp.c:990
void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
Definition: bmesh_interp.c:736
void BM_face_interp_multires_ex(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset)
Definition: bmesh_interp.c:544
static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk)
void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n)
Definition: bmesh_interp.c:944
void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
static void bm_vert_loop_groups_data_layer_merge__single(BMesh *bm, void *lf_p, int layer_n, void *data_tmp)
void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm, LinkNode *groups, const int layer_n, const float *loop_weights)
static void UNUSED_FUNCTION() BM_Data_Vert_Average(BMesh *UNUSED(bm), BMFace *UNUSED(f))
Data Vert Average.
Definition: bmesh_interp.c:88
bool BM_data_layer_free_named(BMesh *bm, CustomData *data, const char *name)
Definition: bmesh_interp.c:897
struct BMLoopInterpMultiresData BMLoopInterpMultiresData
void BM_face_interp_from_face_ex(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex, const void **blocks_l, const void **blocks_v, float(*cos_2d)[2], float axis_mat[3][3])
Data Interpolate From Face.
Definition: bmesh_interp.c:136
static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
Definition: bmesh_interp.c:765
static bool mdisp_in_mdispquad(BMLoop *l_src, BMLoop *l_dst, const float l_dst_f_center[3], const float p[3], int res, float r_axis_x[3], float r_axis_y[3], float r_uv[2])
Definition: bmesh_interp.c:307
void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
Definition: bmesh_interp.c:529
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:839
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
Definition: bmesh_interp.c:857
void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac)
Data, Interpolate From Edges.
Definition: bmesh_interp.c:75
void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex)
Definition: bmesh_interp.c:169
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
Definition: bmesh_interp.c:574
void BM_loop_interp_from_face(BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires)
Definition: bmesh_interp.c:682
static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l)
static bool quad_co(const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float p[3], const float n[3], float r_uv[2])
Definition: bmesh_interp.c:245
void BM_data_interp_face_vert_edge(BMesh *bm, const BMVert *v_src_1, const BMVert *UNUSED(v_src_2), BMVert *v, BMEdge *e, const float fac)
Definition: bmesh_interp.c:93
static void bm_vert_loop_groups_data_layer_merge_weights__single(BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, const float *loop_weights)
static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3], const float coord[3], int i, int j)
Definition: bmesh_interp.c:355
void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
Definition: bmesh_interp.c:996
static void loop_interp_multires_cb(void *__restrict userdata, const int ix, const TaskParallelTLS *__restrict UNUSED(tls))
Definition: bmesh_interp.c:421
static void bm_loop_flip_disp(const float source_axis_x[3], const float source_axis_y[3], const float target_axis_x[3], const float target_axis_y[3], float disp[3])
Definition: bmesh_interp.c:373
static void bm_data_interp_from_elem(CustomData *data_layer, const BMElem *ele_src_1, const BMElem *ele_src_2, BMElem *ele_dst, const float fac)
Definition: bmesh_interp.c:27
void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
Data, Interpolate From Verts.
Definition: bmesh_interp.c:68
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
ATTR_WARN_UNUSED_RESULT const void * element
void poly_rotate_plane(const float normal[3], float(*verts)[3], const uint nverts)
POLY ROTATE PLANE.
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
void BM_vert_normal_update_all(BMVert *v)
bool BM_face_is_normal_valid(const BMFace *f)
Definition: bmesh_query.c:2033
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
SyclQueue void void * src
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned c
Definition: RandGen.cpp:83
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
const btScalar eps
Definition: poly34.cpp:11
BMHeader head
Definition: bmesh_class.h:111
BMHeader head
Definition: bmesh_class.h:243
int len
Definition: bmesh_class.h:267
BMHeader head
Definition: bmesh_class.h:255
float no[3]
Definition: bmesh_class.h:271
void * data
Definition: bmesh_class.h:51
const float * f_src_center
Definition: bmesh_interp.c:411
BMHeader head
Definition: bmesh_class.h:145
struct BMVert * v
Definition: bmesh_class.h:153
struct BMLoop * radial_next
Definition: bmesh_class.h:204
struct BMLoop * prev
Definition: bmesh_class.h:233
struct BMFace * f
Definition: bmesh_class.h:171
struct BMLoop * next
Definition: bmesh_class.h:233
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
BMHeader head
Definition: bmesh_class.h:85
int totvert
Definition: bmesh_class.h:297
char elem_index_dirty
Definition: bmesh_class.h:305
CustomData vdata
Definition: bmesh_class.h:337
int totedge
Definition: bmesh_class.h:297
CustomData edata
Definition: bmesh_class.h:337
int totloop
Definition: bmesh_class.h:297
CustomData pdata
Definition: bmesh_class.h:337
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
struct BLI_mempool * pool
CustomDataLayer * layers
void * link
Definition: BLI_linklist.h:24
struct LinkNode * next
Definition: BLI_linklist.h:23
int * data_index
void ** data
float * data_weights
const float * loop_weights
float weight_accum
float * weight_array
const void * data_ref
int * data_index_array
void ** data_array
MemArena * arena
float(* disps)[3]
PointerRNA * ptr
Definition: wm_files.c:3480