2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Daniel Dunbar
27 * ***** END GPL LICENSE BLOCK *****
31 /** \file blender/modifiers/intern/MOD_wave.c
38 #include "DNA_mesh_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_scene_types.h"
43 #include "BLI_utildefines.h"
46 #include "BKE_deform.h"
47 #include "BKE_editmesh.h"
48 #include "BKE_library.h"
49 #include "BKE_library_query.h"
51 #include "BKE_scene.h"
52 #include "BKE_texture.h"
54 #include "MEM_guardedalloc.h"
55 #include "RE_shader_ext.h"
57 #include "MOD_modifiertypes.h"
60 #include "DEG_depsgraph.h"
61 #include "DEG_depsgraph_query.h"
63 static void initData(ModifierData *md)
65 WaveModifierData *wmd = (WaveModifierData *) md; // whadya know, moved here from Iraq
67 wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL |
68 MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
70 wmd->objectcenter = NULL;
72 wmd->map_object = NULL;
80 wmd->texmapping = MOD_DISP_MAP_LOCAL;
81 wmd->defgrp_name[0] = 0;
84 static bool dependsOnTime(ModifierData *UNUSED(md))
89 static void foreachObjectLink(
90 ModifierData *md, Object *ob,
91 ObjectWalkFunc walk, void *userData)
93 WaveModifierData *wmd = (WaveModifierData *) md;
95 walk(userData, ob, &wmd->objectcenter, IDWALK_CB_NOP);
96 walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP);
99 static void foreachIDLink(
100 ModifierData *md, Object *ob,
101 IDWalkFunc walk, void *userData)
103 WaveModifierData *wmd = (WaveModifierData *) md;
105 walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER);
107 foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
110 static void foreachTexLink(
111 ModifierData *md, Object *ob,
112 TexWalkFunc walk, void *userData)
114 walk(userData, ob, md, "texture");
117 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
119 WaveModifierData *wmd = (WaveModifierData *)md;
120 if (wmd->objectcenter != NULL) {
121 DEG_add_object_relation(ctx->node, wmd->objectcenter, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
123 if (wmd->map_object != NULL) {
124 DEG_add_object_relation(ctx->node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
126 if (wmd->objectcenter != NULL || wmd->map_object != NULL) {
127 DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Wave Modifier");
129 if (wmd->texture != NULL) {
130 DEG_add_generic_id_relation(ctx->node, &wmd->texture->id, "Wave Modifier");
134 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
136 WaveModifierData *wmd = (WaveModifierData *)md;
137 CustomDataMask dataMask = 0;
140 /* ask for UV coordinates if we need them */
141 if (wmd->texture && wmd->texmapping == MOD_DISP_MAP_UV)
142 dataMask |= CD_MASK_MTFACE;
144 /* ask for vertexgroups if we need them */
145 if (wmd->defgrp_name[0])
146 dataMask |= CD_MASK_MDEFORMVERT;
151 static bool dependsOnNormals(ModifierData *md)
153 WaveModifierData *wmd = (WaveModifierData *)md;
155 return (wmd->flag & MOD_WAVE_NORM) != 0;
158 static void waveModifier_do(
159 WaveModifierData *md,
160 Depsgraph *depsgraph,
161 Object *ob, Mesh *mesh,
162 float (*vertexCos)[3], int numVerts)
164 WaveModifierData *wmd = (WaveModifierData *) md;
168 float ctime = DEG_get_ctime(depsgraph);
169 float minfac = (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
170 float lifefac = wmd->height;
171 float (*tex_co)[3] = NULL;
172 const int wmd_axis = wmd->flag & (MOD_WAVE_X | MOD_WAVE_Y);
173 const float falloff = wmd->falloff;
174 float falloff_fac = 1.0f; /* when falloff == 0.0f this stays at 1.0f */
176 if ((wmd->flag & MOD_WAVE_NORM) && (mesh != NULL)) {
180 if (wmd->objectcenter) {
182 /* get the control object's location in local coordinates */
183 invert_m4_m4(ob->imat, ob->obmat);
184 mul_m4_m4m4(mat, ob->imat, wmd->objectcenter->obmat);
186 wmd->startx = mat[3][0];
187 wmd->starty = mat[3][1];
190 /* get the index of the deform group */
191 MOD_get_vgroup(ob, mesh, wmd->defgrp_name, &dvert, &defgrp_index);
193 if (wmd->damp == 0.0f) {
197 if (wmd->lifetime != 0.0f) {
198 float x = ctime - wmd->timeoffs;
200 if (x > wmd->lifetime) {
201 lifefac = x - wmd->lifetime;
203 if (lifefac > wmd->damp) lifefac = 0.0;
204 else lifefac = (float)(wmd->height * (1.0f - sqrtf(lifefac / wmd->damp)));
208 if (mesh != NULL && wmd->texture) {
209 tex_co = MEM_malloc_arrayN(numVerts, sizeof(*tex_co), "waveModifier_do tex_co");
210 MOD_get_texture_coords((MappingInfoModifierData *)wmd, ob, mesh, vertexCos, tex_co);
212 MOD_init_texture(depsgraph, wmd->texture);
215 if (lifefac != 0.0f) {
216 /* avoid divide by zero checks within the loop */
217 float falloff_inv = falloff != 0.0f ? 1.0f / falloff : 1.0f;
220 for (i = 0; i < numVerts; i++) {
221 float *co = vertexCos[i];
222 float x = co[0] - wmd->startx;
223 float y = co[1] - wmd->starty;
225 float def_weight = 1.0f;
229 def_weight = defvert_find_weight(&dvert[i], defgrp_index);
231 /* if this vert isn't in the vgroup, don't deform it */
232 if (def_weight == 0.0f) {
238 case MOD_WAVE_X | MOD_WAVE_Y:
239 amplit = sqrtf(x * x + y * y);
249 /* this way it makes nice circles */
250 amplit -= (ctime - wmd->timeoffs) * wmd->speed;
252 if (wmd->flag & MOD_WAVE_CYCL) {
253 amplit = (float)fmodf(amplit - wmd->width, 2.0f * wmd->width) +
257 if (falloff != 0.0f) {
261 case MOD_WAVE_X | MOD_WAVE_Y:
262 dist = sqrtf(x * x + y * y);
272 falloff_fac = (1.0f - (dist * falloff_inv));
273 CLAMP(falloff_fac, 0.0f, 1.0f);
277 if ((falloff_fac != 0.0f) && (amplit > -wmd->width) && (amplit < wmd->width)) {
278 amplit = amplit * wmd->narrow;
279 amplit = (float)(1.0f / expf(amplit * amplit) - minfac);
283 Scene *scene = DEG_get_evaluated_scene(depsgraph);
286 BKE_texture_get_value(scene, wmd->texture, tex_co[i], &texres, false);
287 amplit *= texres.tin;
290 /*apply weight & falloff */
291 amplit *= def_weight * falloff_fac;
294 /* move along normals */
295 if (wmd->flag & MOD_WAVE_NORM_X) {
296 co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
298 if (wmd->flag & MOD_WAVE_NORM_Y) {
299 co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
301 if (wmd->flag & MOD_WAVE_NORM_Z) {
302 co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
306 /* move along local z axis */
307 co[2] += lifefac * amplit;
313 MEM_SAFE_FREE(tex_co);
316 static void deformVerts(
317 ModifierData *md, const ModifierEvalContext *ctx,
319 float (*vertexCos)[3],
322 WaveModifierData *wmd = (WaveModifierData *)md;
323 Mesh *mesh_src = NULL;
325 if (wmd->flag & MOD_WAVE_NORM) {
326 mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, vertexCos, numVerts, true, false);
328 else if (wmd->texture != NULL || wmd->defgrp_name[0] != '\0') {
329 mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
332 waveModifier_do(wmd, ctx->depsgraph, ctx->object, mesh_src, vertexCos, numVerts);
334 if (!ELEM(mesh_src, NULL, mesh)) {
335 BKE_id_free(NULL, mesh_src);
339 static void deformVertsEM(
340 ModifierData *md, const ModifierEvalContext *ctx,
341 struct BMEditMesh *editData,
342 Mesh *mesh, float (*vertexCos)[3], int numVerts)
344 WaveModifierData *wmd = (WaveModifierData *)md;
345 Mesh *mesh_src = NULL;
347 if (wmd->flag & MOD_WAVE_NORM) {
348 mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, vertexCos, numVerts, true, false);
350 else if (wmd->texture != NULL || wmd->defgrp_name[0] != '\0') {
351 mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
354 waveModifier_do(wmd, ctx->depsgraph, ctx->object, mesh_src, vertexCos, numVerts);
356 if (!ELEM(mesh_src, NULL, mesh)) {
357 BKE_id_free(NULL, mesh_src);
362 ModifierTypeInfo modifierType_Wave = {
364 /* structName */ "WaveModifierData",
365 /* structSize */ sizeof(WaveModifierData),
366 /* type */ eModifierTypeType_OnlyDeform,
367 /* flags */ eModifierTypeFlag_AcceptsCVs |
368 eModifierTypeFlag_AcceptsLattice |
369 eModifierTypeFlag_SupportsEditmode,
371 /* copyData */ modifier_copyData_generic,
373 /* deformVerts_DM */ NULL,
374 /* deformMatrices_DM */ NULL,
375 /* deformVertsEM_DM */ NULL,
376 /* deformMatricesEM_DM*/NULL,
377 /* applyModifier_DM */ NULL,
379 /* deformVerts */ deformVerts,
380 /* deformMatrices */ NULL,
381 /* deformVertsEM */ deformVertsEM,
382 /* deformMatricesEM */ NULL,
383 /* applyModifier */ NULL,
385 /* initData */ initData,
386 /* requiredDataMask */ requiredDataMask,
388 /* isDisabled */ NULL,
389 /* updateDepsgraph */ updateDepsgraph,
390 /* dependsOnTime */ dependsOnTime,
391 /* dependsOnNormals */ dependsOnNormals,
392 /* foreachObjectLink */ foreachObjectLink,
393 /* foreachIDLink */ foreachIDLink,
394 /* foreachTexLink */ foreachTexLink,