Blender V4.3
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
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
29#include "UI_interface.hh"
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
53static void free_data(ModifierData *md)
54{
56
57 if (mmd->bindinfluences) {
59 }
60 if (mmd->bindoffsets) {
62 }
63 if (mmd->bindcagecos) {
65 }
66 if (mmd->dyngrid) {
67 MEM_freeN(mmd->dyngrid);
68 }
69 if (mmd->dyninfluences) {
71 }
72 if (mmd->dynverts) {
73 MEM_freeN(mmd->dynverts);
74 }
75 if (mmd->bindweights) {
76 MEM_freeN(mmd->bindweights); /* deprecated */
77 }
78 if (mmd->bindcos) {
79 MEM_freeN(mmd->bindcos); /* deprecated */
80 }
81}
82
83static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
84{
85 const MeshDeformModifierData *mmd = (const MeshDeformModifierData *)md;
87
89
90 if (mmd->bindinfluences) {
91 tmmd->bindinfluences = static_cast<MDefInfluence *>(MEM_dupallocN(mmd->bindinfluences));
92 }
93 if (mmd->bindoffsets) {
94 tmmd->bindoffsets = static_cast<int *>(MEM_dupallocN(mmd->bindoffsets));
95 }
96 if (mmd->bindcagecos) {
97 tmmd->bindcagecos = static_cast<float *>(MEM_dupallocN(mmd->bindcagecos));
98 }
99 if (mmd->dyngrid) {
100 tmmd->dyngrid = static_cast<MDefCell *>(MEM_dupallocN(mmd->dyngrid));
101 }
102 if (mmd->dyninfluences) {
103 tmmd->dyninfluences = static_cast<MDefInfluence *>(MEM_dupallocN(mmd->dyninfluences));
104 }
105 if (mmd->dynverts) {
106 tmmd->dynverts = static_cast<int *>(MEM_dupallocN(mmd->dynverts));
107 }
108 if (mmd->bindweights) {
109 tmmd->bindweights = static_cast<float *>(MEM_dupallocN(mmd->bindweights)); /* deprecated */
110 }
111 if (mmd->bindcos) {
112 tmmd->bindcos = static_cast<float *>(MEM_dupallocN(mmd->bindcos)); /* deprecated */
113 }
114}
115
116static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
117{
119
120 /* Ask for vertex-groups if we need them. */
121 if (mmd->defgrp_name[0] != '\0') {
122 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
123 }
124}
125
126static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
127{
129
130 /* The object type check is only needed here in case we have a placeholder
131 * object assigned (because the library containing the mesh is missing).
132 *
133 * In other cases it should be impossible to have a type mismatch.
134 */
135 return !mmd->object || mmd->object->type != OB_MESH;
136}
137
138static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
139{
141
142 walk(user_data, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
143}
144
146{
148 if (mmd->object != nullptr) {
149 DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Mesh Deform Modifier");
150 DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_GEOMETRY, "Mesh Deform Modifier");
151 }
152 /* We need our own transformation as well. */
153 DEG_add_depends_on_transform_relation(ctx->node, "Mesh Deform Modifier");
154}
155
156static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3], float vec[3])
157{
158 MDefCell *cell;
159 MDefInfluence *inf;
160 float gridvec[3], dvec[3], ivec[3], wx, wy, wz;
161 float weight, cageweight, totweight, *cageco;
162 int i, j, a, x, y, z, size;
163#if BLI_HAVE_SSE2
164 __m128 co = _mm_setzero_ps();
165#else
166 float co[3] = {0.0f, 0.0f, 0.0f};
167#endif
168
169 totweight = 0.0f;
170 size = mmd->dyngridsize;
171
172 for (i = 0; i < 3; i++) {
173 gridvec[i] = (vec[i] - mmd->dyncellmin[i] - mmd->dyncellwidth * 0.5f) / mmd->dyncellwidth;
174 ivec[i] = int(gridvec[i]);
175 dvec[i] = gridvec[i] - ivec[i];
176 }
177
178 for (i = 0; i < 8; i++) {
179 if (i & 1) {
180 x = ivec[0] + 1;
181 wx = dvec[0];
182 }
183 else {
184 x = ivec[0];
185 wx = 1.0f - dvec[0];
186 }
187
188 if (i & 2) {
189 y = ivec[1] + 1;
190 wy = dvec[1];
191 }
192 else {
193 y = ivec[1];
194 wy = 1.0f - dvec[1];
195 }
196
197 if (i & 4) {
198 z = ivec[2] + 1;
199 wz = dvec[2];
200 }
201 else {
202 z = ivec[2];
203 wz = 1.0f - dvec[2];
204 }
205
206 CLAMP(x, 0, size - 1);
207 CLAMP(y, 0, size - 1);
208 CLAMP(z, 0, size - 1);
209
210 a = x + y * size + z * size * size;
211 weight = wx * wy * wz;
212
213 cell = &mmd->dyngrid[a];
214 inf = mmd->dyninfluences + cell->offset;
215 for (j = 0; j < cell->influences_num; j++, inf++) {
216 cageco = dco[inf->vertex];
217 cageweight = weight * inf->weight;
218#if BLI_HAVE_SSE2
219 {
220 __m128 cageweight_r = _mm_set1_ps(cageweight);
221 /* This will load one extra element, this is ok because
222 * we ignore that part of register anyway.
223 */
224 __m128 cageco_r = _mm_loadu_ps(cageco);
225 co = _mm_add_ps(co, _mm_mul_ps(cageco_r, cageweight_r));
226 }
227#else
228 co[0] += cageweight * cageco[0];
229 co[1] += cageweight * cageco[1];
230 co[2] += cageweight * cageco[2];
231#endif
232 totweight += cageweight;
233 }
234 }
235
236#if BLI_HAVE_SSE2
237 copy_v3_v3(vec, (float *)&co);
238#else
239 copy_v3_v3(vec, co);
240#endif
241
242 return totweight;
243}
244
254
255static void meshdeform_vert_task(void *__restrict userdata,
256 const int iter,
257 const TaskParallelTLS *__restrict /*tls*/)
258{
259 MeshdeformUserdata *data = static_cast<MeshdeformUserdata *>(userdata);
260 /*const*/ MeshDeformModifierData *mmd = data->mmd;
261 const MDeformVert *dvert = data->dvert;
262 const int defgrp_index = data->defgrp_index;
263 const int *offsets = mmd->bindoffsets;
264 const MDefInfluence *__restrict influences = mmd->bindinfluences;
265 /*const*/ float(*__restrict dco)[3] = data->dco;
266 float(*vertexCos)[3] = data->vertexCos;
267 float co[3];
268 float weight, totweight, fac = 1.0f;
269
270 if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
271 if (!mmd->dynverts[iter]) {
272 return;
273 }
274 }
275
276 if (dvert) {
277 fac = BKE_defvert_find_weight(&dvert[iter], defgrp_index);
278
279 if (mmd->flag & MOD_MDEF_INVERT_VGROUP) {
280 fac = 1.0f - fac;
281 }
282
283 if (fac <= 0.0f) {
284 return;
285 }
286 }
287
288 if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
289 /* transform coordinate into cage's local space */
290 mul_v3_m4v3(co, data->cagemat, vertexCos[iter]);
291 totweight = meshdeform_dynamic_bind(mmd, dco, co);
292 }
293 else {
294 totweight = 0.0f;
295 zero_v3(co);
296 int start = offsets[iter];
297 int end = offsets[iter + 1];
298
299 for (int a = start; a < end; a++) {
300 weight = influences[a].weight;
301 madd_v3_v3fl(co, dco[influences[a].vertex], weight);
302 totweight += weight;
303 }
304 }
305
306 if (totweight > 0.0f) {
307 mul_v3_fl(co, fac / totweight);
308 mul_m3_v3(data->icagemat, co);
309 add_v3_v3(vertexCos[iter], co);
310 }
311}
312
314 const ModifierEvalContext *ctx,
315 Mesh *mesh,
316 float (*vertexCos)[3],
317 const int verts_num)
318{
320 Object *ob = ctx->object;
321
322 Mesh *cagemesh;
323 const MDeformVert *dvert = nullptr;
324 float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
325 float(*bindcagecos)[3];
326 int a, cage_verts_num, defgrp_index;
328
329 static int recursive_bind_sentinel = 0;
330
331 if (mmd->object == nullptr || (mmd->bindcagecos == nullptr && mmd->bindfunc == nullptr)) {
332 return;
333 }
334
335 /* Get cage mesh.
336 *
337 * Only do this is the target object is in edit mode by itself, meaning
338 * we don't allow linked edit meshes here.
339 * This is because editbmesh_get_mesh_cage_and_final() might easily
340 * conflict with the thread which evaluates object which is in the edit
341 * mode for this mesh.
342 *
343 * We'll support this case once granular dependency graph is landed.
344 */
345 Object *ob_target = mmd->object;
347 if (cagemesh == nullptr) {
348 BKE_modifier_set_error(ctx->object, md, "Cannot get mesh from cage object");
349 return;
350 }
351
352 /* compute matrices to go in and out of cage object space */
353 invert_m4_m4(imat, ob_target->object_to_world().ptr());
354 mul_m4_m4m4(cagemat, imat, ob->object_to_world().ptr());
355 mul_m4_m4m4(cmat, mmd->bindmat, cagemat);
356 invert_m4_m4(iobmat, cmat);
357 copy_m3_m4(icagemat, iobmat);
358
359 /* bind weights if needed */
360 if (!mmd->bindcagecos) {
361 /* progress bar redraw can make this recursive. */
362 if (!DEG_is_active(ctx->depsgraph)) {
363 BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph");
364 return;
365 }
366 if (!recursive_bind_sentinel) {
367 recursive_bind_sentinel = 1;
368 mmd->bindfunc(ob, mmd, cagemesh, (float *)vertexCos, verts_num, cagemat);
369 recursive_bind_sentinel = 0;
370 }
371
372 return;
373 }
374
375 /* verify we have compatible weights */
376 cage_verts_num = BKE_mesh_wrapper_vert_len(cagemesh);
377
378 if (mmd->verts_num != verts_num) {
379 BKE_modifier_set_error(ob, md, "Vertices changed from %d to %d", mmd->verts_num, verts_num);
380 return;
381 }
382 else if (mmd->cage_verts_num != cage_verts_num) {
384 ob, md, "Cage vertices changed from %d to %d", mmd->cage_verts_num, cage_verts_num);
385 return;
386 }
387 else if (mmd->bindcagecos == nullptr) {
388 BKE_modifier_set_error(ob, md, "Bind data missing");
389 return;
390 }
391
392 /* We allocate 1 element extra to make it possible to
393 * load the values to SSE registers, which are float4.
394 */
395 blender::Array<blender::float3> dco(cage_verts_num + 1);
396 zero_v3(dco[cage_verts_num]);
397
398 /* setup deformation data */
399 BKE_mesh_wrapper_vert_coords_copy(cagemesh, dco.as_mutable_span().take_front(cage_verts_num));
400 bindcagecos = (float(*)[3])mmd->bindcagecos;
401
402 for (a = 0; a < cage_verts_num; a++) {
403 /* Get cage vertex in world-space with binding transform. */
404 float co[3];
405 mul_v3_m4v3(co, mmd->bindmat, dco[a]);
406 /* compute difference with world space bind coord */
407 sub_v3_v3v3(dco[a], co, bindcagecos[a]);
408 }
409
410 MOD_get_vgroup(ob, mesh, mmd->defgrp_name, &dvert, &defgrp_index);
411
412 /* Initialize data to be pass to the for body function. */
413 data.mmd = mmd;
414 data.dvert = dvert;
415 data.dco = reinterpret_cast<float(*)[3]>(dco.data());
416 data.defgrp_index = defgrp_index;
417 data.vertexCos = vertexCos;
418 data.cagemat = cagemat;
419 data.icagemat = icagemat;
420
421 /* Do deformation. */
422 TaskParallelSettings settings;
424 settings.min_iter_per_thread = 16;
425 BLI_task_parallel_range(0, verts_num, &data, meshdeform_vert_task, &settings);
426}
427
429 const ModifierEvalContext *ctx,
430 Mesh *mesh,
432{
433 /* if next modifier needs original vertices */
434 MOD_previous_vcos_store(md, reinterpret_cast<float(*)[3]>(positions.data()));
436 md, ctx, mesh, reinterpret_cast<float(*)[3]>(positions.data()), positions.size());
437}
438
439#define MESHDEFORM_MIN_INFLUENCE 0.00001f
440
442{
444 float weight, totweight;
445 int influences_num, verts_num, cage_verts_num, a, b;
446
447 const float *weights = mmd->bindweights;
448 if (!weights) {
449 return;
450 }
451
452 verts_num = mmd->verts_num;
453 cage_verts_num = mmd->cage_verts_num;
454
455 /* count number of influences above threshold */
456 for (b = 0; b < verts_num; b++) {
457 for (a = 0; a < cage_verts_num; a++) {
458 weight = weights[a + b * cage_verts_num];
459
460 if (weight > MESHDEFORM_MIN_INFLUENCE) {
461 mmd->influences_num++;
462 }
463 }
464 }
465
466 /* allocate bind influences */
467 mmd->bindinfluences = static_cast<MDefInfluence *>(
468 MEM_calloc_arrayN(mmd->influences_num, sizeof(MDefInfluence), __func__));
469 mmd->bindoffsets = static_cast<int *>(MEM_calloc_arrayN((verts_num + 1), sizeof(int), __func__));
470
471 /* write influences */
472 influences_num = 0;
473
474 for (b = 0; b < verts_num; b++) {
475 mmd->bindoffsets[b] = influences_num;
476 totweight = 0.0f;
477
478 /* sum total weight */
479 for (a = 0; a < cage_verts_num; a++) {
480 weight = weights[a + b * cage_verts_num];
481
482 if (weight > MESHDEFORM_MIN_INFLUENCE) {
483 totweight += weight;
484 }
485 }
486
487 /* assign weights normalized */
488 for (a = 0; a < cage_verts_num; a++) {
489 weight = weights[a + b * cage_verts_num];
490
491 if (weight > MESHDEFORM_MIN_INFLUENCE) {
492 mmd->bindinfluences[influences_num].weight = weight / totweight;
493 mmd->bindinfluences[influences_num].vertex = a;
494 influences_num++;
495 }
496 }
497 }
498
499 mmd->bindoffsets[b] = influences_num;
500
501 /* free */
503 mmd->bindweights = nullptr;
504}
505
506static void panel_draw(const bContext * /*C*/, Panel *panel)
507{
508 uiLayout *col;
509 uiLayout *layout = panel->layout;
510
511 PointerRNA ob_ptr;
513
514 bool is_bound = RNA_boolean_get(ptr, "is_bound");
515
516 uiLayoutSetPropSep(layout, true);
517
518 col = uiLayoutColumn(layout, true);
519 uiLayoutSetEnabled(col, !is_bound);
520 uiItemR(col, ptr, "object", UI_ITEM_NONE, nullptr, ICON_NONE);
521
522 modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
523
524 col = uiLayoutColumn(layout, false);
525 uiLayoutSetEnabled(col, !is_bound);
526 uiItemR(col, ptr, "precision", UI_ITEM_NONE, nullptr, ICON_NONE);
527 uiItemR(col, ptr, "use_dynamic_bind", UI_ITEM_NONE, nullptr, ICON_NONE);
528
529 uiItemO(layout,
530 is_bound ? IFACE_("Unbind") : IFACE_("Bind"),
531 ICON_NONE,
532 "OBJECT_OT_meshdeform_bind");
533
534 modifier_panel_end(layout, ptr);
535}
536
537static void panel_register(ARegionType *region_type)
538{
540}
541
542static void blend_write(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
543{
545 const bool is_undo = BLO_write_is_undo(writer);
546
547 if (ID_IS_OVERRIDE_LIBRARY(id_owner) && !is_undo) {
548 BLI_assert(!ID_IS_LINKED(id_owner));
549 const bool is_local = (md->flag & eModifierFlag_OverrideLibrary_Local) != 0;
550 if (!is_local) {
551 /* Modifier coming from linked data cannot be bound from an override, so we can remove all
552 * binding data, can save a significant amount of memory. */
553 mmd.influences_num = 0;
554 mmd.bindinfluences = nullptr;
555 mmd.verts_num = 0;
556 mmd.bindoffsets = nullptr;
557 mmd.cage_verts_num = 0;
558 mmd.bindcagecos = nullptr;
559 mmd.dyngridsize = 0;
560 mmd.dyngrid = nullptr;
561 mmd.influences_num = 0;
562 mmd.dyninfluences = nullptr;
563 mmd.dynverts = nullptr;
564 }
565 }
566
567 const int size = mmd.dyngridsize;
568
570
572
573 /* NOTE: `bindoffset` is abusing `verts_num + 1` as its size, this becomes an incorrect value in
574 * case `verts_num == 0`, since `bindoffset` is then nullptr, not a size 1 allocated array. */
575 if (mmd.verts_num > 0) {
576 BLO_write_int32_array(writer, mmd.verts_num + 1, mmd.bindoffsets);
577 }
578 else {
579 BLI_assert(mmd.bindoffsets == nullptr);
580 }
581
583 BLO_write_struct_array(writer, MDefCell, size * size * size, mmd.dyngrid);
585 BLO_write_int32_array(writer, mmd.verts_num, mmd.dynverts);
586}
587
588static void blend_read(BlendDataReader *reader, ModifierData *md)
589{
591 const int size = mmd->dyngridsize;
592
594
595 /* NOTE: `bindoffset` is abusing `verts_num + 1` as its size, this becomes an incorrect value in
596 * case `verts_num == 0`, since `bindoffset` is then nullptr, not a size 1 allocated array. */
597 if (mmd->verts_num > 0) {
598 BLO_read_int32_array(reader, mmd->verts_num + 1, &mmd->bindoffsets);
599 }
600
602 BLO_read_struct_array(reader, MDefCell, size * size * size, &mmd->dyngrid);
604 BLO_read_int32_array(reader, mmd->verts_num, &mmd->dynverts);
605
606 /* Deprecated storage. */
607 BLO_read_float_array(reader, mmd->verts_num, &mmd->bindweights);
608 BLO_read_float3_array(reader, mmd->cage_verts_num, &mmd->bindcos);
609}
610
612 /*idname*/ "MeshDeform",
613 /*name*/ N_("MeshDeform"),
614 /*struct_name*/ "MeshDeformModifierData",
615 /*struct_size*/ sizeof(MeshDeformModifierData),
616 /*srna*/ &RNA_MeshDeformModifier,
620 /*icon*/ ICON_MOD_MESHDEFORM,
621
622 /*copy_data*/ copy_data,
623
624 /*deform_verts*/ deform_verts,
625 /*deform_matrices*/ nullptr,
626 /*deform_verts_EM*/ nullptr,
627 /*deform_matrices_EM*/ nullptr,
628 /*modify_mesh*/ nullptr,
629 /*modify_geometry_set*/ nullptr,
630
631 /*init_data*/ init_data,
632 /*required_data_mask*/ required_data_mask,
633 /*free_data*/ free_data,
634 /*is_disabled*/ is_disabled,
635 /*update_depsgraph*/ update_depsgraph,
636 /*depends_on_time*/ nullptr,
637 /*depends_on_normals*/ nullptr,
638 /*foreach_ID_link*/ foreach_ID_link,
639 /*foreach_tex_link*/ nullptr,
640 /*free_runtime_data*/ nullptr,
641 /*panel_register*/ panel_register,
642 /*blend_write*/ blend_write,
643 /*blend_read*/ blend_read,
644 /*foreach_cache*/ nullptr,
645};
support for deformation groups and hooks.
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:770
@ 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)
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(*)(void *user_data, Object *ob, ID **idpoin, int cb_flag) IDWalkFunc
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
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:230
#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, int array_size, float **ptr_p)
Definition readfile.cc:4977
void BLO_write_float3_array(BlendWriter *writer, uint num, const float *data_ptr)
void BLO_write_int32_array(BlendWriter *writer, uint num, const int32_t *data_ptr)
void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition readfile.cc:4967
void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p)
Definition readfile.cc:4947
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
bool BLO_write_is_undo(BlendWriter *writer)
#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:318
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: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
@ MOD_MDEF_DYNAMIC_BIND
@ MOD_MDEF_INVERT_VGROUP
@ eModifierType_MeshDeform
struct MeshDeformModifierData MeshDeformModifierData
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)
#define MESHDEFORM_MIN_INFLUENCE
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_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 MOD_previous_vcos_store(ModifierData *md, const float(*vert_coords)[3])
Definition MOD_util.cc:145
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
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:237
const T * data() const
Definition BLI_array.hh:301
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
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
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition DNA_ID.h:413
void(* bindfunc)(struct Object *object, struct MeshDeformModifierData *mmd, struct Mesh *cagemesh, float *vertexcos, int verts_num, float cagemat[4][4])
MeshDeformModifierData * mmd
const MDeformVert * dvert
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138