forked from bartvdbraak/blender
Adding WeightVG modifiers code. Still some points to tweak, though.
NOTE : Haven’t yet tested build with scons, will do asap (unless someone else does :) ).
This commit is contained in:
parent
110f6d81ec
commit
1e2e080853
Binary file not shown.
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 206 KiB |
@ -735,5 +735,134 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
|
|||||||
col.prop(md, "width", slider=True)
|
col.prop(md, "width", slider=True)
|
||||||
col.prop(md, "narrowness", slider=True)
|
col.prop(md, "narrowness", slider=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def weight_vg_mask(layout, ob, md):
|
||||||
|
layout.label(text="Influence/Mask Options:")
|
||||||
|
split = layout.split()
|
||||||
|
col1 = split.column()
|
||||||
|
col2 = split.column()
|
||||||
|
|
||||||
|
col1.label(text="Global Influence:")
|
||||||
|
col2.prop(md, "mask_constant", text="")
|
||||||
|
|
||||||
|
if not md.mask_texture:
|
||||||
|
col1.label(text="Vertex Group Mask:")
|
||||||
|
col2.prop_search(md, "mask_vertex_group", ob, "vertex_groups", text="")
|
||||||
|
|
||||||
|
if not md.mask_vertex_group:
|
||||||
|
col1.label(text="Texture Mask:")
|
||||||
|
col2.template_ID(md, "mask_texture", new="texture.new")
|
||||||
|
if md.mask_texture:
|
||||||
|
split = layout.split()
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Texture Coordinates:")
|
||||||
|
col.prop(md, "mask_tex_mapping", text="")
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Use Channel:")
|
||||||
|
col.prop(md, "mask_tex_use_channel", text="")
|
||||||
|
|
||||||
|
if md.mask_tex_mapping == 'OBJECT':
|
||||||
|
layout.prop(md, "mask_tex_map_obj", text="Object")
|
||||||
|
elif md.mask_tex_mapping == 'UV' and ob.type == 'MESH':
|
||||||
|
layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_textures")
|
||||||
|
|
||||||
|
def WEIGHT_VGEDIT(self, layout, ob, md):
|
||||||
|
if ob.type == 'MESH':
|
||||||
|
split = layout.split()
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Vertex Group:")
|
||||||
|
col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||||
|
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Default Weight:")
|
||||||
|
col.prop(md, "default_weight", text="")
|
||||||
|
|
||||||
|
layout.prop(md, "flag_map")
|
||||||
|
if md.flag_map:
|
||||||
|
split = layout.split()
|
||||||
|
col = split.column()
|
||||||
|
col.label("Input:")
|
||||||
|
col.label("Output:")
|
||||||
|
col = split.column()
|
||||||
|
col.prop(md, "map_input_low", text="Min")
|
||||||
|
col.prop(md, "map_output_low", text="Min")
|
||||||
|
col = split.column()
|
||||||
|
col.prop(md, "map_input_high", text="Max")
|
||||||
|
col.prop(md, "map_output_high", text="Max")
|
||||||
|
|
||||||
|
layout.prop(md, "flag_curve_map")
|
||||||
|
if md.flag_curve_map:
|
||||||
|
row = layout.row()
|
||||||
|
row.template_curve_mapping(md, "cmap_curve")
|
||||||
|
|
||||||
|
layout.prop(md, "flag_reverse")
|
||||||
|
|
||||||
|
layout.prop(md, "flag_clamp")
|
||||||
|
if md.flag_clamp:
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(md, "clamp_min_weight")
|
||||||
|
row.prop(md, "clamp_max_weight")
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(md, "flag_add2vg")
|
||||||
|
row.prop(md, "flag_remfvg")
|
||||||
|
row = layout.row()
|
||||||
|
if md.flag_add2vg:
|
||||||
|
row.prop(md, "add_threshold")
|
||||||
|
if md.flag_remfvg:
|
||||||
|
row.prop(md, "rem_threshold")
|
||||||
|
|
||||||
|
# Common mask options…
|
||||||
|
layout.separator()
|
||||||
|
self.weight_vg_mask(layout, ob, md)
|
||||||
|
|
||||||
|
def WEIGHT_VGMIX(self, layout, ob, md):
|
||||||
|
if ob.type == 'MESH':
|
||||||
|
split = layout.split()
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Vertex Group 1:")
|
||||||
|
col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||||
|
col.label(text="Default Weight 1:")
|
||||||
|
col.prop(md, "default_weight", text="")
|
||||||
|
|
||||||
|
col.label(text="Mix Mode:")
|
||||||
|
col.prop(md, "mix_mode", text="")
|
||||||
|
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Vertex Group 2:")
|
||||||
|
col.prop_search(md, "vertex_group2", ob, "vertex_groups", text="")
|
||||||
|
col.label(text="Default Weight 2:")
|
||||||
|
col.prop(md, "default_weight2", text="")
|
||||||
|
|
||||||
|
col.label(text="Mix Set:")
|
||||||
|
col.prop(md, "mix_set", text="")
|
||||||
|
|
||||||
|
# Common mask options…
|
||||||
|
layout.separator()
|
||||||
|
self.weight_vg_mask(layout, ob, md)
|
||||||
|
|
||||||
|
def WEIGHT_VGPROXIMITY(self, layout, ob, md):
|
||||||
|
if ob.type == 'MESH':
|
||||||
|
split = layout.split()
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Vertex Group:")
|
||||||
|
col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||||
|
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Target Object:")
|
||||||
|
col.prop(md, "ob_target", text="")
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(md, "proximity_mode", expand=True)
|
||||||
|
if md.proximity_mode == 'OBJ2VERTDIST':
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(md, "obj2vert_verts")
|
||||||
|
row.prop(md, "obj2vert_edges")
|
||||||
|
row.prop(md, "obj2vert_faces")
|
||||||
|
|
||||||
|
# Common mask options…
|
||||||
|
layout.separator()
|
||||||
|
self.weight_vg_mask(layout, ob, md)
|
||||||
|
|
||||||
if __name__ == "__main__": # only for live edit.
|
if __name__ == "__main__": # only for live edit.
|
||||||
bpy.utils.register_module(__name__)
|
bpy.utils.register_module(__name__)
|
||||||
|
@ -4154,6 +4154,13 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
|
|||||||
if(tmd->curfalloff)
|
if(tmd->curfalloff)
|
||||||
direct_link_curvemapping(fd, tmd->curfalloff);
|
direct_link_curvemapping(fd, tmd->curfalloff);
|
||||||
}
|
}
|
||||||
|
else if (md->type==eModifierType_WeightVGEdit) {
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
|
||||||
|
wmd->cmap_curve = newdataadr(fd, wmd->cmap_curve);
|
||||||
|
if(wmd->cmap_curve)
|
||||||
|
direct_link_curvemapping(fd, wmd->cmap_curve);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11707,7 +11714,22 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
/* put compatibility code here until next subversion bump */
|
/* put compatibility code here until next subversion bump */
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Object *ob;
|
||||||
|
ModifierData *md;
|
||||||
|
|
||||||
|
/* WeightVGEdit modifier: CurveMapping pointer… */
|
||||||
|
for(ob = main->object.first; ob; ob = ob->id.next) {
|
||||||
|
for(md = ob->modifiers.first; md; md = md->next) {
|
||||||
|
if(md->type == eModifierType_WeightVGEdit) {
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
if (wmd->cmap_curve == NULL) {
|
||||||
|
wmd->cmap_curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||||
|
curvemapping_initialize(wmd->cmap_curve);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||||
|
@ -1294,6 +1294,12 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
|
|||||||
write_curvemapping(wd, tmd->curfalloff);
|
write_curvemapping(wd, tmd->curfalloff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (md->type==eModifierType_WeightVGEdit) {
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
|
||||||
|
if (wmd->cmap_curve)
|
||||||
|
write_curvemapping(wd, wmd->cmap_curve);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -589,8 +589,9 @@ DEF_ICON(MOD_MULTIRES)
|
|||||||
DEF_ICON(MOD_SMOKE)
|
DEF_ICON(MOD_SMOKE)
|
||||||
DEF_ICON(MOD_SOLIDIFY)
|
DEF_ICON(MOD_SOLIDIFY)
|
||||||
DEF_ICON(MOD_SCREW)
|
DEF_ICON(MOD_SCREW)
|
||||||
|
DEF_ICON(MOD_WEIGHTVG)
|
||||||
#ifndef DEF_ICON_BLANK_SKIP
|
#ifndef DEF_ICON_BLANK_SKIP
|
||||||
DEF_ICON(BLANK160)
|
/* DEF_ICON(BLANK160)*/
|
||||||
DEF_ICON(BLANK161)
|
DEF_ICON(BLANK161)
|
||||||
DEF_ICON(BLANK162)
|
DEF_ICON(BLANK162)
|
||||||
DEF_ICON(BLANK163)
|
DEF_ICON(BLANK163)
|
||||||
|
@ -4424,6 +4424,10 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
|
|||||||
UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break;
|
UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break;
|
||||||
case eModifierType_Screw:
|
case eModifierType_Screw:
|
||||||
UI_icon_draw(x, y, ICON_MOD_SCREW); break;
|
UI_icon_draw(x, y, ICON_MOD_SCREW); break;
|
||||||
|
case eModifierType_WeightVGEdit:
|
||||||
|
case eModifierType_WeightVGMix:
|
||||||
|
case eModifierType_WeightVGProximity:
|
||||||
|
UI_icon_draw(x, y, ICON_MOD_WEIGHTVG); break;
|
||||||
default:
|
default:
|
||||||
UI_icon_draw(x, y, ICON_DOT); break;
|
UI_icon_draw(x, y, ICON_DOT); break;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,9 @@ typedef enum ModifierType {
|
|||||||
eModifierType_Solidify,
|
eModifierType_Solidify,
|
||||||
eModifierType_Screw,
|
eModifierType_Screw,
|
||||||
eModifierType_Warp,
|
eModifierType_Warp,
|
||||||
|
eModifierType_WeightVGEdit,
|
||||||
|
eModifierType_WeightVGMix,
|
||||||
|
eModifierType_WeightVGProximity,
|
||||||
NUM_MODIFIER_TYPES
|
NUM_MODIFIER_TYPES
|
||||||
} ModifierType;
|
} ModifierType;
|
||||||
|
|
||||||
@ -674,7 +677,6 @@ typedef struct ShrinkwrapModifierData {
|
|||||||
#define MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS (1<<2)
|
#define MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS (1<<2)
|
||||||
#define MOD_SHRINKWRAP_PROJECT_OVER_NORMAL 0 /* projection over normal is used if no axis is selected */
|
#define MOD_SHRINKWRAP_PROJECT_OVER_NORMAL 0 /* projection over normal is used if no axis is selected */
|
||||||
|
|
||||||
|
|
||||||
typedef struct SimpleDeformModifierData {
|
typedef struct SimpleDeformModifierData {
|
||||||
ModifierData modifier;
|
ModifierData modifier;
|
||||||
|
|
||||||
@ -784,4 +786,167 @@ typedef enum {
|
|||||||
/* PROP_RANDOM not used */
|
/* PROP_RANDOM not used */
|
||||||
} WarpModifierFalloff;
|
} WarpModifierFalloff;
|
||||||
|
|
||||||
|
typedef struct WeightVGEditModifierData {
|
||||||
|
ModifierData modifier;
|
||||||
|
|
||||||
|
/* XXX Note: I tried to keep everything logically ordered – provided the
|
||||||
|
* alignment constraints…
|
||||||
|
*/
|
||||||
|
|
||||||
|
char defgrp_name[32]; /* Name of vertex group to edit. */
|
||||||
|
|
||||||
|
/* Flags (MOD_WVG_EDIT_MAP, MOD_WVG_EDIT_CMAP, MOD_WVG_EDIT_REVERSE_WEIGHTS,
|
||||||
|
* MOD_WVG_EDIT_ADD2VG, MOD_WVG_EDIT_REMFVG, MOD_WVG_EDIT_CLAMP).
|
||||||
|
*/
|
||||||
|
int edit_flags;
|
||||||
|
float default_weight; /* Weight for vertices not in vgroup. */
|
||||||
|
|
||||||
|
/* Mapping stuff. */
|
||||||
|
float map_org_min, map_org_max;
|
||||||
|
float map_new_min, map_new_max;
|
||||||
|
struct CurveMapping *cmap_curve; /* The custom mapping curve! */
|
||||||
|
|
||||||
|
/* The add/remove vertices weight thresholds. */
|
||||||
|
float add_threshold, rem_threshold;
|
||||||
|
|
||||||
|
/* Clamping options. */
|
||||||
|
float clamp_min_weight, clamp_max_weight;
|
||||||
|
|
||||||
|
/* Masking options. */
|
||||||
|
float mask_constant; /* The global “influence”, if no vgroup nor tex is used as mask. */
|
||||||
|
/* Name of mask vertex group from which to get weight factors. */
|
||||||
|
char mask_defgrp_name[32];
|
||||||
|
|
||||||
|
/* Texture masking. */
|
||||||
|
int mask_tex_use_channel; /* Which channel to use as weightf. */
|
||||||
|
struct Tex *mask_texture; /* The texture. */
|
||||||
|
struct Object *mask_tex_map_obj; /* Name of the map object. */
|
||||||
|
/* How to map the texture (using MOD_DISP_MAP_xxx constants). */
|
||||||
|
int mask_tex_mapping;
|
||||||
|
char mask_tex_uvlayer_name[32]; /* Name of the UV layer. */
|
||||||
|
|
||||||
|
/* Padding… */
|
||||||
|
int pad_i1;
|
||||||
|
} WeightVGEditModifierData;
|
||||||
|
|
||||||
|
/* WeightVGEdit flags. */
|
||||||
|
/* Use parametric mapping. */
|
||||||
|
#define MOD_WVG_EDIT_MAP (1 << 0)
|
||||||
|
/* Use curve mapping. */
|
||||||
|
#define MOD_WVG_EDIT_CMAP (1 << 1)
|
||||||
|
/* Reverse weights (in the [0.0, 1.0] standard range). */
|
||||||
|
#define MOD_WVG_EDIT_REVERSE_WEIGHTS (1 << 2)
|
||||||
|
/* Add vertices with higher weight than threshold to vgroup. */
|
||||||
|
#define MOD_WVG_EDIT_ADD2VG (1 << 3)
|
||||||
|
/* Remove vertices with lower weight than threshold from vgroup. */
|
||||||
|
#define MOD_WVG_EDIT_REMFVG (1 << 4)
|
||||||
|
/* Clamp weights. */
|
||||||
|
#define MOD_WVG_EDIT_CLAMP (1 << 5)
|
||||||
|
|
||||||
|
typedef struct WeightVGMixModifierData {
|
||||||
|
ModifierData modifier;
|
||||||
|
|
||||||
|
/* XXX Note: I tried to keep everything logically ordered – provided the
|
||||||
|
* alignment constraints…
|
||||||
|
*/
|
||||||
|
|
||||||
|
char defgrp_name[32]; /* Name of vertex group to modify/weight. */
|
||||||
|
char defgrp_name2[32]; /* Name of other vertex group to mix in. */
|
||||||
|
float default_weight; /* Default weight value for first vgroup. */
|
||||||
|
float default_weight2; /* Default weight value to mix in. */
|
||||||
|
char mix_mode; /* How second vgroup’s weights affect first ones */
|
||||||
|
char mix_set; /* What vertices to affect. */
|
||||||
|
|
||||||
|
char pad_c1, pad_c2;
|
||||||
|
int pad_i1;
|
||||||
|
|
||||||
|
/* Masking options. */
|
||||||
|
float mask_constant; /* The global “influence”, if no vgroup nor tex is used as mask. */
|
||||||
|
/* Name of mask vertex group from which to get weight factors. */
|
||||||
|
char mask_defgrp_name[32];
|
||||||
|
|
||||||
|
/* Texture masking. */
|
||||||
|
int mask_tex_use_channel; /* Which channel to use as weightf. */
|
||||||
|
struct Tex *mask_texture; /* The texture. */
|
||||||
|
struct Object *mask_tex_map_obj; /* Name of the map object. */
|
||||||
|
int mask_tex_mapping; /* How to map the texture! */
|
||||||
|
char mask_tex_uvlayer_name[32]; /* Name of the UV layer. */
|
||||||
|
|
||||||
|
/* Padding… */
|
||||||
|
int pad_i2;
|
||||||
|
} WeightVGMixModifierData;
|
||||||
|
|
||||||
|
/* How second vgroup’s weights affect first ones. */
|
||||||
|
#define MOD_WVG_MIX_SET 1 /* Second weights replace weights. */
|
||||||
|
#define MOD_WVG_MIX_ADD 2 /* Second weights are added to weights. */
|
||||||
|
#define MOD_WVG_MIX_SUB 3 /* Second weights are subtracted from weights. */
|
||||||
|
#define MOD_WVG_MIX_MUL 4 /* Second weights are multiplied with weights. */
|
||||||
|
#define MOD_WVG_MIX_DIV 5 /* Second weights divide weights. */
|
||||||
|
#define MOD_WVG_MIX_DIF 6 /* Difference between second weights and weights. */
|
||||||
|
#define MOD_WVG_MIX_AVG 7 /* Average of both weights. */
|
||||||
|
|
||||||
|
/* What vertices to affect. */
|
||||||
|
#define MOD_WVG_SET_ALL 1 /* Affect all vertices. */
|
||||||
|
#define MOD_WVG_SET_ORG 2 /* Affect only vertices in first vgroup. */
|
||||||
|
#define MOD_WVG_SET_NEW 3 /* Affect only vertices in second vgroup. */
|
||||||
|
#define MOD_WVG_SET_UNION 4 /* Affect only vertices in one vgroup or the other. */
|
||||||
|
#define MOD_WVG_SET_INTER 5 /* Affect only vertices in both vgroups. */
|
||||||
|
|
||||||
|
typedef struct WeightVGProximityModifierData {
|
||||||
|
ModifierData modifier;
|
||||||
|
|
||||||
|
/* XXX Note: I tried to keep everything logically ordered – provided the
|
||||||
|
* alignment constraints…
|
||||||
|
*/
|
||||||
|
|
||||||
|
char defgrp_name[32]; /* Name of vertex group to modify/weight. */
|
||||||
|
|
||||||
|
/* Proximity modes. */
|
||||||
|
int proximity_mode;
|
||||||
|
int proximity_flags;
|
||||||
|
|
||||||
|
/* Target object from which to calculate vertices’ distances. */
|
||||||
|
struct Object *proximity_ob_target;
|
||||||
|
|
||||||
|
/* Masking options. */
|
||||||
|
float mask_constant; /* The global “influence”, if no vgroup nor tex is used as mask. */
|
||||||
|
/* Name of mask vertex group from which to get weight factors. */
|
||||||
|
char mask_defgrp_name[32];
|
||||||
|
|
||||||
|
/* Texture masking. */
|
||||||
|
int mask_tex_use_channel; /* Which channel to use as weightf. */
|
||||||
|
struct Tex *mask_texture; /* The texture. */
|
||||||
|
struct Object *mask_tex_map_obj; /* Name of the map object. */
|
||||||
|
int mask_tex_mapping; /* How to map the texture! */
|
||||||
|
char mask_tex_uvlayer_name[32]; /* Name of the UV layer. */
|
||||||
|
|
||||||
|
/* Padding… */
|
||||||
|
int pad_i2;
|
||||||
|
} WeightVGProximityModifierData;
|
||||||
|
|
||||||
|
/* Modes of proximity weighting. */
|
||||||
|
/* Dist from target object to affected object. */
|
||||||
|
#define MOD_WVG_PROXIMITY_OBJ2OBJDIST 1
|
||||||
|
/* Dist from target object to vertex. */
|
||||||
|
#define MOD_WVG_PROXIMITY_OBJ2VERTDIST 2
|
||||||
|
|
||||||
|
/* Flags options for proximity weighting. */
|
||||||
|
/* Use nearest vertices of target obj, in OVJ2VERTDIST mode. */
|
||||||
|
#define MOD_WVG_PROXIMITY_O2VD_VERTS (1 << 0)
|
||||||
|
/* Use nearest edges of target obj, in OVJ2VERTDIST mode. */
|
||||||
|
#define MOD_WVG_PROXIMITY_O2VD_EDGES (1 << 1)
|
||||||
|
/* Use nearest faces of target obj, in OVJ2VERTDIST mode. */
|
||||||
|
#define MOD_WVG_PROXIMITY_O2VD_FACES (1 << 2)
|
||||||
|
|
||||||
|
/* Defines common to all WeightVG modifiers. */
|
||||||
|
/* Tex channel to be used as mask. */
|
||||||
|
#define MOD_WVG_MASK_TEX_USE_INT 1
|
||||||
|
#define MOD_WVG_MASK_TEX_USE_RED 2
|
||||||
|
#define MOD_WVG_MASK_TEX_USE_GREEN 3
|
||||||
|
#define MOD_WVG_MASK_TEX_USE_BLUE 4
|
||||||
|
#define MOD_WVG_MASK_TEX_USE_HUE 5
|
||||||
|
#define MOD_WVG_MASK_TEX_USE_SAT 6
|
||||||
|
#define MOD_WVG_MASK_TEX_USE_VAL 7
|
||||||
|
#define MOD_WVG_MASK_TEX_USE_ALPHA 8
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -562,6 +562,9 @@ extern StructRNA RNA_VoxelData;
|
|||||||
extern StructRNA RNA_VoxelDataTexture;
|
extern StructRNA RNA_VoxelDataTexture;
|
||||||
extern StructRNA RNA_WarpModifier;
|
extern StructRNA RNA_WarpModifier;
|
||||||
extern StructRNA RNA_WaveModifier;
|
extern StructRNA RNA_WaveModifier;
|
||||||
|
extern StructRNA RNA_WeightVGEditModifier;
|
||||||
|
extern StructRNA RNA_WeightVGMixModifier;
|
||||||
|
extern StructRNA RNA_WeightVGProximityModifier;
|
||||||
extern StructRNA RNA_Window;
|
extern StructRNA RNA_Window;
|
||||||
extern StructRNA RNA_WindowManager;
|
extern StructRNA RNA_WindowManager;
|
||||||
extern StructRNA RNA_WipeSequence;
|
extern StructRNA RNA_WipeSequence;
|
||||||
|
@ -68,6 +68,9 @@ EnumPropertyItem modifier_type_items[] ={
|
|||||||
{eModifierType_Solidify, "SOLIDIFY", ICON_MOD_SOLIDIFY, "Solidify", ""},
|
{eModifierType_Solidify, "SOLIDIFY", ICON_MOD_SOLIDIFY, "Solidify", ""},
|
||||||
{eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""},
|
{eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""},
|
||||||
{eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
|
{eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
|
||||||
|
{eModifierType_WeightVGEdit, "WEIGHT_VGEDIT", ICON_MOD_WEIGHTVG, "Edit Vertex Group Weights", ""},
|
||||||
|
{eModifierType_WeightVGMix, "WEIGHT_VGMIX", ICON_MOD_WEIGHTVG, "Mix Two Vertex Groups", ""},
|
||||||
|
{eModifierType_WeightVGProximity, "WEIGHT_VGPROXIMITY", ICON_MOD_WEIGHTVG, "Weight Vertex Group - Poximity", ""},
|
||||||
{0, "", 0, "Deform", ""},
|
{0, "", 0, "Deform", ""},
|
||||||
{eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""},
|
{eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""},
|
||||||
{eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""},
|
{eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""},
|
||||||
@ -183,6 +186,12 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr)
|
|||||||
return &RNA_ScrewModifier;
|
return &RNA_ScrewModifier;
|
||||||
case eModifierType_Warp:
|
case eModifierType_Warp:
|
||||||
return &RNA_WarpModifier;
|
return &RNA_WarpModifier;
|
||||||
|
case eModifierType_WeightVGEdit:
|
||||||
|
return &RNA_WeightVGEditModifier;
|
||||||
|
case eModifierType_WeightVGMix:
|
||||||
|
return &RNA_WeightVGMixModifier;
|
||||||
|
case eModifierType_WeightVGProximity:
|
||||||
|
return &RNA_WeightVGProximityModifier;
|
||||||
default:
|
default:
|
||||||
return &RNA_Modifier;
|
return &RNA_Modifier;
|
||||||
}
|
}
|
||||||
@ -375,6 +384,46 @@ static void rna_SolidifyModifier_vgroup_set(PointerRNA *ptr, const char *value)
|
|||||||
rna_object_vgroup_name_set(ptr, value, smd->defgrp_name, sizeof(smd->defgrp_name));
|
rna_object_vgroup_name_set(ptr, value, smd->defgrp_name, sizeof(smd->defgrp_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_WeightVGModifier_vgroup_set(PointerRNA *ptr, const char *value)
|
||||||
|
{
|
||||||
|
ModifierData *md = (ModifierData*)ptr->data;
|
||||||
|
if (md->type == eModifierType_WeightVGEdit) {
|
||||||
|
WeightVGEditModifierData *wmd= (WeightVGEditModifierData*)md;
|
||||||
|
rna_object_vgroup_name_set(ptr, value, wmd->defgrp_name, sizeof(wmd->defgrp_name));
|
||||||
|
}
|
||||||
|
else if (md->type == eModifierType_WeightVGMix) {
|
||||||
|
WeightVGMixModifierData *wmd= (WeightVGMixModifierData*)md;
|
||||||
|
rna_object_vgroup_name_set(ptr, value, wmd->defgrp_name, sizeof(wmd->defgrp_name));
|
||||||
|
}
|
||||||
|
else if (md->type == eModifierType_WeightVGProximity) {
|
||||||
|
WeightVGProximityModifierData *wmd= (WeightVGProximityModifierData*)md;
|
||||||
|
rna_object_vgroup_name_set(ptr, value, wmd->defgrp_name, sizeof(wmd->defgrp_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rna_WeightVGModifier_mask_vgroup_set(PointerRNA *ptr, const char *value)
|
||||||
|
{
|
||||||
|
ModifierData *md = (ModifierData*)ptr->data;
|
||||||
|
if (md->type == eModifierType_WeightVGEdit) {
|
||||||
|
WeightVGEditModifierData *wmd= (WeightVGEditModifierData*)md;
|
||||||
|
rna_object_vgroup_name_set(ptr, value, wmd->mask_defgrp_name, sizeof(wmd->mask_defgrp_name));
|
||||||
|
}
|
||||||
|
else if (md->type == eModifierType_WeightVGMix) {
|
||||||
|
WeightVGMixModifierData *wmd= (WeightVGMixModifierData*)md;
|
||||||
|
rna_object_vgroup_name_set(ptr, value, wmd->mask_defgrp_name, sizeof(wmd->mask_defgrp_name));
|
||||||
|
}
|
||||||
|
else if (md->type == eModifierType_WeightVGProximity) {
|
||||||
|
WeightVGProximityModifierData *wmd= (WeightVGProximityModifierData*)md;
|
||||||
|
rna_object_vgroup_name_set(ptr, value, wmd->mask_defgrp_name, sizeof(wmd->mask_defgrp_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rna_WeightVGMixModifier_vgroup2_set(PointerRNA *ptr, const char *value)
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd= (WeightVGMixModifierData*)ptr->data;
|
||||||
|
rna_object_vgroup_name_set(ptr, value, wmd->defgrp_name2, sizeof(wmd->defgrp_name2));
|
||||||
|
}
|
||||||
|
|
||||||
static void rna_MappingInfo_uvlayer_set(PointerRNA *ptr, const char *value)
|
static void rna_MappingInfo_uvlayer_set(PointerRNA *ptr, const char *value)
|
||||||
{
|
{
|
||||||
MappingInfoModifierData *mmd= (MappingInfoModifierData *)ptr->data;
|
MappingInfoModifierData *mmd= (MappingInfoModifierData *)ptr->data;
|
||||||
@ -399,6 +448,23 @@ static void rna_WaveModifier_uvlayer_set(PointerRNA *ptr, const char *value)
|
|||||||
rna_object_uvlayer_name_set(ptr, value, wmd->uvlayer_name, sizeof(wmd->uvlayer_name));
|
rna_object_uvlayer_name_set(ptr, value, wmd->uvlayer_name, sizeof(wmd->uvlayer_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_WeightVGModifier_mask_uvlayer_set(PointerRNA *ptr, const char *value)
|
||||||
|
{
|
||||||
|
ModifierData *md = (ModifierData*)ptr->data;
|
||||||
|
if (md->type == eModifierType_WeightVGEdit) {
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*)md;
|
||||||
|
rna_object_uvlayer_name_set(ptr, value, wmd->mask_tex_uvlayer_name, sizeof(wmd->mask_tex_uvlayer_name));
|
||||||
|
}
|
||||||
|
else if (md->type == eModifierType_WeightVGMix) {
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*)md;
|
||||||
|
rna_object_uvlayer_name_set(ptr, value, wmd->mask_tex_uvlayer_name, sizeof(wmd->mask_tex_uvlayer_name));
|
||||||
|
}
|
||||||
|
else if (md->type == eModifierType_WeightVGProximity) {
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*)md;
|
||||||
|
rna_object_uvlayer_name_set(ptr, value, wmd->mask_tex_uvlayer_name, sizeof(wmd->mask_tex_uvlayer_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void rna_MultiresModifier_level_range(PointerRNA *ptr, int *min, int *max)
|
static void rna_MultiresModifier_level_range(PointerRNA *ptr, int *min, int *max)
|
||||||
{
|
{
|
||||||
MultiresModifierData *mmd = (MultiresModifierData*)ptr->data;
|
MultiresModifierData *mmd = (MultiresModifierData*)ptr->data;
|
||||||
@ -2407,6 +2473,314 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
|
|||||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");*/
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_def_modifier_weightvg_mask(BlenderRNA *brna, StructRNA *srna)
|
||||||
|
{
|
||||||
|
static EnumPropertyItem weightvg_mask_tex_map_items[] = {
|
||||||
|
{MOD_DISP_MAP_LOCAL, "LOCAL", 0, "Local", ""},
|
||||||
|
{MOD_DISP_MAP_GLOBAL, "GLOBAL", 0, "Global", ""},
|
||||||
|
{MOD_DISP_MAP_OBJECT, "OBJECT", 0, "Object", ""},
|
||||||
|
{MOD_DISP_MAP_UV, "UV", 0, "UV", ""},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
|
static EnumPropertyItem weightvg_mask_tex_used_items[] = {
|
||||||
|
{MOD_WVG_MASK_TEX_USE_INT, "INT", 0, "Intensity", ""},
|
||||||
|
{MOD_WVG_MASK_TEX_USE_RED, "RED", 0, "Red", ""},
|
||||||
|
{MOD_WVG_MASK_TEX_USE_GREEN, "GREEN", 0, "Green", ""},
|
||||||
|
{MOD_WVG_MASK_TEX_USE_BLUE, "BLUE", 0, "Blue", ""},
|
||||||
|
{MOD_WVG_MASK_TEX_USE_HUE, "HUE", 0, "Hue", ""},
|
||||||
|
{MOD_WVG_MASK_TEX_USE_SAT, "SAT", 0, "Saturation", ""},
|
||||||
|
{MOD_WVG_MASK_TEX_USE_VAL, "VAL", 0, "Value", ""},
|
||||||
|
{MOD_WVG_MASK_TEX_USE_ALPHA, "ALPHA", 0, "Alpha", ""},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mask_constant", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Influence", "Global influence of current modifications on vgroup.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mask_vertex_group", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "mask_defgrp_name");
|
||||||
|
RNA_def_property_ui_text(prop, "Mask VGroup", "Masking vertex group name.");
|
||||||
|
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightVGModifier_mask_vgroup_set");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mask_texture", PROP_POINTER, PROP_NONE);
|
||||||
|
RNA_def_property_ui_text(prop, "Masking Tex", "Masking texture.");
|
||||||
|
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mask_tex_use_channel", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, weightvg_mask_tex_used_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Use Channel", "Which texture channel to use for masking.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mask_tex_mapping", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, weightvg_mask_tex_map_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Texture Coordinates", "Which texture coordinates "
|
||||||
|
"to use for mapping.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mask_tex_uv_layer", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "mask_tex_uvlayer_name");
|
||||||
|
RNA_def_property_ui_text(prop, "UV Layer", "UV layer name");
|
||||||
|
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightVGModifier_mask_uvlayer_set");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mask_tex_map_obj", PROP_POINTER, PROP_NONE);
|
||||||
|
RNA_def_property_ui_text(prop, "Texture Coordinate Object", "Which object to take texture "
|
||||||
|
"coordinates from.");
|
||||||
|
RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
|
||||||
|
{
|
||||||
|
StructRNA *srna;
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
srna= RNA_def_struct(brna, "WeightVGEditModifier", "Modifier");
|
||||||
|
RNA_def_struct_ui_text(srna, "Edit Vertex Group Weights Modifier",
|
||||||
|
"Edit the weights of vertices in a group.");
|
||||||
|
RNA_def_struct_sdna(srna, "WeightVGEditModifierData");
|
||||||
|
RNA_def_struct_ui_icon(srna, ICON_MOD_WEIGHTVG);
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
|
||||||
|
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name.");
|
||||||
|
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightVGModifier_vgroup_set");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "flag_map", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_MAP);
|
||||||
|
RNA_def_property_ui_text(prop, "Map", "Map vertex group weights.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "flag_curve_map", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_CMAP);
|
||||||
|
RNA_def_property_ui_text(prop, "Curve Map", "Map vertex group weights with a curve.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "flag_reverse", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_REVERSE_WEIGHTS);
|
||||||
|
RNA_def_property_ui_text(prop, "Reverse", "Reverse vertex group weights.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "flag_add2vg", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_ADD2VG);
|
||||||
|
RNA_def_property_ui_text(prop, "Add to VG", "Add vertices with weight over threshold "
|
||||||
|
"to vgroup.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "flag_remfvg", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_REMFVG);
|
||||||
|
RNA_def_property_ui_text(prop, "Rem from VG", "Remove vertices with weight below threshold "
|
||||||
|
"from vgroup.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "flag_clamp", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_CLAMP);
|
||||||
|
RNA_def_property_ui_text(prop, "Clamp", "Clamp vertex group weights.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "default_weight", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Default Weight", "Default weight a vertex will have if "
|
||||||
|
"it is not in the vgroup.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "map_input_low", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_float_sdna(prop, NULL, "map_org_min");
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Input Low Weight", "Low input mapping value.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "map_input_high", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_float_sdna(prop, NULL, "map_org_max");
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Input High Weight", "High input mapping value.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "map_output_low", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_float_sdna(prop, NULL, "map_new_min");
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Output Low Weight", "Low output mapping value.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "map_output_high", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_float_sdna(prop, NULL, "map_new_max");
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Output High Weight", "High output mapping value.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "cmap_curve", PROP_POINTER, PROP_NONE);
|
||||||
|
RNA_def_property_pointer_sdna(prop, NULL, "cmap_curve");
|
||||||
|
RNA_def_property_ui_text(prop, "Mapping Curve", "Custom mapping curve.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "add_threshold", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Add Threshold", "Lower bound for a vertex’s weight "
|
||||||
|
"to be added to the vgroup.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "rem_threshold", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Rem Threshold", "Upper bound for a vertex’s weight "
|
||||||
|
"to be removed from the vgroup.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "clamp_min_weight", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Min Weight", "Lowest weight a vertex can get.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "clamp_max_weight", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Max Weight", "Highest weight a vertex can get.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
/* Common masking properties. */
|
||||||
|
rna_def_modifier_weightvg_mask(brna, srna);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
|
||||||
|
{
|
||||||
|
static EnumPropertyItem weightvg_mix_modes_items[] = {
|
||||||
|
{MOD_WVG_MIX_SET, "SET", 0, "Replace weights", ""},
|
||||||
|
{MOD_WVG_MIX_ADD, "ADD", 0, "Add to weights", ""},
|
||||||
|
{MOD_WVG_MIX_SUB, "SUB", 0, "Subtract from weights", ""},
|
||||||
|
{MOD_WVG_MIX_MUL, "MUL", 0, "Multiply weights", ""},
|
||||||
|
{MOD_WVG_MIX_DIV, "DIV", 0, "Divide weights", ""},
|
||||||
|
{MOD_WVG_MIX_DIF, "DIF", 0, "Difference", ""},
|
||||||
|
{MOD_WVG_MIX_AVG, "AVG", 0, "Average", ""},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
|
static EnumPropertyItem weightvg_mix_set_items[] = {
|
||||||
|
{MOD_WVG_SET_ALL, "ALL", 0, "All vertices", ""},
|
||||||
|
{MOD_WVG_SET_ORG, "ORG", 0, "Vertices from vgroup 1", ""},
|
||||||
|
{MOD_WVG_SET_NEW, "NEW", 0, "Vertices from vgroup 2", ""},
|
||||||
|
{MOD_WVG_SET_UNION, "UNION", 0, "Vertices from one group", ""},
|
||||||
|
{MOD_WVG_SET_INTER, "INTER", 0, "Vertices from both groups", ""},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
|
StructRNA *srna;
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
srna= RNA_def_struct(brna, "WeightVGMixModifier", "Modifier");
|
||||||
|
RNA_def_struct_ui_text(srna, "Weight Vertex Group Modifier",
|
||||||
|
"Mix the weights of two vertex groups.");
|
||||||
|
RNA_def_struct_sdna(srna, "WeightVGMixModifierData");
|
||||||
|
RNA_def_struct_ui_icon(srna, ICON_MOD_WEIGHTVG);
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
|
||||||
|
RNA_def_property_ui_text(prop, "Vertex Group", "First vertex group name.");
|
||||||
|
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightVGModifier_vgroup_set");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "vertex_group2", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "defgrp_name2");
|
||||||
|
RNA_def_property_ui_text(prop, "Vertex Group 2", "Second vertex group name.");
|
||||||
|
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightVGMixModifier_vgroup2_set");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "default_weight", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Default Weight", "Default weight a vertex will have if "
|
||||||
|
"it is not in the first vgroup.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "default_weight2", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100000.0, 100000.0, 10, 0);
|
||||||
|
RNA_def_property_ui_text(prop, "Default Weight 2", "Default weight a vertex will have if "
|
||||||
|
"it is not in the second vgroup.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, weightvg_mix_modes_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Mix Mode", "How weights from vgroup 2 affect weights "
|
||||||
|
"of vgroup 1.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "mix_set", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, weightvg_mix_set_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Vertex Set", "Which vertices should be affected.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
/* Common masking properties. */
|
||||||
|
rna_def_modifier_weightvg_mask(brna, srna);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
|
||||||
|
{
|
||||||
|
static EnumPropertyItem weightvg_proximity_modes_items[] = {
|
||||||
|
{MOD_WVG_PROXIMITY_OBJ2OBJDIST, "OBJ2OBJDIST", 0, "O2O Distance", ""},
|
||||||
|
{MOD_WVG_PROXIMITY_OBJ2VERTDIST, "OBJ2VERTDIST", 0, "O2V Distance", ""},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
|
StructRNA *srna;
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
srna= RNA_def_struct(brna, "WeightVGProximityModifier", "Modifier");
|
||||||
|
RNA_def_struct_ui_text(srna, "Weight Vertex Group - Proximity Modifier",
|
||||||
|
"Set the weights of vertices in a group from a target object’s "
|
||||||
|
"distance.");
|
||||||
|
RNA_def_struct_sdna(srna, "WeightVGProximityModifierData");
|
||||||
|
RNA_def_struct_ui_icon(srna, ICON_MOD_WEIGHTVG);
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
|
||||||
|
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name.");
|
||||||
|
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightVGModifier_vgroup_set");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "proximity_mode", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, weightvg_proximity_modes_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Proximity Mode", "Which distances to target object to use.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "obj2vert_verts", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_O2VD_VERTS);
|
||||||
|
RNA_def_property_ui_text(prop, "Use Target Vertices",
|
||||||
|
"Use shortest distance to target object’s vertices as weight.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "obj2vert_edges", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_O2VD_EDGES);
|
||||||
|
RNA_def_property_ui_text(prop, "Use Target Edges",
|
||||||
|
"Use shortest distance to target object’s edges as weight.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "obj2vert_faces", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_O2VD_FACES);
|
||||||
|
RNA_def_property_ui_text(prop, "Use Target Faces",
|
||||||
|
"Use shortest distance to target object’s faces as weight.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "ob_target", PROP_POINTER, PROP_NONE);
|
||||||
|
RNA_def_property_pointer_sdna(prop, NULL, "proximity_ob_target");
|
||||||
|
RNA_def_property_ui_text(prop, "Target Object", "Object to calculate vertices’ distances from.");
|
||||||
|
RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
|
||||||
|
|
||||||
|
/* Common masking properties. */
|
||||||
|
rna_def_modifier_weightvg_mask(brna, srna);
|
||||||
|
}
|
||||||
|
|
||||||
void RNA_def_modifier(BlenderRNA *brna)
|
void RNA_def_modifier(BlenderRNA *brna)
|
||||||
{
|
{
|
||||||
StructRNA *srna;
|
StructRNA *srna;
|
||||||
@ -2504,6 +2878,9 @@ void RNA_def_modifier(BlenderRNA *brna)
|
|||||||
rna_def_modifier_smoke(brna);
|
rna_def_modifier_smoke(brna);
|
||||||
rna_def_modifier_solidify(brna);
|
rna_def_modifier_solidify(brna);
|
||||||
rna_def_modifier_screw(brna);
|
rna_def_modifier_screw(brna);
|
||||||
|
rna_def_modifier_weightvgedit(brna);
|
||||||
|
rna_def_modifier_weightvgmix(brna);
|
||||||
|
rna_def_modifier_weightvgproximity(brna);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -80,11 +80,16 @@ set(SRC
|
|||||||
intern/MOD_uvproject.c
|
intern/MOD_uvproject.c
|
||||||
intern/MOD_warp.c
|
intern/MOD_warp.c
|
||||||
intern/MOD_wave.c
|
intern/MOD_wave.c
|
||||||
|
intern/MOD_weightvg_util.c
|
||||||
|
intern/MOD_weightvgedit.c
|
||||||
|
intern/MOD_weightvgmix.c
|
||||||
|
intern/MOD_weightvgproximity.c
|
||||||
|
|
||||||
MOD_modifiertypes.h
|
MOD_modifiertypes.h
|
||||||
intern/MOD_boolean_util.h
|
intern/MOD_boolean_util.h
|
||||||
intern/MOD_fluidsim_util.h
|
intern/MOD_fluidsim_util.h
|
||||||
intern/MOD_util.h
|
intern/MOD_util.h
|
||||||
|
intern/MOD_weightvg_util.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WITH_MOD_BOOLEAN)
|
if(WITH_MOD_BOOLEAN)
|
||||||
|
@ -72,6 +72,9 @@ extern ModifierTypeInfo modifierType_ShapeKey;
|
|||||||
extern ModifierTypeInfo modifierType_Solidify;
|
extern ModifierTypeInfo modifierType_Solidify;
|
||||||
extern ModifierTypeInfo modifierType_Screw;
|
extern ModifierTypeInfo modifierType_Screw;
|
||||||
extern ModifierTypeInfo modifierType_Warp;
|
extern ModifierTypeInfo modifierType_Warp;
|
||||||
|
extern ModifierTypeInfo modifierType_WeightVGEdit;
|
||||||
|
extern ModifierTypeInfo modifierType_WeightVGMix;
|
||||||
|
extern ModifierTypeInfo modifierType_WeightVGProximity;
|
||||||
|
|
||||||
/* MOD_util.c */
|
/* MOD_util.c */
|
||||||
void modifier_type_init(ModifierTypeInfo *types[]);
|
void modifier_type_init(ModifierTypeInfo *types[]);
|
||||||
|
@ -295,5 +295,8 @@ void modifier_type_init(ModifierTypeInfo *types[])
|
|||||||
INIT_TYPE(Solidify);
|
INIT_TYPE(Solidify);
|
||||||
INIT_TYPE(Screw);
|
INIT_TYPE(Screw);
|
||||||
INIT_TYPE(Warp);
|
INIT_TYPE(Warp);
|
||||||
|
INIT_TYPE(WeightVGEdit);
|
||||||
|
INIT_TYPE(WeightVGMix);
|
||||||
|
INIT_TYPE(WeightVGProximity);
|
||||||
#undef INIT_TYPE
|
#undef INIT_TYPE
|
||||||
}
|
}
|
||||||
|
246
source/blender/modifiers/intern/MOD_weightvg_util.c
Normal file
246
source/blender/modifiers/intern/MOD_weightvg_util.c
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2011 by Bastien Montagne.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): None yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX I’d like to make modified weights visible in WeightPaint mode,
|
||||||
|
* but couldn’t figure a way to do this…
|
||||||
|
* Maybe this will need changes in mesh_calc_modifiers (DerivedMesh.c)?
|
||||||
|
* Or the WeightPaint mode code itself?
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BKE_cdderivedmesh.h"
|
||||||
|
#include "BKE_deform.h"
|
||||||
|
#include "BKE_mesh.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_texture.h" /* Texture masking. */
|
||||||
|
|
||||||
|
#include "depsgraph_private.h"
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
#include "MOD_util.h"
|
||||||
|
#include "MOD_weightvg_util.h"
|
||||||
|
#include "RE_shader_ext.h" /* Texture masking. */
|
||||||
|
|
||||||
|
/* Applies new_w weights to org_w ones, using either a texture, vgroup or constant value as factor.
|
||||||
|
* Return values are in org_w.
|
||||||
|
* If indices is not NULL, it must be a table of same length as org_w and new_w, mapping to the real
|
||||||
|
* 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(int num, int *indices, float *org_w, float *new_w, Object *ob,
|
||||||
|
DerivedMesh *dm, float fact, const char *defgrp_name, Tex *texture,
|
||||||
|
int tex_use_channel, int tex_mapping, Object *tex_map_object,
|
||||||
|
const char *tex_uvlayer_name) {
|
||||||
|
int ref_didx;
|
||||||
|
MDeformVert *dvert = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* If influence factor is null, nothing to do! */
|
||||||
|
if (fact == 0.0) return;
|
||||||
|
|
||||||
|
/* If we want to mask vgroup weights from a texture. */
|
||||||
|
if (texture) {
|
||||||
|
/* The texture coordinates. */
|
||||||
|
float (*tex_co)[3];
|
||||||
|
/* See mapping note below… */
|
||||||
|
MappingInfoModifierData t_map;
|
||||||
|
float (*v_co)[3];
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
v_co = MEM_mallocN(sizeof(*v_co) * num, "WeightVG Modifier, TEX mode, v_co");
|
||||||
|
dm->getVertCos(dm, v_co);
|
||||||
|
tex_co = MEM_callocN(sizeof(*tex_co) * num, "WeightVG Modifier, TEX mode, tex_co");
|
||||||
|
get_texture_coords(&t_map, ob, dm, v_co, tex_co, num);
|
||||||
|
MEM_freeN(v_co);
|
||||||
|
|
||||||
|
/* 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 h, s, v; /* For HSV color space. */
|
||||||
|
|
||||||
|
texres.nor = NULL;
|
||||||
|
get_texture_value(texture, tex_co[idx], &texres);
|
||||||
|
/* 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.0 - (texres.tin*fact)));
|
||||||
|
break;
|
||||||
|
case MOD_WVG_MASK_TEX_USE_RED:
|
||||||
|
org_w[i] = (new_w[i] * texres.tr * fact) + (org_w[i] * (1.0 - (texres.tr*fact)));
|
||||||
|
break;
|
||||||
|
case MOD_WVG_MASK_TEX_USE_GREEN:
|
||||||
|
org_w[i] = (new_w[i] * texres.tg * fact) + (org_w[i] * (1.0 - (texres.tg*fact)));
|
||||||
|
break;
|
||||||
|
case MOD_WVG_MASK_TEX_USE_BLUE:
|
||||||
|
org_w[i] = (new_w[i] * texres.tb * fact) + (org_w[i] * (1.0 - (texres.tb*fact)));
|
||||||
|
break;
|
||||||
|
case MOD_WVG_MASK_TEX_USE_HUE:
|
||||||
|
rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v);
|
||||||
|
org_w[i] = (new_w[i] * h * fact) + (org_w[i] * (1.0 - (h*fact)));
|
||||||
|
break;
|
||||||
|
case MOD_WVG_MASK_TEX_USE_SAT:
|
||||||
|
rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v);
|
||||||
|
org_w[i] = (new_w[i] * s * fact) + (org_w[i] * (1.0 - (s*fact)));
|
||||||
|
break;
|
||||||
|
case MOD_WVG_MASK_TEX_USE_VAL:
|
||||||
|
rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v);
|
||||||
|
org_w[i] = (new_w[i] * v * fact) + (org_w[i] * (1.0 - (v*fact)));
|
||||||
|
break;
|
||||||
|
case MOD_WVG_MASK_TEX_USE_ALPHA:
|
||||||
|
org_w[i] = (new_w[i] * texres.ta * fact) + (org_w[i] * (1.0 - (texres.ta*fact)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0 - (texres.tin*fact)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeN(tex_co);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether we want to set vgroup weights from a constant weight factor or a vertex
|
||||||
|
* group.
|
||||||
|
*/
|
||||||
|
/* Get vgroup idx from its name. */
|
||||||
|
ref_didx = defgroup_name_index(ob, defgrp_name);
|
||||||
|
/* Proceed only if vgroup is valid, else use constant factor. */
|
||||||
|
if (ref_didx >= 0) {
|
||||||
|
/* Get actual dverts (ie vertex group data). */
|
||||||
|
dvert = dm->getVertDataArray(dm, 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;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < dvert[idx].totweight; j++) {
|
||||||
|
if(dvert[idx].dw[j].def_nr == ref_didx) {
|
||||||
|
float f = dvert[idx].dw[j].weight * fact;
|
||||||
|
org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0-f));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default "influence" behavior. */
|
||||||
|
/* For each weight (vertex), make the mix between org and new weights. */
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
org_w[i] = (new_w[i] * fact) + (org_w[i] * (1.0-fact));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Applies weights to given vgroup (defgroup), and optionnaly add/remove vertices from the group.
|
||||||
|
* If indices is not NULL, it must be a table of same length as weights, mapping to the real
|
||||||
|
* vertex index (in case the weight table does not cover the whole vertices...).
|
||||||
|
*/
|
||||||
|
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, int num, int *indices,
|
||||||
|
float *weights, int do_add, float add_thresh, int do_rem,
|
||||||
|
float rem_thresh){
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
int j;
|
||||||
|
float w = weights[i];
|
||||||
|
MDeformVert *dv = &dvert[indices ? indices[i] : i];
|
||||||
|
MDeformWeight *newdw;
|
||||||
|
|
||||||
|
/* Let’s first check to see if this vert is already in the weight group – if so
|
||||||
|
* let’s update it, or remove it if needed.
|
||||||
|
*/
|
||||||
|
for (j = 0; j < dv->totweight; j++) {
|
||||||
|
/* If this weight corresponds to the deform group, update the value or,
|
||||||
|
* if lower than rem_threshold, remove the vertex from the vgroup.
|
||||||
|
*/
|
||||||
|
if (dv->dw[j].def_nr == defgrp_idx) {
|
||||||
|
/* Remove the vertex from this vgroup if needed. */
|
||||||
|
if (do_rem && w < rem_thresh) {
|
||||||
|
dv->totweight--;
|
||||||
|
/* If there are still other deform weights attached to this vert then remove
|
||||||
|
* this deform weight, and reshuffle the others.
|
||||||
|
*/
|
||||||
|
if(dv->totweight) {
|
||||||
|
newdw = MEM_mallocN(sizeof(MDeformWeight)*(dv->totweight), "deformWeight");
|
||||||
|
if(dv->dw){
|
||||||
|
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*j);
|
||||||
|
memcpy(newdw+j, dv->dw+j+1, sizeof(MDeformWeight)*(dv->totweight-j));
|
||||||
|
MEM_freeN(dv->dw);
|
||||||
|
}
|
||||||
|
dv->dw = newdw;
|
||||||
|
}
|
||||||
|
/* If there are no other deform weights left then just remove this one. */
|
||||||
|
else {
|
||||||
|
MEM_freeN(dv->dw);
|
||||||
|
dv->dw = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Else, just set the new computed weight. */
|
||||||
|
else
|
||||||
|
dv->dw[j].weight = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the vert wasn’t in the deform group, add it if needed!
|
||||||
|
*/
|
||||||
|
if (do_add && w > add_thresh) {
|
||||||
|
newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "WeightVGEdit Modifier, deformWeight");
|
||||||
|
if(dv->dw) {
|
||||||
|
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
|
||||||
|
MEM_freeN(dv->dw);
|
||||||
|
}
|
||||||
|
dv->dw = newdw;
|
||||||
|
dv->dw[dv->totweight].weight = w;
|
||||||
|
dv->dw[dv->totweight].def_nr = defgrp_idx;
|
||||||
|
dv->totweight++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
82
source/blender/modifiers/intern/MOD_weightvg_util.h
Normal file
82
source/blender/modifiers/intern/MOD_weightvg_util.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2011 by Bastien Montagne.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): None yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file blender/modifiers/intern/MOD_util.h
|
||||||
|
* \ingroup modifiers
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MOD_WEIGHTVG_UTIL_H
|
||||||
|
#define MOD_WEIGHTVG_UTIL_H
|
||||||
|
|
||||||
|
/* so modifier types match their defines */
|
||||||
|
#include "MOD_modifiertypes.h"
|
||||||
|
|
||||||
|
struct Tex;
|
||||||
|
struct DerivedMesh;
|
||||||
|
struct Object;
|
||||||
|
/*struct ModifierData;
|
||||||
|
struct MappingInfoModifierData;*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX I’d like to make modified weights visible in WeightPaint mode,
|
||||||
|
* but couldn’t figure a way to do this…
|
||||||
|
* Maybe this will need changes in mesh_calc_modifiers (DerivedMesh.c)?
|
||||||
|
* Or the WeightPaint mode code itself?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
* Util functions. *
|
||||||
|
**************************************/
|
||||||
|
|
||||||
|
/* We cannot divide by zero (what a surprise…).
|
||||||
|
* So if -MOD_WEIGHTVGROUP_DIVMODE_ZEROFLOOR < weightf < MOD_WEIGHTVGROUP_DIVMODE_ZEROFLOOR,
|
||||||
|
* we clamp weightf to this value (or its negative version).
|
||||||
|
* Also used to avoid null power factor.
|
||||||
|
*/
|
||||||
|
#define MOD_WVG_ZEROFLOOR 1.0e-32f
|
||||||
|
|
||||||
|
/* Applies new_w weights to org_w ones, using either a texture, vgroup or constant value as factor.
|
||||||
|
* Return values are in org_w.
|
||||||
|
* If indices is not NULL, it must be a table of same length as org_w and new_w, mapping to the real
|
||||||
|
* 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(int num, int *indices, float *org_w, float *new_w, Object *ob,
|
||||||
|
struct DerivedMesh *dm, float fact, const char *defgrp_name, Tex *texture,
|
||||||
|
int tex_use_channel, int tex_mapping, Object *tex_map_object,
|
||||||
|
const char *tex_uvlayer_name);
|
||||||
|
|
||||||
|
/* Applies weights to given vgroup (defgroup), and optionnaly add/remove vertices from the group.
|
||||||
|
* If indices is not NULL, it must be a table of same length as weights, mapping to the real
|
||||||
|
* vertex index (in case the weight table does not cover the whole vertices...).
|
||||||
|
*/
|
||||||
|
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, int num, int *indices, float *weights,
|
||||||
|
int do_add, float add_thresh, int do_rem, float rem_thresh);
|
||||||
|
|
||||||
|
#endif /* MOD_WEIGHTVG_UTIL_H */
|
343
source/blender/modifiers/intern/MOD_weightvgedit.c
Normal file
343
source/blender/modifiers/intern/MOD_weightvgedit.c
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2011 by Bastien Montagne.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): None yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX I’d like to make modified weights visible in WeightPaint mode,
|
||||||
|
* but couldn’t figure a way to do this…
|
||||||
|
* Maybe this will need changes in mesh_calc_modifiers (DerivedMesh.c)?
|
||||||
|
* Or the WeightPaint mode code itself?
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#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 "BKE_cdderivedmesh.h"
|
||||||
|
#include "BKE_colortools.h" /* CurveMapping. */
|
||||||
|
#include "BKE_deform.h"
|
||||||
|
#include "BKE_mesh.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_texture.h" /* Texture masking. */
|
||||||
|
|
||||||
|
#include "depsgraph_private.h"
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
#include "MOD_util.h"
|
||||||
|
#include "MOD_weightvg_util.h"
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
* Modifiers functions. *
|
||||||
|
**************************************/
|
||||||
|
static void initData(ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
wmd->edit_flags = MOD_WVG_EDIT_CLAMP;
|
||||||
|
wmd->default_weight = 0.0f;
|
||||||
|
|
||||||
|
wmd->map_org_min = 0.0f;
|
||||||
|
wmd->map_org_max = 1.0f;
|
||||||
|
wmd->map_new_min = 0.0f;
|
||||||
|
wmd->map_new_max = 1.0f;
|
||||||
|
wmd->cmap_curve = curvemapping_add(1, 0.0, 0.0, 1.0, 1.0);
|
||||||
|
curvemapping_initialize(wmd->cmap_curve);
|
||||||
|
|
||||||
|
wmd->clamp_min_weight = 0.0f;
|
||||||
|
wmd->clamp_max_weight = 1.0f;
|
||||||
|
|
||||||
|
wmd->add_threshold = 0.01f;
|
||||||
|
wmd->rem_threshold = 0.01f;
|
||||||
|
|
||||||
|
wmd->mask_constant = 1.0f;
|
||||||
|
wmd->mask_tex_use_channel = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */
|
||||||
|
wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeData(ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
curvemapping_free(wmd->cmap_curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copyData(ModifierData *md, ModifierData *target)
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
WeightVGEditModifierData *twmd = (WeightVGEditModifierData*) target;
|
||||||
|
|
||||||
|
BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name));
|
||||||
|
|
||||||
|
twmd->edit_flags = wmd->edit_flags;
|
||||||
|
twmd->default_weight = wmd->default_weight;
|
||||||
|
|
||||||
|
twmd->map_org_min = wmd->map_org_min;
|
||||||
|
twmd->map_org_max = wmd->map_org_max;
|
||||||
|
twmd->map_new_min = wmd->map_new_min;
|
||||||
|
twmd->map_new_max = wmd->map_new_max;
|
||||||
|
twmd->cmap_curve = curvemapping_copy(wmd->cmap_curve);
|
||||||
|
|
||||||
|
twmd->clamp_min_weight = wmd->clamp_min_weight;
|
||||||
|
twmd->clamp_max_weight = wmd->clamp_max_weight;
|
||||||
|
|
||||||
|
twmd->add_threshold = wmd->add_threshold;
|
||||||
|
twmd->rem_threshold = wmd->rem_threshold;
|
||||||
|
|
||||||
|
twmd->mask_constant = wmd->mask_constant;
|
||||||
|
BLI_strncpy(twmd->mask_defgrp_name, wmd->mask_defgrp_name, sizeof(twmd->mask_defgrp_name));
|
||||||
|
twmd->mask_texture = wmd->mask_texture;
|
||||||
|
twmd->mask_tex_use_channel = wmd->mask_tex_use_channel;
|
||||||
|
twmd->mask_tex_mapping = wmd->mask_tex_mapping;
|
||||||
|
twmd->mask_tex_map_obj = wmd->mask_tex_map_obj;
|
||||||
|
BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name,
|
||||||
|
sizeof(twmd->mask_tex_uvlayer_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
CustomDataMask dataMask = 0;
|
||||||
|
|
||||||
|
/* We need vertex groups! */
|
||||||
|
dataMask |= CD_MASK_MDEFORMVERT;
|
||||||
|
|
||||||
|
/* Ask for UV coordinates if we need them. */
|
||||||
|
if(wmd->mask_tex_mapping == MOD_DISP_MAP_UV)
|
||||||
|
dataMask |= CD_MASK_MTFACE;
|
||||||
|
|
||||||
|
return dataMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dependsOnTime(ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
|
||||||
|
if(wmd->mask_texture)
|
||||||
|
return BKE_texture_dependsOnTime(wmd->mask_texture);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreachObjectLink(ModifierData *md, Object *ob,
|
||||||
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
||||||
|
void *userData)
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
walk(userData, ob, &wmd->mask_tex_map_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
|
||||||
|
walk(userData, ob, (ID **)&wmd->mask_texture);
|
||||||
|
|
||||||
|
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
|
||||||
|
Object *UNUSED(ob), DagNode *obNode)
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
DagNode *curNode;
|
||||||
|
|
||||||
|
if(wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
|
||||||
|
curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
|
||||||
|
|
||||||
|
dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
|
||||||
|
"WeightVGEdit Modifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
|
||||||
|
dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
|
||||||
|
"WeightVGEdit Modifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
/* If no vertex group, bypass. */
|
||||||
|
return (wmd->defgrp_name == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
||||||
|
int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
|
||||||
|
{
|
||||||
|
WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
|
||||||
|
DerivedMesh *dm = derivedData;
|
||||||
|
DerivedMesh *ret;
|
||||||
|
MDeformVert *dvert = NULL;
|
||||||
|
float *org_w = NULL; /* Array original weights. */
|
||||||
|
float *new_w = NULL; /* Array new weights. */
|
||||||
|
int numVerts;
|
||||||
|
int defgrp_idx;
|
||||||
|
int i;
|
||||||
|
char rel_ret = 0; /* Boolean, whether we have to release ret dm or not, when not using it! */
|
||||||
|
float *mapf = NULL; /* Cache for mapping factors. */
|
||||||
|
/* Flags. */
|
||||||
|
char do_map = wmd->edit_flags & MOD_WVG_EDIT_MAP;
|
||||||
|
char do_cmap = wmd->edit_flags & MOD_WVG_EDIT_CMAP;
|
||||||
|
char do_rev = wmd->edit_flags & MOD_WVG_EDIT_REVERSE_WEIGHTS;
|
||||||
|
char do_add = wmd->edit_flags & MOD_WVG_EDIT_ADD2VG;
|
||||||
|
char do_rem = wmd->edit_flags & MOD_WVG_EDIT_REMFVG;
|
||||||
|
char do_clamp = wmd->edit_flags & MOD_WVG_EDIT_CLAMP;
|
||||||
|
|
||||||
|
/* Get number of verts. */
|
||||||
|
numVerts = dm->getNumVerts(dm);
|
||||||
|
|
||||||
|
/* Check if we can just return the original mesh.
|
||||||
|
* Must have verts and therefore verts assigned to vgroups to do anything useful!
|
||||||
|
*/
|
||||||
|
if ((numVerts == 0) || (ob->defbase.first == NULL))
|
||||||
|
return dm;
|
||||||
|
|
||||||
|
/* Create a copy of our dmesh.
|
||||||
|
* TODO: This should be done only if needed, i.e. if dm has the org data !
|
||||||
|
*/
|
||||||
|
if (1) {
|
||||||
|
/* XXX Seems to create problems with weightpaint mode... */
|
||||||
|
// DM_set_only_copy(dm, CD_MASK_MDEFORMVERT); /* Only copy defgroup layer. */
|
||||||
|
ret = CDDM_copy(dm);
|
||||||
|
rel_ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = dm;
|
||||||
|
|
||||||
|
/* Get vgroup idx from its name. */
|
||||||
|
defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name);
|
||||||
|
|
||||||
|
/* Get actual dverts (ie vertex group data). */
|
||||||
|
if (defgrp_idx >= 0)
|
||||||
|
dvert = ret->getVertDataArray(ret, CD_MDEFORMVERT);
|
||||||
|
/* If no dverts, return unmodified data… */
|
||||||
|
if ((defgrp_idx < 0) || (dvert == NULL)) {
|
||||||
|
if (rel_ret)
|
||||||
|
ret->release(ret);
|
||||||
|
return dm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get org weights, assuming 0.0 for vertices not in given vgroup. */
|
||||||
|
org_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, org_w");
|
||||||
|
new_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, org_w");
|
||||||
|
for (i = 0; i < numVerts; i++) {
|
||||||
|
int j;
|
||||||
|
org_w[i] = new_w[i] = wmd->default_weight;
|
||||||
|
for (j = 0; j < dvert[i].totweight; j++) {
|
||||||
|
if(dvert[i].dw[j].def_nr == defgrp_idx) {
|
||||||
|
org_w[i] = new_w[i] = dvert[i].dw[j].weight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Do mapping. */
|
||||||
|
if (do_map) {
|
||||||
|
/* This mapping is a simple func: a*in + b.
|
||||||
|
* with a = (out_min - out_max)/(in_min - in_max)
|
||||||
|
* and b = out_max - a*in_max
|
||||||
|
* Note a and b are cached!
|
||||||
|
*/
|
||||||
|
if (mapf == NULL) {
|
||||||
|
float denom = wmd->map_org_min - wmd->map_org_max;
|
||||||
|
mapf = MEM_mallocN(sizeof(float) * 2, "WeightVGEdit, mapf");
|
||||||
|
if (denom > 0.0 && denom < MOD_WVG_ZEROFLOOR)
|
||||||
|
denom = MOD_WVG_ZEROFLOOR;
|
||||||
|
else if (denom < 0.0 && denom > -MOD_WVG_ZEROFLOOR)
|
||||||
|
denom = -MOD_WVG_ZEROFLOOR;
|
||||||
|
mapf[0] = (wmd->map_new_min - wmd->map_new_max) / denom;
|
||||||
|
mapf[1] = wmd->map_new_max - (mapf[0] * wmd->map_org_max);
|
||||||
|
}
|
||||||
|
new_w[i] = (mapf[0] * new_w[i]) + mapf[1];
|
||||||
|
}
|
||||||
|
if (do_cmap)
|
||||||
|
new_w[i] = curvemapping_evaluateF(wmd->cmap_curve, 0, new_w[i]);
|
||||||
|
if (do_rev)
|
||||||
|
new_w[i] = (-1.0 * new_w[i]) + 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do masking. */
|
||||||
|
weightvg_do_mask(numVerts, NULL, org_w, new_w, ob, ret, wmd->mask_constant,
|
||||||
|
wmd->mask_defgrp_name, wmd->mask_texture, wmd->mask_tex_use_channel,
|
||||||
|
wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
|
||||||
|
|
||||||
|
/* Do clamping. */
|
||||||
|
if (do_clamp) {
|
||||||
|
for (i = 0; i < numVerts; i++)
|
||||||
|
CLAMP(org_w[i], wmd->clamp_min_weight, wmd->clamp_max_weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update/add/remove from vgroup. */
|
||||||
|
weightvg_update_vg(dvert, defgrp_idx, numVerts, NULL, org_w, do_add, wmd->add_threshold,
|
||||||
|
do_rem, wmd->rem_threshold);
|
||||||
|
|
||||||
|
/* Freeing stuff. */
|
||||||
|
if (org_w)
|
||||||
|
MEM_freeN(org_w);
|
||||||
|
if (new_w)
|
||||||
|
MEM_freeN(new_w);
|
||||||
|
if (mapf)
|
||||||
|
MEM_freeN(mapf);
|
||||||
|
|
||||||
|
/* Return the vgroup-modified mesh. */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
|
||||||
|
struct EditMesh *UNUSED(editData),
|
||||||
|
DerivedMesh *derivedData)
|
||||||
|
{
|
||||||
|
return applyModifier(md, ob, derivedData, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModifierTypeInfo modifierType_WeightVGEdit = {
|
||||||
|
/* name */ "WeightVGEdit",
|
||||||
|
/* structName */ "WeightVGEditModifierData",
|
||||||
|
/* structSize */ sizeof(WeightVGEditModifierData),
|
||||||
|
/* type */ eModifierTypeType_Nonconstructive,
|
||||||
|
/* flags */ eModifierTypeFlag_AcceptsMesh
|
||||||
|
|eModifierTypeFlag_SupportsMapping
|
||||||
|
|eModifierTypeFlag_SupportsEditmode,
|
||||||
|
|
||||||
|
/* copyData */ copyData,
|
||||||
|
/* deformVerts */ NULL,
|
||||||
|
/* deformMatrices */ NULL,
|
||||||
|
/* deformVertsEM */ NULL,
|
||||||
|
/* deformMatricesEM */ NULL,
|
||||||
|
/* applyModifier */ applyModifier,
|
||||||
|
/* applyModifierEM */ applyModifierEM,
|
||||||
|
/* initData */ initData,
|
||||||
|
/* requiredDataMask */ requiredDataMask,
|
||||||
|
/* freeData */ freeData,
|
||||||
|
/* isDisabled */ isDisabled,
|
||||||
|
/* updateDepgraph */ updateDepgraph,
|
||||||
|
/* dependsOnTime */ dependsOnTime,
|
||||||
|
/* dependsOnNormals */ NULL,
|
||||||
|
/* foreachObjectLink */ foreachObjectLink,
|
||||||
|
/* foreachIDLink */ foreachIDLink,
|
||||||
|
};
|
||||||
|
|
433
source/blender/modifiers/intern/MOD_weightvgmix.c
Normal file
433
source/blender/modifiers/intern/MOD_weightvgmix.c
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2011 by Bastien Montagne.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): None yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX I’d like to make modified weights visible in WeightPaint mode,
|
||||||
|
* but couldn’t figure a way to do this…
|
||||||
|
* Maybe this will need changes in mesh_calc_modifiers (DerivedMesh.c)?
|
||||||
|
* Or the WeightPaint mode code itself?
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BKE_cdderivedmesh.h"
|
||||||
|
#include "BKE_deform.h"
|
||||||
|
#include "BKE_mesh.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_texture.h" /* Texture masking. */
|
||||||
|
|
||||||
|
#include "depsgraph_private.h"
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
#include "MOD_util.h"
|
||||||
|
#include "MOD_weightvg_util.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This mixes the old weight with the new weight factor.
|
||||||
|
*/
|
||||||
|
static float mix_weight(float weight, float weight2, char mix_mode)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* XXX Don’t know why, but the switch version takes many CPU time,
|
||||||
|
* and produces lag in realtime playback…
|
||||||
|
*/
|
||||||
|
switch (mix_mode)
|
||||||
|
{
|
||||||
|
case MOD_WVG_MIX_ADD:
|
||||||
|
return (weight + weight2);
|
||||||
|
case MOD_WVG_MIX_SUB:
|
||||||
|
return (weight - weight2);
|
||||||
|
case MOD_WVG_MIX_MUL:
|
||||||
|
return (weight * weight2);
|
||||||
|
case MOD_WVG_MIX_DIV:
|
||||||
|
/* Avoid dividing by zero (or really small values). */
|
||||||
|
if (0.0 <= weight2 < MOD_WVG_ZEROFLOOR)
|
||||||
|
weight2 = MOD_WVG_ZEROFLOOR;
|
||||||
|
else if (-MOD_WVG_ZEROFLOOR < weight2)
|
||||||
|
weight2 = -MOD_WVG_ZEROFLOOR;
|
||||||
|
return (weight / weight2);
|
||||||
|
case MOD_WVG_MIX_DIF:
|
||||||
|
return (weight < weight2 ? weight2 - weight : weight - weight2);
|
||||||
|
case MOD_WVG_MIX_AVG:
|
||||||
|
return (weight + weight2) / 2.0;
|
||||||
|
case MOD_WVG_MIX_SET:
|
||||||
|
default:
|
||||||
|
return weight2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (mix_mode == MOD_WVG_MIX_SET)
|
||||||
|
return weight2;
|
||||||
|
else if (mix_mode == MOD_WVG_MIX_ADD)
|
||||||
|
return (weight + weight2);
|
||||||
|
else if (mix_mode == MOD_WVG_MIX_SUB)
|
||||||
|
return (weight - weight2);
|
||||||
|
else if (mix_mode == MOD_WVG_MIX_MUL)
|
||||||
|
return (weight * weight2);
|
||||||
|
else if (mix_mode == MOD_WVG_MIX_DIV) {
|
||||||
|
/* Avoid dividing by zero (or really small values). */
|
||||||
|
if (weight2 < 0.0 && weight2 > -MOD_WVG_ZEROFLOOR)
|
||||||
|
weight2 = -MOD_WVG_ZEROFLOOR;
|
||||||
|
else if (weight2 >= 0.0 && weight2 < MOD_WVG_ZEROFLOOR)
|
||||||
|
weight2 = MOD_WVG_ZEROFLOOR;
|
||||||
|
return (weight / weight2);
|
||||||
|
}
|
||||||
|
else if (mix_mode == MOD_WVG_MIX_DIF)
|
||||||
|
return (weight < weight2 ? weight2 - weight : weight - weight2);
|
||||||
|
else if (mix_mode == MOD_WVG_MIX_AVG)
|
||||||
|
return (weight + weight2) / 2.0;
|
||||||
|
else return weight2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
* Modifiers functions. *
|
||||||
|
**************************************/
|
||||||
|
static void initData(ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
|
||||||
|
wmd->default_weight = 0.0;
|
||||||
|
wmd->default_weight2 = 0.0;
|
||||||
|
wmd->mix_mode = MOD_WVG_MIX_SET;
|
||||||
|
wmd->mix_set = MOD_WVG_SET_INTER;
|
||||||
|
|
||||||
|
wmd->mask_constant = 1.0f;
|
||||||
|
wmd->mask_tex_use_channel = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */
|
||||||
|
wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copyData(ModifierData *md, ModifierData *target)
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
WeightVGMixModifierData *twmd = (WeightVGMixModifierData*) target;
|
||||||
|
|
||||||
|
BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name));
|
||||||
|
BLI_strncpy(twmd->defgrp_name2, wmd->defgrp_name2, sizeof(twmd->defgrp_name2));
|
||||||
|
twmd->default_weight = wmd->default_weight;
|
||||||
|
twmd->default_weight2 = wmd->default_weight2;
|
||||||
|
twmd->mix_mode = wmd->mix_mode;
|
||||||
|
twmd->mix_set = wmd->mix_set;
|
||||||
|
|
||||||
|
twmd->mask_constant = wmd->mask_constant;
|
||||||
|
BLI_strncpy(twmd->mask_defgrp_name, wmd->mask_defgrp_name, sizeof(twmd->mask_defgrp_name));
|
||||||
|
twmd->mask_texture = wmd->mask_texture;
|
||||||
|
twmd->mask_tex_use_channel = wmd->mask_tex_use_channel;
|
||||||
|
twmd->mask_tex_mapping = wmd->mask_tex_mapping;
|
||||||
|
twmd->mask_tex_map_obj = wmd->mask_tex_map_obj;
|
||||||
|
BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name,
|
||||||
|
sizeof(twmd->mask_tex_uvlayer_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
CustomDataMask dataMask = 0;
|
||||||
|
|
||||||
|
/* We need vertex groups! */
|
||||||
|
dataMask |= CD_MASK_MDEFORMVERT;
|
||||||
|
|
||||||
|
/* Ask for UV coordinates if we need them. */
|
||||||
|
if(wmd->mask_tex_mapping == MOD_DISP_MAP_UV)
|
||||||
|
dataMask |= CD_MASK_MTFACE;
|
||||||
|
|
||||||
|
return dataMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dependsOnTime(ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
|
||||||
|
if(wmd->mask_texture)
|
||||||
|
return BKE_texture_dependsOnTime(wmd->mask_texture);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreachObjectLink(ModifierData *md, Object *ob,
|
||||||
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
||||||
|
void *userData)
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
walk(userData, ob, &wmd->mask_tex_map_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
|
||||||
|
walk(userData, ob, (ID **)&wmd->mask_texture);
|
||||||
|
|
||||||
|
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
|
||||||
|
Object *UNUSED(ob), DagNode *obNode)
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
DagNode *curNode;
|
||||||
|
|
||||||
|
if(wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
|
||||||
|
curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
|
||||||
|
|
||||||
|
dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
|
||||||
|
"WeightVGMix Modifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
|
||||||
|
dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
|
||||||
|
"WeightVGMix Modifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
/* If no vertex group, bypass. */
|
||||||
|
return (wmd->defgrp_name == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
||||||
|
int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
|
||||||
|
{
|
||||||
|
WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
|
||||||
|
DerivedMesh *dm = derivedData;
|
||||||
|
DerivedMesh *ret;
|
||||||
|
MDeformVert *dvert = NULL;
|
||||||
|
int numVerts;
|
||||||
|
int defgrp_idx, defgrp_idx2 = -1;
|
||||||
|
float *org_w = NULL;
|
||||||
|
float *new_w = NULL;
|
||||||
|
int *tidx, *indices = NULL;
|
||||||
|
int numIdx = 0;
|
||||||
|
int i, j;
|
||||||
|
char rel_ret = 0; /* Boolean, whether we have to release ret dm or not, when not using it! */
|
||||||
|
|
||||||
|
/* Get number of verts. */
|
||||||
|
numVerts = dm->getNumVerts(dm);
|
||||||
|
|
||||||
|
/* Check if we can just return the original mesh.
|
||||||
|
* Must have verts and therefore verts assigned to vgroups to do anything useful!
|
||||||
|
*/
|
||||||
|
if ((numVerts == 0) || (ob->defbase.first == NULL))
|
||||||
|
return dm;
|
||||||
|
|
||||||
|
/* Create a copy of our dmesh.
|
||||||
|
* TODO: This should be done only if needed !
|
||||||
|
*/
|
||||||
|
if (1) {
|
||||||
|
/* XXX Seems to create problems with weightpaint mode... */
|
||||||
|
// DM_set_only_copy(dm, CD_MASK_MDEFORMVERT); /* Only copy defgroup layer. */
|
||||||
|
ret = CDDM_copy(dm);
|
||||||
|
rel_ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = dm;
|
||||||
|
|
||||||
|
/* Get first vgroup idx from its name. */
|
||||||
|
defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name);
|
||||||
|
|
||||||
|
/* Get seconf vgroup idx from its name, if given. */
|
||||||
|
if (wmd->defgrp_name2)
|
||||||
|
defgrp_idx2 = defgroup_name_index(ob, wmd->defgrp_name2);
|
||||||
|
|
||||||
|
/* Get actual dverts (ie vertex group data). */
|
||||||
|
if (defgrp_idx >= 0)
|
||||||
|
dvert = ret->getVertDataArray(ret, CD_MDEFORMVERT);
|
||||||
|
/* If no dverts, return unmodified data… */
|
||||||
|
if ((defgrp_idx < 0) || (dvert == NULL)) {
|
||||||
|
if (rel_ret)
|
||||||
|
ret->release(ret);
|
||||||
|
return dm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find out which vertices to work on. */
|
||||||
|
tidx = MEM_mallocN(sizeof(int) * numVerts, "WeightVGMix Modifier, tidx");
|
||||||
|
switch (wmd->mix_set) {
|
||||||
|
case MOD_WVG_SET_ORG:
|
||||||
|
/* All vertices in first vgroup. */
|
||||||
|
for (i = 0; i < numVerts; i++) {
|
||||||
|
for (j = 0; j < dvert[i].totweight; j++) {
|
||||||
|
if(dvert[i].dw[j].def_nr == defgrp_idx) {
|
||||||
|
tidx[numIdx++] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD_WVG_SET_NEW:
|
||||||
|
/* All vertices in second vgroup. */
|
||||||
|
for (i = 0; i < numVerts; i++) {
|
||||||
|
for (j = 0; j < dvert[i].totweight; j++) {
|
||||||
|
if(dvert[i].dw[j].def_nr == defgrp_idx2) {
|
||||||
|
tidx[numIdx++] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD_WVG_SET_UNION:
|
||||||
|
/* All vertices in one vgroup or the other. */
|
||||||
|
for (i = 0; i < numVerts; i++) {
|
||||||
|
for (j = 0; j < dvert[i].totweight; j++) {
|
||||||
|
if(dvert[i].dw[j].def_nr == defgrp_idx || dvert[i].dw[j].def_nr == defgrp_idx2) {
|
||||||
|
tidx[numIdx++] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD_WVG_SET_INTER:
|
||||||
|
/* All vertices in both vgroups. */
|
||||||
|
for (i = 0; i < numVerts; i++) {
|
||||||
|
char idx1 = 0;
|
||||||
|
char idx2 = 0;
|
||||||
|
for (j = 0; j < dvert[i].totweight; j++) {
|
||||||
|
if(dvert[i].dw[j].def_nr == defgrp_idx) {
|
||||||
|
if (idx2) {
|
||||||
|
tidx[numIdx++] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
idx1 = 1;
|
||||||
|
}
|
||||||
|
else if(dvert[i].dw[j].def_nr == defgrp_idx2) {
|
||||||
|
if (idx1) {
|
||||||
|
tidx[numIdx++] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
idx2 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD_WVG_SET_ALL:
|
||||||
|
default:
|
||||||
|
/* Use all vertices, no need to do anything here. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (numIdx) {
|
||||||
|
indices = MEM_mallocN(sizeof(int) * numIdx, "WeightVGMix Modifier, indices");
|
||||||
|
memcpy(indices, tidx, sizeof(int) * numIdx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
numIdx = numVerts;
|
||||||
|
MEM_freeN(tidx);
|
||||||
|
|
||||||
|
org_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, org_w");
|
||||||
|
new_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, new_w");
|
||||||
|
|
||||||
|
/* Mix weights. */
|
||||||
|
for (i = 0; i < numIdx; i++) {
|
||||||
|
float weight2 = 0.0;
|
||||||
|
char w1 = 0;
|
||||||
|
char w2 = 0;
|
||||||
|
int idx = indices ? indices[i] : i;
|
||||||
|
for (j = 0; j < dvert[idx].totweight; j++) {
|
||||||
|
if(dvert[idx].dw[j].def_nr == defgrp_idx) {
|
||||||
|
org_w[i] = dvert[idx].dw[j].weight;
|
||||||
|
w1 = 1;
|
||||||
|
if (w2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(dvert[idx].dw[j].def_nr == defgrp_idx2) {
|
||||||
|
weight2 = dvert[idx].dw[j].weight;
|
||||||
|
w2 = 1;
|
||||||
|
if (w1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (w1 == 0)
|
||||||
|
org_w[i] = wmd->default_weight;
|
||||||
|
if (w2 == 0)
|
||||||
|
weight2 = wmd->default_weight2;
|
||||||
|
new_w[i] = mix_weight(org_w[i], weight2, wmd->mix_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do masking. */
|
||||||
|
weightvg_do_mask(numIdx, indices, org_w, new_w, ob, ret, wmd->mask_constant,
|
||||||
|
wmd->mask_defgrp_name, wmd->mask_texture, wmd->mask_tex_use_channel,
|
||||||
|
wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
|
||||||
|
|
||||||
|
/* Update (add to) vgroup.
|
||||||
|
* XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup.
|
||||||
|
*/
|
||||||
|
weightvg_update_vg(dvert, defgrp_idx, numIdx, indices, org_w, 1, -FLT_MAX, 0, 0.0f);
|
||||||
|
|
||||||
|
/* Freeing stuff. */
|
||||||
|
if (org_w)
|
||||||
|
MEM_freeN(org_w);
|
||||||
|
if (new_w)
|
||||||
|
MEM_freeN(new_w);
|
||||||
|
if (indices)
|
||||||
|
MEM_freeN(indices);
|
||||||
|
|
||||||
|
/* Return the vgroup-modified mesh. */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
|
||||||
|
struct EditMesh *UNUSED(editData),
|
||||||
|
DerivedMesh *derivedData)
|
||||||
|
{
|
||||||
|
return applyModifier(md, ob, derivedData, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModifierTypeInfo modifierType_WeightVGMix = {
|
||||||
|
/* name */ "WeightVGMix",
|
||||||
|
/* structName */ "WeightVGMixModifierData",
|
||||||
|
/* structSize */ sizeof(WeightVGMixModifierData),
|
||||||
|
/* type */ eModifierTypeType_Nonconstructive,
|
||||||
|
/* flags */ eModifierTypeFlag_AcceptsMesh
|
||||||
|
|eModifierTypeFlag_SupportsMapping
|
||||||
|
|eModifierTypeFlag_SupportsEditmode,
|
||||||
|
|
||||||
|
/* copyData */ copyData,
|
||||||
|
/* deformVerts */ NULL,
|
||||||
|
/* deformMatrices */ NULL,
|
||||||
|
/* deformVertsEM */ NULL,
|
||||||
|
/* deformMatricesEM */ NULL,
|
||||||
|
/* applyModifier */ applyModifier,
|
||||||
|
/* applyModifierEM */ applyModifierEM,
|
||||||
|
/* initData */ initData,
|
||||||
|
/* requiredDataMask */ requiredDataMask,
|
||||||
|
/* freeData */ NULL,
|
||||||
|
/* isDisabled */ isDisabled,
|
||||||
|
/* updateDepgraph */ updateDepgraph,
|
||||||
|
/* dependsOnTime */ dependsOnTime,
|
||||||
|
/* dependsOnNormals */ NULL,
|
||||||
|
/* foreachObjectLink */ foreachObjectLink,
|
||||||
|
/* foreachIDLink */ foreachIDLink,
|
||||||
|
};
|
||||||
|
|
512
source/blender/modifiers/intern/MOD_weightvgproximity.c
Normal file
512
source/blender/modifiers/intern/MOD_weightvgproximity.c
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2011 by Bastien Montagne.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): None yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX I’d like to make modified weights visible in WeightPaint mode,
|
||||||
|
* but couldn’t figure a way to do this…
|
||||||
|
* Maybe this will need changes in mesh_calc_modifiers (DerivedMesh.c)?
|
||||||
|
* Or the WeightPaint mode code itself?
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
#include "BLI_editVert.h"
|
||||||
|
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BKE_cdderivedmesh.h"
|
||||||
|
#include "BKE_deform.h"
|
||||||
|
#include "BKE_mesh.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_shrinkwrap.h" /* For SpaceTransform stuff. */
|
||||||
|
#include "BKE_texture.h" /* Texture masking. */
|
||||||
|
|
||||||
|
#include "depsgraph_private.h"
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
#include "MOD_util.h"
|
||||||
|
#include "MOD_weightvg_util.h"
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
* Util functions. *
|
||||||
|
**************************************/
|
||||||
|
|
||||||
|
/* Util macro. */
|
||||||
|
#define OUT_OF_MEMORY() ((void)printf("WeightVGProximity: Out of memory.\n"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the squared distance between two given points.
|
||||||
|
*/
|
||||||
|
static float squared_dist(const float *a, const float *b)
|
||||||
|
{
|
||||||
|
float tmp[3];
|
||||||
|
VECSUB(tmp, a, b);
|
||||||
|
return INPR(tmp, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find nearest vertex and/or edge and/or face, for each vertex (adapted from shrinkwrap.c).
|
||||||
|
*/
|
||||||
|
static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
|
||||||
|
float *dist_v, float *dist_e, float *dist_f,
|
||||||
|
DerivedMesh *target, const SpaceTransform *loc2trgt)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
BVHTreeFromMesh treeData_v = NULL_BVHTreeFromMesh;
|
||||||
|
BVHTreeFromMesh treeData_e = NULL_BVHTreeFromMesh;
|
||||||
|
BVHTreeFromMesh treeData_f = NULL_BVHTreeFromMesh;
|
||||||
|
BVHTreeNearest nearest_v = NULL_BVHTreeNearest;
|
||||||
|
BVHTreeNearest nearest_e = NULL_BVHTreeNearest;
|
||||||
|
BVHTreeNearest nearest_f = NULL_BVHTreeNearest;
|
||||||
|
|
||||||
|
if (dist_v) {
|
||||||
|
/* Create a bvh-tree of the given target's verts. */
|
||||||
|
bvhtree_from_mesh_verts(&treeData_v, target, 0.0, 2, 6);
|
||||||
|
if(treeData_v.tree == NULL) {
|
||||||
|
OUT_OF_MEMORY();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dist_e) {
|
||||||
|
/* Create a bvh-tree of the given target's edges. */
|
||||||
|
bvhtree_from_mesh_edges(&treeData_e, target, 0.0, 2, 6);
|
||||||
|
if(treeData_e.tree == NULL) {
|
||||||
|
OUT_OF_MEMORY();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dist_f) {
|
||||||
|
/* Create a bvh-tree of the given target's faces. */
|
||||||
|
bvhtree_from_mesh_faces(&treeData_f, target, 0.0, 2, 6);
|
||||||
|
if(treeData_f.tree == NULL) {
|
||||||
|
OUT_OF_MEMORY();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup nearest. */
|
||||||
|
nearest_v.index = nearest_e.index = nearest_f.index = -1;
|
||||||
|
/*nearest_v.dist = nearest_e.dist = nearest_f.dist = FLT_MAX;*/
|
||||||
|
/* Find the nearest vert/edge/face. */
|
||||||
|
#ifndef __APPLE__
|
||||||
|
#pragma omp parallel for default(none) private(i) firstprivate(nearest_v,nearest_e,nearest_f) \
|
||||||
|
shared(treeData_v,treeData_e,treeData_f,numVerts,v_cos,dist_v,dist_e, \
|
||||||
|
dist_f,loc2trgt) \
|
||||||
|
schedule(static)
|
||||||
|
#endif
|
||||||
|
for (i = 0; i < numVerts; ++i) {
|
||||||
|
float tmp_co[3];
|
||||||
|
|
||||||
|
/* Convert the vertex to tree coordinates. */
|
||||||
|
VECCOPY(tmp_co, v_cos[i]);
|
||||||
|
space_transform_apply(loc2trgt, tmp_co);
|
||||||
|
|
||||||
|
/* Use local proximity heuristics (to reduce the nearest search).
|
||||||
|
*
|
||||||
|
* If we already had an hit before, we assume this vertex is going to have a close hit to
|
||||||
|
* that other vertex, so we can initiate the "nearest.dist" with the expected value to that
|
||||||
|
* last hit.
|
||||||
|
* This will lead in prunning of the search tree.
|
||||||
|
*/
|
||||||
|
if (dist_v) {
|
||||||
|
nearest_v.dist = nearest_v.index != -1 ? squared_dist(tmp_co, nearest_v.co) : FLT_MAX;
|
||||||
|
/* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */
|
||||||
|
BLI_bvhtree_find_nearest(treeData_v.tree, tmp_co, &nearest_v, treeData_v.nearest_callback, &treeData_v);
|
||||||
|
dist_v[i] = sqrtf(nearest_v.dist);
|
||||||
|
}
|
||||||
|
if (dist_e) {
|
||||||
|
nearest_e.dist = nearest_e.index != -1 ? squared_dist(tmp_co, nearest_e.co) : FLT_MAX;
|
||||||
|
/* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */
|
||||||
|
BLI_bvhtree_find_nearest(treeData_e.tree, tmp_co, &nearest_e, treeData_e.nearest_callback, &treeData_e);
|
||||||
|
dist_e[i] = sqrtf(nearest_e.dist);
|
||||||
|
}
|
||||||
|
if (dist_f) {
|
||||||
|
nearest_f.dist = nearest_f.index != -1 ? squared_dist(tmp_co, nearest_f.co) : FLT_MAX;
|
||||||
|
/* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */
|
||||||
|
BLI_bvhtree_find_nearest(treeData_f.tree, tmp_co, &nearest_f, treeData_f.nearest_callback, &treeData_f);
|
||||||
|
dist_f[i] = sqrtf(nearest_f.dist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dist_v)
|
||||||
|
free_bvhtree_from_mesh(&treeData_v);
|
||||||
|
if (dist_e)
|
||||||
|
free_bvhtree_from_mesh(&treeData_e);
|
||||||
|
if (dist_f)
|
||||||
|
free_bvhtree_from_mesh(&treeData_f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the real distance between a vertex and another reference object.
|
||||||
|
* Note that it works in final world space (i.e. with constraints etc. applied).
|
||||||
|
*/
|
||||||
|
static void get_vert2ob_distance(int numVerts, float (*v_cos)[3], float *dist,
|
||||||
|
const Object* ob, const Object* obr)
|
||||||
|
{
|
||||||
|
/* Vertex and ref object coordinates. */
|
||||||
|
float v_wco[3],
|
||||||
|
or_wco[3],
|
||||||
|
or_wro[3][3], /*unused*/
|
||||||
|
or_wsz[3]; /*unused*/
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Get world-coordinates of the reference object (constraints and anim included).
|
||||||
|
* We also get rotation and scale, even though we do not want them…
|
||||||
|
*/
|
||||||
|
mat4_to_loc_rot_size(or_wco, or_wro, or_wsz, (float (*)[4])obr->obmat);
|
||||||
|
|
||||||
|
for (i = 0; i < numVerts; i++) {
|
||||||
|
/* Get world-coordinates of the vertex (constraints and anim included). */
|
||||||
|
mul_v3_m4v3(v_wco, (float (*)[4])ob->obmat, v_cos[i]);
|
||||||
|
/* Return distance between both coordinates. */
|
||||||
|
dist[i] = len_v3v3(v_wco, or_wco);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the real distance between an object and another reference object.
|
||||||
|
* Note that it works in final world space (i.e. with constraints etc. applied).
|
||||||
|
*/
|
||||||
|
static float get_ob2ob_distance(const Object* ob, const Object* obr)
|
||||||
|
{
|
||||||
|
/* Both objects coordinates. */
|
||||||
|
float o_wco[3],
|
||||||
|
o_wro[3][3], /*unused*/
|
||||||
|
o_wsz[3], /*unused*/
|
||||||
|
or_wco[3],
|
||||||
|
or_wro[3][3],/*unused*/
|
||||||
|
or_wsz[3]; /*unused*/
|
||||||
|
/* Get world-coordinates of both objects (constraints and anim included).
|
||||||
|
* We also get rotation and scale, even though we do not want them…
|
||||||
|
*/
|
||||||
|
mat4_to_loc_rot_size(o_wco, o_wro, o_wsz, (float (*)[4])ob->obmat);
|
||||||
|
mat4_to_loc_rot_size(or_wco, or_wro, or_wsz, (float (*)[4])obr->obmat);
|
||||||
|
/* Return distance between both coordinates. */
|
||||||
|
return len_v3v3(o_wco, or_wco);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
* Modifiers functions. *
|
||||||
|
**************************************/
|
||||||
|
static void initData(ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
|
||||||
|
wmd->proximity_mode = MOD_WVG_PROXIMITY_OBJ2OBJDIST;
|
||||||
|
wmd->proximity_flags = MOD_WVG_PROXIMITY_O2VD_VERTS;
|
||||||
|
|
||||||
|
wmd->mask_constant = 1.0f;
|
||||||
|
wmd->mask_tex_use_channel = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */
|
||||||
|
wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copyData(ModifierData *md, ModifierData *target)
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
WeightVGProximityModifierData *twmd = (WeightVGProximityModifierData*) target;
|
||||||
|
|
||||||
|
BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name));
|
||||||
|
twmd->proximity_mode = wmd->proximity_mode;
|
||||||
|
twmd->proximity_flags = wmd->proximity_flags;
|
||||||
|
twmd->proximity_ob_target = wmd->proximity_ob_target;
|
||||||
|
|
||||||
|
twmd->mask_constant = wmd->mask_constant;
|
||||||
|
BLI_strncpy(twmd->mask_defgrp_name, wmd->mask_defgrp_name, sizeof(twmd->mask_defgrp_name));
|
||||||
|
twmd->mask_texture = wmd->mask_texture;
|
||||||
|
twmd->mask_tex_use_channel = wmd->mask_tex_use_channel;
|
||||||
|
twmd->mask_tex_mapping = wmd->mask_tex_mapping;
|
||||||
|
twmd->mask_tex_map_obj = wmd->mask_tex_map_obj;
|
||||||
|
BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name,
|
||||||
|
sizeof(twmd->mask_tex_uvlayer_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
CustomDataMask dataMask = 0;
|
||||||
|
|
||||||
|
/* We need vertex groups! */
|
||||||
|
dataMask |= CD_MASK_MDEFORMVERT;
|
||||||
|
|
||||||
|
/* Ask for UV coordinates if we need them. */
|
||||||
|
if(wmd->mask_tex_mapping == MOD_DISP_MAP_UV)
|
||||||
|
dataMask |= CD_MASK_MTFACE;
|
||||||
|
|
||||||
|
return dataMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dependsOnTime(ModifierData *md)
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
|
||||||
|
if(wmd->mask_texture)
|
||||||
|
return BKE_texture_dependsOnTime(wmd->mask_texture);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreachObjectLink(ModifierData *md, Object *ob,
|
||||||
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
||||||
|
void *userData)
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
walk(userData, ob, &wmd->proximity_ob_target);
|
||||||
|
walk(userData, ob, &wmd->mask_tex_map_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
|
||||||
|
walk(userData, ob, (ID **)&wmd->mask_texture);
|
||||||
|
|
||||||
|
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
|
||||||
|
Object *UNUSED(ob), DagNode *obNode)
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
DagNode *curNode;
|
||||||
|
|
||||||
|
if (wmd->proximity_ob_target) {
|
||||||
|
curNode = dag_get_node(forest, wmd->proximity_ob_target);
|
||||||
|
dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
|
||||||
|
"WeightVGProximity Modifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
|
||||||
|
curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
|
||||||
|
|
||||||
|
dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
|
||||||
|
"WeightVGProximity Modifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
|
||||||
|
dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
|
||||||
|
"WeightVGProximity Modifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
/* If no vertex group, bypass. */
|
||||||
|
if (wmd->defgrp_name == NULL) return 1;
|
||||||
|
/* If no target object, bypass. */
|
||||||
|
return (wmd->proximity_ob_target == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
||||||
|
int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
|
||||||
|
{
|
||||||
|
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md;
|
||||||
|
DerivedMesh *dm = derivedData;
|
||||||
|
DerivedMesh *ret;
|
||||||
|
MDeformVert *dvert = NULL;
|
||||||
|
int numVerts;
|
||||||
|
float (*v_cos)[3] = NULL; /* The vertices coordinates. */
|
||||||
|
Object *obr; /* Our target object. */
|
||||||
|
int defgrp_idx;
|
||||||
|
float *tw = NULL;
|
||||||
|
float *org_w = NULL;
|
||||||
|
float *new_w =NULL;
|
||||||
|
int *tidx, *indices = NULL;
|
||||||
|
int numIdx = 0;
|
||||||
|
int i, j;
|
||||||
|
char rel_ret = 0; /* Boolean, whether we have to release ret dm or not, when not using it! */
|
||||||
|
|
||||||
|
/* Get number of verts. */
|
||||||
|
numVerts = dm->getNumVerts(dm);
|
||||||
|
|
||||||
|
/* Check if we can just return the original mesh.
|
||||||
|
* Must have verts and therefore verts assigned to vgroups to do anything useful!
|
||||||
|
*/
|
||||||
|
if ((numVerts == 0) || (ob->defbase.first == NULL))
|
||||||
|
return dm;
|
||||||
|
|
||||||
|
/* Create a copy of our dmesh.
|
||||||
|
* TODO: This should be done only if needed !
|
||||||
|
*/
|
||||||
|
if (1) {
|
||||||
|
/* XXX Seems to create problems with weightpaint mode... */
|
||||||
|
// DM_set_only_copy(dm, CD_MASK_MDEFORMVERT); /* Only copy defgroup layer. */
|
||||||
|
ret = CDDM_copy(dm);
|
||||||
|
rel_ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = dm;
|
||||||
|
|
||||||
|
/* Get vgroup idx from its name. */
|
||||||
|
defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name);
|
||||||
|
|
||||||
|
/* Get actual dverts (ie vertex group data). */
|
||||||
|
if (defgrp_idx >= 0)
|
||||||
|
dvert = ret->getVertDataArray(ret, CD_MDEFORMVERT);
|
||||||
|
/* Get our target object. */
|
||||||
|
obr = wmd->proximity_ob_target;
|
||||||
|
/* If no dverts or target object, return unmodified data… */
|
||||||
|
if ((defgrp_idx < 0) || (dvert == NULL) || (!obr)) {
|
||||||
|
if (rel_ret)
|
||||||
|
ret->release(ret);
|
||||||
|
return dm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight.
|
||||||
|
*/
|
||||||
|
tidx = MEM_mallocN(sizeof(int) * numVerts, "WeightVGProximity Modifier, tidx");
|
||||||
|
tw = MEM_mallocN(sizeof(float) * numVerts, "WeightVGProximity Modifier, tw");
|
||||||
|
for (i = 0; i < numVerts; i++) {
|
||||||
|
for (j = 0; j < dvert[i].totweight; j++) {
|
||||||
|
if(dvert[i].dw[j].def_nr == defgrp_idx) {
|
||||||
|
tidx[numIdx] = i;
|
||||||
|
tw[numIdx++] = dvert[i].dw[j].weight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indices = MEM_mallocN(sizeof(int) * numIdx, "WeightVGProximity Modifier, indices");
|
||||||
|
memcpy(indices, tidx, sizeof(int) * numIdx);
|
||||||
|
org_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, org_w");
|
||||||
|
new_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, new_w");
|
||||||
|
memcpy(org_w, tw, sizeof(float) * numIdx);
|
||||||
|
MEM_freeN(tidx);
|
||||||
|
MEM_freeN(tw);
|
||||||
|
|
||||||
|
/* Get our vertex coordinates. */
|
||||||
|
v_cos = MEM_mallocN(sizeof(float[3]) * numIdx, "WeightVGProximity Modifier, v_cos");
|
||||||
|
for (i = 0; i < numIdx; i++)
|
||||||
|
ret->getVertCo(ret, indices[i], v_cos[i]);
|
||||||
|
|
||||||
|
/* Compute wanted distances. */
|
||||||
|
if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJ2OBJDIST) {
|
||||||
|
float dist = get_ob2ob_distance(ob, obr);
|
||||||
|
for(i = 0; i < numIdx; i++)
|
||||||
|
new_w[i] = dist;
|
||||||
|
}
|
||||||
|
else if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJ2VERTDIST) {
|
||||||
|
char use_trgt_verts = (wmd->proximity_flags & MOD_WVG_PROXIMITY_O2VD_VERTS);
|
||||||
|
char use_trgt_edges = (wmd->proximity_flags & MOD_WVG_PROXIMITY_O2VD_EDGES);
|
||||||
|
char use_trgt_faces = (wmd->proximity_flags & MOD_WVG_PROXIMITY_O2VD_FACES);
|
||||||
|
|
||||||
|
if (use_trgt_verts || use_trgt_edges || use_trgt_faces) {
|
||||||
|
DerivedMesh *target_dm = obr->derivedFinal;
|
||||||
|
if (!target_dm) {
|
||||||
|
if (ELEM3(obr->type, OB_CURVE, OB_SURF, OB_FONT))
|
||||||
|
target_dm = CDDM_from_curve(obr);
|
||||||
|
else if (obr->type == OB_MESH) {
|
||||||
|
Mesh *me = (Mesh*)obr->data;
|
||||||
|
if (me->edit_mesh)
|
||||||
|
target_dm = CDDM_from_editmesh((EditMesh*)me->edit_mesh, me);
|
||||||
|
else
|
||||||
|
target_dm = CDDM_from_mesh(me, obr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must check that we do have a valid target_dm! */
|
||||||
|
if (target_dm) {
|
||||||
|
SpaceTransform loc2trgt;
|
||||||
|
float *dists_v = use_trgt_verts ? MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, dists_v") : NULL;
|
||||||
|
float *dists_e = use_trgt_edges ? MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, dists_e") : NULL;
|
||||||
|
float *dists_f = use_trgt_faces ? MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, dists_f") : NULL;
|
||||||
|
|
||||||
|
space_transform_setup(&loc2trgt, ob, obr);
|
||||||
|
get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f,
|
||||||
|
target_dm, &loc2trgt);
|
||||||
|
for(i = 0; i < numIdx; i++) {
|
||||||
|
new_w[i] = dists_v ? dists_v[i] : FLT_MAX;
|
||||||
|
new_w[i] = dists_e ? minf(dists_e[i], new_w[i]) : new_w[i];
|
||||||
|
new_w[i] = dists_f ? minf(dists_f[i], new_w[i]) : new_w[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Else, fall back to default obj2vert behavior. */
|
||||||
|
else
|
||||||
|
get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do masking. */
|
||||||
|
weightvg_do_mask(numIdx, indices, org_w, new_w, ob, ret, wmd->mask_constant,
|
||||||
|
wmd->mask_defgrp_name, wmd->mask_texture, wmd->mask_tex_use_channel,
|
||||||
|
wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
|
||||||
|
|
||||||
|
/* Update vgroup. Note we never add nor remove vertices from vgroup here. */
|
||||||
|
weightvg_update_vg(dvert, defgrp_idx, numIdx, indices, org_w, 0, 0.0f, 0, 0.0f);
|
||||||
|
|
||||||
|
/* Freeing stuff. */
|
||||||
|
if (org_w)
|
||||||
|
MEM_freeN(org_w);
|
||||||
|
if (new_w)
|
||||||
|
MEM_freeN(new_w);
|
||||||
|
if (indices)
|
||||||
|
MEM_freeN(indices);
|
||||||
|
if (v_cos)
|
||||||
|
MEM_freeN(v_cos);
|
||||||
|
|
||||||
|
/* Return the vgroup-modified mesh. */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
|
||||||
|
struct EditMesh *UNUSED(editData),
|
||||||
|
DerivedMesh *derivedData)
|
||||||
|
{
|
||||||
|
return applyModifier(md, ob, derivedData, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModifierTypeInfo modifierType_WeightVGProximity = {
|
||||||
|
/* name */ "WeightVGProximity",
|
||||||
|
/* structName */ "WeightVGProximityModifierData",
|
||||||
|
/* structSize */ sizeof(WeightVGProximityModifierData),
|
||||||
|
/* type */ eModifierTypeType_Nonconstructive,
|
||||||
|
/* flags */ eModifierTypeFlag_AcceptsMesh
|
||||||
|
|eModifierTypeFlag_SupportsMapping
|
||||||
|
|eModifierTypeFlag_SupportsEditmode,
|
||||||
|
|
||||||
|
/* copyData */ copyData,
|
||||||
|
/* deformVerts */ NULL,
|
||||||
|
/* deformMatrices */ NULL,
|
||||||
|
/* deformVertsEM */ NULL,
|
||||||
|
/* deformMatricesEM */ NULL,
|
||||||
|
/* applyModifier */ applyModifier,
|
||||||
|
/* applyModifierEM */ applyModifierEM,
|
||||||
|
/* initData */ initData,
|
||||||
|
/* requiredDataMask */ requiredDataMask,
|
||||||
|
/* freeData */ NULL,
|
||||||
|
/* isDisabled */ isDisabled,
|
||||||
|
/* updateDepgraph */ updateDepgraph,
|
||||||
|
/* dependsOnTime */ dependsOnTime,
|
||||||
|
/* dependsOnNormals */ NULL,
|
||||||
|
/* foreachObjectLink */ foreachObjectLink,
|
||||||
|
/* foreachIDLink */ foreachIDLink,
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user