Blender V2.61 - r43446

MOD_warp.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software  Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Campbell Barton
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  *
00022  */
00023 
00028 #include <string.h>
00029 
00030 #include "MEM_guardedalloc.h"
00031 
00032 #include "BLI_math.h"
00033 #include "BLI_utildefines.h"
00034 #include "BLI_string.h"
00035 
00036 #include "BKE_cdderivedmesh.h"
00037 #include "BKE_modifier.h"
00038 #include "BKE_deform.h"
00039 #include "BKE_texture.h"
00040 #include "BKE_colortools.h"
00041 
00042 #include "DNA_object_types.h"
00043 #include "DNA_meshdata_types.h"
00044 
00045 #include "depsgraph_private.h"
00046 
00047 #include "RE_shader_ext.h"
00048 
00049 #include "MOD_util.h"
00050 
00051 
00052 static void initData(ModifierData *md)
00053 {
00054     WarpModifierData *wmd = (WarpModifierData*) md;
00055 
00056     wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
00057     wmd->texture = NULL;
00058     wmd->strength = 1.0f;
00059     wmd->falloff_radius = 1.0f;
00060     wmd->falloff_type = eWarp_Falloff_Smooth;
00061     wmd->flag = 0;
00062 }
00063 
00064 static void copyData(ModifierData *md, ModifierData *target)
00065 {
00066     WarpModifierData *wmd = (WarpModifierData*) md;
00067     WarpModifierData *twmd = (WarpModifierData*) target;
00068 
00069     twmd->object_from = wmd->object_from;
00070     twmd->object_to = wmd->object_to;
00071 
00072     twmd->strength = wmd->strength;
00073     twmd->falloff_radius = wmd->falloff_radius;
00074     twmd->falloff_type = wmd->falloff_type;
00075     BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name));
00076     twmd->curfalloff = curvemapping_copy(wmd->curfalloff);
00077 
00078     /* map info */
00079     twmd->texture = wmd->texture;
00080     twmd->map_object = wmd->map_object;
00081     BLI_strncpy(twmd->uvlayer_name, wmd->uvlayer_name, sizeof(twmd->uvlayer_name));
00082     twmd->texmapping= wmd->texmapping;
00083 }
00084 
00085 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
00086 {
00087     WarpModifierData *wmd = (WarpModifierData *)md;
00088     CustomDataMask dataMask = 0;
00089 
00090     /* ask for vertexgroups if we need them */
00091     if(wmd->defgrp_name[0]) dataMask |= (CD_MASK_MDEFORMVERT);
00092     dataMask |= (CD_MASK_MDEFORMVERT);
00093 
00094     /* ask for UV coordinates if we need them */
00095     if(wmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE);
00096 
00097     return dataMask;
00098 }
00099 
00100 static int dependsOnTime(ModifierData *md)
00101 {
00102     WarpModifierData *wmd = (WarpModifierData *)md;
00103 
00104     if(wmd->texture) {
00105         return BKE_texture_dependsOnTime(wmd->texture);
00106     }
00107     else {
00108         return 0;
00109     }
00110 }
00111 
00112 static void freeData(ModifierData *md)
00113 {
00114     WarpModifierData *wmd = (WarpModifierData *) md;
00115     curvemapping_free(wmd->curfalloff);
00116 }
00117 
00118 
00119 static int isDisabled(ModifierData *md, int UNUSED(userRenderParams))
00120 {
00121     WarpModifierData *wmd = (WarpModifierData*) md;
00122 
00123     return !(wmd->object_from && wmd->object_to);
00124 }
00125 
00126 static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
00127 {
00128     WarpModifierData *wmd = (WarpModifierData*) md;
00129 
00130     walk(userData, ob, &wmd->object_from);
00131     walk(userData, ob, &wmd->object_to);
00132     walk(userData, ob, &wmd->map_object);
00133 }
00134 
00135 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
00136 {
00137     WarpModifierData *wmd = (WarpModifierData*) md;
00138 
00139     walk(userData, ob, (ID **)&wmd->texture);
00140 
00141     walk(userData, ob, (ID **)&wmd->object_from);
00142     walk(userData, ob, (ID **)&wmd->object_to);
00143     walk(userData, ob, (ID **)&wmd->map_object);
00144 }
00145 
00146 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
00147 {
00148     walk(userData, ob, md, "texture");
00149 }
00150 
00151 static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
00152                            Object *UNUSED(ob), DagNode *obNode)
00153 {
00154     WarpModifierData *wmd = (WarpModifierData*) md;
00155 
00156     if(wmd->object_from && wmd->object_to) {
00157         DagNode *fromNode = dag_get_node(forest, wmd->object_from);
00158         DagNode *toNode = dag_get_node(forest, wmd->object_to);
00159 
00160         dag_add_relation(forest, fromNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier1");
00161         dag_add_relation(forest, toNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier2");
00162     }
00163 
00164     if((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object) {
00165         DagNode *curNode = dag_get_node(forest, wmd->map_object);
00166         dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier3");
00167     }
00168 }
00169 
00170 static void warpModifier_do(WarpModifierData *wmd, Object *ob,
00171                             DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
00172 {
00173     float obinv[4][4];
00174     float mat_from[4][4];
00175     float mat_from_inv[4][4];
00176     float mat_to[4][4];
00177     float mat_unit[4][4];
00178     float mat_final[4][4];
00179 
00180     float tmat[4][4];
00181 
00182     float strength = wmd->strength;
00183     float fac = 1.0f, weight;
00184     int i;
00185     int defgrp_index;
00186     MDeformVert *dvert, *dv= NULL;
00187 
00188     float (*tex_co)[3]= NULL;
00189 
00190     if(!(wmd->object_from && wmd->object_to))
00191         return;
00192 
00193     modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index);
00194 
00195     if(wmd->curfalloff==NULL) /* should never happen, but bad lib linking could cause it */
00196         wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
00197 
00198     invert_m4_m4(obinv, ob->obmat);
00199 
00200     mult_m4_m4m4(mat_from, obinv, wmd->object_from->obmat);
00201     mult_m4_m4m4(mat_to, obinv, wmd->object_to->obmat);
00202 
00203     invert_m4_m4(tmat, mat_from); // swap?
00204     mult_m4_m4m4(mat_final, tmat, mat_to);
00205 
00206     invert_m4_m4(mat_from_inv, mat_from);
00207 
00208     unit_m4(mat_unit);
00209 
00210     if(strength < 0.0f) {
00211         float loc[3];
00212         strength = -strength;
00213 
00214         /* inverted location is not useful, just use the negative */
00215         copy_v3_v3(loc, mat_final[3]);
00216         invert_m4(mat_final);
00217         negate_v3_v3(mat_final[3], loc);
00218 
00219     }
00220     weight= strength;
00221 
00222     if(wmd->texture) {
00223         tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, "warpModifier_do tex_co");
00224         get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts);
00225     }
00226 
00227     for(i = 0; i < numVerts; i++) {
00228         float *co = vertexCos[i];
00229 
00230         if(wmd->falloff_type==eWarp_Falloff_None ||
00231                 ((fac=len_v3v3(co, mat_from[3])) < wmd->falloff_radius && (fac=(wmd->falloff_radius-fac)/wmd->falloff_radius)) ) {
00232 
00233             /* skip if no vert group found */
00234             if(dvert && defgrp_index >= 0) {
00235                 dv = &dvert[i];
00236 
00237                 if(dv) {
00238                     weight = defvert_find_weight(dv, defgrp_index) * strength;
00239                     if(weight <= 0.0f) /* Should never occure... */
00240                         continue;
00241                 }
00242             }
00243 
00244 
00245             /* closely match PROP_SMOOTH and similar */
00246             switch(wmd->falloff_type) {
00247             case eWarp_Falloff_None:
00248                 fac = 1.0f;
00249                 break;
00250             case eWarp_Falloff_Curve:
00251                 fac = curvemapping_evaluateF(wmd->curfalloff, 0, fac);
00252                 break;
00253             case eWarp_Falloff_Sharp:
00254                 fac = fac*fac;
00255                 break;
00256             case eWarp_Falloff_Smooth:
00257                 fac = 3.0f*fac*fac - 2.0f*fac*fac*fac;
00258                 break;
00259             case eWarp_Falloff_Root:
00260                 fac = (float)sqrt(fac);
00261                 break;
00262             case eWarp_Falloff_Linear:
00263                 /* pass */
00264                 break;
00265             case eWarp_Falloff_Const:
00266                 fac = 1.0f;
00267                 break;
00268             case eWarp_Falloff_Sphere:
00269                 fac = (float)sqrt(2*fac - fac * fac);
00270                 break;
00271             }
00272 
00273             fac *= weight;
00274 
00275             if(tex_co) {
00276                 TexResult texres;
00277                 texres.nor = NULL;
00278                 get_texture_value(wmd->texture, tex_co[i], &texres);
00279                 fac *= texres.tin;
00280             }
00281 
00282             /* into the 'from' objects space */
00283             mul_m4_v3(mat_from_inv, co);
00284 
00285             if(fac >= 1.0f) {
00286                 mul_m4_v3(mat_final, co);
00287             }
00288             else if(fac > 0.0f) {
00289                 if(wmd->flag & MOD_WARP_VOLUME_PRESERVE) {
00290                     /* interpolate the matrix for nicer locations */
00291                     blend_m4_m4m4(tmat, mat_unit, mat_final, fac);
00292                     mul_m4_v3(tmat, co);
00293                 }
00294                 else {
00295                     float tvec[3];
00296                     mul_v3_m4v3(tvec, mat_final, co);
00297                     interp_v3_v3v3(co, co, tvec, fac);
00298                 }
00299             }
00300 
00301             /* out of the 'from' objects space */
00302             mul_m4_v3(mat_from, co);
00303         }
00304     }
00305 
00306     if(tex_co)
00307         MEM_freeN(tex_co);
00308 
00309 }
00310 
00311 static int warp_needs_dm(WarpModifierData *wmd)
00312 {
00313     return wmd->texture || wmd->defgrp_name[0];
00314 }
00315 
00316 static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
00317                         float (*vertexCos)[3], int numVerts, int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
00318 {
00319     DerivedMesh *dm= NULL;
00320     int use_dm= warp_needs_dm((WarpModifierData *)md);
00321 
00322     if(use_dm) {
00323         dm= get_cddm(ob, NULL, derivedData, vertexCos);
00324     }
00325 
00326     warpModifier_do((WarpModifierData *)md, ob, dm, vertexCos, numVerts);
00327 
00328     if(use_dm) {
00329         if(dm != derivedData) dm->release(dm);
00330     }
00331 }
00332 
00333 static void deformVertsEM(ModifierData *md, Object *ob, struct EditMesh *editData,
00334                           DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
00335 {
00336     DerivedMesh *dm = derivedData;
00337     int use_dm= warp_needs_dm((WarpModifierData *)md);
00338 
00339     if(use_dm) {
00340         if(!derivedData)
00341             dm = CDDM_from_editmesh(editData, ob->data);
00342     }
00343 
00344     deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
00345 
00346     if(use_dm) {
00347         if(!derivedData) dm->release(dm);
00348     }
00349 }
00350 
00351 
00352 ModifierTypeInfo modifierType_Warp = {
00353     /* name */              "Warp",
00354     /* structName */        "WarpModifierData",
00355     /* structSize */        sizeof(WarpModifierData),
00356     /* type */              eModifierTypeType_OnlyDeform,
00357     /* flags */             eModifierTypeFlag_AcceptsCVs
00358                             | eModifierTypeFlag_SupportsEditmode,
00359     /* copyData */          copyData,
00360     /* deformVerts */       deformVerts,
00361     /* deformMatrices */    NULL,
00362     /* deformVertsEM */     deformVertsEM,
00363     /* deformMatricesEM */  NULL,
00364     /* applyModifier */     0,
00365     /* applyModifierEM */   0,
00366     /* initData */          initData,
00367     /* requiredDataMask */  requiredDataMask,
00368     /* freeData */          freeData,
00369     /* isDisabled */        isDisabled,
00370     /* updateDepgraph */    updateDepgraph,
00371     /* dependsOnTime */     dependsOnTime,
00372     /* dependsOnNormals */  NULL,
00373     /* foreachObjectLink */ foreachObjectLink,
00374     /* foreachIDLink */     foreachIDLink,
00375     /* foreachTexLink */    foreachTexLink,
00376 };