Blender V4.3
MOD_laplaciansmooth.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_math_geom.h"
10#include "BLI_utildefines.h"
11
12#include "BLT_translation.hh"
13
14#include "DNA_defaults.h"
15#include "DNA_mesh_types.h"
16#include "DNA_meshdata_types.h"
17#include "DNA_screen_types.h"
18
19#include "MEM_guardedalloc.h"
20
21#include "BKE_deform.hh"
22#include "BKE_modifier.hh"
23
24#include "UI_interface.hh"
25#include "UI_resources.hh"
26
27#include "RNA_prototypes.hh"
28
29#include "MOD_ui_common.hh"
30#include "MOD_util.hh"
31
32#include "eigen_capi.h"
33
34struct LaplacianSystem {
35 float *eweights; /* Length weights per Edge */
36 float (*fweights)[3]; /* Cotangent weights per face */
37 float *ring_areas; /* Total area per ring. */
38 float *vlengths; /* Total sum of lengths(edges) per vertex. */
39 float *vweights; /* Total sum of weights per vertex. */
40 int verts_num; /* Number of verts. */
41 short *ne_fa_num; /* Number of neighbors faces around vertex. */
42 short *ne_ed_num; /* Number of neighbors Edges around vertex. */
43 bool *zerola; /* Is zero area or length. */
44
45 /* Pointers to data. */
51
52 /* Data. */
53 float min_area;
54 float vert_centroid[3];
55};
56
58{
67
68 if (sys->context) {
70 }
71 sys->vertexCos = nullptr;
72 MEM_freeN(sys);
73}
74
75static void memset_laplacian_system(LaplacianSystem *sys, int val)
76{
77 memset(sys->eweights, val, sizeof(float) * sys->edges.size());
78 memset(sys->fweights, val, sizeof(float[3]) * sys->corner_verts.size());
79 memset(sys->ne_ed_num, val, sizeof(short) * sys->verts_num);
80 memset(sys->ne_fa_num, val, sizeof(short) * sys->verts_num);
81 memset(sys->ring_areas, val, sizeof(float) * sys->verts_num);
82 memset(sys->vlengths, val, sizeof(float) * sys->verts_num);
83 memset(sys->vweights, val, sizeof(float) * sys->verts_num);
84 memset(sys->zerola, val, sizeof(bool) * sys->verts_num);
85}
86
87static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts)
88{
89 LaplacianSystem *sys;
90 sys = static_cast<LaplacianSystem *>(MEM_callocN(sizeof(LaplacianSystem), __func__));
91 sys->verts_num = a_numVerts;
92
93 sys->eweights = MEM_cnew_array<float>(a_numEdges, __func__);
94 sys->fweights = MEM_cnew_array<float[3]>(a_numLoops, __func__);
95 sys->ne_ed_num = MEM_cnew_array<short>(sys->verts_num, __func__);
96 sys->ne_fa_num = MEM_cnew_array<short>(sys->verts_num, __func__);
97 sys->ring_areas = MEM_cnew_array<float>(sys->verts_num, __func__);
98 sys->vlengths = MEM_cnew_array<float>(sys->verts_num, __func__);
99 sys->vweights = MEM_cnew_array<float>(sys->verts_num, __func__);
100 sys->zerola = MEM_cnew_array<bool>(sys->verts_num, __func__);
101
102 return sys;
103}
104
105static float compute_volume(const float center[3],
106 float (*vertexCos)[3],
107 const blender::OffsetIndices<int> faces,
108 const blender::Span<int> corner_verts)
109{
110 float vol = 0.0f;
111
112 for (const int i : faces.index_range()) {
113 const blender::IndexRange face = faces[i];
114 int corner_first = face.start();
115 int corner_prev = corner_first + 1;
116 int corner_curr = corner_first + 2;
117 int corner_term = corner_first + face.size();
118
119 for (; corner_curr != corner_term; corner_prev = corner_curr, corner_curr++) {
120 vol += volume_tetrahedron_signed_v3(center,
121 vertexCos[corner_verts[corner_first]],
122 vertexCos[corner_verts[corner_prev]],
123 vertexCos[corner_verts[corner_curr]]);
124 }
125 }
126
127 return fabsf(vol);
128}
129
130static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag)
131{
132 float beta;
133 int i;
134
135 if (vend != 0.0f) {
136 beta = pow(vini / vend, 1.0f / 3.0f);
137 for (i = 0; i < sys->verts_num; i++) {
139 sys->vertexCos[i][0] = (sys->vertexCos[i][0] - sys->vert_centroid[0]) * beta +
140 sys->vert_centroid[0];
141 }
143 sys->vertexCos[i][1] = (sys->vertexCos[i][1] - sys->vert_centroid[1]) * beta +
144 sys->vert_centroid[1];
145 }
147 sys->vertexCos[i][2] = (sys->vertexCos[i][2] - sys->vert_centroid[2]) * beta +
148 sys->vert_centroid[2];
149 }
150 }
151 }
152}
153
155{
156 float *v1, *v2;
157 float w1, w2, w3;
158 float areaf;
159 int i;
160 uint idv1, idv2;
161
162 for (i = 0; i < sys->edges.size(); i++) {
163 idv1 = sys->edges[i][0];
164 idv2 = sys->edges[i][1];
165
166 v1 = sys->vertexCos[idv1];
167 v2 = sys->vertexCos[idv2];
168
169 sys->ne_ed_num[idv1] = sys->ne_ed_num[idv1] + 1;
170 sys->ne_ed_num[idv2] = sys->ne_ed_num[idv2] + 1;
171 w1 = len_v3v3(v1, v2);
172 if (w1 < sys->min_area) {
173 sys->zerola[idv1] = true;
174 sys->zerola[idv2] = true;
175 }
176 else {
177 w1 = 1.0f / w1;
178 }
179
180 sys->eweights[i] = w1;
181 }
182
183 const blender::Span<int> corner_verts = sys->corner_verts;
184
185 for (const int i : sys->faces.index_range()) {
186 const blender::IndexRange face = sys->faces[i];
187 int corner_next = face.start();
188 int corner_term = corner_next + face.size();
189 int corner_prev = corner_term - 2;
190 int corner_curr = corner_term - 1;
191
192 for (; corner_next != corner_term;
193 corner_prev = corner_curr, corner_curr = corner_next, corner_next++)
194 {
195 const float *v_prev = sys->vertexCos[corner_verts[corner_prev]];
196 const float *v_curr = sys->vertexCos[corner_verts[corner_curr]];
197 const float *v_next = sys->vertexCos[corner_verts[corner_next]];
198
199 sys->ne_fa_num[corner_verts[corner_curr]] += 1;
200
201 areaf = area_tri_v3(v_prev, v_curr, v_next);
202
203 if (areaf < sys->min_area) {
204 sys->zerola[corner_verts[corner_curr]] = true;
205 }
206
207 sys->ring_areas[corner_verts[corner_prev]] += areaf;
208 sys->ring_areas[corner_verts[corner_curr]] += areaf;
209 sys->ring_areas[corner_verts[corner_next]] += areaf;
210
211 w1 = cotangent_tri_weight_v3(v_curr, v_next, v_prev) / 2.0f;
212 w2 = cotangent_tri_weight_v3(v_next, v_prev, v_curr) / 2.0f;
213 w3 = cotangent_tri_weight_v3(v_prev, v_curr, v_next) / 2.0f;
214
215 sys->fweights[corner_curr][0] += w1;
216 sys->fweights[corner_curr][1] += w2;
217 sys->fweights[corner_curr][2] += w3;
218
219 sys->vweights[corner_verts[corner_curr]] += w2 + w3;
220 sys->vweights[corner_verts[corner_next]] += w1 + w3;
221 sys->vweights[corner_verts[corner_prev]] += w1 + w2;
222 }
223 }
224 for (i = 0; i < sys->edges.size(); i++) {
225 idv1 = sys->edges[i][0];
226 idv2 = sys->edges[i][1];
227 /* if is boundary, apply scale-dependent umbrella operator only with neighbors in boundary */
228 if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] &&
229 sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2])
230 {
231 sys->vlengths[idv1] += sys->eweights[i];
232 sys->vlengths[idv2] += sys->eweights[i];
233 }
234 }
235}
236
238{
239 int i;
240 uint idv1, idv2;
241
242 const blender::Span<int> corner_verts = sys->corner_verts;
243
244 for (const int i : sys->faces.index_range()) {
245 const blender::IndexRange face = sys->faces[i];
246 int corner_next = face.start();
247 int corner_term = corner_next + face.size();
248 int corner_prev = corner_term - 2;
249 int corner_curr = corner_term - 1;
250
251 for (; corner_next != corner_term;
252 corner_prev = corner_curr, corner_curr = corner_next, corner_next++)
253 {
254
255 /* Is ring if number of faces == number of edges around vertex. */
256 if (sys->ne_ed_num[corner_verts[corner_curr]] == sys->ne_fa_num[corner_verts[corner_curr]] &&
257 sys->zerola[corner_verts[corner_curr]] == false)
258 {
260 corner_verts[corner_curr],
261 corner_verts[corner_next],
262 sys->fweights[corner_curr][2] *
263 sys->vweights[corner_verts[corner_curr]]);
265 corner_verts[corner_curr],
266 corner_verts[corner_prev],
267 sys->fweights[corner_curr][1] *
268 sys->vweights[corner_verts[corner_curr]]);
269 }
270 if (sys->ne_ed_num[corner_verts[corner_next]] == sys->ne_fa_num[corner_verts[corner_next]] &&
271 sys->zerola[corner_verts[corner_next]] == false)
272 {
274 corner_verts[corner_next],
275 corner_verts[corner_curr],
276 sys->fweights[corner_curr][2] *
277 sys->vweights[corner_verts[corner_next]]);
279 corner_verts[corner_next],
280 corner_verts[corner_prev],
281 sys->fweights[corner_curr][0] *
282 sys->vweights[corner_verts[corner_next]]);
283 }
284 if (sys->ne_ed_num[corner_verts[corner_prev]] == sys->ne_fa_num[corner_verts[corner_prev]] &&
285 sys->zerola[corner_verts[corner_prev]] == false)
286 {
288 corner_verts[corner_prev],
289 corner_verts[corner_curr],
290 sys->fweights[corner_curr][1] *
291 sys->vweights[corner_verts[corner_prev]]);
293 corner_verts[corner_prev],
294 corner_verts[corner_next],
295 sys->fweights[corner_curr][0] *
296 sys->vweights[corner_verts[corner_prev]]);
297 }
298 }
299 }
300
301 for (i = 0; i < sys->edges.size(); i++) {
302 idv1 = sys->edges[i][0];
303 idv2 = sys->edges[i][1];
304 /* Is boundary */
305 if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] &&
306 sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2] && sys->zerola[idv1] == false &&
307 sys->zerola[idv2] == false)
308 {
310 sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
312 sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
313 }
314 }
315}
316
317static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border)
318{
319 int i;
320 float lam;
321 float vini = 0.0f, vend = 0.0f;
322
324 vini = compute_volume(sys->vert_centroid, sys->vertexCos, sys->faces, sys->corner_verts);
325 }
326 for (i = 0; i < sys->verts_num; i++) {
327 if (sys->zerola[i] == false) {
328 lam = sys->ne_ed_num[i] == sys->ne_fa_num[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) :
329 (lambda_border >= 0.0f ? 1.0f : -1.0f);
331 sys->vertexCos[i][0] += lam * (float(EIG_linear_solver_variable_get(sys->context, 0, i)) -
332 sys->vertexCos[i][0]);
333 }
335 sys->vertexCos[i][1] += lam * (float(EIG_linear_solver_variable_get(sys->context, 1, i)) -
336 sys->vertexCos[i][1]);
337 }
339 sys->vertexCos[i][2] += lam * (float(EIG_linear_solver_variable_get(sys->context, 2, i)) -
340 sys->vertexCos[i][2]);
341 }
342 }
343 }
345 vend = compute_volume(sys->vert_centroid, sys->vertexCos, sys->faces, sys->corner_verts);
346 volume_preservation(sys, vini, vend, flag);
347 }
348}
349
351 LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num)
352{
353 LaplacianSystem *sys;
354 const MDeformVert *dvert = nullptr;
355 const MDeformVert *dv = nullptr;
356 float w, wpaint;
357 int i, iter;
358 int defgrp_index;
359 const bool invert_vgroup = (smd->flag & MOD_LAPLACIANSMOOTH_INVERT_VGROUP) != 0;
360
361 sys = init_laplacian_system(mesh->edges_num, mesh->corners_num, verts_num);
362 if (!sys) {
363 return;
364 }
365
366 sys->edges = mesh->edges();
367 sys->faces = mesh->faces();
368 sys->corner_verts = mesh->corner_verts();
369 sys->vertexCos = vertexCos;
370 sys->min_area = 0.00001f;
371 MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index);
372
373 sys->vert_centroid[0] = 0.0f;
374 sys->vert_centroid[1] = 0.0f;
375 sys->vert_centroid[2] = 0.0f;
377
378 sys->context = EIG_linear_least_squares_solver_new(verts_num, verts_num, 3);
379
381
382 for (iter = 0; iter < smd->repeat; iter++) {
383 for (i = 0; i < verts_num; i++) {
384 EIG_linear_solver_variable_set(sys->context, 0, i, vertexCos[i][0]);
385 EIG_linear_solver_variable_set(sys->context, 1, i, vertexCos[i][1]);
386 EIG_linear_solver_variable_set(sys->context, 2, i, vertexCos[i][2]);
387 if (iter == 0) {
388 add_v3_v3(sys->vert_centroid, vertexCos[i]);
389 }
390 }
391 if (iter == 0 && verts_num > 0) {
392 mul_v3_fl(sys->vert_centroid, 1.0f / float(verts_num));
393 }
394
395 dv = dvert;
396 for (i = 0; i < verts_num; i++) {
397 EIG_linear_solver_right_hand_side_add(sys->context, 0, i, vertexCos[i][0]);
398 EIG_linear_solver_right_hand_side_add(sys->context, 1, i, vertexCos[i][1]);
399 EIG_linear_solver_right_hand_side_add(sys->context, 2, i, vertexCos[i][2]);
400 if (iter == 0) {
401 if (dv) {
402 wpaint = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) :
403 BKE_defvert_find_weight(dv, defgrp_index);
404 dv++;
405 }
406 else {
407 wpaint = 1.0f;
408 }
409
410 if (sys->zerola[i] == false) {
412 w = sys->vweights[i];
413 sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w;
414 w = sys->vlengths[i];
415 sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
416 if (sys->ne_ed_num[i] == sys->ne_fa_num[i]) {
417 EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint);
418 }
419 else {
421 sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
422 }
423 }
424 else {
425 w = sys->vweights[i] * sys->ring_areas[i];
426 sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / (4.0f * w);
427 w = sys->vlengths[i];
428 sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
429
430 if (sys->ne_ed_num[i] == sys->ne_fa_num[i]) {
432 i,
433 i,
434 1.0f + fabsf(smd->lambda) * wpaint /
435 (4.0f * sys->ring_areas[i]));
436 }
437 else {
439 sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
440 }
441 }
442 }
443 else {
444 EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f);
445 }
446 }
447 }
448
449 if (iter == 0) {
451 }
452
454 validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border);
455 }
456 }
458 sys->context = nullptr;
459
461}
462
471
472static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
473{
475 short flag;
476
478
479 /* disable if modifier is off for X, Y and Z or if factor is 0 */
480 if (flag == 0) {
481 return true;
482 }
483
484 return false;
485}
486
487static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
488{
490
491 /* Ask for vertex-groups if we need them. */
492 if (smd->defgrp_name[0] != '\0') {
493 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
494 }
495}
496
498 const ModifierEvalContext *ctx,
499 Mesh *mesh,
501{
502 if (positions.is_empty()) {
503 return;
504 }
505
507 ctx->object,
508 mesh,
509 reinterpret_cast<float(*)[3]>(positions.data()),
510 positions.size());
511}
512
513static void panel_draw(const bContext * /*C*/, Panel *panel)
514{
515 uiLayout *row;
516 uiLayout *layout = panel->layout;
518
519 PointerRNA ob_ptr;
521
522 uiLayoutSetPropSep(layout, true);
523
524 uiItemR(layout, ptr, "iterations", UI_ITEM_NONE, nullptr, ICON_NONE);
525
526 row = uiLayoutRowWithHeading(layout, true, IFACE_("Axis"));
527 uiItemR(row, ptr, "use_x", toggles_flag, nullptr, ICON_NONE);
528 uiItemR(row, ptr, "use_y", toggles_flag, nullptr, ICON_NONE);
529 uiItemR(row, ptr, "use_z", toggles_flag, nullptr, ICON_NONE);
530
531 uiItemR(layout, ptr, "lambda_factor", UI_ITEM_NONE, nullptr, ICON_NONE);
532 uiItemR(layout, ptr, "lambda_border", UI_ITEM_NONE, nullptr, ICON_NONE);
533
534 uiItemR(layout, ptr, "use_volume_preserve", UI_ITEM_NONE, nullptr, ICON_NONE);
535 uiItemR(layout, ptr, "use_normalized", UI_ITEM_NONE, nullptr, ICON_NONE);
536
537 modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
538
539 modifier_panel_end(layout, ptr);
540}
541
542static void panel_register(ARegionType *region_type)
543{
545}
546
548 /*idname*/ "LaplacianSmooth",
549 /*name*/ N_("LaplacianSmooth"),
550 /*struct_name*/ "LaplacianSmoothModifierData",
551 /*struct_size*/ sizeof(LaplacianSmoothModifierData),
552 /*srna*/ &RNA_LaplacianSmoothModifier,
555 /*icon*/ ICON_MOD_SMOOTH,
556
557 /*copy_data*/ BKE_modifier_copydata_generic,
558
559 /*deform_verts*/ deform_verts,
560 /*deform_matrices*/ nullptr,
561 /*deform_verts_EM*/ nullptr,
562 /*deform_matrices_EM*/ nullptr,
563 /*modify_mesh*/ nullptr,
564 /*modify_geometry_set*/ nullptr,
565
566 /*init_data*/ init_data,
567 /*required_data_mask*/ required_data_mask,
568 /*free_data*/ nullptr,
569 /*is_disabled*/ is_disabled,
570 /*update_depsgraph*/ nullptr,
571 /*depends_on_time*/ nullptr,
572 /*depends_on_normals*/ nullptr,
573 /*foreach_ID_link*/ nullptr,
574 /*foreach_tex_link*/ nullptr,
575 /*free_runtime_data*/ nullptr,
576 /*panel_register*/ panel_register,
577 /*blend_write*/ nullptr,
578 /*blend_read*/ nullptr,
579 /*foreach_cache*/ nullptr,
580};
support for deformation groups and hooks.
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:770
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
#define BLI_assert(a)
Definition BLI_assert.h:50
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:98
float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition math_geom.cc:249
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:196
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
#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)
struct LaplacianSmoothModifierData LaplacianSmoothModifierData
@ eModifierType_LaplacianSmooth
@ MOD_LAPLACIANSMOOTH_X
@ MOD_LAPLACIANSMOOTH_Y
@ MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME
@ MOD_LAPLACIANSMOOTH_NORMALIZED
@ MOD_LAPLACIANSMOOTH_Z
@ MOD_LAPLACIANSMOOTH_INVERT_VGROUP
static bool is_disabled
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static void init_data(ModifierData *md)
static void deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
static void panel_register(ARegionType *region_type)
static void laplaciansmoothModifier_do(LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float(*vertexCos)[3], int verts_num)
ModifierTypeInfo modifierType_LaplacianSmooth
static void init_laplacian_matrix(LaplacianSystem *sys)
static void delete_laplacian_system(LaplacianSystem *sys)
static LaplacianSystem * init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts)
static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag)
static void memset_laplacian_system(LaplacianSystem *sys, int val)
static void panel_draw(const bContext *, Panel *panel)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border)
static void fill_laplacian_matrix(LaplacianSystem *sys)
static float compute_volume(const float center[3], float(*vertexCos)[3], const blender::OffsetIndices< int > faces, const blender::Span< int > corner_verts)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
void MOD_get_vgroup(const Object *ob, const Mesh *mesh, const char *name, const MDeformVert **dvert, int *defgrp_index)
Definition MOD_util.cc:159
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
#define UI_ITEM_NONE
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
eUI_Item_Flag
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
ATTR_WARN_UNUSED_RESULT const BMVert * v2
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
constexpr int64_t start() const
constexpr int64_t size() const
Definition BLI_span.hh:253
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
#define fabsf(x)
draw_view in_light_buf[] float
LinearSolver * EIG_linear_least_squares_solver_new(int num_rows, int num_columns, int num_rhs)
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_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.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
blender::OffsetIndices< int > faces
LinearSolver * context
float(* fweights)[3]
blender::Span< int > corner_verts
blender::Span< blender::int2 > edges
struct uiLayout * layout
ccl_device_inline float beta(float x, float y)
Definition util/math.h:833
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138