Blender V5.0
MOD_meshdeform.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
8
9#include "BLI_utildefines.h"
10
11#include "BLI_array.hh"
12#include "BLI_math_matrix.h"
13#include "BLI_math_vector.h"
14#include "BLI_simd.hh"
15#include "BLI_task.h"
16
17#include "BLT_translation.hh"
18
19#include "DNA_defaults.h"
20#include "DNA_meshdata_types.h"
21#include "DNA_object_types.h"
22#include "DNA_screen_types.h"
23
24#include "BKE_deform.hh"
25#include "BKE_lib_query.hh"
26#include "BKE_mesh_wrapper.hh"
27#include "BKE_modifier.hh"
28
30#include "UI_resources.hh"
31
32#include "BLO_read_write.hh"
33
34#include "RNA_access.hh"
35#include "RNA_prototypes.hh"
36
37#include "MEM_guardedalloc.h"
38
39#include "DEG_depsgraph.hh"
40
41#include "MOD_ui_common.hh"
42#include "MOD_util.hh"
43
52
71
72static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
73{
74 using namespace blender;
75 const MeshDeformModifierData *mmd = (const MeshDeformModifierData *)md;
77
79
82 &tmmd->bindinfluences,
86 &tmmd->bindoffsets,
90 &tmmd->bindcagecos,
93 mmd->dyngrid, mmd->dyngrid_sharing_info, &tmmd->dyngrid, &tmmd->dyngrid_sharing_info);
96 &tmmd->dyninfluences,
100 if (mmd->bindweights) {
101 tmmd->bindweights = static_cast<float *>(MEM_dupallocN(mmd->bindweights)); /* deprecated */
102 }
103 if (mmd->bindcos) {
104 tmmd->bindcos = static_cast<float *>(MEM_dupallocN(mmd->bindcos)); /* deprecated */
105 }
106}
107
108static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
109{
111
112 /* Ask for vertex-groups if we need them. */
113 if (mmd->defgrp_name[0] != '\0') {
114 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
115 }
116}
117
118static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
119{
121
122 /* The object type check is only needed here in case we have a placeholder
123 * object assigned (because the library containing the mesh is missing).
124 *
125 * In other cases it should be impossible to have a type mismatch.
126 */
127 return !mmd->object || mmd->object->type != OB_MESH;
128}
129
130static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
131{
133
134 walk(user_data, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
135}
136
138{
140 if (mmd->object != nullptr) {
141 DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Mesh Deform Modifier");
142 DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_GEOMETRY, "Mesh Deform Modifier");
143 }
144 /* We need our own transformation as well. */
145 DEG_add_depends_on_transform_relation(ctx->node, "Mesh Deform Modifier");
146}
147
148static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3], float vec[3])
149{
150 MDefCell *cell;
151 MDefInfluence *inf;
152 float gridvec[3], dvec[3], ivec[3], wx, wy, wz;
153 float weight, cageweight, totweight, *cageco;
154 int i, j, a, x, y, z, size;
155#if BLI_HAVE_SSE2
156 __m128 co = _mm_setzero_ps();
157#else
158 float co[3] = {0.0f, 0.0f, 0.0f};
159#endif
160
161 totweight = 0.0f;
162 size = mmd->dyngridsize;
163
164 for (i = 0; i < 3; i++) {
165 gridvec[i] = (vec[i] - mmd->dyncellmin[i] - mmd->dyncellwidth * 0.5f) / mmd->dyncellwidth;
166 ivec[i] = int(gridvec[i]);
167 dvec[i] = gridvec[i] - ivec[i];
168 }
169
170 for (i = 0; i < 8; i++) {
171 if (i & 1) {
172 x = ivec[0] + 1;
173 wx = dvec[0];
174 }
175 else {
176 x = ivec[0];
177 wx = 1.0f - dvec[0];
178 }
179
180 if (i & 2) {
181 y = ivec[1] + 1;
182 wy = dvec[1];
183 }
184 else {
185 y = ivec[1];
186 wy = 1.0f - dvec[1];
187 }
188
189 if (i & 4) {
190 z = ivec[2] + 1;
191 wz = dvec[2];
192 }
193 else {
194 z = ivec[2];
195 wz = 1.0f - dvec[2];
196 }
197
198 CLAMP(x, 0, size - 1);
199 CLAMP(y, 0, size - 1);
200 CLAMP(z, 0, size - 1);
201
202 a = x + y * size + z * size * size;
203 weight = wx * wy * wz;
204
205 cell = &mmd->dyngrid[a];
206 inf = mmd->dyninfluences + cell->offset;
207 for (j = 0; j < cell->influences_num; j++, inf++) {
208 cageco = dco[inf->vertex];
209 cageweight = weight * inf->weight;
210#if BLI_HAVE_SSE2
211 {
212 __m128 cageweight_r = _mm_set1_ps(cageweight);
213 /* This will load one extra element, this is ok because
214 * we ignore that part of register anyway.
215 */
216 __m128 cageco_r = _mm_loadu_ps(cageco);
217 co = _mm_add_ps(co, _mm_mul_ps(cageco_r, cageweight_r));
218 }
219#else
220 co[0] += cageweight * cageco[0];
221 co[1] += cageweight * cageco[1];
222 co[2] += cageweight * cageco[2];
223#endif
224 totweight += cageweight;
225 }
226 }
227
228#if BLI_HAVE_SSE2
229 copy_v3_v3(vec, (float *)&co);
230#else
231 copy_v3_v3(vec, co);
232#endif
233
234 return totweight;
235}
236
246
247static void meshdeform_vert_task(void *__restrict userdata,
248 const int iter,
249 const TaskParallelTLS *__restrict /*tls*/)
250{
251 MeshdeformUserdata *data = static_cast<MeshdeformUserdata *>(userdata);
252 /*const*/ MeshDeformModifierData *mmd = data->mmd;
253 const MDeformVert *dvert = data->dvert;
254 const int defgrp_index = data->defgrp_index;
255 const int *offsets = mmd->bindoffsets;
256 const MDefInfluence *__restrict influences = mmd->bindinfluences;
257 /*const*/ float (*__restrict dco)[3] = data->dco;
258 float (*vertexCos)[3] = data->vertexCos;
259 float co[3];
260 float weight, totweight, fac = 1.0f;
261
262 if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
263 if (!mmd->dynverts[iter]) {
264 return;
265 }
266 }
267
268 if (dvert) {
269 fac = BKE_defvert_find_weight(&dvert[iter], defgrp_index);
270
271 if (mmd->flag & MOD_MDEF_INVERT_VGROUP) {
272 fac = 1.0f - fac;
273 }
274
275 if (fac <= 0.0f) {
276 return;
277 }
278 }
279
280 if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
281 /* transform coordinate into cage's local space */
282 mul_v3_m4v3(co, data->cagemat, vertexCos[iter]);
283 totweight = meshdeform_dynamic_bind(mmd, dco, co);
284 }
285 else {
286 totweight = 0.0f;
287 zero_v3(co);
288 int start = offsets[iter];
289 int end = offsets[iter + 1];
290
291 for (int a = start; a < end; a++) {
292 weight = influences[a].weight;
293 madd_v3_v3fl(co, dco[influences[a].vertex], weight);
294 totweight += weight;
295 }
296 }
297
298 if (totweight > 0.0f) {
299 mul_v3_fl(co, fac / totweight);
300 mul_m3_v3(data->icagemat, co);
301 add_v3_v3(vertexCos[iter], co);
302 }
303}
304
306 const ModifierEvalContext *ctx,
307 Mesh *mesh,
308 float (*vertexCos)[3],
309 const int verts_num)
310{
312 Object *ob = ctx->object;
313
314 Mesh *cagemesh;
315 const MDeformVert *dvert = nullptr;
316 float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
317 const float (*bindcagecos)[3];
318 int a, cage_verts_num, defgrp_index;
320
321 static int recursive_bind_sentinel = 0;
322
323 if (mmd->object == nullptr || (mmd->bindcagecos == nullptr && mmd->bindfunc == nullptr)) {
324 return;
325 }
326
327 /* Get cage mesh.
328 *
329 * Only do this is the target object is in edit mode by itself, meaning
330 * we don't allow linked edit meshes here.
331 * This is because editbmesh_get_mesh_cage_and_final() might easily
332 * conflict with the thread which evaluates object which is in the edit
333 * mode for this mesh.
334 *
335 * We'll support this case once granular dependency graph is landed.
336 */
337 Object *ob_target = mmd->object;
339 if (cagemesh == nullptr) {
340 BKE_modifier_set_error(ctx->object, md, "Cannot get mesh from cage object");
341 return;
342 }
343
344 /* compute matrices to go in and out of cage object space */
345 invert_m4_m4(imat, ob_target->object_to_world().ptr());
346 mul_m4_m4m4(cagemat, imat, ob->object_to_world().ptr());
347 mul_m4_m4m4(cmat, mmd->bindmat, cagemat);
348 invert_m4_m4(iobmat, cmat);
349 copy_m3_m4(icagemat, iobmat);
350
351 /* bind weights if needed */
352 if (!mmd->bindcagecos) {
353 /* progress bar redraw can make this recursive. */
354 if (!DEG_is_active(ctx->depsgraph)) {
355 BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph");
356 return;
357 }
358 if (!recursive_bind_sentinel) {
359 recursive_bind_sentinel = 1;
360 mmd->bindfunc(ob, mmd, cagemesh, (float *)vertexCos, verts_num, cagemat);
361 recursive_bind_sentinel = 0;
362 }
363
364 return;
365 }
366
367 /* verify we have compatible weights */
368 cage_verts_num = BKE_mesh_wrapper_vert_len(cagemesh);
369
370 if (mmd->verts_num != verts_num) {
371 BKE_modifier_set_error(ob, md, "Vertices changed from %d to %d", mmd->verts_num, verts_num);
372 return;
373 }
374 if (mmd->cage_verts_num != cage_verts_num) {
376 ob, md, "Cage vertices changed from %d to %d", mmd->cage_verts_num, cage_verts_num);
377 return;
378 }
379 if (mmd->bindcagecos == nullptr) {
380 BKE_modifier_set_error(ob, md, "Bind data missing");
381 return;
382 }
383
384 /* We allocate 1 element extra to make it possible to
385 * load the values to SSE registers, which are float4.
386 */
387 blender::Array<blender::float3> dco(cage_verts_num + 1);
388 zero_v3(dco[cage_verts_num]);
389
390 /* setup deformation data */
391 BKE_mesh_wrapper_vert_coords_copy(cagemesh, dco.as_mutable_span().take_front(cage_verts_num));
392 bindcagecos = (const float (*)[3])mmd->bindcagecos;
393
394 for (a = 0; a < cage_verts_num; a++) {
395 /* Get cage vertex in world-space with binding transform. */
396 float co[3];
397 mul_v3_m4v3(co, mmd->bindmat, dco[a]);
398 /* compute difference with world space bind coord */
399 sub_v3_v3v3(dco[a], co, bindcagecos[a]);
400 }
401
402 MOD_get_vgroup(ob, mesh, mmd->defgrp_name, &dvert, &defgrp_index);
403
404 /* Initialize data to be pass to the for body function. */
405 data.mmd = mmd;
406 data.dvert = dvert;
407 data.dco = reinterpret_cast<float (*)[3]>(dco.data());
408 data.defgrp_index = defgrp_index;
409 data.vertexCos = vertexCos;
410 data.cagemat = cagemat;
411 data.icagemat = icagemat;
412
413 /* Do deformation. */
414 TaskParallelSettings settings;
416 settings.min_iter_per_thread = 16;
417 BLI_task_parallel_range(0, verts_num, &data, meshdeform_vert_task, &settings);
418}
419
421 const ModifierEvalContext *ctx,
422 Mesh *mesh,
424{
425 /* if next modifier needs original vertices */
426 MOD_previous_vcos_store(md, reinterpret_cast<float (*)[3]>(positions.data()));
428 md, ctx, mesh, reinterpret_cast<float (*)[3]>(positions.data()), positions.size());
429}
430
431#define MESHDEFORM_MIN_INFLUENCE 0.00001f
432
434{
435 using namespace blender;
437 float weight, totweight;
438 int influences_num, verts_num, cage_verts_num, a, b;
439
440 const float *weights = mmd->bindweights;
441 if (!weights) {
442 return;
443 }
444
445 verts_num = mmd->verts_num;
446 cage_verts_num = mmd->cage_verts_num;
447
448 /* count number of influences above threshold */
449 for (b = 0; b < verts_num; b++) {
450 for (a = 0; a < cage_verts_num; a++) {
451 weight = weights[a + b * cage_verts_num];
452
453 if (weight > MESHDEFORM_MIN_INFLUENCE) {
454 mmd->influences_num++;
455 }
456 }
457 }
458
459 /* allocate bind influences */
462 mmd->bindoffsets = MEM_calloc_arrayN<int>(size_t(verts_num) + 1, __func__);
464
465 /* write influences */
466 influences_num = 0;
467
468 for (b = 0; b < verts_num; b++) {
469 mmd->bindoffsets[b] = influences_num;
470 totweight = 0.0f;
471
472 /* sum total weight */
473 for (a = 0; a < cage_verts_num; a++) {
474 weight = weights[a + b * cage_verts_num];
475
476 if (weight > MESHDEFORM_MIN_INFLUENCE) {
477 totweight += weight;
478 }
479 }
480
481 /* assign weights normalized */
482 for (a = 0; a < cage_verts_num; a++) {
483 weight = weights[a + b * cage_verts_num];
484
485 if (weight > MESHDEFORM_MIN_INFLUENCE) {
486 mmd->bindinfluences[influences_num].weight = weight / totweight;
487 mmd->bindinfluences[influences_num].vertex = a;
488 influences_num++;
489 }
490 }
491 }
492
493 mmd->bindoffsets[b] = influences_num;
494
495 /* free */
497 mmd->bindweights = nullptr;
498}
499
500static void panel_draw(const bContext * /*C*/, Panel *panel)
501{
502 uiLayout *col;
503 uiLayout *layout = panel->layout;
504
505 PointerRNA ob_ptr;
507
508 bool is_bound = RNA_boolean_get(ptr, "is_bound");
509
510 layout->use_property_split_set(true);
511
512 col = &layout->column(true);
513 col->enabled_set(!is_bound);
514 col->prop(ptr, "object", UI_ITEM_NONE, std::nullopt, ICON_NONE);
515
516 modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", std::nullopt);
517
518 col = &layout->column(false);
519 col->enabled_set(!is_bound);
520 col->prop(ptr, "precision", UI_ITEM_NONE, std::nullopt, ICON_NONE);
521 col->prop(ptr, "use_dynamic_bind", UI_ITEM_NONE, std::nullopt, ICON_NONE);
522
523 layout->op("OBJECT_OT_meshdeform_bind", is_bound ? IFACE_("Unbind") : IFACE_("Bind"), ICON_NONE);
524
526}
527
528static void panel_register(ARegionType *region_type)
529{
531}
532
533static void blend_write(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
534{
536 const bool is_undo = BLO_write_is_undo(writer);
537
538 if (ID_IS_OVERRIDE_LIBRARY(id_owner) && !is_undo) {
539 BLI_assert(!ID_IS_LINKED(id_owner));
540 const bool is_local = (md->flag & eModifierFlag_OverrideLibrary_Local) != 0;
541 if (!is_local) {
542 /* Modifier coming from linked data cannot be bound from an override, so we can remove all
543 * binding data, can save a significant amount of memory. */
544 mmd.influences_num = 0;
545 mmd.bindinfluences = nullptr;
546 mmd.bindinfluences_sharing_info = nullptr;
547 mmd.verts_num = 0;
548 mmd.bindoffsets = nullptr;
549 mmd.bindoffsets_sharing_info = nullptr;
550 mmd.cage_verts_num = 0;
551 mmd.bindcagecos = nullptr;
552 mmd.bindcagecos_sharing_info = nullptr;
553 mmd.dyngridsize = 0;
554 mmd.dyngrid = nullptr;
555 mmd.dyngrid_sharing_info = nullptr;
556 mmd.influences_num = 0;
557 mmd.dyninfluences = nullptr;
558 mmd.dyninfluences_sharing_info = nullptr;
559 mmd.dynverts = nullptr;
560 mmd.dynverts_sharing_info = nullptr;
561 }
562 }
563
564 const int size = mmd.dyngridsize;
565
566 BLO_write_shared(writer,
567 mmd.bindinfluences,
568 sizeof(MDefInfluence) * mmd.influences_num,
570 [&]() {
571 BLO_write_struct_array(
572 writer, MDefInfluence, mmd.influences_num, mmd.bindinfluences);
573 });
574
575 /* NOTE: `bindoffset` is abusing `verts_num + 1` as its size, this becomes an incorrect value in
576 * case `verts_num == 0`, since `bindoffset` is then nullptr, not a size 1 allocated array. */
577 if (mmd.verts_num > 0) {
578 BLO_write_shared(writer,
579 mmd.bindoffsets,
580 sizeof(int) * (mmd.verts_num + 1),
582 [&]() { BLO_write_int32_array(writer, mmd.verts_num + 1, mmd.bindoffsets); });
583 }
584 else {
585 BLI_assert(mmd.bindoffsets == nullptr);
586 }
587
588 BLO_write_shared(writer,
589 mmd.bindcagecos,
590 sizeof(float[3]) * mmd.cage_verts_num,
592 [&]() { BLO_write_float3_array(writer, mmd.cage_verts_num, mmd.bindcagecos); });
594 writer, mmd.dyngrid, sizeof(MDefCell) * size * size * size, mmd.dyngrid_sharing_info, [&]() {
595 BLO_write_struct_array(writer, MDefCell, size * size * size, mmd.dyngrid);
596 });
597 BLO_write_shared(writer,
598 mmd.dyninfluences,
599 sizeof(MDefInfluence) * mmd.influences_num,
601 [&]() {
602 BLO_write_struct_array(
603 writer, MDefInfluence, mmd.influences_num, mmd.dyninfluences);
604 });
605 BLO_write_shared(writer,
606 mmd.dynverts,
607 sizeof(MDefInfluence) * mmd.verts_num,
609 [&]() { BLO_write_int32_array(writer, mmd.verts_num, mmd.dynverts); });
610
612}
613
614static void blend_read(BlendDataReader *reader, ModifierData *md)
615{
617 const int size = mmd->dyngridsize;
618
619 if (mmd->bindinfluences) {
621 BLO_read_struct_array(reader, MDefInfluence, mmd->influences_num, &mmd->bindinfluences);
622 return blender::implicit_sharing::info_for_mem_free(mmd->bindinfluences);
623 });
624 }
625
626 /* NOTE: `bindoffset` is abusing `verts_num + 1` as its size, this becomes an incorrect value in
627 * case `verts_num == 0`, since `bindoffset` is then nullptr, not a size 1 allocated array. */
628 if (mmd->verts_num > 0) {
629 if (mmd->bindoffsets) {
630 mmd->bindoffsets_sharing_info = BLO_read_shared(reader, &mmd->bindoffsets, [&]() {
631 BLO_read_int32_array(reader, mmd->verts_num + 1, &mmd->bindoffsets);
632 return blender::implicit_sharing::info_for_mem_free(mmd->bindoffsets);
633 });
634 }
635 }
636
637 if (mmd->bindcagecos) {
638 mmd->bindcagecos_sharing_info = BLO_read_shared(reader, &mmd->bindcagecos, [&]() {
639 BLO_read_float3_array(reader, mmd->cage_verts_num, &mmd->bindcagecos);
640 return blender::implicit_sharing::info_for_mem_free(mmd->bindcagecos);
641 });
642 }
643 if (mmd->dyngrid) {
644 mmd->dyngrid_sharing_info = BLO_read_shared(reader, &mmd->dyngrid, [&]() {
645 BLO_read_struct_array(reader, MDefCell, size * size * size, &mmd->dyngrid);
646 return blender::implicit_sharing::info_for_mem_free(mmd->dyngrid);
647 });
648 }
649 if (mmd->dyninfluences) {
650 mmd->dyninfluences_sharing_info = BLO_read_shared(reader, &mmd->dyninfluences, [&]() {
651 BLO_read_struct_array(reader, MDefInfluence, mmd->influences_num, &mmd->dyninfluences);
652 return blender::implicit_sharing::info_for_mem_free(mmd->dyninfluences);
653 });
654 }
655 if (mmd->dynverts) {
656 mmd->dynverts_sharing_info = BLO_read_shared(reader, &mmd->dynverts, [&]() {
657 BLO_read_int32_array(reader, mmd->verts_num, &mmd->dynverts);
658 return blender::implicit_sharing::info_for_mem_free(mmd->dynverts);
659 });
660 }
661
662 /* Deprecated storage. */
663 BLO_read_float_array(reader, mmd->verts_num, &mmd->bindweights);
664 BLO_read_float3_array(reader, mmd->cage_verts_num, &mmd->bindcos);
665}
666
668 /*idname*/ "MeshDeform",
669 /*name*/ N_("MeshDeform"),
670 /*struct_name*/ "MeshDeformModifierData",
671 /*struct_size*/ sizeof(MeshDeformModifierData),
672 /*srna*/ &RNA_MeshDeformModifier,
676 /*icon*/ ICON_MOD_MESHDEFORM,
677
678 /*copy_data*/ copy_data,
679
680 /*deform_verts*/ deform_verts,
681 /*deform_matrices*/ nullptr,
682 /*deform_verts_EM*/ nullptr,
683 /*deform_matrices_EM*/ nullptr,
684 /*modify_mesh*/ nullptr,
685 /*modify_geometry_set*/ nullptr,
686
687 /*init_data*/ init_data,
688 /*required_data_mask*/ required_data_mask,
689 /*free_data*/ free_data,
690 /*is_disabled*/ is_disabled,
691 /*update_depsgraph*/ update_depsgraph,
692 /*depends_on_time*/ nullptr,
693 /*depends_on_normals*/ nullptr,
694 /*foreach_ID_link*/ foreach_ID_link,
695 /*foreach_tex_link*/ nullptr,
696 /*free_runtime_data*/ nullptr,
697 /*panel_register*/ panel_register,
698 /*blend_write*/ blend_write,
699 /*blend_read*/ blend_read,
700 /*foreach_cache*/ nullptr,
701 /*foreach_working_space_color*/ nullptr,
702};
support for deformation groups and hooks.
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:774
@ IDWALK_CB_NOP
void BKE_mesh_wrapper_vert_coords_copy(const Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
int BKE_mesh_wrapper_vert_len(const Mesh *mesh)
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsVertexCosOnly
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:46
void mul_m3_v3(const float M[3][3], float r[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:221
#define CLAMP(a, b, c)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
void BLO_read_float3_array(BlendDataReader *reader, int64_t array_size, float **ptr_p)
Definition readfile.cc:5816
void BLO_read_float_array(BlendDataReader *reader, int64_t array_size, float **ptr_p)
Definition readfile.cc:5809
bool BLO_write_is_undo(BlendWriter *writer)
void BLO_write_shared(BlendWriter *writer, const void *data, size_t approximate_size_in_bytes, const blender::ImplicitSharingInfo *sharing_info, blender::FunctionRef< void()> write_fn)
const blender::ImplicitSharingInfo * BLO_read_shared(BlendDataReader *reader, T **data_ptr, blender::FunctionRef< const blender::ImplicitSharingInfo *()> read_fn)
#define BLO_write_struct_at_address(writer, struct_name, address, data_ptr)
#define IFACE_(msgid)
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:323
void DEG_add_depends_on_transform_relation(DepsNodeHandle *node_handle, const char *description)
void DEG_add_object_relation(DepsNodeHandle *node_handle, Object *object, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
#define CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
@ eModifierFlag_OverrideLibrary_Local
@ MOD_MDEF_DYNAMIC_BIND
@ MOD_MDEF_INVERT_VGROUP
@ eModifierType_MeshDeform
Object is a sort of wrapper for general info.
@ OB_MESH
static bool is_disabled
Read Guarded memory(de)allocation.
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 required_data_mask(ModifierData *, CustomData_MeshMasks *r_cddata_masks)
static void blend_read(BlendDataReader *, ModifierData *md)
static void panel_draw(const bContext *, Panel *panel)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static void free_data(ModifierData *md)
Definition MOD_bevel.cc:272
static void blend_write(BlendWriter *writer, const ID *, const ModifierData *md)
Definition MOD_bevel.cc:433
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)
ModifierTypeInfo modifierType_MeshDeform
static void free_data(ModifierData *md)
static void meshdeform_vert_task(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict)
static void blend_read(BlendDataReader *reader, ModifierData *md)
static void panel_draw(const bContext *, Panel *panel)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
void BKE_modifier_mdef_compact_influences(ModifierData *md)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void blend_write(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
static void meshdeformModifier_do(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float(*vertexCos)[3], const int verts_num)
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float(*dco)[3], float vec[3])
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const StringRefNull vgroup_prop, const std::optional< StringRefNull > invert_vgroup_prop, const std::optional< StringRefNull > text)
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_error_message_draw(uiLayout *layout, PointerRNA *ptr)
void MOD_get_vgroup(const Object *ob, const Mesh *mesh, const char *name, const MDeformVert **dvert, int *defgrp_index)
Definition MOD_util.cc:156
void MOD_previous_vcos_store(ModifierData *md, const float(*vert_coords)[3])
Definition MOD_util.cc:142
#define UI_ITEM_NONE
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:248
const T * data() const
Definition BLI_array.hh:312
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr T * data() const
Definition BLI_span.hh:539
nullptr float
uint col
static void update_depsgraph(tGraphSliderOp *gso)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define MESHDEFORM_MIN_INFLUENCE
void copy_shared_pointer(T *src_ptr, const ImplicitSharingInfo *src_sharing_info, T **r_dst_ptr, const ImplicitSharingInfo **r_dst_sharing_info)
const ImplicitSharingInfo * info_for_mem_free(void *data)
void free_shared_data(T **data, const ImplicitSharingInfo **sharing_info)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition DNA_ID.h:414
void(* bindfunc)(struct Object *object, struct MeshDeformModifierData *mmd, struct Mesh *cagemesh, float *vertexcos, int verts_num, float cagemat[4][4])
const ImplicitSharingInfoHandle * dyninfluences_sharing_info
const ImplicitSharingInfoHandle * bindinfluences_sharing_info
const ImplicitSharingInfoHandle * dynverts_sharing_info
const ImplicitSharingInfoHandle * dyngrid_sharing_info
const ImplicitSharingInfoHandle * bindcagecos_sharing_info
const ImplicitSharingInfoHandle * bindoffsets_sharing_info
MeshDeformModifierData * mmd
const MDeformVert * dvert
struct uiLayout * layout
uiLayout & column(bool align)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
void use_property_split_set(bool value)
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238
uint8_t flag
Definition wm_window.cc:145