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