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_global.h"
45 #include "BKE_main.h"
46 #include "BKE_modifier.h"
47 #include "BKE_ocean.h"
48
49 #include "MOD_modifiertypes.h"
50
51 #ifdef WITH_OCEANSIM
52 static void init_cache_data(Object *ob, struct OceanModifierData *omd)
53 {
54         const char *relbase = modifier_path_relbase_from_global(ob);
55
56         omd->oceancache = BKE_ocean_init_cache(omd->cachepath, relbase,
57                                                omd->bakestart, omd->bakeend, omd->wave_scale,
58                                                omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
59 }
60
61 static void clear_cache_data(struct OceanModifierData *omd)
62 {
63         BKE_ocean_free_cache(omd->oceancache);
64         omd->oceancache = NULL;
65         omd->cached = false;
66 }
67
68 /* keep in sync with init_ocean_modifier_bake(), object_modifier.c */
69 static void init_ocean_modifier(struct OceanModifierData *omd)
70 {
71         int do_heightfield, do_chop, do_normals, do_jacobian;
72
73         if (!omd || !omd->ocean) return;
74
75         do_heightfield = true;
76         do_chop = (omd->chop_amount > 0);
77         do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
78         do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
79
80         BKE_ocean_free_data(omd->ocean);
81         BKE_ocean_init(omd->ocean, omd->resolution * omd->resolution, omd->resolution * omd->resolution,
82                        omd->spatial_size, omd->spatial_size,
83                        omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
84                        omd->depth, omd->time,
85                        do_heightfield, do_chop, do_normals, do_jacobian,
86                        omd->seed);
87 }
88
89 static void simulate_ocean_modifier(struct OceanModifierData *omd)
90 {
91         if (!omd || !omd->ocean) return;
92
93         BKE_ocean_simulate(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount);
94 }
95 #endif /* WITH_OCEANSIM */
96
97
98
99 /* Modifier Code */
100
101 static void initData(ModifierData *md)
102 {
103 #ifdef WITH_OCEANSIM
104         OceanModifierData *omd = (OceanModifierData *) md;
105
106         omd->resolution = 7;
107         omd->spatial_size = 50;
108
109         omd->wave_alignment = 0.0;
110         omd->wind_velocity = 30.0;
111
112         omd->damp = 0.5;
113         omd->smallest_wave = 0.01;
114         omd->wave_direction = 0.0;
115         omd->depth = 200.0;
116
117         omd->wave_scale = 1.0;
118
119         omd->chop_amount = 1.0;
120
121         omd->foam_coverage = 0.0;
122
123         omd->seed = 0;
124         omd->time = 1.0;
125
126         omd->refresh = 0;
127
128         omd->size = 1.0;
129         omd->repeat_x = 1;
130         omd->repeat_y = 1;
131
132         modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean");
133
134         omd->cached = 0;
135         omd->bakestart = 1;
136         omd->bakeend = 250;
137         omd->oceancache = NULL;
138         omd->foam_fade = 0.98;
139         omd->foamlayername[0] = '\0';   /* layer name empty by default */
140
141         omd->ocean = BKE_ocean_add();
142         init_ocean_modifier(omd);
143         simulate_ocean_modifier(omd);
144 #else  /* WITH_OCEANSIM */
145            /* unused */
146         (void)md;
147 #endif /* WITH_OCEANSIM */
148 }
149
150 static void freeData(ModifierData *md)
151 {
152 #ifdef WITH_OCEANSIM
153         OceanModifierData *omd = (OceanModifierData *) md;
154
155         BKE_ocean_free(omd->ocean);
156         if (omd->oceancache)
157                 BKE_ocean_free_cache(omd->oceancache);
158 #else /* WITH_OCEANSIM */
159         /* unused */
160         (void)md;
161 #endif /* WITH_OCEANSIM */
162 }
163
164 static void copyData(const ModifierData *md, ModifierData *target)
165 {
166 #ifdef WITH_OCEANSIM
167 #if 0
168         const OceanModifierData *omd = (const OceanModifierData *) md;
169 #endif
170         OceanModifierData *tomd = (OceanModifierData *) 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(
409         ModifierData *md, Object *ob,
410         DerivedMesh *derivedData,
411         int UNUSED(useRenderParams))
412 {
413         OceanModifierData *omd = (OceanModifierData *) md;
414
415         DerivedMesh *dm = NULL;
416         OceanResult ocr;
417
418         MVert *mverts;
419
420         int cfra;
421         int i, j;
422
423         /* use cached & inverted value for speed
424          * expanded this would read...
425          *
426          * (axis / (omd->size * omd->spatial_size)) + 0.5f) */
427 #define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f)
428
429         const float size_co_inv = 1.0f / (omd->size * omd->spatial_size);
430
431         /* can happen in when size is small, avoid bad array lookups later and quit now */
432         if (!isfinite(size_co_inv)) {
433                 return derivedData;
434         }
435
436         /* update modifier */
437         if (omd->refresh & MOD_OCEAN_REFRESH_ADD) {
438                 omd->ocean = BKE_ocean_add();
439         }
440         if (omd->refresh & MOD_OCEAN_REFRESH_RESET) {
441                 init_ocean_modifier(omd);
442         }
443         if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) {
444                 clear_cache_data(omd);
445         }
446         omd->refresh = 0;
447
448         /* do ocean simulation */
449         if (omd->cached == true) {
450                 if (!omd->oceancache) {
451                         init_cache_data(ob, omd);
452                 }
453                 BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra);
454         }
455         else {
456                 simulate_ocean_modifier(omd);
457         }
458
459         if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) {
460                 dm = generate_ocean_geometry(omd);
461                 DM_ensure_normals(dm);
462         }
463         else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
464                 dm = CDDM_copy(derivedData);
465         }
466
467         cfra = md->scene->r.cfra;
468         CLAMP(cfra, omd->bakestart, omd->bakeend);
469         cfra -= omd->bakestart; /* shift to 0 based */
470
471         mverts = dm->getVertArray(dm);
472
473         /* add vcols before displacement - allows lookup based on position */
474
475         if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
476                 if (CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL) < MAX_MCOL) {
477                         const int num_polys = dm->getNumPolys(dm);
478                         const int num_loops = dm->getNumLoops(dm);
479                         MLoop *mloops = dm->getLoopArray(dm);
480                         MLoopCol *mloopcols = CustomData_add_layer_named(
481                                                   &dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->foamlayername);
482
483                         if (mloopcols) { /* unlikely to fail */
484                                 MPoly *mpolys = dm->getPolyArray(dm);
485                                 MPoly *mp;
486
487                                 for (i = 0, mp = mpolys; i < num_polys; i++, mp++) {
488                                         MLoop *ml = &mloops[mp->loopstart];
489                                         MLoopCol *mlcol = &mloopcols[mp->loopstart];
490
491                                         for (j = mp->totloop; j--; ml++, mlcol++) {
492                                                 const float *vco = mverts[ml->v].co;
493                                                 const float u = OCEAN_CO(size_co_inv, vco[0]);
494                                                 const float v = OCEAN_CO(size_co_inv, vco[1]);
495                                                 float foam;
496
497                                                 if (omd->oceancache && omd->cached == true) {
498                                                         BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
499                                                         foam = ocr.foam;
500                                                         CLAMP(foam, 0.0f, 1.0f);
501                                                 }
502                                                 else {
503                                                         BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
504                                                         foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
505                                                 }
506
507                                                 mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
508                                                 /* This needs to be set (render engine uses) */
509                                                 mlcol->a = 255;
510                                         }
511                                 }
512                         }
513                 }
514         }
515
516
517         /* displace the geometry */
518
519         /* Note: tried to parallelized that one and previous foam loop, but gives 20% slower results... odd. */
520         {
521                 const int num_verts = dm->getNumVerts(dm);
522
523                 for (i = 0; i < num_verts; i++) {
524                         float *vco = mverts[i].co;
525                         const float u = OCEAN_CO(size_co_inv, vco[0]);
526                         const float v = OCEAN_CO(size_co_inv, vco[1]);
527
528                         if (omd->oceancache && omd->cached == true) {
529                                 BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
530                         }
531                         else {
532                                 BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
533                         }
534
535                         vco[2] += ocr.disp[1];
536
537                         if (omd->chop_amount > 0.0f) {
538                                 vco[0] += ocr.disp[0];
539                                 vco[1] += ocr.disp[2];
540                         }
541                 }
542         }
543
544 #undef OCEAN_CO
545
546         return dm;
547 }
548 #else  /* WITH_OCEANSIM */
549 static DerivedMesh *doOcean(
550         ModifierData *md, Object *UNUSED(ob),
551         DerivedMesh *derivedData,
552         int UNUSED(useRenderParams))
553 {
554         /* unused */
555         (void)md;
556         return derivedData;
557 }
558 #endif /* WITH_OCEANSIM */
559
560 static DerivedMesh *applyModifier(
561         ModifierData *md, const ModifierEvalContext *ctx,
562         DerivedMesh *derivedData)
563 {
564         DerivedMesh *result;
565
566         result = doOcean(md, ctx->object, derivedData, 0);
567
568         if (result != derivedData)
569                 result->dirty |= DM_DIRTY_NORMALS;
570
571         return result;
572 }
573
574
575 ModifierTypeInfo modifierType_Ocean = {
576         /* name */              "Ocean",
577         /* structName */        "OceanModifierData",
578         /* structSize */        sizeof(OceanModifierData),
579         /* type */              eModifierTypeType_Constructive,
580         /* flags */             eModifierTypeFlag_AcceptsMesh |
581                                 eModifierTypeFlag_SupportsEditmode |
582                                 eModifierTypeFlag_EnableInEditmode,
583
584         /* copyData */          copyData,
585         /* deformMatrices_DM */ NULL,
586
587         /* deformVerts_DM */    NULL,
588         /* deformVertsEM_DM */  NULL,
589         /* deformMatricesEM_DM*/NULL,
590         /* applyModifier_DM */  applyModifier,
591         /* applyModifierEM_DM */NULL,
592
593         /* deformVerts */       NULL,
594         /* deformMatrices */    NULL,
595         /* deformVertsEM */     NULL,
596         /* deformMatricesEM */  NULL,
597         /* applyModifier */     NULL,
598         /* applyModifierEM */   NULL,
599
600         /* initData */          initData,
601         /* requiredDataMask */  requiredDataMask,
602         /* freeData */          freeData,
603         /* isDisabled */        NULL,
604         /* updateDepsgraph */   NULL,
605         /* dependsOnTime */     NULL,
606         /* dependsOnNormals */  dependsOnNormals,
607         /* foreachObjectLink */ NULL,
608         /* foreachIDLink */     NULL,
609         /* foreachTexLink */    NULL,
610 };