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