Merge branch 'master' into blender2.8
[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(const ModifierData *md, ModifierData *target)
163 {
164 #ifdef WITH_OCEANSIM
165 #if 0
166         const OceanModifierData *omd = (const OceanModifierData *) md;
167 #endif
168         OceanModifierData *tomd = (OceanModifierData *) target;
169
170         modifier_copyData_generic(md, target);
171
172         tomd->refresh = 0;
173
174         /* XXX todo: copy cache runtime too */
175         tomd->cached = 0;
176         tomd->oceancache = NULL;
177
178         tomd->ocean = BKE_ocean_add();
179         init_ocean_modifier(tomd);
180         simulate_ocean_modifier(tomd);
181 #else /* WITH_OCEANSIM */
182         /* unused */
183         (void)md;
184         (void)target;
185 #endif /* WITH_OCEANSIM */
186 }
187
188 #ifdef WITH_OCEANSIM
189 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
190 {
191         OceanModifierData *omd = (OceanModifierData *)md;
192         CustomDataMask dataMask = 0;
193
194         if (omd->flag & MOD_OCEAN_GENERATE_FOAM)
195                 dataMask |= CD_MASK_MCOL;
196
197         return dataMask;
198 }
199 #else /* WITH_OCEANSIM */
200 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
201 {
202         /* unused */
203         (void)md;
204         return 0;
205 }
206 #endif /* WITH_OCEANSIM */
207
208 static bool dependsOnNormals(ModifierData *md)
209 {
210         OceanModifierData *omd = (OceanModifierData *)md;
211         return (omd->geometry_mode != MOD_OCEAN_GEOM_GENERATE);
212 }
213
214 #if 0
215 static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, float *oy)
216 {
217         /* get bounding box of underlying dm */
218         int v, totvert = dm->getNumVerts(dm);
219         float min[3], max[3], delta[3];
220
221         MVert *mvert = dm->getVertDataArray(dm, 0);
222
223         copy_v3_v3(min, mvert->co);
224         copy_v3_v3(max, mvert->co);
225
226         for (v = 1; v < totvert; v++, mvert++) {
227                 min[0] = min_ff(min[0], mvert->co[0]);
228                 min[1] = min_ff(min[1], mvert->co[1]);
229                 min[2] = min_ff(min[2], mvert->co[2]);
230
231                 max[0] = max_ff(max[0], mvert->co[0]);
232                 max[1] = max_ff(max[1], mvert->co[1]);
233                 max[2] = max_ff(max[2], mvert->co[2]);
234         }
235
236         sub_v3_v3v3(delta, max, min);
237
238         *sx = delta[0];
239         *sy = delta[1];
240
241         *ox = min[0];
242         *oy = min[1];
243 }
244 #endif
245
246 #ifdef WITH_OCEANSIM
247
248 typedef struct GenerateOceanGeometryData {
249         MVert *mverts;
250         MPoly *mpolys;
251         MLoop *mloops;
252         int *origindex;
253         MLoopUV *mloopuvs;
254
255         int res_x, res_y;
256         int rx, ry;
257         float ox, oy;
258         float sx, sy;
259         float ix, iy;
260 } GenerateOceanGeometryData;
261
262 static void generate_ocean_geometry_vertices(
263         void *__restrict userdata,
264         const int y,
265         const ParallelRangeTLS *__restrict UNUSED(tls))
266 {
267         GenerateOceanGeometryData *gogd = userdata;
268         int x;
269
270         for (x = 0; x <= gogd->res_x; x++) {
271                 const int i = y * (gogd->res_x + 1) + x;
272                 float *co = gogd->mverts[i].co;
273                 co[0] = gogd->ox + (x * gogd->sx);
274                 co[1] = gogd->oy + (y * gogd->sy);
275                 co[2] = 0.0f;
276         }
277 }
278
279 static void generate_ocean_geometry_polygons(
280         void *__restrict userdata,
281         const int y,
282         const ParallelRangeTLS *__restrict UNUSED(tls))
283 {
284         GenerateOceanGeometryData *gogd = userdata;
285         int x;
286
287         for (x = 0; x < gogd->res_x; x++) {
288                 const int fi = y * gogd->res_x + x;
289                 const int vi = y * (gogd->res_x + 1) + x;
290                 MPoly *mp = &gogd->mpolys[fi];
291                 MLoop *ml = &gogd->mloops[fi * 4];
292
293                 ml->v = vi;
294                 ml++;
295                 ml->v = vi + 1;
296                 ml++;
297                 ml->v = vi + 1 + gogd->res_x + 1;
298                 ml++;
299                 ml->v = vi + gogd->res_x + 1;
300                 ml++;
301
302                 mp->loopstart = fi * 4;
303                 mp->totloop = 4;
304
305                 mp->flag |= ME_SMOOTH;
306
307                 /* generated geometry does not map to original faces */
308                 gogd->origindex[fi] = ORIGINDEX_NONE;
309         }
310 }
311
312 static void generate_ocean_geometry_uvs(
313         void *__restrict userdata,
314         const int y,
315         const ParallelRangeTLS *__restrict UNUSED(tls))
316 {
317         GenerateOceanGeometryData *gogd = userdata;
318         int x;
319
320         for (x = 0; x < gogd->res_x; x++) {
321                 const int i = y * gogd->res_x + x;
322                 MLoopUV *luv = &gogd->mloopuvs[i * 4];
323
324                 luv->uv[0] = x * gogd->ix;
325                 luv->uv[1] = y * gogd->iy;
326                 luv++;
327
328                 luv->uv[0] = (x + 1) * gogd->ix;
329                 luv->uv[1] = y * gogd->iy;
330                 luv++;
331
332                 luv->uv[0] = (x + 1) * gogd->ix;
333                 luv->uv[1] = (y + 1) * gogd->iy;
334                 luv++;
335
336                 luv->uv[0] = x * gogd->ix;
337                 luv->uv[1] = (y + 1) * gogd->iy;
338                 luv++;
339         }
340 }
341
342 static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
343 {
344         DerivedMesh *result;
345
346         GenerateOceanGeometryData gogd;
347
348         int num_verts;
349         int num_polys;
350
351         const bool use_threading = omd->resolution > 4;
352
353         gogd.rx = omd->resolution * omd->resolution;
354         gogd.ry = omd->resolution * omd->resolution;
355         gogd.res_x = gogd.rx * omd->repeat_x;
356         gogd.res_y = gogd.ry * omd->repeat_y;
357
358         num_verts = (gogd.res_x + 1) * (gogd.res_y + 1);
359         num_polys = gogd.res_x * gogd.res_y;
360
361         gogd.sx = omd->size * omd->spatial_size;
362         gogd.sy = omd->size * omd->spatial_size;
363         gogd.ox = -gogd.sx / 2.0f;
364         gogd.oy = -gogd.sy / 2.0f;
365
366         gogd.sx /= gogd.rx;
367         gogd.sy /= gogd.ry;
368
369         result = CDDM_new(num_verts, 0, 0, num_polys * 4, num_polys);
370
371         gogd.mverts = CDDM_get_verts(result);
372         gogd.mpolys = CDDM_get_polys(result);
373         gogd.mloops = CDDM_get_loops(result);
374
375         gogd.origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
376
377         ParallelRangeSettings settings;
378         BLI_parallel_range_settings_defaults(&settings);
379         settings.use_threading = use_threading;
380
381         /* create vertices */
382         BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_vertices, &settings);
383
384         /* create faces */
385         BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_polygons, &settings);
386
387         CDDM_calc_edges(result);
388
389         /* add uvs */
390         if (CustomData_number_of_layers(&result->loopData, CD_MLOOPUV) < MAX_MTFACE) {
391                 gogd.mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_polys * 4);
392
393                 if (gogd.mloopuvs) { /* unlikely to fail */
394                         gogd.ix = 1.0 / gogd.rx;
395                         gogd.iy = 1.0 / gogd.ry;
396
397                         BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_uvs, &settings);
398                 }
399         }
400
401         result->dirty |= DM_DIRTY_NORMALS;
402
403         return result;
404 }
405
406 static DerivedMesh *doOcean(
407         ModifierData *md, Object *ob,
408         DerivedMesh *derivedData,
409         int UNUSED(useRenderParams))
410 {
411         OceanModifierData *omd = (OceanModifierData *) md;
412
413         DerivedMesh *dm = NULL;
414         OceanResult ocr;
415
416         MVert *mverts;
417
418         int cfra;
419         int i, j;
420
421         /* use cached & inverted value for speed
422          * expanded this would read...
423          *
424          * (axis / (omd->size * omd->spatial_size)) + 0.5f) */
425 #define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f)
426
427         const float size_co_inv = 1.0f / (omd->size * omd->spatial_size);
428
429         /* can happen in when size is small, avoid bad array lookups later and quit now */
430         if (!isfinite(size_co_inv)) {
431                 return derivedData;
432         }
433
434         /* update modifier */
435         if (omd->refresh & MOD_OCEAN_REFRESH_ADD) {
436                 omd->ocean = BKE_ocean_add();
437         }
438         if (omd->refresh & MOD_OCEAN_REFRESH_RESET) {
439                 init_ocean_modifier(omd);
440         }
441         if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) {
442                 clear_cache_data(omd);
443         }
444         omd->refresh = 0;
445
446         /* do ocean simulation */
447         if (omd->cached == true) {
448                 if (!omd->oceancache) {
449                         init_cache_data(ob, omd);
450                 }
451                 BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra);
452         }
453         else {
454                 simulate_ocean_modifier(omd);
455         }
456
457         if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) {
458                 dm = generate_ocean_geometry(omd);
459                 DM_ensure_normals(dm);
460         }
461         else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
462                 dm = CDDM_copy(derivedData);
463         }
464
465         cfra = md->scene->r.cfra;
466         CLAMP(cfra, omd->bakestart, omd->bakeend);
467         cfra -= omd->bakestart; /* shift to 0 based */
468
469         mverts = dm->getVertArray(dm);
470
471         /* add vcols before displacement - allows lookup based on position */
472
473         if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
474                 if (CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL) < MAX_MCOL) {
475                         const int num_polys = dm->getNumPolys(dm);
476                         const int num_loops = dm->getNumLoops(dm);
477                         MLoop *mloops = dm->getLoopArray(dm);
478                         MLoopCol *mloopcols = CustomData_add_layer_named(
479                                                   &dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->foamlayername);
480
481                         if (mloopcols) { /* unlikely to fail */
482                                 MPoly *mpolys = dm->getPolyArray(dm);
483                                 MPoly *mp;
484
485                                 for (i = 0, mp = mpolys; i < num_polys; i++, mp++) {
486                                         MLoop *ml = &mloops[mp->loopstart];
487                                         MLoopCol *mlcol = &mloopcols[mp->loopstart];
488
489                                         for (j = mp->totloop; j--; ml++, mlcol++) {
490                                                 const float *vco = mverts[ml->v].co;
491                                                 const float u = OCEAN_CO(size_co_inv, vco[0]);
492                                                 const float v = OCEAN_CO(size_co_inv, vco[1]);
493                                                 float foam;
494
495                                                 if (omd->oceancache && omd->cached == true) {
496                                                         BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
497                                                         foam = ocr.foam;
498                                                         CLAMP(foam, 0.0f, 1.0f);
499                                                 }
500                                                 else {
501                                                         BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
502                                                         foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
503                                                 }
504
505                                                 mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
506                                                 /* This needs to be set (render engine uses) */
507                                                 mlcol->a = 255;
508                                         }
509                                 }
510                         }
511                 }
512         }
513
514
515         /* displace the geometry */
516
517         /* Note: tried to parallelized that one and previous foam loop, but gives 20% slower results... odd. */
518         {
519                 const int num_verts = dm->getNumVerts(dm);
520
521                 for (i = 0; i < num_verts; i++) {
522                         float *vco = mverts[i].co;
523                         const float u = OCEAN_CO(size_co_inv, vco[0]);
524                         const float v = OCEAN_CO(size_co_inv, vco[1]);
525
526                         if (omd->oceancache && omd->cached == true) {
527                                 BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
528                         }
529                         else {
530                                 BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
531                         }
532
533                         vco[2] += ocr.disp[1];
534
535                         if (omd->chop_amount > 0.0f) {
536                                 vco[0] += ocr.disp[0];
537                                 vco[1] += ocr.disp[2];
538                         }
539                 }
540         }
541
542 #undef OCEAN_CO
543
544         return dm;
545 }
546 #else  /* WITH_OCEANSIM */
547 static DerivedMesh *doOcean(
548         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(
559         ModifierData *md, const ModifierEvalContext *ctx,
560         DerivedMesh *derivedData)
561 {
562         DerivedMesh *result;
563
564         result = doOcean(md, ctx->object, 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_DM */ NULL,
584
585         /* deformVerts_DM */    NULL,
586         /* deformVertsEM_DM */  NULL,
587         /* deformMatricesEM_DM*/NULL,
588         /* applyModifier_DM */  applyModifier,
589         /* applyModifierEM_DM */NULL,
590
591         /* deformVerts */       NULL,
592         /* deformMatrices */    NULL,
593         /* deformVertsEM */     NULL,
594         /* deformMatricesEM */  NULL,
595         /* applyModifier */     NULL,
596         /* applyModifierEM */   NULL,
597
598         /* initData */          initData,
599         /* requiredDataMask */  requiredDataMask,
600         /* freeData */          freeData,
601         /* isDisabled */        NULL,
602         /* updateDepsgraph */   NULL,
603         /* dependsOnTime */     NULL,
604         /* dependsOnNormals */  dependsOnNormals,
605         /* foreachObjectLink */ NULL,
606         /* foreachIDLink */     NULL,
607         /* foreachTexLink */    NULL,
608 };