Blender  V2.93
MOD_laplaciansmooth.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  *
16  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BLI_utildefines.h"
25 
26 #include "BLI_math.h"
27 
28 #include "BLT_translation.h"
29 
30 #include "DNA_defaults.h"
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_screen_types.h"
35 
36 #include "MEM_guardedalloc.h"
37 
38 #include "BKE_context.h"
39 #include "BKE_deform.h"
40 #include "BKE_editmesh.h"
41 #include "BKE_lib_id.h"
42 #include "BKE_mesh.h"
43 #include "BKE_mesh_wrapper.h"
44 #include "BKE_modifier.h"
45 #include "BKE_screen.h"
46 
47 #include "UI_interface.h"
48 #include "UI_resources.h"
49 
50 #include "RNA_access.h"
51 
52 #include "MOD_ui_common.h"
53 #include "MOD_util.h"
54 
55 #include "eigen_capi.h"
56 
57 struct BLaplacianSystem {
58  float *eweights; /* Length weights per Edge */
59  float (*fweights)[3]; /* Cotangent weights per face */
60  float *ring_areas; /* Total area per ring*/
61  float *vlengths; /* Total sum of lengths(edges) per vertice*/
62  float *vweights; /* Total sum of weights per vertice*/
63  int numEdges; /* Number of edges*/
64  int numLoops; /* Number of edges*/
65  int numPolys; /* Number of faces*/
66  int numVerts; /* Number of verts*/
67  short *numNeFa; /* Number of neighbors faces around vertice*/
68  short *numNeEd; /* Number of neighbors Edges around vertice*/
69  short *zerola; /* Is zero area or length*/
70 
71  /* Pointers to data*/
73  const MPoly *mpoly;
74  const MLoop *mloop;
75  const MEdge *medges;
77 
78  /*Data*/
79  float min_area;
80  float vert_centroid[3];
81 };
82 typedef struct BLaplacianSystem LaplacianSystem;
83 
84 static void required_data_mask(Object *ob, ModifierData *md, CustomData_MeshMasks *r_cddata_masks);
85 static bool is_disabled(const struct Scene *scene, ModifierData *md, bool useRenderParams);
86 static float compute_volume(const float center[3],
87  float (*vertexCos)[3],
88  const MPoly *mpoly,
89  int numPolys,
90  const MLoop *mloop);
91 static LaplacianSystem *init_laplacian_system(int a_numEdges,
92  int a_numPolys,
93  int a_numLoops,
94  int a_numVerts);
96 static void fill_laplacian_matrix(LaplacianSystem *sys);
97 static void init_data(ModifierData *md);
98 static void init_laplacian_matrix(LaplacianSystem *sys);
99 static void memset_laplacian_system(LaplacianSystem *sys, int val);
100 static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag);
101 static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border);
102 
104 {
105  MEM_SAFE_FREE(sys->eweights);
106  MEM_SAFE_FREE(sys->fweights);
107  MEM_SAFE_FREE(sys->numNeEd);
108  MEM_SAFE_FREE(sys->numNeFa);
109  MEM_SAFE_FREE(sys->ring_areas);
110  MEM_SAFE_FREE(sys->vlengths);
111  MEM_SAFE_FREE(sys->vweights);
112  MEM_SAFE_FREE(sys->zerola);
113 
114  if (sys->context) {
116  }
117  sys->vertexCos = NULL;
118  sys->mpoly = NULL;
119  sys->mloop = NULL;
120  sys->medges = NULL;
121  MEM_freeN(sys);
122 }
123 
124 static void memset_laplacian_system(LaplacianSystem *sys, int val)
125 {
126  memset(sys->eweights, val, sizeof(float) * sys->numEdges);
127  memset(sys->fweights, val, sizeof(float[3]) * sys->numLoops);
128  memset(sys->numNeEd, val, sizeof(short) * sys->numVerts);
129  memset(sys->numNeFa, val, sizeof(short) * sys->numVerts);
130  memset(sys->ring_areas, val, sizeof(float) * sys->numVerts);
131  memset(sys->vlengths, val, sizeof(float) * sys->numVerts);
132  memset(sys->vweights, val, sizeof(float) * sys->numVerts);
133  memset(sys->zerola, val, sizeof(short) * sys->numVerts);
134 }
135 
136 static LaplacianSystem *init_laplacian_system(int a_numEdges,
137  int a_numPolys,
138  int a_numLoops,
139  int a_numVerts)
140 {
141  LaplacianSystem *sys;
142  sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem");
143  sys->numEdges = a_numEdges;
144  sys->numPolys = a_numPolys;
145  sys->numLoops = a_numLoops;
146  sys->numVerts = a_numVerts;
147 
148  sys->eweights = MEM_calloc_arrayN(sys->numEdges, sizeof(float), __func__);
149  sys->fweights = MEM_calloc_arrayN(sys->numLoops, sizeof(float[3]), __func__);
150  sys->numNeEd = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__);
151  sys->numNeFa = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__);
152  sys->ring_areas = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__);
153  sys->vlengths = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__);
154  sys->vweights = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__);
155  sys->zerola = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__);
156 
157  return sys;
158 }
159 
160 static float compute_volume(const float center[3],
161  float (*vertexCos)[3],
162  const MPoly *mpoly,
163  int numPolys,
164  const MLoop *mloop)
165 {
166  int i;
167  float vol = 0.0f;
168 
169  for (i = 0; i < numPolys; i++) {
170  const MPoly *mp = &mpoly[i];
171  const MLoop *l_first = &mloop[mp->loopstart];
172  const MLoop *l_prev = l_first + 1;
173  const MLoop *l_curr = l_first + 2;
174  const MLoop *l_term = l_first + mp->totloop;
175 
176  for (; l_curr != l_term; l_prev = l_curr, l_curr++) {
178  center, vertexCos[l_first->v], vertexCos[l_prev->v], vertexCos[l_curr->v]);
179  }
180  }
181 
182  return fabsf(vol);
183 }
184 
185 static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag)
186 {
187  float beta;
188  int i;
189 
190  if (vend != 0.0f) {
191  beta = pow(vini / vend, 1.0f / 3.0f);
192  for (i = 0; i < sys->numVerts; i++) {
193  if (flag & MOD_LAPLACIANSMOOTH_X) {
194  sys->vertexCos[i][0] = (sys->vertexCos[i][0] - sys->vert_centroid[0]) * beta +
195  sys->vert_centroid[0];
196  }
197  if (flag & MOD_LAPLACIANSMOOTH_Y) {
198  sys->vertexCos[i][1] = (sys->vertexCos[i][1] - sys->vert_centroid[1]) * beta +
199  sys->vert_centroid[1];
200  }
201  if (flag & MOD_LAPLACIANSMOOTH_Z) {
202  sys->vertexCos[i][2] = (sys->vertexCos[i][2] - sys->vert_centroid[2]) * beta +
203  sys->vert_centroid[2];
204  }
205  }
206  }
207 }
208 
210 {
211  float *v1, *v2;
212  float w1, w2, w3;
213  float areaf;
214  int i;
215  uint idv1, idv2;
216 
217  for (i = 0; i < sys->numEdges; i++) {
218  idv1 = sys->medges[i].v1;
219  idv2 = sys->medges[i].v2;
220 
221  v1 = sys->vertexCos[idv1];
222  v2 = sys->vertexCos[idv2];
223 
224  sys->numNeEd[idv1] = sys->numNeEd[idv1] + 1;
225  sys->numNeEd[idv2] = sys->numNeEd[idv2] + 1;
226  w1 = len_v3v3(v1, v2);
227  if (w1 < sys->min_area) {
228  sys->zerola[idv1] = 1;
229  sys->zerola[idv2] = 1;
230  }
231  else {
232  w1 = 1.0f / w1;
233  }
234 
235  sys->eweights[i] = w1;
236  }
237 
238  for (i = 0; i < sys->numPolys; i++) {
239  const MPoly *mp = &sys->mpoly[i];
240  const MLoop *l_next = &sys->mloop[mp->loopstart];
241  const MLoop *l_term = l_next + mp->totloop;
242  const MLoop *l_prev = l_term - 2;
243  const MLoop *l_curr = l_term - 1;
244 
245  for (; l_next != l_term; l_prev = l_curr, l_curr = l_next, l_next++) {
246  const float *v_prev = sys->vertexCos[l_prev->v];
247  const float *v_curr = sys->vertexCos[l_curr->v];
248  const float *v_next = sys->vertexCos[l_next->v];
249  const uint l_curr_index = l_curr - sys->mloop;
250 
251  sys->numNeFa[l_curr->v] += 1;
252 
253  areaf = area_tri_v3(v_prev, v_curr, v_next);
254 
255  if (areaf < sys->min_area) {
256  sys->zerola[l_curr->v] = 1;
257  }
258 
259  sys->ring_areas[l_prev->v] += areaf;
260  sys->ring_areas[l_curr->v] += areaf;
261  sys->ring_areas[l_next->v] += areaf;
262 
263  w1 = cotangent_tri_weight_v3(v_curr, v_next, v_prev) / 2.0f;
264  w2 = cotangent_tri_weight_v3(v_next, v_prev, v_curr) / 2.0f;
265  w3 = cotangent_tri_weight_v3(v_prev, v_curr, v_next) / 2.0f;
266 
267  sys->fweights[l_curr_index][0] += w1;
268  sys->fweights[l_curr_index][1] += w2;
269  sys->fweights[l_curr_index][2] += w3;
270 
271  sys->vweights[l_curr->v] += w2 + w3;
272  sys->vweights[l_next->v] += w1 + w3;
273  sys->vweights[l_prev->v] += w1 + w2;
274  }
275  }
276  for (i = 0; i < sys->numEdges; i++) {
277  idv1 = sys->medges[i].v1;
278  idv2 = sys->medges[i].v2;
279  /* if is boundary, apply scale-dependent umbrella operator only with neighbors in boundary */
280  if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2]) {
281  sys->vlengths[idv1] += sys->eweights[i];
282  sys->vlengths[idv2] += sys->eweights[i];
283  }
284  }
285 }
286 
288 {
289  int i;
290  uint idv1, idv2;
291 
292  for (i = 0; i < sys->numPolys; i++) {
293  const MPoly *mp = &sys->mpoly[i];
294  const MLoop *l_next = &sys->mloop[mp->loopstart];
295  const MLoop *l_term = l_next + mp->totloop;
296  const MLoop *l_prev = l_term - 2;
297  const MLoop *l_curr = l_term - 1;
298 
299  for (; l_next != l_term; l_prev = l_curr, l_curr = l_next, l_next++) {
300  const uint l_curr_index = l_curr - sys->mloop;
301 
302  /* Is ring if number of faces == number of edges around vertice*/
303  if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == 0) {
305  l_curr->v,
306  l_next->v,
307  sys->fweights[l_curr_index][2] * sys->vweights[l_curr->v]);
309  l_curr->v,
310  l_prev->v,
311  sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]);
312  }
313  if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == 0) {
315  l_next->v,
316  l_curr->v,
317  sys->fweights[l_curr_index][2] * sys->vweights[l_next->v]);
319  l_next->v,
320  l_prev->v,
321  sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]);
322  }
323  if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == 0) {
325  l_prev->v,
326  l_curr->v,
327  sys->fweights[l_curr_index][1] * sys->vweights[l_prev->v]);
329  l_prev->v,
330  l_next->v,
331  sys->fweights[l_curr_index][0] * sys->vweights[l_prev->v]);
332  }
333  }
334  }
335 
336  for (i = 0; i < sys->numEdges; i++) {
337  idv1 = sys->medges[i].v1;
338  idv2 = sys->medges[i].v2;
339  /* Is boundary */
340  if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2] &&
341  sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) {
343  sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
345  sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
346  }
347  }
348 }
349 
350 static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border)
351 {
352  int i;
353  float lam;
354  float vini = 0.0f, vend = 0.0f;
355 
357  vini = compute_volume(
358  sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
359  }
360  for (i = 0; i < sys->numVerts; i++) {
361  if (sys->zerola[i] == 0) {
362  lam = sys->numNeEd[i] == sys->numNeFa[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) :
363  (lambda_border >= 0.0f ? 1.0f : -1.0f);
364  if (flag & MOD_LAPLACIANSMOOTH_X) {
365  sys->vertexCos[i][0] += lam * ((float)EIG_linear_solver_variable_get(sys->context, 0, i) -
366  sys->vertexCos[i][0]);
367  }
368  if (flag & MOD_LAPLACIANSMOOTH_Y) {
369  sys->vertexCos[i][1] += lam * ((float)EIG_linear_solver_variable_get(sys->context, 1, i) -
370  sys->vertexCos[i][1]);
371  }
372  if (flag & MOD_LAPLACIANSMOOTH_Z) {
373  sys->vertexCos[i][2] += lam * ((float)EIG_linear_solver_variable_get(sys->context, 2, i) -
374  sys->vertexCos[i][2]);
375  }
376  }
377  }
379  vend = compute_volume(
380  sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
381  volume_preservation(sys, vini, vend, flag);
382  }
383 }
384 
386  LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts)
387 {
388  LaplacianSystem *sys;
389  MDeformVert *dvert = NULL;
390  MDeformVert *dv = NULL;
391  float w, wpaint;
392  int i, iter;
393  int defgrp_index;
394  const bool invert_vgroup = (smd->flag & MOD_LAPLACIANSMOOTH_INVERT_VGROUP) != 0;
395 
397  if (!sys) {
398  return;
399  }
400 
401  sys->mpoly = mesh->mpoly;
402  sys->mloop = mesh->mloop;
403  sys->medges = mesh->medge;
404  sys->vertexCos = vertexCos;
405  sys->min_area = 0.00001f;
406  MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index);
407 
408  sys->vert_centroid[0] = 0.0f;
409  sys->vert_centroid[1] = 0.0f;
410  sys->vert_centroid[2] = 0.0f;
411  memset_laplacian_system(sys, 0);
412 
414 
416 
417  for (iter = 0; iter < smd->repeat; iter++) {
418  for (i = 0; i < numVerts; i++) {
422  if (iter == 0) {
423  add_v3_v3(sys->vert_centroid, vertexCos[i]);
424  }
425  }
426  if (iter == 0 && numVerts > 0) {
427  mul_v3_fl(sys->vert_centroid, 1.0f / (float)numVerts);
428  }
429 
430  dv = dvert;
431  for (i = 0; i < numVerts; i++) {
435  if (iter == 0) {
436  if (dv) {
437  wpaint = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) :
438  BKE_defvert_find_weight(dv, defgrp_index);
439  dv++;
440  }
441  else {
442  wpaint = 1.0f;
443  }
444 
445  if (sys->zerola[i] == 0) {
447  w = sys->vweights[i];
448  sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w;
449  w = sys->vlengths[i];
450  sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
451  if (sys->numNeEd[i] == sys->numNeFa[i]) {
452  EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint);
453  }
454  else {
456  sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
457  }
458  }
459  else {
460  w = sys->vweights[i] * sys->ring_areas[i];
461  sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / (4.0f * w);
462  w = sys->vlengths[i];
463  sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
464 
465  if (sys->numNeEd[i] == sys->numNeFa[i]) {
467  i,
468  i,
469  1.0f + fabsf(smd->lambda) * wpaint /
470  (4.0f * sys->ring_areas[i]));
471  }
472  else {
474  sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
475  }
476  }
477  }
478  else {
479  EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f);
480  }
481  }
482  }
483 
484  if (iter == 0) {
486  }
487 
488  if (EIG_linear_solver_solve(sys->context)) {
489  validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border);
490  }
491  }
493  sys->context = NULL;
494 
496 }
497 
498 static void init_data(ModifierData *md)
499 {
501 
502  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier));
503 
505 }
506 
507 static bool is_disabled(const struct Scene *UNUSED(scene),
508  ModifierData *md,
509  bool UNUSED(useRenderParams))
510 {
512  short flag;
513 
515 
516  /* disable if modifier is off for X, Y and Z or if factor is 0 */
517  if (flag == 0) {
518  return 1;
519  }
520 
521  return 0;
522 }
523 
525  ModifierData *md,
526  CustomData_MeshMasks *r_cddata_masks)
527 {
529 
530  /* ask for vertexgroups if we need them */
531  if (smd->defgrp_name[0] != '\0') {
532  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
533  }
534 }
535 
536 static void deformVerts(ModifierData *md,
537  const ModifierEvalContext *ctx,
538  Mesh *mesh,
539  float (*vertexCos)[3],
540  int numVerts)
541 {
542  Mesh *mesh_src;
543 
544  if (numVerts == 0) {
545  return;
546  }
547 
548  mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
549 
551  (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
552 
553  if (!ELEM(mesh_src, NULL, mesh)) {
554  BKE_id_free(NULL, mesh_src);
555  }
556 }
557 
558 static void deformVertsEM(ModifierData *md,
559  const ModifierEvalContext *ctx,
560  struct BMEditMesh *editData,
561  Mesh *mesh,
562  float (*vertexCos)[3],
563  int numVerts)
564 {
565  Mesh *mesh_src;
566 
567  if (numVerts == 0) {
568  return;
569  }
570 
571  mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
572 
573  /* TODO(Campbell): use edit-mode data only (remove this line). */
574  if (mesh_src != NULL) {
576  }
577 
579  (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
580 
581  if (!ELEM(mesh_src, NULL, mesh)) {
582  BKE_id_free(NULL, mesh_src);
583  }
584 }
585 
586 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
587 {
588  uiLayout *row;
589  uiLayout *layout = panel->layout;
591 
592  PointerRNA ob_ptr;
594 
595  uiLayoutSetPropSep(layout, true);
596 
597  uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
598 
599  row = uiLayoutRowWithHeading(layout, true, IFACE_("Axis"));
600  uiItemR(row, ptr, "use_x", toggles_flag, NULL, ICON_NONE);
601  uiItemR(row, ptr, "use_y", toggles_flag, NULL, ICON_NONE);
602  uiItemR(row, ptr, "use_z", toggles_flag, NULL, ICON_NONE);
603 
604  uiItemR(layout, ptr, "lambda_factor", 0, NULL, ICON_NONE);
605  uiItemR(layout, ptr, "lambda_border", 0, NULL, ICON_NONE);
606 
607  uiItemR(layout, ptr, "use_volume_preserve", 0, NULL, ICON_NONE);
608  uiItemR(layout, ptr, "use_normalized", 0, NULL, ICON_NONE);
609 
610  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
611 
612  modifier_panel_end(layout, ptr);
613 }
614 
615 static void panelRegister(ARegionType *region_type)
616 {
618 }
619 
621  /* name */ "LaplacianSmooth",
622  /* structName */ "LaplacianSmoothModifierData",
623  /* structSize */ sizeof(LaplacianSmoothModifierData),
624  /* srna */ &RNA_LaplacianSmoothModifier,
625  /* type */ eModifierTypeType_OnlyDeform,
627  /* icon */ ICON_MOD_SMOOTH,
628 
629  /* copyData */ BKE_modifier_copydata_generic,
630 
631  /* deformVerts */ deformVerts,
632  /* deformMatrices */ NULL,
633  /* deformVertsEM */ deformVertsEM,
634  /* deformMatricesEM */ NULL,
635  /* modifyMesh */ NULL,
636  /* modifyHair */ NULL,
637  /* modifyGeometrySet */ NULL,
638  /* modifyVolume */ NULL,
639 
640  /* initData */ init_data,
641  /* requiredDataMask */ required_data_mask,
642  /* freeData */ NULL,
643  /* isDisabled */ is_disabled,
644  /* updateDepsgraph */ NULL,
645  /* dependsOnTime */ NULL,
646  /* dependsOnNormals */ NULL,
647  /* foreachIDLink */ NULL,
648  /* foreachTexLink */ NULL,
649  /* freeRuntimeData */ NULL,
650  /* panelRegister */ panelRegister,
651  /* blendWrite */ NULL,
652  /* blendRead */ NULL,
653 };
typedef float(TangentPoint)[2]
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
Definition: deform.c:632
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.c:98
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:83
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:58
#define BLI_assert(a)
Definition: BLI_assert.h:58
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:116
float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:289
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:220
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
#define CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
@ MOD_LAPLACIANSMOOTH_X
@ MOD_LAPLACIANSMOOTH_Y
@ MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME
@ MOD_LAPLACIANSMOOTH_NORMALIZED
@ MOD_LAPLACIANSMOOTH_Z
@ MOD_LAPLACIANSMOOTH_INVERT_VGROUP
struct LaplacianSmoothModifierData LaplacianSmoothModifierData
@ eModifierType_LaplacianSmooth
Object is a sort of wrapper for general info.
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 v1
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static void deformVertsEM(ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *editData, Mesh *mesh, float(*vertexCos)[3], int numVerts)
static void init_data(ModifierData *md)
static bool is_disabled(const struct Scene *scene, ModifierData *md, bool useRenderParams)
static float compute_volume(const float center[3], float(*vertexCos)[3], const MPoly *mpoly, int numPolys, const MLoop *mloop)
ModifierTypeInfo modifierType_LaplacianSmooth
static void init_laplacian_matrix(LaplacianSystem *sys)
static void delete_laplacian_system(LaplacianSystem *sys)
static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float(*vertexCos)[3], int numVerts)
static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag)
static void memset_laplacian_system(LaplacianSystem *sys, int val)
static void laplaciansmoothModifier_do(LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float(*vertexCos)[3], int numVerts)
static void required_data_mask(Object *ob, ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void fill_laplacian_matrix(LaplacianSystem *sys)
static void panelRegister(ARegionType *region_type)
static LaplacianSystem * init_laplacian_system(int a_numEdges, int a_numPolys, int a_numLoops, int a_numVerts)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
Mesh * MOD_deform_mesh_eval_get(Object *ob, struct BMEditMesh *em, Mesh *mesh, const float(*vertexCos)[3], const int num_verts, const bool use_normals, const bool use_orco)
Definition: MOD_util.c:186
void MOD_get_vgroup(Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
Definition: MOD_util.c:254
StructRNA RNA_LaplacianSmoothModifier
#define C
Definition: RandGen.cpp:39
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
Scene scene
#define fabsf(x)
void EIG_linear_solver_variable_set(LinearSolver *solver, int rhs, int index, double value)
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(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
Definition: rall1d.h:359
LinearSolver * context
const MEdge * medges
float(* fweights)[3]
Definition: meshlaplacian.c:82
LinearSolver * context
Definition: meshlaplacian.c:74
unsigned int v
struct MEdge * medge
int totedge
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
struct Object * object
Definition: BKE_modifier.h:154
struct uiLayout * layout
ccl_device_inline float beta(float x, float y)
Definition: util_math.h:666
PointerRNA * ptr
Definition: wm_files.c:3157