=bmesh= merge from trunk at r36529
[blender.git] / source / blender / modifiers / intern / MOD_wave.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
22 *
23 * Contributor(s): Daniel Dunbar
24 *                 Ton Roosendaal,
25 *                 Ben Batt,
26 *                 Brecht Van Lommel,
27 *                 Campbell Barton
28 *
29 * ***** END GPL LICENSE BLOCK *****
30 *
31 */
32
33 /** \file blender/modifiers/intern/MOD_wave.c
34  *  \ingroup modifiers
35  */
36
37
38 #include "BLI_math.h"
39
40 #include "DNA_meshdata_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_object_types.h"
43
44 #include "BLI_utildefines.h"
45
46
47 #include "BKE_DerivedMesh.h"
48 #include "BKE_object.h"
49 #include "BKE_deform.h"
50 #include "BKE_scene.h"
51
52 #include "depsgraph_private.h"
53
54 #include "MEM_guardedalloc.h"
55 #include "RE_shader_ext.h"
56
57 #include "MOD_modifiertypes.h"
58 #include "MOD_util.h"
59
60 static void initData(ModifierData *md)
61 {
62         WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
63
64         wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
65                         | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
66
67         wmd->objectcenter = NULL;
68         wmd->texture = NULL;
69         wmd->map_object = NULL;
70         wmd->height= 0.5f;
71         wmd->width= 1.5f;
72         wmd->speed= 0.25f;
73         wmd->narrow= 1.5f;
74         wmd->lifetime= 0.0f;
75         wmd->damp= 10.0f;
76         wmd->falloff= 0.0f;
77         wmd->texmapping = MOD_WAV_MAP_LOCAL;
78         wmd->defgrp_name[0] = 0;
79 }
80
81 static void copyData(ModifierData *md, ModifierData *target)
82 {
83         WaveModifierData *wmd = (WaveModifierData*) md;
84         WaveModifierData *twmd = (WaveModifierData*) target;
85
86         twmd->damp = wmd->damp;
87         twmd->flag = wmd->flag;
88         twmd->height = wmd->height;
89         twmd->lifetime = wmd->lifetime;
90         twmd->narrow = wmd->narrow;
91         twmd->speed = wmd->speed;
92         twmd->startx = wmd->startx;
93         twmd->starty = wmd->starty;
94         twmd->timeoffs = wmd->timeoffs;
95         twmd->width = wmd->width;
96         twmd->falloff = wmd->falloff;
97         twmd->objectcenter = wmd->objectcenter;
98         twmd->texture = wmd->texture;
99         twmd->map_object = wmd->map_object;
100         twmd->texmapping = wmd->texmapping;
101         strncpy(twmd->defgrp_name, wmd->defgrp_name, 32);
102 }
103
104 static int dependsOnTime(ModifierData *UNUSED(md))
105 {
106         return 1;
107 }
108
109 static void foreachObjectLink(
110                                            ModifierData *md, Object *ob,
111         ObjectWalkFunc walk, void *userData)
112 {
113         WaveModifierData *wmd = (WaveModifierData*) md;
114
115         walk(userData, ob, &wmd->objectcenter);
116         walk(userData, ob, &wmd->map_object);
117 }
118
119 static void foreachIDLink(ModifierData *md, Object *ob,
120                                            IDWalkFunc walk, void *userData)
121 {
122         WaveModifierData *wmd = (WaveModifierData*) md;
123
124         walk(userData, ob, (ID **)&wmd->texture);
125
126         foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
127 }
128
129 static void updateDepgraph(ModifierData *md, DagForest *forest,
130                                                 Scene *UNUSED(scene),
131                                                 Object *UNUSED(ob),
132                                                 DagNode *obNode)
133 {
134         WaveModifierData *wmd = (WaveModifierData*) md;
135
136         if(wmd->objectcenter) {
137                 DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
138
139                 dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
140                         "Wave Modifier");
141         }
142
143         if(wmd->map_object) {
144                 DagNode *curNode = dag_get_node(forest, wmd->map_object);
145
146                 dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
147                         "Wave Modifer");
148         }
149 }
150
151 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
152 {
153         WaveModifierData *wmd = (WaveModifierData *)md;
154         CustomDataMask dataMask = 0;
155
156
157         /* ask for UV coordinates if we need them */
158         if(wmd->texture && wmd->texmapping == MOD_WAV_MAP_UV)
159                 dataMask |= CD_MASK_MTFACE;
160
161         /* ask for vertexgroups if we need them */
162         if(wmd->defgrp_name[0])
163                 dataMask |= CD_MASK_MDEFORMVERT;
164
165         return dataMask;
166 }
167
168 static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
169                                            DerivedMesh *dm,
170            float (*co)[3], float (*texco)[3],
171                    int numVerts)
172 {
173         int i;
174         int texmapping = wmd->texmapping;
175
176         if(texmapping == MOD_WAV_MAP_OBJECT) {
177                 if(wmd->map_object)
178                         invert_m4_m4(wmd->map_object->imat, wmd->map_object->obmat);
179                 else /* if there is no map object, default to local */
180                         texmapping = MOD_WAV_MAP_LOCAL;
181         }
182
183         /* UVs need special handling, since they come from faces */
184         if(texmapping == MOD_WAV_MAP_UV) {
185                 if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
186                         MFace *mface = dm->getTessFaceArray(dm);
187                         MFace *mf;
188                         char *done = MEM_callocN(sizeof(*done) * numVerts,
189                                         "get_texture_coords done");
190                         int numFaces = dm->getNumTessFaces(dm);
191                         char uvname[32];
192                         MTFace *tf;
193
194                         validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name, uvname);
195                         tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
196
197                         /* verts are given the UV from the first face that uses them */
198                         for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
199                                 if(!done[mf->v1]) {
200                                         texco[mf->v1][0] = tf->uv[0][0];
201                                         texco[mf->v1][1] = tf->uv[0][1];
202                                         texco[mf->v1][2] = 0;
203                                         done[mf->v1] = 1;
204                                 }
205                                 if(!done[mf->v2]) {
206                                         texco[mf->v2][0] = tf->uv[1][0];
207                                         texco[mf->v2][1] = tf->uv[1][1];
208                                         texco[mf->v2][2] = 0;
209                                         done[mf->v2] = 1;
210                                 }
211                                 if(!done[mf->v3]) {
212                                         texco[mf->v3][0] = tf->uv[2][0];
213                                         texco[mf->v3][1] = tf->uv[2][1];
214                                         texco[mf->v3][2] = 0;
215                                         done[mf->v3] = 1;
216                                 }
217                                 if(!done[mf->v4]) {
218                                         texco[mf->v4][0] = tf->uv[3][0];
219                                         texco[mf->v4][1] = tf->uv[3][1];
220                                         texco[mf->v4][2] = 0;
221                                         done[mf->v4] = 1;
222                                 }
223                         }
224
225                         /* remap UVs from [0, 1] to [-1, 1] */
226                         for(i = 0; i < numVerts; ++i) {
227                                 texco[i][0] = texco[i][0] * 2 - 1;
228                                 texco[i][1] = texco[i][1] * 2 - 1;
229                         }
230
231                         MEM_freeN(done);
232                         return;
233                 } else /* if there are no UVs, default to local */
234                         texmapping = MOD_WAV_MAP_LOCAL;
235         }
236
237         for(i = 0; i < numVerts; ++i, ++co, ++texco) {
238                 switch(texmapping) {
239                         case MOD_WAV_MAP_LOCAL:
240                                 copy_v3_v3(*texco, *co);
241                                 break;
242                         case MOD_WAV_MAP_GLOBAL:
243                                 mul_v3_m4v3(*texco, ob->obmat, *co);
244                                 break;
245                         case MOD_WAV_MAP_OBJECT:
246                                 mul_v3_m4v3(*texco, ob->obmat, *co);
247                                 mul_m4_v3(wmd->map_object->imat, *texco);
248                                 break;
249                 }
250         }
251 }
252
253 static void waveModifier_do(WaveModifierData *md, 
254                 Scene *scene, Object *ob, DerivedMesh *dm,
255            float (*vertexCos)[3], int numVerts)
256 {
257         WaveModifierData *wmd = (WaveModifierData*) md;
258         MVert *mvert = NULL;
259         MDeformVert *dvert = NULL;
260         int defgrp_index;
261         float ctime = BKE_curframe(scene);
262         float minfac =
263                         (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
264         float lifefac = wmd->height;
265         float (*tex_co)[3] = NULL;
266         const int wmd_axis= wmd->flag & (MOD_WAVE_X|MOD_WAVE_Y);
267         const float falloff= wmd->falloff;
268         float falloff_fac= 1.0f; /* when falloff == 0.0f this stays at 1.0f */
269
270         if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH)
271                 mvert = dm->getVertArray(dm);
272
273         if(wmd->objectcenter){
274                 float mat[4][4];
275                 /* get the control object's location in local coordinates */
276                 invert_m4_m4(ob->imat, ob->obmat);
277                 mul_m4_m4m4(mat, wmd->objectcenter->obmat, ob->imat);
278
279                 wmd->startx = mat[3][0];
280                 wmd->starty = mat[3][1];
281         }
282
283         /* get the index of the deform group */
284         defgrp_index = defgroup_name_index(ob, wmd->defgrp_name);
285
286         if(defgrp_index >= 0){
287                 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
288         }
289
290         if(wmd->damp == 0) wmd->damp = 10.0f;
291
292         if(wmd->lifetime != 0.0f) {
293                 float x = ctime - wmd->timeoffs;
294
295                 if(x > wmd->lifetime) {
296                         lifefac = x - wmd->lifetime;
297
298                         if(lifefac > wmd->damp) lifefac = 0.0;
299                         else lifefac =
300                                 (float)(wmd->height * (1.0f - sqrtf(lifefac / wmd->damp)));
301                 }
302         }
303
304         if(wmd->texture) {
305                 tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
306                                          "waveModifier_do tex_co");
307                 wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts);
308         }
309
310         if(lifefac != 0.0f) {
311                 /* avoid divide by zero checks within the loop */
312                 float falloff_inv= falloff ? 1.0f / falloff : 1.0f;
313                 int i;
314
315                 for(i = 0; i < numVerts; i++) {
316                         float *co = vertexCos[i];
317                         float x = co[0] - wmd->startx;
318                         float y = co[1] - wmd->starty;
319                         float amplit= 0.0f;
320                         float def_weight= 1.0f;
321
322                         /* get weights */
323                         if(dvert) {
324                                 def_weight= defvert_find_weight(&dvert[i], defgrp_index);
325
326                                 /* if this vert isn't in the vgroup, don't deform it */
327                                 if(def_weight == 0.0f) {
328                                         continue;
329                                 }
330                         }
331
332                         switch(wmd_axis) {
333                         case MOD_WAVE_X|MOD_WAVE_Y:
334                                 amplit = sqrtf(x*x + y*y);
335                                 break;
336                         case MOD_WAVE_X:
337                                 amplit = x;
338                                 break;
339                         case MOD_WAVE_Y:
340                                 amplit = y;
341                                 break;
342                         }
343
344                         /* this way it makes nice circles */
345                         amplit -= (ctime - wmd->timeoffs) * wmd->speed;
346
347                         if(wmd->flag & MOD_WAVE_CYCL) {
348                                 amplit = (float)fmodf(amplit - wmd->width, 2.0f * wmd->width)
349                                                 + wmd->width;
350                         }
351
352                         if(falloff != 0.0f) {
353                                 float dist = 0.0f;
354
355                                 switch(wmd_axis) {
356                                 case MOD_WAVE_X|MOD_WAVE_Y:
357                                         dist = sqrtf(x*x + y*y);
358                                         break;
359                                 case MOD_WAVE_X:
360                                         dist = fabsf(x);
361                                         break;
362                                 case MOD_WAVE_Y:
363                                         dist = fabsf(y);
364                                         break;
365                                 }
366
367                                 falloff_fac = (1.0f - (dist * falloff_inv));
368                                 CLAMP(falloff_fac, 0.0f, 1.0f);
369                         }
370
371                         /* GAUSSIAN */
372                         if((falloff_fac != 0.0f) && (amplit > -wmd->width) && (amplit < wmd->width)) {
373                                 amplit = amplit * wmd->narrow;
374                                 amplit = (float)(1.0f / expf(amplit * amplit) - minfac);
375
376                                 /*apply texture*/
377                                 if(wmd->texture) {
378                                         TexResult texres;
379                                         texres.nor = NULL;
380                                         get_texture_value(wmd->texture, tex_co[i], &texres);
381                                         amplit *= texres.tin;
382                                 }
383
384                                 /*apply weight & falloff */
385                                 amplit *= def_weight * falloff_fac;
386
387                                 if(mvert) {
388                                         /* move along normals */
389                                         if(wmd->flag & MOD_WAVE_NORM_X) {
390                                                 co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
391                                         }
392                                         if(wmd->flag & MOD_WAVE_NORM_Y) {
393                                                 co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
394                                         }
395                                         if(wmd->flag & MOD_WAVE_NORM_Z) {
396                                                 co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
397                                         }
398                                 }
399                                 else {
400                                         /* move along local z axis */
401                                         co[2] += lifefac * amplit;
402                                 }
403                         }
404                 }
405         }
406
407         if(wmd->texture) MEM_freeN(tex_co);
408 }
409
410 static void deformVerts(ModifierData *md, Object *ob,
411                                                 DerivedMesh *derivedData,
412                                                 float (*vertexCos)[3],
413                                                 int numVerts,
414                                                 int UNUSED(useRenderParams),
415                                                 int UNUSED(isFinalCalc))
416 {
417         DerivedMesh *dm= derivedData;
418         WaveModifierData *wmd = (WaveModifierData *)md;
419
420         if(wmd->flag & MOD_WAVE_NORM)
421                 dm= get_cddm(ob, NULL, dm, vertexCos);
422         else if(wmd->texture || wmd->defgrp_name[0])
423                 dm= get_dm(ob, NULL, dm, NULL, 0);
424
425         waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
426
427         if(dm != derivedData)
428                 dm->release(dm);
429 }
430
431 static void deformVertsEM(
432                                            ModifierData *md, Object *ob, struct EditMesh *editData,
433            DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
434 {
435         DerivedMesh *dm= derivedData;
436         WaveModifierData *wmd = (WaveModifierData *)md;
437
438         if(wmd->flag & MOD_WAVE_NORM)
439                 dm= get_cddm(ob, editData, dm, vertexCos);
440         else if(wmd->texture || wmd->defgrp_name[0])
441                 dm= get_dm(ob, editData, dm, NULL, 0);
442
443         waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
444
445         if(dm != derivedData)
446                 dm->release(dm);
447 }
448
449
450 ModifierTypeInfo modifierType_Wave = {
451         /* name */              "Wave",
452         /* structName */        "WaveModifierData",
453         /* structSize */        sizeof(WaveModifierData),
454         /* type */              eModifierTypeType_OnlyDeform,
455         /* flags */             eModifierTypeFlag_AcceptsCVs
456                                                         | eModifierTypeFlag_SupportsEditmode,
457         /* copyData */          copyData,
458         /* deformVerts */       deformVerts,
459         /* deformMatrices */    NULL,
460         /* deformVertsEM */     deformVertsEM,
461         /* deformMatricesEM */  NULL,
462         /* applyModifier */     NULL,
463         /* applyModifierEM */   NULL,
464         /* initData */          initData,
465         /* requiredDataMask */  requiredDataMask,
466         /* freeData */          NULL,
467         /* isDisabled */        NULL,
468         /* updateDepgraph */    updateDepgraph,
469         /* dependsOnTime */     dependsOnTime,
470         /* dependsOnNormals */  NULL,
471         /* foreachObjectLink */ foreachObjectLink,
472         /* foreachIDLink */     foreachIDLink,
473 };