Code cleanup: use bool for static methods
[blender.git] / source / blender / bmesh / intern / bmesh_interp.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Geoffrey Bantle.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/bmesh/intern/bmesh_interp.c
29  *  \ingroup bmesh
30  *
31  * Functions for interpolating data across the surface of a mesh.
32  */
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_mesh_types.h"
37 #include "DNA_meshdata_types.h"
38
39 #include "BLI_alloca.h"
40 #include "BLI_math.h"
41
42 #include "BKE_customdata.h"
43 #include "BKE_multires.h"
44
45 #include "bmesh.h"
46 #include "intern/bmesh_private.h"
47
48 /* edge and vertex share, currently theres no need to have different logic */
49 static void bm_data_interp_from_elem(CustomData *data_layer, BMElem *ele1, BMElem *ele2, BMElem *ele_dst, const float fac)
50 {
51         if (ele1->head.data && ele2->head.data) {
52                 /* first see if we can avoid interpolation */
53                 if (fac <= 0.0f) {
54                         if (ele1 == ele_dst) {
55                                 /* do nothing */
56                         }
57                         else {
58                                 CustomData_bmesh_free_block_data(data_layer, &ele_dst->head.data);
59                                 CustomData_bmesh_copy_data(data_layer, data_layer, ele1->head.data, &ele_dst->head.data);
60                         }
61                 }
62                 else if (fac >= 1.0f) {
63                         if (ele2 == ele_dst) {
64                                 /* do nothing */
65                         }
66                         else {
67                                 CustomData_bmesh_free_block_data(data_layer, &ele_dst->head.data);
68                                 CustomData_bmesh_copy_data(data_layer, data_layer, ele2->head.data, &ele_dst->head.data);
69                         }
70                 }
71                 else {
72                         void *src[2];
73                         float w[2];
74
75                         src[0] = ele1->head.data;
76                         src[1] = ele2->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
84 /**
85  * \brief Data, Interp From Verts
86  *
87  * Interpolates per-vertex data from two sources to a target.
88  *
89  * \note This is an exact match to #BM_data_interp_from_edges
90  */
91 void BM_data_interp_from_verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, const float fac)
92 {
93         bm_data_interp_from_elem(&bm->vdata, (BMElem *)v1, (BMElem *)v2, (BMElem *)v, fac);
94 }
95
96 /**
97  * \brief Data, Interp From Edges
98  *
99  * Interpolates per-edge data from two sources to a target.
100  *
101  * \note This is an exact match to #BM_data_interp_from_verts
102  */
103 void BM_data_interp_from_edges(BMesh *bm, BMEdge *e1, BMEdge *e2, BMEdge *e, const float fac)
104 {
105         bm_data_interp_from_elem(&bm->edata, (BMElem *)e1, (BMElem *)e2, (BMElem *)e, fac);
106 }
107
108 /**
109  * \brief Data Vert Average
110  *
111  * Sets all the customdata (e.g. vert, loop) associated with a vert
112  * to the average of the face regions surrounding it.
113  */
114 static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNUSED(f))
115 {
116         // BMIter iter;
117 }
118
119 /**
120  * \brief Data Face-Vert Edge Interp
121  *
122  * Walks around the faces of an edge and interpolates the per-face-edge
123  * data between two sources to a target.
124  */
125 void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BMVert *v, BMEdge *e1, const float fac)
126 {
127         void *src[2];
128         float w[2];
129         BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL;
130         BMLoop *l_iter = NULL;
131
132         if (!e1->l) {
133                 return;
134         }
135
136         w[1] = 1.0f - fac;
137         w[0] = fac;
138
139         l_iter = e1->l;
140         do {
141                 if (l_iter->v == v1) {
142                         l_v1 = l_iter;
143                         l_v = l_v1->next;
144                         l_v2 = l_v->next;
145                 }
146                 else if (l_iter->v == v) {
147                         l_v1 = l_iter->next;
148                         l_v = l_iter;
149                         l_v2 = l_iter->prev;
150                 }
151                 
152                 if (!l_v1 || !l_v2)
153                         return;
154                 
155                 src[0] = l_v1->head.data;
156                 src[1] = l_v2->head.data;
157
158                 CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
159         } while ((l_iter = l_iter->radial_next) != e1->l);
160 }
161
162 /**
163  * \brief Data Interp From Face
164  *
165  * projects target onto source, and pulls interpolated customdata from
166  * source.
167  *
168  * \note Only handles loop customdata. multires is handled.
169  */
170 void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex,
171                                  void **blocks_l, void **blocks_v, float (*cos_2d)[2], float axis_mat[3][3])
172 {
173         BMLoop *l_iter;
174         BMLoop *l_first;
175
176         float *w = BLI_array_alloca(w, source->len);
177         float co[2];
178         int i;
179
180         if (source != target)
181                 BM_elem_attrs_copy(bm, bm, source, target);
182
183         /* interpolate */
184         i = 0;
185         l_iter = l_first = BM_FACE_FIRST_LOOP(target);
186         do {
187                 mul_v2_m3v3(co, axis_mat, l_iter->v->co);
188                 interp_weights_poly_v2(w, cos_2d, source->len, co);
189                 CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, source->len, l_iter->head.data);
190                 if (do_vertex) {
191                         CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, source->len, l_iter->v->head.data);
192                 }
193         } while (i++, (l_iter = l_iter->next) != l_first);
194 }
195
196 void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex)
197 {
198         BMLoop *l_iter;
199         BMLoop *l_first;
200
201         void **blocks_l    = BLI_array_alloca(blocks_l, source->len);
202         void **blocks_v    = do_vertex ? BLI_array_alloca(blocks_v, source->len) : NULL;
203         float (*cos_2d)[2] = BLI_array_alloca(cos_2d, source->len);
204         float axis_mat[3][3];  /* use normal to transform into 2d xy coords */
205         int i;
206
207         /* convert the 3d coords into 2d for projection */
208         BLI_assert(BM_face_is_normal_valid(source));
209         axis_dominant_v3_to_m3(axis_mat, source->no);
210
211         i = 0;
212         l_iter = l_first = BM_FACE_FIRST_LOOP(source);
213         do {
214                 mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
215                 blocks_l[i] = l_iter->head.data;
216                 if (do_vertex) blocks_v[i] = l_iter->v->head.data;
217         } while (i++, (l_iter = l_iter->next) != l_first);
218
219         BM_face_interp_from_face_ex(bm, target, source, do_vertex,
220                                     blocks_l, blocks_v, cos_2d, axis_mat);
221 }
222
223 /**
224  * \brief Multires Interpolation
225  *
226  * mdisps is a grid of displacements, ordered thus:
227  * <pre>
228  *      v1/center----v4/next -> x
229  *          |           |
230  *          |           |
231  *       v2/prev------v3/cur
232  *          |
233  *          V
234  *          y
235  * </pre>
236  */
237 static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3],
238                               float e1[3], float e2[3])
239 {
240         float cent[3], n[3], p[3];
241
242         /* computer center */
243         BM_face_calc_center_mean(l->f, cent);
244
245         mid_v3_v3v3(p, l->prev->v->co, l->v->co);
246         mid_v3_v3v3(n, l->next->v->co, l->v->co);
247         
248         copy_v3_v3(v1, cent);
249         copy_v3_v3(v2, p);
250         copy_v3_v3(v3, l->v->co);
251         copy_v3_v3(v4, n);
252         
253         sub_v3_v3v3(e1, v2, v1);
254         sub_v3_v3v3(e2, v3, v4);
255         
256         return 1;
257 }
258
259 /* funnily enough, I think this is identical to face_to_crn_interp, heh */
260 static float quad_coord(float aa[3], float bb[3], float cc[3], float dd[3], int a1, int a2)
261 {
262         float x, y, z, f1;
263         
264         x = aa[a1] * cc[a2] - cc[a1] * aa[a2];
265         y = aa[a1] * dd[a2] + bb[a1] * cc[a2] - cc[a1] * bb[a2] - dd[a1] * aa[a2];
266         z = bb[a1] * dd[a2] - dd[a1] * bb[a2];
267         
268         if (fabsf(2.0f * (x - y + z)) > FLT_EPSILON * 10.0f) {
269                 float f2;
270
271                 f1 = ( sqrtf(y * y - 4.0f * x * z) - y + 2.0f * z) / (2.0f * (x - y + z));
272                 f2 = (-sqrtf(y * y - 4.0f * x * z) - y + 2.0f * z) / (2.0f * (x - y + z));
273
274                 f1 = fabsf(f1);
275                 f2 = fabsf(f2);
276                 f1 = min_ff(f1, f2);
277                 CLAMP(f1, 0.0f, 1.0f + FLT_EPSILON);
278         }
279         else {
280                 f1 = -z / (y - 2 * z);
281                 CLAMP(f1, 0.0f, 1.0f + FLT_EPSILON);
282                 
283                 if (isnan(f1) || f1 > 1.0f || f1 < 0.0f) {
284                         int i;
285                         
286                         for (i = 0; i < 2; i++) {
287                                 if (fabsf(aa[i]) < FLT_EPSILON * 100.0f)
288                                         return aa[(i + 1) % 2] / fabsf(bb[(i + 1) % 2] - aa[(i + 1) % 2]);
289                                 if (fabsf(cc[i]) < FLT_EPSILON * 100.0f)
290                                         return cc[(i + 1) % 2] / fabsf(dd[(i + 1) % 2] - cc[(i + 1) % 2]);
291                         }
292                 }
293         }
294
295         return f1;
296 }
297
298 static int quad_co(float *x, float *y, float v1[3], float v2[3], float v3[3], float v4[3],
299                    float p[3], float n[3])
300 {
301         float projverts[5][3], n2[3];
302         float dprojverts[4][3], origin[3] = {0.0f, 0.0f, 0.0f};
303         int i;
304
305         /* project points into 2d along normal */
306         copy_v3_v3(projverts[0], v1);
307         copy_v3_v3(projverts[1], v2);
308         copy_v3_v3(projverts[2], v3);
309         copy_v3_v3(projverts[3], v4);
310         copy_v3_v3(projverts[4], p);
311
312         normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]);
313
314         if (dot_v3v3(n, n2) < -FLT_EPSILON) {
315                 return 0;
316         }
317
318         /* rotate */
319         poly_rotate_plane(n, projverts, 5);
320         
321         /* flatten */
322         for (i = 0; i < 5; i++) {
323                 projverts[i][2] = 0.0f;
324         }
325         
326         /* subtract origin */
327         for (i = 0; i < 4; i++) {
328                 sub_v3_v3(projverts[i], projverts[4]);
329         }
330         
331         copy_v3_v3(dprojverts[0], projverts[0]);
332         copy_v3_v3(dprojverts[1], projverts[1]);
333         copy_v3_v3(dprojverts[2], projverts[2]);
334         copy_v3_v3(dprojverts[3], projverts[3]);
335
336         if (!isect_point_quad_v2(origin, dprojverts[0], dprojverts[1], dprojverts[2], dprojverts[3])) {
337                 return 0;
338         }
339         
340         *y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1);
341         *x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1);
342
343         return 1;
344 }
345
346 static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3],
347                                 float axis_x[3], float axis_y[3])
348 {
349         sub_v3_v3v3(axis_x, v4, v1);
350         sub_v3_v3v3(axis_y, v2, v1);
351
352         normalize_v3(axis_x);
353         normalize_v3(axis_y);
354 }
355
356 /* tl is loop to project onto, l is loop whose internal displacement, co, is being
357  * projected.  x and y are location in loop's mdisps grid of point co. */
358 static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float *y,
359                                int res, float axis_x[3], float axis_y[3])
360 {
361         float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
362         float eps = FLT_EPSILON * 4000;
363         
364         if (is_zero_v3(l->v->no))
365                 BM_vert_normal_update_all(l->v);
366         if (is_zero_v3(tl->v->no))
367                 BM_vert_normal_update_all(tl->v);
368
369         compute_mdisp_quad(tl, v1, v2, v3, v4, e1, e2);
370
371         /* expand quad a bit */
372         cent_quad_v3(c, v1, v2, v3, v4);
373         
374         sub_v3_v3(v1, c); sub_v3_v3(v2, c);
375         sub_v3_v3(v3, c); sub_v3_v3(v4, c);
376         mul_v3_fl(v1, 1.0f + eps); mul_v3_fl(v2, 1.0f + eps);
377         mul_v3_fl(v3, 1.0f + eps); mul_v3_fl(v4, 1.0f + eps);
378         add_v3_v3(v1, c); add_v3_v3(v2, c);
379         add_v3_v3(v3, c); add_v3_v3(v4, c);
380         
381         if (!quad_co(x, y, v1, v2, v3, v4, p, l->v->no))
382                 return 0;
383         
384         *x *= res - 1;
385         *y *= res - 1;
386
387         mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
388
389         return 1;
390 }
391
392 static float bm_loop_flip_equotion(float mat[2][2], float b[2], float target_axis_x[3], float target_axis_y[3],
393                                    float coord[3], int i, int j)
394 {
395         mat[0][0] = target_axis_x[i];
396         mat[0][1] = target_axis_y[i];
397         mat[1][0] = target_axis_x[j];
398         mat[1][1] = target_axis_y[j];
399         b[0] = coord[i];
400         b[1] = coord[j];
401
402         return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
403 }
404
405 static void bm_loop_flip_disp(float source_axis_x[3], float source_axis_y[3],
406                                  float target_axis_x[3], float target_axis_y[3], float disp[3])
407 {
408         float vx[3], vy[3], coord[3];
409         float n[3], vec[3];
410         float b[2], mat[2][2], d;
411
412         mul_v3_v3fl(vx, source_axis_x, disp[0]);
413         mul_v3_v3fl(vy, source_axis_y, disp[1]);
414         add_v3_v3v3(coord, vx, vy);
415
416         /* project displacement from source grid plane onto target grid plane */
417         cross_v3_v3v3(n, target_axis_x, target_axis_y);
418         project_v3_v3v3(vec, coord, n);
419         sub_v3_v3v3(coord, coord, vec);
420
421         d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1);
422
423         if (fabsf(d) < 1e-4f) {
424                 d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2);
425                 if (fabsf(d) < 1e-4f)
426                         d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2);
427         }
428
429         disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d;
430         disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d;
431 }
432
433 static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, BMFace *f_src)
434 {
435         const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
436         MDisps *md_dst;
437         float d, v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
438         int ix, res;
439         float axis_x[3], axis_y[3];
440
441         if (cd_loop_mdisp_offset == -1)
442                 return;
443         
444         /* ignore 2-edged faces */
445         if (UNLIKELY(l_dst->f->len < 3))
446                 return;
447
448         md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset);
449         compute_mdisp_quad(l_dst, v1, v2, v3, v4, e1, e2);
450         
451         /* if no disps data allocate a new grid, the size of the first grid in f_src. */
452         if (!md_dst->totdisp) {
453                 MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
454                 
455                 md_dst->totdisp = md_src->totdisp;
456                 md_dst->level = md_src->level;
457                 if (md_dst->totdisp) {
458                         md_dst->disps = MEM_callocN(sizeof(float) * 3 * md_dst->totdisp, __func__);
459                 }
460                 else {
461                         return;
462                 }
463         }
464         
465         mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
466
467         res = (int)sqrt(md_dst->totdisp);
468         d = 1.0f / (float)(res - 1);
469 #pragma omp parallel for if (res > 3)
470         for (ix = 0; ix < res; ix++) {
471                 float x = d * ix, y;
472                 int iy;
473                 for (y = 0.0f, iy = 0; iy < res; y += d, iy++) {
474                         BMLoop *l_iter;
475                         BMLoop *l_first;
476                         float co1[3], co2[3], co[3];
477
478                         copy_v3_v3(co1, e1);
479                         
480                         mul_v3_fl(co1, y);
481                         add_v3_v3(co1, v1);
482                         
483                         copy_v3_v3(co2, e2);
484                         mul_v3_fl(co2, y);
485                         add_v3_v3(co2, v4);
486                         
487                         sub_v3_v3v3(co, co2, co1);
488                         mul_v3_fl(co, x);
489                         add_v3_v3(co, co1);
490                         
491                         l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
492                         do {
493                                 float x2, y2;
494                                 MDisps *md_src;
495                                 float src_axis_x[3], src_axis_y[3];
496
497                                 md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
498                                 
499                                 if (mdisp_in_mdispquad(l_dst, l_iter, co, &x2, &y2, res, src_axis_x, src_axis_y)) {
500                                         old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, (float)x2, (float)y2);
501                                         bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]);
502
503                                         break;
504                                 }
505                         } while ((l_iter = l_iter->next) != l_first);
506                 }
507         }
508 }
509
510 /**
511  * smooths boundaries between multires grids,
512  * including some borders in adjacent faces
513  */
514 void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
515 {
516         const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
517         BMLoop *l;
518         BMIter liter;
519         
520         if (cd_loop_mdisp_offset == -1)
521                 return;
522         
523         BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
524                 MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset);
525                 MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
526                 MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset);
527                 float co1[3];
528                 int sides;
529                 int y;
530                 
531                 /*
532                  *  mdisps is a grid of displacements, ordered thus:
533                  *
534                  *                     v4/next
535                  *                       |
536                  *   |      v1/cent-----mid2 ---> x
537                  *   |         |         |
538                  *   |         |         |
539                  *  v2/prev---mid1-----v3/cur
540                  *             |
541                  *             V
542                  *             y
543                  */
544
545                 sides = (int)sqrt(mdp->totdisp);
546                 for (y = 0; y < sides; y++) {
547                         mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]);
548
549                         copy_v3_v3(mdn->disps[y * sides], co1);
550                         copy_v3_v3(mdl->disps[y], co1);
551                 }
552         }
553         
554         BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
555                 MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
556                 MDisps *mdl2;
557                 float co1[3], co2[3], co[3];
558                 int sides;
559                 int y;
560                 
561                 /*
562                  *  mdisps is a grid of displacements, ordered thus:
563                  *
564                  *                     v4/next
565                  *                       |
566                  *   |      v1/cent-----mid2 ---> x
567                  *   |         |         |
568                  *   |         |         |
569                  *  v2/prev---mid1-----v3/cur
570                  *             |
571                  *             V
572                  *             y
573                  */
574
575                 if (l->radial_next == l)
576                         continue;
577
578                 if (l->radial_next->v == l->v)
579                         mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset);
580                 else
581                         mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset);
582
583                 sides = (int)sqrt(mdl1->totdisp);
584                 for (y = 0; y < sides; y++) {
585                         int a1, a2, o1, o2;
586                         
587                         if (l->v != l->radial_next->v) {
588                                 a1 = sides * y + sides - 2;
589                                 a2 = (sides - 2) * sides + y;
590                                 
591                                 o1 = sides * y + sides - 1;
592                                 o2 = (sides - 1) * sides + y;
593                         }
594                         else {
595                                 a1 = sides * y + sides - 2;
596                                 a2 = sides * y + sides - 2;
597                                 o1 = sides * y + sides - 1;
598                                 o2 = sides * y + sides - 1;
599                         }
600                         
601                         /* magic blending numbers, hardcoded! */
602                         add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]);
603                         mul_v3_fl(co1, 0.18);
604                         
605                         add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
606                         mul_v3_fl(co2, 0.32);
607                         
608                         add_v3_v3v3(co, co1, co2);
609                         
610                         copy_v3_v3(mdl1->disps[o1], co);
611                         copy_v3_v3(mdl2->disps[o2], co);
612                 }
613         }
614 }
615
616 /**
617  * project the multires grid in target onto source's set of multires grids
618  */
619 void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source)
620 {
621         bm_loop_interp_mdisps(bm, target, source);
622 }
623
624 /**
625  * projects a single loop, target, onto source for customdata interpolation. multires is handled.
626  * if do_vertex is true, target's vert data will also get interpolated.
627  */
628 void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
629                               const bool do_vertex, const bool do_multires)
630 {
631         BMLoop *l_iter;
632         BMLoop *l_first;
633         void **vblocks  = do_vertex ? BLI_array_alloca(vblocks, source->len) : NULL;
634         void **blocks   = BLI_array_alloca(blocks, source->len);
635         float (*cos_2d)[2] = BLI_array_alloca(cos_2d, source->len);
636         float *w        = BLI_array_alloca(w, source->len);
637         float axis_mat[3][3];  /* use normal to transform into 2d xy coords */
638         float co[2];
639         int i;
640
641         /* convert the 3d coords into 2d for projection */
642         BLI_assert(BM_face_is_normal_valid(source));
643         axis_dominant_v3_to_m3(axis_mat, source->no);
644
645         i = 0;
646         l_iter = l_first = BM_FACE_FIRST_LOOP(source);
647         do {
648                 mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
649                 blocks[i] = l_iter->head.data;
650
651                 if (do_vertex) {
652                         vblocks[i] = l_iter->v->head.data;
653                 }
654         } while (i++, (l_iter = l_iter->next) != l_first);
655
656         mul_v2_m3v3(co, axis_mat, target->v->co);
657
658         /* interpolate */
659         interp_weights_poly_v2(w, cos_2d, source->len, co);
660         CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, target->head.data);
661         if (do_vertex) {
662                 CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, source->len, target->v->head.data);
663         }
664
665         if (do_multires) {
666                 bm_loop_interp_mdisps(bm, target, source);
667         }
668 }
669
670
671 void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source)
672 {
673         BMLoop *l_iter;
674         BMLoop *l_first;
675         void **blocks   = BLI_array_alloca(blocks, source->len);
676         float (*cos_2d)[2] = BLI_array_alloca(cos_2d, source->len);
677         float *w        = BLI_array_alloca(w,      source->len);
678         float axis_mat[3][3];  /* use normal to transform into 2d xy coords */
679         float co[2];
680         int i;
681
682         /* convert the 3d coords into 2d for projection */
683         BLI_assert(BM_face_is_normal_valid(source));
684         axis_dominant_v3_to_m3(axis_mat, source->no);
685
686         i = 0;
687         l_iter = l_first = BM_FACE_FIRST_LOOP(source);
688         do {
689                 mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
690                 blocks[i] = l_iter->v->head.data;
691         } while (i++, (l_iter = l_iter->next) != l_first);
692
693         mul_v2_m3v3(co, axis_mat, v->co);
694
695         /* interpolate */
696         interp_weights_poly_v2(w, cos_2d, source->len, co);
697         CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, source->len, v->head.data);
698 }
699
700 static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
701 {
702         BMIter iter;
703         BLI_mempool *oldpool = olddata->pool;
704         void *block;
705
706         if (data == &bm->vdata) {
707                 BMVert *eve;
708
709                 CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT);
710
711                 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
712                         block = NULL;
713                         CustomData_bmesh_set_default(data, &block);
714                         CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
715                         CustomData_bmesh_free_block(olddata, &eve->head.data);
716                         eve->head.data = block;
717                 }
718         }
719         else if (data == &bm->edata) {
720                 BMEdge *eed;
721
722                 CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE);
723
724                 BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
725                         block = NULL;
726                         CustomData_bmesh_set_default(data, &block);
727                         CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
728                         CustomData_bmesh_free_block(olddata, &eed->head.data);
729                         eed->head.data = block;
730                 }
731         }
732         else if (data == &bm->ldata) {
733                 BMIter liter;
734                 BMFace *efa;
735                 BMLoop *l;
736
737                 CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP);
738                 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
739                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
740                                 block = NULL;
741                                 CustomData_bmesh_set_default(data, &block);
742                                 CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
743                                 CustomData_bmesh_free_block(olddata, &l->head.data);
744                                 l->head.data = block;
745                         }
746                 }
747         }
748         else if (data == &bm->pdata) {
749                 BMFace *efa;
750
751                 CustomData_bmesh_init_pool(data, bm->totface, BM_FACE);
752
753                 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
754                         block = NULL;
755                         CustomData_bmesh_set_default(data, &block);
756                         CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
757                         CustomData_bmesh_free_block(olddata, &efa->head.data);
758                         efa->head.data = block;
759                 }
760         }
761         else {
762                 /* should never reach this! */
763                 BLI_assert(0);
764         }
765
766         if (oldpool) {
767                 /* this should never happen but can when dissolve fails - [#28960] */
768                 BLI_assert(data->pool != oldpool);
769
770                 BLI_mempool_destroy(oldpool);
771         }
772 }
773
774 void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
775 {
776         CustomData olddata;
777
778         olddata = *data;
779         olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
780
781         /* the pool is now owned by olddata and must not be shared */
782         data->pool = NULL;
783
784         CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0);
785
786         update_data_blocks(bm, &olddata, data);
787         if (olddata.layers) MEM_freeN(olddata.layers);
788 }
789
790 void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
791 {
792         CustomData olddata;
793
794         olddata = *data;
795         olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
796
797         /* the pool is now owned by olddata and must not be shared */
798         data->pool = NULL;
799
800         CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name);
801
802         update_data_blocks(bm, &olddata, data);
803         if (olddata.layers) MEM_freeN(olddata.layers);
804 }
805
806 void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
807 {
808         CustomData olddata;
809         bool has_layer;
810
811         olddata = *data;
812         olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
813
814         /* the pool is now owned by olddata and must not be shared */
815         data->pool = NULL;
816
817         has_layer = CustomData_free_layer_active(data, type, 0);
818         /* assert because its expensive to realloc - better not do if layer isnt present */
819         BLI_assert(has_layer != false);
820
821         update_data_blocks(bm, &olddata, data);
822         if (olddata.layers) MEM_freeN(olddata.layers);
823 }
824
825 void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
826 {
827         CustomData olddata;
828         bool has_layer;
829
830         olddata = *data;
831         olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
832
833         /* the pool is now owned by olddata and must not be shared */
834         data->pool = NULL;
835
836         has_layer = CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n));
837         /* assert because its expensive to realloc - better not do if layer isnt present */
838         BLI_assert(has_layer != false);
839         
840         update_data_blocks(bm, &olddata, data);
841         if (olddata.layers) MEM_freeN(olddata.layers);
842 }
843
844 void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n)
845 {
846         BMIter iter;
847
848         if (&bm->vdata == data) {
849                 BMVert *eve;
850
851                 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
852                         void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n);
853                         CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr);
854                 }
855         }
856         else if (&bm->edata == data) {
857                 BMEdge *eed;
858
859                 BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
860                         void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n);
861                         CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr);
862                 }
863         }
864         else if (&bm->pdata == data) {
865                 BMFace *efa;
866
867                 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
868                         void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n);
869                         CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr);
870                 }
871         }
872         else if (&bm->ldata == data) {
873                 BMIter liter;
874                 BMFace *efa;
875                 BMLoop *l;
876
877                 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
878                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
879                                 void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n);
880                                 CustomData_bmesh_set_n(data, l->head.data, type, dst_n, ptr);
881                         }
882                 }
883         }
884         else {
885                 /* should never reach this! */
886                 BLI_assert(0);
887         }
888 }
889
890 float BM_elem_float_data_get(CustomData *cd, void *element, int type)
891 {
892         float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
893         return f ? *f : 0.0f;
894 }
895
896 void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
897 {
898         float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
899         if (f) *f = val;
900 }