Blender V4.5
MOD_weightvg_util.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 by Bastien Montagne. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_utildefines.h"
10
11#include "BLI_math_color.h"
12#include "BLI_rand.h"
13#include "BLI_string.h"
14
15#include "BLT_translation.hh"
16
17#include "DNA_color_types.h" /* CurveMapping. */
18#include "DNA_mesh_types.h"
19#include "DNA_meshdata_types.h"
20#include "DNA_modifier_types.h"
21#include "DNA_object_types.h"
22#include "DNA_scene_types.h"
23
24#include "BKE_colortools.hh" /* CurveMapping. */
25#include "BKE_context.hh"
26#include "BKE_customdata.hh"
27#include "BKE_deform.hh"
28#include "BKE_modifier.hh"
29#include "BKE_texture.h" /* Texture masking. */
30
31#include "UI_interface.hh"
32#include "UI_resources.hh"
33
34#include "RNA_access.hh"
35
37
38#include "MEM_guardedalloc.h"
39#include "MOD_ui_common.hh"
40#include "MOD_util.hh"
41#include "MOD_weightvg_util.hh"
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 == nullptr)) ||
52 !ELEM(falloff_type,
60 {
61 return;
62 }
63
64 if (cmap && falloff_type == MOD_WVG_MAPPING_CURVE) {
66 }
67
68 /* Map each weight (vertex) to its new value, accordingly to the chosen mode. */
69 for (i = 0; i < num; i++) {
70 float fac = new_w[i];
71
72 /* Code borrowed from the warp modifier. */
73 /* Closely matches PROP_SMOOTH and similar. */
74 switch (falloff_type) {
76 fac = BKE_curvemapping_evaluateF(cmap, 0, fac);
77 break;
79 fac = fac * fac;
80 break;
82 fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
83 break;
85 fac = sqrtf(fac);
86 break;
88 fac = sqrtf(2 * fac - fac * fac);
89 break;
91 fac = BLI_rng_get_float(rng) * fac;
92 break;
94 fac = (fac >= 0.5f) ? 1.0f : 0.0f;
95 break;
97 BLI_assert(do_invert);
98 break;
99 default:
101 }
102
103 new_w[i] = do_invert ? 1.0f - fac : fac;
104 }
105}
106
108 const int num,
109 const int *indices,
110 float *org_w,
111 const float *new_w,
112 Object *ob,
113 Mesh *mesh,
114 const float fact,
115 const char defgrp_name[MAX_VGROUP_NAME],
116 Scene * /*scene*/,
117 Tex *texture,
118 const int tex_use_channel,
119 const int tex_mapping,
120 Object *tex_map_object,
121 const char *text_map_bone,
122 const char *tex_uvlayer_name,
123 const bool invert_vgroup_mask)
124{
125 int ref_didx;
126 int i;
127
128 /* If influence factor is null, nothing to do! */
129 if (fact == 0.0f) {
130 return;
131 }
132
133 /* If we want to mask vgroup weights from a texture. */
134 if (texture != nullptr) {
135 /* The texture coordinates. */
136 float(*tex_co)[3];
137 /* See mapping note below... */
139 const int verts_num = mesh->verts_num;
140
141 /* Use new generic get_texture_coords, but do not modify our DNA struct for it...
142 * XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters?
143 * What e.g. if a modifier wants to use several textures?
144 * Why use only v_co, and not mesh positions (or both)?
145 */
146 t_map.texture = texture;
147 t_map.map_object = tex_map_object;
148 STRNCPY(t_map.map_bone, text_map_bone);
149 STRNCPY(t_map.uvlayer_name, tex_uvlayer_name);
150 t_map.texmapping = tex_mapping;
151
152 tex_co = MEM_calloc_arrayN<float[3]>(verts_num, __func__);
153 MOD_get_texture_coords(&t_map, ctx, ob, mesh, nullptr, tex_co);
154
155 MOD_init_texture(&t_map, ctx);
156
157 /* For each weight (vertex), make the mix between org and new weights. */
158 for (i = 0; i < num; i++) {
159 int idx = indices ? indices[i] : i;
160 TexResult texres;
161 float hsv[3]; /* For HSV color space. */
162 bool do_color_manage = tex_use_channel != MOD_WVG_MASK_TEX_USE_INT;
163
164 BKE_texture_get_value(texture, tex_co[idx], &texres, do_color_manage);
165 /* Get the good channel value... */
166 switch (tex_use_channel) {
168 org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact)));
169 break;
171 org_w[i] = (new_w[i] * texres.trgba[0] * fact) +
172 (org_w[i] * (1.0f - (texres.trgba[0] * fact)));
173 break;
175 org_w[i] = (new_w[i] * texres.trgba[1] * fact) +
176 (org_w[i] * (1.0f - (texres.trgba[1] * fact)));
177 break;
179 org_w[i] = (new_w[i] * texres.trgba[2] * fact) +
180 (org_w[i] * (1.0f - (texres.trgba[2] * fact)));
181 break;
183 rgb_to_hsv_v(texres.trgba, hsv);
184 org_w[i] = (new_w[i] * hsv[0] * fact) + (org_w[i] * (1.0f - (hsv[0] * fact)));
185 break;
187 rgb_to_hsv_v(texres.trgba, hsv);
188 org_w[i] = (new_w[i] * hsv[1] * fact) + (org_w[i] * (1.0f - (hsv[1] * fact)));
189 break;
191 rgb_to_hsv_v(texres.trgba, hsv);
192 org_w[i] = (new_w[i] * hsv[2] * fact) + (org_w[i] * (1.0f - (hsv[2] * fact)));
193 break;
195 org_w[i] = (new_w[i] * texres.trgba[3] * fact) +
196 (org_w[i] * (1.0f - (texres.trgba[3] * fact)));
197 break;
198 default:
199 org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact)));
200 break;
201 }
202 }
203
204 MEM_freeN(tex_co);
205 }
206 else if ((ref_didx = BKE_id_defgroup_name_index(&mesh->id, defgrp_name)) != -1) {
207 /* Check whether we want to set vgroup weights from a constant weight factor or a vertex
208 * group.
209 */
210 /* Get vgroup idx from its name. */
211
212 /* Proceed only if vgroup is valid, else use constant factor. */
213 /* Get actual deform-verts (ie vertex group data). */
214 const MDeformVert *dvert = static_cast<const MDeformVert *>(
216 /* Proceed only if vgroup is valid, else assume factor = O. */
217 if (dvert == nullptr) {
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 ?
285 dws[i] :
286 ((defgrp_idx >= 0) ? BKE_defvert_find_index(dv, defgrp_idx) : nullptr);
287
288 if (do_normalize) {
289 w = (w - min_w) * norm_fac;
290 }
291 /* Never allow weights out of [0.0, 1.0] range. */
292 CLAMP(w, 0.0f, 1.0f);
293
294 /* If the vertex is in this vgroup, remove it if needed, or just update it. */
295 if (dw != nullptr) {
296 if (do_rem && w <= rem_thresh) {
298 }
299 else {
300 dw->weight = w;
301 }
302 }
303 /* Else, add it if needed! */
304 else if (do_add && w >= add_thresh) {
305 BKE_defvert_add_index_notest(dv, defgrp_idx, w);
306 }
307 }
308}
309
311{
312 PointerRNA mask_texture_ptr = RNA_pointer_get(ptr, "mask_texture");
313 bool has_mask_texture = !RNA_pointer_is_null(&mask_texture_ptr);
314 bool has_mask_vertex_group = RNA_string_length(ptr, "mask_vertex_group") != 0;
315 int mask_tex_mapping = RNA_enum_get(ptr, "mask_tex_mapping");
316
317 uiLayoutSetPropSep(layout, true);
318
319 layout->prop(ptr, "mask_constant", UI_ITEM_R_SLIDER, IFACE_("Global Influence:"), ICON_NONE);
320
321 if (!has_mask_texture) {
323 layout, ptr, ob_ptr, "mask_vertex_group", "invert_mask_vertex_group", std::nullopt);
324 }
325
326 if (!has_mask_vertex_group) {
327 uiTemplateID(layout,
328 C,
329 ptr,
330 "mask_texture",
331 "texture.new",
332 nullptr,
333 nullptr,
335 false,
336 IFACE_("Mask Texture"));
337
338 if (has_mask_texture) {
339 layout->prop(ptr, "mask_tex_use_channel", UI_ITEM_NONE, IFACE_("Channel"), ICON_NONE);
340 layout->prop(ptr, "mask_tex_mapping", UI_ITEM_NONE, std::nullopt, ICON_NONE);
341
342 if (mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
343 layout->prop(ptr, "mask_tex_map_object", UI_ITEM_NONE, IFACE_("Object"), ICON_NONE);
344 }
345 else if (mask_tex_mapping == MOD_DISP_MAP_UV && RNA_enum_get(ob_ptr, "type") == OB_MESH) {
346 PointerRNA obj_data_ptr = RNA_pointer_get(ob_ptr, "data");
348 layout, ptr, "mask_tex_uv_layer", &obj_data_ptr, "uv_layers", std::nullopt, ICON_NONE);
349 }
350 }
351 }
352}
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
void BKE_curvemapping_init(CurveMapping *cumap)
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
support for deformation groups and hooks.
void BKE_defvert_add_index_notest(MDeformVert *dv, int defgroup, float weight)
Definition deform.cc:845
MDeformWeight * BKE_defvert_find_index(const MDeformVert *dv, int defgroup)
Definition deform.cc:795
int BKE_id_defgroup_name_index(const ID *id, blender::StringRef name)
Definition deform.cc:538
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:763
void BKE_defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
Definition deform.cc:869
void BKE_texture_get_value(struct Tex *texture, const float *tex_co, struct TexResult *texres, bool use_color_management)
Definition texture.cc:712
#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])
ATTR_WARN_UNUSED_RESULT const size_t num
Random number functions.
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:88
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define CLAMP(a, b, c)
#define ELEM(...)
#define IFACE_(msgid)
@ CD_MDEFORMVERT
@ MOD_DISP_MAP_OBJECT
@ MOD_DISP_MAP_UV
@ 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_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 StringRefNull vgroup_prop, const std::optional< StringRefNull > invert_vgroup_prop, const std::optional< StringRefNull > text)
void MOD_init_texture(MappingInfoModifierData *dmd, const ModifierEvalContext *ctx)
Definition MOD_util.cc:36
void MOD_get_texture_coords(MappingInfoModifierData *dmd, const ModifierEvalContext *, Object *ob, Mesh *mesh, float(*cos)[3], float(*r_texco)[3])
Definition MOD_util.cc:49
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_ui_common(const bContext *C, PointerRNA *ob_ptr, PointerRNA *ptr, uiLayout *layout)
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 *, 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)
#define C
Definition RandGen.cpp:29
@ UI_TEMPLATE_ID_FILTER_ALL
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, blender::StringRefNull propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, std::optional< blender::StringRef > text=std::nullopt)
@ UI_ITEM_R_SLIDER
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, PointerRNA *searchptr, blender::StringRefNull searchpropname, std::optional< blender::StringRefNull > name, int icon)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
#define fabsf(x)
#define sqrtf(x)
static ushort indices[]
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
int RNA_string_length(PointerRNA *ptr, const char *name)
bool RNA_pointer_is_null(const PointerRNA *ptr)
int RNA_enum_get(PointerRNA *ptr, const char *name)
CustomData vert_data
int verts_num
Definition rand.cc:33
float tin
Definition RE_texture.h:83
float trgba[4]
Definition RE_texture.h:84
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4226