2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 * meshlaplacian.c: Algorithms using the mesh laplacian.
22 #include "MEM_guardedalloc.h"
24 #include "DNA_mesh_types.h"
25 #include "DNA_meshdata_types.h"
26 #include "DNA_object_types.h"
27 #include "DNA_scene_types.h"
29 #include "BLI_alloca.h"
30 #include "BLI_edgehash.h"
32 #include "BLI_memarena.h"
33 #include "BLI_string.h"
35 #include "BLT_translation.h"
37 #include "BKE_bvhutils.h"
39 #include "BKE_mesh_runtime.h"
40 #include "BKE_modifier.h"
42 #include "ED_armature.h"
45 #include "DEG_depsgraph.h"
47 #include "eigen_capi.h"
49 #include "meshlaplacian.h"
51 /* ************* XXX *************** */
52 static void waitcursor(int UNUSED(val))
55 static void progress_bar(int UNUSED(dummy_val), const char *UNUSED(dummy))
58 static void start_progress_bar(void)
61 static void end_progress_bar(void)
64 static void error(const char *str)
66 printf("error: %s\n", str);
68 /* ************* XXX *************** */
70 /************************** Laplacian System *****************************/
72 struct LaplacianSystem {
73 LinearSolver *context; /* linear solver */
77 float **verts; /* vertex coordinates */
78 float *varea; /* vertex weights for laplacian computation */
79 char *vpinned; /* vertex pinning */
80 int (*faces)[3]; /* face vertex indices */
81 float (*fweights)[3]; /* cotangent weights per face */
83 int areaweights; /* use area in cotangent weights? */
84 int storeweights; /* store cotangent weights in fweights */
85 bool variablesdone; /* variables set in linear system */
87 EdgeHash *edgehash; /* edge hash for construction */
89 struct HeatWeighting {
90 const MLoopTri *mlooptri;
91 const MLoop *mloop; /* needed to find vertices by index */
94 float (*verts)[3]; /* vertex coordinates */
95 float (*vnors)[3]; /* vertex normals */
97 float (*root)[3]; /* bone root */
98 float (*tip)[3]; /* bone tip */
99 float (*source)[3]; /* vertex source */
102 float *H; /* diagonal H matrix */
103 float *p; /* values from all p vectors */
104 float *mindist; /* minimum distance to a bone for all vertices */
106 BVHTree *bvhtree; /* ray tracing acceleration structure */
107 const MLoopTri **vltree; /* a looptri that the vertex belongs to */
111 /* Laplacian matrix construction */
113 /* Computation of these weights for the laplacian is based on:
114 * "Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
115 * Meyer et al, 2002. Section 3.5, formula (8).
117 * We do it a bit different by going over faces instead of going over each
118 * vertex and adjacent faces, since we don't store this adjacency. Also, the
119 * formulas are tweaked a bit to work for non-manifold meshes. */
121 static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
125 if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p)) {
126 *p = (void *)((intptr_t)*p + (intptr_t)1);
129 *p = (void *)((intptr_t)1);
133 static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2)
135 return (int)(intptr_t)BLI_edgehash_lookup(edgehash, v1, v2);
138 static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3)
140 float t1, t2, t3, len1, len2, len3, area;
141 float *varea = sys->varea, *v1, *v2, *v3;
148 t1 = cotangent_tri_weight_v3(v1, v2, v3);
149 t2 = cotangent_tri_weight_v3(v2, v3, v1);
150 t3 = cotangent_tri_weight_v3(v3, v1, v2);
152 if (angle_v3v3v3(v2, v1, v3) > DEG2RADF(90.0f)) {
155 else if (angle_v3v3v3(v1, v2, v3) > DEG2RADF(90.0f)) {
158 else if (angle_v3v3v3(v1, v3, v2) > DEG2RADF(90.0f)) {
163 area = area_tri_v3(v1, v2, v3);
165 varea[i1] += (obtuse == 1) ? area : area * 0.5f;
166 varea[i2] += (obtuse == 2) ? area : area * 0.5f;
167 varea[i3] += (obtuse == 3) ? area : area * 0.5f;
170 len1 = len_v3v3(v2, v3);
171 len2 = len_v3v3(v1, v3);
172 len3 = len_v3v3(v1, v2);
178 varea[i1] += (t2 + t3) * 0.25f;
179 varea[i2] += (t1 + t3) * 0.25f;
180 varea[i3] += (t1 + t2) * 0.25f;
184 static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3)
187 float *varea = sys->varea, *v1, *v2, *v3;
193 /* instead of *0.5 we divided by the number of faces of the edge, it still
194 * needs to be verified that this is indeed the correct thing to do! */
195 t1 = cotangent_tri_weight_v3(v1, v2, v3) / laplacian_edge_count(sys->edgehash, i2, i3);
196 t2 = cotangent_tri_weight_v3(v2, v3, v1) / laplacian_edge_count(sys->edgehash, i3, i1);
197 t3 = cotangent_tri_weight_v3(v3, v1, v2) / laplacian_edge_count(sys->edgehash, i1, i2);
199 EIG_linear_solver_matrix_add(sys->context, i1, i1, (t2 + t3) * varea[i1]);
200 EIG_linear_solver_matrix_add(sys->context, i2, i2, (t1 + t3) * varea[i2]);
201 EIG_linear_solver_matrix_add(sys->context, i3, i3, (t1 + t2) * varea[i3]);
203 EIG_linear_solver_matrix_add(sys->context, i1, i2, -t3 * varea[i1]);
204 EIG_linear_solver_matrix_add(sys->context, i2, i1, -t3 * varea[i2]);
206 EIG_linear_solver_matrix_add(sys->context, i2, i3, -t1 * varea[i2]);
207 EIG_linear_solver_matrix_add(sys->context, i3, i2, -t1 * varea[i3]);
209 EIG_linear_solver_matrix_add(sys->context, i3, i1, -t2 * varea[i3]);
210 EIG_linear_solver_matrix_add(sys->context, i1, i3, -t2 * varea[i1]);
212 if (sys->storeweights) {
213 sys->fweights[f][0] = t1 * varea[i1];
214 sys->fweights[f][1] = t2 * varea[i2];
215 sys->fweights[f][2] = t3 * varea[i3];
219 static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq)
221 LaplacianSystem *sys;
223 sys = MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem");
225 sys->verts = MEM_callocN(sizeof(float *) * totvert, "LaplacianSystemVerts");
226 sys->vpinned = MEM_callocN(sizeof(char) * totvert, "LaplacianSystemVpinned");
227 sys->faces = MEM_callocN(sizeof(int) * 3 * totface, "LaplacianSystemFaces");
232 sys->areaweights = 1;
233 sys->storeweights = 0;
235 /* create linear solver */
237 sys->context = EIG_linear_least_squares_solver_new(0, totvert, 1);
240 sys->context = EIG_linear_solver_new(0, totvert, 1);
246 void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned)
248 sys->verts[sys->totvert] = co;
249 sys->vpinned[sys->totvert] = pinned;
253 void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3)
255 sys->faces[sys->totface][0] = v1;
256 sys->faces[sys->totface][1] = v2;
257 sys->faces[sys->totface][2] = v3;
261 static void laplacian_system_construct_end(LaplacianSystem *sys)
264 int a, totvert = sys->totvert, totface = sys->totface;
266 laplacian_begin_solve(sys, 0);
268 sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea");
270 sys->edgehash = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->totface));
271 for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
272 laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]);
273 laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]);
274 laplacian_increase_edge_count(sys->edgehash, (*face)[2], (*face)[0]);
277 if (sys->areaweights) {
278 for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
279 laplacian_triangle_area(sys, (*face)[0], (*face)[1], (*face)[2]);
283 for (a = 0; a < totvert; a++) {
284 if (sys->areaweights) {
285 if (sys->varea[a] != 0.0f) {
286 sys->varea[a] = 0.5f / sys->varea[a];
290 sys->varea[a] = 1.0f;
293 /* for heat weighting */
295 EIG_linear_solver_matrix_add(sys->context, a, a, sys->heat.H[a]);
299 if (sys->storeweights) {
300 sys->fweights = MEM_callocN(sizeof(float) * 3 * totface, "LaplacianFWeight");
303 for (a = 0, face = sys->faces; a < totface; a++, face++) {
304 laplacian_triangle_weights(sys, a, (*face)[0], (*face)[1], (*face)[2]);
307 MEM_freeN(sys->faces);
311 MEM_freeN(sys->varea);
315 BLI_edgehash_free(sys->edgehash, NULL);
316 sys->edgehash = NULL;
319 static void laplacian_system_delete(LaplacianSystem *sys)
322 MEM_freeN(sys->verts);
325 MEM_freeN(sys->varea);
328 MEM_freeN(sys->vpinned);
331 MEM_freeN(sys->faces);
334 MEM_freeN(sys->fweights);
337 EIG_linear_solver_delete(sys->context);
341 void laplacian_begin_solve(LaplacianSystem *sys, int index)
345 if (!sys->variablesdone) {
347 for (a = 0; a < sys->totvert; a++) {
348 if (sys->vpinned[a]) {
349 EIG_linear_solver_variable_set(sys->context, 0, a, sys->verts[a][index]);
350 EIG_linear_solver_variable_lock(sys->context, a);
355 sys->variablesdone = true;
359 void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
361 EIG_linear_solver_right_hand_side_add(sys->context, 0, v, value);
364 int laplacian_system_solve(LaplacianSystem *sys)
366 sys->variablesdone = false;
368 // EIG_linear_solver_print_matrix(sys->context, );
370 return EIG_linear_solver_solve(sys->context);
373 float laplacian_system_get_solution(LaplacianSystem *sys, int v)
375 return EIG_linear_solver_variable_get(sys->context, 0, v);
378 /************************* Heat Bone Weighting ******************************/
379 /* From "Automatic Rigging and Animation of 3D Characters"
380 * Ilya Baran and Jovan Popovic, SIGGRAPH 2007 */
382 #define C_WEIGHT 1.0f
383 #define WEIGHT_LIMIT_START 0.05f
384 #define WEIGHT_LIMIT_END 0.025f
385 #define DISTANCE_EPSILON 1e-4f
387 typedef struct BVHCallbackUserData {
390 LaplacianSystem *sys;
391 } BVHCallbackUserData;
393 static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
395 BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata;
396 const MLoopTri *lt = &data->sys->heat.mlooptri[index];
397 const MLoop *mloop = data->sys->heat.mloop;
398 float(*verts)[3] = data->sys->heat.verts;
399 const float *vtri_co[3];
402 vtri_co[0] = verts[mloop[lt->tri[0]].v];
403 vtri_co[1] = verts[mloop[lt->tri[1]].v];
404 vtri_co[2] = verts[mloop[lt->tri[2]].v];
406 #ifdef USE_KDOPBVH_WATERTIGHT
407 if (isect_ray_tri_watertight_v3(
408 data->start, ray->isect_precalc, UNPACK3(vtri_co), &dist_test, NULL))
411 if (isect_ray_tri_v3(data->start, data->vec, UNPACK3(vtri_co), &dist_test, NULL))
414 if (dist_test < hit->dist) {
416 normal_tri_v3(n, UNPACK3(vtri_co));
417 if (dot_v3v3(n, data->vec) < -1e-5f) {
419 hit->dist = dist_test;
425 /* Raytracing for vertex to bone/vertex visibility */
426 static void heat_ray_tree_create(LaplacianSystem *sys)
428 const MLoopTri *looptri = sys->heat.mlooptri;
429 const MLoop *mloop = sys->heat.mloop;
430 float(*verts)[3] = sys->heat.verts;
431 int tottri = sys->heat.tottri;
432 int totvert = sys->heat.totvert;
435 sys->heat.bvhtree = BLI_bvhtree_new(tottri, 0.0f, 4, 6);
436 sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * totvert, "HeatVFaces");
438 for (a = 0; a < tottri; a++) {
439 const MLoopTri *lt = &looptri[a];
443 vtri[0] = mloop[lt->tri[0]].v;
444 vtri[1] = mloop[lt->tri[1]].v;
445 vtri[2] = mloop[lt->tri[2]].v;
447 INIT_MINMAX(bb, bb + 3);
448 minmax_v3v3_v3(bb, bb + 3, verts[vtri[0]]);
449 minmax_v3v3_v3(bb, bb + 3, verts[vtri[1]]);
450 minmax_v3v3_v3(bb, bb + 3, verts[vtri[2]]);
452 BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2);
454 // Setup inverse pointers to use on isect.orig
455 sys->heat.vltree[vtri[0]] = lt;
456 sys->heat.vltree[vtri[1]] = lt;
457 sys->heat.vltree[vtri[2]] = lt;
460 BLI_bvhtree_balance(sys->heat.bvhtree);
463 static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
466 BVHCallbackUserData data;
471 lt = sys->heat.vltree[vertex];
477 copy_v3_v3(data.start, sys->heat.verts[vertex]);
479 closest_to_line_segment_v3(end, data.start, sys->heat.root[source], sys->heat.tip[source]);
481 sub_v3_v3v3(data.vec, end, data.start);
482 madd_v3_v3v3fl(data.start, data.start, data.vec, 1e-5);
483 mul_v3_fl(data.vec, 1.0f - 2e-5f);
485 /* pass normalized vec + distance to bvh */
487 hit.dist = normalize_v3(data.vec);
490 BLI_bvhtree_ray_cast(
491 sys->heat.bvhtree, data.start, data.vec, 0.0f, &hit, bvh_callback, (void *)&data) == -1;
496 static float heat_source_distance(LaplacianSystem *sys, int vertex, int source)
498 float closest[3], d[3], dist, cosine;
500 /* compute euclidian distance */
501 closest_to_line_segment_v3(
502 closest, sys->heat.verts[vertex], sys->heat.root[source], sys->heat.tip[source]);
504 sub_v3_v3v3(d, sys->heat.verts[vertex], closest);
505 dist = normalize_v3(d);
507 /* if the vertex normal does not point along the bone, increase distance */
508 cosine = dot_v3v3(d, sys->heat.vnors[vertex]);
510 return dist / (0.5f * (cosine + 1.001f));
513 static int heat_source_closest(LaplacianSystem *sys, int vertex, int source)
517 dist = heat_source_distance(sys, vertex, source);
519 if (dist <= sys->heat.mindist[vertex] * (1.0f + DISTANCE_EPSILON)) {
520 if (heat_ray_source_visible(sys, vertex, source)) {
528 static void heat_set_H(LaplacianSystem *sys, int vertex)
530 float dist, mindist, h;
531 int j, numclosest = 0;
535 /* compute minimum distance */
536 for (j = 0; j < sys->heat.numsource; j++) {
537 dist = heat_source_distance(sys, vertex, j);
539 if (dist < mindist) {
544 sys->heat.mindist[vertex] = mindist;
546 /* count number of sources with approximately this minimum distance */
547 for (j = 0; j < sys->heat.numsource; j++) {
548 if (heat_source_closest(sys, vertex, j)) {
553 sys->heat.p[vertex] = (numclosest > 0) ? 1.0f / numclosest : 0.0f;
555 /* compute H entry */
556 if (numclosest > 0) {
557 mindist = max_ff(mindist, 1e-4f);
558 h = numclosest * C_WEIGHT / (mindist * mindist);
564 sys->heat.H[vertex] = h;
567 static void heat_calc_vnormals(LaplacianSystem *sys)
570 int a, v1, v2, v3, (*face)[3];
572 sys->heat.vnors = MEM_callocN(sizeof(float) * 3 * sys->totvert, "HeatVNors");
574 for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
579 normal_tri_v3(fnor, sys->verts[v1], sys->verts[v2], sys->verts[v3]);
581 add_v3_v3(sys->heat.vnors[v1], fnor);
582 add_v3_v3(sys->heat.vnors[v2], fnor);
583 add_v3_v3(sys->heat.vnors[v3], fnor);
586 for (a = 0; a < sys->totvert; a++) {
587 normalize_v3(sys->heat.vnors[a]);
591 static void heat_laplacian_create(LaplacianSystem *sys)
593 const MLoopTri *mlooptri = sys->heat.mlooptri, *lt;
594 const MLoop *mloop = sys->heat.mloop;
595 int tottri = sys->heat.tottri;
596 int totvert = sys->heat.totvert;
599 /* heat specific definitions */
600 sys->heat.mindist = MEM_callocN(sizeof(float) * totvert, "HeatMinDist");
601 sys->heat.H = MEM_callocN(sizeof(float) * totvert, "HeatH");
602 sys->heat.p = MEM_callocN(sizeof(float) * totvert, "HeatP");
604 /* add verts and faces to laplacian */
605 for (a = 0; a < totvert; a++) {
606 laplacian_add_vertex(sys, sys->heat.verts[a], 0);
609 for (a = 0, lt = mlooptri; a < tottri; a++, lt++) {
611 vtri[0] = mloop[lt->tri[0]].v;
612 vtri[1] = mloop[lt->tri[1]].v;
613 vtri[2] = mloop[lt->tri[2]].v;
614 laplacian_add_triangle(sys, UNPACK3(vtri));
617 /* for distance computation in set_H */
618 heat_calc_vnormals(sys);
620 for (a = 0; a < totvert; a++) {
625 static void heat_system_free(LaplacianSystem *sys)
627 BLI_bvhtree_free(sys->heat.bvhtree);
628 MEM_freeN((void *)sys->heat.vltree);
629 MEM_freeN((void *)sys->heat.mlooptri);
631 MEM_freeN(sys->heat.mindist);
632 MEM_freeN(sys->heat.H);
633 MEM_freeN(sys->heat.p);
634 MEM_freeN(sys->heat.vnors);
637 static float heat_limit_weight(float weight)
641 if (weight < WEIGHT_LIMIT_END) {
644 else if (weight < WEIGHT_LIMIT_START) {
645 t = (weight - WEIGHT_LIMIT_END) / (WEIGHT_LIMIT_START - WEIGHT_LIMIT_END);
646 return t * WEIGHT_LIMIT_START;
653 void heat_bone_weighting(Object *ob,
657 bDeformGroup **dgrouplist,
658 bDeformGroup **dgroupflip,
662 const char **err_str)
664 LaplacianSystem *sys;
668 float solution, weight;
669 int *vertsflipped = NULL, *mask = NULL;
670 int a, tottri, j, bbone, firstsegment, lastsegment;
671 bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
673 MVert *mvert = me->mvert;
674 bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
675 bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
679 /* bone heat needs triangulated faces */
680 tottri = poly_to_tri_count(me->totpoly, me->totloop);
682 /* count triangles and create mask */
683 if (ob->mode & OB_MODE_WEIGHT_PAINT && (use_face_sel || use_vert_sel)) {
684 mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask");
686 /* (added selectedVerts content for vertex mask, they used to just equal 1) */
688 for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
689 for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
690 mask[ml->v] = (mvert[ml->v].flag & SELECT) != 0;
694 else if (use_face_sel) {
695 for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
696 if (mp->flag & ME_FACE_SEL) {
697 for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
705 /* create laplacian */
706 sys = laplacian_system_construct_begin(me->totvert, tottri, 1);
708 sys->heat.tottri = poly_to_tri_count(me->totpoly, me->totloop);
709 mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__);
711 BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri);
713 sys->heat.mlooptri = mlooptri;
714 sys->heat.mloop = me->mloop;
715 sys->heat.totvert = me->totvert;
716 sys->heat.verts = verts;
717 sys->heat.root = root;
719 sys->heat.numsource = numsource;
721 heat_ray_tree_create(sys);
722 heat_laplacian_create(sys);
724 laplacian_system_construct_end(sys);
727 vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped");
728 for (a = 0; a < me->totvert; a++) {
729 vertsflipped[a] = mesh_get_x_mirror_vert(ob, NULL, a, use_topology);
733 /* compute weights per bone */
734 for (j = 0; j < numsource; j++) {
739 firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]);
740 lastsegment = (j == numsource - 1 || dgrouplist[j] != dgrouplist[j + 1]);
741 bbone = !(firstsegment && lastsegment);
744 if (bbone && firstsegment) {
745 for (a = 0; a < me->totvert; a++) {
746 if (mask && !mask[a]) {
750 ED_vgroup_vert_remove(ob, dgrouplist[j], a);
751 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
752 ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
757 /* fill right hand side */
758 laplacian_begin_solve(sys, -1);
760 for (a = 0; a < me->totvert; a++) {
761 if (heat_source_closest(sys, a, j)) {
762 laplacian_add_right_hand_side(sys, a, sys->heat.H[a] * sys->heat.p[a]);
767 if (laplacian_system_solve(sys)) {
768 /* load solution into vertex groups */
769 for (a = 0; a < me->totvert; a++) {
770 if (mask && !mask[a]) {
774 solution = laplacian_system_get_solution(sys, a);
777 if (solution > 0.0f) {
778 ED_vgroup_vert_add(ob, dgrouplist[j], a, solution, WEIGHT_ADD);
782 weight = heat_limit_weight(solution);
784 ED_vgroup_vert_add(ob, dgrouplist[j], a, weight, WEIGHT_REPLACE);
787 ED_vgroup_vert_remove(ob, dgrouplist[j], a);
791 /* do same for mirror */
792 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
794 if (solution > 0.0f) {
795 ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], solution, WEIGHT_ADD);
799 weight = heat_limit_weight(solution);
801 ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], weight, WEIGHT_REPLACE);
804 ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
810 else if (*err_str == NULL) {
811 *err_str = N_("Bone Heat Weighting: failed to find solution for one or more bones");
815 /* remove too small vertex weights */
816 if (bbone && lastsegment) {
817 for (a = 0; a < me->totvert; a++) {
818 if (mask && !mask[a]) {
822 weight = ED_vgroup_vert_weight(ob, dgrouplist[j], a);
823 weight = heat_limit_weight(weight);
824 if (weight <= 0.0f) {
825 ED_vgroup_vert_remove(ob, dgrouplist[j], a);
828 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
829 weight = ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
830 weight = heat_limit_weight(weight);
831 if (weight <= 0.0f) {
832 ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
841 MEM_freeN(vertsflipped);
847 heat_system_free(sys);
849 laplacian_system_delete(sys);
852 /************************** Harmonic Coordinates ****************************/
853 /* From "Harmonic Coordinates for Character Articulation",
854 * Pushkar Joshi, Mark Meyer, Tony DeRose, Brian Green and Tom Sanocki,
857 #define EPSILON 0.0001f
859 #define MESHDEFORM_TAG_UNTYPED 0
860 #define MESHDEFORM_TAG_BOUNDARY 1
861 #define MESHDEFORM_TAG_INTERIOR 2
862 #define MESHDEFORM_TAG_EXTERIOR 3
864 /** minimum length for #MDefBoundIsect.len */
865 #define MESHDEFORM_LEN_THRESHOLD 1e-6f
867 #define MESHDEFORM_MIN_INFLUENCE 0.0005f
869 static const int MESHDEFORM_OFFSET[7][3] = {
879 typedef struct MDefBoundIsect {
880 /* intersection on the cage 'cagecos' */
882 /* non-facing intersections are considered interior */
884 /* ray-cast index aligned with MPoly (ray-hit-triangle isn't needed) */
886 /* distance from 'co' to the ray-cast start (clamped to avoid zero division) */
888 /* weights aligned with the MPoly's loop indices */
889 float poly_weights[0];
892 typedef struct MDefBindInfluence {
893 struct MDefBindInfluence *next;
898 typedef struct MeshDeformBind {
899 /* grid dimensions */
900 float min[3], max[3];
901 float width[3], halfwidth[3];
907 float (*vertexcos)[3];
908 int totvert, totcagevert;
912 MDefBoundIsect *(*boundisect)[6];
915 float *phi, *totalphi;
920 MDefBindInfluence **dyngrid;
927 BVHTreeFromMesh bvhdata;
929 /* avoid DM function calls during intersections */
933 const MLoopTri *looptri;
934 const float (*poly_nors)[3];
938 typedef struct MeshDeformIsect {
949 /* ray intersection */
951 struct MeshRayCallbackData {
953 MeshDeformIsect *isec;
956 static void harmonic_ray_callback(void *userdata,
958 const BVHTreeRay *ray,
961 struct MeshRayCallbackData *data = userdata;
962 MeshDeformBind *mdb = data->mdb;
963 const MLoop *mloop = mdb->cagemesh_cache.mloop;
964 const MLoopTri *looptri = mdb->cagemesh_cache.looptri, *lt;
965 const float(*poly_nors)[3] = mdb->cagemesh_cache.poly_nors;
966 MeshDeformIsect *isec = data->isec;
967 float no[3], co[3], dist;
970 lt = &looptri[index];
972 face[0] = mdb->cagecos[mloop[lt->tri[0]].v];
973 face[1] = mdb->cagecos[mloop[lt->tri[1]].v];
974 face[2] = mdb->cagecos[mloop[lt->tri[2]].v];
976 bool isect_ray_tri = isect_ray_tri_watertight_v3(
977 ray->origin, ray->isect_precalc, UNPACK3(face), &dist, NULL);
979 if (!isect_ray_tri || dist > isec->vec_length) {
984 copy_v3_v3(no, poly_nors[lt->poly]);
987 normal_tri_v3(no, UNPACK3(face));
990 madd_v3_v3v3fl(co, ray->origin, ray->direction, dist);
991 dist /= isec->vec_length;
992 if (dist < hit->dist) {
995 copy_v3_v3(hit->co, co);
997 isec->isect = (dot_v3v3(no, ray->direction) <= 0.0f);
1002 static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb,
1007 MeshDeformIsect isect_mdef;
1008 struct MeshRayCallbackData data = {
1012 float end[3], vec_normal[3];
1014 /* happens binding when a cage has no faces */
1015 if (UNLIKELY(mdb->bvhtree == NULL)) {
1020 memset(&isect_mdef, 0, sizeof(isect_mdef));
1021 isect_mdef.lambda = 1e10f;
1023 copy_v3_v3(isect_mdef.start, co1);
1024 copy_v3_v3(end, co2);
1025 sub_v3_v3v3(isect_mdef.vec, end, isect_mdef.start);
1026 isect_mdef.vec_length = normalize_v3_v3(vec_normal, isect_mdef.vec);
1029 hit.dist = BVH_RAYCAST_DIST_MAX;
1030 if (BLI_bvhtree_ray_cast_ex(mdb->bvhtree,
1035 harmonic_ray_callback,
1037 BVH_RAYCAST_WATERTIGHT) != -1) {
1038 const MLoop *mloop = mdb->cagemesh_cache.mloop;
1039 const MLoopTri *lt = &mdb->cagemesh_cache.looptri[hit.index];
1040 const MPoly *mp = &mdb->cagemesh_cache.mpoly[lt->poly];
1041 const float(*cagecos)[3] = mdb->cagecos;
1042 const float len = isect_mdef.lambda;
1043 MDefBoundIsect *isect;
1045 float(*mp_cagecos)[3] = BLI_array_alloca(mp_cagecos, mp->totloop);
1048 /* create MDefBoundIsect, and extra for 'poly_weights[]' */
1049 isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect) + (sizeof(float) * mp->totloop));
1051 /* compute intersection coordinate */
1052 madd_v3_v3v3fl(isect->co, co1, isect_mdef.vec, len);
1054 isect->facing = isect_mdef.isect;
1056 isect->poly_index = lt->poly;
1058 isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD);
1060 /* compute mean value coordinates for interpolation */
1061 for (i = 0; i < mp->totloop; i++) {
1062 copy_v3_v3(mp_cagecos[i], cagecos[mloop[mp->loopstart + i].v]);
1065 interp_weights_poly_v3(isect->poly_weights, mp_cagecos, mp->totloop, isect->co);
1073 static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
1075 MDefBoundIsect *isect;
1076 float outside[3], start[3], dir[3];
1079 for (i = 1; i <= 6; i++) {
1080 outside[0] = co[0] + (mdb->max[0] - mdb->min[0] + 1.0f) * MESHDEFORM_OFFSET[i][0];
1081 outside[1] = co[1] + (mdb->max[1] - mdb->min[1] + 1.0f) * MESHDEFORM_OFFSET[i][1];
1082 outside[2] = co[2] + (mdb->max[2] - mdb->min[2] + 1.0f) * MESHDEFORM_OFFSET[i][2];
1084 copy_v3_v3(start, co);
1085 sub_v3_v3v3(dir, outside, start);
1088 isect = meshdeform_ray_tree_intersect(mdb, start, outside);
1089 if (isect && !isect->facing) {
1099 BLI_INLINE int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
1101 int size = mdb->size;
1103 x += MESHDEFORM_OFFSET[n][0];
1104 y += MESHDEFORM_OFFSET[n][1];
1105 z += MESHDEFORM_OFFSET[n][2];
1107 if (x < 0 || x >= mdb->size) {
1110 if (y < 0 || y >= mdb->size) {
1113 if (z < 0 || z >= mdb->size) {
1117 return x + y * size + z * size * size;
1120 BLI_INLINE void meshdeform_cell_center(
1121 MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
1123 x += MESHDEFORM_OFFSET[n][0];
1124 y += MESHDEFORM_OFFSET[n][1];
1125 z += MESHDEFORM_OFFSET[n][2];
1127 center[0] = mdb->min[0] + x * mdb->width[0] + mdb->halfwidth[0];
1128 center[1] = mdb->min[1] + y * mdb->width[1] + mdb->halfwidth[1];
1129 center[2] = mdb->min[2] + z * mdb->width[2] + mdb->halfwidth[2];
1132 static void meshdeform_add_intersections(MeshDeformBind *mdb, int x, int y, int z)
1134 MDefBoundIsect *isect;
1135 float center[3], ncenter[3];
1138 a = meshdeform_index(mdb, x, y, z, 0);
1139 meshdeform_cell_center(mdb, x, y, z, 0, center);
1141 /* check each outgoing edge for intersection */
1142 for (i = 1; i <= 6; i++) {
1143 if (meshdeform_index(mdb, x, y, z, i) == -1) {
1147 meshdeform_cell_center(mdb, x, y, z, i, ncenter);
1149 isect = meshdeform_ray_tree_intersect(mdb, center, ncenter);
1151 mdb->boundisect[a][i - 1] = isect;
1152 mdb->tag[a] = MESHDEFORM_TAG_BOUNDARY;
1157 static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
1159 int *stack, *tag = mdb->tag;
1160 int a, b, i, xyz[3], stacksize, size = mdb->size;
1162 stack = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformBindStack");
1164 /* we know lower left corner is EXTERIOR because of padding */
1165 tag[0] = MESHDEFORM_TAG_EXTERIOR;
1169 /* floodfill exterior tag */
1170 while (stacksize > 0) {
1171 a = stack[--stacksize];
1173 xyz[2] = a / (size * size);
1174 xyz[1] = (a - xyz[2] * size * size) / size;
1175 xyz[0] = a - xyz[1] * size - xyz[2] * size * size;
1177 for (i = 1; i <= 6; i++) {
1178 b = meshdeform_index(mdb, xyz[0], xyz[1], xyz[2], i);
1181 if (tag[b] == MESHDEFORM_TAG_UNTYPED ||
1182 (tag[b] == MESHDEFORM_TAG_BOUNDARY && !mdb->boundisect[a][i - 1])) {
1183 tag[b] = MESHDEFORM_TAG_EXTERIOR;
1184 stack[stacksize++] = b;
1190 /* other cells are interior */
1191 for (a = 0; a < size * size * size; a++) {
1192 if (tag[a] == MESHDEFORM_TAG_UNTYPED) {
1193 tag[a] = MESHDEFORM_TAG_INTERIOR;
1200 tb = ti = te = ts = 0;
1201 for (a = 0; a < size * size * size; a++) {
1202 if (tag[a] == MESHDEFORM_TAG_BOUNDARY) {
1205 else if (tag[a] == MESHDEFORM_TAG_INTERIOR) {
1208 else if (tag[a] == MESHDEFORM_TAG_EXTERIOR) {
1211 if (mdb->semibound[a]) {
1217 printf("interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
1224 static float meshdeform_boundary_phi(const MeshDeformBind *mdb,
1225 const MDefBoundIsect *isect,
1228 const MLoop *mloop = mdb->cagemesh_cache.mloop;
1229 const MPoly *mp = &mdb->cagemesh_cache.mpoly[isect->poly_index];
1232 for (i = 0; i < mp->totloop; i++) {
1233 if (mloop[mp->loopstart + i].v == cagevert) {
1234 return isect->poly_weights[i];
1241 static float meshdeform_interp_w(MeshDeformBind *mdb,
1244 int UNUSED(cagevert))
1246 float dvec[3], ivec[3], wx, wy, wz, result = 0.0f;
1247 float weight, totweight = 0.0f;
1250 for (i = 0; i < 3; i++) {
1251 ivec[i] = (int)gridvec[i];
1252 dvec[i] = gridvec[i] - ivec[i];
1255 for (i = 0; i < 8; i++) {
1262 wx = 1.0f - dvec[0];
1271 wy = 1.0f - dvec[1];
1280 wz = 1.0f - dvec[2];
1283 CLAMP(x, 0, mdb->size - 1);
1284 CLAMP(y, 0, mdb->size - 1);
1285 CLAMP(z, 0, mdb->size - 1);
1287 a = meshdeform_index(mdb, x, y, z, 0);
1288 weight = wx * wy * wz;
1289 result += weight * mdb->phi[a];
1290 totweight += weight;
1293 if (totweight > 0.0f) {
1294 result /= totweight;
1300 static void meshdeform_check_semibound(MeshDeformBind *mdb, int x, int y, int z)
1304 a = meshdeform_index(mdb, x, y, z, 0);
1305 if (mdb->tag[a] != MESHDEFORM_TAG_EXTERIOR) {
1309 for (i = 1; i <= 6; i++) {
1310 if (mdb->boundisect[a][i - 1]) {
1311 mdb->semibound[a] = 1;
1316 static float meshdeform_boundary_total_weight(MeshDeformBind *mdb, int x, int y, int z)
1318 float weight, totweight = 0.0f;
1321 a = meshdeform_index(mdb, x, y, z, 0);
1323 /* count weight for neighbor cells */
1324 for (i = 1; i <= 6; i++) {
1325 if (meshdeform_index(mdb, x, y, z, i) == -1) {
1329 if (mdb->boundisect[a][i - 1]) {
1330 weight = 1.0f / mdb->boundisect[a][i - 1]->len;
1332 else if (!mdb->semibound[a]) {
1333 weight = 1.0f / mdb->width[0];
1339 totweight += weight;
1345 static void meshdeform_matrix_add_cell(
1346 MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z)
1348 MDefBoundIsect *isect;
1349 float weight, totweight;
1352 acenter = meshdeform_index(mdb, x, y, z, 0);
1353 if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR) {
1357 EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
1359 totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
1360 for (i = 1; i <= 6; i++) {
1361 a = meshdeform_index(mdb, x, y, z, i);
1362 if (a == -1 || mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR) {
1366 isect = mdb->boundisect[acenter][i - 1];
1368 weight = (1.0f / mdb->width[0]) / totweight;
1369 EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[a], -weight);
1374 static void meshdeform_matrix_add_rhs(
1375 MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z, int cagevert)
1377 MDefBoundIsect *isect;
1378 float rhs, weight, totweight;
1381 acenter = meshdeform_index(mdb, x, y, z, 0);
1382 if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR) {
1386 totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
1387 for (i = 1; i <= 6; i++) {
1388 a = meshdeform_index(mdb, x, y, z, i);
1393 isect = mdb->boundisect[acenter][i - 1];
1396 weight = (1.0f / isect->len) / totweight;
1397 rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
1398 EIG_linear_solver_right_hand_side_add(context, 0, mdb->varidx[acenter], rhs);
1403 static void meshdeform_matrix_add_semibound_phi(
1404 MeshDeformBind *mdb, int x, int y, int z, int cagevert)
1406 MDefBoundIsect *isect;
1407 float rhs, weight, totweight;
1410 a = meshdeform_index(mdb, x, y, z, 0);
1411 if (!mdb->semibound[a]) {
1417 totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
1418 for (i = 1; i <= 6; i++) {
1419 isect = mdb->boundisect[a][i - 1];
1422 weight = (1.0f / isect->len) / totweight;
1423 rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
1429 static void meshdeform_matrix_add_exterior_phi(
1430 MeshDeformBind *mdb, int x, int y, int z, int UNUSED(cagevert))
1432 float phi, totweight;
1435 acenter = meshdeform_index(mdb, x, y, z, 0);
1436 if (mdb->tag[acenter] != MESHDEFORM_TAG_EXTERIOR || mdb->semibound[acenter]) {
1442 for (i = 1; i <= 6; i++) {
1443 a = meshdeform_index(mdb, x, y, z, i);
1445 if (a != -1 && mdb->semibound[a]) {
1451 if (totweight != 0.0f) {
1452 mdb->phi[acenter] = phi / totweight;
1456 static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
1458 LinearSolver *context;
1459 float vec[3], gridvec[3];
1460 int a, b, x, y, z, totvar;
1463 /* setup variable indices */
1464 mdb->varidx = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformDSvaridx");
1465 for (a = 0, totvar = 0; a < mdb->size3; a++) {
1466 mdb->varidx[a] = (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR) ? -1 : totvar++;
1470 MEM_freeN(mdb->varidx);
1474 progress_bar(0, "Starting mesh deform solve");
1476 /* setup linear solver */
1477 context = EIG_linear_solver_new(totvar, totvar, 1);
1480 for (z = 0; z < mdb->size; z++) {
1481 for (y = 0; y < mdb->size; y++) {
1482 for (x = 0; x < mdb->size; x++) {
1483 meshdeform_matrix_add_cell(mdb, context, x, y, z);
1488 /* solve for each cage vert */
1489 for (a = 0; a < mdb->totcagevert; a++) {
1490 /* fill in right hand side and solve */
1491 for (z = 0; z < mdb->size; z++) {
1492 for (y = 0; y < mdb->size; y++) {
1493 for (x = 0; x < mdb->size; x++) {
1494 meshdeform_matrix_add_rhs(mdb, context, x, y, z, a);
1499 if (EIG_linear_solver_solve(context)) {
1500 for (z = 0; z < mdb->size; z++) {
1501 for (y = 0; y < mdb->size; y++) {
1502 for (x = 0; x < mdb->size; x++) {
1503 meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a);
1508 for (z = 0; z < mdb->size; z++) {
1509 for (y = 0; y < mdb->size; y++) {
1510 for (x = 0; x < mdb->size; x++) {
1511 meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a);
1516 for (b = 0; b < mdb->size3; b++) {
1517 if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR) {
1518 mdb->phi[b] = EIG_linear_solver_variable_get(context, 0, mdb->varidx[b]);
1520 mdb->totalphi[b] += mdb->phi[b];
1524 /* static bind : compute weights for each vertex */
1525 for (b = 0; b < mdb->totvert; b++) {
1526 if (mdb->inside[b]) {
1527 copy_v3_v3(vec, mdb->vertexcos[b]);
1528 gridvec[0] = (vec[0] - mdb->min[0] - mdb->halfwidth[0]) / mdb->width[0];
1529 gridvec[1] = (vec[1] - mdb->min[1] - mdb->halfwidth[1]) / mdb->width[1];
1530 gridvec[2] = (vec[2] - mdb->min[2] - mdb->halfwidth[2]) / mdb->width[2];
1532 mdb->weights[b * mdb->totcagevert + a] = meshdeform_interp_w(mdb, gridvec, vec, a);
1537 MDefBindInfluence *inf;
1540 for (b = 0; b < mdb->size3; b++) {
1541 if (mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) {
1542 inf = BLI_memarena_alloc(mdb->memarena, sizeof(*inf));
1544 inf->weight = mdb->phi[b];
1545 inf->next = mdb->dyngrid[b];
1546 mdb->dyngrid[b] = inf;
1552 modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)");
1553 error("Mesh Deform: failed to find bind solution.");
1558 message, sizeof(message), "Mesh deform solve %d / %d |||", a + 1, mdb->totcagevert);
1559 progress_bar((float)(a + 1) / (float)(mdb->totcagevert), message);
1564 for (b = 0; b < mdb->size3; b++) {
1565 if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR) {
1566 if (fabsf(mdb->totalphi[b] - 1.0f) > 1e-4f) {
1567 printf("totalphi deficiency [%s|%d] %d: %.10f\n",
1568 (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR) ? "interior" : "boundary",
1578 MEM_freeN(mdb->varidx);
1580 EIG_linear_solver_delete(context);
1583 static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
1585 MDefBindInfluence *inf;
1586 MDefInfluence *mdinf;
1588 float center[3], vec[3], maxwidth, totweight;
1589 int a, b, x, y, z, totinside, offset;
1591 /* compute bounding box of the cage mesh */
1592 INIT_MINMAX(mdb->min, mdb->max);
1594 for (a = 0; a < mdb->totcagevert; a++) {
1595 minmax_v3v3_v3(mdb->min, mdb->max, mdb->cagecos[a]);
1598 /* allocate memory */
1599 mdb->size = (2 << (mmd->gridsize - 1)) + 2;
1600 mdb->size3 = mdb->size * mdb->size * mdb->size;
1601 mdb->tag = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformBindTag");
1602 mdb->phi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindPhi");
1603 mdb->totalphi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindTotalPhi");
1604 mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect");
1605 mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound");
1606 mdb->bvhtree = BKE_bvhtree_from_mesh_get(&mdb->bvhdata, mdb->cagemesh, BVHTREE_FROM_LOOPTRI, 4);
1607 mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside");
1609 if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
1610 mdb->dyngrid = MEM_callocN(sizeof(MDefBindInfluence *) * mdb->size3, "MDefDynGrid");
1613 mdb->weights = MEM_callocN(sizeof(float) * mdb->totvert * mdb->totcagevert, "MDefWeights");
1616 mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
1617 BLI_memarena_use_calloc(mdb->memarena);
1619 /* initialize data from 'cagedm' for reuse */
1621 Mesh *me = mdb->cagemesh;
1622 mdb->cagemesh_cache.mpoly = me->mpoly;
1623 mdb->cagemesh_cache.mloop = me->mloop;
1624 mdb->cagemesh_cache.looptri = BKE_mesh_runtime_looptri_ensure(me);
1626 mdb->cagemesh_cache.poly_nors = CustomData_get_layer(&me->pdata, CD_NORMAL);
1629 /* make bounding box equal size in all directions, add padding, and compute
1630 * width of the cells */
1632 for (a = 0; a < 3; a++) {
1633 if (mdb->max[a] - mdb->min[a] > maxwidth) {
1634 maxwidth = mdb->max[a] - mdb->min[a];
1638 for (a = 0; a < 3; a++) {
1639 center[a] = (mdb->min[a] + mdb->max[a]) * 0.5f;
1640 mdb->min[a] = center[a] - maxwidth * 0.5f;
1641 mdb->max[a] = center[a] + maxwidth * 0.5f;
1643 mdb->width[a] = (mdb->max[a] - mdb->min[a]) / (mdb->size - 4);
1644 mdb->min[a] -= 2.1f * mdb->width[a];
1645 mdb->max[a] += 2.1f * mdb->width[a];
1647 mdb->width[a] = (mdb->max[a] - mdb->min[a]) / mdb->size;
1648 mdb->halfwidth[a] = mdb->width[a] * 0.5f;
1651 progress_bar(0, "Setting up mesh deform system");
1654 for (a = 0; a < mdb->totvert; a++) {
1655 copy_v3_v3(vec, mdb->vertexcos[a]);
1656 mdb->inside[a] = meshdeform_inside_cage(mdb, vec);
1657 if (mdb->inside[a]) {
1662 /* free temporary MDefBoundIsects */
1663 BLI_memarena_free(mdb->memarena);
1664 mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
1666 /* start with all cells untyped */
1667 for (a = 0; a < mdb->size3; a++) {
1668 mdb->tag[a] = MESHDEFORM_TAG_UNTYPED;
1671 /* detect intersections and tag boundary cells */
1672 for (z = 0; z < mdb->size; z++) {
1673 for (y = 0; y < mdb->size; y++) {
1674 for (x = 0; x < mdb->size; x++) {
1675 meshdeform_add_intersections(mdb, x, y, z);
1680 /* compute exterior and interior tags */
1681 meshdeform_bind_floodfill(mdb);
1683 for (z = 0; z < mdb->size; z++) {
1684 for (y = 0; y < mdb->size; y++) {
1685 for (x = 0; x < mdb->size; x++) {
1686 meshdeform_check_semibound(mdb, x, y, z);
1692 meshdeform_matrix_solve(mmd, mdb);
1694 /* assign results */
1695 if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
1696 mmd->totinfluence = 0;
1697 for (a = 0; a < mdb->size3; a++) {
1698 for (inf = mdb->dyngrid[a]; inf; inf = inf->next) {
1699 mmd->totinfluence++;
1703 /* convert MDefBindInfluences to smaller MDefInfluences */
1704 mmd->dyngrid = MEM_callocN(sizeof(MDefCell) * mdb->size3, "MDefDynGrid");
1705 mmd->dyninfluences = MEM_callocN(sizeof(MDefInfluence) * mmd->totinfluence, "MDefInfluence");
1707 for (a = 0; a < mdb->size3; a++) {
1708 cell = &mmd->dyngrid[a];
1709 cell->offset = offset;
1712 mdinf = mmd->dyninfluences + cell->offset;
1713 for (inf = mdb->dyngrid[a]; inf; inf = inf->next, mdinf++) {
1714 mdinf->weight = inf->weight;
1715 mdinf->vertex = inf->vertex;
1716 totweight += mdinf->weight;
1717 cell->totinfluence++;
1720 if (totweight > 0.0f) {
1721 mdinf = mmd->dyninfluences + cell->offset;
1722 for (b = 0; b < cell->totinfluence; b++, mdinf++) {
1723 mdinf->weight /= totweight;
1727 offset += cell->totinfluence;
1730 mmd->dynverts = mdb->inside;
1731 mmd->dyngridsize = mdb->size;
1732 copy_v3_v3(mmd->dyncellmin, mdb->min);
1733 mmd->dyncellwidth = mdb->width[0];
1734 MEM_freeN(mdb->dyngrid);
1737 mmd->bindweights = mdb->weights;
1738 MEM_freeN(mdb->inside);
1741 MEM_freeN(mdb->tag);
1742 MEM_freeN(mdb->phi);
1743 MEM_freeN(mdb->totalphi);
1744 MEM_freeN(mdb->boundisect);
1745 MEM_freeN(mdb->semibound);
1746 BLI_memarena_free(mdb->memarena);
1747 free_bvhtree_from_mesh(&mdb->bvhdata);
1750 void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd,
1754 float cagemat[4][4])
1756 MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)modifier_get_original(
1763 start_progress_bar();
1765 memset(&mdb, 0, sizeof(MeshDeformBind));
1767 /* get mesh and cage mesh */
1768 mdb.vertexcos = MEM_callocN(sizeof(float) * 3 * totvert, "MeshDeformCos");
1769 mdb.totvert = totvert;
1771 mdb.cagemesh = cagemesh;
1772 mdb.totcagevert = mdb.cagemesh->totvert;
1773 mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos");
1774 copy_m4_m4(mdb.cagemat, cagemat);
1776 mvert = mdb.cagemesh->mvert;
1777 for (a = 0; a < mdb.totcagevert; a++) {
1778 copy_v3_v3(mdb.cagecos[a], mvert[a].co);
1780 for (a = 0; a < mdb.totvert; a++) {
1781 mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3);
1785 harmonic_coordinates_bind(mmd_orig, &mdb);
1787 /* assign bind variables */
1788 mmd_orig->bindcagecos = (float *)mdb.cagecos;
1789 mmd_orig->totvert = mdb.totvert;
1790 mmd_orig->totcagevert = mdb.totcagevert;
1791 copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat);
1793 /* transform bindcagecos to world space */
1794 for (a = 0; a < mdb.totcagevert; a++) {
1795 mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3);
1799 MEM_freeN(mdb.vertexcos);
1801 /* compact weights */
1802 modifier_mdef_compact_influences((ModifierData *)mmd_orig);