1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  *
19  * Based on original code by Drew Whitehouse / Houdini Ocean Toolkit
20  * OpenMP hints by Christian Schnellhammer
21  */
22 
23 /** \file
24  * \ingroup bke
25  */
26 
27 #include <math.h>
28 #include <stdlib.h>
29 
30 #include <string.h>
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "DNA_modifier_types.h"
35 #include "DNA_scene_types.h"
36 
37 #include "BLI_math.h"
38 #include "BLI_path_util.h"
39 #include "BLI_rand.h"
40 #include "BLI_task.h"
41 #include "BLI_utildefines.h"
42 
43 #include "BKE_image.h"
44 #include "BKE_ocean.h"
45 #include "ocean_intern.h"
46 
47 #include "IMB_imbuf.h"
48 #include "IMB_imbuf_types.h"
49 
50 #include "RE_render_ext.h"
51 
52 #include "BLI_hash.h"
53 
54 #ifdef WITH_OCEANSIM
55 
56 /* Ocean code */
57 
nextfr(RNG * rng,float min,float max)58 static float nextfr(RNG *rng, float min, float max)
59 {
60   return BLI_rng_get_float(rng) * (min - max) + max;
61 }
62 
gaussRand(RNG * rng)63 static float gaussRand(RNG *rng)
64 {
65   /* Note: to avoid numerical problems with very small numbers, we make these variables
66    * singe-precision floats, but later we call the double-precision log() and sqrt() functions
67    * instead of logf() and sqrtf(). */
68   float x;
69   float y;
70   float length2;
71 
72   do {
73     x = (float)(nextfr(rng, -1, 1));
74     y = (float)(nextfr(rng, -1, 1));
75     length2 = x * x + y * y;
76   } while (length2 >= 1 || length2 == 0);
77 
78   return x * sqrtf(-2.0f * logf(length2) / length2);
79 }
80 
81 /**
82  * Some useful functions
83  */
catrom(float p0,float p1,float p2,float p3,float f)84 MINLINE float catrom(float p0, float p1, float p2, float p3, float f)
85 {
86   return 0.5f * ((2.0f * p1) + (-p0 + p2) * f + (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * f * f +
87                  (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * f * f * f);
88 }
89 
omega(float k,float depth)90 MINLINE float omega(float k, float depth)
91 {
92   return sqrtf(GRAVITY * k * tanhf(k * depth));
93 }
94 
95 /* modified Phillips spectrum */
Ph(struct Ocean * o,float kx,float kz)96 static float Ph(struct Ocean *o, float kx, float kz)
97 {
98   float tmp;
99   float k2 = kx * kx + kz * kz;
100 
101   if (k2 == 0.0f) {
102     return 0.0f; /* no DC component */
103   }
104 
105   /* damp out the waves going in the direction opposite the wind */
106   tmp = (o->_wx * kx + o->_wz * kz) / sqrtf(k2);
107   if (tmp < 0) {
108     tmp *= o->_damp_reflections;
109   }
110 
111   return o->_A * expf(-1.0f / (k2 * (o->_L * o->_L))) * expf(-k2 * (o->_l * o->_l)) *
112          powf(fabsf(tmp), o->_wind_alignment) / (k2 * k2);
113 }
114 
compute_eigenstuff(struct OceanResult * ocr,float jxx,float jzz,float jxz)115 static void compute_eigenstuff(struct OceanResult *ocr, float jxx, float jzz, float jxz)
116 {
117   float a, b, qplus, qminus;
118   a = jxx + jzz;
119   b = sqrt((jxx - jzz) * (jxx - jzz) + 4 * jxz * jxz);
120 
121   ocr->Jminus = 0.5f * (a - b);
122   ocr->Jplus = 0.5f * (a + b);
123 
124   qplus = (ocr->Jplus - jxx) / jxz;
125   qminus = (ocr->Jminus - jxx) / jxz;
126 
127   a = sqrt(1 + qplus * qplus);
128   b = sqrt(1 + qminus * qminus);
129 
130   ocr->Eplus[0] = 1.0f / a;
131   ocr->Eplus[1] = 0.0f;
132   ocr->Eplus[2] = qplus / a;
133 
134   ocr->Eminus[0] = 1.0f / b;
135   ocr->Eminus[1] = 0.0f;
136   ocr->Eminus[2] = qminus / b;
137 }
138 
139 /*
140  * instead of Complex.h
141  * in fftw.h "fftw_complex" typedefed as double[2]
142  * below you can see functions are needed to work with such complex numbers.
143  * */
init_complex(fftw_complex cmpl,float real,float image)144 static void init_complex(fftw_complex cmpl, float real, float image)
145 {
146   cmpl[0] = real;
147   cmpl[1] = image;
148 }
149 
add_comlex_c(fftw_complex res,const fftw_complex cmpl1,const fftw_complex cmpl2)150 static void add_comlex_c(fftw_complex res, const fftw_complex cmpl1, const fftw_complex cmpl2)
151 {
152   res[0] = cmpl1[0] + cmpl2[0];
153   res[1] = cmpl1[1] + cmpl2[1];
154 }
155 
mul_complex_f(fftw_complex res,const fftw_complex cmpl,float f)156 static void mul_complex_f(fftw_complex res, const fftw_complex cmpl, float f)
157 {
158   res[0] = cmpl[0] * (double)f;
159   res[1] = cmpl[1] * (double)f;
160 }
161 
mul_complex_c(fftw_complex res,const fftw_complex cmpl1,const fftw_complex cmpl2)162 static void mul_complex_c(fftw_complex res, const fftw_complex cmpl1, const fftw_complex cmpl2)
163 {
164   fftwf_complex temp;
165   temp[0] = cmpl1[0] * cmpl2[0] - cmpl1[1] * cmpl2[1];
166   temp[1] = cmpl1[0] * cmpl2[1] + cmpl1[1] * cmpl2[0];
167   res[0] = temp[0];
168   res[1] = temp[1];
169 }
170 
real_c(fftw_complex cmpl)171 static float real_c(fftw_complex cmpl)
172 {
173   return cmpl[0];
174 }
175 
image_c(fftw_complex cmpl)176 static float image_c(fftw_complex cmpl)
177 {
178   return cmpl[1];
179 }
180 
conj_complex(fftw_complex res,const fftw_complex cmpl1)181 static void conj_complex(fftw_complex res, const fftw_complex cmpl1)
182 {
183   res[0] = cmpl1[0];
184   res[1] = -cmpl1[1];
185 }
186 
exp_complex(fftw_complex res,fftw_complex cmpl)187 static void exp_complex(fftw_complex res, fftw_complex cmpl)
188 {
189   float r = expf(cmpl[0]);
190 
191   res[0] = cosf(cmpl[1]) * r;
192   res[1] = sinf(cmpl[1]) * r;
193 }
194 
BKE_ocean_jminus_to_foam(float jminus,float coverage)195 float BKE_ocean_jminus_to_foam(float jminus, float coverage)
196 {
197   float foam = jminus * -0.005f + coverage;
198   CLAMP(foam, 0.0f, 1.0f);
199   return foam;
200 }
201 
BKE_ocean_eval_uv(struct Ocean * oc,struct OceanResult * ocr,float u,float v)202 void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
203 {
204   int i0, i1, j0, j1;
205   float frac_x, frac_z;
206   float uu, vv;
207 
208   /* first wrap the texture so 0 <= (u, v) < 1 */
209   u = fmodf(u, 1.0f);
210   v = fmodf(v, 1.0f);
211 
212   if (u < 0) {
213     u += 1.0f;
214   }
215   if (v < 0) {
216     v += 1.0f;
217   }
218 
219   BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
220 
221   uu = u * oc->_M;
222   vv = v * oc->_N;
223 
224   i0 = (int)floor(uu);
225   j0 = (int)floor(vv);
226 
227   i1 = (i0 + 1);
228   j1 = (j0 + 1);
229 
230   frac_x = uu - i0;
231   frac_z = vv - j0;
232 
233   i0 = i0 % oc->_M;
234   j0 = j0 % oc->_N;
235 
236   i1 = i1 % oc->_M;
237   j1 = j1 % oc->_N;
238 
239 #  define BILERP(m) \
240     (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
241              interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
242              frac_z))
243 
244   {
245     if (oc->_do_disp_y) {
246       ocr->disp[1] = BILERP(oc->_disp_y);
247     }
248 
249     if (oc->_do_normals) {
250       ocr->normal[0] = BILERP(oc->_N_x);
251       ocr->normal[1] = oc->_N_y /*BILERP(oc->_N_y) (MEM01)*/;
252       ocr->normal[2] = BILERP(oc->_N_z);
253     }
254 
255     if (oc->_do_chop) {
256       ocr->disp[0] = BILERP(oc->_disp_x);
257       ocr->disp[2] = BILERP(oc->_disp_z);
258     }
259     else {
260       ocr->disp[0] = 0.0;
261       ocr->disp[2] = 0.0;
262     }
263 
264     if (oc->_do_jacobian) {
265       compute_eigenstuff(ocr, BILERP(oc->_Jxx), BILERP(oc->_Jzz), BILERP(oc->_Jxz));
266     }
267   }
268 #  undef BILERP
269 
270   BLI_rw_mutex_unlock(&oc->oceanmutex);
271 }
272 
273 /* use catmullrom interpolation rather than linear */
BKE_ocean_eval_uv_catrom(struct Ocean * oc,struct OceanResult * ocr,float u,float v)274 void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
275 {
276   int i0, i1, i2, i3, j0, j1, j2, j3;
277   float frac_x, frac_z;
278   float uu, vv;
279 
280   /* first wrap the texture so 0 <= (u, v) < 1 */
281   u = fmod(u, 1.0f);
282   v = fmod(v, 1.0f);
283 
284   if (u < 0) {
285     u += 1.0f;
286   }
287   if (v < 0) {
288     v += 1.0f;
289   }
290 
291   BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
292 
293   uu = u * oc->_M;
294   vv = v * oc->_N;
295 
296   i1 = (int)floor(uu);
297   j1 = (int)floor(vv);
298 
299   i2 = (i1 + 1);
300   j2 = (j1 + 1);
301 
302   frac_x = uu - i1;
303   frac_z = vv - j1;
304 
305   i1 = i1 % oc->_M;
306   j1 = j1 % oc->_N;
307 
308   i2 = i2 % oc->_M;
309   j2 = j2 % oc->_N;
310 
311   i0 = (i1 - 1);
312   i3 = (i2 + 1);
313   i0 = i0 < 0 ? i0 + oc->_M : i0;
314   i3 = i3 >= oc->_M ? i3 - oc->_M : i3;
315 
316   j0 = (j1 - 1);
317   j3 = (j2 + 1);
318   j0 = j0 < 0 ? j0 + oc->_N : j0;
319   j3 = j3 >= oc->_N ? j3 - oc->_N : j3;
320 
321 #  define INTERP(m) \
322     catrom(catrom(m[i0 * oc->_N + j0], \
323                   m[i1 * oc->_N + j0], \
324                   m[i2 * oc->_N + j0], \
325                   m[i3 * oc->_N + j0], \
326                   frac_x), \
327            catrom(m[i0 * oc->_N + j1], \
328                   m[i1 * oc->_N + j1], \
329                   m[i2 * oc->_N + j1], \
330                   m[i3 * oc->_N + j1], \
331                   frac_x), \
332            catrom(m[i0 * oc->_N + j2], \
333                   m[i1 * oc->_N + j2], \
334                   m[i2 * oc->_N + j2], \
335                   m[i3 * oc->_N + j2], \
336                   frac_x), \
337            catrom(m[i0 * oc->_N + j3], \
338                   m[i1 * oc->_N + j3], \
339                   m[i2 * oc->_N + j3], \
340                   m[i3 * oc->_N + j3], \
341                   frac_x), \
342            frac_z)
343 
344   {
345     if (oc->_do_disp_y) {
346       ocr->disp[1] = INTERP(oc->_disp_y);
347     }
348     if (oc->_do_normals) {
349       ocr->normal[0] = INTERP(oc->_N_x);
350       ocr->normal[1] = oc->_N_y /*INTERP(oc->_N_y) (MEM01)*/;
351       ocr->normal[2] = INTERP(oc->_N_z);
352     }
353     if (oc->_do_chop) {
354       ocr->disp[0] = INTERP(oc->_disp_x);
355       ocr->disp[2] = INTERP(oc->_disp_z);
356     }
357     else {
358       ocr->disp[0] = 0.0;
359       ocr->disp[2] = 0.0;
360     }
361 
362     if (oc->_do_jacobian) {
363       compute_eigenstuff(ocr, INTERP(oc->_Jxx), INTERP(oc->_Jzz), INTERP(oc->_Jxz));
364     }
365   }
366 #  undef INTERP
367 
368   BLI_rw_mutex_unlock(&oc->oceanmutex);
369 }
370 
BKE_ocean_eval_xz(struct Ocean * oc,struct OceanResult * ocr,float x,float z)371 void BKE_ocean_eval_xz(struct Ocean *oc, struct OceanResult *ocr, float x, float z)
372 {
373   BKE_ocean_eval_uv(oc, ocr, x / oc->_Lx, z / oc->_Lz);
374 }
375 
BKE_ocean_eval_xz_catrom(struct Ocean * oc,struct OceanResult * ocr,float x,float z)376 void BKE_ocean_eval_xz_catrom(struct Ocean *oc, struct OceanResult *ocr, float x, float z)
377 {
378   BKE_ocean_eval_uv_catrom(oc, ocr, x / oc->_Lx, z / oc->_Lz);
379 }
380 
381 /* note that this doesn't wrap properly for i, j < 0, but its not really meant for that being
382  * just a way to get the raw data out to save in some image format. */
BKE_ocean_eval_ij(struct Ocean * oc,struct OceanResult * ocr,int i,int j)383 void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
384 {
385   BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
386 
387   i = abs(i) % oc->_M;
388   j = abs(j) % oc->_N;
389 
390   ocr->disp[1] = oc->_do_disp_y ? (float)oc->_disp_y[i * oc->_N + j] : 0.0f;
391 
392   if (oc->_do_chop) {
393     ocr->disp[0] = oc->_disp_x[i * oc->_N + j];
394     ocr->disp[2] = oc->_disp_z[i * oc->_N + j];
395   }
396   else {
397     ocr->disp[0] = 0.0f;
398     ocr->disp[2] = 0.0f;
399   }
400 
401   if (oc->_do_normals) {
402     ocr->normal[0] = oc->_N_x[i * oc->_N + j];
403     ocr->normal[1] = oc->_N_y /* oc->_N_y[i * oc->_N + j] (MEM01) */;
404     ocr->normal[2] = oc->_N_z[i * oc->_N + j];
405 
406     normalize_v3(ocr->normal);
407   }
408 
409   if (oc->_do_jacobian) {
410     compute_eigenstuff(
411         ocr, oc->_Jxx[i * oc->_N + j], oc->_Jzz[i * oc->_N + j], oc->_Jxz[i * oc->_N + j]);
412   }
413 
414   BLI_rw_mutex_unlock(&oc->oceanmutex);
415 }
416 
417 typedef struct OceanSimulateData {
418   Ocean *o;
419   float t;
420   float scale;
421   float chop_amount;
422 } OceanSimulateData;
423 
ocean_compute_htilda(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))424 static void ocean_compute_htilda(void *__restrict userdata,
425                                  const int i,
426                                  const TaskParallelTLS *__restrict UNUSED(tls))
427 {
428   OceanSimulateData *osd = userdata;
429   const Ocean *o = osd->o;
430   const float scale = osd->scale;
431   const float t = osd->t;
432 
433   int j;
434 
435   /* Note the <= _N/2 here, see the FFTW documentation
436    * about the mechanics of the complex->real fft storage. */
437   for (j = 0; j <= o->_N / 2; j++) {
438     fftw_complex exp_param1;
439     fftw_complex exp_param2;
440     fftw_complex conj_param;
441 
442     init_complex(exp_param1, 0.0, omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
443     init_complex(exp_param2, 0.0, -omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
444     exp_complex(exp_param1, exp_param1);
445     exp_complex(exp_param2, exp_param2);
446     conj_complex(conj_param, o->_h0_minus[i * o->_N + j]);
447 
448     mul_complex_c(exp_param1, o->_h0[i * o->_N + j], exp_param1);
449     mul_complex_c(exp_param2, conj_param, exp_param2);
450 
451     add_comlex_c(o->_htilda[i * (1 + o->_N / 2) + j], exp_param1, exp_param2);
452     mul_complex_f(o->_fft_in[i * (1 + o->_N / 2) + j], o->_htilda[i * (1 + o->_N / 2) + j], scale);
453   }
454 }
455 
ocean_compute_displacement_y(TaskPool * __restrict pool,void * UNUSED (taskdata))456 static void ocean_compute_displacement_y(TaskPool *__restrict pool, void *UNUSED(taskdata))
457 {
458   OceanSimulateData *osd = BLI_task_pool_user_data(pool);
459   const Ocean *o = osd->o;
460 
461   fftw_execute(o->_disp_y_plan);
462 }
463 
ocean_compute_displacement_x(TaskPool * __restrict pool,void * UNUSED (taskdata))464 static void ocean_compute_displacement_x(TaskPool *__restrict pool, void *UNUSED(taskdata))
465 {
466   OceanSimulateData *osd = BLI_task_pool_user_data(pool);
467   const Ocean *o = osd->o;
468   const float scale = osd->scale;
469   const float chop_amount = osd->chop_amount;
470   int i, j;
471 
472   for (i = 0; i < o->_M; i++) {
473     for (j = 0; j <= o->_N / 2; j++) {
474       fftw_complex mul_param;
475       fftw_complex minus_i;
476 
477       init_complex(minus_i, 0.0, -1.0);
478       init_complex(mul_param, -scale, 0);
479       mul_complex_f(mul_param, mul_param, chop_amount);
480       mul_complex_c(mul_param, mul_param, minus_i);
481       mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
482       mul_complex_f(mul_param,
483                     mul_param,
484                     ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
485                          0.0f :
486                          o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
487       init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
488     }
489   }
490   fftw_execute(o->_disp_x_plan);
491 }
492 
ocean_compute_displacement_z(TaskPool * __restrict pool,void * UNUSED (taskdata))493 static void ocean_compute_displacement_z(TaskPool *__restrict pool, void *UNUSED(taskdata))
494 {
495   OceanSimulateData *osd = BLI_task_pool_user_data(pool);
496   const Ocean *o = osd->o;
497   const float scale = osd->scale;
498   const float chop_amount = osd->chop_amount;
499   int i, j;
500 
501   for (i = 0; i < o->_M; i++) {
502     for (j = 0; j <= o->_N / 2; j++) {
503       fftw_complex mul_param;
504       fftw_complex minus_i;
505 
506       init_complex(minus_i, 0.0, -1.0);
507       init_complex(mul_param, -scale, 0);
508       mul_complex_f(mul_param, mul_param, chop_amount);
509       mul_complex_c(mul_param, mul_param, minus_i);
510       mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
511       mul_complex_f(mul_param,
512                     mul_param,
513                     ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
514                          0.0f :
515                          o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
516       init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
517     }
518   }
519   fftw_execute(o->_disp_z_plan);
520 }
521 
ocean_compute_jacobian_jxx(TaskPool * __restrict pool,void * UNUSED (taskdata))522 static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, void *UNUSED(taskdata))
523 {
524   OceanSimulateData *osd = BLI_task_pool_user_data(pool);
525   const Ocean *o = osd->o;
526   const float chop_amount = osd->chop_amount;
527   int i, j;
528 
529   for (i = 0; i < o->_M; i++) {
530     for (j = 0; j <= o->_N / 2; j++) {
531       fftw_complex mul_param;
532 
533       /* init_complex(mul_param, -scale, 0); */
534       init_complex(mul_param, -1, 0);
535 
536       mul_complex_f(mul_param, mul_param, chop_amount);
537       mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
538       mul_complex_f(mul_param,
539                     mul_param,
540                     ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
541                          0.0f :
542                          o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
543       init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
544     }
545   }
546   fftw_execute(o->_Jxx_plan);
547 
548   for (i = 0; i < o->_M; i++) {
549     for (j = 0; j < o->_N; j++) {
550       o->_Jxx[i * o->_N + j] += 1.0;
551     }
552   }
553 }
554 
ocean_compute_jacobian_jzz(TaskPool * __restrict pool,void * UNUSED (taskdata))555 static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, void *UNUSED(taskdata))
556 {
557   OceanSimulateData *osd = BLI_task_pool_user_data(pool);
558   const Ocean *o = osd->o;
559   const float chop_amount = osd->chop_amount;
560   int i, j;
561 
562   for (i = 0; i < o->_M; i++) {
563     for (j = 0; j <= o->_N / 2; j++) {
564       fftw_complex mul_param;
565 
566       /* init_complex(mul_param, -scale, 0); */
567       init_complex(mul_param, -1, 0);
568 
569       mul_complex_f(mul_param, mul_param, chop_amount);
570       mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
571       mul_complex_f(mul_param,
572                     mul_param,
573                     ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
574                          0.0f :
575                          o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
576       init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
577     }
578   }
579   fftw_execute(o->_Jzz_plan);
580 
581   for (i = 0; i < o->_M; i++) {
582     for (j = 0; j < o->_N; j++) {
583       o->_Jzz[i * o->_N + j] += 1.0;
584     }
585   }
586 }
587 
ocean_compute_jacobian_jxz(TaskPool * __restrict pool,void * UNUSED (taskdata))588 static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, void *UNUSED(taskdata))
589 {
590   OceanSimulateData *osd = BLI_task_pool_user_data(pool);
591   const Ocean *o = osd->o;
592   const float chop_amount = osd->chop_amount;
593   int i, j;
594 
595   for (i = 0; i < o->_M; i++) {
596     for (j = 0; j <= o->_N / 2; j++) {
597       fftw_complex mul_param;
598 
599       /* init_complex(mul_param, -scale, 0); */
600       init_complex(mul_param, -1, 0);
601 
602       mul_complex_f(mul_param, mul_param, chop_amount);
603       mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
604       mul_complex_f(mul_param,
605                     mul_param,
606                     ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
607                          0.0f :
608                          o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
609       init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
610     }
611   }
612   fftw_execute(o->_Jxz_plan);
613 }
614 
ocean_compute_normal_x(TaskPool * __restrict pool,void * UNUSED (taskdata))615 static void ocean_compute_normal_x(TaskPool *__restrict pool, void *UNUSED(taskdata))
616 {
617   OceanSimulateData *osd = BLI_task_pool_user_data(pool);
618   const Ocean *o = osd->o;
619   int i, j;
620 
621   for (i = 0; i < o->_M; i++) {
622     for (j = 0; j <= o->_N / 2; j++) {
623       fftw_complex mul_param;
624 
625       init_complex(mul_param, 0.0, -1.0);
626       mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
627       mul_complex_f(mul_param, mul_param, o->_kx[i]);
628       init_complex(o->_fft_in_nx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
629     }
630   }
631   fftw_execute(o->_N_x_plan);
632 }
633 
ocean_compute_normal_z(TaskPool * __restrict pool,void * UNUSED (taskdata))634 static void ocean_compute_normal_z(TaskPool *__restrict pool, void *UNUSED(taskdata))
635 {
636   OceanSimulateData *osd = BLI_task_pool_user_data(pool);
637   const Ocean *o = osd->o;
638   int i, j;
639 
640   for (i = 0; i < o->_M; i++) {
641     for (j = 0; j <= o->_N / 2; j++) {
642       fftw_complex mul_param;
643 
644       init_complex(mul_param, 0.0, -1.0);
645       mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
646       mul_complex_f(mul_param, mul_param, o->_kz[i]);
647       init_complex(o->_fft_in_nz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
648     }
649   }
650   fftw_execute(o->_N_z_plan);
651 }
652 
BKE_ocean_simulate(struct Ocean * o,float t,float scale,float chop_amount)653 void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount)
654 {
655   TaskPool *pool;
656 
657   OceanSimulateData osd;
658 
659   scale *= o->normalize_factor;
660 
661   osd.o = o;
662   osd.t = t;
663   osd.scale = scale;
664   osd.chop_amount = chop_amount;
665 
666   pool = BLI_task_pool_create(&osd, TASK_PRIORITY_HIGH);
667 
668   BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
669 
670   /* Note about multi-threading here: we have to run a first set of computations (htilda one)
671    * before we can run all others, since they all depend on it.
672    * So we make a first parallelized forloop run for htilda,
673    * and then pack all other computations into a set of parallel tasks.
674    * This is not optimal in all cases,
675    * but remains reasonably simple and should be OK most of the time. */
676 
677   /* compute a new htilda */
678   TaskParallelSettings settings;
679   BLI_parallel_range_settings_defaults(&settings);
680   settings.use_threading = (o->_M > 16);
681   BLI_task_parallel_range(0, o->_M, &osd, ocean_compute_htilda, &settings);
682 
683   if (o->_do_disp_y) {
684     BLI_task_pool_push(pool, ocean_compute_displacement_y, NULL, false, NULL);
685   }
686 
687   if (o->_do_chop) {
688     BLI_task_pool_push(pool, ocean_compute_displacement_x, NULL, false, NULL);
689     BLI_task_pool_push(pool, ocean_compute_displacement_z, NULL, false, NULL);
690   }
691 
692   if (o->_do_jacobian) {
693     BLI_task_pool_push(pool, ocean_compute_jacobian_jxx, NULL, false, NULL);
694     BLI_task_pool_push(pool, ocean_compute_jacobian_jzz, NULL, false, NULL);
695     BLI_task_pool_push(pool, ocean_compute_jacobian_jxz, NULL, false, NULL);
696   }
697 
698   if (o->_do_normals) {
699     BLI_task_pool_push(pool, ocean_compute_normal_x, NULL, false, NULL);
700     BLI_task_pool_push(pool, ocean_compute_normal_z, NULL, false, NULL);
701     o->_N_y = 1.0f / scale;
702   }
703 
704   BLI_task_pool_work_and_wait(pool);
705 
706   BLI_rw_mutex_unlock(&o->oceanmutex);
707 
708   BLI_task_pool_free(pool);
709 }
710 
set_height_normalize_factor(struct Ocean * oc)711 static void set_height_normalize_factor(struct Ocean *oc)
712 {
713   float res = 1.0;
714   float max_h = 0.0;
715 
716   int i, j;
717 
718   if (!oc->_do_disp_y) {
719     return;
720   }
721 
722   oc->normalize_factor = 1.0;
723 
724   BKE_ocean_simulate(oc, 0.0, 1.0, 0);
725 
726   BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
727 
728   for (i = 0; i < oc->_M; i++) {
729     for (j = 0; j < oc->_N; j++) {
730       if (max_h < fabs(oc->_disp_y[i * oc->_N + j])) {
731         max_h = fabs(oc->_disp_y[i * oc->_N + j]);
732       }
733     }
734   }
735 
736   BLI_rw_mutex_unlock(&oc->oceanmutex);
737 
738   if (max_h == 0.0f) {
739     max_h = 0.00001f; /* just in case ... */
740   }
741 
742   res = 1.0f / (max_h);
743 
744   oc->normalize_factor = res;
745 }
746 
BKE_ocean_add(void)747 struct Ocean *BKE_ocean_add(void)
748 {
749   Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data");
750 
751   BLI_rw_mutex_init(&oc->oceanmutex);
752 
753   return oc;
754 }
755 
BKE_ocean_ensure(struct OceanModifierData * omd,const int resolution)756 bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution)
757 {
758   if (omd->ocean) {
759     /* Check that the ocean has the same resolution than we want now. */
760     if (omd->ocean->_M == resolution * resolution) {
761       return false;
762     }
763 
764     BKE_ocean_free(omd->ocean);
765   }
766 
767   omd->ocean = BKE_ocean_add();
768   BKE_ocean_init_from_modifier(omd->ocean, omd, resolution);
769   return true;
770 }
771 
BKE_ocean_init_from_modifier(struct Ocean * ocean,struct OceanModifierData const * omd,const int resolution)772 void BKE_ocean_init_from_modifier(struct Ocean *ocean,
773                                   struct OceanModifierData const *omd,
774                                   const int resolution)
775 {
776   short do_heightfield, do_chop, do_normals, do_jacobian, do_spray;
777 
778   do_heightfield = true;
779   do_chop = (omd->chop_amount > 0);
780   do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
781   do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
782   do_spray = do_jacobian && (omd->flag & MOD_OCEAN_GENERATE_SPRAY);
783 
784   BKE_ocean_free_data(ocean);
785 
786   BKE_ocean_init(ocean,
787                  resolution * resolution,
788                  resolution * resolution,
789                  omd->spatial_size,
790                  omd->spatial_size,
791                  omd->wind_velocity,
792                  omd->smallest_wave,
793                  1.0,
794                  omd->wave_direction,
795                  omd->damp,
796                  omd->wave_alignment,
797                  omd->depth,
798                  omd->time,
799                  omd->spectrum,
800                  omd->fetch_jonswap,
801                  omd->sharpen_peak_jonswap,
802                  do_heightfield,
803                  do_chop,
804                  do_spray,
805                  do_normals,
806                  do_jacobian,
807                  omd->seed);
808 }
809 
BKE_ocean_init(struct Ocean * o,int M,int N,float Lx,float Lz,float V,float l,float A,float w,float damp,float alignment,float depth,float time,int spectrum,float fetch_jonswap,float sharpen_peak_jonswap,short do_height_field,short do_chop,short do_spray,short do_normals,short do_jacobian,int seed)810 void BKE_ocean_init(struct Ocean *o,
811                     int M,
812                     int N,
813                     float Lx,
814                     float Lz,
815                     float V,
816                     float l,
817                     float A,
818                     float w,
819                     float damp,
820                     float alignment,
821                     float depth,
822                     float time,
823                     int spectrum,
824                     float fetch_jonswap,
825                     float sharpen_peak_jonswap,
826                     short do_height_field,
827                     short do_chop,
828                     short do_spray,
829                     short do_normals,
830                     short do_jacobian,
831                     int seed)
832 {
833   RNG *rng;
834   int i, j, ii;
835 
836   BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
837 
838   o->_M = M;
839   o->_N = N;
840   o->_V = V;
841   o->_l = l;
842   o->_A = A;
843   o->_w = w;
844   o->_damp_reflections = 1.0f - damp;
845   o->_wind_alignment = alignment * 10.0f;
846   o->_depth = depth;
847   o->_Lx = Lx;
848   o->_Lz = Lz;
849   o->_wx = cos(w);
850   o->_wz = -sin(w);        /* wave direction */
851   o->_L = V * V / GRAVITY; /* largest wave for a given velocity V */
852   o->time = time;
853 
854   /* Spectrum to use. */
855   o->_spectrum = spectrum;
856 
857   /* Common JONSWAP parameters. */
858   o->_fetch_jonswap = fetch_jonswap;
859   o->_sharpen_peak_jonswap = sharpen_peak_jonswap * 10.0f;
860 
861   o->_do_disp_y = do_height_field;
862   o->_do_normals = do_normals;
863   o->_do_spray = do_spray;
864   o->_do_chop = do_chop;
865   o->_do_jacobian = do_jacobian;
866 
867   o->_k = (float *)MEM_mallocN(M * (1 + N / 2) * sizeof(float), "ocean_k");
868   o->_h0 = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0");
869   o->_h0_minus = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus");
870   o->_kx = (float *)MEM_mallocN(o->_M * sizeof(float), "ocean_kx");
871   o->_kz = (float *)MEM_mallocN(o->_N * sizeof(float), "ocean_kz");
872 
873   /* make this robust in the face of erroneous usage */
874   if (o->_Lx == 0.0f) {
875     o->_Lx = 0.001f;
876   }
877 
878   if (o->_Lz == 0.0f) {
879     o->_Lz = 0.001f;
880   }
881 
882   /* the +ve components and DC */
883   for (i = 0; i <= o->_M / 2; i++) {
884     o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx;
885   }
886 
887   /* the -ve components */
888   for (i = o->_M - 1, ii = 0; i > o->_M / 2; i--, ii++) {
889     o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx;
890   }
891 
892   /* the +ve components and DC */
893   for (i = 0; i <= o->_N / 2; i++) {
894     o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz;
895   }
896 
897   /* the -ve components */
898   for (i = o->_N - 1, ii = 0; i > o->_N / 2; i--, ii++) {
899     o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz;
900   }
901 
902   /* pre-calculate the k matrix */
903   for (i = 0; i < o->_M; i++) {
904     for (j = 0; j <= o->_N / 2; j++) {
905       o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]);
906     }
907   }
908 
909   rng = BLI_rng_new(seed);
910 
911   for (i = 0; i < o->_M; i++) {
912     for (j = 0; j < o->_N; j++) {
913       /* This ensures we get a value tied to the surface location, avoiding dramatic surface
914        * change with changing resolution. */
915       int new_seed = seed + BLI_hash_int_2d(o->_kx[i] * 360.0f, o->_kz[j] * 360.0f);
916 
917       BLI_rng_seed(rng, new_seed);
918       float r1 = gaussRand(rng);
919       float r2 = gaussRand(rng);
920 
921       fftw_complex r1r2;
922       init_complex(r1r2, r1, r2);
923       switch (o->_spectrum) {
924         case MOD_OCEAN_SPECTRUM_JONSWAP:
925           mul_complex_f(o->_h0[i * o->_N + j],
926                         r1r2,
927                         (float)(sqrt(BLI_ocean_spectrum_jonswap(o, o->_kx[i], o->_kz[j]) / 2.0f)));
928           mul_complex_f(
929               o->_h0_minus[i * o->_N + j],
930               r1r2,
931               (float)(sqrt(BLI_ocean_spectrum_jonswap(o, -o->_kx[i], -o->_kz[j]) / 2.0f)));
932           break;
933         case MOD_OCEAN_SPECTRUM_TEXEL_MARSEN_ARSLOE:
934           mul_complex_f(
935               o->_h0[i * o->_N + j],
936               r1r2,
937               (float)(sqrt(BLI_ocean_spectrum_texelmarsenarsloe(o, o->_kx[i], o->_kz[j]) / 2.0f)));
938           mul_complex_f(
939               o->_h0_minus[i * o->_N + j],
940               r1r2,
941               (float)(sqrt(BLI_ocean_spectrum_texelmarsenarsloe(o, -o->_kx[i], -o->_kz[j]) /
942                            2.0f)));
943           break;
944         case MOD_OCEAN_SPECTRUM_PIERSON_MOSKOWITZ:
945           mul_complex_f(
946               o->_h0[i * o->_N + j],
947               r1r2,
948               (float)(sqrt(BLI_ocean_spectrum_piersonmoskowitz(o, o->_kx[i], o->_kz[j]) / 2.0f)));
949           mul_complex_f(
950               o->_h0_minus[i * o->_N + j],
951               r1r2,
952               (float)(sqrt(BLI_ocean_spectrum_piersonmoskowitz(o, -o->_kx[i], -o->_kz[j]) /
953                            2.0f)));
954           break;
955         default:
956           mul_complex_f(
957               o->_h0[i * o->_N + j], r1r2, (float)(sqrt(Ph(o, o->_kx[i], o->_kz[j]) / 2.0f)));
958           mul_complex_f(o->_h0_minus[i * o->_N + j],
959                         r1r2,
960                         (float)(sqrt(Ph(o, -o->_kx[i], -o->_kz[j]) / 2.0f)));
961           break;
962       }
963     }
964   }
965 
966   o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
967                                            "ocean_fft_in");
968   o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
969                                            "ocean_htilda");
970 
971   BLI_thread_lock(LOCK_FFTW);
972 
973   if (o->_do_disp_y) {
974     o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
975     o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE);
976   }
977 
978   if (o->_do_normals) {
979     o->_fft_in_nx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
980                                                 "ocean_fft_in_nx");
981     o->_fft_in_nz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
982                                                 "ocean_fft_in_nz");
983 
984     o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
985     /* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */
986     o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");
987 
988     o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE);
989     o->_N_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nz, o->_N_z, FFTW_ESTIMATE);
990   }
991 
992   if (o->_do_chop) {
993     o->_fft_in_x = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
994                                                "ocean_fft_in_x");
995     o->_fft_in_z = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
996                                                "ocean_fft_in_z");
997 
998     o->_disp_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x");
999     o->_disp_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z");
1000 
1001     o->_disp_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_x, o->_disp_x, FFTW_ESTIMATE);
1002     o->_disp_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_z, o->_disp_z, FFTW_ESTIMATE);
1003   }
1004   if (o->_do_jacobian) {
1005     o->_fft_in_jxx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
1006                                                  "ocean_fft_in_jxx");
1007     o->_fft_in_jzz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
1008                                                  "ocean_fft_in_jzz");
1009     o->_fft_in_jxz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
1010                                                  "ocean_fft_in_jxz");
1011 
1012     o->_Jxx = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx");
1013     o->_Jzz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz");
1014     o->_Jxz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz");
1015 
1016     o->_Jxx_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxx, o->_Jxx, FFTW_ESTIMATE);
1017     o->_Jzz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jzz, o->_Jzz, FFTW_ESTIMATE);
1018     o->_Jxz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxz, o->_Jxz, FFTW_ESTIMATE);
1019   }
1020 
1021   BLI_thread_unlock(LOCK_FFTW);
1022 
1023   BLI_rw_mutex_unlock(&o->oceanmutex);
1024 
1025   set_height_normalize_factor(o);
1026 
1027   BLI_rng_free(rng);
1028 }
1029 
BKE_ocean_free_data(struct Ocean * oc)1030 void BKE_ocean_free_data(struct Ocean *oc)
1031 {
1032   if (!oc) {
1033     return;
1034   }
1035 
1036   BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE);
1037 
1038   BLI_thread_lock(LOCK_FFTW);
1039 
1040   if (oc->_do_disp_y) {
1041     fftw_destroy_plan(oc->_disp_y_plan);
1042     MEM_freeN(oc->_disp_y);
1043   }
1044 
1045   if (oc->_do_normals) {
1046     MEM_freeN(oc->_fft_in_nx);
1047     MEM_freeN(oc->_fft_in_nz);
1048     fftw_destroy_plan(oc->_N_x_plan);
1049     fftw_destroy_plan(oc->_N_z_plan);
1050     MEM_freeN(oc->_N_x);
1051     /*fftwf_free(oc->_N_y); (MEM01)*/
1052     MEM_freeN(oc->_N_z);
1053   }
1054 
1055   if (oc->_do_chop) {
1056     MEM_freeN(oc->_fft_in_x);
1057     MEM_freeN(oc->_fft_in_z);
1058     fftw_destroy_plan(oc->_disp_x_plan);
1059     fftw_destroy_plan(oc->_disp_z_plan);
1060     MEM_freeN(oc->_disp_x);
1061     MEM_freeN(oc->_disp_z);
1062   }
1063 
1064   if (oc->_do_jacobian) {
1065     MEM_freeN(oc->_fft_in_jxx);
1066     MEM_freeN(oc->_fft_in_jzz);
1067     MEM_freeN(oc->_fft_in_jxz);
1068     fftw_destroy_plan(oc->_Jxx_plan);
1069     fftw_destroy_plan(oc->_Jzz_plan);
1070     fftw_destroy_plan(oc->_Jxz_plan);
1071     MEM_freeN(oc->_Jxx);
1072     MEM_freeN(oc->_Jzz);
1073     MEM_freeN(oc->_Jxz);
1074   }
1075 
1076   BLI_thread_unlock(LOCK_FFTW);
1077 
1078   if (oc->_fft_in) {
1079     MEM_freeN(oc->_fft_in);
1080   }
1081 
1082   /* check that ocean data has been initialized */
1083   if (oc->_htilda) {
1084     MEM_freeN(oc->_htilda);
1085     MEM_freeN(oc->_k);
1086     MEM_freeN(oc->_h0);
1087     MEM_freeN(oc->_h0_minus);
1088     MEM_freeN(oc->_kx);
1089     MEM_freeN(oc->_kz);
1090   }
1091 
1092   BLI_rw_mutex_unlock(&oc->oceanmutex);
1093 }
1094 
BKE_ocean_free(struct Ocean * oc)1095 void BKE_ocean_free(struct Ocean *oc)
1096 {
1097   if (!oc) {
1098     return;
1099   }
1100 
1101   BKE_ocean_free_data(oc);
1102   BLI_rw_mutex_end(&oc->oceanmutex);
1103 
1104   MEM_freeN(oc);
1105 }
1106 
1107 #  undef GRAVITY
1108 
1109 /* ********* Baking/Caching ********* */
1110 
1111 #  define CACHE_TYPE_DISPLACE 1
1112 #  define CACHE_TYPE_FOAM 2
1113 #  define CACHE_TYPE_NORMAL 3
1114 #  define CACHE_TYPE_SPRAY 4
1115 #  define CACHE_TYPE_SPRAY_INVERSE 5
1116 
cache_filename(char * string,const char * path,const char * relbase,int frame,int type)1117 static void cache_filename(
1118     char *string, const char *path, const char *relbase, int frame, int type)
1119 {
1120   char cachepath[FILE_MAX];
1121   const char *fname;
1122 
1123   switch (type) {
1124     case CACHE_TYPE_FOAM:
1125       fname = "foam_";
1126       break;
1127     case CACHE_TYPE_NORMAL:
1128       fname = "normal_";
1129       break;
1130     case CACHE_TYPE_SPRAY:
1131       fname = "spray_";
1132       break;
1133     case CACHE_TYPE_SPRAY_INVERSE:
1134       fname = "spray_inverse_";
1135       break;
1136     case CACHE_TYPE_DISPLACE:
1137     default:
1138       fname = "disp_";
1139       break;
1140   }
1141 
1142   BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname);
1143 
1144   BKE_image_path_from_imtype(
1145       string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true, "");
1146 }
1147 
1148 /* silly functions but useful to inline when the args do a lot of indirections */
rgb_to_rgba_unit_alpha(float r_rgba[4],const float rgb[3])1149 MINLINE void rgb_to_rgba_unit_alpha(float r_rgba[4], const float rgb[3])
1150 {
1151   r_rgba[0] = rgb[0];
1152   r_rgba[1] = rgb[1];
1153   r_rgba[2] = rgb[2];
1154   r_rgba[3] = 1.0f;
1155 }
value_to_rgba_unit_alpha(float r_rgba[4],const float value)1156 MINLINE void value_to_rgba_unit_alpha(float r_rgba[4], const float value)
1157 {
1158   r_rgba[0] = value;
1159   r_rgba[1] = value;
1160   r_rgba[2] = value;
1161   r_rgba[3] = 1.0f;
1162 }
1163 
BKE_ocean_free_cache(struct OceanCache * och)1164 void BKE_ocean_free_cache(struct OceanCache *och)
1165 {
1166   int i, f = 0;
1167 
1168   if (!och) {
1169     return;
1170   }
1171 
1172   if (och->ibufs_disp) {
1173     for (i = och->start, f = 0; i <= och->end; i++, f++) {
1174       if (och->ibufs_disp[f]) {
1175         IMB_freeImBuf(och->ibufs_disp[f]);
1176       }
1177     }
1178     MEM_freeN(och->ibufs_disp);
1179   }
1180 
1181   if (och->ibufs_foam) {
1182     for (i = och->start, f = 0; i <= och->end; i++, f++) {
1183       if (och->ibufs_foam[f]) {
1184         IMB_freeImBuf(och->ibufs_foam[f]);
1185       }
1186     }
1187     MEM_freeN(och->ibufs_foam);
1188   }
1189 
1190   if (och->ibufs_spray) {
1191     for (i = och->start, f = 0; i <= och->end; i++, f++) {
1192       if (och->ibufs_spray[f]) {
1193         IMB_freeImBuf(och->ibufs_spray[f]);
1194       }
1195     }
1196     MEM_freeN(och->ibufs_spray);
1197   }
1198 
1199   if (och->ibufs_spray_inverse) {
1200     for (i = och->start, f = 0; i <= och->end; i++, f++) {
1201       if (och->ibufs_spray_inverse[f]) {
1202         IMB_freeImBuf(och->ibufs_spray_inverse[f]);
1203       }
1204     }
1205     MEM_freeN(och->ibufs_spray_inverse);
1206   }
1207 
1208   if (och->ibufs_norm) {
1209     for (i = och->start, f = 0; i <= och->end; i++, f++) {
1210       if (och->ibufs_norm[f]) {
1211         IMB_freeImBuf(och->ibufs_norm[f]);
1212       }
1213     }
1214     MEM_freeN(och->ibufs_norm);
1215   }
1216 
1217   if (och->time) {
1218     MEM_freeN(och->time);
1219   }
1220   MEM_freeN(och);
1221 }
1222 
BKE_ocean_cache_eval_uv(struct OceanCache * och,struct OceanResult * ocr,int f,float u,float v)1223 void BKE_ocean_cache_eval_uv(
1224     struct OceanCache *och, struct OceanResult *ocr, int f, float u, float v)
1225 {
1226   int res_x = och->resolution_x;
1227   int res_y = och->resolution_y;
1228   float result[4];
1229 
1230   u = fmod(u, 1.0);
1231   v = fmod(v, 1.0);
1232 
1233   if (u < 0) {
1234     u += 1.0f;
1235   }
1236   if (v < 0) {
1237     v += 1.0f;
1238   }
1239 
1240   if (och->ibufs_disp[f]) {
1241     ibuf_sample(och->ibufs_disp[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
1242     copy_v3_v3(ocr->disp, result);
1243   }
1244 
1245   if (och->ibufs_foam[f]) {
1246     ibuf_sample(och->ibufs_foam[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
1247     ocr->foam = result[0];
1248   }
1249 
1250   if (och->ibufs_spray[f]) {
1251     ibuf_sample(och->ibufs_spray[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
1252     copy_v3_v3(ocr->Eplus, result);
1253   }
1254 
1255   if (och->ibufs_spray_inverse[f]) {
1256     ibuf_sample(
1257         och->ibufs_spray_inverse[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
1258     copy_v3_v3(ocr->Eminus, result);
1259   }
1260 
1261   if (och->ibufs_norm[f]) {
1262     ibuf_sample(och->ibufs_norm[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
1263     copy_v3_v3(ocr->normal, result);
1264   }
1265 }
1266 
BKE_ocean_cache_eval_ij(struct OceanCache * och,struct OceanResult * ocr,int f,int i,int j)1267 void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, int f, int i, int j)
1268 {
1269   const int res_x = och->resolution_x;
1270   const int res_y = och->resolution_y;
1271 
1272   if (i < 0) {
1273     i = -i;
1274   }
1275   if (j < 0) {
1276     j = -j;
1277   }
1278 
1279   i = i % res_x;
1280   j = j % res_y;
1281 
1282   if (och->ibufs_disp[f]) {
1283     copy_v3_v3(ocr->disp, &och->ibufs_disp[f]->rect_float[4 * (res_x * j + i)]);
1284   }
1285 
1286   if (och->ibufs_foam[f]) {
1287     ocr->foam = och->ibufs_foam[f]->rect_float[4 * (res_x * j + i)];
1288   }
1289 
1290   if (och->ibufs_spray[f]) {
1291     copy_v3_v3(ocr->Eplus, &och->ibufs_spray[f]->rect_float[4 * (res_x * j + i)]);
1292   }
1293 
1294   if (och->ibufs_spray_inverse[f]) {
1295     copy_v3_v3(ocr->Eminus, &och->ibufs_spray_inverse[f]->rect_float[4 * (res_x * j + i)]);
1296   }
1297 
1298   if (och->ibufs_norm[f]) {
1299     copy_v3_v3(ocr->normal, &och->ibufs_norm[f]->rect_float[4 * (res_x * j + i)]);
1300   }
1301 }
1302 
BKE_ocean_init_cache(const char * bakepath,const char * relbase,int start,int end,float wave_scale,float chop_amount,float foam_coverage,float foam_fade,int resolution)1303 struct OceanCache *BKE_ocean_init_cache(const char *bakepath,
1304                                         const char *relbase,
1305                                         int start,
1306                                         int end,
1307                                         float wave_scale,
1308                                         float chop_amount,
1309                                         float foam_coverage,
1310                                         float foam_fade,
1311                                         int resolution)
1312 {
1313   OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
1314 
1315   och->bakepath = bakepath;
1316   och->relbase = relbase;
1317 
1318   och->start = start;
1319   och->end = end;
1320   och->duration = (end - start) + 1;
1321   och->wave_scale = wave_scale;
1322   och->chop_amount = chop_amount;
1323   och->foam_coverage = foam_coverage;
1324   och->foam_fade = foam_fade;
1325   och->resolution_x = resolution * resolution;
1326   och->resolution_y = resolution * resolution;
1327 
1328   och->ibufs_disp = MEM_callocN(sizeof(ImBuf *) * och->duration,
1329                                 "displacement imbuf pointer array");
1330   och->ibufs_foam = MEM_callocN(sizeof(ImBuf *) * och->duration, "foam imbuf pointer array");
1331   och->ibufs_spray = MEM_callocN(sizeof(ImBuf *) * och->duration, "spray imbuf pointer array");
1332   och->ibufs_spray_inverse = MEM_callocN(sizeof(ImBuf *) * och->duration,
1333                                          "spray_inverse imbuf pointer array");
1334   och->ibufs_norm = MEM_callocN(sizeof(ImBuf *) * och->duration, "normal imbuf pointer array");
1335 
1336   och->time = NULL;
1337 
1338   return och;
1339 }
1340 
BKE_ocean_simulate_cache(struct OceanCache * och,int frame)1341 void BKE_ocean_simulate_cache(struct OceanCache *och, int frame)
1342 {
1343   char string[FILE_MAX];
1344   int f = frame;
1345 
1346   /* ibufs array is zero based, but filenames are based on frame numbers */
1347   /* still need to clamp frame numbers to valid range of images on disk though */
1348   CLAMP(frame, och->start, och->end);
1349   f = frame - och->start; /* shift to 0 based */
1350 
1351   /* if image is already loaded in mem, return */
1352   if (och->ibufs_disp[f] != NULL) {
1353     return;
1354   }
1355 
1356   /* Use default color spaces since we know for sure cache
1357    * files were saved with default settings too. */
1358 
1359   cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE);
1360   och->ibufs_disp[f] = IMB_loadiffname(string, 0, NULL);
1361 
1362   cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM);
1363   och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL);
1364 
1365   cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_SPRAY);
1366   och->ibufs_spray[f] = IMB_loadiffname(string, 0, NULL);
1367 
1368   cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_SPRAY_INVERSE);
1369   och->ibufs_spray_inverse[f] = IMB_loadiffname(string, 0, NULL);
1370 
1371   cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL);
1372   och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL);
1373 }
1374 
BKE_ocean_bake(struct Ocean * o,struct OceanCache * och,void (* update_cb)(void *,float progress,int * cancel),void * update_cb_data)1375 void BKE_ocean_bake(struct Ocean *o,
1376                     struct OceanCache *och,
1377                     void (*update_cb)(void *, float progress, int *cancel),
1378                     void *update_cb_data)
1379 {
1380   /* note: some of these values remain uninitialized unless certain options
1381    * are enabled, take care that BKE_ocean_eval_ij() initializes a member
1382    * before use - campbell */
1383   OceanResult ocr;
1384 
1385   ImageFormatData imf = {0};
1386 
1387   int f, i = 0, x, y, cancel = 0;
1388   float progress;
1389 
1390   ImBuf *ibuf_foam, *ibuf_disp, *ibuf_normal, *ibuf_spray, *ibuf_spray_inverse;
1391   float *prev_foam;
1392   int res_x = och->resolution_x;
1393   int res_y = och->resolution_y;
1394   char string[FILE_MAX];
1395   // RNG *rng;
1396 
1397   if (!o) {
1398     return;
1399   }
1400 
1401   if (o->_do_jacobian) {
1402     prev_foam = MEM_callocN(res_x * res_y * sizeof(float), "previous frame foam bake data");
1403   }
1404   else {
1405     prev_foam = NULL;
1406   }
1407 
1408   // rng = BLI_rng_new(0);
1409 
1410   /* setup image format */
1411   imf.imtype = R_IMF_IMTYPE_OPENEXR;
1412   imf.depth = R_IMF_CHAN_DEPTH_16;
1413   imf.exr_codec = R_IMF_EXR_CODEC_ZIP;
1414 
1415   for (f = och->start, i = 0; f <= och->end; f++, i++) {
1416 
1417     /* create a new imbuf to store image for this frame */
1418     ibuf_foam = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
1419     ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
1420     ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
1421     ibuf_spray = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
1422     ibuf_spray_inverse = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
1423 
1424     BKE_ocean_simulate(o, och->time[i], och->wave_scale, och->chop_amount);
1425 
1426     /* add new foam */
1427     for (y = 0; y < res_y; y++) {
1428       for (x = 0; x < res_x; x++) {
1429 
1430         BKE_ocean_eval_ij(o, &ocr, x, y);
1431 
1432         /* add to the image */
1433         rgb_to_rgba_unit_alpha(&ibuf_disp->rect_float[4 * (res_x * y + x)], ocr.disp);
1434 
1435         if (o->_do_jacobian) {
1436           /* TODO, cleanup unused code - campbell */
1437 
1438           float /*r, */ /* UNUSED */ pr = 0.0f, foam_result;
1439           float neg_disp, neg_eplus;
1440 
1441           ocr.foam = BKE_ocean_jminus_to_foam(ocr.Jminus, och->foam_coverage);
1442 
1443           /* accumulate previous value for this cell */
1444           if (i > 0) {
1445             pr = prev_foam[res_x * y + x];
1446           }
1447 
1448           /* r = BLI_rng_get_float(rng); */ /* UNUSED */ /* randomly reduce foam */
1449 
1450           /* pr = pr * och->foam_fade; */ /* overall fade */
1451 
1452           /* Remember ocean coord sys is Y up!
1453            * break up the foam where height (Y) is low (wave valley),
1454            * and X and Z displacement is greatest. */
1455 
1456           neg_disp = ocr.disp[1] < 0.0f ? 1.0f + ocr.disp[1] : 1.0f;
1457           neg_disp = neg_disp < 0.0f ? 0.0f : neg_disp;
1458 
1459           /* foam, 'ocr.Eplus' only initialized with do_jacobian */
1460           neg_eplus = ocr.Eplus[2] < 0.0f ? 1.0f + ocr.Eplus[2] : 1.0f;
1461           neg_eplus = neg_eplus < 0.0f ? 0.0f : neg_eplus;
1462 
1463           if (pr < 1.0f) {
1464             pr *= pr;
1465           }
1466 
1467           pr *= och->foam_fade * (0.75f + neg_eplus * 0.25f);
1468 
1469           /* A full clamping should not be needed! */
1470           foam_result = min_ff(pr + ocr.foam, 1.0f);
1471 
1472           prev_foam[res_x * y + x] = foam_result;
1473 
1474           /*foam_result = min_ff(foam_result, 1.0f); */
1475 
1476           value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4 * (res_x * y + x)], foam_result);
1477 
1478           /* spray map baking */
1479           if (o->_do_spray) {
1480             rgb_to_rgba_unit_alpha(&ibuf_spray->rect_float[4 * (res_x * y + x)], ocr.Eplus);
1481             rgb_to_rgba_unit_alpha(&ibuf_spray_inverse->rect_float[4 * (res_x * y + x)],
1482                                    ocr.Eminus);
1483           }
1484         }
1485 
1486         if (o->_do_normals) {
1487           rgb_to_rgba_unit_alpha(&ibuf_normal->rect_float[4 * (res_x * y + x)], ocr.normal);
1488         }
1489       }
1490     }
1491 
1492     /* write the images */
1493     cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_DISPLACE);
1494     if (0 == BKE_imbuf_write(ibuf_disp, string, &imf)) {
1495       printf("Cannot save Displacement File Output to %s\n", string);
1496     }
1497 
1498     if (o->_do_jacobian) {
1499       cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_FOAM);
1500       if (0 == BKE_imbuf_write(ibuf_foam, string, &imf)) {
1501         printf("Cannot save Foam File Output to %s\n", string);
1502       }
1503 
1504       if (o->_do_spray) {
1505         cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_SPRAY);
1506         if (0 == BKE_imbuf_write(ibuf_spray, string, &imf)) {
1507           printf("Cannot save Spray File Output to %s\n", string);
1508         }
1509 
1510         cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_SPRAY_INVERSE);
1511         if (0 == BKE_imbuf_write(ibuf_spray_inverse, string, &imf)) {
1512           printf("Cannot save Spray Inverse File Output to %s\n", string);
1513         }
1514       }
1515     }
1516 
1517     if (o->_do_normals) {
1518       cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_NORMAL);
1519       if (0 == BKE_imbuf_write(ibuf_normal, string, &imf)) {
1520         printf("Cannot save Normal File Output to %s\n", string);
1521       }
1522     }
1523 
1524     IMB_freeImBuf(ibuf_disp);
1525     IMB_freeImBuf(ibuf_foam);
1526     IMB_freeImBuf(ibuf_normal);
1527     IMB_freeImBuf(ibuf_spray);
1528     IMB_freeImBuf(ibuf_spray_inverse);
1529 
1530     progress = (f - och->start) / (float)och->duration;
1531 
1532     update_cb(update_cb_data, progress, &cancel);
1533 
1534     if (cancel) {
1535       if (prev_foam) {
1536         MEM_freeN(prev_foam);
1537       }
1538       // BLI_rng_free(rng);
1539       return;
1540     }
1541   }
1542 
1543   // BLI_rng_free(rng);
1544   if (prev_foam) {
1545     MEM_freeN(prev_foam);
1546   }
1547   och->baked = 1;
1548 }
1549 
1550 #else /* WITH_OCEANSIM */
1551 
BKE_ocean_jminus_to_foam(float UNUSED (jminus),float UNUSED (coverage))1552 float BKE_ocean_jminus_to_foam(float UNUSED(jminus), float UNUSED(coverage))
1553 {
1554   return 0.0f;
1555 }
1556 
BKE_ocean_eval_uv(struct Ocean * UNUSED (oc),struct OceanResult * UNUSED (ocr),float UNUSED (u),float UNUSED (v))1557 void BKE_ocean_eval_uv(struct Ocean *UNUSED(oc),
1558                        struct OceanResult *UNUSED(ocr),
1559                        float UNUSED(u),
1560                        float UNUSED(v))
1561 {
1562 }
1563 
1564 /* use catmullrom interpolation rather than linear */
BKE_ocean_eval_uv_catrom(struct Ocean * UNUSED (oc),struct OceanResult * UNUSED (ocr),float UNUSED (u),float UNUSED (v))1565 void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc),
1566                               struct OceanResult *UNUSED(ocr),
1567                               float UNUSED(u),
1568                               float UNUSED(v))
1569 {
1570 }
1571 
BKE_ocean_eval_xz(struct Ocean * UNUSED (oc),struct OceanResult * UNUSED (ocr),float UNUSED (x),float UNUSED (z))1572 void BKE_ocean_eval_xz(struct Ocean *UNUSED(oc),
1573                        struct OceanResult *UNUSED(ocr),
1574                        float UNUSED(x),
1575                        float UNUSED(z))
1576 {
1577 }
1578 
BKE_ocean_eval_xz_catrom(struct Ocean * UNUSED (oc),struct OceanResult * UNUSED (ocr),float UNUSED (x),float UNUSED (z))1579 void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc),
1580                               struct OceanResult *UNUSED(ocr),
1581                               float UNUSED(x),
1582                               float UNUSED(z))
1583 {
1584 }
1585 
BKE_ocean_eval_ij(struct Ocean * UNUSED (oc),struct OceanResult * UNUSED (ocr),int UNUSED (i),int UNUSED (j))1586 void BKE_ocean_eval_ij(struct Ocean *UNUSED(oc),
1587                        struct OceanResult *UNUSED(ocr),
1588                        int UNUSED(i),
1589                        int UNUSED(j))
1590 {
1591 }
1592 
BKE_ocean_simulate(struct Ocean * UNUSED (o),float UNUSED (t),float UNUSED (scale),float UNUSED (chop_amount))1593 void BKE_ocean_simulate(struct Ocean *UNUSED(o),
1594                         float UNUSED(t),
1595                         float UNUSED(scale),
1596                         float UNUSED(chop_amount))
1597 {
1598 }
1599 
BKE_ocean_add(void)1600 struct Ocean *BKE_ocean_add(void)
1601 {
1602   Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data");
1603 
1604   return oc;
1605 }
1606 
BKE_ocean_init(struct Ocean * UNUSED (o),int UNUSED (M),int UNUSED (N),float UNUSED (Lx),float UNUSED (Lz),float UNUSED (V),float UNUSED (l),float UNUSED (A),float UNUSED (w),float UNUSED (damp),float UNUSED (alignment),float UNUSED (depth),float UNUSED (time),int UNUSED (spectrum),float UNUSED (fetch_jonswap),float UNUSED (sharpen_peak_jonswap),short UNUSED (do_height_field),short UNUSED (do_chop),short UNUSED (do_spray),short UNUSED (do_normals),short UNUSED (do_jacobian),int UNUSED (seed))1607 void BKE_ocean_init(struct Ocean *UNUSED(o),
1608                     int UNUSED(M),
1609                     int UNUSED(N),
1610                     float UNUSED(Lx),
1611                     float UNUSED(Lz),
1612                     float UNUSED(V),
1613                     float UNUSED(l),
1614                     float UNUSED(A),
1615                     float UNUSED(w),
1616                     float UNUSED(damp),
1617                     float UNUSED(alignment),
1618                     float UNUSED(depth),
1619                     float UNUSED(time),
1620                     int UNUSED(spectrum),
1621                     float UNUSED(fetch_jonswap),
1622                     float UNUSED(sharpen_peak_jonswap),
1623                     short UNUSED(do_height_field),
1624                     short UNUSED(do_chop),
1625                     short UNUSED(do_spray),
1626                     short UNUSED(do_normals),
1627                     short UNUSED(do_jacobian),
1628                     int UNUSED(seed))
1629 {
1630 }
1631 
BKE_ocean_free_data(struct Ocean * UNUSED (oc))1632 void BKE_ocean_free_data(struct Ocean *UNUSED(oc))
1633 {
1634 }
1635 
BKE_ocean_free(struct Ocean * oc)1636 void BKE_ocean_free(struct Ocean *oc)
1637 {
1638   if (!oc) {
1639     return;
1640   }
1641   MEM_freeN(oc);
1642 }
1643 
1644 /* ********* Baking/Caching ********* */
1645 
BKE_ocean_free_cache(struct OceanCache * och)1646 void BKE_ocean_free_cache(struct OceanCache *och)
1647 {
1648   if (!och) {
1649     return;
1650   }
1651 
1652   MEM_freeN(och);
1653 }
1654 
BKE_ocean_cache_eval_uv(struct OceanCache * UNUSED (och),struct OceanResult * UNUSED (ocr),int UNUSED (f),float UNUSED (u),float UNUSED (v))1655 void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och),
1656                              struct OceanResult *UNUSED(ocr),
1657                              int UNUSED(f),
1658                              float UNUSED(u),
1659                              float UNUSED(v))
1660 {
1661 }
1662 
BKE_ocean_cache_eval_ij(struct OceanCache * UNUSED (och),struct OceanResult * UNUSED (ocr),int UNUSED (f),int UNUSED (i),int UNUSED (j))1663 void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och),
1664                              struct OceanResult *UNUSED(ocr),
1665                              int UNUSED(f),
1666                              int UNUSED(i),
1667                              int UNUSED(j))
1668 {
1669 }
1670 
BKE_ocean_init_cache(const char * UNUSED (bakepath),const char * UNUSED (relbase),int UNUSED (start),int UNUSED (end),float UNUSED (wave_scale),float UNUSED (chop_amount),float UNUSED (foam_coverage),float UNUSED (foam_fade),int UNUSED (resolution))1671 OceanCache *BKE_ocean_init_cache(const char *UNUSED(bakepath),
1672                                  const char *UNUSED(relbase),
1673                                  int UNUSED(start),
1674                                  int UNUSED(end),
1675                                  float UNUSED(wave_scale),
1676                                  float UNUSED(chop_amount),
1677                                  float UNUSED(foam_coverage),
1678                                  float UNUSED(foam_fade),
1679                                  int UNUSED(resolution))
1680 {
1681   OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
1682 
1683   return och;
1684 }
1685 
BKE_ocean_simulate_cache(struct OceanCache * UNUSED (och),int UNUSED (frame))1686 void BKE_ocean_simulate_cache(struct OceanCache *UNUSED(och), int UNUSED(frame))
1687 {
1688 }
1689 
BKE_ocean_bake(struct Ocean * UNUSED (o),struct OceanCache * UNUSED (och),void (* update_cb)(void *,float progress,int * cancel),void * UNUSED (update_cb_data))1690 void BKE_ocean_bake(struct Ocean *UNUSED(o),
1691                     struct OceanCache *UNUSED(och),
1692                     void (*update_cb)(void *, float progress, int *cancel),
1693                     void *UNUSED(update_cb_data))
1694 {
1695   /* unused */
1696   (void)update_cb;
1697 }
1698 
BKE_ocean_init_from_modifier(struct Ocean * UNUSED (ocean),struct OceanModifierData const * UNUSED (omd),int UNUSED (resolution))1699 void BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean),
1700                                   struct OceanModifierData const *UNUSED(omd),
1701                                   int UNUSED(resolution))
1702 {
1703 }
1704 
1705 #endif /* WITH_OCEANSIM */
1706 
BKE_ocean_free_modifier_cache(struct OceanModifierData * omd)1707 void BKE_ocean_free_modifier_cache(struct OceanModifierData *omd)
1708 {
1709   BKE_ocean_free_cache(omd->oceancache);
1710   omd->oceancache = NULL;
1711   omd->cached = false;
1712 }
1713