Blender  V2.93
MOD_weightvgproximity.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2011 by Bastien Montagne.
17  * All rights reserved.
18  */
19 
24 #include "BLI_utildefines.h"
25 
26 #include "BLI_ghash.h"
27 #include "BLI_listbase.h"
28 #include "BLI_math.h"
29 #include "BLI_rand.h"
30 #include "BLI_task.h"
31 
32 #include "BLT_translation.h"
33 
34 #include "DNA_color_types.h" /* CurveMapping. */
35 #include "DNA_defaults.h"
36 #include "DNA_mesh_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_screen_types.h"
41 
42 #include "BKE_bvhutils.h"
43 #include "BKE_colortools.h" /* CurveMapping. */
44 #include "BKE_context.h"
45 #include "BKE_curve.h"
46 #include "BKE_customdata.h"
47 #include "BKE_deform.h"
48 #include "BKE_lib_id.h"
49 #include "BKE_lib_query.h"
50 #include "BKE_mesh.h"
51 #include "BKE_mesh_wrapper.h"
52 #include "BKE_modifier.h"
53 #include "BKE_screen.h"
54 #include "BKE_texture.h" /* Texture masking. */
55 
56 #include "UI_interface.h"
57 #include "UI_resources.h"
58 
59 #include "BLO_read_write.h"
60 
61 #include "RNA_access.h"
62 
63 #include "DEG_depsgraph_build.h"
64 #include "DEG_depsgraph_query.h"
65 
66 #include "MEM_guardedalloc.h"
67 
68 #include "MOD_modifiertypes.h"
69 #include "MOD_ui_common.h"
70 #include "MOD_util.h"
71 #include "MOD_weightvg_util.h"
72 
73 //#define USE_TIMEIT
74 
75 #ifdef USE_TIMEIT
76 # include "PIL_time.h"
77 # include "PIL_time_utildefines.h"
78 #endif
79 
80 /**************************************
81  * Util functions. *
82  **************************************/
83 
84 /* Util macro. */
85 #define OUT_OF_MEMORY() ((void)printf("WeightVGProximity: Out of memory.\n"))
86 
87 typedef struct Vert2GeomData {
88  /* Read-only data */
89  float (*v_cos)[3];
90 
92 
94 
95  /* Write data, but not needing locking (two different threads will never write same index). */
96  float *dist[3];
98 
103 typedef struct Vert2GeomDataChunk {
104  /* Read-only data */
105  float last_hit_co[3][3];
106  bool is_init[3];
108 
112 static void vert2geom_task_cb_ex(void *__restrict userdata,
113  const int iter,
114  const TaskParallelTLS *__restrict tls)
115 {
116  Vert2GeomData *data = userdata;
117  Vert2GeomDataChunk *data_chunk = tls->userdata_chunk;
118 
119  float tmp_co[3];
120  int i;
121 
122  /* Convert the vertex to tree coordinates. */
123  copy_v3_v3(tmp_co, data->v_cos[iter]);
124  BLI_space_transform_apply(data->loc2trgt, tmp_co);
125 
126  for (i = 0; i < ARRAY_SIZE(data->dist); i++) {
127  if (data->dist[i]) {
128  BVHTreeNearest nearest = {0};
129 
130  /* Note that we use local proximity heuristics (to reduce the nearest search).
131  *
132  * If we already had an hit before in same chunk of tasks (i.e. previous vertex by index),
133  * we assume this vertex is going to have a close hit to that other vertex,
134  * so we can initiate the "nearest.dist" with the expected value to that last hit.
135  * This will lead in pruning of the search tree.
136  */
137  nearest.dist_sq = data_chunk->is_init[i] ?
138  len_squared_v3v3(tmp_co, data_chunk->last_hit_co[i]) :
139  FLT_MAX;
140  nearest.index = -1;
141 
142  /* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */
143  BLI_bvhtree_find_nearest(data->treeData[i]->tree,
144  tmp_co,
145  &nearest,
146  data->treeData[i]->nearest_callback,
147  data->treeData[i]);
148  data->dist[i][iter] = sqrtf(nearest.dist_sq);
149 
150  if (nearest.index != -1) {
151  copy_v3_v3(data_chunk->last_hit_co[i], nearest.co);
152  data_chunk->is_init[i] = true;
153  }
154  }
155  }
156 }
157 
161 static void get_vert2geom_distance(int numVerts,
162  float (*v_cos)[3],
163  float *dist_v,
164  float *dist_e,
165  float *dist_f,
166  Mesh *target,
167  const SpaceTransform *loc2trgt)
168 {
169  Vert2GeomData data = {0};
170  Vert2GeomDataChunk data_chunk = {{{0}}};
171 
172  BVHTreeFromMesh treeData_v = {NULL};
173  BVHTreeFromMesh treeData_e = {NULL};
174  BVHTreeFromMesh treeData_f = {NULL};
175 
176  if (dist_v) {
177  /* Create a bvh-tree of the given target's verts. */
178  BKE_bvhtree_from_mesh_get(&treeData_v, target, BVHTREE_FROM_VERTS, 2);
179  if (treeData_v.tree == NULL) {
180  OUT_OF_MEMORY();
181  return;
182  }
183  }
184  if (dist_e) {
185  /* Create a bvh-tree of the given target's edges. */
186  BKE_bvhtree_from_mesh_get(&treeData_e, target, BVHTREE_FROM_EDGES, 2);
187  if (treeData_e.tree == NULL) {
188  OUT_OF_MEMORY();
189  return;
190  }
191  }
192  if (dist_f) {
193  /* Create a bvh-tree of the given target's faces. */
194  BKE_bvhtree_from_mesh_get(&treeData_f, target, BVHTREE_FROM_LOOPTRI, 2);
195  if (treeData_f.tree == NULL) {
196  OUT_OF_MEMORY();
197  return;
198  }
199  }
200 
201  data.v_cos = v_cos;
202  data.loc2trgt = loc2trgt;
203  data.treeData[0] = &treeData_v;
204  data.treeData[1] = &treeData_e;
205  data.treeData[2] = &treeData_f;
206  data.dist[0] = dist_v;
207  data.dist[1] = dist_e;
208  data.dist[2] = dist_f;
209 
210  TaskParallelSettings settings;
212  settings.use_threading = (numVerts > 10000);
213  settings.userdata_chunk = &data_chunk;
214  settings.userdata_chunk_size = sizeof(data_chunk);
215  BLI_task_parallel_range(0, numVerts, &data, vert2geom_task_cb_ex, &settings);
216 
217  if (dist_v) {
218  free_bvhtree_from_mesh(&treeData_v);
219  }
220  if (dist_e) {
221  free_bvhtree_from_mesh(&treeData_e);
222  }
223  if (dist_f) {
224  free_bvhtree_from_mesh(&treeData_f);
225  }
226 }
227 
233  int numVerts, float (*v_cos)[3], float *dist, Object *ob, Object *obr)
234 {
235  /* Vertex and ref object coordinates. */
236  float v_wco[3];
237  uint i = numVerts;
238 
239  while (i-- > 0) {
240  /* Get world-coordinates of the vertex (constraints and anim included). */
241  mul_v3_m4v3(v_wco, ob->obmat, v_cos[i]);
242  /* Return distance between both coordinates. */
243  dist[i] = len_v3v3(v_wco, obr->obmat[3]);
244  }
245 }
246 
251 static float get_ob2ob_distance(const Object *ob, const Object *obr)
252 {
253  return len_v3v3(ob->obmat[3], obr->obmat[3]);
254 }
255 
259 static void do_map(Object *ob,
260  float *weights,
261  const int nidx,
262  const float min_d,
263  const float max_d,
264  short mode,
265  const bool do_invert_mapping,
266  CurveMapping *cmap)
267 {
268  const float range_inv = 1.0f / (max_d - min_d); /* invert since multiplication is faster */
269  uint i = nidx;
270  if (max_d == min_d) {
271  while (i-- > 0) {
272  weights[i] = (weights[i] >= max_d) ? 1.0f : 0.0f; /* "Step" behavior... */
273  }
274  }
275  else if (max_d > min_d) {
276  while (i-- > 0) {
277  if (weights[i] >= max_d) {
278  weights[i] = 1.0f; /* most likely case first */
279  }
280  else if (weights[i] <= min_d) {
281  weights[i] = 0.0f;
282  }
283  else {
284  weights[i] = (weights[i] - min_d) * range_inv;
285  }
286  }
287  }
288  else {
289  while (i-- > 0) {
290  if (weights[i] <= max_d) {
291  weights[i] = 1.0f; /* most likely case first */
292  }
293  else if (weights[i] >= min_d) {
294  weights[i] = 0.0f;
295  }
296  else {
297  weights[i] = (weights[i] - min_d) * range_inv;
298  }
299  }
300  }
301 
302  if (do_invert_mapping || mode != MOD_WVG_MAPPING_NONE) {
303  RNG *rng = NULL;
304 
305  if (mode == MOD_WVG_MAPPING_RANDOM) {
307  }
308 
309  weightvg_do_map(nidx, weights, mode, do_invert_mapping, cmap, rng);
310 
311  if (rng) {
312  BLI_rng_free(rng);
313  }
314  }
315 }
316 
317 /**************************************
318  * Modifiers functions. *
319  **************************************/
320 static void initData(ModifierData *md)
321 {
323 
324  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier));
325 
327 
328  wmd->cmap_curve = BKE_curvemapping_add(1, 0.0, 0.0, 1.0, 1.0);
330 }
331 
332 static void freeData(ModifierData *md)
333 {
336 }
337 
338 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
339 {
342 
343  BKE_modifier_copydata_generic(md, target, flag);
344 
346 }
347 
348 static void requiredDataMask(Object *UNUSED(ob),
349  ModifierData *md,
350  CustomData_MeshMasks *r_cddata_masks)
351 {
353 
354  /* We need vertex groups! */
355  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
356 
357  /* Ask for UV coordinates if we need them. */
358  if (wmd->mask_tex_mapping == MOD_DISP_MAP_UV) {
359  r_cddata_masks->fmask |= CD_MASK_MTFACE;
360  }
361 
362  /* No need to ask for CD_PREVIEW_MLOOPCOL... */
363 }
364 
365 static bool dependsOnTime(ModifierData *md)
366 {
368 
369  if (wmd->mask_texture) {
371  }
372  return 0;
373 }
374 
375 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
376 {
378 
379  walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
380  walk(userData, ob, (ID **)&wmd->proximity_ob_target, IDWALK_CB_NOP);
381  walk(userData, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP);
382 }
383 
384 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
385 {
386  walk(userData, ob, md, "mask_texture");
387 }
388 
390 {
392  bool need_transform_relation = false;
393 
394  if (wmd->proximity_ob_target != NULL) {
396  ctx->node, wmd->proximity_ob_target, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier");
397  if (wmd->proximity_ob_target->data != NULL &&
400  ctx->node, wmd->proximity_ob_target, DEG_OB_COMP_GEOMETRY, "WeightVGProximity Modifier");
401  }
402  need_transform_relation = true;
403  }
404 
405  if (wmd->mask_texture != NULL) {
406  DEG_add_generic_id_relation(ctx->node, &wmd->mask_texture->id, "WeightVGProximity Modifier");
407 
410  ctx->node, wmd->mask_tex_map_obj, wmd->mask_tex_map_bone, "WeightVGProximity Modifier");
411  need_transform_relation = true;
412  }
413  else if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
414  need_transform_relation = true;
415  }
416  }
417 
418  if (need_transform_relation) {
419  DEG_add_modifier_to_transform_relation(ctx->node, "WeightVGProximity Modifier");
420  }
421 }
422 
423 static bool isDisabled(const struct Scene *UNUSED(scene),
424  ModifierData *md,
425  bool UNUSED(useRenderParams))
426 {
428  /* If no vertex group, bypass. */
429  if (wmd->defgrp_name[0] == '\0') {
430  return true;
431  }
432  /* If no target object, bypass. */
433  return (wmd->proximity_ob_target == NULL);
434 }
435 
437 {
438  BLI_assert(mesh != NULL);
439 
441  MDeformVert *dvert = NULL;
442  MDeformWeight **dw, **tdw;
443  float(*v_cos)[3] = NULL; /* The vertices coordinates. */
444  Object *ob = ctx->object;
445  Object *obr = NULL; /* Our target object. */
446  int defgrp_index;
447  float *tw = NULL;
448  float *org_w = NULL;
449  float *new_w = NULL;
450  int *tidx, *indices = NULL;
451  int numIdx = 0;
452  int i;
453  const bool invert_vgroup_mask = (wmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK) !=
454  0;
455  const bool do_normalize = (wmd->proximity_flags & MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE) != 0;
456  /* Flags. */
457 #if 0
458  const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0;
459 #endif
460 
461 #ifdef USE_TIMEIT
462  TIMEIT_START(perf);
463 #endif
464 
465  /* Get number of verts. */
466  const int numVerts = mesh->totvert;
467 
468  /* Check if we can just return the original mesh.
469  * Must have verts and therefore verts assigned to vgroups to do anything useful!
470  */
471  if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) {
472  return mesh;
473  }
474 
475  /* Get our target object. */
476  obr = wmd->proximity_ob_target;
477  if (obr == NULL) {
478  return mesh;
479  }
480 
481  /* Get vgroup idx from its name. */
482  defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name);
483  if (defgrp_index == -1) {
484  return mesh;
485  }
486 
487  const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT);
488  /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
489  /* As this modifier never add vertices to vgroup, just return. */
490  if (!has_mdef) {
491  return mesh;
492  }
493 
494  dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts);
495  /* Ultimate security check. */
496  if (!dvert) {
497  return mesh;
498  }
499  mesh->dvert = dvert;
500 
501  /* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight. */
502  tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGProximity Modifier, tidx");
503  tw = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGProximity Modifier, tw");
504  tdw = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGProximity Modifier, tdw");
505  for (i = 0; i < numVerts; i++) {
506  MDeformWeight *_dw = BKE_defvert_find_index(&dvert[i], defgrp_index);
507  if (_dw) {
508  tidx[numIdx] = i;
509  tw[numIdx] = _dw->weight;
510  tdw[numIdx++] = _dw;
511  }
512  }
513  /* If no vertices found, return org data! */
514  if (numIdx == 0) {
515  MEM_freeN(tidx);
516  MEM_freeN(tw);
517  MEM_freeN(tdw);
518  return mesh;
519  }
520  if (numIdx != numVerts) {
521  indices = MEM_malloc_arrayN(numIdx, sizeof(int), "WeightVGProximity Modifier, indices");
522  memcpy(indices, tidx, sizeof(int) * numIdx);
523  org_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGProximity Modifier, org_w");
524  memcpy(org_w, tw, sizeof(float) * numIdx);
525  dw = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGProximity Modifier, dw");
526  memcpy(dw, tdw, sizeof(MDeformWeight *) * numIdx);
527  MEM_freeN(tw);
528  MEM_freeN(tdw);
529  }
530  else {
531  org_w = tw;
532  dw = tdw;
533  }
534  new_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGProximity Modifier, new_w");
535  MEM_freeN(tidx);
536 
537  /* Get our vertex coordinates. */
538  if (numIdx != numVerts) {
539  float(*tv_cos)[3] = BKE_mesh_vert_coords_alloc(mesh, NULL);
540  v_cos = MEM_malloc_arrayN(numIdx, sizeof(float[3]), "WeightVGProximity Modifier, v_cos");
541  for (i = 0; i < numIdx; i++) {
542  copy_v3_v3(v_cos[i], tv_cos[indices[i]]);
543  }
544  MEM_freeN(tv_cos);
545  }
546  else {
548  }
549 
550  /* Compute wanted distances. */
552  const float dist = get_ob2ob_distance(ob, obr);
553  for (i = 0; i < numIdx; i++) {
554  new_w[i] = dist;
555  }
556  }
557  else if (wmd->proximity_mode == MOD_WVG_PROXIMITY_GEOMETRY) {
558  const bool use_trgt_verts = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_VERTS) != 0;
559  const bool use_trgt_edges = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_EDGES) != 0;
560  const bool use_trgt_faces = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_FACES) != 0;
561 
562  if (use_trgt_verts || use_trgt_edges || use_trgt_faces) {
564 
565  /* We must check that we do have a valid target_mesh! */
566  if (target_mesh != NULL) {
567 
568  /* TODO: edit-mode versions of the BVH lookup functions are available so it could be
569  * avoided. */
570  BKE_mesh_wrapper_ensure_mdata(target_mesh);
571 
572  SpaceTransform loc2trgt;
573  float *dists_v = use_trgt_verts ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_v") :
574  NULL;
575  float *dists_e = use_trgt_edges ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_e") :
576  NULL;
577  float *dists_f = use_trgt_faces ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_f") :
578  NULL;
579 
580  BLI_SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr);
581  get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f, target_mesh, &loc2trgt);
582  for (i = 0; i < numIdx; i++) {
583  new_w[i] = dists_v ? dists_v[i] : FLT_MAX;
584  if (dists_e) {
585  new_w[i] = min_ff(dists_e[i], new_w[i]);
586  }
587  if (dists_f) {
588  new_w[i] = min_ff(dists_f[i], new_w[i]);
589  }
590  }
591 
592  MEM_SAFE_FREE(dists_v);
593  MEM_SAFE_FREE(dists_e);
594  MEM_SAFE_FREE(dists_f);
595  }
596  /* Else, fall back to default obj2vert behavior. */
597  else {
598  get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr);
599  }
600  }
601  else {
602  get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr);
603  }
604  }
605 
606  /* Map distances to weights. */
607  do_map(ob,
608  new_w,
609  numIdx,
610  wmd->min_dist,
611  wmd->max_dist,
612  wmd->falloff_type,
614  wmd->cmap_curve);
615 
616  /* Do masking. */
618  weightvg_do_mask(ctx,
619  numIdx,
620  indices,
621  org_w,
622  new_w,
623  ob,
624  mesh,
625  wmd->mask_constant,
626  wmd->mask_defgrp_name,
627  scene,
628  wmd->mask_texture,
630  wmd->mask_tex_mapping,
631  wmd->mask_tex_map_obj,
632  wmd->mask_tex_map_bone,
634  invert_vgroup_mask);
635 
636  /* Update vgroup. Note we never add nor remove vertices from vgroup here. */
638  dvert, defgrp_index, dw, numIdx, indices, org_w, false, 0.0f, false, 0.0f, do_normalize);
639 
640  /* If weight preview enabled... */
641 #if 0 /* XXX Currently done in mod stack :/ */
642  if (do_prev) {
643  DM_update_weight_mcol(ob, dm, 0, org_w, numIdx, indices);
644  }
645 #endif
646 
647  /* Freeing stuff. */
648  MEM_freeN(org_w);
649  MEM_freeN(new_w);
650  MEM_freeN(dw);
651  MEM_freeN(v_cos);
653 
654 #ifdef USE_TIMEIT
655  TIMEIT_END(perf);
656 #endif
657 
658  mesh->runtime.is_original = false;
659 
660  /* Return the vgroup-modified mesh. */
661  return mesh;
662 }
663 
664 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
665 {
666  uiLayout *col;
667  uiLayout *layout = panel->layout;
668 
669  PointerRNA ob_ptr;
671 
672  uiLayoutSetPropSep(layout, true);
673 
674  uiItemPointerR(layout, ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
675 
676  uiItemR(layout, ptr, "target", 0, NULL, ICON_NONE);
677 
678  uiItemS(layout);
679 
680  uiItemR(layout, ptr, "proximity_mode", 0, NULL, ICON_NONE);
681  if (RNA_enum_get(ptr, "proximity_mode") == MOD_WVG_PROXIMITY_GEOMETRY) {
682  uiItemR(layout, ptr, "proximity_geometry", UI_ITEM_R_EXPAND, IFACE_("Geometry"), ICON_NONE);
683  }
684 
685  col = uiLayoutColumn(layout, true);
686  uiItemR(col, ptr, "min_dist", 0, NULL, ICON_NONE);
687  uiItemR(col, ptr, "max_dist", 0, NULL, ICON_NONE);
688 
689  uiItemR(layout, ptr, "normalize", 0, NULL, ICON_NONE);
690 }
691 
692 static void falloff_panel_draw(const bContext *UNUSED(C), Panel *panel)
693 {
694  uiLayout *row, *sub;
695  uiLayout *layout = panel->layout;
696 
697  PointerRNA ob_ptr;
699 
700  uiLayoutSetPropSep(layout, true);
701 
702  row = uiLayoutRow(layout, true);
703  uiItemR(row, ptr, "falloff_type", 0, IFACE_("Type"), ICON_NONE);
704  sub = uiLayoutRow(row, true);
705  uiLayoutSetPropSep(sub, false);
706  uiItemR(row, ptr, "invert_falloff", 0, "", ICON_ARROW_LEFTRIGHT);
707  if (RNA_enum_get(ptr, "falloff_type") == MOD_WVG_MAPPING_CURVE) {
708  uiTemplateCurveMapping(layout, ptr, "map_curve", 0, false, false, false, false);
709  }
710  modifier_panel_end(layout, ptr);
711 }
712 
713 static void influence_panel_draw(const bContext *C, Panel *panel)
714 {
715  uiLayout *layout = panel->layout;
716 
717  PointerRNA ob_ptr;
719 
720  weightvg_ui_common(C, &ob_ptr, ptr, layout);
721 }
722 
723 static void panelRegister(ARegionType *region_type)
724 {
725  PanelType *panel_type = modifier_panel_register(
728  region_type, "falloff", "Falloff", NULL, falloff_panel_draw, panel_type);
730  region_type, "influence", "Influence", NULL, influence_panel_draw, panel_type);
731 }
732 
733 static void blendWrite(BlendWriter *writer, const ModifierData *md)
734 {
736 
737  if (wmd->cmap_curve) {
739  }
740 }
741 
742 static void blendRead(BlendDataReader *reader, ModifierData *md)
743 {
745 
746  BLO_read_data_address(reader, &wmd->cmap_curve);
747  if (wmd->cmap_curve) {
749  }
750 }
751 
753  /* name */ "VertexWeightProximity",
754  /* structName */ "WeightVGProximityModifierData",
755  /* structSize */ sizeof(WeightVGProximityModifierData),
760  /* icon */ ICON_MOD_VERTEX_WEIGHT,
761 
762  /* copyData */ copyData,
763 
764  /* deformVerts */ NULL,
765  /* deformMatrices */ NULL,
766  /* deformVertsEM */ NULL,
767  /* deformMatricesEM */ NULL,
768  /* modifyMesh */ modifyMesh,
769  /* modifyHair */ NULL,
770  /* modifyGeometrySet */ NULL,
771  /* modifyVolume */ NULL,
772 
773  /* initData */ initData,
774  /* requiredDataMask */ requiredDataMask,
775  /* freeData */ freeData,
776  /* isDisabled */ isDisabled,
777  /* updateDepsgraph */ updateDepsgraph,
778  /* dependsOnTime */ dependsOnTime,
779  /* dependsOnNormals */ NULL,
780  /* foreachIDLink */ foreachIDLink,
781  /* foreachTexLink */ foreachTexLink,
782  /* freeRuntimeData */ NULL,
783  /* panelRegister */ panelRegister,
784  /* blendWrite */ blendWrite,
785  /* blendRead */ blendRead,
786 };
typedef float(TangentPoint)[2]
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, struct Mesh *mesh, const BVHCacheType bvh_cache_type, const int tree_type)
Definition: bvhutils.c:1413
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.c:1701
@ BVHTREE_FROM_EDGES
Definition: BKE_bvhutils.h:91
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:93
@ BVHTREE_FROM_VERTS
Definition: BKE_bvhutils.h:90
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1200
struct CurveMapping * BKE_curvemapping_copy(const struct CurveMapping *cumap)
void BKE_curvemapping_blend_read(struct BlendDataReader *reader, struct CurveMapping *cumap)
Definition: colortools.c:1252
void BKE_curvemapping_blend_write(struct BlendWriter *writer, const struct CurveMapping *cumap)
void BKE_curvemapping_free(struct CurveMapping *cumap)
Definition: colortools.c:119
struct CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition: colortools.c:88
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem)
Definition: customdata.c:2788
support for deformation groups and hooks.
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name)
struct MDeformWeight * BKE_defvert_find_index(const struct MDeformVert *dv, const int defgroup)
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:87
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:47
float(* BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3]
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.c:98
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:120
@ eModifierTypeFlag_SupportsMapping
Definition: BKE_modifier.h:82
@ eModifierTypeFlag_UsesPreview
Definition: BKE_modifier.h:113
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:83
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
void(* TexWalkFunc)(void *userData, struct Object *ob, struct ModifierData *md, const char *propname)
Definition: BKE_modifier.h:121
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_NonGeometrical
Definition: BKE_modifier.h:76
struct Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval, const bool get_cage_mesh)
bool BKE_texture_dependsOnTime(const struct Tex *texture)
Definition: texture.c:697
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_ghashutil_strhash(key)
Definition: BLI_ghash.h:350
int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1654
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
MINLINE float min_ff(float a, float b)
void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3])
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition: rand.cc:76
struct RNG * BLI_rng_new_srandom(unsigned int seed)
Definition: rand.cc:64
unsigned int uint
Definition: BLI_sys_types.h:83
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
#define ARRAY_SIZE(arr)
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_read_data_address(reader, ptr_p)
#define IFACE_(msgid)
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
void DEG_add_generic_id_relation(struct DepsNodeHandle *node_handle, struct ID *id, const char *description)
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
#define CD_MASK_MDEFORMVERT
@ CD_MDEFORMVERT
#define CD_MASK_MTFACE
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
@ MOD_DISP_MAP_OBJECT
@ MOD_DISP_MAP_GLOBAL
@ MOD_DISP_MAP_UV
struct WeightVGProximityModifierData WeightVGProximityModifierData
@ MOD_WVG_PROXIMITY_OBJECT
@ MOD_WVG_PROXIMITY_GEOMETRY
@ eModifierType_WeightVGProximity
@ MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE
@ MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK
@ MOD_WVG_PROXIMITY_GEOM_VERTS
@ MOD_WVG_PROXIMITY_INVERT_FALLOFF
@ MOD_WVG_PROXIMITY_GEOM_EDGES
@ MOD_WVG_PROXIMITY_GEOM_FACES
@ MOD_WVG_MAPPING_NONE
@ MOD_WVG_MAPPING_CURVE
@ MOD_WVG_MAPPING_RANDOM
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
void MOD_depsgraph_update_object_bone_relation(struct DepsNodeHandle *node, Object *object, const char *bonename, const char *description)
Definition: MOD_util.c:270
void weightvg_do_map(int num, float *new_w, short falloff_type, const bool do_invert, CurveMapping *cmap, RNG *rng)
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, MDeformWeight **dws, int num, const int *indices, const float *weights, const bool do_add, const float add_thresh, const bool do_rem, const float rem_thresh, const bool do_normalize)
void weightvg_do_mask(const ModifierEvalContext *ctx, const int num, const int *indices, float *org_w, const float *new_w, Object *ob, Mesh *mesh, const float fact, const char defgrp_name[MAX_VGROUP_NAME], Scene *scene, Tex *texture, const int tex_use_channel, const int tex_mapping, Object *tex_map_object, const char *text_map_bone, const char *tex_uvlayer_name, const bool invert_vgroup_mask)
void weightvg_ui_common(const bContext *C, PointerRNA *ob_ptr, PointerRNA *ptr, uiLayout *layout)
static void influence_panel_draw(const bContext *C, Panel *panel)
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
#define OUT_OF_MEMORY()
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void vert2geom_task_cb_ex(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict tls)
struct Vert2GeomData Vert2GeomData
static void falloff_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
ModifierTypeInfo modifierType_WeightVGProximity
static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
static void blendWrite(BlendWriter *writer, const ModifierData *md)
static void blendRead(BlendDataReader *reader, ModifierData *md)
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
static float get_ob2ob_distance(const Object *ob, const Object *obr)
static void get_vert2geom_distance(int numVerts, float(*v_cos)[3], float *dist_v, float *dist_e, float *dist_f, Mesh *target, const SpaceTransform *loc2trgt)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
struct Vert2GeomDataChunk Vert2GeomDataChunk
static void initData(ModifierData *md)
static void panelRegister(ARegionType *region_type)
static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
static void get_vert2ob_distance(int numVerts, float(*v_cos)[3], float *dist, Object *ob, Object *obr)
static void do_map(Object *ob, float *weights, const int nidx, const float min_d, const float max_d, short mode, const bool do_invert_mapping, CurveMapping *cmap)
static bool dependsOnTime(ModifierData *md)
static void freeData(ModifierData *md)
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
Platform independent time functions.
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
#define TIMEIT_END(var)
StructRNA RNA_VertexWeightProximityModifier
#define C
Definition: RandGen.cpp:39
@ UI_ITEM_R_EXPAND
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type, bool levels, bool brush, bool neg_slope, bool tone)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
Scene scene
static ushort indices[]
uint col
#define sqrtf(x)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
struct BVHTree * tree
Definition: BKE_bvhutils.h:66
float co[3]
Definition: BLI_kdopbvh.h:59
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
struct MDeformVert * dvert
int totvert
Mesh_Runtime runtime
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:153
struct Object * object
Definition: BKE_modifier.h:154
struct DepsNodeHandle * node
Definition: BKE_modifier.h:147
ListBase defbase
float obmat[4][4]
void * data
struct uiLayout * layout
Definition: rand.cc:48
size_t userdata_chunk_size
Definition: BLI_task.h:150
BVHTreeFromMesh * treeData[3]
const SpaceTransform * loc2trgt
struct CurveMapping * cmap_curve
PointerRNA * ptr
Definition: wm_files.c:3157