Blender  V2.93
meshlaplacian.c
Go to the documentation of this file.
1 /*
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.
6  *
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.
11  *
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.
16  */
17 
22 #include "MEM_guardedalloc.h"
23 
24 #include "DNA_mesh_types.h"
25 #include "DNA_meshdata_types.h"
26 #include "DNA_object_types.h"
27 #include "DNA_scene_types.h"
28 
29 #include "BLI_alloca.h"
30 #include "BLI_edgehash.h"
31 #include "BLI_math.h"
32 #include "BLI_memarena.h"
33 #include "BLI_string.h"
34 
35 #include "BLT_translation.h"
36 
37 #include "BKE_bvhutils.h"
38 #include "BKE_mesh.h"
39 #include "BKE_mesh_runtime.h"
40 #include "BKE_mesh_wrapper.h"
41 #include "BKE_modifier.h"
42 
43 #include "ED_armature.h"
44 #include "ED_mesh.h"
45 
46 #include "DEG_depsgraph.h"
47 
48 #include "eigen_capi.h"
49 
50 #include "meshlaplacian.h"
51 
52 /* ************* XXX *************** */
53 static void waitcursor(int UNUSED(val))
54 {
55 }
56 static void progress_bar(int UNUSED(dummy_val), const char *UNUSED(dummy))
57 {
58 }
59 static void start_progress_bar(void)
60 {
61 }
62 static void end_progress_bar(void)
63 {
64 }
65 static void error(const char *str)
66 {
67  printf("error: %s\n", str);
68 }
69 /* ************* XXX *************** */
70 
71 /************************** Laplacian System *****************************/
72 
74  LinearSolver *context; /* linear solver */
75 
77 
78  float **verts; /* vertex coordinates */
79  float *varea; /* vertex weights for laplacian computation */
80  char *vpinned; /* vertex pinning */
81  int (*faces)[3]; /* face vertex indices */
82  float (*fweights)[3]; /* cotangent weights per face */
83 
84  int areaweights; /* use area in cotangent weights? */
85  int storeweights; /* store cotangent weights in fweights */
86  bool variablesdone; /* variables set in linear system */
87 
88  EdgeHash *edgehash; /* edge hash for construction */
89 
90  struct HeatWeighting {
92  const MLoop *mloop; /* needed to find vertices by index */
93  int totvert;
94  int tottri;
95  float (*verts)[3]; /* vertex coordinates */
96  float (*vnors)[3]; /* vertex normals */
97 
98  float (*root)[3]; /* bone root */
99  float (*tip)[3]; /* bone tip */
101 
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 */
105 
106  BVHTree *bvhtree; /* ray tracing acceleration structure */
107  const MLoopTri **vltree; /* a looptri that the vertex belongs to */
108  } heat;
109 };
110 
111 /* Laplacian matrix construction */
112 
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).
116  *
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. */
120 
121 static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
122 {
123  void **p;
124 
125  if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p)) {
126  *p = (void *)((intptr_t)*p + (intptr_t)1);
127  }
128  else {
129  *p = (void *)((intptr_t)1);
130  }
131 }
132 
133 static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2)
134 {
135  return (int)(intptr_t)BLI_edgehash_lookup(edgehash, v1, v2);
136 }
137 
138 static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3)
139 {
140  float t1, t2, t3, len1, len2, len3, area;
141  float *varea = sys->varea, *v1, *v2, *v3;
142  int obtuse = 0;
143 
144  v1 = sys->verts[i1];
145  v2 = sys->verts[i2];
146  v3 = sys->verts[i3];
147 
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);
151 
152  if (angle_v3v3v3(v2, v1, v3) > DEG2RADF(90.0f)) {
153  obtuse = 1;
154  }
155  else if (angle_v3v3v3(v1, v2, v3) > DEG2RADF(90.0f)) {
156  obtuse = 2;
157  }
158  else if (angle_v3v3v3(v1, v3, v2) > DEG2RADF(90.0f)) {
159  obtuse = 3;
160  }
161 
162  if (obtuse > 0) {
163  area = area_tri_v3(v1, v2, v3);
164 
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;
168  }
169  else {
170  len1 = len_v3v3(v2, v3);
171  len2 = len_v3v3(v1, v3);
172  len3 = len_v3v3(v1, v2);
173 
174  t1 *= len1 * len1;
175  t2 *= len2 * len2;
176  t3 *= len3 * len3;
177 
178  varea[i1] += (t2 + t3) * 0.25f;
179  varea[i2] += (t1 + t3) * 0.25f;
180  varea[i3] += (t1 + t2) * 0.25f;
181  }
182 }
183 
184 static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3)
185 {
186  float t1, t2, t3;
187  float *varea = sys->varea, *v1, *v2, *v3;
188 
189  v1 = sys->verts[i1];
190  v2 = sys->verts[i2];
191  v3 = sys->verts[i3];
192 
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);
198 
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]);
202 
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]);
205 
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]);
208 
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]);
211 
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];
216  }
217 }
218 
219 static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq)
220 {
221  LaplacianSystem *sys;
222 
223  sys = MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem");
224 
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");
228 
229  sys->totvert = 0;
230  sys->totface = 0;
231 
232  sys->areaweights = 1;
233  sys->storeweights = 0;
234 
235  /* create linear solver */
236  if (lsq) {
237  sys->context = EIG_linear_least_squares_solver_new(0, totvert, 1);
238  }
239  else {
240  sys->context = EIG_linear_solver_new(0, totvert, 1);
241  }
242 
243  return sys;
244 }
245 
246 void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned)
247 {
248  sys->verts[sys->totvert] = co;
249  sys->vpinned[sys->totvert] = pinned;
250  sys->totvert++;
251 }
252 
253 void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3)
254 {
255  sys->faces[sys->totface][0] = v1;
256  sys->faces[sys->totface][1] = v2;
257  sys->faces[sys->totface][2] = v3;
258  sys->totface++;
259 }
260 
262 {
263  int(*face)[3];
264  int a, totvert = sys->totvert, totface = sys->totface;
265 
266  laplacian_begin_solve(sys, 0);
267 
268  sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea");
269 
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]);
275  }
276 
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]);
280  }
281  }
282 
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];
287  }
288  }
289  else {
290  sys->varea[a] = 1.0f;
291  }
292 
293  /* for heat weighting */
294  if (sys->heat.H) {
295  EIG_linear_solver_matrix_add(sys->context, a, a, sys->heat.H[a]);
296  }
297  }
298 
299  if (sys->storeweights) {
300  sys->fweights = MEM_callocN(sizeof(float[3]) * totface, "LaplacianFWeight");
301  }
302 
303  for (a = 0, face = sys->faces; a < totface; a++, face++) {
304  laplacian_triangle_weights(sys, a, (*face)[0], (*face)[1], (*face)[2]);
305  }
306 
307  MEM_freeN(sys->faces);
308  sys->faces = NULL;
309 
310  if (sys->varea) {
311  MEM_freeN(sys->varea);
312  sys->varea = NULL;
313  }
314 
316  sys->edgehash = NULL;
317 }
318 
320 {
321  if (sys->verts) {
322  MEM_freeN(sys->verts);
323  }
324  if (sys->varea) {
325  MEM_freeN(sys->varea);
326  }
327  if (sys->vpinned) {
328  MEM_freeN(sys->vpinned);
329  }
330  if (sys->faces) {
331  MEM_freeN(sys->faces);
332  }
333  if (sys->fweights) {
334  MEM_freeN(sys->fweights);
335  }
336 
338  MEM_freeN(sys);
339 }
340 
342 {
343  int a;
344 
345  if (!sys->variablesdone) {
346  if (index >= 0) {
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]);
351  }
352  }
353  }
354 
355  sys->variablesdone = true;
356  }
357 }
358 
359 void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
360 {
362 }
363 
365 {
366  sys->variablesdone = false;
367 
368  // EIG_linear_solver_print_matrix(sys->context, );
369 
370  return EIG_linear_solver_solve(sys->context);
371 }
372 
374 {
375  return EIG_linear_solver_variable_get(sys->context, 0, v);
376 }
377 
378 /************************* Heat Bone Weighting ******************************/
379 /* From "Automatic Rigging and Animation of 3D Characters"
380  * Ilya Baran and Jovan Popovic, SIGGRAPH 2007 */
381 
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
386 
387 typedef struct BVHCallbackUserData {
388  float start[3];
389  float vec[3];
392 
393 static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
394 {
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];
400  float dist_test;
401 
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];
405 
406 #ifdef USE_KDOPBVH_WATERTIGHT
408  data->start, ray->isect_precalc, UNPACK3(vtri_co), &dist_test, NULL))
409 #else
410  UNUSED_VARS(ray);
411  if (isect_ray_tri_v3(data->start, data->vec, UNPACK3(vtri_co), &dist_test, NULL))
412 #endif
413  {
414  if (dist_test < hit->dist) {
415  float n[3];
416  normal_tri_v3(n, UNPACK3(vtri_co));
417  if (dot_v3v3(n, data->vec) < -1e-5f) {
418  hit->index = index;
419  hit->dist = dist_test;
420  }
421  }
422  }
423 }
424 
425 /* Ray-tracing for vertex to bone/vertex visibility. */
427 {
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;
433  int a;
434 
435  sys->heat.bvhtree = BLI_bvhtree_new(tottri, 0.0f, 4, 6);
436  sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * totvert, "HeatVFaces");
437 
438  for (a = 0; a < tottri; a++) {
439  const MLoopTri *lt = &looptri[a];
440  float bb[6];
441  int vtri[3];
442 
443  vtri[0] = mloop[lt->tri[0]].v;
444  vtri[1] = mloop[lt->tri[1]].v;
445  vtri[2] = mloop[lt->tri[2]].v;
446 
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]]);
451 
452  BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2);
453 
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;
458  }
459 
461 }
462 
463 static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
464 {
465  BVHTreeRayHit hit;
467  const MLoopTri *lt;
468  float end[3];
469  int visible;
470 
471  lt = sys->heat.vltree[vertex];
472  if (lt == NULL) {
473  return 1;
474  }
475 
476  data.sys = sys;
477  copy_v3_v3(data.start, sys->heat.verts[vertex]);
478 
479  closest_to_line_segment_v3(end, data.start, sys->heat.root[source], sys->heat.tip[source]);
480 
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);
484 
485  /* pass normalized vec + distance to bvh */
486  hit.index = -1;
487  hit.dist = normalize_v3(data.vec);
488 
489  visible =
491  sys->heat.bvhtree, data.start, data.vec, 0.0f, &hit, bvh_callback, (void *)&data) == -1;
492 
493  return visible;
494 }
495 
496 static float heat_source_distance(LaplacianSystem *sys, int vertex, int source)
497 {
498  float closest[3], d[3], dist, cosine;
499 
500  /* compute Euclidean distance */
502  closest, sys->heat.verts[vertex], sys->heat.root[source], sys->heat.tip[source]);
503 
504  sub_v3_v3v3(d, sys->heat.verts[vertex], closest);
505  dist = normalize_v3(d);
506 
507  /* if the vertex normal does not point along the bone, increase distance */
508  cosine = dot_v3v3(d, sys->heat.vnors[vertex]);
509 
510  return dist / (0.5f * (cosine + 1.001f));
511 }
512 
513 static int heat_source_closest(LaplacianSystem *sys, int vertex, int source)
514 {
515  float dist;
516 
517  dist = heat_source_distance(sys, vertex, source);
518 
519  if (dist <= sys->heat.mindist[vertex] * (1.0f + DISTANCE_EPSILON)) {
520  if (heat_ray_source_visible(sys, vertex, source)) {
521  return 1;
522  }
523  }
524 
525  return 0;
526 }
527 
528 static void heat_set_H(LaplacianSystem *sys, int vertex)
529 {
530  float dist, mindist, h;
531  int j, numclosest = 0;
532 
533  mindist = 1e10;
534 
535  /* compute minimum distance */
536  for (j = 0; j < sys->heat.numsource; j++) {
537  dist = heat_source_distance(sys, vertex, j);
538 
539  if (dist < mindist) {
540  mindist = dist;
541  }
542  }
543 
544  sys->heat.mindist[vertex] = mindist;
545 
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)) {
549  numclosest++;
550  }
551  }
552 
553  sys->heat.p[vertex] = (numclosest > 0) ? 1.0f / numclosest : 0.0f;
554 
555  /* compute H entry */
556  if (numclosest > 0) {
557  mindist = max_ff(mindist, 1e-4f);
558  h = numclosest * C_WEIGHT / (mindist * mindist);
559  }
560  else {
561  h = 0.0f;
562  }
563 
564  sys->heat.H[vertex] = h;
565 }
566 
568 {
569  float fnor[3];
570  int a, v1, v2, v3, (*face)[3];
571 
572  sys->heat.vnors = MEM_callocN(sizeof(float[3]) * sys->totvert, "HeatVNors");
573 
574  for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
575  v1 = (*face)[0];
576  v2 = (*face)[1];
577  v3 = (*face)[2];
578 
579  normal_tri_v3(fnor, sys->verts[v1], sys->verts[v2], sys->verts[v3]);
580 
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);
584  }
585 
586  for (a = 0; a < sys->totvert; a++) {
588  }
589 }
590 
592 {
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;
597  int a;
598 
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");
603 
604  /* add verts and faces to laplacian */
605  for (a = 0; a < totvert; a++) {
607  }
608 
609  for (a = 0, lt = mlooptri; a < tottri; a++, lt++) {
610  int vtri[3];
611  vtri[0] = mloop[lt->tri[0]].v;
612  vtri[1] = mloop[lt->tri[1]].v;
613  vtri[2] = mloop[lt->tri[2]].v;
615  }
616 
617  /* for distance computation in set_H */
619 
620  for (a = 0; a < totvert; a++) {
621  heat_set_H(sys, a);
622  }
623 }
624 
626 {
628  MEM_freeN((void *)sys->heat.vltree);
629  MEM_freeN((void *)sys->heat.mlooptri);
630 
632  MEM_freeN(sys->heat.H);
633  MEM_freeN(sys->heat.p);
635 }
636 
637 static float heat_limit_weight(float weight)
638 {
639  float t;
640 
641  if (weight < WEIGHT_LIMIT_END) {
642  return 0.0f;
643  }
644  if (weight < WEIGHT_LIMIT_START) {
646  return t * WEIGHT_LIMIT_START;
647  }
648  return weight;
649 }
650 
652  Mesh *me,
653  float (*verts)[3],
654  int numbones,
655  bDeformGroup **dgrouplist,
656  bDeformGroup **dgroupflip,
657  float (*root)[3],
658  float (*tip)[3],
659  const int *selected,
660  const char **error_str)
661 {
663  MLoopTri *mlooptri;
664  MPoly *mp;
665  MLoop *ml;
666  float solution, weight;
667  int *vertsflipped = NULL, *mask = NULL;
668  int a, tottri, j, bbone, firstsegment, lastsegment;
669  bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
670 
671  MVert *mvert = me->mvert;
672  bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
673  bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
674 
675  *error_str = NULL;
676 
677  /* bone heat needs triangulated faces */
678  tottri = poly_to_tri_count(me->totpoly, me->totloop);
679 
680  /* count triangles and create mask */
681  if (ob->mode & OB_MODE_WEIGHT_PAINT && (use_face_sel || use_vert_sel)) {
682  mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask");
683 
684  /* (added selectedVerts content for vertex mask, they used to just equal 1) */
685  if (use_vert_sel) {
686  for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
687  for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
688  mask[ml->v] = (mvert[ml->v].flag & SELECT) != 0;
689  }
690  }
691  }
692  else if (use_face_sel) {
693  for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
694  if (mp->flag & ME_FACE_SEL) {
695  for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
696  mask[ml->v] = 1;
697  }
698  }
699  }
700  }
701  }
702 
703  /* create laplacian */
704  sys = laplacian_system_construct_begin(me->totvert, tottri, 1);
705 
707  mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__);
708 
709  BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri);
710 
711  sys->heat.mlooptri = mlooptri;
712  sys->heat.mloop = me->mloop;
713  sys->heat.totvert = me->totvert;
714  sys->heat.verts = verts;
715  sys->heat.root = root;
716  sys->heat.tip = tip;
717  sys->heat.numsource = numbones;
718 
721 
723 
724  if (dgroupflip) {
725  vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped");
726  for (a = 0; a < me->totvert; a++) {
727  vertsflipped[a] = mesh_get_x_mirror_vert(ob, NULL, a, use_topology);
728  }
729  }
730 
731  /* compute weights per bone */
732  for (j = 0; j < numbones; j++) {
733  if (!selected[j]) {
734  continue;
735  }
736 
737  firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]);
738  lastsegment = (j == numbones - 1 || dgrouplist[j] != dgrouplist[j + 1]);
739  bbone = !(firstsegment && lastsegment);
740 
741  /* clear weights */
742  if (bbone && firstsegment) {
743  for (a = 0; a < me->totvert; a++) {
744  if (mask && !mask[a]) {
745  continue;
746  }
747 
748  ED_vgroup_vert_remove(ob, dgrouplist[j], a);
749  if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
750  ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
751  }
752  }
753  }
754 
755  /* fill right hand side */
757 
758  for (a = 0; a < me->totvert; a++) {
759  if (heat_source_closest(sys, a, j)) {
761  }
762  }
763 
764  /* solve */
766  /* load solution into vertex groups */
767  for (a = 0; a < me->totvert; a++) {
768  if (mask && !mask[a]) {
769  continue;
770  }
771 
772  solution = laplacian_system_get_solution(sys, a);
773 
774  if (bbone) {
775  if (solution > 0.0f) {
776  ED_vgroup_vert_add(ob, dgrouplist[j], a, solution, WEIGHT_ADD);
777  }
778  }
779  else {
780  weight = heat_limit_weight(solution);
781  if (weight > 0.0f) {
782  ED_vgroup_vert_add(ob, dgrouplist[j], a, weight, WEIGHT_REPLACE);
783  }
784  else {
785  ED_vgroup_vert_remove(ob, dgrouplist[j], a);
786  }
787  }
788 
789  /* do same for mirror */
790  if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
791  if (bbone) {
792  if (solution > 0.0f) {
793  ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], solution, WEIGHT_ADD);
794  }
795  }
796  else {
797  weight = heat_limit_weight(solution);
798  if (weight > 0.0f) {
799  ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], weight, WEIGHT_REPLACE);
800  }
801  else {
802  ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
803  }
804  }
805  }
806  }
807  }
808  else if (*error_str == NULL) {
809  *error_str = N_("Bone Heat Weighting: failed to find solution for one or more bones");
810  break;
811  }
812 
813  /* remove too small vertex weights */
814  if (bbone && lastsegment) {
815  for (a = 0; a < me->totvert; a++) {
816  if (mask && !mask[a]) {
817  continue;
818  }
819 
820  weight = ED_vgroup_vert_weight(ob, dgrouplist[j], a);
821  weight = heat_limit_weight(weight);
822  if (weight <= 0.0f) {
823  ED_vgroup_vert_remove(ob, dgrouplist[j], a);
824  }
825 
826  if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
827  weight = ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
828  weight = heat_limit_weight(weight);
829  if (weight <= 0.0f) {
830  ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
831  }
832  }
833  }
834  }
835  }
836 
837  /* free */
838  if (vertsflipped) {
839  MEM_freeN(vertsflipped);
840  }
841  if (mask) {
842  MEM_freeN(mask);
843  }
844 
846 
848 }
849 
850 /************************** Harmonic Coordinates ****************************/
851 /* From "Harmonic Coordinates for Character Articulation",
852  * Pushkar Joshi, Mark Meyer, Tony DeRose, Brian Green and Tom Sanocki,
853  * SIGGRAPH 2007. */
854 
855 #define EPSILON 0.0001f
856 
857 #define MESHDEFORM_TAG_UNTYPED 0
858 #define MESHDEFORM_TAG_BOUNDARY 1
859 #define MESHDEFORM_TAG_INTERIOR 2
860 #define MESHDEFORM_TAG_EXTERIOR 3
861 
863 #define MESHDEFORM_LEN_THRESHOLD 1e-6f
864 
865 #define MESHDEFORM_MIN_INFLUENCE 0.0005f
866 
867 static const int MESHDEFORM_OFFSET[7][3] = {
868  {0, 0, 0},
869  {1, 0, 0},
870  {-1, 0, 0},
871  {0, 1, 0},
872  {0, -1, 0},
873  {0, 0, 1},
874  {0, 0, -1},
875 };
876 
877 typedef struct MDefBoundIsect {
878  /* intersection on the cage 'cagecos' */
879  float co[3];
880  /* non-facing intersections are considered interior */
881  bool facing;
882  /* ray-cast index aligned with MPoly (ray-hit-triangle isn't needed) */
884  /* distance from 'co' to the ray-cast start (clamped to avoid zero division) */
885  float len;
886  /* weights aligned with the MPoly's loop indices */
887  float poly_weights[0];
889 
890 typedef struct MDefBindInfluence {
892  float weight;
893  int vertex;
895 
896 typedef struct MeshDeformBind {
897  /* grid dimensions */
898  float min[3], max[3];
899  float width[3], halfwidth[3];
900  int size, size3;
901 
902  /* meshes */
904  float (*cagecos)[3];
907 
908  /* grids */
910  MDefBoundIsect *(*boundisect)[6];
911  int *semibound;
912  int *tag;
913  float *phi, *totalphi;
914 
915  /* mesh stuff */
916  int *inside;
917  float *weights;
919  float cagemat[4][4];
920 
921  /* direct solver */
922  int *varidx;
923 
926 
927  /* avoid DM function calls during intersections */
928  struct {
929  const MPoly *mpoly;
930  const MLoop *mloop;
932  const float (*poly_nors)[3];
935 
936 typedef struct MeshDeformIsect {
937  float start[3];
938  float vec[3];
939  float vec_length;
940  float lambda;
941 
942  bool isect;
943  float u, v;
944 
946 
947 /* ray intersection */
948 
952 };
953 
954 static void harmonic_ray_callback(void *userdata,
955  int index,
956  const BVHTreeRay *ray,
957  BVHTreeRayHit *hit)
958 {
959  struct MeshRayCallbackData *data = userdata;
960  MeshDeformBind *mdb = data->mdb;
961  const MLoop *mloop = mdb->cagemesh_cache.mloop;
962  const MLoopTri *looptri = mdb->cagemesh_cache.looptri, *lt;
963  const float(*poly_nors)[3] = mdb->cagemesh_cache.poly_nors;
964  MeshDeformIsect *isec = data->isec;
965  float no[3], co[3], dist;
966  float *face[3];
967 
968  lt = &looptri[index];
969 
970  face[0] = mdb->cagecos[mloop[lt->tri[0]].v];
971  face[1] = mdb->cagecos[mloop[lt->tri[1]].v];
972  face[2] = mdb->cagecos[mloop[lt->tri[2]].v];
973 
974  bool isect_ray_tri = isect_ray_tri_watertight_v3(
975  ray->origin, ray->isect_precalc, UNPACK3(face), &dist, NULL);
976 
977  if (!isect_ray_tri || dist > isec->vec_length) {
978  return;
979  }
980 
981  if (poly_nors) {
982  copy_v3_v3(no, poly_nors[lt->poly]);
983  }
984  else {
985  normal_tri_v3(no, UNPACK3(face));
986  }
987 
988  madd_v3_v3v3fl(co, ray->origin, ray->direction, dist);
989  dist /= isec->vec_length;
990  if (dist < hit->dist) {
991  hit->index = index;
992  hit->dist = dist;
993  copy_v3_v3(hit->co, co);
994 
995  isec->isect = (dot_v3v3(no, ray->direction) <= 0.0f);
996  isec->lambda = dist;
997  }
998 }
999 
1001  const float co1[3],
1002  const float co2[3])
1003 {
1004  BVHTreeRayHit hit;
1005  MeshDeformIsect isect_mdef;
1006  struct MeshRayCallbackData data = {
1007  mdb,
1008  &isect_mdef,
1009  };
1010  float end[3], vec_normal[3];
1011 
1012  /* happens binding when a cage has no faces */
1013  if (UNLIKELY(mdb->bvhtree == NULL)) {
1014  return NULL;
1015  }
1016 
1017  /* setup isec */
1018  memset(&isect_mdef, 0, sizeof(isect_mdef));
1019  isect_mdef.lambda = 1e10f;
1020 
1021  copy_v3_v3(isect_mdef.start, co1);
1022  copy_v3_v3(end, co2);
1023  sub_v3_v3v3(isect_mdef.vec, end, isect_mdef.start);
1024  isect_mdef.vec_length = normalize_v3_v3(vec_normal, isect_mdef.vec);
1025 
1026  hit.index = -1;
1027  hit.dist = BVH_RAYCAST_DIST_MAX;
1029  isect_mdef.start,
1030  vec_normal,
1031  0.0,
1032  &hit,
1034  &data,
1035  BVH_RAYCAST_WATERTIGHT) != -1) {
1036  const MLoop *mloop = mdb->cagemesh_cache.mloop;
1037  const MLoopTri *lt = &mdb->cagemesh_cache.looptri[hit.index];
1038  const MPoly *mp = &mdb->cagemesh_cache.mpoly[lt->poly];
1039  const float(*cagecos)[3] = mdb->cagecos;
1040  const float len = isect_mdef.lambda;
1041  MDefBoundIsect *isect;
1042 
1043  float(*mp_cagecos)[3] = BLI_array_alloca(mp_cagecos, mp->totloop);
1044 
1045  /* create MDefBoundIsect, and extra for 'poly_weights[]' */
1046  isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect) + (sizeof(float) * mp->totloop));
1047 
1048  /* compute intersection coordinate */
1049  madd_v3_v3v3fl(isect->co, co1, isect_mdef.vec, len);
1050 
1051  isect->facing = isect_mdef.isect;
1052 
1053  isect->poly_index = lt->poly;
1054 
1055  isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD);
1056 
1057  /* compute mean value coordinates for interpolation */
1058  for (int i = 0; i < mp->totloop; i++) {
1059  copy_v3_v3(mp_cagecos[i], cagecos[mloop[mp->loopstart + i].v]);
1060  }
1061 
1062  interp_weights_poly_v3(isect->poly_weights, mp_cagecos, mp->totloop, isect->co);
1063 
1064  return isect;
1065  }
1066 
1067  return NULL;
1068 }
1069 
1071 {
1072  MDefBoundIsect *isect;
1073  float outside[3], start[3], dir[3];
1074  int i;
1075 
1076  for (i = 1; i <= 6; i++) {
1077  outside[0] = co[0] + (mdb->max[0] - mdb->min[0] + 1.0f) * MESHDEFORM_OFFSET[i][0];
1078  outside[1] = co[1] + (mdb->max[1] - mdb->min[1] + 1.0f) * MESHDEFORM_OFFSET[i][1];
1079  outside[2] = co[2] + (mdb->max[2] - mdb->min[2] + 1.0f) * MESHDEFORM_OFFSET[i][2];
1080 
1081  copy_v3_v3(start, co);
1082  sub_v3_v3v3(dir, outside, start);
1083  normalize_v3(dir);
1084 
1085  isect = meshdeform_ray_tree_intersect(mdb, start, outside);
1086  if (isect && !isect->facing) {
1087  return 1;
1088  }
1089  }
1090 
1091  return 0;
1092 }
1093 
1094 /* solving */
1095 
1096 BLI_INLINE int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
1097 {
1098  int size = mdb->size;
1099 
1100  x += MESHDEFORM_OFFSET[n][0];
1101  y += MESHDEFORM_OFFSET[n][1];
1102  z += MESHDEFORM_OFFSET[n][2];
1103 
1104  if (x < 0 || x >= mdb->size) {
1105  return -1;
1106  }
1107  if (y < 0 || y >= mdb->size) {
1108  return -1;
1109  }
1110  if (z < 0 || z >= mdb->size) {
1111  return -1;
1112  }
1113 
1114  return x + y * size + z * size * size;
1115 }
1116 
1118  MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
1119 {
1120  x += MESHDEFORM_OFFSET[n][0];
1121  y += MESHDEFORM_OFFSET[n][1];
1122  z += MESHDEFORM_OFFSET[n][2];
1123 
1124  center[0] = mdb->min[0] + x * mdb->width[0] + mdb->halfwidth[0];
1125  center[1] = mdb->min[1] + y * mdb->width[1] + mdb->halfwidth[1];
1126  center[2] = mdb->min[2] + z * mdb->width[2] + mdb->halfwidth[2];
1127 }
1128 
1129 static void meshdeform_add_intersections(MeshDeformBind *mdb, int x, int y, int z)
1130 {
1131  MDefBoundIsect *isect;
1132  float center[3], ncenter[3];
1133  int i, a;
1134 
1135  a = meshdeform_index(mdb, x, y, z, 0);
1137 
1138  /* check each outgoing edge for intersection */
1139  for (i = 1; i <= 6; i++) {
1140  if (meshdeform_index(mdb, x, y, z, i) == -1) {
1141  continue;
1142  }
1143 
1144  meshdeform_cell_center(mdb, x, y, z, i, ncenter);
1145 
1146  isect = meshdeform_ray_tree_intersect(mdb, center, ncenter);
1147  if (isect) {
1148  mdb->boundisect[a][i - 1] = isect;
1150  }
1151  }
1152 }
1153 
1155 {
1156  int *stack, *tag = mdb->tag;
1157  int a, b, i, xyz[3], stacksize, size = mdb->size;
1158 
1159  stack = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformBindStack");
1160 
1161  /* we know lower left corner is EXTERIOR because of padding */
1162  tag[0] = MESHDEFORM_TAG_EXTERIOR;
1163  stack[0] = 0;
1164  stacksize = 1;
1165 
1166  /* floodfill exterior tag */
1167  while (stacksize > 0) {
1168  a = stack[--stacksize];
1169 
1170  xyz[2] = a / (size * size);
1171  xyz[1] = (a - xyz[2] * size * size) / size;
1172  xyz[0] = a - xyz[1] * size - xyz[2] * size * size;
1173 
1174  for (i = 1; i <= 6; i++) {
1175  b = meshdeform_index(mdb, xyz[0], xyz[1], xyz[2], i);
1176 
1177  if (b != -1) {
1178  if (tag[b] == MESHDEFORM_TAG_UNTYPED ||
1179  (tag[b] == MESHDEFORM_TAG_BOUNDARY && !mdb->boundisect[a][i - 1])) {
1180  tag[b] = MESHDEFORM_TAG_EXTERIOR;
1181  stack[stacksize++] = b;
1182  }
1183  }
1184  }
1185  }
1186 
1187  /* other cells are interior */
1188  for (a = 0; a < size * size * size; a++) {
1189  if (tag[a] == MESHDEFORM_TAG_UNTYPED) {
1190  tag[a] = MESHDEFORM_TAG_INTERIOR;
1191  }
1192  }
1193 
1194 #if 0
1195  {
1196  int tb, ti, te, ts;
1197  tb = ti = te = ts = 0;
1198  for (a = 0; a < size * size * size; a++) {
1199  if (tag[a] == MESHDEFORM_TAG_BOUNDARY) {
1200  tb++;
1201  }
1202  else if (tag[a] == MESHDEFORM_TAG_INTERIOR) {
1203  ti++;
1204  }
1205  else if (tag[a] == MESHDEFORM_TAG_EXTERIOR) {
1206  te++;
1207 
1208  if (mdb->semibound[a]) {
1209  ts++;
1210  }
1211  }
1212  }
1213 
1214  printf("interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
1215  }
1216 #endif
1217 
1218  MEM_freeN(stack);
1219 }
1220 
1222  const MDefBoundIsect *isect,
1223  int cagevert)
1224 {
1225  const MLoop *mloop = mdb->cagemesh_cache.mloop;
1226  const MPoly *mp = &mdb->cagemesh_cache.mpoly[isect->poly_index];
1227 
1228  for (int i = 0; i < mp->totloop; i++) {
1229  if (mloop[mp->loopstart + i].v == cagevert) {
1230  return isect->poly_weights[i];
1231  }
1232  }
1233 
1234  return 0.0f;
1235 }
1236 
1238  const float *gridvec,
1239  float *UNUSED(vec),
1240  int UNUSED(cagevert))
1241 {
1242  float dvec[3], ivec[3], result = 0.0f;
1243  float totweight = 0.0f;
1244 
1245  for (int i = 0; i < 3; i++) {
1246  ivec[i] = (int)gridvec[i];
1247  dvec[i] = gridvec[i] - ivec[i];
1248  }
1249 
1250  for (int i = 0; i < 8; i++) {
1251  int x, y, z;
1252  float wx, wy, wz;
1253 
1254  if (i & 1) {
1255  x = ivec[0] + 1;
1256  wx = dvec[0];
1257  }
1258  else {
1259  x = ivec[0];
1260  wx = 1.0f - dvec[0];
1261  }
1262 
1263  if (i & 2) {
1264  y = ivec[1] + 1;
1265  wy = dvec[1];
1266  }
1267  else {
1268  y = ivec[1];
1269  wy = 1.0f - dvec[1];
1270  }
1271 
1272  if (i & 4) {
1273  z = ivec[2] + 1;
1274  wz = dvec[2];
1275  }
1276  else {
1277  z = ivec[2];
1278  wz = 1.0f - dvec[2];
1279  }
1280 
1281  CLAMP(x, 0, mdb->size - 1);
1282  CLAMP(y, 0, mdb->size - 1);
1283  CLAMP(z, 0, mdb->size - 1);
1284 
1285  int a = meshdeform_index(mdb, x, y, z, 0);
1286  float weight = wx * wy * wz;
1287  result += weight * mdb->phi[a];
1288  totweight += weight;
1289  }
1290 
1291  if (totweight > 0.0f) {
1292  result /= totweight;
1293  }
1294 
1295  return result;
1296 }
1297 
1298 static void meshdeform_check_semibound(MeshDeformBind *mdb, int x, int y, int z)
1299 {
1300  int i, a;
1301 
1302  a = meshdeform_index(mdb, x, y, z, 0);
1303  if (mdb->tag[a] != MESHDEFORM_TAG_EXTERIOR) {
1304  return;
1305  }
1306 
1307  for (i = 1; i <= 6; i++) {
1308  if (mdb->boundisect[a][i - 1]) {
1309  mdb->semibound[a] = 1;
1310  }
1311  }
1312 }
1313 
1315 {
1316  float weight, totweight = 0.0f;
1317  int i, a;
1318 
1319  a = meshdeform_index(mdb, x, y, z, 0);
1320 
1321  /* count weight for neighbor cells */
1322  for (i = 1; i <= 6; i++) {
1323  if (meshdeform_index(mdb, x, y, z, i) == -1) {
1324  continue;
1325  }
1326 
1327  if (mdb->boundisect[a][i - 1]) {
1328  weight = 1.0f / mdb->boundisect[a][i - 1]->len;
1329  }
1330  else if (!mdb->semibound[a]) {
1331  weight = 1.0f / mdb->width[0];
1332  }
1333  else {
1334  weight = 0.0f;
1335  }
1336 
1337  totweight += weight;
1338  }
1339 
1340  return totweight;
1341 }
1342 
1344  MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z)
1345 {
1346  MDefBoundIsect *isect;
1347  float weight, totweight;
1348  int i, a, acenter;
1349 
1350  acenter = meshdeform_index(mdb, x, y, z, 0);
1351  if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR) {
1352  return;
1353  }
1354 
1355  EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
1356 
1357  totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
1358  for (i = 1; i <= 6; i++) {
1359  a = meshdeform_index(mdb, x, y, z, i);
1360  if (a == -1 || mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR) {
1361  continue;
1362  }
1363 
1364  isect = mdb->boundisect[acenter][i - 1];
1365  if (!isect) {
1366  weight = (1.0f / mdb->width[0]) / totweight;
1367  EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[a], -weight);
1368  }
1369  }
1370 }
1371 
1373  MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z, int cagevert)
1374 {
1375  MDefBoundIsect *isect;
1376  float rhs, weight, totweight;
1377  int i, a, acenter;
1378 
1379  acenter = meshdeform_index(mdb, x, y, z, 0);
1380  if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR) {
1381  return;
1382  }
1383 
1384  totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
1385  for (i = 1; i <= 6; i++) {
1386  a = meshdeform_index(mdb, x, y, z, i);
1387  if (a == -1) {
1388  continue;
1389  }
1390 
1391  isect = mdb->boundisect[acenter][i - 1];
1392 
1393  if (isect) {
1394  weight = (1.0f / isect->len) / totweight;
1395  rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
1397  }
1398  }
1399 }
1400 
1402  MeshDeformBind *mdb, int x, int y, int z, int cagevert)
1403 {
1404  MDefBoundIsect *isect;
1405  float rhs, weight, totweight;
1406  int i, a;
1407 
1408  a = meshdeform_index(mdb, x, y, z, 0);
1409  if (!mdb->semibound[a]) {
1410  return;
1411  }
1412 
1413  mdb->phi[a] = 0.0f;
1414 
1415  totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
1416  for (i = 1; i <= 6; i++) {
1417  isect = mdb->boundisect[a][i - 1];
1418 
1419  if (isect) {
1420  weight = (1.0f / isect->len) / totweight;
1421  rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
1422  mdb->phi[a] += rhs;
1423  }
1424  }
1425 }
1426 
1428  MeshDeformBind *mdb, int x, int y, int z, int UNUSED(cagevert))
1429 {
1430  float phi, totweight;
1431  int i, a, acenter;
1432 
1433  acenter = meshdeform_index(mdb, x, y, z, 0);
1434  if (mdb->tag[acenter] != MESHDEFORM_TAG_EXTERIOR || mdb->semibound[acenter]) {
1435  return;
1436  }
1437 
1438  phi = 0.0f;
1439  totweight = 0.0f;
1440  for (i = 1; i <= 6; i++) {
1441  a = meshdeform_index(mdb, x, y, z, i);
1442 
1443  if (a != -1 && mdb->semibound[a]) {
1444  phi += mdb->phi[a];
1445  totweight += 1.0f;
1446  }
1447  }
1448 
1449  if (totweight != 0.0f) {
1450  mdb->phi[acenter] = phi / totweight;
1451  }
1452 }
1453 
1455 {
1457  float vec[3], gridvec[3];
1458  int a, b, x, y, z, totvar;
1459  char message[256];
1460 
1461  /* setup variable indices */
1462  mdb->varidx = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformDSvaridx");
1463  for (a = 0, totvar = 0; a < mdb->size3; a++) {
1464  mdb->varidx[a] = (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR) ? -1 : totvar++;
1465  }
1466 
1467  if (totvar == 0) {
1468  MEM_freeN(mdb->varidx);
1469  return;
1470  }
1471 
1472  progress_bar(0, "Starting mesh deform solve");
1473 
1474  /* setup linear solver */
1475  context = EIG_linear_solver_new(totvar, totvar, 1);
1476 
1477  /* build matrix */
1478  for (z = 0; z < mdb->size; z++) {
1479  for (y = 0; y < mdb->size; y++) {
1480  for (x = 0; x < mdb->size; x++) {
1482  }
1483  }
1484  }
1485 
1486  /* solve for each cage vert */
1487  for (a = 0; a < mdb->totcagevert; a++) {
1488  /* fill in right hand side and solve */
1489  for (z = 0; z < mdb->size; z++) {
1490  for (y = 0; y < mdb->size; y++) {
1491  for (x = 0; x < mdb->size; x++) {
1493  }
1494  }
1495  }
1496 
1498  for (z = 0; z < mdb->size; z++) {
1499  for (y = 0; y < mdb->size; y++) {
1500  for (x = 0; x < mdb->size; x++) {
1502  }
1503  }
1504  }
1505 
1506  for (z = 0; z < mdb->size; z++) {
1507  for (y = 0; y < mdb->size; y++) {
1508  for (x = 0; x < mdb->size; x++) {
1510  }
1511  }
1512  }
1513 
1514  for (b = 0; b < mdb->size3; b++) {
1515  if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR) {
1517  }
1518  mdb->totalphi[b] += mdb->phi[b];
1519  }
1520 
1521  if (mdb->weights) {
1522  /* static bind : compute weights for each vertex */
1523  for (b = 0; b < mdb->totvert; b++) {
1524  if (mdb->inside[b]) {
1525  copy_v3_v3(vec, mdb->vertexcos[b]);
1526  gridvec[0] = (vec[0] - mdb->min[0] - mdb->halfwidth[0]) / mdb->width[0];
1527  gridvec[1] = (vec[1] - mdb->min[1] - mdb->halfwidth[1]) / mdb->width[1];
1528  gridvec[2] = (vec[2] - mdb->min[2] - mdb->halfwidth[2]) / mdb->width[2];
1529 
1530  mdb->weights[b * mdb->totcagevert + a] = meshdeform_interp_w(mdb, gridvec, vec, a);
1531  }
1532  }
1533  }
1534  else {
1535  MDefBindInfluence *inf;
1536 
1537  /* dynamic bind */
1538  for (b = 0; b < mdb->size3; b++) {
1539  if (mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) {
1540  inf = BLI_memarena_alloc(mdb->memarena, sizeof(*inf));
1541  inf->vertex = a;
1542  inf->weight = mdb->phi[b];
1543  inf->next = mdb->dyngrid[b];
1544  mdb->dyngrid[b] = inf;
1545  }
1546  }
1547  }
1548  }
1549  else {
1551  mmd->object, &mmd->modifier, "Failed to find bind solution (increase precision?)");
1552  error("Mesh Deform: failed to find bind solution.");
1553  break;
1554  }
1555 
1556  BLI_snprintf(
1557  message, sizeof(message), "Mesh deform solve %d / %d |||", a + 1, mdb->totcagevert);
1558  progress_bar((float)(a + 1) / (float)(mdb->totcagevert), message);
1559  }
1560 
1561 #if 0
1562  /* sanity check */
1563  for (b = 0; b < mdb->size3; b++) {
1564  if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR) {
1565  if (fabsf(mdb->totalphi[b] - 1.0f) > 1e-4f) {
1566  printf("totalphi deficiency [%s|%d] %d: %.10f\n",
1567  (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR) ? "interior" : "boundary",
1568  mdb->semibound[b],
1569  mdb->varidx[b],
1570  mdb->totalphi[b]);
1571  }
1572  }
1573  }
1574 #endif
1575 
1576  /* free */
1577  MEM_freeN(mdb->varidx);
1578 
1580 }
1581 
1583 {
1584  MDefBindInfluence *inf;
1585  MDefInfluence *mdinf;
1586  MDefCell *cell;
1587  float center[3], vec[3], maxwidth, totweight;
1588  int a, b, x, y, z, totinside, offset;
1589 
1590  /* compute bounding box of the cage mesh */
1591  INIT_MINMAX(mdb->min, mdb->max);
1592 
1593  for (a = 0; a < mdb->totcagevert; a++) {
1595  }
1596 
1597  /* allocate memory */
1598  mdb->size = (2 << (mmd->gridsize - 1)) + 2;
1599  mdb->size3 = mdb->size * mdb->size * mdb->size;
1600  mdb->tag = MEM_callocN(sizeof(int) * mdb->size3, "MeshDeformBindTag");
1601  mdb->phi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindPhi");
1602  mdb->totalphi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindTotalPhi");
1603  mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect");
1604  mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound");
1606  mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside");
1607 
1608  if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
1609  mdb->dyngrid = MEM_callocN(sizeof(MDefBindInfluence *) * mdb->size3, "MDefDynGrid");
1610  }
1611  else {
1612  mdb->weights = MEM_callocN(sizeof(float) * mdb->totvert * mdb->totcagevert, "MDefWeights");
1613  }
1614 
1615  mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
1617 
1618  /* initialize data from 'cagedm' for reuse */
1619  {
1620  Mesh *me = mdb->cagemesh;
1621  mdb->cagemesh_cache.mpoly = me->mpoly;
1622  mdb->cagemesh_cache.mloop = me->mloop;
1624  /* can be NULL */
1626  }
1627 
1628  /* make bounding box equal size in all directions, add padding, and compute
1629  * width of the cells */
1630  maxwidth = -1.0f;
1631  for (a = 0; a < 3; a++) {
1632  if (mdb->max[a] - mdb->min[a] > maxwidth) {
1633  maxwidth = mdb->max[a] - mdb->min[a];
1634  }
1635  }
1636 
1637  for (a = 0; a < 3; a++) {
1638  center[a] = (mdb->min[a] + mdb->max[a]) * 0.5f;
1639  mdb->min[a] = center[a] - maxwidth * 0.5f;
1640  mdb->max[a] = center[a] + maxwidth * 0.5f;
1641 
1642  mdb->width[a] = (mdb->max[a] - mdb->min[a]) / (mdb->size - 4);
1643  mdb->min[a] -= 2.1f * mdb->width[a];
1644  mdb->max[a] += 2.1f * mdb->width[a];
1645 
1646  mdb->width[a] = (mdb->max[a] - mdb->min[a]) / mdb->size;
1647  mdb->halfwidth[a] = mdb->width[a] * 0.5f;
1648  }
1649 
1650  progress_bar(0, "Setting up mesh deform system");
1651 
1652  totinside = 0;
1653  for (a = 0; a < mdb->totvert; a++) {
1654  copy_v3_v3(vec, mdb->vertexcos[a]);
1656  if (mdb->inside[a]) {
1657  totinside++;
1658  }
1659  }
1660 
1661  /* free temporary MDefBoundIsects */
1663  mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
1664 
1665  /* start with all cells untyped */
1666  for (a = 0; a < mdb->size3; a++) {
1668  }
1669 
1670  /* detect intersections and tag boundary cells */
1671  for (z = 0; z < mdb->size; z++) {
1672  for (y = 0; y < mdb->size; y++) {
1673  for (x = 0; x < mdb->size; x++) {
1675  }
1676  }
1677  }
1678 
1679  /* compute exterior and interior tags */
1681 
1682  for (z = 0; z < mdb->size; z++) {
1683  for (y = 0; y < mdb->size; y++) {
1684  for (x = 0; x < mdb->size; x++) {
1686  }
1687  }
1688  }
1689 
1690  /* solve */
1692 
1693  /* assign results */
1694  if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
1695  mmd->totinfluence = 0;
1696  for (a = 0; a < mdb->size3; a++) {
1697  for (inf = mdb->dyngrid[a]; inf; inf = inf->next) {
1698  mmd->totinfluence++;
1699  }
1700  }
1701 
1702  /* convert MDefBindInfluences to smaller MDefInfluences */
1703  mmd->dyngrid = MEM_callocN(sizeof(MDefCell) * mdb->size3, "MDefDynGrid");
1704  mmd->dyninfluences = MEM_callocN(sizeof(MDefInfluence) * mmd->totinfluence, "MDefInfluence");
1705  offset = 0;
1706  for (a = 0; a < mdb->size3; a++) {
1707  cell = &mmd->dyngrid[a];
1708  cell->offset = offset;
1709 
1710  totweight = 0.0f;
1711  mdinf = mmd->dyninfluences + cell->offset;
1712  for (inf = mdb->dyngrid[a]; inf; inf = inf->next, mdinf++) {
1713  mdinf->weight = inf->weight;
1714  mdinf->vertex = inf->vertex;
1715  totweight += mdinf->weight;
1716  cell->totinfluence++;
1717  }
1718 
1719  if (totweight > 0.0f) {
1720  mdinf = mmd->dyninfluences + cell->offset;
1721  for (b = 0; b < cell->totinfluence; b++, mdinf++) {
1722  mdinf->weight /= totweight;
1723  }
1724  }
1725 
1726  offset += cell->totinfluence;
1727  }
1728 
1729  mmd->dynverts = mdb->inside;
1730  mmd->dyngridsize = mdb->size;
1731  copy_v3_v3(mmd->dyncellmin, mdb->min);
1732  mmd->dyncellwidth = mdb->width[0];
1733  MEM_freeN(mdb->dyngrid);
1734  }
1735  else {
1736  mmd->bindweights = mdb->weights;
1737  MEM_freeN(mdb->inside);
1738  }
1739 
1740  MEM_freeN(mdb->tag);
1741  MEM_freeN(mdb->phi);
1747 }
1748 
1750  Mesh *cagemesh,
1751  float *vertexcos,
1752  int totvert,
1753  float cagemat[4][4])
1754 {
1756  &mmd->modifier);
1758  MVert *mvert;
1759  int a;
1760 
1761  waitcursor(1);
1763 
1764  memset(&mdb, 0, sizeof(MeshDeformBind));
1765 
1766  /* No need to support other kinds of mesh data as binding is a one-off action. */
1768 
1769  /* get mesh and cage mesh */
1770  mdb.vertexcos = MEM_callocN(sizeof(float[3]) * totvert, "MeshDeformCos");
1771  mdb.totvert = totvert;
1772 
1773  mdb.cagemesh = cagemesh;
1775  mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos");
1776  copy_m4_m4(mdb.cagemat, cagemat);
1777 
1778  mvert = mdb.cagemesh->mvert;
1779  for (a = 0; a < mdb.totcagevert; a++) {
1780  copy_v3_v3(mdb.cagecos[a], mvert[a].co);
1781  }
1782  for (a = 0; a < mdb.totvert; a++) {
1783  mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3);
1784  }
1785 
1786  /* solve */
1787  harmonic_coordinates_bind(mmd_orig, &mdb);
1788 
1789  /* assign bind variables */
1790  mmd_orig->bindcagecos = (float *)mdb.cagecos;
1791  mmd_orig->totvert = mdb.totvert;
1792  mmd_orig->totcagevert = mdb.totcagevert;
1793  copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat);
1794 
1795  /* transform bindcagecos to world space */
1796  for (a = 0; a < mdb.totcagevert; a++) {
1797  mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3);
1798  }
1799 
1800  /* free */
1802 
1803  /* compact weights */
1805 
1806  end_progress_bar();
1807  waitcursor(0);
1808 }
typedef float(TangentPoint)[2]
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, struct Mesh *mesh, const BVHCacheType bvh_cache_type, const int tree_type)
Definition: bvhutils.c:1413
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.c:1701
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:93
void * CustomData_get_layer(const struct CustomData *data, int type)
void BKE_mesh_recalc_looptri(const struct MLoop *mloop, const struct MPoly *mpoly, const struct MVert *mvert, int totloop, int totpoly, struct MLoopTri *mlooptri)
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(struct Mesh *mesh)
Definition: mesh_runtime.c:155
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.c:98
void BKE_modifier_mdef_compact_influences(struct ModifierData *md)
struct ModifierData * BKE_modifier_get_original(struct ModifierData *md)
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_INLINE
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value)
Definition: edgehash.c:244
EdgeHash * BLI_edgehash_new_ex(const char *info, const unsigned int nentries_reserve)
Definition: edgehash.c:226
bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:355
#define BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly)
Definition: BLI_edgehash.h:115
void * BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:325
#define BVH_RAYCAST_DIST_MAX
Definition: BLI_kdopbvh.h:105
void BLI_bvhtree_balance(BVHTree *tree)
Definition: BLI_kdopbvh.c:956
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
Definition: BLI_kdopbvh.c:873
int BLI_bvhtree_ray_cast_ex(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata, int flag)
Definition: BLI_kdopbvh.c:1939
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:945
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
Definition: BLI_kdopbvh.c:998
@ BVH_RAYCAST_WATERTIGHT
Definition: BLI_kdopbvh.h:102
int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1984
MINLINE float max_ff(float a, float b)
MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
bool isect_ray_tri_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
Definition: math_geom.c:1751
void interp_weights_poly_v3(float w[], float v[][3], const int n, const float co[3])
bool isect_ray_tri_watertight_v3(const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, const float v0[3], const float v1[3], const float v2[3], float *r_dist, float r_uv[2])
Definition: math_geom.c:1906
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:116
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:220
void closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:375
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:51
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
#define DEG2RADF(_deg)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:417
MINLINE void add_v3_v3(float r[3], const float a[3])
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:36
void BLI_memarena_use_calloc(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:91
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define INIT_MINMAX(min, max)
#define UNUSED_VARS(...)
#define UNUSED(x)
#define UNPACK3(a)
#define UNLIKELY(x)
#define N_(msgid)
@ ME_EDIT_PAINT_VERT_SEL
@ ME_EDIT_PAINT_FACE_SEL
@ ME_EDIT_MIRROR_TOPO
@ ME_FACE_SEL
@ MOD_MDEF_DYNAMIC_BIND
@ OB_MODE_WEIGHT_PAINT
Object is a sort of wrapper for general info.
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode)
int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, const bool use_topology)
Definition: meshtools.c:932
#define WEIGHT_REPLACE
Definition: ED_mesh.h:345
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum)
#define WEIGHT_ADD
Definition: ED_mesh.h:346
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum)
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint i1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
bool closest(btVector3 &v)
#define SELECT
#define str(s)
static float verts[][3]
#define fabsf(x)
void EIG_linear_solver_variable_set(LinearSolver *solver, int rhs, int index, double value)
LinearSolver * EIG_linear_solver_new(int num_rows, int num_columns, int num_rhs)
void EIG_linear_solver_right_hand_side_add(LinearSolver *solver, int rhs, int index, double value)
LinearSolver * EIG_linear_least_squares_solver_new(int num_rows, int num_columns, int num_rhs)
void EIG_linear_solver_delete(LinearSolver *solver)
double EIG_linear_solver_variable_get(LinearSolver *solver, int rhs, int index)
void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value)
bool EIG_linear_solver_solve(LinearSolver *solver)
void EIG_linear_solver_variable_lock(LinearSolver *solver, int index)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
struct MeshDeformIsect MeshDeformIsect
static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
static float meshdeform_boundary_phi(const MeshDeformBind *mdb, const MDefBoundIsect *isect, int cagevert)
static void laplacian_system_delete(LaplacianSystem *sys)
static float meshdeform_interp_w(MeshDeformBind *mdb, const float *gridvec, float *UNUSED(vec), int UNUSED(cagevert))
BLI_INLINE void meshdeform_cell_center(MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3)
float laplacian_system_get_solution(LaplacianSystem *sys, int v)
static void laplacian_system_construct_end(LaplacianSystem *sys)
static void waitcursor(int UNUSED(val))
Definition: meshlaplacian.c:53
static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
static void heat_set_H(LaplacianSystem *sys, int vertex)
void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
struct BVHCallbackUserData BVHCallbackUserData
static float heat_limit_weight(float weight)
int laplacian_system_solve(LaplacianSystem *sys)
static void heat_ray_tree_create(LaplacianSystem *sys)
static void meshdeform_matrix_add_semibound_phi(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2)
#define WEIGHT_LIMIT_END
#define WEIGHT_LIMIT_START
static float heat_source_distance(LaplacianSystem *sys, int vertex, int source)
static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z)
#define MESHDEFORM_MIN_INFLUENCE
static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
static void meshdeform_add_intersections(MeshDeformBind *mdb, int x, int y, int z)
static void start_progress_bar(void)
Definition: meshlaplacian.c:59
static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3)
static void error(const char *str)
Definition: meshlaplacian.c:65
static int heat_source_closest(LaplacianSystem *sys, int vertex, int source)
BLI_INLINE int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
static void meshdeform_matrix_add_exterior_phi(MeshDeformBind *mdb, int x, int y, int z, int UNUSED(cagevert))
static void progress_bar(int UNUSED(dummy_val), const char *UNUSED(dummy))
Definition: meshlaplacian.c:56
struct MDefBoundIsect MDefBoundIsect
static float meshdeform_boundary_total_weight(MeshDeformBind *mdb, int x, int y, int z)
struct MDefBindInfluence MDefBindInfluence
static void heat_calc_vnormals(LaplacianSystem *sys)
static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static void heat_laplacian_create(LaplacianSystem *sys)
void heat_bone_weighting(Object *ob, Mesh *me, float(*verts)[3], int numbones, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float(*root)[3], float(*tip)[3], const int *selected, const char **error_str)
static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
static const int MESHDEFORM_OFFSET[7][3]
#define MESHDEFORM_TAG_UNTYPED
static LaplacianSystem * laplacian_system_construct_begin(int totvert, int totface, int lsq)
#define MESHDEFORM_TAG_BOUNDARY
static void end_progress_bar(void)
Definition: meshlaplacian.c:62
static void meshdeform_check_semibound(MeshDeformBind *mdb, int x, int y, int z)
#define MESHDEFORM_TAG_INTERIOR
void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd, Mesh *cagemesh, float *vertexcos, int totvert, float cagemat[4][4])
static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3)
#define MESHDEFORM_LEN_THRESHOLD
static void heat_system_free(LaplacianSystem *sys)
#define C_WEIGHT
static MDefBoundIsect * meshdeform_ray_tree_intersect(MeshDeformBind *mdb, const float co1[3], const float co2[3])
static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z, int cagevert)
void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned)
#define DISTANCE_EPSILON
#define MESHDEFORM_TAG_EXTERIOR
struct MeshDeformBind MeshDeformBind
void laplacian_begin_solve(LaplacianSystem *sys, int index)
static unsigned a[3]
Definition: RandGen.cpp:92
static void area(int d1, int d2, int e1, int e2, float weights[2])
struct SELECTID_Context context
Definition: select_engine.c:47
_W64 int intptr_t
Definition: stdint.h:121
LaplacianSystem * sys
float co[3]
Definition: BLI_kdopbvh.h:84
float origin[3]
Definition: BLI_kdopbvh.h:70
struct IsectRayPrecalc * isect_precalc
Definition: BLI_kdopbvh.h:76
float direction[3]
Definition: BLI_kdopbvh.h:72
float(* fweights)[3]
Definition: meshlaplacian.c:82
EdgeHash * edgehash
Definition: meshlaplacian.c:88
int(* faces)[3]
Definition: meshlaplacian.c:81
LinearSolver * context
Definition: meshlaplacian.c:74
struct LaplacianSystem::HeatWeighting heat
struct MDefBindInfluence * next
float poly_weights[0]
unsigned int poly
unsigned int tri[3]
unsigned int v
float co[3]
float cagemat[4][4]
const MPoly * mpoly
const MLoopTri * looptri
const float(* poly_nors)[3]
float(* vertexcos)[3]
MemArena * memarena
struct MeshDeformBind::@303 cagemesh_cache
const MLoop * mloop
float halfwidth[3]
MDefBoundIsect *(* boundisect)[6]
BVHTreeFromMesh bvhdata
float(* cagecos)[3]
MDefBindInfluence ** dyngrid
BVHTree * bvhtree
MDefInfluence * dyninfluences
MeshDeformBind * mdb
MeshDeformIsect * isec
struct MVert * mvert
char editflag
int totvert
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
float obmat[4][4]
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
uint len