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