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