remove double promotions and some formatting edits (tabs & spaces mixed)
[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 #include "MEM_guardedalloc.h"
29
30 #include "DNA_customdata_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_meshdata_types.h"
33 #include "DNA_modifier_types.h"
34 #include "DNA_scene_types.h"
35
36 #include "BKE_cdderivedmesh.h"
37 #include "BKE_modifier.h"
38 #include "BKE_ocean.h"
39 #include "BKE_utildefines.h"
40
41 #include "BLI_math.h"
42 #include "BLI_math_inline.h"
43 #include "BLI_utildefines.h"
44 #include "BLI_string.h"
45
46 #include "MOD_util.h"
47
48 #ifdef WITH_OCEANSIM
49 static void init_cache_data(struct OceanModifierData *omd)
50 {
51         omd->oceancache = BKE_init_ocean_cache(omd->cachepath, omd->bakestart, omd->bakeend, omd->wave_scale,
52                                                                                    omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
53 }
54
55 static void clear_cache_data(struct OceanModifierData *omd)
56 {
57         BKE_free_ocean_cache(omd->oceancache);
58         omd->oceancache = NULL;
59         omd->cached = FALSE;
60 }
61
62 /* keep in sync with init_ocean_modifier_bake(), object_modifier.c */
63 static void init_ocean_modifier(struct OceanModifierData *omd)
64 {
65         int do_heightfield, do_chop, do_normals, do_jacobian;
66
67         if (!omd || !omd->ocean) return;
68
69         do_heightfield = TRUE;
70         do_chop = (omd->chop_amount > 0);
71         do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
72         do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
73
74         BKE_free_ocean_data(omd->ocean);
75         BKE_init_ocean(omd->ocean, omd->resolution*omd->resolution, omd->resolution*omd->resolution, omd->spatial_size, omd->spatial_size,
76                                    omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
77                                    omd->depth, omd->time,
78                                    do_heightfield, do_chop, do_normals, do_jacobian,
79                                    omd->seed);
80 }
81
82 static void simulate_ocean_modifier(struct OceanModifierData *omd)
83 {
84         if (!omd || !omd->ocean) return;
85
86         BKE_simulate_ocean(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount);
87 }
88 #endif // WITH_OCEANSIM
89
90
91
92 /* Modifier Code */
93
94 static void initData(ModifierData *md)
95 {
96 #ifdef WITH_OCEANSIM
97         OceanModifierData *omd = (OceanModifierData*) md;
98
99         omd->resolution = 7;
100         omd->spatial_size = 50;
101
102         omd->wave_alignment = 0.0;
103         omd->wind_velocity = 30.0;
104
105         omd->damp = 0.5;
106         omd->smallest_wave = 0.01;
107         omd->wave_direction= 0.0;
108         omd->depth = 200.0;
109
110         omd->wave_scale = 1.0;
111
112         omd->chop_amount = 1.0;
113
114         omd->foam_coverage = 0.0;
115
116         omd->seed = 0;
117         omd->time = 1.0;
118
119         omd->refresh = 0;
120
121         omd->size = 1.0;
122         omd->repeat_x = 1;
123         omd->repeat_y = 1;
124
125         BLI_strncpy(omd->cachepath, "//ocean_cache", sizeof(omd->cachepath));
126
127         omd->cached = 0;
128         omd->bakestart = 1;
129         omd->bakeend = 250;
130         omd->oceancache = NULL;
131         omd->foam_fade = 0.98;
132
133         omd->ocean = BKE_add_ocean();
134         init_ocean_modifier(omd);
135         simulate_ocean_modifier(omd);
136 #else  // WITH_OCEANSIM
137         /* unused */
138         (void)md;
139 #endif // WITH_OCEANSIM
140 }
141
142 static void freeData(ModifierData *md)
143 {
144 #ifdef WITH_OCEANSIM
145         OceanModifierData *omd = (OceanModifierData*) md;
146
147         BKE_free_ocean(omd->ocean);
148         if (omd->oceancache)
149                 BKE_free_ocean_cache(omd->oceancache);
150 #else // WITH_OCEANSIM
151         /* unused */
152         (void)md;
153 #endif // WITH_OCEANSIM
154 }
155
156 static void copyData(ModifierData *md, ModifierData *target)
157 {
158 #ifdef WITH_OCEANSIM
159         OceanModifierData *omd = (OceanModifierData*) md;
160         OceanModifierData *tomd = (OceanModifierData*) target;
161
162         tomd->resolution = omd->resolution;
163         tomd->spatial_size = omd->spatial_size;
164
165         tomd->wind_velocity = omd->wind_velocity;
166
167         tomd->damp = omd->damp;
168         tomd->smallest_wave = omd->smallest_wave;
169         tomd->depth = omd->depth;
170
171         tomd->wave_alignment = omd->wave_alignment;
172         tomd->wave_direction = omd->wave_direction;
173         tomd->wave_scale = omd->wave_scale;
174
175         tomd->chop_amount = omd->chop_amount;
176         tomd->foam_coverage = omd->foam_coverage;
177         tomd->time = omd->time;
178
179         tomd->seed = omd->seed;
180         tomd->flag = omd->flag;
181         tomd->output = omd->output;
182
183         tomd->refresh = 0;
184
185
186         tomd->size = omd->size;
187         tomd->repeat_x = omd->repeat_x;
188         tomd->repeat_y = omd->repeat_y;
189
190         /* XXX todo: copy cache runtime too */
191         tomd->cached = 0;
192         tomd->bakestart = omd->bakestart;
193         tomd->bakeend = omd->bakeend;
194         tomd->oceancache = NULL;
195
196         tomd->ocean = BKE_add_ocean();
197         init_ocean_modifier(tomd);
198         simulate_ocean_modifier(tomd);
199 #else // WITH_OCEANSIM
200         /* unused */
201         (void)md;
202         (void)target;
203 #endif // WITH_OCEANSIM
204 }
205
206 #ifdef WITH_OCEANSIM
207 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
208 {
209         OceanModifierData *omd = (OceanModifierData *)md;
210         CustomDataMask dataMask = 0;
211
212         if (omd->flag & MOD_OCEAN_GENERATE_FOAM)
213                 dataMask |= CD_MASK_MCOL;
214
215         return dataMask;
216 }
217 #else // WITH_OCEANSIM
218 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
219 {
220         /* unused */
221         (void)md;
222         return 0;
223 }
224 #endif // WITH_OCEANSIM
225
226 #if 0
227 static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, float *oy)
228 {
229         /* get bounding box of underlying dm */
230         int v, totvert=dm->getNumVerts(dm);
231         float min[3], max[3], delta[3];
232
233         MVert *mvert = dm->getVertDataArray(dm,0);
234
235         copy_v3_v3(min, mvert->co);
236         copy_v3_v3(max, mvert->co);
237
238         for(v=1; v<totvert; v++, mvert++) {
239                 min[0]=MIN2(min[0],mvert->co[0]);
240                 min[1]=MIN2(min[1],mvert->co[1]);
241                 min[2]=MIN2(min[2],mvert->co[2]);
242
243                 max[0]=MAX2(max[0],mvert->co[0]);
244                 max[1]=MAX2(max[1],mvert->co[1]);
245                 max[2]=MAX2(max[2],mvert->co[2]);
246         }
247
248         sub_v3_v3v3(delta, max, min);
249
250         *sx = delta[0];
251         *sy = delta[1];
252
253         *ox = min[0];
254         *oy = min[1];
255 }
256 #endif
257
258 #ifdef WITH_OCEANSIM
259 MINLINE float ocean_co(OceanModifierData *omd, float v)
260 {
261         //float scale = 1.0 / (omd->size * omd->spatial_size);
262         //*v = (*v * scale) + 0.5;
263
264         return (v / (omd->size * omd->spatial_size)) + 0.5f;
265 }
266
267 #define OMP_MIN_RES     18
268 static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
269 {
270         DerivedMesh *result;
271
272         MVert *mv;
273         MFace *mf;
274         MTFace *tf;
275
276         int cdlayer;
277
278         const int rx = omd->resolution*omd->resolution;
279         const int ry = omd->resolution*omd->resolution;
280         const int res_x = rx * omd->repeat_x;
281         const int res_y = ry * omd->repeat_y;
282
283         const int num_verts = (res_x + 1) * (res_y + 1);
284         const int num_edges = (res_x * res_y * 2) + res_x + res_y;
285         const int num_faces = res_x * res_y;
286
287         float sx = omd->size * omd->spatial_size;
288         float sy = omd->size * omd->spatial_size;
289         const float ox = -sx / 2.0f;
290         const float oy = -sy / 2.0f;
291
292         float ix, iy;
293
294         int x, y;
295
296         sx /= rx;
297         sy /= ry;
298
299         result = CDDM_new(num_verts, num_edges, num_faces);
300
301         mv = CDDM_get_verts(result);
302         mf = CDDM_get_faces(result);
303
304         /* create vertices */
305         #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
306         for (y=0; y < res_y+1; y++) {
307                 for (x=0; x < res_x+1; x++) {
308                         const int i = y*(res_x+1) + x;
309                         mv[i].co[0] = ox + (x * sx);
310                         mv[i].co[1] = oy + (y * sy);
311                         mv[i].co[2] = 0;
312                 }
313         }
314
315         /* create faces */
316         #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
317         for (y=0; y < res_y; y++) {
318                 for (x=0; x < res_x; x++) {
319                         const int fi = y*res_x + x;
320                         const int vi = y*(res_x+1) + x;
321                         mf[fi].v1 = vi;
322                         mf[fi].v2 = vi + 1;
323                         mf[fi].v3 = vi + 1 + res_x+1;
324                         mf[fi].v4 = vi + res_x+1;
325
326                         mf[fi].flag |= ME_SMOOTH;
327                 }
328         }
329
330         CDDM_calc_edges(result);
331
332         /* add uvs */
333         cdlayer= CustomData_number_of_layers(&result->faceData, CD_MTFACE);
334         if(cdlayer >= MAX_MTFACE)
335                 return result;
336         CustomData_add_layer(&result->faceData, CD_MTFACE, CD_CALLOC, NULL, num_faces);
337         tf = CustomData_get_layer(&result->faceData, CD_MTFACE);
338
339         ix = 1.0 / rx;
340         iy = 1.0 / ry;
341         #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
342         for (y=0; y < res_y; y++) {
343                 for (x=0; x < res_x; x++) {
344                         const int i = y*res_x + x;
345                         tf[i].uv[0][0] = x * ix;
346                         tf[i].uv[0][1] = y * iy;
347
348                         tf[i].uv[1][0] = (x+1) * ix;
349                         tf[i].uv[1][1] = y * iy;
350
351                         tf[i].uv[2][0] = (x+1) * ix;
352                         tf[i].uv[2][1] = (y+1) * iy;
353
354                         tf[i].uv[3][0] = x * ix;
355                         tf[i].uv[3][1] = (y+1) * iy;
356                 }
357         }
358
359         return result;
360 }
361
362 static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
363                                                           DerivedMesh *derivedData,
364                                                           int UNUSED(useRenderParams))
365 {
366         OceanModifierData *omd = (OceanModifierData*) md;
367
368         DerivedMesh *dm=NULL;
369         OceanResult ocr;
370
371         MVert *mv;
372         MFace *mf;
373
374         int cdlayer;
375
376         int i, j;
377
378         int num_verts;
379         int num_faces;
380
381         int cfra;
382
383         /* update modifier */
384         if (omd->refresh & MOD_OCEAN_REFRESH_ADD)
385                 omd->ocean = BKE_add_ocean();
386         if (omd->refresh & MOD_OCEAN_REFRESH_RESET)
387                 init_ocean_modifier(omd);
388         if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE)
389                 clear_cache_data(omd);
390
391         omd->refresh = 0;
392
393         /* do ocean simulation */
394         if (omd->cached == TRUE) {
395                 if (!omd->oceancache) init_cache_data(omd);
396                 BKE_simulate_ocean_cache(omd->oceancache, md->scene->r.cfra);
397         } else {
398                 simulate_ocean_modifier(omd);
399         }
400
401         if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE)
402                 dm = generate_ocean_geometry(omd);
403         else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
404                 dm = CDDM_copy(derivedData);
405         }
406
407         cfra = md->scene->r.cfra;
408         CLAMP(cfra, omd->bakestart, omd->bakeend);
409         cfra -= omd->bakestart; // shift to 0 based
410
411         num_verts = dm->getNumVerts(dm);
412         num_faces = dm->getNumFaces(dm);
413
414         /* add vcols before displacement - allows lookup based on position */
415
416         if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
417                 MCol *mc;
418                 float foam;
419                 char cf;
420
421                 float u=0.0, v=0.0;
422
423                 cdlayer= CustomData_number_of_layers(&dm->faceData, CD_MCOL);
424                 if(cdlayer >= MAX_MCOL)
425                         return dm;
426
427                 CustomData_add_layer(&dm->faceData, CD_MCOL, CD_CALLOC, NULL, num_faces);
428
429                 mc = dm->getFaceDataArray(dm, CD_MCOL);
430                 mv = dm->getVertArray(dm);
431                 mf = dm->getFaceArray(dm);
432
433                 for (i = 0; i < num_faces; i++, mf++) {
434                         for (j=0; j<4; j++) {
435
436                                 if (j == 3 && !mf->v4) continue;
437
438                                 switch(j) {
439                                         case 0:
440                                                 u = ocean_co(omd, mv[mf->v1].co[0]);
441                                                 v = ocean_co(omd, mv[mf->v1].co[1]);
442                                                 break;
443                                         case 1:
444                                                 u = ocean_co(omd, mv[mf->v2].co[0]);
445                                                 v = ocean_co(omd, mv[mf->v2].co[1]);
446                                                 break;
447                                         case 2:
448                                                 u = ocean_co(omd, mv[mf->v3].co[0]);
449                                                 v = ocean_co(omd, mv[mf->v3].co[1]);
450                                                 break;
451                                         case 3:
452                                                 u = ocean_co(omd, mv[mf->v4].co[0]);
453                                                 v = ocean_co(omd, mv[mf->v4].co[1]);
454
455                                                 break;
456                                 }
457
458                                 if (omd->oceancache && omd->cached==TRUE) {
459                                         BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
460                                         foam = ocr.foam;
461                                         CLAMP(foam, 0.0f, 1.0f);
462                                 } else {
463                                         BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
464                                         foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
465                                 }
466
467                                 cf = (char)(foam*255);
468                                 mc[i*4 + j].r = mc[i*4 + j].g = mc[i*4 + j].b = cf;
469                                 mc[i*4 + j].a = 255;
470                         }
471                 }
472         }
473
474
475         /* displace the geometry */
476
477         mv = dm->getVertArray(dm);
478
479         //#pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES)
480         for (i=0; i< num_verts; i++) {
481                 const float u = ocean_co(omd, mv[i].co[0]);
482                 const float v = ocean_co(omd, mv[i].co[1]);
483
484                 if (omd->oceancache && omd->cached==TRUE)
485                         BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
486                 else
487                         BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
488
489                 mv[i].co[2] += ocr.disp[1];
490
491                 if (omd->chop_amount > 0.0f) {
492                         mv[i].co[0] += ocr.disp[0];
493                         mv[i].co[1] += ocr.disp[2];
494                 }
495         }
496
497
498         return dm;
499 }
500 #else  // WITH_OCEANSIM
501 static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
502                                                           DerivedMesh *derivedData,
503                                                           int UNUSED(useRenderParams))
504 {
505         /* unused */
506         (void)md;
507         return derivedData;
508 }
509 #endif // WITH_OCEANSIM
510
511 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
512                                                                   DerivedMesh *derivedData,
513                                                                   int UNUSED(useRenderParams),
514                                                                   int UNUSED(isFinalCalc))
515 {
516         DerivedMesh *result;
517
518         result = doOcean(md, ob, derivedData, 0);
519
520         if(result != derivedData)
521                 CDDM_calc_normals(result);
522
523         return result;
524 }
525
526 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
527                                                                         struct EditMesh *UNUSED(editData),
528                                                                         DerivedMesh *derivedData)
529 {
530         return applyModifier(md, ob, derivedData, 0, 1);
531 }
532
533
534
535 ModifierTypeInfo modifierType_Ocean = {
536         /* name */              "Ocean",
537         /* structName */        "OceanModifierData",
538         /* structSize */        sizeof(OceanModifierData),
539         /* type */              eModifierTypeType_Constructive,
540         /* flags */             eModifierTypeFlag_AcceptsMesh
541                                                         | eModifierTypeFlag_SupportsEditmode
542                                                         | eModifierTypeFlag_EnableInEditmode,
543
544         /* copyData */          copyData,
545         /* deformMatrices */    0,
546         /* deformVerts */       0,
547         /* deformVertsEM */     0,
548         /* deformMatricesEM */  0,
549         /* applyModifier */     applyModifier,
550         /* applyModifierEM */   applyModifierEM,
551         /* initData */          initData,
552         /* requiredDataMask */  requiredDataMask,
553         /* freeData */          freeData,
554         /* isDisabled */        0,
555         /* updateDepgraph */    0,
556         /* dependsOnTime */     0,
557         /* dependsOnNormals */  0,
558         /* foreachObjectLink */ 0,
559         /* foreachIDLink */     0,
560 };