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