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