diff options
Diffstat (limited to 'source/blender/modifiers/intern/MOD_weightvg_util.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_weightvg_util.c | 371 |
1 files changed, 195 insertions, 176 deletions
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index d0631a0c30b..3e1c2f9bc02 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -27,18 +27,18 @@ #include "BLI_rand.h" #include "BLI_string.h" -#include "DNA_color_types.h" /* CurveMapping. */ +#include "DNA_color_types.h" /* CurveMapping. */ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_colortools.h" /* CurveMapping. */ +#include "BKE_colortools.h" /* CurveMapping. */ #include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_modifier.h" -#include "BKE_texture.h" /* Texture masking. */ +#include "BKE_texture.h" /* Texture masking. */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -46,7 +46,7 @@ #include "MEM_guardedalloc.h" #include "MOD_util.h" #include "MOD_weightvg_util.h" -#include "RE_shader_ext.h" /* Texture masking. */ +#include "RE_shader_ext.h" /* Texture masking. */ /* Maps new_w weights in place, using either one of the predefined functions, or a custom curve. * Return values are in new_w. @@ -56,54 +56,57 @@ */ void weightvg_do_map(int num, float *new_w, short falloff_type, CurveMapping *cmap, RNG *rng) { - int i; + int i; - /* Return immediately, if we have nothing to do! */ - /* Also security checks... */ - if (((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) || - !ELEM(falloff_type, MOD_WVG_MAPPING_CURVE, MOD_WVG_MAPPING_SHARP, MOD_WVG_MAPPING_SMOOTH, - MOD_WVG_MAPPING_ROOT, MOD_WVG_MAPPING_SPHERE, MOD_WVG_MAPPING_RANDOM, - MOD_WVG_MAPPING_STEP)) - { - return; - } + /* Return immediately, if we have nothing to do! */ + /* Also security checks... */ + if (((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) || !ELEM(falloff_type, + MOD_WVG_MAPPING_CURVE, + MOD_WVG_MAPPING_SHARP, + MOD_WVG_MAPPING_SMOOTH, + MOD_WVG_MAPPING_ROOT, + MOD_WVG_MAPPING_SPHERE, + MOD_WVG_MAPPING_RANDOM, + MOD_WVG_MAPPING_STEP)) { + return; + } - if (cmap && falloff_type == MOD_WVG_MAPPING_CURVE) { - curvemapping_initialize(cmap); - } + if (cmap && falloff_type == MOD_WVG_MAPPING_CURVE) { + curvemapping_initialize(cmap); + } - /* Map each weight (vertex) to its new value, accordingly to the chosen mode. */ - for (i = 0; i < num; ++i) { - float fac = new_w[i]; + /* Map each weight (vertex) to its new value, accordingly to the chosen mode. */ + for (i = 0; i < num; ++i) { + float fac = new_w[i]; - /* Code borrowed from the warp modifier. */ - /* Closely matches PROP_SMOOTH and similar. */ - switch (falloff_type) { - case MOD_WVG_MAPPING_CURVE: - fac = curvemapping_evaluateF(cmap, 0, fac); - break; - case MOD_WVG_MAPPING_SHARP: - fac = fac * fac; - break; - case MOD_WVG_MAPPING_SMOOTH: - fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; - break; - case MOD_WVG_MAPPING_ROOT: - fac = sqrtf(fac); - break; - case MOD_WVG_MAPPING_SPHERE: - fac = sqrtf(2 * fac - fac * fac); - break; - case MOD_WVG_MAPPING_RANDOM: - fac = BLI_rng_get_float(rng) * fac; - break; - case MOD_WVG_MAPPING_STEP: - fac = (fac >= 0.5f) ? 1.0f : 0.0f; - break; - } + /* Code borrowed from the warp modifier. */ + /* Closely matches PROP_SMOOTH and similar. */ + switch (falloff_type) { + case MOD_WVG_MAPPING_CURVE: + fac = curvemapping_evaluateF(cmap, 0, fac); + break; + case MOD_WVG_MAPPING_SHARP: + fac = fac * fac; + break; + case MOD_WVG_MAPPING_SMOOTH: + fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; + break; + case MOD_WVG_MAPPING_ROOT: + fac = sqrtf(fac); + break; + case MOD_WVG_MAPPING_SPHERE: + fac = sqrtf(2 * fac - fac * fac); + break; + case MOD_WVG_MAPPING_RANDOM: + fac = BLI_rng_get_float(rng) * fac; + break; + case MOD_WVG_MAPPING_STEP: + fac = (fac >= 0.5f) ? 1.0f : 0.0f; + break; + } - new_w[i] = fac; - } + new_w[i] = fac; + } } /* Applies new_w weights to org_w ones, using either a texture, vgroup or constant value as factor. @@ -112,158 +115,174 @@ void weightvg_do_map(int num, float *new_w, short falloff_type, CurveMapping *cm * vertex index (in case the weight tables do not cover the whole vertices...). * XXX The standard "factor" value is assumed in [0.0, 1.0] range. Else, weird results might appear. */ -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 *tex_uvlayer_name) +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 *tex_uvlayer_name) { - int ref_didx; - int i; + int ref_didx; + int i; - /* If influence factor is null, nothing to do! */ - if (fact == 0.0f) return; + /* If influence factor is null, nothing to do! */ + if (fact == 0.0f) + return; - /* If we want to mask vgroup weights from a texture. */ - if (texture != NULL) { - /* The texture coordinates. */ - float (*tex_co)[3]; - /* See mapping note below... */ - MappingInfoModifierData t_map; - const int numVerts = mesh->totvert; + /* If we want to mask vgroup weights from a texture. */ + if (texture != NULL) { + /* The texture coordinates. */ + float(*tex_co)[3]; + /* See mapping note below... */ + MappingInfoModifierData t_map; + const int numVerts = mesh->totvert; - /* Use new generic get_texture_coords, but do not modify our DNA struct for it... - * XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters ? - * What e.g. if a modifier wants to use several textures ? - * Why use only v_co, and not MVert (or both) ? - */ - t_map.texture = texture; - t_map.map_object = tex_map_object; - BLI_strncpy(t_map.uvlayer_name, tex_uvlayer_name, sizeof(t_map.uvlayer_name)); - t_map.texmapping = tex_mapping; + /* Use new generic get_texture_coords, but do not modify our DNA struct for it... + * XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters ? + * What e.g. if a modifier wants to use several textures ? + * Why use only v_co, and not MVert (or both) ? + */ + t_map.texture = texture; + t_map.map_object = tex_map_object; + BLI_strncpy(t_map.uvlayer_name, tex_uvlayer_name, sizeof(t_map.uvlayer_name)); + t_map.texmapping = tex_mapping; - tex_co = MEM_calloc_arrayN(numVerts, sizeof(*tex_co), "WeightVG Modifier, TEX mode, tex_co"); - MOD_get_texture_coords(&t_map, ctx, ob, mesh, NULL, tex_co); + tex_co = MEM_calloc_arrayN(numVerts, sizeof(*tex_co), "WeightVG Modifier, TEX mode, tex_co"); + MOD_get_texture_coords(&t_map, ctx, ob, mesh, NULL, tex_co); - MOD_init_texture(&t_map, ctx); + MOD_init_texture(&t_map, ctx); - /* For each weight (vertex), make the mix between org and new weights. */ - for (i = 0; i < num; ++i) { - int idx = indices ? indices[i] : i; - TexResult texres; - float hsv[3]; /* For HSV color space. */ - bool do_color_manage; + /* For each weight (vertex), make the mix between org and new weights. */ + for (i = 0; i < num; ++i) { + int idx = indices ? indices[i] : i; + TexResult texres; + float hsv[3]; /* For HSV color space. */ + bool do_color_manage; - do_color_manage = tex_use_channel != MOD_WVG_MASK_TEX_USE_INT; + do_color_manage = tex_use_channel != MOD_WVG_MASK_TEX_USE_INT; - texres.nor = NULL; - BKE_texture_get_value(scene, texture, tex_co[idx], &texres, do_color_manage); - /* Get the good channel value... */ - switch (tex_use_channel) { - case MOD_WVG_MASK_TEX_USE_INT: - org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact))); - break; - case MOD_WVG_MASK_TEX_USE_RED: - org_w[i] = (new_w[i] * texres.tr * fact) + (org_w[i] * (1.0f - (texres.tr * fact))); - break; - case MOD_WVG_MASK_TEX_USE_GREEN: - org_w[i] = (new_w[i] * texres.tg * fact) + (org_w[i] * (1.0f - (texres.tg * fact))); - break; - case MOD_WVG_MASK_TEX_USE_BLUE: - org_w[i] = (new_w[i] * texres.tb * fact) + (org_w[i] * (1.0f - (texres.tb * fact))); - break; - case MOD_WVG_MASK_TEX_USE_HUE: - rgb_to_hsv_v(&texres.tr, hsv); - org_w[i] = (new_w[i] * hsv[0] * fact) + (org_w[i] * (1.0f - (hsv[0] * fact))); - break; - case MOD_WVG_MASK_TEX_USE_SAT: - rgb_to_hsv_v(&texres.tr, hsv); - org_w[i] = (new_w[i] * hsv[1] * fact) + (org_w[i] * (1.0f - (hsv[1] * fact))); - break; - case MOD_WVG_MASK_TEX_USE_VAL: - rgb_to_hsv_v(&texres.tr, hsv); - org_w[i] = (new_w[i] * hsv[2] * fact) + (org_w[i] * (1.0f - (hsv[2] * fact))); - break; - case MOD_WVG_MASK_TEX_USE_ALPHA: - org_w[i] = (new_w[i] * texres.ta * fact) + (org_w[i] * (1.0f - (texres.ta * fact))); - break; - default: - org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact))); - break; - } - } + texres.nor = NULL; + BKE_texture_get_value(scene, texture, tex_co[idx], &texres, do_color_manage); + /* Get the good channel value... */ + switch (tex_use_channel) { + case MOD_WVG_MASK_TEX_USE_INT: + org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact))); + break; + case MOD_WVG_MASK_TEX_USE_RED: + org_w[i] = (new_w[i] * texres.tr * fact) + (org_w[i] * (1.0f - (texres.tr * fact))); + break; + case MOD_WVG_MASK_TEX_USE_GREEN: + org_w[i] = (new_w[i] * texres.tg * fact) + (org_w[i] * (1.0f - (texres.tg * fact))); + break; + case MOD_WVG_MASK_TEX_USE_BLUE: + org_w[i] = (new_w[i] * texres.tb * fact) + (org_w[i] * (1.0f - (texres.tb * fact))); + break; + case MOD_WVG_MASK_TEX_USE_HUE: + rgb_to_hsv_v(&texres.tr, hsv); + org_w[i] = (new_w[i] * hsv[0] * fact) + (org_w[i] * (1.0f - (hsv[0] * fact))); + break; + case MOD_WVG_MASK_TEX_USE_SAT: + rgb_to_hsv_v(&texres.tr, hsv); + org_w[i] = (new_w[i] * hsv[1] * fact) + (org_w[i] * (1.0f - (hsv[1] * fact))); + break; + case MOD_WVG_MASK_TEX_USE_VAL: + rgb_to_hsv_v(&texres.tr, hsv); + org_w[i] = (new_w[i] * hsv[2] * fact) + (org_w[i] * (1.0f - (hsv[2] * fact))); + break; + case MOD_WVG_MASK_TEX_USE_ALPHA: + org_w[i] = (new_w[i] * texres.ta * fact) + (org_w[i] * (1.0f - (texres.ta * fact))); + break; + default: + org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact))); + break; + } + } - MEM_freeN(tex_co); - } - else if ((ref_didx = defgroup_name_index(ob, defgrp_name)) != -1) { - MDeformVert *dvert = NULL; + MEM_freeN(tex_co); + } + else if ((ref_didx = defgroup_name_index(ob, defgrp_name)) != -1) { + MDeformVert *dvert = NULL; - /* Check whether we want to set vgroup weights from a constant weight factor or a vertex - * group. - */ - /* Get vgroup idx from its name. */ + /* Check whether we want to set vgroup weights from a constant weight factor or a vertex + * group. + */ + /* Get vgroup idx from its name. */ - /* Proceed only if vgroup is valid, else use constant factor. */ - /* Get actual dverts (ie vertex group data). */ - dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT); - /* Proceed only if vgroup is valid, else assume factor = O. */ - if (dvert == NULL) { - return; - } + /* Proceed only if vgroup is valid, else use constant factor. */ + /* Get actual dverts (ie vertex group data). */ + dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT); + /* Proceed only if vgroup is valid, else assume factor = O. */ + if (dvert == NULL) { + return; + } - /* For each weight (vertex), make the mix between org and new weights. */ - for (i = 0; i < num; i++) { - int idx = indices ? indices[i] : i; - const float f = defvert_find_weight(&dvert[idx], ref_didx) * fact; - org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f - f)); - /* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */ - } - } - else { - /* Default "influence" behavior. */ - /* For each weight (vertex), make the mix between org and new weights. */ - const float ifact = 1.0f - fact; - for (i = 0; i < num; i++) { - org_w[i] = (new_w[i] * fact) + (org_w[i] * ifact); - } - } + /* For each weight (vertex), make the mix between org and new weights. */ + for (i = 0; i < num; i++) { + int idx = indices ? indices[i] : i; + const float f = defvert_find_weight(&dvert[idx], ref_didx) * fact; + org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f - f)); + /* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */ + } + } + else { + /* Default "influence" behavior. */ + /* For each weight (vertex), make the mix between org and new weights. */ + const float ifact = 1.0f - fact; + for (i = 0; i < num; i++) { + org_w[i] = (new_w[i] * fact) + (org_w[i] * ifact); + } + } } - /* Applies weights to given vgroup (defgroup), and optionally add/remove vertices from the group. * If dws is not NULL, it must be an array of MDeformWeight pointers of same length as weights (and * defgrp_idx can then have any value). * If indices is not NULL, it must be an array of same length as weights, mapping to the real * vertex index (in case the weight array does not cover the whole vertices...). */ -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) +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) { - int i; + int i; - for (i = 0; i < num; i++) { - float w = weights[i]; - MDeformVert *dv = &dvert[indices ? indices[i] : i]; - MDeformWeight *dw = dws ? dws[i] : ((defgrp_idx >= 0) ? defvert_find_index(dv, defgrp_idx) : NULL); + for (i = 0; i < num; i++) { + float w = weights[i]; + MDeformVert *dv = &dvert[indices ? indices[i] : i]; + MDeformWeight *dw = dws ? dws[i] : + ((defgrp_idx >= 0) ? defvert_find_index(dv, defgrp_idx) : NULL); - /* Never allow weights out of [0.0, 1.0] range. */ - CLAMP(w, 0.0f, 1.0f); + /* Never allow weights out of [0.0, 1.0] range. */ + CLAMP(w, 0.0f, 1.0f); - /* If the vertex is in this vgroup, remove it if needed, or just update it. */ - if (dw != NULL) { - if (do_rem && w < rem_thresh) { - defvert_remove_group(dv, dw); - } - else { - dw->weight = w; - } - } - /* Else, add it if needed! */ - else if (do_add && w > add_thresh) { - defvert_add_index_notest(dv, defgrp_idx, w); - } - } + /* If the vertex is in this vgroup, remove it if needed, or just update it. */ + if (dw != NULL) { + if (do_rem && w < rem_thresh) { + defvert_remove_group(dv, dw); + } + else { + dw->weight = w; + } + } + /* Else, add it if needed! */ + else if (do_add && w > add_thresh) { + defvert_add_index_notest(dv, defgrp_idx, w); + } + } } |