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