4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
28 * meshlaplacian.c: Algorithms using the mesh laplacian.
34 #include "MEM_guardedalloc.h"
36 #include "DNA_object_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_meshdata_types.h"
39 #include "DNA_modifier_types.h"
40 #include "DNA_scene_types.h"
43 #include "BLI_edgehash.h"
44 #include "BLI_memarena.h"
46 #include "BKE_DerivedMesh.h"
47 #include "BKE_modifier.h"
48 #include "BKE_utildefines.h"
51 #include "BLI_editVert.h"
52 #include "BLI_polardecomp.h"
55 #include "RE_raytrace.h"
57 #include "ONL_opennl.h"
59 #include "BLO_sys_types.h" // for intptr_t support
63 #include "meshlaplacian.h"
66 /* ************* XXX *************** */
67 static void waitcursor(int val) {}
68 static void progress_bar() {}
69 static void start_progress_bar() {}
70 static void end_progress_bar() {}
71 static void error(char *str) { printf("error: %s\n", str); }
72 /* ************* XXX *************** */
75 /************************** Laplacian System *****************************/
77 struct LaplacianSystem {
78 NLContext context; /* opennl context */
82 float **verts; /* vertex coordinates */
83 float *varea; /* vertex weights for laplacian computation */
84 char *vpinned; /* vertex pinning */
85 int (*faces)[3]; /* face vertex indices */
86 float (*fweights)[3]; /* cotangent weights per face */
88 int areaweights; /* use area in cotangent weights? */
89 int storeweights; /* store cotangent weights in fweights */
90 int nlbegun; /* nlBegin(NL_SYSTEM/NL_MATRIX) done */
92 EdgeHash *edgehash; /* edge hash for construction */
94 struct HeatWeighting {
98 float (*verts)[3]; /* vertex coordinates */
99 float (*vnors)[3]; /* vertex normals */
101 float (*root)[3]; /* bone root */
102 float (*tip)[3]; /* bone tip */
103 float (*source)[3]; /* vertex source */
106 float *H; /* diagonal H matrix */
107 float *p; /* values from all p vectors */
108 float *mindist; /* minimum distance to a bone for all vertices */
110 RayObject *raytree; /* ray tracing acceleration structure */
111 RayFace *faces; /* faces to add to the ray tracing struture */
112 MFace **vface; /* a face that the vertex belongs to */
116 struct RigidDeformation {
127 /* Laplacian matrix construction */
129 /* Computation of these weights for the laplacian is based on:
130 "Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
131 Meyer et al, 2002. Section 3.5, formula (8).
133 We do it a bit different by going over faces instead of going over each
134 vertex and adjacent faces, since we don't store this adjacency. Also, the
135 formulas are tweaked a bit to work for non-manifold meshes. */
137 static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
139 void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
142 *p = (void*)((intptr_t)*p + (intptr_t)1);
144 BLI_edgehash_insert(edgehash, v1, v2, (void*)(intptr_t)1);
147 static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2)
149 return (int)(intptr_t)BLI_edgehash_lookup(edgehash, v1, v2);
152 static float cotan_weight(float *v1, float *v2, float *v3)
154 float a[3], b[3], c[3], clen;
156 sub_v3_v3v3(a, v2, v1);
157 sub_v3_v3v3(b, v3, v1);
158 cross_v3_v3v3(c, a, b);
165 return dot_v3v3(a, b)/clen;
168 static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3)
170 float t1, t2, t3, len1, len2, len3, area;
171 float *varea= sys->varea, *v1, *v2, *v3;
178 t1= cotan_weight(v1, v2, v3);
179 t2= cotan_weight(v2, v3, v1);
180 t3= cotan_weight(v3, v1, v2);
182 if(RAD2DEG(angle_v3v3v3(v2, v1, v3)) > 90) obtuse= 1;
183 else if(RAD2DEG(angle_v3v3v3(v1, v2, v3)) > 90) obtuse= 2;
184 else if(RAD2DEG(angle_v3v3v3(v1, v3, v2)) > 90) obtuse= 3;
187 area= area_tri_v3(v1, v2, v3);
189 varea[i1] += (obtuse == 1)? area: area*0.5;
190 varea[i2] += (obtuse == 2)? area: area*0.5;
191 varea[i3] += (obtuse == 3)? area: area*0.5;
194 len1= len_v3v3(v2, v3);
195 len2= len_v3v3(v1, v3);
196 len3= len_v3v3(v1, v2);
202 varea[i1] += (t2 + t3)*0.25f;
203 varea[i2] += (t1 + t3)*0.25f;
204 varea[i3] += (t1 + t2)*0.25f;
208 static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3)
211 float *varea= sys->varea, *v1, *v2, *v3;
217 /* instead of *0.5 we divided by the number of faces of the edge, it still
218 needs to be verified that this is indeed the correct thing to do! */
219 t1= cotan_weight(v1, v2, v3)/laplacian_edge_count(sys->edgehash, i2, i3);
220 t2= cotan_weight(v2, v3, v1)/laplacian_edge_count(sys->edgehash, i3, i1);
221 t3= cotan_weight(v3, v1, v2)/laplacian_edge_count(sys->edgehash, i1, i2);
223 nlMatrixAdd(i1, i1, (t2+t3)*varea[i1]);
224 nlMatrixAdd(i2, i2, (t1+t3)*varea[i2]);
225 nlMatrixAdd(i3, i3, (t1+t2)*varea[i3]);
227 nlMatrixAdd(i1, i2, -t3*varea[i1]);
228 nlMatrixAdd(i2, i1, -t3*varea[i2]);
230 nlMatrixAdd(i2, i3, -t1*varea[i2]);
231 nlMatrixAdd(i3, i2, -t1*varea[i3]);
233 nlMatrixAdd(i3, i1, -t2*varea[i3]);
234 nlMatrixAdd(i1, i3, -t2*varea[i1]);
236 if(sys->storeweights) {
237 sys->fweights[f][0]= t1*varea[i1];
238 sys->fweights[f][1]= t2*varea[i2];
239 sys->fweights[f][2]= t3*varea[i3];
243 LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq)
245 LaplacianSystem *sys;
247 sys= MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem");
249 sys->verts= MEM_callocN(sizeof(float*)*totvert, "LaplacianSystemVerts");
250 sys->vpinned= MEM_callocN(sizeof(char)*totvert, "LaplacianSystemVpinned");
251 sys->faces= MEM_callocN(sizeof(int)*3*totface, "LaplacianSystemFaces");
257 sys->storeweights= 0;
259 /* create opennl context */
261 nlSolverParameteri(NL_NB_VARIABLES, totvert);
263 nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
265 sys->context= nlGetCurrent();
270 void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned)
272 sys->verts[sys->totvert]= co;
273 sys->vpinned[sys->totvert]= pinned;
277 void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3)
279 sys->faces[sys->totface][0]= v1;
280 sys->faces[sys->totface][1]= v2;
281 sys->faces[sys->totface][2]= v3;
285 void laplacian_system_construct_end(LaplacianSystem *sys)
288 int a, totvert=sys->totvert, totface=sys->totface;
290 laplacian_begin_solve(sys, 0);
292 sys->varea= MEM_callocN(sizeof(float)*totvert, "LaplacianSystemVarea");
294 sys->edgehash= BLI_edgehash_new();
295 for(a=0, face=sys->faces; a<sys->totface; a++, face++) {
296 laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]);
297 laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]);
298 laplacian_increase_edge_count(sys->edgehash, (*face)[2], (*face)[0]);
302 for(a=0, face=sys->faces; a<sys->totface; a++, face++)
303 laplacian_triangle_area(sys, (*face)[0], (*face)[1], (*face)[2]);
305 for(a=0; a<totvert; a++) {
306 if(sys->areaweights) {
307 if(sys->varea[a] != 0.0f)
308 sys->varea[a]= 0.5f/sys->varea[a];
313 /* for heat weighting */
315 nlMatrixAdd(a, a, sys->heat.H[a]);
318 if(sys->storeweights)
319 sys->fweights= MEM_callocN(sizeof(float)*3*totface, "LaplacianFWeight");
321 for(a=0, face=sys->faces; a<totface; a++, face++)
322 laplacian_triangle_weights(sys, a, (*face)[0], (*face)[1], (*face)[2]);
324 MEM_freeN(sys->faces);
328 MEM_freeN(sys->varea);
332 BLI_edgehash_free(sys->edgehash, NULL);
336 void laplacian_system_delete(LaplacianSystem *sys)
338 if(sys->verts) MEM_freeN(sys->verts);
339 if(sys->varea) MEM_freeN(sys->varea);
340 if(sys->vpinned) MEM_freeN(sys->vpinned);
341 if(sys->faces) MEM_freeN(sys->faces);
342 if(sys->fweights) MEM_freeN(sys->fweights);
344 nlDeleteContext(sys->context);
348 void laplacian_begin_solve(LaplacianSystem *sys, int index)
356 for(a=0; a<sys->totvert; a++) {
357 if(sys->vpinned[a]) {
358 nlSetVariable(0, a, sys->verts[a][index]);
369 void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
371 nlRightHandSideAdd(0, v, value);
374 int laplacian_system_solve(LaplacianSystem *sys)
382 return nlSolveAdvanced(NULL, NL_TRUE);
385 float laplacian_system_get_solution(int v)
387 return nlGetVariable(0, v);
390 /************************* Heat Bone Weighting ******************************/
391 /* From "Automatic Rigging and Animation of 3D Characters"
392 Ilya Baran and Jovan Popovic, SIGGRAPH 2007 */
394 #define C_WEIGHT 1.0f
395 #define WEIGHT_LIMIT_START 0.05f
396 #define WEIGHT_LIMIT_END 0.025f
397 #define DISTANCE_EPSILON 1e-4f
399 /* Raytracing for vertex to bone/vertex visibility */
400 static void heat_ray_tree_create(LaplacianSystem *sys)
402 MFace *mface = sys->heat.mface;
403 int totface = sys->heat.totface;
404 int totvert = sys->heat.totvert;
407 sys->heat.raytree = RE_rayobject_vbvh_create(totface);
408 sys->heat.faces = MEM_callocN(sizeof(RayFace)*totface, "Heat RayFaces");
409 sys->heat.vface = MEM_callocN(sizeof(MFace*)*totvert, "HeatVFaces");
411 for(a=0; a<totface; a++) {
414 RayFace *rayface = sys->heat.faces+a;
416 RayObject *obj = RE_rayface_from_coords(
417 rayface, &sys->heat, mf,
418 sys->heat.verts[mf->v1], sys->heat.verts[mf->v2],
419 sys->heat.verts[mf->v3], mf->v4 ? sys->heat.verts[mf->v4] : 0
421 RE_rayobject_add(sys->heat.raytree, obj);
423 //Setup inverse pointers to use on isect.orig
424 sys->heat.vface[mf->v1]= mf;
425 sys->heat.vface[mf->v2]= mf;
426 sys->heat.vface[mf->v3]= mf;
427 if(mf->v4) sys->heat.vface[mf->v4]= mf;
429 RE_rayobject_done(sys->heat.raytree);
432 static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
439 mface= sys->heat.vface[vertex];
444 memset(&isec, 0, sizeof(isec));
445 isec.mode= RE_RAY_SHADOW;
447 isec.orig.ob = &sys->heat;
448 isec.orig.face = mface;
449 isec.skip = RE_SKIP_CULLFACE;
451 copy_v3_v3(isec.start, sys->heat.verts[vertex]);
453 if(sys->heat.root) /* bone */
454 closest_to_line_segment_v3(end, isec.start,
455 sys->heat.root[source], sys->heat.tip[source]);
457 copy_v3_v3(end, sys->heat.source[source]);
459 sub_v3_v3v3(isec.vec, end, isec.start);
460 isec.labda = 1.0f - 1e-5;
461 madd_v3_v3v3fl(isec.start, isec.start, isec.vec, 1e-5);
463 visible= !RE_rayobject_raycast(sys->heat.raytree, &isec);
468 static float heat_source_distance(LaplacianSystem *sys, int vertex, int source)
470 float closest[3], d[3], dist, cosine;
472 /* compute euclidian distance */
473 if(sys->heat.root) /* bone */
474 closest_to_line_segment_v3(closest, sys->heat.verts[vertex],
475 sys->heat.root[source], sys->heat.tip[source]);
477 copy_v3_v3(closest, sys->heat.source[source]);
479 sub_v3_v3v3(d, sys->heat.verts[vertex], closest);
480 dist= normalize_v3(d);
482 /* if the vertex normal does not point along the bone, increase distance */
483 cosine= INPR(d, sys->heat.vnors[vertex]);
485 return dist/(0.5f*(cosine + 1.001f));
488 static int heat_source_closest(LaplacianSystem *sys, int vertex, int source)
492 dist= heat_source_distance(sys, vertex, source);
494 if(dist <= sys->heat.mindist[vertex]*(1.0f + DISTANCE_EPSILON))
495 if(heat_ray_source_visible(sys, vertex, source))
501 static void heat_set_H(LaplacianSystem *sys, int vertex)
503 float dist, mindist, h;
504 int j, numclosest = 0;
508 /* compute minimum distance */
509 for(j=0; j<sys->heat.numsource; j++) {
510 dist= heat_source_distance(sys, vertex, j);
516 sys->heat.mindist[vertex]= mindist;
518 /* count number of sources with approximately this minimum distance */
519 for(j=0; j<sys->heat.numsource; j++)
520 if(heat_source_closest(sys, vertex, j))
523 sys->heat.p[vertex]= (numclosest > 0)? 1.0f/numclosest: 0.0f;
525 /* compute H entry */
527 mindist= maxf(mindist, 1e-4f);
528 h= numclosest*C_WEIGHT/(mindist*mindist);
533 sys->heat.H[vertex]= h;
536 void heat_calc_vnormals(LaplacianSystem *sys)
539 int a, v1, v2, v3, (*face)[3];
541 sys->heat.vnors= MEM_callocN(sizeof(float)*3*sys->totvert, "HeatVNors");
543 for(a=0, face=sys->faces; a<sys->totface; a++, face++) {
548 normal_tri_v3( fnor,sys->verts[v1], sys->verts[v2], sys->verts[v3]);
550 add_v3_v3(sys->heat.vnors[v1], fnor);
551 add_v3_v3(sys->heat.vnors[v2], fnor);
552 add_v3_v3(sys->heat.vnors[v3], fnor);
555 for(a=0; a<sys->totvert; a++)
556 normalize_v3(sys->heat.vnors[a]);
559 static void heat_laplacian_create(LaplacianSystem *sys)
561 MFace *mface = sys->heat.mface, *mf;
562 int totface= sys->heat.totface;
563 int totvert= sys->heat.totvert;
566 /* heat specific definitions */
567 sys->heat.mindist= MEM_callocN(sizeof(float)*totvert, "HeatMinDist");
568 sys->heat.H= MEM_callocN(sizeof(float)*totvert, "HeatH");
569 sys->heat.p= MEM_callocN(sizeof(float)*totvert, "HeatP");
571 /* add verts and faces to laplacian */
572 for(a=0; a<totvert; a++)
573 laplacian_add_vertex(sys, sys->heat.verts[a], 0);
575 for(a=0, mf=mface; a<totface; a++, mf++) {
576 laplacian_add_triangle(sys, mf->v1, mf->v2, mf->v3);
578 laplacian_add_triangle(sys, mf->v1, mf->v3, mf->v4);
581 /* for distance computation in set_H */
582 heat_calc_vnormals(sys);
584 for(a=0; a<totvert; a++)
588 static void heat_system_free(LaplacianSystem *sys)
590 RE_rayobject_free(sys->heat.raytree);
591 MEM_freeN(sys->heat.vface);
592 MEM_freeN(sys->heat.faces);
594 MEM_freeN(sys->heat.mindist);
595 MEM_freeN(sys->heat.H);
596 MEM_freeN(sys->heat.p);
597 MEM_freeN(sys->heat.vnors);
600 static float heat_limit_weight(float weight)
604 if(weight < WEIGHT_LIMIT_END) {
607 else if(weight < WEIGHT_LIMIT_START) {
608 t= (weight - WEIGHT_LIMIT_END)/(WEIGHT_LIMIT_START - WEIGHT_LIMIT_END);
609 return t*WEIGHT_LIMIT_START;
615 void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected)
617 LaplacianSystem *sys;
619 float solution, weight;
620 int *vertsflipped = NULL, *mask= NULL;
621 int a, totface, j, bbone, firstsegment, lastsegment, thrownerror = 0;
623 /* count triangles and create mask */
624 if(me->editflag & ME_EDIT_PAINT_MASK)
625 mask= MEM_callocN(sizeof(int)*me->totvert, "heat_bone_weighting mask");
627 for(totface=0, a=0, mface=me->mface; a<me->totface; a++, mface++) {
629 if(mface->v4) totface++;
631 if(mask && (mface->flag & ME_FACE_SEL)) {
640 /* create laplacian */
641 sys = laplacian_system_construct_begin(me->totvert, totface, 1);
643 sys->heat.mface= me->mface;
644 sys->heat.totface= me->totface;
645 sys->heat.totvert= me->totvert;
646 sys->heat.verts= verts;
647 sys->heat.root= root;
649 sys->heat.numsource= numsource;
651 heat_ray_tree_create(sys);
652 heat_laplacian_create(sys);
654 laplacian_system_construct_end(sys);
657 vertsflipped = MEM_callocN(sizeof(int)*me->totvert, "vertsflipped");
658 for(a=0; a<me->totvert; a++)
659 vertsflipped[a] = mesh_get_x_mirror_vert(ob, a);
662 /* compute weights per bone */
663 for(j=0; j<numsource; j++) {
667 firstsegment= (j == 0 || dgrouplist[j-1] != dgrouplist[j]);
668 lastsegment= (j == numsource-1 || dgrouplist[j] != dgrouplist[j+1]);
669 bbone= !(firstsegment && lastsegment);
672 if(bbone && firstsegment) {
673 for(a=0; a<me->totvert; a++) {
677 ED_vgroup_vert_remove(ob, dgrouplist[j], a);
678 if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0)
679 ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
683 /* fill right hand side */
684 laplacian_begin_solve(sys, -1);
686 for(a=0; a<me->totvert; a++)
687 if(heat_source_closest(sys, a, j))
688 laplacian_add_right_hand_side(sys, a,
689 sys->heat.H[a]*sys->heat.p[a]);
692 if(laplacian_system_solve(sys)) {
693 /* load solution into vertex groups */
694 for(a=0; a<me->totvert; a++) {
698 solution= laplacian_system_get_solution(a);
702 ED_vgroup_vert_add(ob, dgrouplist[j], a, solution,
706 weight= heat_limit_weight(solution);
708 ED_vgroup_vert_add(ob, dgrouplist[j], a, weight,
711 ED_vgroup_vert_remove(ob, dgrouplist[j], a);
714 /* do same for mirror */
715 if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
718 ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a],
719 solution, WEIGHT_ADD);
722 weight= heat_limit_weight(solution);
724 ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a],
725 weight, WEIGHT_REPLACE);
727 ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
732 else if(!thrownerror) {
733 error("Bone Heat Weighting:"
734 " failed to find solution for one or more bones");
739 /* remove too small vertex weights */
740 if(bbone && lastsegment) {
741 for(a=0; a<me->totvert; a++) {
745 weight= ED_vgroup_vert_weight(ob, dgrouplist[j], a);
746 weight= heat_limit_weight(weight);
748 ED_vgroup_vert_remove(ob, dgrouplist[j], a);
750 if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
751 weight= ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
752 weight= heat_limit_weight(weight);
754 ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
761 if(vertsflipped) MEM_freeN(vertsflipped);
762 if(mask) MEM_freeN(mask);
764 heat_system_free(sys);
766 laplacian_system_delete(sys);
770 /********************** As-Rigid-As-Possible Deformation ******************/
771 /* From "As-Rigid-As-Possible Surface Modeling",
772 Olga Sorkine and Marc Alexa, ESGP 2007. */
775 - transpose R in orthogonal
776 - flipped normals and per face adding
777 - move cancelling to transform, make origco pointer
780 static LaplacianSystem *RigidDeformSystem = NULL;
782 static void rigid_add_half_edge_to_R(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
787 sub_v3_v3v3(e, sys->rigid.origco[v1->tmp.l], sys->rigid.origco[v2->tmp.l]);
788 sub_v3_v3v3(e_, v1->co, v2->co);
791 for (i=0; i<3; i++) {
792 sys->rigid.R[v1->tmp.l][i][0] += w*e[0]*e_[i];
793 sys->rigid.R[v1->tmp.l][i][1] += w*e[1]*e_[i];
794 sys->rigid.R[v1->tmp.l][i][2] += w*e[2]*e_[i];
798 static void rigid_add_edge_to_R(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
800 rigid_add_half_edge_to_R(sys, v1, v2, w);
801 rigid_add_half_edge_to_R(sys, v2, v1, w);
804 static void rigid_orthogonalize_R(float R[][3])
809 polar_decomp(M, Q, S);
813 static void rigid_add_half_edge_to_rhs(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
816 float Rsum[3][3], rhs[3];
818 if (sys->vpinned[v1->tmp.l])
821 add_m3_m3m3(Rsum, sys->rigid.R[v1->tmp.l], sys->rigid.R[v2->tmp.l]);
824 sub_v3_v3v3(rhs, sys->rigid.origco[v1->tmp.l], sys->rigid.origco[v2->tmp.l]);
825 mul_m3_v3(Rsum, rhs);
826 mul_v3_fl(rhs, 0.5f);
829 add_v3_v3(sys->rigid.rhs[v1->tmp.l], rhs);
832 static void rigid_add_edge_to_rhs(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
834 rigid_add_half_edge_to_rhs(sys, v1, v2, w);
835 rigid_add_half_edge_to_rhs(sys, v2, v1, w);
838 void rigid_deform_iteration()
840 LaplacianSystem *sys= RigidDeformSystem;
849 nlMakeCurrent(sys->context);
853 memset(sys->rigid.R, 0, sizeof(float)*3*3*sys->totvert);
854 memset(sys->rigid.rhs, 0, sizeof(float)*3*sys->totvert);
856 for(a=0, efa=em->faces.first; efa; efa=efa->next, a++) {
857 rigid_add_edge_to_R(sys, efa->v1, efa->v2, sys->fweights[a][2]);
858 rigid_add_edge_to_R(sys, efa->v2, efa->v3, sys->fweights[a][0]);
859 rigid_add_edge_to_R(sys, efa->v3, efa->v1, sys->fweights[a][1]);
863 rigid_add_edge_to_R(sys, efa->v1, efa->v3, sys->fweights[a][2]);
864 rigid_add_edge_to_R(sys, efa->v3, efa->v4, sys->fweights[a][0]);
865 rigid_add_edge_to_R(sys, efa->v4, efa->v1, sys->fweights[a][1]);
869 for(a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
870 rigid_orthogonalize_R(sys->rigid.R[a]);
874 /* compute right hand sides for solving */
875 for(a=0, efa=em->faces.first; efa; efa=efa->next, a++) {
876 rigid_add_edge_to_rhs(sys, efa->v1, efa->v2, sys->fweights[a][2]);
877 rigid_add_edge_to_rhs(sys, efa->v2, efa->v3, sys->fweights[a][0]);
878 rigid_add_edge_to_rhs(sys, efa->v3, efa->v1, sys->fweights[a][1]);
882 rigid_add_edge_to_rhs(sys, efa->v1, efa->v3, sys->fweights[a][2]);
883 rigid_add_edge_to_rhs(sys, efa->v3, efa->v4, sys->fweights[a][0]);
884 rigid_add_edge_to_rhs(sys, efa->v4, efa->v1, sys->fweights[a][1]);
888 /* solve for positions, for X,Y and Z separately */
890 laplacian_begin_solve(sys, i);
892 for(a=0; a<sys->totvert; a++)
894 laplacian_add_right_hand_side(sys, a, sys->rigid.rhs[a][i]);
896 if(laplacian_system_solve(sys)) {
897 for(a=0, eve=em->verts.first; eve; eve=eve->next, a++)
898 eve->co[i]= laplacian_system_get_solution(a);
901 if(!sys->rigid.thrownerror) {
902 error("RigidDeform: failed to find solution.");
903 sys->rigid.thrownerror= 1;
910 static void rigid_laplacian_create(LaplacianSystem *sys)
912 EditMesh *em = sys->rigid.mesh;
917 /* add verts and faces to laplacian */
918 for(a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
919 laplacian_add_vertex(sys, eve->co, eve->pinned);
923 for(efa=em->faces.first; efa; efa=efa->next) {
924 laplacian_add_triangle(sys,
925 efa->v1->tmp.l, efa->v2->tmp.l, efa->v3->tmp.l);
927 laplacian_add_triangle(sys,
928 efa->v1->tmp.l, efa->v3->tmp.l, efa->v4->tmp.l);
932 void rigid_deform_begin(EditMesh *em)
934 LaplacianSystem *sys;
937 int a, totvert, totface;
939 /* count vertices, triangles */
940 for(totvert=0, eve=em->verts.first; eve; eve=eve->next)
943 for(totface=0, efa=em->faces.first; efa; efa=efa->next) {
945 if(efa->v4) totface++;
948 /* create laplacian */
949 sys = laplacian_system_construct_begin(totvert, totface, 0);
952 sys->rigid.R = MEM_callocN(sizeof(float)*3*3*totvert, "RigidDeformR");
953 sys->rigid.rhs = MEM_callocN(sizeof(float)*3*totvert, "RigidDeformRHS");
954 sys->rigid.origco = MEM_callocN(sizeof(float)*3*totvert, "RigidDeformCo");
956 for(a=0, eve=em->verts.first; eve; eve=eve->next, a++)
957 copy_v3_v3(sys->rigid.origco[a], eve->co);
960 sys->storeweights= 1;
962 rigid_laplacian_create(sys);
964 laplacian_system_construct_end(sys);
966 RigidDeformSystem = sys;
969 void rigid_deform_end(int cancel)
971 LaplacianSystem *sys = RigidDeformSystem;
974 EditMesh *em = sys->rigid.mesh;
979 for(a=0, eve=em->verts.first; eve; eve=eve->next, a++)
981 copy_v3_v3(eve->co, sys->rigid.origco[a]);
983 if(sys->rigid.R) MEM_freeN(sys->rigid.R);
984 if(sys->rigid.rhs) MEM_freeN(sys->rigid.rhs);
985 if(sys->rigid.origco) MEM_freeN(sys->rigid.origco);
988 laplacian_system_delete(sys);
991 RigidDeformSystem = NULL;
995 /************************** Harmonic Coordinates ****************************/
996 /* From "Harmonic Coordinates for Character Articulation",
997 Pushkar Joshi, Mark Meyer, Tony DeRose, Brian Green and Tom Sanocki,
1000 #define EPSILON 0.0001f
1002 #define MESHDEFORM_TAG_UNTYPED 0
1003 #define MESHDEFORM_TAG_BOUNDARY 1
1004 #define MESHDEFORM_TAG_INTERIOR 2
1005 #define MESHDEFORM_TAG_EXTERIOR 3
1007 #define MESHDEFORM_LEN_THRESHOLD 1e-6
1009 #define MESHDEFORM_MIN_INFLUENCE 0.0005
1011 static int MESHDEFORM_OFFSET[7][3] =
1012 {{0,0,0}, {1,0,0}, {-1,0,0}, {0,1,0}, {0,-1,0}, {0,0,1}, {0,0,-1}};
1014 typedef struct MDefBoundIsect {
1015 float co[3], uvw[4];
1016 int nvert, v[4], facing;
1020 typedef struct MDefBindInfluence {
1021 struct MDefBindInfluence *next;
1024 } MDefBindInfluence;
1026 typedef struct MeshDeformBind {
1027 /* grid dimensions */
1028 float min[3], max[3];
1029 float width[3], halfwidth[3];
1033 DerivedMesh *cagedm;
1034 float (*cagecos)[3];
1035 float (*vertexcos)[3];
1036 int totvert, totcagevert;
1040 MDefBoundIsect *(*boundisect)[6];
1043 float *phi, *totalphi;
1048 MDefBindInfluence **dyngrid;
1049 float cagemat[4][4];
1058 /* ray intersection */
1060 /* our own triangle intersection, so we can fully control the epsilons and
1061 * prevent corner case from going wrong*/
1062 static int meshdeform_tri_intersect(float orig[3], float end[3], float vert0[3],
1063 float vert1[3], float vert2[3], float *isectco, float *uvw)
1065 float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
1066 float det,inv_det, u, v, dir[3], isectdir[3];
1068 sub_v3_v3v3(dir, end, orig);
1070 /* find vectors for two edges sharing vert0 */
1071 sub_v3_v3v3(edge1, vert1, vert0);
1072 sub_v3_v3v3(edge2, vert2, vert0);
1074 /* begin calculating determinant - also used to calculate U parameter */
1075 cross_v3_v3v3(pvec, dir, edge2);
1077 /* if determinant is near zero, ray lies in plane of triangle */
1078 det = INPR(edge1, pvec);
1082 inv_det = 1.0f / det;
1084 /* calculate distance from vert0 to ray origin */
1085 sub_v3_v3v3(tvec, orig, vert0);
1087 /* calculate U parameter and test bounds */
1088 u = INPR(tvec, pvec) * inv_det;
1089 if (u < -EPSILON || u > 1.0f+EPSILON)
1092 /* prepare to test V parameter */
1093 cross_v3_v3v3(qvec, tvec, edge1);
1095 /* calculate V parameter and test bounds */
1096 v = INPR(dir, qvec) * inv_det;
1097 if (v < -EPSILON || u + v > 1.0f+EPSILON)
1100 isectco[0]= (1.0f - u - v)*vert0[0] + u*vert1[0] + v*vert2[0];
1101 isectco[1]= (1.0f - u - v)*vert0[1] + u*vert1[1] + v*vert2[1];
1102 isectco[2]= (1.0f - u - v)*vert0[2] + u*vert1[2] + v*vert2[2];
1104 uvw[0]= 1.0 - u - v;
1108 /* check if it is within the length of the line segment */
1109 sub_v3_v3v3(isectdir, isectco, orig);
1111 if(INPR(dir, isectdir) < -EPSILON)
1114 if(INPR(dir, dir) + EPSILON < INPR(isectdir, isectdir))
1120 /* blender's raytracer is not use now, even though it is much faster. it can
1121 * give problems with rays falling through, so we use our own intersection
1122 * function above with tweaked epsilons */
1125 static MeshDeformBind *MESHDEFORM_BIND = NULL;
1127 static void meshdeform_ray_coords_func(RayFace *face, float **v1, float **v2, float **v3, float **v4)
1129 MFace *mface= (MFace*)face;
1130 float (*cagecos)[3]= MESHDEFORM_BIND->cagecos;
1132 *v1= cagecos[mface->v1];
1133 *v2= cagecos[mface->v2];
1134 *v3= cagecos[mface->v3];
1135 *v4= (mface->v4)? cagecos[mface->v4]: NULL;
1138 static int meshdeform_ray_check_func(Isect *is, RayFace *face)
1143 static void meshdeform_ray_tree_create(MeshDeformBind *mdb)
1146 float min[3], max[3];
1149 /* create a raytrace tree from the mesh */
1150 INIT_MINMAX(min, max);
1152 for(a=0; a<mdb->totcagevert; a++)
1153 DO_MINMAX(mdb->cagecos[a], min, max)
1155 MESHDEFORM_BIND= mdb;
1157 mface= mdb->cagedm->getFaceArray(mdb->cagedm);
1158 totface= mdb->cagedm->getNumFaces(mdb->cagedm);
1160 mdb->raytree= RE_ray_tree_create(64, totface, min, max,
1161 meshdeform_ray_coords_func, meshdeform_ray_check_func);
1163 for(a=0; a<totface; a++, mface++)
1164 RE_ray_tree_add_face(mdb->raytree, mface);
1166 RE_ray_tree_done(mdb->raytree);
1169 static void meshdeform_ray_tree_free(MeshDeformBind *mdb)
1171 MESHDEFORM_BIND= NULL;
1172 RE_ray_tree_free(mdb->raytree);
1176 static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec)
1179 float face[4][3], co[3], uvw[3], len, nor[3], end[3];
1180 int f, hit, is= 0, totface;
1184 mface= mdb->cagedm->getFaceArray(mdb->cagedm);
1185 totface= mdb->cagedm->getNumFaces(mdb->cagedm);
1187 add_v3_v3v3(end, isec->start, isec->vec);
1189 for(f=0; f<totface; f++, mface++) {
1190 copy_v3_v3(face[0], mdb->cagecos[mface->v1]);
1191 copy_v3_v3(face[1], mdb->cagecos[mface->v2]);
1192 copy_v3_v3(face[2], mdb->cagecos[mface->v3]);
1195 copy_v3_v3(face[3], mdb->cagecos[mface->v4]);
1196 hit = meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw);
1199 normal_tri_v3( nor,face[0], face[1], face[2]);
1202 hit= meshdeform_tri_intersect(isec->start, end, face[0], face[2], face[3], co, uvw);
1203 normal_tri_v3( nor,face[0], face[2], face[3]);
1207 hit= meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw);
1208 normal_tri_v3( nor,face[0], face[1], face[2]);
1212 len= len_v3v3(isec->start, co)/len_v3v3(isec->start, end);
1213 if(len < isec->labda) {
1215 isec->hit.face = mface;
1216 isec->isect= (INPR(isec->vec, nor) <= 0.0f);
1225 static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float *co1, float *co2)
1227 MDefBoundIsect *isect;
1229 float (*cagecos)[3];
1231 float vert[4][3], len, end[3];
1232 static float epsilon[3]= {0, 0, 0}; //1e-4, 1e-4, 1e-4};
1235 memset(&isec, 0, sizeof(isec));
1236 isec.mode= RE_RAY_MIRROR; /* we want the closest intersection */
1240 VECADD(isec.start, co1, epsilon);
1241 VECADD(end, co2, epsilon);
1242 sub_v3_v3v3(isec.vec, end, isec.start);
1245 /*if(RE_ray_tree_intersect(mdb->raytree, &isec)) {*/
1248 if(meshdeform_intersect(mdb, &isec)) {
1250 mface=(MFace*)isec.hit.face;
1252 /* create MDefBoundIsect */
1253 isect= BLI_memarena_alloc(mdb->memarena, sizeof(*isect));
1255 /* compute intersection coordinate */
1256 isect->co[0]= co1[0] + isec.vec[0]*len;
1257 isect->co[1]= co1[1] + isec.vec[1]*len;
1258 isect->co[2]= co1[2] + isec.vec[2]*len;
1260 isect->len= len_v3v3(co1, isect->co);
1261 if(isect->len < MESHDEFORM_LEN_THRESHOLD)
1262 isect->len= MESHDEFORM_LEN_THRESHOLD;
1264 isect->v[0]= mface->v1;
1265 isect->v[1]= mface->v2;
1266 isect->v[2]= mface->v3;
1267 isect->v[3]= mface->v4;
1268 isect->nvert= (mface->v4)? 4: 3;
1270 isect->facing= isec.isect;
1272 /* compute mean value coordinates for interpolation */
1273 cagecos= mdb->cagecos;
1274 copy_v3_v3(vert[0], cagecos[mface->v1]);
1275 copy_v3_v3(vert[1], cagecos[mface->v2]);
1276 copy_v3_v3(vert[2], cagecos[mface->v3]);
1277 if(mface->v4) copy_v3_v3(vert[3], cagecos[mface->v4]);
1278 interp_weights_poly_v3( isect->uvw,vert, isect->nvert, isect->co);
1286 static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
1288 MDefBoundIsect *isect;
1289 float outside[3], start[3], dir[3];
1292 for(i=1; i<=6; i++) {
1295 outside[0] = co[0] + (mdb->max[0] - mdb->min[0] + 1.0f)*MESHDEFORM_OFFSET[i][0];
1296 outside[1] = co[1] + (mdb->max[1] - mdb->min[1] + 1.0f)*MESHDEFORM_OFFSET[i][1];
1297 outside[2] = co[2] + (mdb->max[2] - mdb->min[2] + 1.0f)*MESHDEFORM_OFFSET[i][2];
1299 copy_v3_v3(start, co);
1300 sub_v3_v3v3(dir, outside, start);
1303 isect = meshdeform_ray_tree_intersect(mdb, start, outside);
1304 if(isect && !isect->facing)
1313 static int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
1315 int size= mdb->size;
1317 x += MESHDEFORM_OFFSET[n][0];
1318 y += MESHDEFORM_OFFSET[n][1];
1319 z += MESHDEFORM_OFFSET[n][2];
1321 if(x < 0 || x >= mdb->size)
1323 if(y < 0 || y >= mdb->size)
1325 if(z < 0 || z >= mdb->size)
1328 return x + y*size + z*size*size;
1331 static void meshdeform_cell_center(MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
1333 x += MESHDEFORM_OFFSET[n][0];
1334 y += MESHDEFORM_OFFSET[n][1];
1335 z += MESHDEFORM_OFFSET[n][2];
1337 center[0]= mdb->min[0] + x*mdb->width[0] + mdb->halfwidth[0];
1338 center[1]= mdb->min[1] + y*mdb->width[1] + mdb->halfwidth[1];
1339 center[2]= mdb->min[2] + z*mdb->width[2] + mdb->halfwidth[2];
1342 static void meshdeform_add_intersections(MeshDeformBind *mdb, int x, int y, int z)
1344 MDefBoundIsect *isect;
1345 float center[3], ncenter[3];
1348 a= meshdeform_index(mdb, x, y, z, 0);
1349 meshdeform_cell_center(mdb, x, y, z, 0, center);
1351 /* check each outgoing edge for intersection */
1352 for(i=1; i<=6; i++) {
1353 if(meshdeform_index(mdb, x, y, z, i) == -1)
1356 meshdeform_cell_center(mdb, x, y, z, i, ncenter);
1358 isect= meshdeform_ray_tree_intersect(mdb, center, ncenter);
1360 mdb->boundisect[a][i-1]= isect;
1361 mdb->tag[a]= MESHDEFORM_TAG_BOUNDARY;
1366 static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
1368 int *stack, *tag= mdb->tag;
1369 int a, b, i, xyz[3], stacksize, size= mdb->size;
1371 stack= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformBindStack");
1373 /* we know lower left corner is EXTERIOR because of padding */
1374 tag[0]= MESHDEFORM_TAG_EXTERIOR;
1378 /* floodfill exterior tag */
1379 while(stacksize > 0) {
1380 a= stack[--stacksize];
1382 xyz[2]= a/(size*size);
1383 xyz[1]= (a - xyz[2]*size*size)/size;
1384 xyz[0]= a - xyz[1]*size - xyz[2]*size*size;
1386 for(i=1; i<=6; i++) {
1387 b= meshdeform_index(mdb, xyz[0], xyz[1], xyz[2], i);
1390 if(tag[b] == MESHDEFORM_TAG_UNTYPED ||
1391 (tag[b] == MESHDEFORM_TAG_BOUNDARY && !mdb->boundisect[a][i-1])) {
1392 tag[b]= MESHDEFORM_TAG_EXTERIOR;
1393 stack[stacksize++]= b;
1399 /* other cells are interior */
1400 for(a=0; a<size*size*size; a++)
1401 if(tag[a]==MESHDEFORM_TAG_UNTYPED)
1402 tag[a]= MESHDEFORM_TAG_INTERIOR;
1408 for(a=0; a<size*size*size; a++)
1409 if(tag[a]==MESHDEFORM_TAG_BOUNDARY)
1411 else if(tag[a]==MESHDEFORM_TAG_INTERIOR)
1413 else if(tag[a]==MESHDEFORM_TAG_EXTERIOR) {
1416 if(mdb->semibound[a])
1420 printf("interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
1427 static float meshdeform_boundary_phi(MeshDeformBind *mdb, MDefBoundIsect *isect, int cagevert)
1431 for(a=0; a<isect->nvert; a++)
1432 if(isect->v[a] == cagevert)
1433 return isect->uvw[a];
1438 static float meshdeform_interp_w(MeshDeformBind *mdb, float *gridvec, float *vec, int cagevert)
1440 float dvec[3], ivec[3], wx, wy, wz, result=0.0f;
1441 float weight, totweight= 0.0f;
1444 for(i=0; i<3; i++) {
1445 ivec[i]= (int)gridvec[i];
1446 dvec[i]= gridvec[i] - ivec[i];
1449 for(i=0; i<8; i++) {
1450 if(i & 1) { x= ivec[0]+1; wx= dvec[0]; }
1451 else { x= ivec[0]; wx= 1.0f-dvec[0]; }
1453 if(i & 2) { y= ivec[1]+1; wy= dvec[1]; }
1454 else { y= ivec[1]; wy= 1.0f-dvec[1]; }
1456 if(i & 4) { z= ivec[2]+1; wz= dvec[2]; }
1457 else { z= ivec[2]; wz= 1.0f-dvec[2]; }
1459 CLAMP(x, 0, mdb->size-1);
1460 CLAMP(y, 0, mdb->size-1);
1461 CLAMP(z, 0, mdb->size-1);
1463 a= meshdeform_index(mdb, x, y, z, 0);
1465 result += weight*mdb->phi[a];
1466 totweight += weight;
1469 if(totweight > 0.0f)
1470 result /= totweight;
1475 static void meshdeform_check_semibound(MeshDeformBind *mdb, int x, int y, int z)
1479 a= meshdeform_index(mdb, x, y, z, 0);
1480 if(mdb->tag[a] != MESHDEFORM_TAG_EXTERIOR)
1484 if(mdb->boundisect[a][i-1])
1485 mdb->semibound[a]= 1;
1488 static float meshdeform_boundary_total_weight(MeshDeformBind *mdb, int x, int y, int z)
1490 float weight, totweight= 0.0f;
1493 a= meshdeform_index(mdb, x, y, z, 0);
1495 /* count weight for neighbour cells */
1496 for(i=1; i<=6; i++) {
1497 if(meshdeform_index(mdb, x, y, z, i) == -1)
1500 if(mdb->boundisect[a][i-1])
1501 weight= 1.0f/mdb->boundisect[a][i-1]->len;
1502 else if(!mdb->semibound[a])
1503 weight= 1.0f/mdb->width[0];
1507 totweight += weight;
1513 static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, int x, int y, int z)
1515 MDefBoundIsect *isect;
1516 float weight, totweight;
1519 acenter= meshdeform_index(mdb, x, y, z, 0);
1520 if(mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
1523 nlMatrixAdd(mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
1525 totweight= meshdeform_boundary_total_weight(mdb, x, y, z);
1526 for(i=1; i<=6; i++) {
1527 a= meshdeform_index(mdb, x, y, z, i);
1528 if(a == -1 || mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)
1531 isect= mdb->boundisect[acenter][i-1];
1533 weight= (1.0f/mdb->width[0])/totweight;
1534 nlMatrixAdd(mdb->varidx[acenter], mdb->varidx[a], -weight);
1539 static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
1541 MDefBoundIsect *isect;
1542 float rhs, weight, totweight;
1545 acenter= meshdeform_index(mdb, x, y, z, 0);
1546 if(mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
1549 totweight= meshdeform_boundary_total_weight(mdb, x, y, z);
1550 for(i=1; i<=6; i++) {
1551 a= meshdeform_index(mdb, x, y, z, i);
1555 isect= mdb->boundisect[acenter][i-1];
1558 weight= (1.0f/isect->len)/totweight;
1559 rhs= weight*meshdeform_boundary_phi(mdb, isect, cagevert);
1560 nlRightHandSideAdd(0, mdb->varidx[acenter], rhs);
1565 static void meshdeform_matrix_add_semibound_phi(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
1567 MDefBoundIsect *isect;
1568 float rhs, weight, totweight;
1571 a= meshdeform_index(mdb, x, y, z, 0);
1572 if(!mdb->semibound[a])
1577 totweight= meshdeform_boundary_total_weight(mdb, x, y, z);
1578 for(i=1; i<=6; i++) {
1579 isect= mdb->boundisect[a][i-1];
1582 weight= (1.0f/isect->len)/totweight;
1583 rhs= weight*meshdeform_boundary_phi(mdb, isect, cagevert);
1589 static void meshdeform_matrix_add_exterior_phi(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
1591 float phi, totweight;
1594 acenter= meshdeform_index(mdb, x, y, z, 0);
1595 if(mdb->tag[acenter] != MESHDEFORM_TAG_EXTERIOR || mdb->semibound[acenter])
1600 for(i=1; i<=6; i++) {
1601 a= meshdeform_index(mdb, x, y, z, i);
1603 if(a != -1 && mdb->semibound[a]) {
1609 if(totweight != 0.0f)
1610 mdb->phi[acenter]= phi/totweight;
1613 static void meshdeform_matrix_solve(MeshDeformBind *mdb)
1616 float vec[3], gridvec[3];
1617 int a, b, x, y, z, totvar;
1620 /* setup variable indices */
1621 mdb->varidx= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformDSvaridx");
1622 for(a=0, totvar=0; a<mdb->size3; a++)
1623 mdb->varidx[a]= (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)? -1: totvar++;
1626 MEM_freeN(mdb->varidx);
1630 progress_bar(0, "Starting mesh deform solve");
1632 /* setup opennl solver */
1634 context= nlGetCurrent();
1636 nlSolverParameteri(NL_NB_VARIABLES, totvar);
1637 nlSolverParameteri(NL_NB_ROWS, totvar);
1638 nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 1);
1644 for(z=0; z<mdb->size; z++)
1645 for(y=0; y<mdb->size; y++)
1646 for(x=0; x<mdb->size; x++)
1647 meshdeform_matrix_add_cell(mdb, x, y, z);
1649 /* solve for each cage vert */
1650 for(a=0; a<mdb->totcagevert; a++) {
1656 /* fill in right hand side and solve */
1657 for(z=0; z<mdb->size; z++)
1658 for(y=0; y<mdb->size; y++)
1659 for(x=0; x<mdb->size; x++)
1660 meshdeform_matrix_add_rhs(mdb, x, y, z, a);
1669 if(nlSolveAdvanced(NULL, NL_TRUE)) {
1670 for(z=0; z<mdb->size; z++)
1671 for(y=0; y<mdb->size; y++)
1672 for(x=0; x<mdb->size; x++)
1673 meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a);
1675 for(z=0; z<mdb->size; z++)
1676 for(y=0; y<mdb->size; y++)
1677 for(x=0; x<mdb->size; x++)
1678 meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a);
1680 for(b=0; b<mdb->size3; b++) {
1681 if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
1682 mdb->phi[b]= nlGetVariable(0, mdb->varidx[b]);
1683 mdb->totalphi[b] += mdb->phi[b];
1687 /* static bind : compute weights for each vertex */
1688 for(b=0; b<mdb->totvert; b++) {
1689 if(mdb->inside[b]) {
1690 copy_v3_v3(vec, mdb->vertexcos[b]);
1691 gridvec[0]= (vec[0] - mdb->min[0] - mdb->halfwidth[0])/mdb->width[0];
1692 gridvec[1]= (vec[1] - mdb->min[1] - mdb->halfwidth[1])/mdb->width[1];
1693 gridvec[2]= (vec[2] - mdb->min[2] - mdb->halfwidth[2])/mdb->width[2];
1695 mdb->weights[b*mdb->totcagevert + a]= meshdeform_interp_w(mdb, gridvec, vec, a);
1700 MDefBindInfluence *inf;
1703 for(b=0; b<mdb->size3; b++) {
1704 if(mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) {
1705 inf= BLI_memarena_alloc(mdb->memarena, sizeof(*inf));
1707 inf->weight= mdb->phi[b];
1708 inf->next= mdb->dyngrid[b];
1709 mdb->dyngrid[b]= inf;
1715 error("Mesh Deform: failed to find solution.");
1719 sprintf(message, "Mesh deform solve %d / %d |||", a+1, mdb->totcagevert);
1720 progress_bar((float)(a+1)/(float)(mdb->totcagevert), message);
1725 for(b=0; b<mdb->size3; b++)
1726 if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
1727 if(fabs(mdb->totalphi[b] - 1.0f) > 1e-4)
1728 printf("totalphi deficiency [%s|%d] %d: %.10f\n",
1729 (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR)? "interior": "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]);
1733 MEM_freeN(mdb->varidx);
1735 nlDeleteContext(context);
1738 static void harmonic_coordinates_bind(Scene *scene, MeshDeformModifierData *mmd, MeshDeformBind *mdb)
1740 MDefBindInfluence *inf;
1741 MDefInfluence *mdinf;
1743 float center[3], vec[3], maxwidth, totweight;
1744 int a, b, x, y, z, totinside, offset;
1746 /* compute bounding box of the cage mesh */
1747 INIT_MINMAX(mdb->min, mdb->max);
1749 for(a=0; a<mdb->totcagevert; a++)
1750 DO_MINMAX(mdb->cagecos[a], mdb->min, mdb->max);
1752 /* allocate memory */
1753 mdb->size= (2<<(mmd->gridsize-1)) + 2;
1754 mdb->size3= mdb->size*mdb->size*mdb->size;
1755 mdb->tag= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformBindTag");
1756 mdb->phi= MEM_callocN(sizeof(float)*mdb->size3, "MeshDeformBindPhi");
1757 mdb->totalphi= MEM_callocN(sizeof(float)*mdb->size3, "MeshDeformBindTotalPhi");
1758 mdb->boundisect= MEM_callocN(sizeof(*mdb->boundisect)*mdb->size3, "MDefBoundIsect");
1759 mdb->semibound= MEM_callocN(sizeof(int)*mdb->size3, "MDefSemiBound");
1761 mdb->inside= MEM_callocN(sizeof(int)*mdb->totvert, "MDefInside");
1763 if(mmd->flag & MOD_MDEF_DYNAMIC_BIND)
1764 mdb->dyngrid= MEM_callocN(sizeof(MDefBindInfluence*)*mdb->size3, "MDefDynGrid");
1766 mdb->weights= MEM_callocN(sizeof(float)*mdb->totvert*mdb->totcagevert, "MDefWeights");
1768 mdb->memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
1769 BLI_memarena_use_calloc(mdb->memarena);
1771 /* make bounding box equal size in all directions, add padding, and compute
1772 * width of the cells */
1775 if(mdb->max[a]-mdb->min[a] > maxwidth)
1776 maxwidth= mdb->max[a]-mdb->min[a];
1778 for(a=0; a<3; a++) {
1779 center[a]= (mdb->min[a]+mdb->max[a])*0.5f;
1780 mdb->min[a]= center[a] - maxwidth*0.5f;
1781 mdb->max[a]= center[a] + maxwidth*0.5f;
1783 mdb->width[a]= (mdb->max[a]-mdb->min[a])/(mdb->size-4);
1784 mdb->min[a] -= 2.1f*mdb->width[a];
1785 mdb->max[a] += 2.1f*mdb->width[a];
1787 mdb->width[a]= (mdb->max[a]-mdb->min[a])/mdb->size;
1788 mdb->halfwidth[a]= mdb->width[a]*0.5f;
1791 progress_bar(0, "Setting up mesh deform system");
1794 /* create ray tree */
1795 meshdeform_ray_tree_create(mdb);
1799 for(a=0; a<mdb->totvert; a++) {
1800 copy_v3_v3(vec, mdb->vertexcos[a]);
1801 mdb->inside[a]= meshdeform_inside_cage(mdb, vec);
1806 /* free temporary MDefBoundIsects */
1807 BLI_memarena_free(mdb->memarena);
1808 mdb->memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
1810 /* start with all cells untyped */
1811 for(a=0; a<mdb->size3; a++)
1812 mdb->tag[a]= MESHDEFORM_TAG_UNTYPED;
1814 /* detect intersections and tag boundary cells */
1815 for(z=0; z<mdb->size; z++)
1816 for(y=0; y<mdb->size; y++)
1817 for(x=0; x<mdb->size; x++)
1818 meshdeform_add_intersections(mdb, x, y, z);
1822 meshdeform_ray_tree_free(mdb);
1825 /* compute exterior and interior tags */
1826 meshdeform_bind_floodfill(mdb);
1828 for(z=0; z<mdb->size; z++)
1829 for(y=0; y<mdb->size; y++)
1830 for(x=0; x<mdb->size; x++)
1831 meshdeform_check_semibound(mdb, x, y, z);
1834 meshdeform_matrix_solve(mdb);
1836 /* assign results */
1837 if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
1838 mmd->totinfluence= 0;
1839 for(a=0; a<mdb->size3; a++)
1840 for(inf=mdb->dyngrid[a]; inf; inf=inf->next)
1841 mmd->totinfluence++;
1843 /* convert MDefBindInfluences to smaller MDefInfluences */
1844 mmd->dyngrid= MEM_callocN(sizeof(MDefCell)*mdb->size3, "MDefDynGrid");
1845 mmd->dyninfluences= MEM_callocN(sizeof(MDefInfluence)*mmd->totinfluence, "MDefInfluence");
1847 for(a=0; a<mdb->size3; a++) {
1848 cell= &mmd->dyngrid[a];
1849 cell->offset= offset;
1852 mdinf= mmd->dyninfluences + cell->offset;
1853 for(inf=mdb->dyngrid[a]; inf; inf=inf->next, mdinf++) {
1854 mdinf->weight= inf->weight;
1855 mdinf->vertex= inf->vertex;
1856 totweight += mdinf->weight;
1857 cell->totinfluence++;
1860 if(totweight > 0.0f) {
1861 mdinf= mmd->dyninfluences + cell->offset;
1862 for(b=0; b<cell->totinfluence; b++, mdinf++)
1863 mdinf->weight /= totweight;
1866 offset += cell->totinfluence;
1869 mmd->dynverts= mdb->inside;
1870 mmd->dyngridsize= mdb->size;
1871 copy_v3_v3(mmd->dyncellmin, mdb->min);
1872 mmd->dyncellwidth= mdb->width[0];
1873 MEM_freeN(mdb->dyngrid);
1876 mmd->bindweights= mdb->weights;
1877 MEM_freeN(mdb->inside);
1880 MEM_freeN(mdb->tag);
1881 MEM_freeN(mdb->phi);
1882 MEM_freeN(mdb->totalphi);
1883 MEM_freeN(mdb->boundisect);
1884 MEM_freeN(mdb->semibound);
1885 BLI_memarena_free(mdb->memarena);
1889 static void heat_weighting_bind(Scene *scene, DerivedMesh *dm, MeshDeformModifierData *mmd, MeshDeformBind *mdb)
1891 LaplacianSystem *sys;
1892 MFace *mface= dm->getFaceArray(dm), *mf;
1893 int totvert= dm->getNumVerts(dm);
1894 int totface= dm->getNumFaces(dm);
1895 float solution, weight;
1896 int a, tottri, j, thrownerror = 0;
1898 mdb->weights= MEM_callocN(sizeof(float)*mdb->totvert*mdb->totcagevert, "MDefWeights");
1900 /* count triangles */
1901 for(tottri=0, a=0, mf=mface; a<totface; a++, mf++) {
1903 if(mf->v4) tottri++;
1906 /* create laplacian */
1907 sys = laplacian_system_construct_begin(totvert, tottri, 1);
1909 sys->heat.mface= mface;
1910 sys->heat.totface= totface;
1911 sys->heat.totvert= totvert;
1912 sys->heat.verts= mdb->vertexcos;
1913 sys->heat.source = mdb->cagecos;
1914 sys->heat.numsource= mdb->totcagevert;
1916 heat_ray_tree_create(sys);
1917 heat_laplacian_create(sys);
1919 laplacian_system_construct_end(sys);
1921 /* compute weights per bone */
1922 for(j=0; j<mdb->totcagevert; j++) {
1923 /* fill right hand side */
1924 laplacian_begin_solve(sys, -1);
1926 for(a=0; a<totvert; a++)
1927 if(heat_source_closest(sys, a, j))
1928 laplacian_add_right_hand_side(sys, a,
1929 sys->heat.H[a]*sys->heat.p[a]);
1932 if(laplacian_system_solve(sys)) {
1933 /* load solution into vertex groups */
1934 for(a=0; a<totvert; a++) {
1935 solution= laplacian_system_get_solution(a);
1937 weight= heat_limit_weight(solution);
1939 mdb->weights[a*mdb->totcagevert + j] = weight;
1942 else if(!thrownerror) {
1943 error("Mesh Deform Heat Weighting:"
1944 " failed to find solution for one or more vertices");
1951 heat_system_free(sys);
1952 laplacian_system_delete(sys);
1954 mmd->bindweights= mdb->weights;
1958 void mesh_deform_bind(Scene *scene, DerivedMesh *dm, MeshDeformModifierData *mmd, float *vertexcos, int totvert, float cagemat[][4])
1965 start_progress_bar();
1967 memset(&mdb, 0, sizeof(MeshDeformBind));
1969 /* get mesh and cage mesh */
1970 mdb.vertexcos= MEM_callocN(sizeof(float)*3*totvert, "MeshDeformCos");
1971 mdb.totvert= totvert;
1973 mdb.cagedm= mesh_create_derived_no_deform(scene, mmd->object, NULL, CD_MASK_BAREMESH);
1974 mdb.totcagevert= mdb.cagedm->getNumVerts(mdb.cagedm);
1975 mdb.cagecos= MEM_callocN(sizeof(*mdb.cagecos)*mdb.totcagevert, "MeshDeformBindCos");
1976 copy_m4_m4(mdb.cagemat, cagemat);
1978 mvert= mdb.cagedm->getVertArray(mdb.cagedm);
1979 for(a=0; a<mdb.totcagevert; a++)
1980 copy_v3_v3(mdb.cagecos[a], mvert[a].co);
1981 for(a=0; a<mdb.totvert; a++)
1982 mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a*3);
1986 if(mmd->mode == MOD_MDEF_VOLUME)
1987 harmonic_coordinates_bind(scene, mmd, &mdb);
1989 heat_weighting_bind(scene, dm, mmd, &mdb);
1991 harmonic_coordinates_bind(scene, mmd, &mdb);
1994 /* assign bind variables */
1995 mmd->bindcagecos= (float*)mdb.cagecos;
1996 mmd->totvert= mdb.totvert;
1997 mmd->totcagevert= mdb.totcagevert;
1998 copy_m4_m4(mmd->bindmat, mmd->object->obmat);
2000 /* transform bindcagecos to world space */
2001 for(a=0; a<mdb.totcagevert; a++)
2002 mul_m4_v3(mmd->object->obmat, mmd->bindcagecos+a*3);
2005 mdb.cagedm->release(mdb.cagedm);
2006 MEM_freeN(mdb.vertexcos);
2008 /* compact weights */
2009 modifier_mdef_compact_influences((ModifierData*)mmd);