diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-05-01 19:16:59 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-05-01 19:16:59 +0400 |
commit | 6b0d932c0d27dbce5e62e2a422e388e02f341a52 (patch) | |
tree | 1a71001adbb6098de00437f346357c66efe8cccf /source/blender/modifiers | |
parent | 5440b57432b43207e42817fe4dcce1716151ef3c (diff) |
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.
Diffstat (limited to 'source/blender/modifiers')
-rw-r--r-- | source/blender/modifiers/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/modifiers/MOD_modifiertypes.h | 1 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_displace.c | 88 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_util.c | 90 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_util.h | 1 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_warp.c | 359 |
6 files changed, 453 insertions, 87 deletions
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 <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, +}; |