Blender  V3.3
MOD_weightvg_util.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 by Bastien Montagne. All rights reserved. */
3 
8 #include "BLI_utildefines.h"
9 
10 #include "BLI_math.h"
11 #include "BLI_rand.h"
12 #include "BLI_string.h"
13 
14 #include "BLT_translation.h"
15 
16 #include "DNA_color_types.h" /* CurveMapping. */
17 #include "DNA_mesh_types.h"
18 #include "DNA_meshdata_types.h"
19 #include "DNA_modifier_types.h"
20 #include "DNA_object_types.h"
21 #include "DNA_scene_types.h"
22 
23 #include "BKE_colortools.h" /* CurveMapping. */
24 #include "BKE_context.h"
25 #include "BKE_customdata.h"
26 #include "BKE_deform.h"
27 #include "BKE_modifier.h"
28 #include "BKE_texture.h" /* Texture masking. */
29 
30 #include "UI_interface.h"
31 #include "UI_resources.h"
32 
33 #include "RNA_access.h"
34 
35 #include "DEG_depsgraph.h"
36 #include "DEG_depsgraph_query.h"
37 
38 #include "MEM_guardedalloc.h"
39 #include "MOD_ui_common.h"
40 #include "MOD_util.h"
41 #include "MOD_weightvg_util.h"
42 #include "RE_texture.h" /* Texture masking. */
43 
45  int num, float *new_w, short falloff_type, const bool do_invert, CurveMapping *cmap, RNG *rng)
46 {
47  int i;
48 
49  /* Return immediately, if we have nothing to do! */
50  /* Also security checks... */
51  if (!do_invert && (((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) ||
52  !ELEM(falloff_type,
60  return;
61  }
62 
63  if (cmap && falloff_type == MOD_WVG_MAPPING_CURVE) {
65  }
66 
67  /* Map each weight (vertex) to its new value, accordingly to the chosen mode. */
68  for (i = 0; i < num; i++) {
69  float fac = new_w[i];
70 
71  /* Code borrowed from the warp modifier. */
72  /* Closely matches PROP_SMOOTH and similar. */
73  switch (falloff_type) {
75  fac = BKE_curvemapping_evaluateF(cmap, 0, fac);
76  break;
78  fac = fac * fac;
79  break;
81  fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
82  break;
84  fac = sqrtf(fac);
85  break;
87  fac = sqrtf(2 * fac - fac * fac);
88  break;
90  fac = BLI_rng_get_float(rng) * fac;
91  break;
93  fac = (fac >= 0.5f) ? 1.0f : 0.0f;
94  break;
96  BLI_assert(do_invert);
97  break;
98  default:
100  }
101 
102  new_w[i] = do_invert ? 1.0f - fac : fac;
103  }
104 }
105 
107  const int num,
108  const int *indices,
109  float *org_w,
110  const float *new_w,
111  Object *ob,
112  Mesh *mesh,
113  const float fact,
114  const char defgrp_name[MAX_VGROUP_NAME],
115  Scene *scene,
116  Tex *texture,
117  const int tex_use_channel,
118  const int tex_mapping,
119  Object *tex_map_object,
120  const char *text_map_bone,
121  const char *tex_uvlayer_name,
122  const bool invert_vgroup_mask)
123 {
124  int ref_didx;
125  int i;
126 
127  /* If influence factor is null, nothing to do! */
128  if (fact == 0.0f) {
129  return;
130  }
131 
132  /* If we want to mask vgroup weights from a texture. */
133  if (texture != NULL) {
134  /* The texture coordinates. */
135  float(*tex_co)[3];
136  /* See mapping note below... */
138  const int verts_num = mesh->totvert;
139 
140  /* Use new generic get_texture_coords, but do not modify our DNA struct for it...
141  * XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters?
142  * What e.g. if a modifier wants to use several textures?
143  * Why use only v_co, and not MVert (or both)?
144  */
145  t_map.texture = texture;
146  t_map.map_object = tex_map_object;
147  BLI_strncpy(t_map.map_bone, text_map_bone, sizeof(t_map.map_bone));
148  BLI_strncpy(t_map.uvlayer_name, tex_uvlayer_name, sizeof(t_map.uvlayer_name));
149  t_map.texmapping = tex_mapping;
150 
151  tex_co = MEM_calloc_arrayN(verts_num, sizeof(*tex_co), "WeightVG Modifier, TEX mode, tex_co");
152  MOD_get_texture_coords(&t_map, ctx, ob, mesh, NULL, tex_co);
153 
154  MOD_init_texture(&t_map, ctx);
155 
156  /* For each weight (vertex), make the mix between org and new weights. */
157  for (i = 0; i < num; i++) {
158  int idx = indices ? indices[i] : i;
159  TexResult texres;
160  float hsv[3]; /* For HSV color space. */
161  bool do_color_manage;
162 
163  do_color_manage = tex_use_channel != MOD_WVG_MASK_TEX_USE_INT;
164 
165  BKE_texture_get_value(scene, texture, tex_co[idx], &texres, do_color_manage);
166  /* Get the good channel value... */
167  switch (tex_use_channel) {
169  org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact)));
170  break;
172  org_w[i] = (new_w[i] * texres.trgba[0] * fact) +
173  (org_w[i] * (1.0f - (texres.trgba[0] * fact)));
174  break;
176  org_w[i] = (new_w[i] * texres.trgba[1] * fact) +
177  (org_w[i] * (1.0f - (texres.trgba[1] * fact)));
178  break;
180  org_w[i] = (new_w[i] * texres.trgba[2] * fact) +
181  (org_w[i] * (1.0f - (texres.trgba[2] * fact)));
182  break;
184  rgb_to_hsv_v(texres.trgba, hsv);
185  org_w[i] = (new_w[i] * hsv[0] * fact) + (org_w[i] * (1.0f - (hsv[0] * fact)));
186  break;
188  rgb_to_hsv_v(texres.trgba, hsv);
189  org_w[i] = (new_w[i] * hsv[1] * fact) + (org_w[i] * (1.0f - (hsv[1] * fact)));
190  break;
192  rgb_to_hsv_v(texres.trgba, hsv);
193  org_w[i] = (new_w[i] * hsv[2] * fact) + (org_w[i] * (1.0f - (hsv[2] * fact)));
194  break;
196  org_w[i] = (new_w[i] * texres.trgba[3] * fact) +
197  (org_w[i] * (1.0f - (texres.trgba[3] * fact)));
198  break;
199  default:
200  org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact)));
201  break;
202  }
203  }
204 
205  MEM_freeN(tex_co);
206  }
207  else if ((ref_didx = BKE_id_defgroup_name_index(&mesh->id, defgrp_name)) != -1) {
208  /* Check whether we want to set vgroup weights from a constant weight factor or a vertex
209  * group.
210  */
211  /* Get vgroup idx from its name. */
212 
213  /* Proceed only if vgroup is valid, else use constant factor. */
214  /* Get actual dverts (ie vertex group data). */
216  /* Proceed only if vgroup is valid, else assume factor = O. */
217  if (dvert == NULL) {
218  return;
219  }
220 
221  /* For each weight (vertex), make the mix between org and new weights. */
222  for (i = 0; i < num; i++) {
223  int idx = indices ? indices[i] : i;
224  const float f = (invert_vgroup_mask ?
225  (1.0f - BKE_defvert_find_weight(&dvert[idx], ref_didx)) :
226  BKE_defvert_find_weight(&dvert[idx], ref_didx)) *
227  fact;
228  org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f - f));
229  /* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */
230  }
231  }
232  else {
233  /* Default "influence" behavior. */
234  /* For each weight (vertex), make the mix between org and new weights. */
235  const float ifact = 1.0f - fact;
236  for (i = 0; i < num; i++) {
237  org_w[i] = (new_w[i] * fact) + (org_w[i] * ifact);
238  }
239  }
240 }
241 
243  int defgrp_idx,
244  MDeformWeight **dws,
245  int num,
246  const int *indices,
247  const float *weights,
248  const bool do_add,
249  const float add_thresh,
250  const bool do_rem,
251  const float rem_thresh,
252  const bool do_normalize)
253 {
254  int i;
255 
256  float min_w = weights[0];
257  float norm_fac = 1.0f;
258  if (do_normalize) {
259  float max_w = weights[0];
260  for (i = 1; i < num; i++) {
261  const float w = weights[i];
262 
263  /* No need to clamp here, normalization will ensure we stay within [0.0, 1.0] range. */
264  if (w < min_w) {
265  min_w = w;
266  }
267  else if (w > max_w) {
268  max_w = w;
269  }
270  }
271 
272  const float range = max_w - min_w;
273  if (fabsf(range) > FLT_EPSILON) {
274  norm_fac = 1.0f / range;
275  }
276  else {
277  min_w = 0.0f;
278  }
279  }
280 
281  for (i = 0; i < num; i++) {
282  float w = weights[i];
283  MDeformVert *dv = &dvert[indices ? indices[i] : i];
284  MDeformWeight *dw = dws ? dws[i] :
285  ((defgrp_idx >= 0) ? BKE_defvert_find_index(dv, defgrp_idx) : NULL);
286 
287  if (do_normalize) {
288  w = (w - min_w) * norm_fac;
289  }
290  /* Never allow weights out of [0.0, 1.0] range. */
291  CLAMP(w, 0.0f, 1.0f);
292 
293  /* If the vertex is in this vgroup, remove it if needed, or just update it. */
294  if (dw != NULL) {
295  if (do_rem && w < rem_thresh) {
296  BKE_defvert_remove_group(dv, dw);
297  }
298  else {
299  dw->weight = w;
300  }
301  }
302  /* Else, add it if needed! */
303  else if (do_add && w > add_thresh) {
304  BKE_defvert_add_index_notest(dv, defgrp_idx, w);
305  }
306  }
307 }
308 
310 {
311  PointerRNA mask_texture_ptr = RNA_pointer_get(ptr, "mask_texture");
312  bool has_mask_texture = !RNA_pointer_is_null(&mask_texture_ptr);
313  bool has_mask_vertex_group = RNA_string_length(ptr, "mask_vertex_group") != 0;
314  int mask_tex_mapping = RNA_enum_get(ptr, "mask_tex_mapping");
315 
316  uiLayoutSetPropSep(layout, true);
317 
318  uiItemR(layout, ptr, "mask_constant", UI_ITEM_R_SLIDER, IFACE_("Global Influence:"), ICON_NONE);
319 
320  if (!has_mask_texture) {
321  modifier_vgroup_ui(layout, ptr, ob_ptr, "mask_vertex_group", "invert_mask_vertex_group", NULL);
322  }
323 
324  if (!has_mask_vertex_group) {
325  uiTemplateID(layout,
326  C,
327  ptr,
328  "mask_texture",
329  "texture.new",
330  NULL,
331  NULL,
332  0,
333  ICON_NONE,
334  IFACE_("Mask Texture"));
335 
336  if (has_mask_texture) {
337  uiItemR(layout, ptr, "mask_tex_use_channel", 0, IFACE_("Channel"), ICON_NONE);
338  uiItemR(layout, ptr, "mask_tex_mapping", 0, NULL, ICON_NONE);
339 
340  if (mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
341  uiItemR(layout, ptr, "mask_tex_map_object", 0, IFACE_("Object"), ICON_NONE);
342  }
343  else if (mask_tex_mapping == MOD_DISP_MAP_UV && RNA_enum_get(ob_ptr, "type") == OB_MESH) {
344  PointerRNA obj_data_ptr = RNA_pointer_get(ob_ptr, "data");
346  layout, ptr, "mask_tex_uv_layer", &obj_data_ptr, "uv_layers", NULL, ICON_NONE);
347  }
348  }
349  }
350 }
typedef float(TangentPoint)[2]
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1235
float BKE_curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value)
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_layer(const struct CustomData *data, int type)
support for deformation groups and hooks.
struct MDeformWeight * BKE_defvert_find_index(const struct MDeformVert *dv, int defgroup)
void BKE_defvert_remove_group(struct MDeformVert *dvert, struct MDeformWeight *dw)
Definition: deform.c:804
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
int BKE_id_defgroup_name_index(const struct ID *id, const char *name)
void BKE_defvert_add_index_notest(struct MDeformVert *dv, int defgroup, float weight)
Definition: deform.c:779
void BKE_texture_get_value(const struct Scene *scene, struct Tex *texture, const float *tex_co, struct TexResult *texres, bool use_color_management)
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:232
Random number functions.
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: rand.cc:93
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define ELEM(...)
#define IFACE_(msgid)
@ CD_MDEFORMVERT
@ MOD_WVG_MASK_TEX_USE_SAT
@ MOD_WVG_MASK_TEX_USE_BLUE
@ MOD_WVG_MASK_TEX_USE_INT
@ MOD_WVG_MASK_TEX_USE_ALPHA
@ MOD_WVG_MASK_TEX_USE_RED
@ MOD_WVG_MASK_TEX_USE_HUE
@ MOD_WVG_MASK_TEX_USE_VAL
@ MOD_WVG_MASK_TEX_USE_GREEN
@ MOD_DISP_MAP_OBJECT
@ MOD_DISP_MAP_UV
@ MOD_WVG_MAPPING_SHARP
@ MOD_WVG_MAPPING_SPHERE
@ MOD_WVG_MAPPING_STEP
@ MOD_WVG_MAPPING_NONE
@ MOD_WVG_MAPPING_ROOT
@ MOD_WVG_MAPPING_CURVE
@ MOD_WVG_MAPPING_RANDOM
@ MOD_WVG_MAPPING_SMOOTH
Object is a sort of wrapper for general info.
@ OB_MESH
#define MAX_VGROUP_NAME
Read Guarded memory(de)allocation.
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_init_texture(MappingInfoModifierData *dmd, const ModifierEvalContext *ctx)
Definition: MOD_util.c:45
void MOD_get_texture_coords(MappingInfoModifierData *dmd, const ModifierEvalContext *UNUSED(ctx), Object *ob, Mesh *mesh, float(*cos)[3], float(*r_texco)[3])
Definition: MOD_util.c:59
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)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define C
Definition: RandGen.cpp:25
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
@ UI_ITEM_R_SLIDER
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiTemplateID(uiLayout *layout, const struct bContext *C, struct PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int filter, bool live_icon, const char *text)
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
Scene scene
ccl_gpu_kernel_postfix int ccl_global int * indices
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5167
int RNA_string_length(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5144
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:164
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
CustomData vdata
int totvert
Definition: rand.cc:33
float tin
Definition: RE_texture.h:86
float trgba[4]
Definition: RE_texture.h:87
PointerRNA * ptr
Definition: wm_files.c:3480