Blender  V2.93
bmo_smooth_laplacian.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 
23 #include "MEM_guardedalloc.h"
24 
25 #include "BLI_math.h"
26 
27 #include "eigen_capi.h"
28 
29 #include "bmesh.h"
30 
31 #include "intern/bmesh_operators_private.h" /* own include */
32 
33 // #define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f /* UNUSED */
34 // #define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f /* UNUSED */
35 #define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f
36 #define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15f
37 
39  float *eweights; /* Length weights per Edge */
40  float (*fweights)[3]; /* Cotangent weights per face */
41  float *ring_areas; /* Total area per ring*/
42  float *vlengths; /* Total sum of lengths(edges) per vertice*/
43  float *vweights; /* Total sum of weights per vertice*/
44  int numEdges; /* Number of edges*/
45  int numFaces; /* Number of faces*/
46  int numVerts; /* Number of verts*/
47  short *zerola; /* Is zero area or length*/
48 
49  /* Pointers to data*/
53 
54  /*Data*/
55  float min_area;
56 };
57 typedef struct BLaplacianSystem LaplacianSystem;
58 
59 static bool vert_is_boundary(BMVert *v);
60 static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts);
61 static void init_laplacian_matrix(LaplacianSystem *sys);
63 static void delete_void_pointer(void *data);
64 static void fill_laplacian_matrix(LaplacianSystem *sys);
65 static void memset_laplacian_system(LaplacianSystem *sys, int val);
66 static void validate_solution(
67  LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume);
68 static void volume_preservation(
69  BMOperator *op, float vini, float vend, int usex, int usey, int usez);
70 
71 static void delete_void_pointer(void *data)
72 {
73  if (data) {
74  MEM_freeN(data);
75  }
76 }
77 
79 {
80  delete_void_pointer(sys->eweights);
82  delete_void_pointer(sys->ring_areas);
83  delete_void_pointer(sys->vlengths);
84  delete_void_pointer(sys->vweights);
85  delete_void_pointer(sys->zerola);
86  if (sys->context) {
88  }
89  sys->bm = NULL;
90  sys->op = NULL;
91  MEM_freeN(sys);
92 }
93 
94 static void memset_laplacian_system(LaplacianSystem *sys, int val)
95 {
96  memset(sys->eweights, val, sizeof(float) * sys->numEdges);
97  memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3);
98  memset(sys->ring_areas, val, sizeof(float) * sys->numVerts);
99  memset(sys->vlengths, val, sizeof(float) * sys->numVerts);
100  memset(sys->vweights, val, sizeof(float) * sys->numVerts);
101  memset(sys->zerola, val, sizeof(short) * sys->numVerts);
102 }
103 
104 static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts)
105 {
106  LaplacianSystem *sys;
107  sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem");
108  sys->numEdges = a_numEdges;
109  sys->numFaces = a_numFaces;
110  sys->numVerts = a_numVerts;
111 
112  sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight");
113  if (!sys->eweights) {
115  return NULL;
116  }
117 
118  sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numFaces, "ModLaplSmoothFWeight");
119  if (!sys->fweights) {
121  return NULL;
122  }
123 
124  sys->ring_areas = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothRingAreas");
125  if (!sys->ring_areas) {
127  return NULL;
128  }
129 
130  sys->vlengths = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVlengths");
131  if (!sys->vlengths) {
133  return NULL;
134  }
135 
136  sys->vweights = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVweights");
137  if (!sys->vweights) {
139  return NULL;
140  }
141 
142  sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothZeloa");
143  if (!sys->zerola) {
145  return NULL;
146  }
147 
148  return sys;
149 }
150 
168 {
169  float areaf;
170  float *v1, *v2, *v3, *v4;
171  float w1, w2, w3, w4;
172  int i, j;
173  bool has_4_vert;
174  uint idv1, idv2, idv3, idv4, idv[4];
175  BMEdge *e;
176  BMFace *f;
177  BMIter eiter;
178  BMIter fiter;
179  BMIter vi;
180  BMVert *vn;
181  BMVert *vf[4];
182 
183  BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) {
185  v1 = e->v1->co;
186  v2 = e->v2->co;
187  idv1 = BM_elem_index_get(e->v1);
188  idv2 = BM_elem_index_get(e->v2);
189 
190  w1 = len_v3v3(v1, v2);
191  if (w1 > sys->min_area) {
192  w1 = 1.0f / w1;
193  sys->eweights[i] = w1;
194  sys->vlengths[idv1] += w1;
195  sys->vlengths[idv2] += w1;
196  }
197  else {
198  sys->zerola[idv1] = 1;
199  sys->zerola[idv2] = 1;
200  }
201  }
202  }
203 
204  BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) {
206 
207  BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) {
208  vf[j] = vn;
209  }
210  has_4_vert = (j == 4) ? 1 : 0;
211  idv1 = BM_elem_index_get(vf[0]);
212  idv2 = BM_elem_index_get(vf[1]);
213  idv3 = BM_elem_index_get(vf[2]);
214  idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0;
215 
216  v1 = vf[0]->co;
217  v2 = vf[1]->co;
218  v3 = vf[2]->co;
219  v4 = has_4_vert ? vf[3]->co : NULL;
220 
221  if (has_4_vert) {
222  areaf = area_quad_v3(v1, v2, v3, v4);
223  }
224  else {
225  areaf = area_tri_v3(v1, v2, v3);
226  }
227 
228  if (fabsf(areaf) < sys->min_area) {
229  sys->zerola[idv1] = 1;
230  sys->zerola[idv2] = 1;
231  sys->zerola[idv3] = 1;
232  if (has_4_vert) {
233  sys->zerola[idv4] = 1;
234  }
235  }
236 
237  sys->ring_areas[idv1] += areaf;
238  sys->ring_areas[idv2] += areaf;
239  sys->ring_areas[idv3] += areaf;
240  if (has_4_vert) {
241  sys->ring_areas[idv4] += areaf;
242  }
243 
244  if (has_4_vert) {
245 
246  idv[0] = idv1;
247  idv[1] = idv2;
248  idv[2] = idv3;
249  idv[3] = idv4;
250 
251  for (j = 0; j < 4; j++) {
252  idv1 = idv[j];
253  idv2 = idv[(j + 1) % 4];
254  idv3 = idv[(j + 2) % 4];
255  idv4 = idv[(j + 3) % 4];
256 
257  v1 = vf[j]->co;
258  v2 = vf[(j + 1) % 4]->co;
259  v3 = vf[(j + 2) % 4]->co;
260  v4 = vf[(j + 3) % 4]->co;
261 
265 
266  sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f;
267  }
268  }
269  else {
270  w1 = cotangent_tri_weight_v3(v1, v2, v3);
271  w2 = cotangent_tri_weight_v3(v2, v3, v1);
272  w3 = cotangent_tri_weight_v3(v3, v1, v2);
273 
274  sys->fweights[i][0] += w1;
275  sys->fweights[i][1] += w2;
276  sys->fweights[i][2] += w3;
277 
278  sys->vweights[idv1] += w2 + w3;
279  sys->vweights[idv2] += w1 + w3;
280  sys->vweights[idv3] += w1 + w2;
281  }
282  }
283  }
284 }
285 
287 {
288  float *v1, *v2, *v3, *v4;
289  float w2, w3, w4;
290  int i, j;
291  bool has_4_vert;
292  uint idv1, idv2, idv3, idv4, idv[4];
293 
294  BMEdge *e;
295  BMFace *f;
296  BMIter eiter;
297  BMIter fiter;
298  BMIter vi;
299  BMVert *vn;
300  BMVert *vf[4];
301 
302  BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) {
304  BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) {
305  vf[j] = vn;
306  }
307  has_4_vert = (j == 4) ? 1 : 0;
308  if (has_4_vert) {
309  idv[0] = BM_elem_index_get(vf[0]);
310  idv[1] = BM_elem_index_get(vf[1]);
311  idv[2] = BM_elem_index_get(vf[2]);
312  idv[3] = BM_elem_index_get(vf[3]);
313  for (j = 0; j < 4; j++) {
314  idv1 = idv[j];
315  idv2 = idv[(j + 1) % 4];
316  idv3 = idv[(j + 2) % 4];
317  idv4 = idv[(j + 3) % 4];
318 
319  v1 = vf[j]->co;
320  v2 = vf[(j + 1) % 4]->co;
321  v3 = vf[(j + 2) % 4]->co;
322  v4 = vf[(j + 3) % 4]->co;
323 
327 
328  w2 = w2 / 4.0f;
329  w3 = w3 / 4.0f;
330  w4 = w4 / 4.0f;
331 
332  if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) {
333  EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]);
334  EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]);
335  EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]);
336  }
337  }
338  }
339  else {
340  idv1 = BM_elem_index_get(vf[0]);
341  idv2 = BM_elem_index_get(vf[1]);
342  idv3 = BM_elem_index_get(vf[2]);
343  /* Is ring if number of faces == number of edges around vertice. */
344  if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) {
346  sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]);
348  sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]);
349  }
350  if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) {
352  sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]);
354  sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]);
355  }
356  if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) {
358  sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]);
360  sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]);
361  }
362  }
363  }
364  }
365  BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) {
367  v1 = e->v1->co;
368  v2 = e->v2->co;
369  idv1 = BM_elem_index_get(e->v1);
370  idv2 = BM_elem_index_get(e->v2);
371  if (sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) {
373  sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
375  sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
376  }
377  }
378  }
379 }
380 
381 static bool vert_is_boundary(BMVert *v)
382 {
383  BMEdge *ed;
384  BMFace *f;
385  BMIter ei;
386  BMIter fi;
387  BM_ITER_ELEM (ed, &ei, v, BM_EDGES_OF_VERT) {
388  if (BM_edge_is_boundary(ed)) {
389  return 1;
390  }
391  }
392  BM_ITER_ELEM (f, &fi, v, BM_FACES_OF_VERT) {
394  return 1;
395  }
396  }
397  return 0;
398 }
399 
401  BMOperator *op, float vini, float vend, int usex, int usey, int usez)
402 {
403  float beta;
404  BMOIter siter;
405  BMVert *v;
406 
407  if (vend != 0.0f) {
408  beta = pow(vini / vend, 1.0f / 3.0f);
409  BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
410  if (usex) {
411  v->co[0] *= beta;
412  }
413  if (usey) {
414  v->co[1] *= beta;
415  }
416  if (usez) {
417  v->co[2] *= beta;
418  }
419  }
420  }
421 }
422 
423 static void validate_solution(
424  LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume)
425 {
426  int m_vertex_id;
427  float leni, lene;
428  float vini, vend;
429  float *vi1, *vi2, ve1[3], ve2[3];
430  uint idv1, idv2;
431  BMOIter siter;
432  BMVert *v;
433  BMEdge *e;
434  BMIter eiter;
435 
436  BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) {
437  idv1 = BM_elem_index_get(e->v1);
438  idv2 = BM_elem_index_get(e->v2);
439  vi1 = e->v1->co;
440  vi2 = e->v2->co;
441  ve1[0] = EIG_linear_solver_variable_get(sys->context, 0, idv1);
442  ve1[1] = EIG_linear_solver_variable_get(sys->context, 1, idv1);
443  ve1[2] = EIG_linear_solver_variable_get(sys->context, 2, idv1);
444  ve2[0] = EIG_linear_solver_variable_get(sys->context, 0, idv2);
445  ve2[1] = EIG_linear_solver_variable_get(sys->context, 1, idv2);
446  ve2[2] = EIG_linear_solver_variable_get(sys->context, 2, idv2);
447  leni = len_v3v3(vi1, vi2);
448  lene = len_v3v3(ve1, ve2);
449  if (lene > leni * SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE ||
450  lene < leni * SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) {
451  sys->zerola[idv1] = 1;
452  sys->zerola[idv2] = 1;
453  }
454  }
455 
456  if (preserve_volume) {
457  vini = BM_mesh_calc_volume(sys->bm, false);
458  }
459  BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) {
460  m_vertex_id = BM_elem_index_get(v);
461  if (sys->zerola[m_vertex_id] == 0) {
462  if (usex) {
463  v->co[0] = EIG_linear_solver_variable_get(sys->context, 0, m_vertex_id);
464  }
465  if (usey) {
466  v->co[1] = EIG_linear_solver_variable_get(sys->context, 1, m_vertex_id);
467  }
468  if (usez) {
469  v->co[2] = EIG_linear_solver_variable_get(sys->context, 2, m_vertex_id);
470  }
471  }
472  }
473  if (preserve_volume) {
474  vend = BM_mesh_calc_volume(sys->bm, false);
475  volume_preservation(sys->op, vini, vend, usex, usey, usez);
476  }
477 }
478 
480 {
481  int i;
482  int m_vertex_id;
483  bool usex, usey, usez, preserve_volume;
484  float lambda_factor, lambda_border;
485  float w;
486  BMOIter siter;
487  BMVert *v;
488  LaplacianSystem *sys;
489 
490  if (bm->totface == 0) {
491  return;
492  }
494  if (!sys) {
495  return;
496  }
497  sys->bm = bm;
498  sys->op = op;
499 
500  memset_laplacian_system(sys, 0);
501 
503  lambda_factor = BMO_slot_float_get(op->slots_in, "lambda_factor");
504  lambda_border = BMO_slot_float_get(op->slots_in, "lambda_border");
505  sys->min_area = 0.00001f;
506  usex = BMO_slot_bool_get(op->slots_in, "use_x");
507  usey = BMO_slot_bool_get(op->slots_in, "use_y");
508  usez = BMO_slot_bool_get(op->slots_in, "use_z");
509  preserve_volume = BMO_slot_bool_get(op->slots_in, "preserve_volume");
510 
512 
513  for (i = 0; i < bm->totvert; i++) {
515  }
516  BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
517  m_vertex_id = BM_elem_index_get(v);
518  EIG_linear_solver_variable_unlock(sys->context, m_vertex_id);
519  EIG_linear_solver_variable_set(sys->context, 0, m_vertex_id, v->co[0]);
520  EIG_linear_solver_variable_set(sys->context, 1, m_vertex_id, v->co[1]);
521  EIG_linear_solver_variable_set(sys->context, 2, m_vertex_id, v->co[2]);
522  }
523 
525  BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
526  m_vertex_id = BM_elem_index_get(v);
527  EIG_linear_solver_right_hand_side_add(sys->context, 0, m_vertex_id, v->co[0]);
528  EIG_linear_solver_right_hand_side_add(sys->context, 1, m_vertex_id, v->co[1]);
529  EIG_linear_solver_right_hand_side_add(sys->context, 2, m_vertex_id, v->co[2]);
530  i = m_vertex_id;
531  if (sys->zerola[i] == 0) {
532  w = sys->vweights[i] * sys->ring_areas[i];
533  sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda_factor / (4.0f * w);
534  w = sys->vlengths[i];
535  sys->vlengths[i] = (w == 0.0f) ? 0.0f : -lambda_border * 2.0f / w;
536 
537  if (!vert_is_boundary(v)) {
539  sys->context, i, i, 1.0f + lambda_factor / (4.0f * sys->ring_areas[i]));
540  }
541  else {
542  EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + lambda_border * 2.0f);
543  }
544  }
545  else {
546  EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f);
547  }
548  }
550 
551  if (EIG_linear_solver_solve(sys->context)) {
552  validate_solution(sys, usex, usey, usez, preserve_volume);
553  }
554 
556 }
typedef float(TangentPoint)[2]
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
float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:100
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:83
_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 vn
_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.
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_FACES_OF_VERT
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_FACE
@ BM_FACES_OF_MESH
@ BM_EDGES_OF_VERT
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2152
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
double BM_mesh_calc_volume(BMesh *bm, bool is_signed)
Definition: bmesh_query.c:2576
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static void delete_void_pointer(void *data)
void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
static void init_laplacian_matrix(LaplacianSystem *sys)
static void delete_laplacian_system(LaplacianSystem *sys)
static bool vert_is_boundary(BMVert *v)
static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume)
static LaplacianSystem * init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts)
#define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE
static void memset_laplacian_system(LaplacianSystem *sys, int val)
#define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE
static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez)
static void fill_laplacian_matrix(LaplacianSystem *sys)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
#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)
void EIG_linear_solver_variable_unlock(LinearSolver *solver, int index)
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
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
Definition: rall1d.h:359
LinearSolver * context
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
float co[3]
Definition: bmesh_class.h:99
int totvert
Definition: bmesh_class.h:297
int totedge
Definition: bmesh_class.h:297
int totface
Definition: bmesh_class.h:297
float(* fweights)[3]
Definition: meshlaplacian.c:82
LinearSolver * context
Definition: meshlaplacian.c:74
ccl_device_inline float beta(float x, float y)
Definition: util_math.h:666