From 6b0d932c0d27dbce5e62e2a422e388e02f341a52 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 1 May 2011 15:16:59 +0000 Subject: [PATCH] warp modifier, added in the render branch for durian. simple modifier, almost like a hook, except it can deform with 2 object source -> target, has option to preserve rotation and use different falloff types. --- .../startup/bl_ui/properties_data_modifier.py | 42 ++ source/blender/blenloader/intern/readfile.c | 7 + source/blender/blenloader/intern/writefile.c | 6 + source/blender/makesdna/DNA_modifier_types.h | 62 ++- source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_modifier.c | 146 +++++-- source/blender/modifiers/CMakeLists.txt | 1 + source/blender/modifiers/MOD_modifiertypes.h | 1 + .../blender/modifiers/intern/MOD_displace.c | 88 +---- source/blender/modifiers/intern/MOD_util.c | 90 +++++ source/blender/modifiers/intern/MOD_util.h | 1 + source/blender/modifiers/intern/MOD_warp.c | 359 ++++++++++++++++++ 12 files changed, 679 insertions(+), 125 deletions(-) create mode 100644 source/blender/modifiers/intern/MOD_warp.c diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index e640654ea69..817ad1d3a76 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -635,6 +635,48 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel): sub.prop(md, "scale_x", text="Scale X") sub.prop(md, "scale_y", text="Scale Y") + def WARP(self, layout, ob, md): + use_falloff = (md.falloff_type != 'NONE') + split = layout.split() + + col = split.column() + col.label(text="From:") + col.prop(md, "object_from", text="") + + col.prop(md, "use_volume_preserve") + + col = split.column() + col.label(text="To:") + col.prop(md, "object_to", text="") + col.prop_search(md, "vertex_group", ob, "vertex_groups", text="") + + col = layout.column() + + row = col.row(align=True) + row.prop(md, "strength") + if use_falloff: + row.prop(md, "falloff_radius") + + col.prop(md, "falloff_type") + if use_falloff: + if md.falloff_type == 'CURVE': + col.template_curve_mapping(md, "falloff_curve") + + # 2 new columns + split = layout.split() + col = split.column() + col.label(text="Texture:") + col.prop(md, "texture", text="") + + col = split.column() + col.label(text="Texture Coordinates:") + col.prop(md, "texture_coords", text="") + + if md.texture_coords == 'OBJECT': + layout.prop(md, "texture_coordinate_object", text="Object") + elif md.texture_coords == 'UV' and ob.type == 'MESH': + layout.prop_object(md, "uv_layer", ob.data, "uv_textures") + def WAVE(self, layout, ob, md): split = layout.split() diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index bfec26375bb..e1b13e0ee50 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4122,6 +4122,13 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) SWITCH_INT(mmd->bindcos[a]) } } + else if (md->type==eModifierType_Warp) { + WarpModifierData *tmd = (WarpModifierData *) md; + + tmd->curfalloff= newdataadr(fd, tmd->curfalloff); + if(tmd->curfalloff) + direct_link_curvemapping(fd, tmd->curfalloff); + } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index af4f97fc78d..f84c4898813 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1274,6 +1274,12 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->dyninfluences); writedata(wd, DATA, sizeof(int)*mmd->totvert, mmd->dynverts); } + else if (md->type==eModifierType_Warp) { + WarpModifierData *tmd = (WarpModifierData*) md; + if(tmd->curfalloff) { + write_curvemapping(wd, tmd->curfalloff); + } + } } } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index de84f69c78d..d2d8e014015 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -70,8 +70,6 @@ typedef enum ModifierType { eModifierType_ShapeKey, eModifierType_Solidify, eModifierType_Screw, - /* placeholder, keep this so durian files load in - * trunk with the correct modifier once its merged */ eModifierType_Warp, NUM_MODIFIER_TYPES } ModifierType; @@ -107,6 +105,17 @@ typedef enum { eSubsurfModifierFlag_SubsurfUv = (1<<3) } SubsurfModifierFlag; +/* not a real modifier */ +typedef struct MappingInfoModifierData { + ModifierData modifier; + + struct Tex *texture; + struct Object *map_object; + char uvlayer_name[32]; + int uvlayer_tmp; + int texmapping; +} MappingInfoModifierData; + typedef struct SubsurfModifierData { ModifierData modifier; @@ -292,15 +301,19 @@ typedef struct SmokeModifierData { typedef struct DisplaceModifierData { ModifierData modifier; + /* keep in sync with MappingInfoModifierData */ struct Tex *texture; + struct Object *map_object; + char uvlayer_name[32]; + int uvlayer_tmp; + int texmapping; + int pad10; + /* end MappingInfoModifierData */ + float strength; int direction; char defgrp_name[32]; float midlevel; - int texmapping; - struct Object *map_object; - char uvlayer_name[32]; - int uvlayer_tmp, pad; } DisplaceModifierData; /* DisplaceModifierData->direction */ @@ -733,5 +746,42 @@ typedef struct ScrewModifierData { #define MOD_SCREW_OBJECT_OFFSET (1<<2) // #define MOD_SCREW_OBJECT_ANGLE (1<<4) +typedef struct WarpModifierData { + ModifierData modifier; + + /* keep in sync with MappingInfoModifierData */ + struct Tex *texture; + struct Object *map_object; + char uvlayer_name[32]; + int uvlayer_tmp; + int texmapping; + int pad10; + /* end MappingInfoModifierData */ + + float strength; + + struct Object *object_from; + struct Object *object_to; + struct CurveMapping *curfalloff; + char defgrp_name[32]; /* optional vertexgroup name */ + float falloff_radius; + char flag; /* not used yet */ + char falloff_type; + char pad[2]; +} WarpModifierData; + +#define MOD_WARP_VOLUME_PRESERVE 1 + +typedef enum { + eWarp_Falloff_None = 0, + eWarp_Falloff_Curve = 1, + eWarp_Falloff_Sharp = 2, /* PROP_SHARP */ + eWarp_Falloff_Smooth = 3, /* PROP_SMOOTH */ + eWarp_Falloff_Root = 4, /* PROP_ROOT */ + eWarp_Falloff_Linear = 5, /* PROP_LIN */ + eWarp_Falloff_Const = 6, /* PROP_CONST */ + eWarp_Falloff_Sphere = 7, /* PROP_SPHERE */ + /* PROP_RANDOM not used */ +} WarpModifierFalloff; #endif diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 2816a8717c1..53af242a0ac 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -559,6 +559,7 @@ extern StructRNA RNA_VertexPaint; extern StructRNA RNA_VoronoiTexture; extern StructRNA RNA_VoxelData; extern StructRNA RNA_VoxelDataTexture; +extern StructRNA RNA_WarpModifier; extern StructRNA RNA_WaveModifier; extern StructRNA RNA_Window; extern StructRNA RNA_WindowManager; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index b58fa98e051..18a93b9defb 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -79,6 +79,7 @@ EnumPropertyItem modifier_type_items[] ={ {eModifierType_Shrinkwrap, "SHRINKWRAP", ICON_MOD_SHRINKWRAP, "Shrinkwrap", ""}, {eModifierType_SimpleDeform, "SIMPLE_DEFORM", ICON_MOD_SIMPLEDEFORM, "Simple Deform", ""}, {eModifierType_Smooth, "SMOOTH", ICON_MOD_SMOOTH, "Smooth", ""}, + {eModifierType_Warp, "WARP", ICON_MOD_SUBSURF, "Warp", ""}, {eModifierType_Wave, "WAVE", ICON_MOD_WAVE, "Wave", ""}, {0, "", 0, "Simulate", ""}, {eModifierType_Cloth, "CLOTH", ICON_MOD_CLOTH, "Cloth", ""}, @@ -180,6 +181,8 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_SolidifyModifier; case eModifierType_Screw: return &RNA_ScrewModifier; + case eModifierType_Warp: + return &RNA_WarpModifier; default: return &RNA_Modifier; } @@ -372,10 +375,10 @@ 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)); } -static void rna_DisplaceModifier_uvlayer_set(PointerRNA *ptr, const char *value) +static void rna_MappingInfo_uvlayer_set(PointerRNA *ptr, const char *value) { - DisplaceModifierData *smd= (DisplaceModifierData*)ptr->data; - rna_object_uvlayer_name_set(ptr, value, smd->uvlayer_name, sizeof(smd->uvlayer_name)); + MappingInfoModifierData *mmd= (MappingInfoModifierData *)ptr->data; + rna_object_uvlayer_name_set(ptr, value, mmd->uvlayer_name, sizeof(mmd->uvlayer_name)); } static void rna_UVProjectModifier_uvlayer_set(PointerRNA *ptr, const char *value) @@ -384,6 +387,12 @@ static void rna_UVProjectModifier_uvlayer_set(PointerRNA *ptr, const char *value rna_object_uvlayer_name_set(ptr, value, umd->uvlayer_name, sizeof(umd->uvlayer_name)); } +static void RNA_WarpModifier_vgroup_set(PointerRNA *ptr, const char *value) +{ + WarpModifierData *tmd= (WarpModifierData*)ptr->data; + rna_object_vgroup_name_set(ptr, value, tmd->defgrp_name, sizeof(tmd->defgrp_name)); +} + static void rna_WaveModifier_uvlayer_set(PointerRNA *ptr, const char *value) { WaveModifierData *wmd= (WaveModifierData*)ptr->data; @@ -619,6 +628,106 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_generic_map_info(StructRNA *srna) +{ + static EnumPropertyItem prop_texture_coordinates_items[] = { + {MOD_DISP_MAP_LOCAL, "LOCAL", 0, "Map", ""}, + {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}}; + + PropertyRNA *prop; + + prop= RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "Texture", ""); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "texmapping"); + RNA_def_property_enum_items(prop, prop_texture_coordinates_items); + RNA_def_property_ui_text(prop, "Texture Coordinates", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + + prop= RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "uvlayer_name"); + RNA_def_property_ui_text(prop, "UV Layer", "UV layer name"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MappingInfo_uvlayer_set"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "texture_coordinate_object", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "map_object"); + RNA_def_property_ui_text(prop, "Texture Coordinate Object", ""); + 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_warp(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem prop_falloff_items[] = { + {eWarp_Falloff_None, "NONE", 0, "No Falloff", ""}, + {eWarp_Falloff_Curve, "CURVE", 0, "Curve", ""}, + {eWarp_Falloff_Smooth, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""}, + {eWarp_Falloff_Sphere, "SPHERE", ICON_SPHERECURVE, "Sphere", ""}, + {eWarp_Falloff_Root, "ROOT", ICON_ROOTCURVE, "Root", ""}, + {eWarp_Falloff_Sharp, "SHARP", ICON_SHARPCURVE, "Sharp", ""}, + {eWarp_Falloff_Linear, "LINEAR", ICON_LINCURVE, "Linear", ""}, + {eWarp_Falloff_Const, "CONSTANT", ICON_NOCURVE, "Constant", ""}, + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "WarpModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Warp Modifier", "Warp modifier"); + RNA_def_struct_sdna(srna, "WarpModifierData"); + //RNA_def_struct_ui_icon(srna, ICON_MOD_SUBSURF); + + prop= RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "From", "Object to transform from"); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + + prop= RNA_def_property(srna, "object_to", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "To", "Object to transform to"); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + + prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -100, 100, 10, 2); + RNA_def_property_ui_text(prop, "Strength", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_falloff_items); + RNA_def_property_ui_text(prop, "Falloff Type", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "falloff_radius", PROP_FLOAT, PROP_UNSIGNED); + RNA_def_property_ui_text(prop, "Radius", "Radius to apply"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "falloff_curve", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curfalloff"); + RNA_def_property_ui_text(prop, "Falloff Curve", "Custom Lamp Falloff Curve"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "use_volume_preserve", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WARP_VOLUME_PRESERVE); + RNA_def_property_ui_text(prop, "Preserve Volume", "Preserve volume when rotations are used"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + 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 for modulating the deform"); + RNA_def_property_string_funcs(prop, NULL, NULL, "RNA_WarpModifier_vgroup_set"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + rna_def_modifier_generic_map_info(srna); +} + static void rna_def_modifier_multires(BlenderRNA *brna) { StructRNA *srna; @@ -1287,13 +1396,6 @@ static void rna_def_modifier_displace(BlenderRNA *brna) {MOD_DISP_DIR_RGB_XYZ, "RGB_TO_XYZ", 0, "RGB to XYZ", ""}, {0, NULL, 0, NULL, NULL}}; - static EnumPropertyItem prop_texture_coordinates_items[] = { - {MOD_DISP_MAP_LOCAL, "LOCAL", 0, "Map", ""}, - {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}}; - srna= RNA_def_struct(brna, "DisplaceModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Displace Modifier", "Displacement modifier"); RNA_def_struct_sdna(srna, "DisplaceModifierData"); @@ -1305,11 +1407,6 @@ static void rna_def_modifier_displace(BlenderRNA *brna) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DisplaceModifier_vgroup_set"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop= RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); - RNA_def_property_ui_text(prop, "Texture", ""); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop= RNA_def_property(srna, "mid_level", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "midlevel"); RNA_def_property_range(prop, 0, 1); @@ -1328,23 +1425,7 @@ static void rna_def_modifier_displace(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Direction", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop= RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "texmapping"); - RNA_def_property_enum_items(prop, prop_texture_coordinates_items); - RNA_def_property_ui_text(prop, "Texture Coordinates", ""); - RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); - - prop= RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "uvlayer_name"); - RNA_def_property_ui_text(prop, "UV Layer", "UV layer name"); - RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DisplaceModifier_uvlayer_set"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - - prop= RNA_def_property(srna, "texture_coordinate_object", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "map_object"); - RNA_def_property_ui_text(prop, "Texture Coordinate Object", ""); - RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK); - RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + rna_def_modifier_generic_map_info(srna); } static void rna_def_modifier_uvproject(BlenderRNA *brna) @@ -2375,6 +2456,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_fluidsim(brna); rna_def_modifier_mask(brna); rna_def_modifier_simpledeform(brna); + rna_def_modifier_warp(brna); rna_def_modifier_multires(brna); rna_def_modifier_surface(brna); rna_def_modifier_smoke(brna); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index c610a2fbdda..7abcb331f08 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -74,6 +74,7 @@ set(SRC intern/MOD_surface.c intern/MOD_util.c intern/MOD_uvproject.c + intern/MOD_warp.c intern/MOD_wave.c MOD_modifiertypes.h diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index 8486e2b5d29..4e44a226c64 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -71,6 +71,7 @@ extern ModifierTypeInfo modifierType_Smoke; extern ModifierTypeInfo modifierType_ShapeKey; extern ModifierTypeInfo modifierType_Solidify; extern ModifierTypeInfo modifierType_Screw; +extern ModifierTypeInfo modifierType_Warp; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 7f887eb162a..3288c1b5da1 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -162,92 +162,6 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } -static void get_texture_coords(DisplaceModifierData *dmd, Object *ob, - DerivedMesh *dm, - float (*co)[3], float (*texco)[3], - int numVerts) -{ - int i; - int texmapping = dmd->texmapping; - float mapob_imat[4][4]; - - if(texmapping == MOD_DISP_MAP_OBJECT) { - if(dmd->map_object) - invert_m4_m4(mapob_imat, dmd->map_object->obmat); - else /* if there is no map object, default to local */ - texmapping = MOD_DISP_MAP_LOCAL; - } - - /* UVs need special handling, since they come from faces */ - if(texmapping == MOD_DISP_MAP_UV) { - if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) { - MFace *mface = dm->getFaceArray(dm); - MFace *mf; - char *done = MEM_callocN(sizeof(*done) * numVerts, - "get_texture_coords done"); - int numFaces = dm->getNumFaces(dm); - char uvname[32]; - MTFace *tf; - - validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname); - tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); - - /* verts are given the UV from the first face that uses them */ - for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) { - if(!done[mf->v1]) { - texco[mf->v1][0] = tf->uv[0][0]; - texco[mf->v1][1] = tf->uv[0][1]; - texco[mf->v1][2] = 0; - done[mf->v1] = 1; - } - if(!done[mf->v2]) { - texco[mf->v2][0] = tf->uv[1][0]; - texco[mf->v2][1] = tf->uv[1][1]; - texco[mf->v2][2] = 0; - done[mf->v2] = 1; - } - if(!done[mf->v3]) { - texco[mf->v3][0] = tf->uv[2][0]; - texco[mf->v3][1] = tf->uv[2][1]; - texco[mf->v3][2] = 0; - done[mf->v3] = 1; - } - if(!done[mf->v4]) { - texco[mf->v4][0] = tf->uv[3][0]; - texco[mf->v4][1] = tf->uv[3][1]; - texco[mf->v4][2] = 0; - done[mf->v4] = 1; - } - } - - /* remap UVs from [0, 1] to [-1, 1] */ - for(i = 0; i < numVerts; ++i) { - texco[i][0] = texco[i][0] * 2 - 1; - texco[i][1] = texco[i][1] * 2 - 1; - } - - MEM_freeN(done); - return; - } else /* if there are no UVs, default to local */ - texmapping = MOD_DISP_MAP_LOCAL; - } - - for(i = 0; i < numVerts; ++i, ++co, ++texco) { - switch(texmapping) { - case MOD_DISP_MAP_LOCAL: - copy_v3_v3(*texco, *co); - break; - case MOD_DISP_MAP_GLOBAL: - mul_v3_m4v3(*texco, ob->obmat, *co); - break; - case MOD_DISP_MAP_OBJECT: - mul_v3_m4v3(*texco, ob->obmat, *co); - mul_m4_v3(mapob_imat, *texco); - break; - } - } -} - /* dm must be a CDDerivedMesh */ static void displaceModifier_do( DisplaceModifierData *dmd, Object *ob, @@ -270,7 +184,7 @@ static void displaceModifier_do( tex_co = MEM_callocN(sizeof(*tex_co) * numVerts, "displaceModifier_do tex_co"); - get_texture_coords(dmd, ob, dm, vertexCos, tex_co, numVerts); + get_texture_coords((MappingInfoModifierData *)dmd, ob, dm, vertexCos, tex_co, numVerts); for(i = 0; i < numVerts; ++i) { TexResult texres; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 8c94e6f65bc..9fe37e2d174 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -40,8 +40,11 @@ #include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_curve_types.h" +#include "DNA_meshdata_types.h" #include "BLI_utildefines.h" +#include "BLI_math_vector.h" +#include "BLI_math_matrix.h" #include "BKE_cdderivedmesh.h" #include "BKE_mesh.h" @@ -74,6 +77,92 @@ void get_texture_value(Tex *texture, float *tex_co, TexResult *texres) texres->tr = texres->tg = texres->tb = texres->tin; } +void get_texture_coords(MappingInfoModifierData *dmd, Object *ob, + DerivedMesh *dm, + float (*co)[3], float (*texco)[3], + int numVerts) +{ + int i; + int texmapping = dmd->texmapping; + float mapob_imat[4][4]; + + if(texmapping == MOD_DISP_MAP_OBJECT) { + if(dmd->map_object) + invert_m4_m4(mapob_imat, dmd->map_object->obmat); + else /* if there is no map object, default to local */ + texmapping = MOD_DISP_MAP_LOCAL; + } + + /* UVs need special handling, since they come from faces */ + if(texmapping == MOD_DISP_MAP_UV) { + if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) { + MFace *mface = dm->getFaceArray(dm); + MFace *mf; + char *done = MEM_callocN(sizeof(*done) * numVerts, + "get_texture_coords done"); + int numFaces = dm->getNumFaces(dm); + char uvname[32]; + MTFace *tf; + + validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname); + tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); + + /* verts are given the UV from the first face that uses them */ + for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) { + if(!done[mf->v1]) { + texco[mf->v1][0] = tf->uv[0][0]; + texco[mf->v1][1] = tf->uv[0][1]; + texco[mf->v1][2] = 0; + done[mf->v1] = 1; + } + if(!done[mf->v2]) { + texco[mf->v2][0] = tf->uv[1][0]; + texco[mf->v2][1] = tf->uv[1][1]; + texco[mf->v2][2] = 0; + done[mf->v2] = 1; + } + if(!done[mf->v3]) { + texco[mf->v3][0] = tf->uv[2][0]; + texco[mf->v3][1] = tf->uv[2][1]; + texco[mf->v3][2] = 0; + done[mf->v3] = 1; + } + if(!done[mf->v4]) { + texco[mf->v4][0] = tf->uv[3][0]; + texco[mf->v4][1] = tf->uv[3][1]; + texco[mf->v4][2] = 0; + done[mf->v4] = 1; + } + } + + /* remap UVs from [0, 1] to [-1, 1] */ + for(i = 0; i < numVerts; ++i) { + texco[i][0] = texco[i][0] * 2 - 1; + texco[i][1] = texco[i][1] * 2 - 1; + } + + MEM_freeN(done); + return; + } else /* if there are no UVs, default to local */ + texmapping = MOD_DISP_MAP_LOCAL; + } + + for(i = 0; i < numVerts; ++i, ++co, ++texco) { + switch(texmapping) { + case MOD_DISP_MAP_LOCAL: + copy_v3_v3(*texco, *co); + break; + case MOD_DISP_MAP_GLOBAL: + mul_v3_m4v3(*texco, ob->obmat, *co); + break; + case MOD_DISP_MAP_OBJECT: + mul_v3_m4v3(*texco, ob->obmat, *co); + mul_m4_v3(mapob_imat, *texco); + break; + } + } +} + void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3]) { while((md=md->next) && md->type==eModifierType_Armature) { @@ -189,5 +278,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(ShapeKey); INIT_TYPE(Solidify); INIT_TYPE(Screw); + INIT_TYPE(Warp); #undef INIT_TYPE } diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h index a42151904e9..b7862403459 100644 --- a/source/blender/modifiers/intern/MOD_util.h +++ b/source/blender/modifiers/intern/MOD_util.h @@ -46,6 +46,7 @@ struct EditMesh; struct ModifierData; void get_texture_value(struct Tex *texture, float *tex_co, struct TexResult *texres); +void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm, float (*co)[3], float (*texco)[3], int numVerts); void modifier_vgroup_cache(struct ModifierData *md, float (*vertexCos)[3]); void validate_layer_name(const struct CustomData *data, int type, char *name, char *outname); struct DerivedMesh *get_cddm(struct Object *ob, struct EditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3]); diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c new file mode 100644 index 00000000000..44eea3f9332 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -0,0 +1,359 @@ +/* +* $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. +* +* Contributor(s): Campbell Barton +* +* ***** END GPL LICENSE BLOCK ***** +* +*/ + +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_modifier.h" +#include "BKE_deform.h" +#include "BKE_texture.h" +#include "BKE_colortools.h" + +#include "DNA_object_types.h" +#include "DNA_meshdata_types.h" + +#include "depsgraph_private.h" + +#include "RE_shader_ext.h" + +#include "MOD_util.h" + + +static void initData(ModifierData *md) +{ + WarpModifierData *wmd = (WarpModifierData*) md; + + wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + wmd->texture = NULL; + wmd->strength = 1.0f; + wmd->falloff_radius = 1.0f; + wmd->falloff_type = eWarp_Falloff_Smooth; + wmd->flag = 0; +} + +static void copyData(ModifierData *md, ModifierData *target) +{ + WarpModifierData *wmd = (WarpModifierData*) md; + WarpModifierData *twmd = (WarpModifierData*) target; + + twmd->object_from = wmd->object_from; + twmd->object_to = wmd->object_to; + + twmd->strength = wmd->strength; + twmd->falloff_radius = wmd->falloff_radius; + twmd->falloff_type = wmd->falloff_type; + strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name)); + twmd->curfalloff = curvemapping_copy(wmd->curfalloff); + + /* map info */ + twmd->texture = wmd->texture; + twmd->map_object = wmd->map_object; + strncpy(twmd->uvlayer_name, wmd->uvlayer_name, sizeof(twmd->uvlayer_name)); + twmd->texmapping= wmd->texmapping; +} + +static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) +{ + WarpModifierData *wmd = (WarpModifierData *)md; + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + if(wmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT); + dataMask |= (1 << CD_MDEFORMVERT); + + /* ask for UV coordinates if we need them */ + if(wmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE); + + return dataMask; +} + +static int dependsOnTime(ModifierData *md) +{ + WarpModifierData *wmd = (WarpModifierData *)md; + + if(wmd->texture) { + return BKE_texture_dependsOnTime(wmd->texture); + } + else { + return 0; + } +} + +static void freeData(ModifierData *md) +{ + WarpModifierData *wmd = (WarpModifierData *) md; + curvemapping_free(wmd->curfalloff); +} + + +static int isDisabled(ModifierData *md, int UNUSED(userRenderParams)) +{ + WarpModifierData *wmd = (WarpModifierData*) md; + + return !(wmd->object_from && wmd->object_to); +} + +static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +{ + WarpModifierData *wmd = (WarpModifierData*) md; + + walk(userData, ob, &wmd->object_from); + walk(userData, ob, &wmd->object_to); + walk(userData, ob, &wmd->map_object); +} + +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + WarpModifierData *wmd = (WarpModifierData*) md; + + walk(userData, ob, (ID **)&wmd->texture); + + walk(userData, ob, (ID **)&wmd->object_from); + walk(userData, ob, (ID **)&wmd->object_to); + walk(userData, ob, (ID **)&wmd->map_object); +} + +static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene), + Object *UNUSED(ob), DagNode *obNode) +{ + WarpModifierData *wmd = (WarpModifierData*) md; + + if(wmd->object_from && wmd->object_to) { + DagNode *fromNode = dag_get_node(forest, wmd->object_from); + DagNode *toNode = dag_get_node(forest, wmd->object_to); + + dag_add_relation(forest, fromNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier1"); + dag_add_relation(forest, toNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier2"); + } + + if((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object) { + DagNode *curNode = dag_get_node(forest, wmd->map_object); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier3"); + } +} + +static void warpModifier_do(WarpModifierData *wmd, Object *ob, + DerivedMesh *dm, float (*vertexCos)[3], int numVerts) +{ + float obinv[4][4]; + float mat_from[4][4]; + float mat_from_inv[4][4]; + float mat_to[4][4]; + float mat_unit[4][4]; + float mat_final[4][4]; + + float tmat[4][4]; + + float strength = wmd->strength; + float fac = 1.0f, weight; + int i; + int defgrp_index = defgroup_name_index(ob, wmd->defgrp_name); + MDeformVert *dv= NULL; + + float (*tex_co)[3]= NULL; + + if(!(wmd->object_from && wmd->object_to)) + return; + + if(wmd->curfalloff==NULL) /* should never happen, but bad lib linking could cause it */ + wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + + invert_m4_m4(obinv, ob->obmat); + + mul_m4_m4m4(mat_from, wmd->object_from->obmat, obinv); + mul_m4_m4m4(mat_to, wmd->object_to->obmat, obinv); + + invert_m4_m4(tmat, mat_from); // swap? + mul_m4_m4m4(mat_final, mat_to, tmat); + + invert_m4_m4(mat_from_inv, mat_from); + + unit_m4(mat_unit); + + if(strength < 0.0f) { + strength = -strength; + invert_m4(mat_final); + } + weight= strength; + + if(wmd->texture) { + tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, "warpModifier_do tex_co"); + get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts); + } + + for(i = 0; i < numVerts; i++) { + float *co = vertexCos[i]; + + if(wmd->falloff_type==eWarp_Falloff_None || + ((fac=len_v3v3(co, mat_from[3])) < wmd->falloff_radius && (fac=(wmd->falloff_radius-fac)/wmd->falloff_radius)) ) { + + /* skip if no vert group found */ + if(defgrp_index >= 0) { + dv = dm->getVertData(dm, i, CD_MDEFORMVERT); + + if(dv) { + weight = defvert_find_weight(dv, defgrp_index) * wmd->strength; + if(weight <= 0.0f) + continue; + } + } + + + /* closely match PROP_SMOOTH and similar */ + switch(wmd->falloff_type) { + case eWarp_Falloff_None: + fac = 1.0f; + break; + case eWarp_Falloff_Curve: + fac = curvemapping_evaluateF(wmd->curfalloff, 0, fac); + break; + case eWarp_Falloff_Sharp: + fac = fac*fac; + break; + case eWarp_Falloff_Smooth: + fac = 3.0f*fac*fac - 2.0f*fac*fac*fac; + break; + case eWarp_Falloff_Root: + fac = (float)sqrt(fac); + break; + case eWarp_Falloff_Linear: + /* pass */ + break; + case eWarp_Falloff_Const: + fac = 1.0f; + break; + case eWarp_Falloff_Sphere: + fac = (float)sqrt(2*fac - fac * fac); + break; + } + + fac *= weight; + + if(tex_co) { + TexResult texres; + texres.nor = NULL; + get_texture_value(wmd->texture, tex_co[i], &texres); + fac *= texres.tin; + } + + /* into the 'from' objects space */ + mul_m4_v3(mat_from_inv, co); + + if(fac >= 1.0f) { + mul_m4_v3(mat_final, co); + } + else if(fac > 0.0f) { + if(wmd->flag & MOD_WARP_VOLUME_PRESERVE) { + /* interpolate the matrix for nicer locations */ + blend_m4_m4m4(tmat, mat_unit, mat_final, fac); + mul_m4_v3(tmat, co); + } + else { + float tvec[3]; + mul_v3_m4v3(tvec, mat_final, co); + interp_v3_v3v3(co, co, tvec, fac); + } + } + + /* out of the 'from' objects space */ + mul_m4_v3(mat_from, co); + } + } + + if(tex_co) + MEM_freeN(tex_co); + +} + +static int warp_needs_dm(WarpModifierData *wmd) +{ + return wmd->texture || wmd->defgrp_name[0]; +} + +static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts, int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) +{ + DerivedMesh *dm= NULL; + int use_dm= warp_needs_dm((WarpModifierData *)md); + + if(use_dm) { + dm= get_cddm(ob, NULL, derivedData, vertexCos); + } + + warpModifier_do((WarpModifierData *)md, ob, dm, vertexCos, numVerts); + + if(use_dm) { + if(dm != derivedData) dm->release(dm); + } +} + +static void deformVertsEM(ModifierData *md, Object *ob, struct EditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = derivedData; + int use_dm= warp_needs_dm((WarpModifierData *)md); + + if(use_dm) { + if(!derivedData) + dm = CDDM_from_editmesh(editData, ob->data); + } + + deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0); + + if(use_dm) { + if(!derivedData) dm->release(dm); + } +} + + +ModifierTypeInfo modifierType_Warp = { + /* name */ "Warp", + /* structName */ "WarpModifierData", + /* structSize */ sizeof(WarpModifierData), + /* type */ eModifierTypeType_OnlyDeform, + /* flags */ eModifierTypeFlag_AcceptsCVs + | eModifierTypeFlag_SupportsEditmode, + /* copyData */ copyData, + /* deformVerts */ deformVerts, + /* deformMatrices */ NULL, + /* deformVertsEM */ deformVertsEM, + /* deformMatricesEM */ NULL, + /* applyModifier */ 0, + /* applyModifierEM */ 0, + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ freeData, + /* isDisabled */ isDisabled, + /* updateDepgraph */ updateDepgraph, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ foreachObjectLink, + /* foreachIDLink */ foreachIDLink, +};