Depsgraph: remove EvaluationContext, pass Depsgraph instead.
[blender.git] / source / blender / modifiers / intern / MOD_ocean.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) Blender Foundation
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Matt Ebb
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/modifiers/intern/MOD_ocean.c
29  *  \ingroup modifiers
30  */
31
32 #include "DNA_customdata_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_meshdata_types.h"
35 #include "DNA_modifier_types.h"
36 #include "DNA_scene_types.h"
37
38 #include "BLI_math.h"
39 #include "BLI_math_inline.h"
40 #include "BLI_task.h"
41 #include "BLI_utildefines.h"
42
43 #include "BKE_cdderivedmesh.h"
44 #include "BKE_modifier.h"
45 #include "BKE_ocean.h"
46
47 #include "MOD_modifiertypes.h"
48
49 #ifdef WITH_OCEANSIM
50 static void init_cache_data(Object *ob, struct OceanModifierData *omd)
51 {
52         const char *relbase = modifier_path_relbase(ob);
53
54         omd->oceancache = BKE_ocean_init_cache(omd->cachepath, relbase,
55                                                omd->bakestart, omd->bakeend, omd->wave_scale,
56                                                omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
57 }
58
59 static void clear_cache_data(struct OceanModifierData *omd)
60 {
61         BKE_ocean_free_cache(omd->oceancache);
62         omd->oceancache = NULL;
63         omd->cached = false;
64 }
65
66 /* keep in sync with init_ocean_modifier_bake(), object_modifier.c */
67 static void init_ocean_modifier(struct OceanModifierData *omd)
68 {
69         int do_heightfield, do_chop, do_normals, do_jacobian;
70
71         if (!omd || !omd->ocean) return;
72
73         do_heightfield = true;
74         do_chop = (omd->chop_amount > 0);
75         do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
76         do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
77
78         BKE_ocean_free_data(omd->ocean);
79         BKE_ocean_init(omd->ocean, omd->resolution * omd->resolution, omd->resolution * omd->resolution,
80                        omd->spatial_size, omd->spatial_size,
81                        omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
82                        omd->depth, omd->time,
83                        do_heightfield, do_chop, do_normals, do_jacobian,
84                        omd->seed);
85 }
86
87 static void simulate_ocean_modifier(struct OceanModifierData *omd)
88 {
89         if (!omd || !omd->ocean) return;
90
91         BKE_ocean_simulate(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount);
92 }
93 #endif /* WITH_OCEANSIM */
94
95
96
97 /* Modifier Code */
98
99 static void initData(ModifierData *md)
100 {
101 #ifdef WITH_OCEANSIM
102         OceanModifierData *omd = (OceanModifierData *) md;
103
104         omd->resolution = 7;
105         omd->spatial_size = 50;
106
107         omd->wave_alignment = 0.0;
108         omd->wind_velocity = 30.0;
109
110         omd->damp = 0.5;
111         omd->smallest_wave = 0.01;
112         omd->wave_direction = 0.0;
113         omd->depth = 200.0;
114
115         omd->wave_scale = 1.0;
116
117         omd->chop_amount = 1.0;
118
119         omd->foam_coverage = 0.0;
120
121         omd->seed = 0;
122         omd->time = 1.0;
123
124         omd->refresh = 0;
125
126         omd->size = 1.0;
127         omd->repeat_x = 1;
128         omd->repeat_y = 1;
129
130         modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean");
131
132         omd->cached = 0;
133         omd->bakestart = 1;
134         omd->bakeend = 250;
135         omd->oceancache = NULL;
136         omd->foam_fade = 0.98;
137         omd->foamlayername[0] = '\0';   /* layer name empty by default */
138
139         omd->ocean = BKE_ocean_add();
140         init_ocean_modifier(omd);
141         simulate_ocean_modifier(omd);
142 #else  /* WITH_OCEANSIM */
143            /* unused */
144         (void)md;
145 #endif /* WITH_OCEANSIM */
146 }
147
148 static void freeData(ModifierData *md)
149 {
150 #ifdef WITH_OCEANSIM
151         OceanModifierData *omd = (OceanModifierData *) md;
152
153         BKE_ocean_free(omd->ocean);
154         if (omd->oceancache)
155                 BKE_ocean_free_cache(omd->oceancache);
156 #else /* WITH_OCEANSIM */
157         /* unused */
158         (void)md;
159 #endif /* WITH_OCEANSIM */
160 }
161
162 static void copyData(ModifierData *md, ModifierData *target)
163 {
164 #ifdef WITH_OCEANSIM
165 #if 0
166         OceanModifierData *omd = (OceanModifierData *) md;
167 #endif
168         OceanModifierData *tomd = (OceanModifierData *) target;
169
170         freeData(target);
171
172         modifier_copyData_generic(md, target);
173
174         tomd->refresh = 0;
175
176         /* XXX todo: copy cache runtime too */
177         tomd->cached = 0;
178         tomd->oceancache = NULL;
179
180         tomd->ocean = BKE_ocean_add();
181         init_ocean_modifier(tomd);
182         simulate_ocean_modifier(tomd);
183 #else /* WITH_OCEANSIM */
184         /* unused */
185         (void)md;
186         (void)target;
187 #endif /* WITH_OCEANSIM */
188 }
189
190 #ifdef WITH_OCEANSIM
191 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
192 {
193         OceanModifierData *omd = (OceanModifierData *)md;
194         CustomDataMask dataMask = 0;
195
196         if (omd->flag & MOD_OCEAN_GENERATE_FOAM)
197                 dataMask |= CD_MASK_MCOL;
198
199         return dataMask;
200 }
201 #else /* WITH_OCEANSIM */
202 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
203 {
204         /* unused */
205         (void)md;
206         return 0;
207 }
208 #endif /* WITH_OCEANSIM */
209
210 static bool dependsOnNormals(ModifierData *md)
211 {
212         OceanModifierData *omd = (OceanModifierData *)md;
213         return (omd->geometry_mode != MOD_OCEAN_GEOM_GENERATE);
214 }
215
216 #if 0
217 static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, float *oy)
218 {
219         /* get bounding box of underlying dm */
220         int v, totvert = dm->getNumVerts(dm);
221         float min[3], max[3], delta[3];
222
223         MVert *mvert = dm->getVertDataArray(dm, 0);
224
225         copy_v3_v3(min, mvert->co);
226         copy_v3_v3(max, mvert->co);
227
228         for (v = 1; v < totvert; v++, mvert++) {
229                 min[0] = min_ff(min[0], mvert->co[0]);
230                 min[1] = min_ff(min[1], mvert->co[1]);
231                 min[2] = min_ff(min[2], mvert->co[2]);
232
233                 max[0] = max_ff(max[0], mvert->co[0]);
234                 max[1] = max_ff(max[1], mvert->co[1]);
235                 max[2] = max_ff(max[2], mvert->co[2]);
236         }
237
238         sub_v3_v3v3(delta, max, min);
239
240         *sx = delta[0];
241         *sy = delta[1];
242
243         *ox = min[0];
244         *oy = min[1];
245 }
246 #endif
247
248 #ifdef WITH_OCEANSIM
249
250 typedef struct GenerateOceanGeometryData {
251         MVert *mverts;
252         MPoly *mpolys;
253         MLoop *mloops;
254         int *origindex;
255         MLoopUV *mloopuvs;
256
257         int res_x, res_y;
258         int rx, ry;
259         float ox, oy;
260         float sx, sy;
261         float ix, iy;
262 } GenerateOceanGeometryData;
263
264 static void generate_ocean_geometry_vertices(
265         void *__restrict userdata,
266         const int y,
267         const ParallelRangeTLS *__restrict UNUSED(tls))
268 {
269         GenerateOceanGeometryData *gogd = userdata;
270         int x;
271
272         for (x = 0; x <= gogd->res_x; x++) {
273                 const int i = y * (gogd->res_x + 1) + x;
274                 float *co = gogd->mverts[i].co;
275                 co[0] = gogd->ox + (x * gogd->sx);
276                 co[1] = gogd->oy + (y * gogd->sy);
277                 co[2] = 0.0f;
278         }
279 }
280
281 static void generate_ocean_geometry_polygons(
282         void *__restrict userdata,
283         const int y,
284         const ParallelRangeTLS *__restrict UNUSED(tls))
285 {
286         GenerateOceanGeometryData *gogd = userdata;
287         int x;
288
289         for (x = 0; x < gogd->res_x; x++) {
290                 const int fi = y * gogd->res_x + x;
291                 const int vi = y * (gogd->res_x + 1) + x;
292                 MPoly *mp = &gogd->mpolys[fi];
293                 MLoop *ml = &gogd->mloops[fi * 4];
294
295                 ml->v = vi;
296                 ml++;
297                 ml->v = vi + 1;
298                 ml++;
299                 ml->v = vi + 1 + gogd->res_x + 1;
300                 ml++;
301                 ml->v = vi + gogd->res_x + 1;
302                 ml++;
303
304                 mp->loopstart = fi * 4;
305                 mp->totloop = 4;
306
307                 mp->flag |= ME_SMOOTH;
308
309                 /* generated geometry does not map to original faces */
310                 gogd->origindex[fi] = ORIGINDEX_NONE;
311         }
312 }
313
314 static void generate_ocean_geometry_uvs(
315         void *__restrict userdata,
316         const int y,
317         const ParallelRangeTLS *__restrict UNUSED(tls))
318 {
319         GenerateOceanGeometryData *gogd = userdata;
320         int x;
321
322         for (x = 0; x < gogd->res_x; x++) {
323                 const int i = y * gogd->res_x + x;
324                 MLoopUV *luv = &gogd->mloopuvs[i * 4];
325
326                 luv->uv[0] = x * gogd->ix;
327                 luv->uv[1] = y * gogd->iy;
328                 luv++;
329
330                 luv->uv[0] = (x + 1) * gogd->ix;
331                 luv->uv[1] = y * gogd->iy;
332                 luv++;
333
334                 luv->uv[0] = (x + 1) * gogd->ix;
335                 luv->uv[1] = (y + 1) * gogd->iy;
336                 luv++;
337
338                 luv->uv[0] = x * gogd->ix;
339                 luv->uv[1] = (y + 1) * gogd->iy;
340                 luv++;
341         }
342 }
343
344 static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
345 {
346         DerivedMesh *result;
347
348         GenerateOceanGeometryData gogd;
349
350         int num_verts;
351         int num_polys;
352
353         const bool use_threading = omd->resolution > 4;
354
355         gogd.rx = omd->resolution * omd->resolution;
356         gogd.ry = omd->resolution * omd->resolution;
357         gogd.res_x = gogd.rx * omd->repeat_x;
358         gogd.res_y = gogd.ry * omd->repeat_y;
359
360         num_verts = (gogd.res_x + 1) * (gogd.res_y + 1);
361         num_polys = gogd.res_x * gogd.res_y;
362
363         gogd.sx = omd->size * omd->spatial_size;
364         gogd.sy = omd->size * omd->spatial_size;
365         gogd.ox = -gogd.sx / 2.0f;
366         gogd.oy = -gogd.sy / 2.0f;
367
368         gogd.sx /= gogd.rx;
369         gogd.sy /= gogd.ry;
370
371         result = CDDM_new(num_verts, 0, 0, num_polys * 4, num_polys);
372
373         gogd.mverts = CDDM_get_verts(result);
374         gogd.mpolys = CDDM_get_polys(result);
375         gogd.mloops = CDDM_get_loops(result);
376
377         gogd.origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
378
379         ParallelRangeSettings settings;
380         BLI_parallel_range_settings_defaults(&settings);
381         settings.use_threading = use_threading;
382
383         /* create vertices */
384         BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_vertices, &settings);
385
386         /* create faces */
387         BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_polygons, &settings);
388
389         CDDM_calc_edges(result);
390
391         /* add uvs */
392         if (CustomData_number_of_layers(&result->loopData, CD_MLOOPUV) < MAX_MTFACE) {
393                 gogd.mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_polys * 4);
394
395                 if (gogd.mloopuvs) { /* unlikely to fail */
396                         gogd.ix = 1.0 / gogd.rx;
397                         gogd.iy = 1.0 / gogd.ry;
398
399                         BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_uvs, &settings);
400                 }
401         }
402
403         result->dirty |= DM_DIRTY_NORMALS;
404
405         return result;
406 }
407
408 static DerivedMesh *doOcean(ModifierData *md, Object *ob,
409                             DerivedMesh *derivedData,
410                             int UNUSED(useRenderParams))
411 {
412         OceanModifierData *omd = (OceanModifierData *) md;
413
414         DerivedMesh *dm = NULL;
415         OceanResult ocr;
416
417         MVert *mverts;
418
419         int cfra;
420         int i, j;
421
422         /* use cached & inverted value for speed
423          * expanded this would read...
424          *
425          * (axis / (omd->size * omd->spatial_size)) + 0.5f) */
426 #define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f)
427
428         const float size_co_inv = 1.0f / (omd->size * omd->spatial_size);
429
430         /* can happen in when size is small, avoid bad array lookups later and quit now */
431         if (!isfinite(size_co_inv)) {
432                 return derivedData;
433         }
434
435         /* update modifier */
436         if (omd->refresh & MOD_OCEAN_REFRESH_ADD) {
437                 omd->ocean = BKE_ocean_add();
438         }
439         if (omd->refresh & MOD_OCEAN_REFRESH_RESET) {
440                 init_ocean_modifier(omd);
441         }
442         if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) {
443                 clear_cache_data(omd);
444         }
445         omd->refresh = 0;
446
447         /* do ocean simulation */
448         if (omd->cached == true) {
449                 if (!omd->oceancache) {
450                         init_cache_data(ob, omd);
451                 }
452                 BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra);
453         }
454         else {
455                 simulate_ocean_modifier(omd);
456         }
457
458         if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) {
459                 dm = generate_ocean_geometry(omd);
460                 DM_ensure_normals(dm);
461         }
462         else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
463                 dm = CDDM_copy(derivedData);
464         }
465
466         cfra = md->scene->r.cfra;
467         CLAMP(cfra, omd->bakestart, omd->bakeend);
468         cfra -= omd->bakestart; /* shift to 0 based */
469
470         mverts = dm->getVertArray(dm);
471
472         /* add vcols before displacement - allows lookup based on position */
473
474         if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
475                 if (CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL) < MAX_MCOL) {
476                         const int num_polys = dm->getNumPolys(dm);
477                         const int num_loops = dm->getNumLoops(dm);
478                         MLoop *mloops = dm->getLoopArray(dm);
479                         MLoopCol *mloopcols = CustomData_add_layer_named(
480                                                   &dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->foamlayername);
481
482                         if (mloopcols) { /* unlikely to fail */
483                                 MPoly *mpolys = dm->getPolyArray(dm);
484                                 MPoly *mp;
485
486                                 for (i = 0, mp = mpolys; i < num_polys; i++, mp++) {
487                                         MLoop *ml = &mloops[mp->loopstart];
488                                         MLoopCol *mlcol = &mloopcols[mp->loopstart];
489
490                                         for (j = mp->totloop; j--; ml++, mlcol++) {
491                                                 const float *vco = mverts[ml->v].co;
492                                                 const float u = OCEAN_CO(size_co_inv, vco[0]);
493                                                 const float v = OCEAN_CO(size_co_inv, vco[1]);
494                                                 float foam;
495
496                                                 if (omd->oceancache && omd->cached == true) {
497                                                         BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
498                                                         foam = ocr.foam;
499                                                         CLAMP(foam, 0.0f, 1.0f);
500                                                 }
501                                                 else {
502                                                         BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
503                                                         foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
504                                                 }
505
506                                                 mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
507                                                 /* This needs to be set (render engine uses) */
508                                                 mlcol->a = 255;
509                                         }
510                                 }
511                         }
512                 }
513         }
514
515
516         /* displace the geometry */
517
518         /* Note: tried to parallelized that one and previous foam loop, but gives 20% slower results... odd. */
519         {
520                 const int num_verts = dm->getNumVerts(dm);
521
522                 for (i = 0; i < num_verts; i++) {
523                         float *vco = mverts[i].co;
524                         const float u = OCEAN_CO(size_co_inv, vco[0]);
525                         const float v = OCEAN_CO(size_co_inv, vco[1]);
526
527                         if (omd->oceancache && omd->cached == true) {
528                                 BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
529                         }
530                         else {
531                                 BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
532                         }
533
534                         vco[2] += ocr.disp[1];
535
536                         if (omd->chop_amount > 0.0f) {
537                                 vco[0] += ocr.disp[0];
538                                 vco[1] += ocr.disp[2];
539                         }
540                 }
541         }
542
543 #undef OCEAN_CO
544
545         return dm;
546 }
547 #else  /* WITH_OCEANSIM */
548 static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
549                             DerivedMesh *derivedData,
550                             int UNUSED(useRenderParams))
551 {
552         /* unused */
553         (void)md;
554         return derivedData;
555 }
556 #endif /* WITH_OCEANSIM */
557
558 static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *UNUSED(depsgraph),
559                                   Object *ob, DerivedMesh *derivedData,
560                                   ModifierApplyFlag UNUSED(flag))
561 {
562         DerivedMesh *result;
563
564         result = doOcean(md, ob, derivedData, 0);
565
566         if (result != derivedData)
567                 result->dirty |= DM_DIRTY_NORMALS;
568
569         return result;
570 }
571
572
573 ModifierTypeInfo modifierType_Ocean = {
574         /* name */              "Ocean",
575         /* structName */        "OceanModifierData",
576         /* structSize */        sizeof(OceanModifierData),
577         /* type */              eModifierTypeType_Constructive,
578         /* flags */             eModifierTypeFlag_AcceptsMesh |
579                                 eModifierTypeFlag_SupportsEditmode |
580                                 eModifierTypeFlag_EnableInEditmode,
581
582         /* copyData */          copyData,
583         /* deformMatrices */    NULL,
584         /* deformVerts */       NULL,
585         /* deformVertsEM */     NULL,
586         /* deformMatricesEM */  NULL,
587         /* applyModifier */     applyModifier,
588         /* applyModifierEM */   NULL,
589         /* initData */          initData,
590         /* requiredDataMask */  requiredDataMask,
591         /* freeData */          freeData,
592         /* isDisabled */        NULL,
593         /* updateDepsgraph */   NULL,
594         /* dependsOnTime */     NULL,
595         /* dependsOnNormals */  dependsOnNormals,
596         /* foreachObjectLink */ NULL,
597         /* foreachIDLink */     NULL,
598         /* foreachTexLink */    NULL,
599 };