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.
This commit is contained in:
Campbell Barton 2011-05-01 15:16:59 +00:00
parent 5440b57432
commit 6b0d932c0d
12 changed files with 679 additions and 125 deletions

@ -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()

@ -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);
}
}
}

@ -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);
}
}
}
}

@ -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

@ -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;

@ -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);

@ -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

@ -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[]);

@ -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;

@ -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
}

@ -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]);

@ -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 <string.h>
#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,
};