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