Blender  V2.93
bmesh_interp.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  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_meshdata_types.h"
29 
30 #include "BLI_alloca.h"
31 #include "BLI_linklist.h"
32 #include "BLI_math.h"
33 #include "BLI_memarena.h"
34 #include "BLI_task.h"
35 
36 #include "BKE_customdata.h"
37 #include "BKE_multires.h"
38 
39 #include "bmesh.h"
40 #include "intern/bmesh_private.h"
41 
42 /* edge and vertex share, currently there's no need to have different logic */
43 static void bm_data_interp_from_elem(CustomData *data_layer,
44  const BMElem *ele_src_1,
45  const BMElem *ele_src_2,
46  BMElem *ele_dst,
47  const float fac)
48 {
49  if (ele_src_1->head.data && ele_src_2->head.data) {
50  /* first see if we can avoid interpolation */
51  if (fac <= 0.0f) {
52  if (ele_src_1 == ele_dst) {
53  /* do nothing */
54  }
55  else {
56  CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
58  data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data);
59  }
60  }
61  else if (fac >= 1.0f) {
62  if (ele_src_2 == ele_dst) {
63  /* do nothing */
64  }
65  else {
66  CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
68  data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data);
69  }
70  }
71  else {
72  const void *src[2];
73  float w[2];
74 
75  src[0] = ele_src_1->head.data;
76  src[1] = ele_src_2->head.data;
77  w[0] = 1.0f - fac;
78  w[1] = fac;
79  CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data);
80  }
81  }
82 }
83 
92  BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
93 {
95  &bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac);
96 }
97 
106  BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac)
107 {
109  &bm->edata, (const BMElem *)e_src_1, (const BMElem *)e_src_2, (BMElem *)e_dst, fac);
110 }
111 
119 {
120  // BMIter iter;
121 }
122 
130  const BMVert *v_src_1,
131  const BMVert *UNUSED(v_src_2),
132  BMVert *v,
133  BMEdge *e,
134  const float fac)
135 {
136  float w[2];
137  BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL;
138  BMLoop *l_iter = NULL;
139 
140  if (!e->l) {
141  return;
142  }
143 
144  w[1] = 1.0f - fac;
145  w[0] = fac;
146 
147  l_iter = e->l;
148  do {
149  if (l_iter->v == v_src_1) {
150  l_v1 = l_iter;
151  l_v = l_v1->next;
152  l_v2 = l_v->next;
153  }
154  else if (l_iter->v == v) {
155  l_v1 = l_iter->next;
156  l_v = l_iter;
157  l_v2 = l_iter->prev;
158  }
159 
160  if (!l_v1 || !l_v2) {
161  return;
162  }
163 
164  const void *src[2];
165  src[0] = l_v1->head.data;
166  src[1] = l_v2->head.data;
167 
168  CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
169  } while ((l_iter = l_iter->radial_next) != e->l);
170 }
171 
181  BMFace *f_dst,
182  const BMFace *f_src,
183  const bool do_vertex,
184  const void **blocks_l,
185  const void **blocks_v,
186  float (*cos_2d)[2],
187  float axis_mat[3][3])
188 {
189  BMLoop *l_iter;
190  BMLoop *l_first;
191 
192  float *w = BLI_array_alloca(w, f_src->len);
193  float co[2];
194  int i;
195 
196  if (f_src != f_dst) {
197  BM_elem_attrs_copy(bm, bm, f_src, f_dst);
198  }
199 
200  /* interpolate */
201  i = 0;
202  l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
203  do {
204  mul_v2_m3v3(co, axis_mat, l_iter->v->co);
205  interp_weights_poly_v2(w, cos_2d, f_src->len, co);
206  CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data);
207  if (do_vertex) {
208  CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data);
209  }
210  } while ((void)i++, (l_iter = l_iter->next) != l_first);
211 }
212 
213 void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex)
214 {
215  BMLoop *l_iter;
216  BMLoop *l_first;
217 
218  const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len);
219  const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL;
220  float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
221  float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
222  int i;
223 
224  /* convert the 3d coords into 2d for projection */
226  axis_dominant_v3_to_m3(axis_mat, f_src->no);
227 
228  i = 0;
229  l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
230  do {
231  mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
232  blocks_l[i] = l_iter->head.data;
233  if (do_vertex) {
234  blocks_v[i] = l_iter->v->head.data;
235  }
236  } while ((void)i++, (l_iter = l_iter->next) != l_first);
237 
238  BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex, blocks_l, blocks_v, cos_2d, axis_mat);
239 }
240 
255 static int compute_mdisp_quad(const BMLoop *l,
256  const float l_f_center[3],
257  float v1[3],
258  float v2[3],
259  float v3[3],
260  float v4[3],
261  float e1[3],
262  float e2[3])
263 {
264  float n[3], p[3];
265 
266 #ifndef NDEBUG
267  {
268  float cent[3];
269  /* computer center */
271  BLI_assert(equals_v3v3(cent, l_f_center));
272  }
273 #endif
274 
275  mid_v3_v3v3(p, l->prev->v->co, l->v->co);
276  mid_v3_v3v3(n, l->next->v->co, l->v->co);
277 
278  copy_v3_v3(v1, l_f_center);
279  copy_v3_v3(v2, p);
280  copy_v3_v3(v3, l->v->co);
281  copy_v3_v3(v4, n);
282 
283  sub_v3_v3v3(e1, v2, v1);
284  sub_v3_v3v3(e2, v3, v4);
285 
286  return 1;
287 }
288 
289 static bool quad_co(const float v1[3],
290  const float v2[3],
291  const float v3[3],
292  const float v4[3],
293  const float p[3],
294  const float n[3],
295  float r_uv[2])
296 {
297  float projverts[5][3], n2[3];
298  const float origin[2] = {0.0f, 0.0f};
299  int i;
300 
301  /* project points into 2d along normal */
302  copy_v3_v3(projverts[0], v1);
303  copy_v3_v3(projverts[1], v2);
304  copy_v3_v3(projverts[2], v3);
305  copy_v3_v3(projverts[3], v4);
306  copy_v3_v3(projverts[4], p);
307 
308  normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]);
309 
310  if (dot_v3v3(n, n2) < -FLT_EPSILON) {
311  return false;
312  }
313 
314  /* rotate */
315  poly_rotate_plane(n, projverts, 5);
316 
317  /* subtract origin */
318  for (i = 0; i < 4; i++) {
319  sub_v2_v2(projverts[i], projverts[4]);
320  }
321 
322  if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) {
323  return false;
324  }
325 
326  resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]);
327 
328  return true;
329 }
330 
331 static void mdisp_axis_from_quad(const float v1[3],
332  const float v2[3],
333  float UNUSED(v3[3]),
334  const float v4[3],
335  float r_axis_x[3],
336  float r_axis_y[3])
337 {
338  sub_v3_v3v3(r_axis_x, v4, v1);
339  sub_v3_v3v3(r_axis_y, v2, v1);
340 
341  normalize_v3(r_axis_x);
342  normalize_v3(r_axis_y);
343 }
344 
351 static bool mdisp_in_mdispquad(BMLoop *l_src,
352  BMLoop *l_dst,
353  const float l_dst_f_center[3],
354  const float p[3],
355  int res,
356  float r_axis_x[3],
357  float r_axis_y[3],
358  float r_uv[2])
359 {
360  float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
361  float eps = FLT_EPSILON * 4000;
362 
363  if (is_zero_v3(l_src->v->no)) {
365  }
366  if (is_zero_v3(l_dst->v->no)) {
368  }
369 
370  compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2);
371 
372  /* expand quad a bit */
373  mid_v3_v3v3v3v3(c, v1, v2, v3, v4);
374 
375  sub_v3_v3(v1, c);
376  sub_v3_v3(v2, c);
377  sub_v3_v3(v3, c);
378  sub_v3_v3(v4, c);
379  mul_v3_fl(v1, 1.0f + eps);
380  mul_v3_fl(v2, 1.0f + eps);
381  mul_v3_fl(v3, 1.0f + eps);
382  mul_v3_fl(v4, 1.0f + eps);
383  add_v3_v3(v1, c);
384  add_v3_v3(v2, c);
385  add_v3_v3(v3, c);
386  add_v3_v3(v4, c);
387 
388  if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) {
389  return 0;
390  }
391 
392  mul_v2_fl(r_uv, (float)(res - 1));
393 
394  mdisp_axis_from_quad(v1, v2, v3, v4, r_axis_x, r_axis_y);
395 
396  return 1;
397 }
398 
399 static float bm_loop_flip_equotion(float mat[2][2],
400  float b[2],
401  const float target_axis_x[3],
402  const float target_axis_y[3],
403  const float coord[3],
404  int i,
405  int j)
406 {
407  mat[0][0] = target_axis_x[i];
408  mat[0][1] = target_axis_y[i];
409  mat[1][0] = target_axis_x[j];
410  mat[1][1] = target_axis_y[j];
411  b[0] = coord[i];
412  b[1] = coord[j];
413 
414  return cross_v2v2(mat[0], mat[1]);
415 }
416 
417 static void bm_loop_flip_disp(const float source_axis_x[3],
418  const float source_axis_y[3],
419  const float target_axis_x[3],
420  const float target_axis_y[3],
421  float disp[3])
422 {
423  float vx[3], vy[3], coord[3];
424  float n[3], vec[3];
425  float b[2], mat[2][2], d;
426 
427  mul_v3_v3fl(vx, source_axis_x, disp[0]);
428  mul_v3_v3fl(vy, source_axis_y, disp[1]);
429  add_v3_v3v3(coord, vx, vy);
430 
431  /* project displacement from source grid plane onto target grid plane */
432  cross_v3_v3v3(n, target_axis_x, target_axis_y);
433  project_v3_v3v3(vec, coord, n);
434  sub_v3_v3v3(coord, coord, vec);
435 
436  d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1);
437 
438  if (fabsf(d) < 1e-4f) {
439  d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2);
440  if (fabsf(d) < 1e-4f) {
441  d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2);
442  }
443  }
444 
445  disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d;
446  disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d;
447 }
448 
449 typedef struct BMLoopInterpMultiresData {
453 
455  const float *f_src_center;
456 
457  float *axis_x, *axis_y;
458  float *v1, *v4;
459  float *e1, *e2;
460 
461  int res;
462  float d;
464 
465 static void loop_interp_multires_cb(void *__restrict userdata,
466  const int ix,
467  const TaskParallelTLS *__restrict UNUSED(tls))
468 {
469  BMLoopInterpMultiresData *data = userdata;
470 
471  BMLoop *l_first = data->l_src_first;
472  BMLoop *l_dst = data->l_dst;
473  const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset;
474 
475  MDisps *md_dst = data->md_dst;
476  const float *f_src_center = data->f_src_center;
477 
478  float *axis_x = data->axis_x;
479  float *axis_y = data->axis_y;
480 
481  float *v1 = data->v1;
482  float *v4 = data->v4;
483  float *e1 = data->e1;
484  float *e2 = data->e2;
485 
486  const int res = data->res;
487  const float d = data->d;
488 
489  float x = d * ix, y;
490  int iy;
491  for (y = 0.0f, iy = 0; iy < res; y += d, iy++) {
492  BMLoop *l_iter = l_first;
493  float co1[3], co2[3], co[3];
494 
495  madd_v3_v3v3fl(co1, v1, e1, y);
496  madd_v3_v3v3fl(co2, v4, e2, y);
497  interp_v3_v3v3(co, co1, co2, x);
498 
499  do {
500  MDisps *md_src;
501  float src_axis_x[3], src_axis_y[3];
502  float uv[2];
503 
504  md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
505 
506  if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
507  old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
508  bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]);
509 
510  break;
511  }
512  } while ((l_iter = l_iter->next) != l_first);
513  }
514 }
515 
517  BMLoop *l_dst,
518  const BMFace *f_src,
519  const float f_dst_center[3],
520  const float f_src_center[3],
521  const int cd_loop_mdisp_offset)
522 {
523  MDisps *md_dst;
524  float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
525  float axis_x[3], axis_y[3];
526 
527  /* ignore 2-edged faces */
528  if (UNLIKELY(l_dst->f->len < 3)) {
529  return;
530  }
531 
532  md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset);
533  compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2);
534 
535  /* if no disps data allocate a new grid, the size of the first grid in f_src. */
536  if (!md_dst->totdisp) {
537  const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
538 
539  md_dst->totdisp = md_src->totdisp;
540  md_dst->level = md_src->level;
541  if (md_dst->totdisp) {
542  md_dst->disps = MEM_callocN(sizeof(float[3]) * md_dst->totdisp, __func__);
543  }
544  else {
545  return;
546  }
547  }
548 
549  mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
550 
551  const int res = (int)sqrt(md_dst->totdisp);
553  .l_dst = l_dst,
554  .l_src_first = BM_FACE_FIRST_LOOP(f_src),
555  .cd_loop_mdisp_offset = cd_loop_mdisp_offset,
556  .md_dst = md_dst,
557  .f_src_center = f_src_center,
558  .axis_x = axis_x,
559  .axis_y = axis_y,
560  .v1 = v1,
561  .v4 = v4,
562  .e1 = e1,
563  .e2 = e2,
564  .res = res,
565  .d = 1.0f / (float)(res - 1),
566  };
567  TaskParallelSettings settings;
569  settings.use_threading = (res > 5);
571 }
572 
576 void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
577 {
578  const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
579 
580  if (cd_loop_mdisp_offset != -1) {
581  float f_dst_center[3];
582  float f_src_center[3];
583 
584  BM_face_calc_center_median(l_dst->f, f_dst_center);
585  BM_face_calc_center_median(f_src, f_src_center);
586 
587  BM_loop_interp_multires_ex(bm, l_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
588  }
589 }
590 
592  BMFace *f_dst,
593  const BMFace *f_src,
594  const float f_dst_center[3],
595  const float f_src_center[3],
596  const int cd_loop_mdisp_offset)
597 {
598  BMLoop *l_iter, *l_first;
599  l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
600  do {
602  bm, l_iter, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
603  } while ((l_iter = l_iter->next) != l_first);
604 }
605 
606 void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src)
607 {
608  const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
609 
610  if (cd_loop_mdisp_offset != -1) {
611  float f_dst_center[3];
612  float f_src_center[3];
613 
614  BM_face_calc_center_median(f_dst, f_dst_center);
615  BM_face_calc_center_median(f_src, f_src_center);
616 
617  BM_face_interp_multires_ex(bm, f_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
618  }
619 }
620 
626 {
627  const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
628  BMLoop *l;
629  BMIter liter;
630 
631  if (cd_loop_mdisp_offset == -1) {
632  return;
633  }
634 
635  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
636  MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset);
637  MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
638  MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset);
639  float co1[3];
640  int sides;
641  int y;
642 
658  sides = (int)sqrt(mdp->totdisp);
659  for (y = 0; y < sides; y++) {
660  mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]);
661 
662  copy_v3_v3(mdn->disps[y * sides], co1);
663  copy_v3_v3(mdl->disps[y], co1);
664  }
665  }
666 
667  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
668  MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
669  MDisps *mdl2;
670  float co1[3], co2[3], co[3];
671  int sides;
672  int y;
673 
689  if (l->radial_next == l) {
690  continue;
691  }
692 
693  if (l->radial_next->v == l->v) {
694  mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset);
695  }
696  else {
697  mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset);
698  }
699 
700  sides = (int)sqrt(mdl1->totdisp);
701  for (y = 0; y < sides; y++) {
702  int a1, a2, o1, o2;
703 
704  if (l->v != l->radial_next->v) {
705  a1 = sides * y + sides - 2;
706  a2 = (sides - 2) * sides + y;
707 
708  o1 = sides * y + sides - 1;
709  o2 = (sides - 1) * sides + y;
710  }
711  else {
712  a1 = sides * y + sides - 2;
713  a2 = sides * y + sides - 2;
714  o1 = sides * y + sides - 1;
715  o2 = sides * y + sides - 1;
716  }
717 
718  /* magic blending numbers, hardcoded! */
719  add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]);
720  mul_v3_fl(co1, 0.18);
721 
722  add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
723  mul_v3_fl(co2, 0.32);
724 
725  add_v3_v3v3(co, co1, co2);
726 
727  copy_v3_v3(mdl1->disps[o1], co);
728  copy_v3_v3(mdl2->disps[o2], co);
729  }
730  }
731 }
732 
738  BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires)
739 {
740  BMLoop *l_iter;
741  BMLoop *l_first;
742  const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL;
743  const void **blocks = BLI_array_alloca(blocks, f_src->len);
744  float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
745  float *w = BLI_array_alloca(w, f_src->len);
746  float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
747  float co[2];
748  int i;
749 
750  /* Convert the 3d coords into 2d for projection. */
751  float axis_dominant[3];
752  if (!is_zero_v3(f_src->no)) {
754  copy_v3_v3(axis_dominant, f_src->no);
755  }
756  else {
757  /* Rare case in which all the vertices of the face are aligned.
758  * Get a random axis that is orthogonal to the tangent. */
759  float vec[3];
760  BM_face_calc_tangent_auto(f_src, vec);
761  ortho_v3_v3(axis_dominant, vec);
762  normalize_v3(axis_dominant);
763  }
764  axis_dominant_v3_to_m3(axis_mat, axis_dominant);
765 
766  i = 0;
767  l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
768  do {
769  mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
770  blocks[i] = l_iter->head.data;
771 
772  if (do_vertex) {
773  vblocks[i] = l_iter->v->head.data;
774  }
775  } while ((void)i++, (l_iter = l_iter->next) != l_first);
776 
777  mul_v2_m3v3(co, axis_mat, l_dst->v->co);
778 
779  /* interpolate */
780  interp_weights_poly_v2(w, cos_2d, f_src->len, co);
781  CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data);
782  if (do_vertex) {
783  CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data);
784  }
785 
786  if (do_multires) {
787  BM_loop_interp_multires(bm, l_dst, f_src);
788  }
789 }
790 
791 void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
792 {
793  BMLoop *l_iter;
794  BMLoop *l_first;
795  const void **blocks = BLI_array_alloca(blocks, f_src->len);
796  float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
797  float *w = BLI_array_alloca(w, f_src->len);
798  float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
799  float co[2];
800  int i;
801 
802  /* convert the 3d coords into 2d for projection */
804  axis_dominant_v3_to_m3(axis_mat, f_src->no);
805 
806  i = 0;
807  l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
808  do {
809  mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
810  blocks[i] = l_iter->v->head.data;
811  } while ((void)i++, (l_iter = l_iter->next) != l_first);
812 
813  mul_v2_m3v3(co, axis_mat, v_dst->co);
814 
815  /* interpolate */
816  interp_weights_poly_v2(w, cos_2d, f_src->len, co);
817  CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data);
818 }
819 
821 {
822  BMIter iter;
823  BLI_mempool *oldpool = olddata->pool;
824  void *block;
825 
826  if (data == &bm->vdata) {
827  BMVert *eve;
828 
830 
831  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
832  block = NULL;
834  CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
835  CustomData_bmesh_free_block(olddata, &eve->head.data);
836  eve->head.data = block;
837  }
838  }
839  else if (data == &bm->edata) {
840  BMEdge *eed;
841 
843 
844  BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
845  block = NULL;
847  CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
848  CustomData_bmesh_free_block(olddata, &eed->head.data);
849  eed->head.data = block;
850  }
851  }
852  else if (data == &bm->ldata) {
853  BMIter liter;
854  BMFace *efa;
855  BMLoop *l;
856 
858  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
859  BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
860  block = NULL;
862  CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
864  l->head.data = block;
865  }
866  }
867  }
868  else if (data == &bm->pdata) {
869  BMFace *efa;
870 
872 
873  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
874  block = NULL;
876  CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
877  CustomData_bmesh_free_block(olddata, &efa->head.data);
878  efa->head.data = block;
879  }
880  }
881  else {
882  /* should never reach this! */
883  BLI_assert(0);
884  }
885 
886  if (oldpool) {
887  /* this should never happen but can when dissolve fails - T28960. */
888  BLI_assert(data->pool != oldpool);
889 
890  BLI_mempool_destroy(oldpool);
891  }
892 }
893 
895 {
896  CustomData olddata;
897 
898  olddata = *data;
899  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
900 
901  /* the pool is now owned by olddata and must not be shared */
902  data->pool = NULL;
903 
905 
906  update_data_blocks(bm, &olddata, data);
907  if (olddata.layers) {
908  MEM_freeN(olddata.layers);
909  }
910 }
911 
912 void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
913 {
914  CustomData olddata;
915 
916  olddata = *data;
917  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
918 
919  /* the pool is now owned by olddata and must not be shared */
920  data->pool = NULL;
921 
923 
924  update_data_blocks(bm, &olddata, data);
925  if (olddata.layers) {
926  MEM_freeN(olddata.layers);
927  }
928 }
929 
931 {
932  CustomData olddata;
933  bool has_layer;
934 
935  olddata = *data;
936  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
937 
938  /* the pool is now owned by olddata and must not be shared */
939  data->pool = NULL;
940 
941  has_layer = CustomData_free_layer_active(data, type, 0);
942  /* Assert because its expensive to realloc - better not do if layer isn't present. */
943  BLI_assert(has_layer != false);
944  UNUSED_VARS_NDEBUG(has_layer);
945 
946  update_data_blocks(bm, &olddata, data);
947  if (olddata.layers) {
948  MEM_freeN(olddata.layers);
949  }
950 }
951 
953 {
954  CustomData olddata;
955  bool has_layer;
956 
957  olddata = *data;
958  olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
959 
960  /* the pool is now owned by olddata and must not be shared */
961  data->pool = NULL;
962 
964  /* Assert because its expensive to realloc - better not do if layer isn't present. */
965  BLI_assert(has_layer != false);
966  UNUSED_VARS_NDEBUG(has_layer);
967 
968  update_data_blocks(bm, &olddata, data);
969  if (olddata.layers) {
970  MEM_freeN(olddata.layers);
971  }
972 }
973 
974 void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n)
975 {
976  BMIter iter;
977 
978  if (&bm->vdata == data) {
979  BMVert *eve;
980 
981  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
982  void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n);
983  CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr);
984  }
985  }
986  else if (&bm->edata == data) {
987  BMEdge *eed;
988 
989  BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
990  void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n);
991  CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr);
992  }
993  }
994  else if (&bm->pdata == data) {
995  BMFace *efa;
996 
997  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
998  void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n);
999  CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr);
1000  }
1001  }
1002  else if (&bm->ldata == data) {
1003  BMIter liter;
1004  BMFace *efa;
1005  BMLoop *l;
1006 
1007  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1008  BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1009  void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n);
1011  }
1012  }
1013  }
1014  else {
1015  /* should never reach this! */
1016  BLI_assert(0);
1017  }
1018 }
1019 
1021 {
1022  const float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
1023  return f ? *f : 0.0f;
1024 }
1025 
1026 void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
1027 {
1028  float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
1029  if (f) {
1030  *f = val;
1031  }
1032 }
1033 
1034 /* -------------------------------------------------------------------- */
1053 struct LoopWalkCtx {
1054  /* same for all groups */
1055  int type;
1057  const float *loop_weights;
1059 
1060  /* --- Per loop fan vars --- */
1061 
1062  /* reference for this contiguous fan */
1063  const void *data_ref;
1065 
1066  /* accumulate 'LoopGroupCD.weight' to make unit length */
1068 
1069  /* both arrays the size of the 'BM_vert_face_count(v)'
1070  * each contiguous fan gets a slide of these arrays */
1071  void **data_array;
1074 };
1075 
1076 /* Store vars to pass into 'CustomData_bmesh_interp' */
1077 struct LoopGroupCD {
1078  /* direct customdata pointer array */
1079  void **data;
1080  /* weights (aligned with 'data') */
1082  /* index-in-face */
1084  /* number of loops in the fan */
1086 };
1087 
1088 static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l)
1089 {
1090  const int i = BM_elem_index_get(l);
1091  const float w = lwc->loop_weights[i];
1094  lwc->data_index_array[lwc->data_len] = i;
1095  lwc->weight_array[lwc->data_len] = w;
1096  lwc->weight_accum += w;
1097 
1098  lwc->data_len += 1;
1099 }
1100 
1106 static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk)
1107 {
1108  int i;
1109 
1111  lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset)));
1113 
1114  bm_loop_walk_add(lwc, l_walk);
1115 
1116  /* recurse around this loop-fan (in both directions) */
1117  for (i = 0; i < 2; i++) {
1118  BMLoop *l_other = ((i == 0) ? l_walk : l_walk->prev)->radial_next;
1119  if (l_other->radial_next != l_other) {
1120  if (l_other->v != l_walk->v) {
1121  l_other = l_other->next;
1122  }
1123  BLI_assert(l_other->v == l_walk->v);
1124  if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) {
1126  lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset))) {
1127  bm_loop_walk_data(lwc, l_other);
1128  }
1129  }
1130  }
1131  }
1132 }
1133 
1135  BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
1136 {
1137  struct LoopWalkCtx lwc;
1138  LinkNode *groups = NULL;
1139  BMLoop *l;
1140  BMIter liter;
1141  int loop_num;
1142 
1143  lwc.type = bm->ldata.layers[layer_n].type;
1144  lwc.cd_layer_offset = bm->ldata.layers[layer_n].offset;
1145  lwc.loop_weights = loop_weights;
1146  lwc.arena = arena;
1147 
1148  /* Enable 'BM_ELEM_INTERNAL_TAG', leaving the flag clean on completion. */
1149  loop_num = 0;
1150  BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
1152  BM_elem_index_set(l, loop_num); /* set_dirty! */
1153  loop_num++;
1154  }
1156 
1157  lwc.data_len = 0;
1158  lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num);
1159  lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num);
1160  lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num);
1161 
1162  BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
1164  struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf));
1165  int len_prev = lwc.data_len;
1166 
1168 
1169  /* assign len-last */
1170  lf->data = &lwc.data_array[lwc.data_len];
1171  lf->data_index = &lwc.data_index_array[lwc.data_len];
1172  lf->data_weights = &lwc.weight_array[lwc.data_len];
1173  lwc.weight_accum = 0.0f;
1174 
1175  /* new group */
1176  bm_loop_walk_data(&lwc, l);
1177  lf->data_len = lwc.data_len - len_prev;
1178 
1179  if (LIKELY(lwc.weight_accum != 0.0f)) {
1180  mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum);
1181  }
1182  else {
1183  copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len);
1184  }
1185 
1186  BLI_linklist_prepend_arena(&groups, lf, lwc.arena);
1187  }
1188  }
1189 
1190  BLI_assert(lwc.data_len == loop_num);
1191 
1192  return groups;
1193 }
1194 
1196  void *lf_p,
1197  int layer_n,
1198  void *data_tmp)
1199 {
1200  struct LoopGroupCD *lf = lf_p;
1201  const int type = bm->ldata.layers[layer_n].type;
1202  int i;
1203  const float *data_weights;
1204 
1205  data_weights = lf->data_weights;
1206 
1208  &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n);
1209 
1210  for (i = 0; i < lf->data_len; i++) {
1211  CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
1212  }
1213 }
1214 
1216  BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, const float *loop_weights)
1217 {
1218  struct LoopGroupCD *lf = lf_p;
1219  const int type = bm->ldata.layers[layer_n].type;
1220  int i;
1221  const float *data_weights;
1222 
1223  /* re-weight */
1224  float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len);
1225  float weight_accum = 0.0f;
1226 
1227  for (i = 0; i < lf->data_len; i++) {
1228  float w = loop_weights[lf->data_index[i]] * lf->data_weights[i];
1229  temp_weights[i] = w;
1230  weight_accum += w;
1231  }
1232 
1233  if (LIKELY(weight_accum != 0.0f)) {
1234  mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum);
1235  data_weights = temp_weights;
1236  }
1237  else {
1238  data_weights = lf->data_weights;
1239  }
1240 
1242  &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n);
1243 
1244  for (i = 0; i < lf->data_len; i++) {
1245  CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
1246  }
1247 }
1248 
1252 void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
1253 {
1254  const int type = bm->ldata.layers[layer_n].type;
1255  const int size = CustomData_sizeof(type);
1256  void *data_tmp = alloca(size);
1257 
1258  do {
1259  bm_vert_loop_groups_data_layer_merge__single(bm, groups->link, layer_n, data_tmp);
1260  } while ((groups = groups->next));
1261 }
1262 
1268  LinkNode *groups,
1269  const int layer_n,
1270  const float *loop_weights)
1271 {
1272  const int type = bm->ldata.layers[layer_n].type;
1273  const int size = CustomData_sizeof(type);
1274  void *data_tmp = alloca(size);
1275 
1276  do {
1278  bm, groups->link, layer_n, data_tmp, loop_weights);
1279  } while ((groups = groups->next));
1280 }
1281 
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_free_layer_active(struct CustomData *data, int type, int totelem)
Definition: customdata.c:2707
bool CustomData_free_layer(struct CustomData *data, int type, int totelem, int index)
Definition: customdata.c:2655
@ 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.c:4031
bool CustomData_data_equals(int type, const void *data1, const void *data2)
Definition: customdata.c:3929
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n)
Definition: customdata.c:2308
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.c:2637
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype)
Definition: customdata.c:3482
void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n, const void *source)
Definition: customdata.c:3993
void CustomData_bmesh_set_default(struct CustomData *data, void **block)
Definition: customdata.c:3703
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.c:4277
void CustomData_bmesh_free_block_data(struct CustomData *data, void *block)
Definition: customdata.c:3633
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.c:2620
void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count)
Definition: customdata.c:2880
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.c:4048
void CustomData_bmesh_free_block(struct CustomData *data, void **block)
Definition: customdata.c:3606
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], const int st, float u, float v)
Definition: multires.c:1305
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:58
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:1616
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:68
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:4620
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
Definition: math_geom.c:3752
void interp_weights_poly_v2(float w[], float v[][2], const 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:921
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:296
void copy_vn_fl(float *array_tar, const int size, const float val)
Definition: math_vector.c:1410
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
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 project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
Definition: math_vector.c:674
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
void ortho_v3_v3(float out[3], const float v[3])
Definition: math_vector.c:875
MINLINE 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:270
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 mul_vn_fl(float *array_tar, const int size, const float f)
Definition: math_vector.c:1244
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:131
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:757
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
#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 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 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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
@ BM_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_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
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:124
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:29
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:125
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
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:606
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:331
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:255
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:516
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
Definition: bmesh_interp.c:952
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:930
float BM_elem_float_data_get(CustomData *cd, void *element, int type)
void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
Definition: bmesh_interp.c:791
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:591
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:974
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:118
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 Interp From Face.
Definition: bmesh_interp.c:180
static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
Definition: bmesh_interp.c:820
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:351
void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
Definition: bmesh_interp.c:576
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:894
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
Definition: bmesh_interp.c:912
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, Interp From Edges.
Definition: bmesh_interp.c:105
void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex)
Definition: bmesh_interp.c:213
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
Definition: bmesh_interp.c:625
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:737
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:289
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)
Data Face-Vert Edge Interp.
Definition: bmesh_interp.c:129
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:399
void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
static void loop_interp_multires_cb(void *__restrict userdata, const int ix, const TaskParallelTLS *__restrict UNUSED(tls))
Definition: bmesh_interp.c:465
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:417
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:43
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, Interp From Verts.
Definition: bmesh_interp.c:91
#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:2533
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
#define fabsf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static unsigned c
Definition: RandGen.cpp:97
const btScalar eps
Definition: poly34.cpp:11
BMHeader head
Definition: bmesh_class.h:123
BMHeader head
Definition: bmesh_class.h:255
int len
Definition: bmesh_class.h:279
BMHeader head
Definition: bmesh_class.h:267
float no[3]
Definition: bmesh_class.h:280
void * data
Definition: bmesh_class.h:63
const float * f_src_center
Definition: bmesh_interp.c:455
BMHeader head
Definition: bmesh_class.h:157
struct BMVert * v
Definition: bmesh_class.h:165
struct BMLoop * radial_next
Definition: bmesh_class.h:216
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
float no[3]
Definition: bmesh_class.h:100
BMHeader head
Definition: bmesh_class.h:97
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:40
struct LinkNode * next
Definition: BLI_linklist.h:39
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:3157