Blender V4.3
MOD_laplaciandeform.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_utildefines.h"
10
11#include "BLI_math_geom.h"
12#include "BLI_math_vector.h"
13#include "BLI_string.h"
15
16#include "MEM_guardedalloc.h"
17
18#include "BLT_translation.hh"
19
20#include "DNA_defaults.h"
21#include "DNA_mesh_types.h"
22#include "DNA_meshdata_types.h"
23#include "DNA_screen_types.h"
24
25#include "BKE_deform.hh"
26#include "BKE_mesh_mapping.hh"
27
28#include "UI_interface.hh"
29#include "UI_resources.hh"
30
31#include "BLO_read_write.hh"
32
33#include "RNA_access.hh"
34#include "RNA_prototypes.hh"
35
36#include "MOD_ui_common.hh"
37#include "MOD_util.hh"
38
39#include "eigen_capi.h"
40
41enum {
50};
51
52struct LaplacianSystem {
55 int verts_num;
59 int repeat;
63 float (*co)[3];
65 float (*no)[3];
67 float (*delta)[3];
73 uint (*tris)[3];
88};
89
91{
92 LaplacianSystem *sys = MEM_cnew<LaplacianSystem>(__func__);
93
94 sys->is_matrix_computed = false;
95 sys->has_solution = false;
96 sys->verts_num = 0;
97 sys->edges_num = 0;
98 sys->anchors_num = 0;
99 sys->tris_num = 0;
100 sys->repeat = 1;
101 sys->anchor_grp_name[0] = '\0';
102
103 return sys;
104}
105
107 int edges_num,
108 int tris_num,
109 int anchors_num,
110 const char defgrpName[64],
111 int iterations)
112{
114
115 sys->is_matrix_computed = false;
116 sys->has_solution = false;
117 sys->verts_num = verts_num;
118 sys->edges_num = edges_num;
119 sys->tris_num = tris_num;
120 sys->anchors_num = anchors_num;
121 sys->repeat = iterations;
122 STRNCPY(sys->anchor_grp_name, defgrpName);
123 sys->co = static_cast<float(*)[3]>(MEM_malloc_arrayN(verts_num, sizeof(float[3]), __func__));
124 sys->no = static_cast<float(*)[3]>(MEM_calloc_arrayN(verts_num, sizeof(float[3]), __func__));
125 sys->delta = static_cast<float(*)[3]>(MEM_calloc_arrayN(verts_num, sizeof(float[3]), __func__));
126 sys->tris = static_cast<uint(*)[3]>(MEM_malloc_arrayN(tris_num, sizeof(int[3]), __func__));
127 sys->index_anchors = static_cast<int *>(MEM_malloc_arrayN((anchors_num), sizeof(int), __func__));
128 sys->unit_verts = static_cast<int *>(MEM_calloc_arrayN(verts_num, sizeof(int), __func__));
129 return sys;
130}
131
133{
134 MEM_SAFE_FREE(sys->co);
135 MEM_SAFE_FREE(sys->no);
136 MEM_SAFE_FREE(sys->delta);
137 MEM_SAFE_FREE(sys->tris);
144
145 if (sys->context) {
147 }
148 MEM_SAFE_FREE(sys);
149}
150
151static void createFaceRingMap(const int mvert_tot,
153 blender::Span<int> corner_verts,
154 MeshElemMap **r_map,
155 int **r_indices)
156{
157 int indices_num = 0;
158 int *indices, *index_iter;
159 MeshElemMap *map = MEM_cnew_array<MeshElemMap>(mvert_tot, __func__);
160
161 for (const int i : corner_tris.index_range()) {
162 const blender::int3 &tri = corner_tris[i];
163 for (int j = 0; j < 3; j++) {
164 const int v_index = corner_verts[tri[j]];
165 map[v_index].count++;
166 indices_num++;
167 }
168 }
169 indices = MEM_cnew_array<int>(indices_num, __func__);
170 index_iter = indices;
171 for (int i = 0; i < mvert_tot; i++) {
172 map[i].indices = index_iter;
173 index_iter += map[i].count;
174 map[i].count = 0;
175 }
176 for (const int i : corner_tris.index_range()) {
177 const blender::int3 &tri = corner_tris[i];
178 for (int j = 0; j < 3; j++) {
179 const int v_index = corner_verts[tri[j]];
180 map[v_index].indices[map[v_index].count] = i;
181 map[v_index].count++;
182 }
183 }
184 *r_map = map;
185 *r_indices = indices;
186}
187
188static void createVertRingMap(const int mvert_tot,
190 MeshElemMap **r_map,
191 int **r_indices)
192{
193 MeshElemMap *map = MEM_cnew_array<MeshElemMap>(mvert_tot, __func__);
194 int i, vid[2], indices_num = 0;
195 int *indices, *index_iter;
196
197 for (const int i : edges.index_range()) {
198 vid[0] = edges[i][0];
199 vid[1] = edges[i][1];
200 map[vid[0]].count++;
201 map[vid[1]].count++;
202 indices_num += 2;
203 }
204 indices = MEM_cnew_array<int>(indices_num, __func__);
205 index_iter = indices;
206 for (i = 0; i < mvert_tot; i++) {
207 map[i].indices = index_iter;
208 index_iter += map[i].count;
209 map[i].count = 0;
210 }
211 for (const int i : edges.index_range()) {
212 vid[0] = edges[i][0];
213 vid[1] = edges[i][1];
214 map[vid[0]].indices[map[vid[0]].count] = vid[1];
215 map[vid[0]].count++;
216 map[vid[1]].indices[map[vid[1]].count] = vid[0];
217 map[vid[1]].count++;
218 }
219 *r_map = map;
220 *r_indices = indices;
221}
222
256{
257 float no[3];
258 float w2, w3;
259 int i = 3, j, ti;
260 int idv[3];
261
262 for (ti = 0; ti < sys->tris_num; ti++) {
263 const uint *vidt = sys->tris[ti];
264 const float *co[3];
265
266 co[0] = sys->co[vidt[0]];
267 co[1] = sys->co[vidt[1]];
268 co[2] = sys->co[vidt[2]];
269
270 normal_tri_v3(no, UNPACK3(co));
271 add_v3_v3(sys->no[vidt[0]], no);
272 add_v3_v3(sys->no[vidt[1]], no);
273 add_v3_v3(sys->no[vidt[2]], no);
274
275 for (j = 0; j < 3; j++) {
276 const float *v1, *v2, *v3;
277
278 idv[0] = vidt[j];
279 idv[1] = vidt[(j + 1) % i];
280 idv[2] = vidt[(j + 2) % i];
281
282 v1 = sys->co[idv[0]];
283 v2 = sys->co[idv[1]];
284 v3 = sys->co[idv[2]];
285
286 w2 = cotangent_tri_weight_v3(v3, v1, v2);
287 w3 = cotangent_tri_weight_v3(v2, v3, v1);
288
289 sys->delta[idv[0]][0] += v1[0] * (w2 + w3);
290 sys->delta[idv[0]][1] += v1[1] * (w2 + w3);
291 sys->delta[idv[0]][2] += v1[2] * (w2 + w3);
292
293 sys->delta[idv[0]][0] -= v2[0] * w2;
294 sys->delta[idv[0]][1] -= v2[1] * w2;
295 sys->delta[idv[0]][2] -= v2[2] * w2;
296
297 sys->delta[idv[0]][0] -= v3[0] * w3;
298 sys->delta[idv[0]][1] -= v3[1] * w3;
299 sys->delta[idv[0]][2] -= v3[2] * w3;
300
301 EIG_linear_solver_matrix_add(sys->context, idv[0], idv[1], -w2);
302 EIG_linear_solver_matrix_add(sys->context, idv[0], idv[2], -w3);
303 EIG_linear_solver_matrix_add(sys->context, idv[0], idv[0], w2 + w3);
304 }
305 }
306}
307
309{
310 int vid, *vidn = nullptr;
311 float minj, mjt, qj[3], vj[3];
312 int i, j, ln;
313
314 for (i = 0; i < sys->verts_num; i++) {
315 normalize_v3(sys->no[i]);
316 vidn = sys->ringv_map[i].indices;
317 ln = sys->ringv_map[i].count;
318 minj = 1000000.0f;
319 for (j = 0; j < ln; j++) {
320 vid = vidn[j];
321 copy_v3_v3(qj, sys->co[vid]);
322 sub_v3_v3v3(vj, qj, sys->co[i]);
323 normalize_v3(vj);
324 mjt = fabsf(dot_v3v3(vj, sys->no[i]));
325 if (mjt < minj) {
326 minj = mjt;
327 sys->unit_verts[i] = vidn[j];
328 }
329 }
330 }
331}
332
334{
335 float alpha, beta, gamma;
336 float pj[3], ni[3], di[3];
337 float uij[3], dun[3], e2[3], pi[3], fni[3], vn[3][3];
338 int i, j, fidn_num, k, fi;
339 int *fidn;
340
341 for (i = 0; i < sys->verts_num; i++) {
342 copy_v3_v3(pi, sys->co[i]);
343 copy_v3_v3(ni, sys->no[i]);
344 k = sys->unit_verts[i];
345 copy_v3_v3(pj, sys->co[k]);
346 sub_v3_v3v3(uij, pj, pi);
347 mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni));
348 sub_v3_v3(uij, dun);
349 normalize_v3(uij);
350 cross_v3_v3v3(e2, ni, uij);
351 copy_v3_v3(di, sys->delta[i]);
352 alpha = dot_v3v3(ni, di);
353 beta = dot_v3v3(uij, di);
354 gamma = dot_v3v3(e2, di);
355
356 pi[0] = EIG_linear_solver_variable_get(sys->context, 0, i);
357 pi[1] = EIG_linear_solver_variable_get(sys->context, 1, i);
358 pi[2] = EIG_linear_solver_variable_get(sys->context, 2, i);
359 zero_v3(ni);
360 fidn_num = sys->ringf_map[i].count;
361 for (fi = 0; fi < fidn_num; fi++) {
362 const uint *vin;
363 fidn = sys->ringf_map[i].indices;
364 vin = sys->tris[fidn[fi]];
365 for (j = 0; j < 3; j++) {
366 vn[j][0] = EIG_linear_solver_variable_get(sys->context, 0, vin[j]);
367 vn[j][1] = EIG_linear_solver_variable_get(sys->context, 1, vin[j]);
368 vn[j][2] = EIG_linear_solver_variable_get(sys->context, 2, vin[j]);
369 if (vin[j] == sys->unit_verts[i]) {
370 copy_v3_v3(pj, vn[j]);
371 }
372 }
373
374 normal_tri_v3(fni, UNPACK3(vn));
375 add_v3_v3(ni, fni);
376 }
377
378 normalize_v3(ni);
379 sub_v3_v3v3(uij, pj, pi);
380 mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni));
381 sub_v3_v3(uij, dun);
382 normalize_v3(uij);
383 cross_v3_v3v3(e2, ni, uij);
384 fni[0] = alpha * ni[0] + beta * uij[0] + gamma * e2[0];
385 fni[1] = alpha * ni[1] + beta * uij[1] + gamma * e2[1];
386 fni[2] = alpha * ni[2] + beta * uij[2] + gamma * e2[2];
387
388 if (len_squared_v3(fni) > FLT_EPSILON) {
392 }
393 else {
397 }
398 }
399}
400
401static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
402{
403 int vid, i, j, n, na;
404 n = sys->verts_num;
405 na = sys->anchors_num;
406
407 if (!sys->is_matrix_computed) {
408 sys->context = EIG_linear_least_squares_solver_new(n + na, n, 3);
409
410 for (i = 0; i < n; i++) {
411 EIG_linear_solver_variable_set(sys->context, 0, i, sys->co[i][0]);
412 EIG_linear_solver_variable_set(sys->context, 1, i, sys->co[i][1]);
413 EIG_linear_solver_variable_set(sys->context, 2, i, sys->co[i][2]);
414 }
415 for (i = 0; i < na; i++) {
416 vid = sys->index_anchors[i];
417 EIG_linear_solver_variable_set(sys->context, 0, vid, vertexCos[vid][0]);
418 EIG_linear_solver_variable_set(sys->context, 1, vid, vertexCos[vid][1]);
419 EIG_linear_solver_variable_set(sys->context, 2, vid, vertexCos[vid][2]);
420 }
421
424
425 for (i = 0; i < n; i++) {
429 }
430 for (i = 0; i < na; i++) {
431 vid = sys->index_anchors[i];
432 EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]);
433 EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]);
434 EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]);
435 EIG_linear_solver_matrix_add(sys->context, n + i, vid, 1.0f);
436 }
438 sys->has_solution = true;
439
440 for (j = 1; j <= sys->repeat; j++) {
442
443 for (i = 0; i < na; i++) {
444 vid = sys->index_anchors[i];
445 EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]);
446 EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]);
447 EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]);
448 }
449
450 if (!EIG_linear_solver_solve(sys->context)) {
451 sys->has_solution = false;
452 break;
453 }
454 }
455 if (sys->has_solution) {
456 for (vid = 0; vid < sys->verts_num; vid++) {
457 vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid);
458 vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid);
459 vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid);
460 }
461 }
462 else {
463 sys->has_solution = false;
464 }
465 }
466 else {
467 sys->has_solution = false;
468 }
469 sys->is_matrix_computed = true;
470 }
471 else if (sys->has_solution) {
472 for (i = 0; i < n; i++) {
476 }
477 for (i = 0; i < na; i++) {
478 vid = sys->index_anchors[i];
479 EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]);
480 EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]);
481 EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]);
482 EIG_linear_solver_matrix_add(sys->context, n + i, vid, 1.0f);
483 }
484
486 sys->has_solution = true;
487 for (j = 1; j <= sys->repeat; j++) {
489
490 for (i = 0; i < na; i++) {
491 vid = sys->index_anchors[i];
492 EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]);
493 EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]);
494 EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]);
495 }
496 if (!EIG_linear_solver_solve(sys->context)) {
497 sys->has_solution = false;
498 break;
499 }
500 }
501 if (sys->has_solution) {
502 for (vid = 0; vid < sys->verts_num; vid++) {
503 vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid);
504 vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid);
505 vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid);
506 }
507 }
508 else {
509 sys->has_solution = false;
510 }
511 }
512 else {
513 sys->has_solution = false;
514 }
515 }
516}
517
519{
520 int defgrp_index;
521 const MDeformVert *dvert = nullptr;
522
523 MOD_get_vgroup(ob, mesh, lmd->anchor_grp_name, &dvert, &defgrp_index);
524
525 return (dvert != nullptr);
526}
527
528static void initSystem(
529 LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num)
530{
531 int i;
532 int defgrp_index;
533 int anchors_num;
534 float wpaint;
535 const MDeformVert *dvert = nullptr;
536 const MDeformVert *dv = nullptr;
537 LaplacianSystem *sys;
538 const bool invert_vgroup = (lmd->flag & MOD_LAPLACIANDEFORM_INVERT_VGROUP) != 0;
539
540 if (isValidVertexGroup(lmd, ob, mesh)) {
541 int *index_anchors = static_cast<int *>(
542 MEM_malloc_arrayN(verts_num, sizeof(int), __func__)); /* Over-allocate. */
543
544 STACK_DECLARE(index_anchors);
545
546 STACK_INIT(index_anchors, verts_num);
547
548 MOD_get_vgroup(ob, mesh, lmd->anchor_grp_name, &dvert, &defgrp_index);
549 BLI_assert(dvert != nullptr);
550 dv = dvert;
551 for (i = 0; i < verts_num; i++) {
552 wpaint = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) :
553 BKE_defvert_find_weight(dv, defgrp_index);
554 dv++;
555 if (wpaint > 0.0f) {
556 STACK_PUSH(index_anchors, i);
557 }
558 }
559
560 const blender::Span<blender::int2> edges = mesh->edges();
561 const blender::Span<int> corner_verts = mesh->corner_verts();
562 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
563
564 anchors_num = STACK_SIZE(index_anchors);
565 lmd->cache_system = initLaplacianSystem(verts_num,
566 edges.size(),
567 corner_tris.size(),
568 anchors_num,
569 lmd->anchor_grp_name,
570 lmd->repeat);
571 sys = (LaplacianSystem *)lmd->cache_system;
572 memcpy(sys->index_anchors, index_anchors, sizeof(int) * anchors_num);
573 memcpy(sys->co, vertexCos, sizeof(float[3]) * verts_num);
574 MEM_freeN(index_anchors);
575 lmd->vertexco = static_cast<float *>(MEM_malloc_arrayN(verts_num, sizeof(float[3]), __func__));
576 memcpy(lmd->vertexco, vertexCos, sizeof(float[3]) * verts_num);
577 lmd->verts_num = verts_num;
578
580 mesh->verts_num, corner_tris, corner_verts, &sys->ringf_map, &sys->ringf_indices);
581 createVertRingMap(mesh->verts_num, edges, &sys->ringv_map, &sys->ringv_indices);
582
583 for (i = 0; i < sys->tris_num; i++) {
584 sys->tris[i][0] = corner_verts[corner_tris[i][0]];
585 sys->tris[i][1] = corner_verts[corner_tris[i][1]];
586 sys->tris[i][2] = corner_verts[corner_tris[i][2]];
587 }
588 }
589}
590
592 Object *ob,
593 Mesh *mesh,
594 int verts_num)
595{
596 int i;
597 int defgrp_index;
598 int anchors_num = 0;
599 float wpaint;
600 const MDeformVert *dvert = nullptr;
601 const MDeformVert *dv = nullptr;
603 const bool invert_vgroup = (lmd->flag & MOD_LAPLACIANDEFORM_INVERT_VGROUP) != 0;
604
605 if (sys->verts_num != verts_num) {
607 }
608 if (sys->edges_num != mesh->edges_num) {
610 }
611 if (!STREQ(lmd->anchor_grp_name, sys->anchor_grp_name)) {
613 }
614 MOD_get_vgroup(ob, mesh, lmd->anchor_grp_name, &dvert, &defgrp_index);
615 if (!dvert) {
617 }
618 dv = dvert;
619 for (i = 0; i < verts_num; i++) {
620 wpaint = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) :
621 BKE_defvert_find_weight(dv, defgrp_index);
622 dv++;
623 if (wpaint > 0.0f) {
624 anchors_num++;
625 }
626 }
627 if (sys->anchors_num != anchors_num) {
629 }
630
632}
633
635 LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num)
636{
637 float(*filevertexCos)[3];
638 int sysdif;
639 LaplacianSystem *sys = nullptr;
640 filevertexCos = nullptr;
641 if (!(lmd->flag & MOD_LAPLACIANDEFORM_BIND)) {
642 if (lmd->cache_system) {
643 sys = static_cast<LaplacianSystem *>(lmd->cache_system);
645 lmd->cache_system = nullptr;
646 }
647 lmd->verts_num = 0;
649 return;
650 }
651 if (lmd->cache_system) {
652 sysdif = isSystemDifferent(lmd, ob, mesh, verts_num);
653 sys = static_cast<LaplacianSystem *>(lmd->cache_system);
654 if (sysdif) {
656 filevertexCos = static_cast<float(*)[3]>(
657 MEM_malloc_arrayN(verts_num, sizeof(float[3]), __func__));
658 memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * verts_num);
660 lmd->verts_num = 0;
662 lmd->cache_system = nullptr;
663 initSystem(lmd, ob, mesh, filevertexCos, verts_num);
664 sys = static_cast<LaplacianSystem *>(lmd->cache_system); /* may have been reallocated */
665 MEM_SAFE_FREE(filevertexCos);
666 if (sys) {
667 laplacianDeformPreview(sys, vertexCos);
668 }
669 }
670 else {
671 if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) {
673 ob, &lmd->modifier, "Vertices changed from %d to %d", lmd->verts_num, verts_num);
674 }
675 else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) {
677 ob, &lmd->modifier, "Edges changed from %d to %d", sys->edges_num, mesh->edges_num);
678 }
679 else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) {
681 &lmd->modifier,
682 "Vertex group '%s' is not valid, or maybe empty",
683 sys->anchor_grp_name);
684 }
685 }
686 }
687 else {
688 sys->repeat = lmd->repeat;
689 laplacianDeformPreview(sys, vertexCos);
690 }
691 }
692 else {
693 if (!isValidVertexGroup(lmd, ob, mesh)) {
695 &lmd->modifier,
696 "Vertex group '%s' is not valid, or maybe empty",
697 lmd->anchor_grp_name);
698 lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
699 }
700 else if (lmd->verts_num > 0 && lmd->verts_num == verts_num) {
701 filevertexCos = static_cast<float(*)[3]>(
702 MEM_malloc_arrayN(verts_num, sizeof(float[3]), "TempDeformCoordinates"));
703 memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * verts_num);
705 lmd->verts_num = 0;
706 initSystem(lmd, ob, mesh, filevertexCos, verts_num);
707 sys = static_cast<LaplacianSystem *>(lmd->cache_system);
708 MEM_SAFE_FREE(filevertexCos);
709 laplacianDeformPreview(sys, vertexCos);
710 }
711 else {
712 initSystem(lmd, ob, mesh, vertexCos, verts_num);
713 sys = static_cast<LaplacianSystem *>(lmd->cache_system);
714 laplacianDeformPreview(sys, vertexCos);
715 }
716 }
717 if (sys && sys->is_matrix_computed && !sys->has_solution) {
718 BKE_modifier_set_error(ob, &lmd->modifier, "The system did not find a solution");
719 }
720}
721
730
731static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
732{
735
737
738 tlmd->vertexco = static_cast<float *>(MEM_dupallocN(lmd->vertexco));
739 tlmd->cache_system = nullptr;
740}
741
742static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
743{
745 if (lmd->anchor_grp_name[0]) {
746 return false;
747 }
748 return true;
749}
750
751static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
752{
754
755 if (lmd->anchor_grp_name[0] != '\0') {
756 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
757 }
758}
759
761 const ModifierEvalContext *ctx,
762 Mesh *mesh,
764{
766 ctx->object,
767 mesh,
768 reinterpret_cast<float(*)[3]>(positions.data()),
769 positions.size());
770}
771
772static void free_data(ModifierData *md)
773{
776 if (sys) {
778 }
780 lmd->verts_num = 0;
781}
782
783static void panel_draw(const bContext * /*C*/, Panel *panel)
784{
785 uiLayout *row;
786 uiLayout *layout = panel->layout;
787
788 PointerRNA ob_ptr;
790
791 bool is_bind = RNA_boolean_get(ptr, "is_bind");
792 bool has_vertex_group = RNA_string_length(ptr, "vertex_group") != 0;
793
794 uiLayoutSetPropSep(layout, true);
795
796 uiItemR(layout, ptr, "iterations", UI_ITEM_NONE, nullptr, ICON_NONE);
797
798 modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
799
800 uiItemS(layout);
801
802 row = uiLayoutRow(layout, true);
803 uiLayoutSetEnabled(row, has_vertex_group);
804 uiItemO(row,
805 is_bind ? IFACE_("Unbind") : IFACE_("Bind"),
806 ICON_NONE,
807 "OBJECT_OT_laplaciandeform_bind");
808
809 modifier_panel_end(layout, ptr);
810}
811
812static void panel_register(ARegionType *region_type)
813{
815}
816
817static void blend_write(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
818{
820 const bool is_undo = BLO_write_is_undo(writer);
821
822 if (ID_IS_OVERRIDE_LIBRARY(id_owner) && !is_undo) {
823 BLI_assert(!ID_IS_LINKED(id_owner));
824 const bool is_local = (md->flag & eModifierFlag_OverrideLibrary_Local) != 0;
825 if (!is_local) {
826 /* Modifier coming from linked data cannot be bound from an override, so we can remove all
827 * binding data, can save a significant amount of memory. */
828 lmd.verts_num = 0;
829 lmd.vertexco = nullptr;
830 }
831 }
832
834
835 if (lmd.vertexco != nullptr) {
836 BLO_write_float3_array(writer, lmd.verts_num, lmd.vertexco);
837 }
838}
839
840static void blend_read(BlendDataReader *reader, ModifierData *md)
841{
843
844 BLO_read_float3_array(reader, lmd->verts_num, &lmd->vertexco);
845 lmd->cache_system = nullptr;
846}
847
849 /*idname*/ "LaplacianDeform",
850 /*name*/ N_("LaplacianDeform"),
851 /*struct_name*/ "LaplacianDeformModifierData",
852 /*struct_size*/ sizeof(LaplacianDeformModifierData),
853 /*srna*/ &RNA_LaplacianDeformModifier,
856 /*icon*/ ICON_MOD_MESHDEFORM,
857 /*copy_data*/ copy_data,
858
859 /*deform_verts*/ deform_verts,
860 /*deform_matrices*/ nullptr,
861 /*deform_verts_EM*/ nullptr,
862 /*deform_matrices_EM*/ nullptr,
863 /*modify_mesh*/ nullptr,
864 /*modify_geometry_set*/ nullptr,
865
866 /*init_data*/ init_data,
867 /*required_data_mask*/ required_data_mask,
868 /*free_data*/ free_data,
869 /*is_disabled*/ is_disabled,
870 /*update_depsgraph*/ nullptr,
871 /*depends_on_time*/ nullptr,
872 /*depends_on_normals*/ nullptr,
873 /*foreach_ID_link*/ nullptr,
874 /*foreach_tex_link*/ nullptr,
875 /*free_runtime_data*/ nullptr,
876 /*panel_register*/ panel_register,
877 /*blend_write*/ blend_write,
878 /*blend_read*/ blend_read,
879 /*foreach_cache*/ nullptr,
880};
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
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition BLI_assert.h:50
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:196
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:39
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
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 void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
#define STRNCPY(dst, src)
Definition BLI_string.h:593
unsigned int uint
#define UNPACK3(a)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
#define STACK_PUSH(stack, val)
#define STACK_DECLARE(stack)
#define STACK_SIZE(stack)
#define STACK_INIT(stack, stack_num)
void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition readfile.cc:4977
void BLO_write_float3_array(BlendWriter *writer, uint num, const float *data_ptr)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLO_write_struct_at_address(writer, struct_name, address, data_ptr)
#define IFACE_(msgid)
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
#define CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
@ eModifierFlag_OverrideLibrary_Local
struct LaplacianDeformModifierData LaplacianDeformModifierData
@ eModifierType_LaplacianDeform
@ MOD_LAPLACIANDEFORM_BIND
@ MOD_LAPLACIANDEFORM_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 LaplacianSystem * newLaplacianSystem()
ModifierTypeInfo modifierType_LaplacianDeform
static void laplacianDeformPreview(LaplacianSystem *sys, float(*vertexCos)[3])
static bool isValidVertexGroup(LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh)
static int isSystemDifferent(LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, int verts_num)
static void deleteLaplacianSystem(LaplacianSystem *sys)
static void panel_register(ARegionType *region_type)
static void initLaplacianMatrix(LaplacianSystem *sys)
static LaplacianSystem * initLaplacianSystem(int verts_num, int edges_num, int tris_num, int anchors_num, const char defgrpName[64], int iterations)
@ LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP
@ LAPDEFORM_SYSTEM_IS_DIFFERENT
@ LAPDEFORM_SYSTEM_ONLY_CHANGE_MESH
@ LAPDEFORM_SYSTEM_CHANGE_EDGES
@ LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP
@ LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS
@ LAPDEFORM_SYSTEM_CHANGE_VERTEXES
@ LAPDEFORM_SYSTEM_NOT_CHANGE
static void free_data(ModifierData *md)
static void blend_read(BlendDataReader *reader, ModifierData *md)
static void createVertRingMap(const int mvert_tot, const blender::Span< blender::int2 > edges, MeshElemMap **r_map, int **r_indices)
static void computeImplictRotations(LaplacianSystem *sys)
static void panel_draw(const bContext *, Panel *panel)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static void blend_write(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float(*vertexCos)[3], int verts_num)
static void rotateDifferentialCoordinates(LaplacianSystem *sys)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static void LaplacianDeformModifier_do(LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float(*vertexCos)[3], int verts_num)
static void createFaceRingMap(const int mvert_tot, blender::Span< blender::int3 > corner_tris, blender::Span< int > corner_verts, MeshElemMap **r_map, int **r_indices)
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 uiLayoutSetEnabled(uiLayout *layout, bool enabled)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
#define UI_ITEM_NONE
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
constexpr int64_t count(const T &value) const
Definition BLI_span.hh:301
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
#define fabsf(x)
draw_view in_light_buf[] float
static ushort indices[]
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_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:43
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
int RNA_string_length(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition DNA_ID.h:413
MeshElemMap * ringv_map
MeshElemMap * ringf_map
LinearSolver * context
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