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