Blender V2.61 - r43446

MOD_wave.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  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Daniel Dunbar
00022  *                 Ton Roosendaal,
00023  *                 Ben Batt,
00024  *                 Brecht Van Lommel,
00025  *                 Campbell Barton
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  *
00029  */
00030 
00036 #include "BLI_math.h"
00037 
00038 #include "DNA_meshdata_types.h"
00039 #include "DNA_scene_types.h"
00040 #include "DNA_object_types.h"
00041 
00042 #include "BLI_utildefines.h"
00043 #include "BLI_string.h"
00044 
00045 
00046 #include "BKE_DerivedMesh.h"
00047 #include "BKE_object.h"
00048 #include "BKE_deform.h"
00049 #include "BKE_scene.h"
00050 
00051 #include "depsgraph_private.h"
00052 
00053 #include "MEM_guardedalloc.h"
00054 #include "RE_shader_ext.h"
00055 
00056 #include "MOD_modifiertypes.h"
00057 #include "MOD_util.h"
00058 
00059 static void initData(ModifierData *md)
00060 {
00061     WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
00062 
00063     wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
00064             | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
00065 
00066     wmd->objectcenter = NULL;
00067     wmd->texture = NULL;
00068     wmd->map_object = NULL;
00069     wmd->height= 0.5f;
00070     wmd->width= 1.5f;
00071     wmd->speed= 0.25f;
00072     wmd->narrow= 1.5f;
00073     wmd->lifetime= 0.0f;
00074     wmd->damp= 10.0f;
00075     wmd->falloff= 0.0f;
00076     wmd->texmapping = MOD_DISP_MAP_LOCAL;
00077     wmd->defgrp_name[0] = 0;
00078 }
00079 
00080 static void copyData(ModifierData *md, ModifierData *target)
00081 {
00082     WaveModifierData *wmd = (WaveModifierData*) md;
00083     WaveModifierData *twmd = (WaveModifierData*) target;
00084 
00085     twmd->damp = wmd->damp;
00086     twmd->flag = wmd->flag;
00087     twmd->height = wmd->height;
00088     twmd->lifetime = wmd->lifetime;
00089     twmd->narrow = wmd->narrow;
00090     twmd->speed = wmd->speed;
00091     twmd->startx = wmd->startx;
00092     twmd->starty = wmd->starty;
00093     twmd->timeoffs = wmd->timeoffs;
00094     twmd->width = wmd->width;
00095     twmd->falloff = wmd->falloff;
00096     twmd->objectcenter = wmd->objectcenter;
00097     twmd->texture = wmd->texture;
00098     twmd->map_object = wmd->map_object;
00099     twmd->texmapping = wmd->texmapping;
00100     BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name));
00101 }
00102 
00103 static int dependsOnTime(ModifierData *UNUSED(md))
00104 {
00105     return 1;
00106 }
00107 
00108 static void foreachObjectLink(
00109                        ModifierData *md, Object *ob,
00110     ObjectWalkFunc walk, void *userData)
00111 {
00112     WaveModifierData *wmd = (WaveModifierData*) md;
00113 
00114     walk(userData, ob, &wmd->objectcenter);
00115     walk(userData, ob, &wmd->map_object);
00116 }
00117 
00118 static void foreachIDLink(ModifierData *md, Object *ob,
00119                        IDWalkFunc walk, void *userData)
00120 {
00121     WaveModifierData *wmd = (WaveModifierData*) md;
00122 
00123     walk(userData, ob, (ID **)&wmd->texture);
00124 
00125     foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
00126 }
00127 
00128 static void foreachTexLink(ModifierData *md, Object *ob,
00129                        TexWalkFunc walk, void *userData)
00130 {
00131     walk(userData, ob, md, "texture");
00132 }
00133 
00134 static void updateDepgraph(ModifierData *md, DagForest *forest,
00135                         Scene *UNUSED(scene),
00136                         Object *UNUSED(ob),
00137                         DagNode *obNode)
00138 {
00139     WaveModifierData *wmd = (WaveModifierData*) md;
00140 
00141     if(wmd->objectcenter) {
00142         DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
00143 
00144         dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
00145             "Wave Modifier");
00146     }
00147 
00148     if(wmd->map_object) {
00149         DagNode *curNode = dag_get_node(forest, wmd->map_object);
00150 
00151         dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
00152             "Wave Modifer");
00153     }
00154 }
00155 
00156 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
00157 {
00158     WaveModifierData *wmd = (WaveModifierData *)md;
00159     CustomDataMask dataMask = 0;
00160 
00161 
00162     /* ask for UV coordinates if we need them */
00163     if(wmd->texture && wmd->texmapping == MOD_DISP_MAP_UV)
00164         dataMask |= CD_MASK_MTFACE;
00165 
00166     /* ask for vertexgroups if we need them */
00167     if(wmd->defgrp_name[0])
00168         dataMask |= CD_MASK_MDEFORMVERT;
00169 
00170     return dataMask;
00171 }
00172 
00173 static void waveModifier_do(WaveModifierData *md, 
00174         Scene *scene, Object *ob, DerivedMesh *dm,
00175        float (*vertexCos)[3], int numVerts)
00176 {
00177     WaveModifierData *wmd = (WaveModifierData*) md;
00178     MVert *mvert = NULL;
00179     MDeformVert *dvert;
00180     int defgrp_index;
00181     float ctime = BKE_curframe(scene);
00182     float minfac =
00183             (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
00184     float lifefac = wmd->height;
00185     float (*tex_co)[3] = NULL;
00186     const int wmd_axis= wmd->flag & (MOD_WAVE_X|MOD_WAVE_Y);
00187     const float falloff= wmd->falloff;
00188     float falloff_fac= 1.0f; /* when falloff == 0.0f this stays at 1.0f */
00189 
00190     if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH)
00191         mvert = dm->getVertArray(dm);
00192 
00193     if(wmd->objectcenter){
00194         float mat[4][4];
00195         /* get the control object's location in local coordinates */
00196         invert_m4_m4(ob->imat, ob->obmat);
00197         mult_m4_m4m4(mat, ob->imat, wmd->objectcenter->obmat);
00198 
00199         wmd->startx = mat[3][0];
00200         wmd->starty = mat[3][1];
00201     }
00202 
00203     /* get the index of the deform group */
00204     modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index);
00205 
00206     if(wmd->damp == 0) wmd->damp = 10.0f;
00207 
00208     if(wmd->lifetime != 0.0f) {
00209         float x = ctime - wmd->timeoffs;
00210 
00211         if(x > wmd->lifetime) {
00212             lifefac = x - wmd->lifetime;
00213 
00214             if(lifefac > wmd->damp) lifefac = 0.0;
00215             else lifefac =
00216                 (float)(wmd->height * (1.0f - sqrtf(lifefac / wmd->damp)));
00217         }
00218     }
00219 
00220     if(wmd->texture) {
00221         tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
00222                      "waveModifier_do tex_co");
00223         get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts);
00224     }
00225 
00226     if(lifefac != 0.0f) {
00227         /* avoid divide by zero checks within the loop */
00228         float falloff_inv= falloff ? 1.0f / falloff : 1.0f;
00229         int i;
00230 
00231         for(i = 0; i < numVerts; i++) {
00232             float *co = vertexCos[i];
00233             float x = co[0] - wmd->startx;
00234             float y = co[1] - wmd->starty;
00235             float amplit= 0.0f;
00236             float def_weight= 1.0f;
00237 
00238             /* get weights */
00239             if(dvert) {
00240                 def_weight= defvert_find_weight(&dvert[i], defgrp_index);
00241 
00242                 /* if this vert isn't in the vgroup, don't deform it */
00243                 if(def_weight == 0.0f) {
00244                     continue;
00245                 }
00246             }
00247 
00248             switch(wmd_axis) {
00249             case MOD_WAVE_X|MOD_WAVE_Y:
00250                 amplit = sqrtf(x*x + y*y);
00251                 break;
00252             case MOD_WAVE_X:
00253                 amplit = x;
00254                 break;
00255             case MOD_WAVE_Y:
00256                 amplit = y;
00257                 break;
00258             }
00259 
00260             /* this way it makes nice circles */
00261             amplit -= (ctime - wmd->timeoffs) * wmd->speed;
00262 
00263             if(wmd->flag & MOD_WAVE_CYCL) {
00264                 amplit = (float)fmodf(amplit - wmd->width, 2.0f * wmd->width)
00265                         + wmd->width;
00266             }
00267 
00268             if(falloff != 0.0f) {
00269                 float dist = 0.0f;
00270 
00271                 switch(wmd_axis) {
00272                 case MOD_WAVE_X|MOD_WAVE_Y:
00273                     dist = sqrtf(x*x + y*y);
00274                     break;
00275                 case MOD_WAVE_X:
00276                     dist = fabsf(x);
00277                     break;
00278                 case MOD_WAVE_Y:
00279                     dist = fabsf(y);
00280                     break;
00281                 }
00282 
00283                 falloff_fac = (1.0f - (dist * falloff_inv));
00284                 CLAMP(falloff_fac, 0.0f, 1.0f);
00285             }
00286 
00287             /* GAUSSIAN */
00288             if((falloff_fac != 0.0f) && (amplit > -wmd->width) && (amplit < wmd->width)) {
00289                 amplit = amplit * wmd->narrow;
00290                 amplit = (float)(1.0f / expf(amplit * amplit) - minfac);
00291 
00292                 /*apply texture*/
00293                 if(wmd->texture) {
00294                     TexResult texres;
00295                     texres.nor = NULL;
00296                     get_texture_value(wmd->texture, tex_co[i], &texres);
00297                     amplit *= texres.tin;
00298                 }
00299 
00300                 /*apply weight & falloff */
00301                 amplit *= def_weight * falloff_fac;
00302 
00303                 if(mvert) {
00304                     /* move along normals */
00305                     if(wmd->flag & MOD_WAVE_NORM_X) {
00306                         co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
00307                     }
00308                     if(wmd->flag & MOD_WAVE_NORM_Y) {
00309                         co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
00310                     }
00311                     if(wmd->flag & MOD_WAVE_NORM_Z) {
00312                         co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
00313                     }
00314                 }
00315                 else {
00316                     /* move along local z axis */
00317                     co[2] += lifefac * amplit;
00318                 }
00319             }
00320         }
00321     }
00322 
00323     if(wmd->texture) MEM_freeN(tex_co);
00324 }
00325 
00326 static void deformVerts(ModifierData *md, Object *ob,
00327                         DerivedMesh *derivedData,
00328                         float (*vertexCos)[3],
00329                         int numVerts,
00330                         int UNUSED(useRenderParams),
00331                         int UNUSED(isFinalCalc))
00332 {
00333     DerivedMesh *dm= derivedData;
00334     WaveModifierData *wmd = (WaveModifierData *)md;
00335 
00336     if(wmd->flag & MOD_WAVE_NORM)
00337         dm= get_cddm(ob, NULL, dm, vertexCos);
00338     else if(wmd->texture || wmd->defgrp_name[0])
00339         dm= get_dm(ob, NULL, dm, NULL, 0);
00340 
00341     waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
00342 
00343     if(dm != derivedData)
00344         dm->release(dm);
00345 }
00346 
00347 static void deformVertsEM(
00348                        ModifierData *md, Object *ob, struct EditMesh *editData,
00349        DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
00350 {
00351     DerivedMesh *dm= derivedData;
00352     WaveModifierData *wmd = (WaveModifierData *)md;
00353 
00354     if(wmd->flag & MOD_WAVE_NORM)
00355         dm= get_cddm(ob, editData, dm, vertexCos);
00356     else if(wmd->texture || wmd->defgrp_name[0])
00357         dm= get_dm(ob, editData, dm, NULL, 0);
00358 
00359     waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
00360 
00361     if(dm != derivedData)
00362         dm->release(dm);
00363 }
00364 
00365 
00366 ModifierTypeInfo modifierType_Wave = {
00367     /* name */              "Wave",
00368     /* structName */        "WaveModifierData",
00369     /* structSize */        sizeof(WaveModifierData),
00370     /* type */              eModifierTypeType_OnlyDeform,
00371     /* flags */             eModifierTypeFlag_AcceptsCVs
00372                             | eModifierTypeFlag_SupportsEditmode,
00373     /* copyData */          copyData,
00374     /* deformVerts */       deformVerts,
00375     /* deformMatrices */    NULL,
00376     /* deformVertsEM */     deformVertsEM,
00377     /* deformMatricesEM */  NULL,
00378     /* applyModifier */     NULL,
00379     /* applyModifierEM */   NULL,
00380     /* initData */          initData,
00381     /* requiredDataMask */  requiredDataMask,
00382     /* freeData */          NULL,
00383     /* isDisabled */        NULL,
00384     /* updateDepgraph */    updateDepgraph,
00385     /* dependsOnTime */     dependsOnTime,
00386     /* dependsOnNormals */  NULL,
00387     /* foreachObjectLink */ foreachObjectLink,
00388     /* foreachIDLink */     foreachIDLink,
00389     /* foreachTexLink */    foreachTexLink,
00390 };