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