2011-11-13 16:10:01 +00:00
|
|
|
/*
|
2011-11-13 12:17:27 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Based on original code by Drew Whitehouse / Houdini Ocean Toolkit
|
|
|
|
|
* OpenMP hints by Christian Schnellhammer
|
|
|
|
|
*/
|
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2013-09-12 03:02:50 +00:00
|
|
|
*/
|
2011-11-13 12:17:27 +00:00
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2018-07-05 16:23:35 +02:00
|
|
|
#include "DNA_modifier_types.h"
|
2011-11-13 12:17:27 +00:00
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
|
2019-01-26 15:02:52 +01:00
|
|
|
#include "BLI_math.h"
|
|
|
|
|
#include "BLI_path_util.h"
|
|
|
|
|
#include "BLI_rand.h"
|
|
|
|
|
#include "BLI_task.h"
|
2011-11-13 12:17:27 +00:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
2013-01-24 21:57:13 +00:00
|
|
|
#include "BKE_image.h"
|
|
|
|
|
#include "BKE_ocean.h"
|
2020-03-12 13:35:22 +11:00
|
|
|
#include "ocean_intern.h"
|
2013-01-24 21:57:13 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
|
2020-11-09 15:42:38 +01:00
|
|
|
#include "RE_texture.h"
|
2011-11-13 12:17:27 +00:00
|
|
|
|
2020-02-25 15:03:47 +01:00
|
|
|
#include "BLI_hash.h"
|
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
#ifdef WITH_OCEANSIM
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* Ocean code */
|
2011-11-13 12:17:27 +00:00
|
|
|
|
2013-04-15 23:12:40 +00:00
|
|
|
static float nextfr(RNG *rng, float min, float max)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2013-04-15 23:12:40 +00:00
|
|
|
return BLI_rng_get_float(rng) * (min - max) + max;
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2013-04-15 23:12:40 +00:00
|
|
|
static float gaussRand(RNG *rng)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Note: to avoid numerical problems with very small numbers, we make these variables
|
|
|
|
|
* singe-precision floats, but later we call the double-precision log() and sqrt() functions
|
|
|
|
|
* instead of logf() and sqrtf(). */
|
2013-01-02 16:03:58 +00:00
|
|
|
float x;
|
|
|
|
|
float y;
|
|
|
|
|
float length2;
|
|
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
do {
|
2013-04-16 00:56:24 +00:00
|
|
|
x = (float)(nextfr(rng, -1, 1));
|
|
|
|
|
y = (float)(nextfr(rng, -1, 1));
|
2011-11-13 12:17:27 +00:00
|
|
|
length2 = x * x + y * y;
|
2012-05-12 19:18:02 +00:00
|
|
|
} while (length2 >= 1 || length2 == 0);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
|
|
|
|
return x * sqrtf(-2.0f * logf(length2) / length2);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-03-01 12:20:18 +00:00
|
|
|
* Some useful functions
|
2013-01-02 16:03:58 +00:00
|
|
|
*/
|
2012-04-29 15:47:02 +00:00
|
|
|
MINLINE float catrom(float p0, float p1, float p2, float p3, float f)
|
2011-11-13 16:10:01 +00:00
|
|
|
{
|
2012-05-12 19:18:02 +00:00
|
|
|
return 0.5f * ((2.0f * p1) + (-p0 + p2) * f + (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * f * f +
|
|
|
|
|
(-p0 + 3.0f * p1 - 3.0f * p2 + p3) * f * f * f);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
MINLINE float omega(float k, float depth)
|
|
|
|
|
{
|
2012-11-09 16:15:00 +00:00
|
|
|
return sqrtf(GRAVITY * k * tanhf(k * depth));
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* modified Phillips spectrum */
|
2012-05-12 19:18:02 +00:00
|
|
|
static float Ph(struct Ocean *o, float kx, float kz)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
float tmp;
|
2012-05-12 19:18:02 +00:00
|
|
|
float k2 = kx * kx + kz * kz;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (k2 == 0.0f) {
|
2013-01-02 16:03:58 +00:00
|
|
|
return 0.0f; /* no DC component */
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* damp out the waves going in the direction opposite the wind */
|
2012-06-23 23:22:19 +00:00
|
|
|
tmp = (o->_wx * kx + o->_wz * kz) / sqrtf(k2);
|
2012-04-28 06:31:57 +00:00
|
|
|
if (tmp < 0) {
|
2011-11-13 16:10:01 +00:00
|
|
|
tmp *= o->_damp_reflections;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
return o->_A * expf(-1.0f / (k2 * (o->_L * o->_L))) * expf(-k2 * (o->_l * o->_l)) *
|
|
|
|
|
powf(fabsf(tmp), o->_wind_alignment) / (k2 * k2);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
static void compute_eigenstuff(struct OceanResult *ocr, float jxx, float jzz, float jxz)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2012-04-29 15:47:02 +00:00
|
|
|
float a, b, qplus, qminus;
|
2011-11-13 16:10:01 +00:00
|
|
|
a = jxx + jzz;
|
2012-05-12 19:18:02 +00:00
|
|
|
b = sqrt((jxx - jzz) * (jxx - jzz) + 4 * jxz * jxz);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->Jminus = 0.5f * (a - b);
|
|
|
|
|
ocr->Jplus = 0.5f * (a + b);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
qplus = (ocr->Jplus - jxx) / jxz;
|
|
|
|
|
qminus = (ocr->Jminus - jxx) / jxz;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
a = sqrt(1 + qplus * qplus);
|
|
|
|
|
b = sqrt(1 + qminus * qminus);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->Eplus[0] = 1.0f / a;
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->Eplus[1] = 0.0f;
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->Eplus[2] = qplus / a;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->Eminus[0] = 1.0f / b;
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->Eminus[1] = 0.0f;
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->Eminus[2] = qminus / b;
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2011-11-13 16:10:01 +00:00
|
|
|
* instead of Complex.h
|
2011-11-13 12:17:27 +00:00
|
|
|
* in fftw.h "fftw_complex" typedefed as double[2]
|
|
|
|
|
* below you can see functions are needed to work with such complex numbers.
|
2021-01-20 15:15:38 +11:00
|
|
|
*/
|
2011-11-13 12:17:27 +00:00
|
|
|
static void init_complex(fftw_complex cmpl, float real, float image)
|
|
|
|
|
{
|
|
|
|
|
cmpl[0] = real;
|
|
|
|
|
cmpl[1] = image;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 11:27:09 +02:00
|
|
|
static void add_comlex_c(fftw_complex res, const fftw_complex cmpl1, const fftw_complex cmpl2)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
res[0] = cmpl1[0] + cmpl2[0];
|
|
|
|
|
res[1] = cmpl1[1] + cmpl2[1];
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 11:27:09 +02:00
|
|
|
static void mul_complex_f(fftw_complex res, const fftw_complex cmpl, float f)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2012-11-09 16:15:00 +00:00
|
|
|
res[0] = cmpl[0] * (double)f;
|
|
|
|
|
res[1] = cmpl[1] * (double)f;
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2020-07-13 11:27:09 +02:00
|
|
|
static void mul_complex_c(fftw_complex res, const fftw_complex cmpl1, const fftw_complex cmpl2)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
fftwf_complex temp;
|
2012-05-12 19:18:02 +00:00
|
|
|
temp[0] = cmpl1[0] * cmpl2[0] - cmpl1[1] * cmpl2[1];
|
|
|
|
|
temp[1] = cmpl1[0] * cmpl2[1] + cmpl1[1] * cmpl2[0];
|
2011-11-13 12:17:27 +00:00
|
|
|
res[0] = temp[0];
|
|
|
|
|
res[1] = temp[1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static float real_c(fftw_complex cmpl)
|
|
|
|
|
{
|
|
|
|
|
return cmpl[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static float image_c(fftw_complex cmpl)
|
|
|
|
|
{
|
|
|
|
|
return cmpl[1];
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 11:27:09 +02:00
|
|
|
static void conj_complex(fftw_complex res, const fftw_complex cmpl1)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
res[0] = cmpl1[0];
|
|
|
|
|
res[1] = -cmpl1[1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void exp_complex(fftw_complex res, fftw_complex cmpl)
|
|
|
|
|
{
|
|
|
|
|
float r = expf(cmpl[0]);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-11-09 16:15:00 +00:00
|
|
|
res[0] = cosf(cmpl[1]) * r;
|
|
|
|
|
res[1] = sinf(cmpl[1]) * r;
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
float BKE_ocean_jminus_to_foam(float jminus, float coverage)
|
|
|
|
|
{
|
|
|
|
|
float foam = jminus * -0.005f + coverage;
|
|
|
|
|
CLAMP(foam, 0.0f, 1.0f);
|
2020-03-12 13:35:22 +11:00
|
|
|
return foam;
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2012-04-29 15:47:02 +00:00
|
|
|
int i0, i1, j0, j1;
|
|
|
|
|
float frac_x, frac_z;
|
|
|
|
|
float uu, vv;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* first wrap the texture so 0 <= (u, v) < 1 */
|
2012-04-29 15:47:02 +00:00
|
|
|
u = fmodf(u, 1.0f);
|
|
|
|
|
v = fmodf(v, 1.0f);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (u < 0) {
|
2011-11-13 16:10:01 +00:00
|
|
|
u += 1.0f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (v < 0) {
|
2011-11-13 16:10:01 +00:00
|
|
|
v += 1.0f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
|
|
|
|
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
|
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
uu = u * oc->_M;
|
2011-11-13 16:10:01 +00:00
|
|
|
vv = v * oc->_N;
|
|
|
|
|
|
|
|
|
|
i0 = (int)floor(uu);
|
|
|
|
|
j0 = (int)floor(vv);
|
|
|
|
|
|
|
|
|
|
i1 = (i0 + 1);
|
|
|
|
|
j1 = (j0 + 1);
|
|
|
|
|
|
|
|
|
|
frac_x = uu - i0;
|
|
|
|
|
frac_z = vv - j0;
|
|
|
|
|
|
|
|
|
|
i0 = i0 % oc->_M;
|
|
|
|
|
j0 = j0 % oc->_N;
|
|
|
|
|
|
|
|
|
|
i1 = i1 % oc->_M;
|
|
|
|
|
j1 = j1 % oc->_N;
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
# define BILERP(m) \
|
|
|
|
|
(interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
|
|
|
|
|
interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
|
|
|
|
|
frac_z))
|
2017-06-12 13:35:00 +10:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
{
|
|
|
|
|
if (oc->_do_disp_y) {
|
|
|
|
|
ocr->disp[1] = BILERP(oc->_disp_y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (oc->_do_normals) {
|
|
|
|
|
ocr->normal[0] = BILERP(oc->_N_x);
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->normal[1] = oc->_N_y /*BILERP(oc->_N_y) (MEM01)*/;
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->normal[2] = BILERP(oc->_N_z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (oc->_do_chop) {
|
|
|
|
|
ocr->disp[0] = BILERP(oc->_disp_x);
|
|
|
|
|
ocr->disp[2] = BILERP(oc->_disp_z);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->disp[0] = 0.0;
|
|
|
|
|
ocr->disp[2] = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (oc->_do_jacobian) {
|
2012-04-29 15:47:02 +00:00
|
|
|
compute_eigenstuff(ocr, BILERP(oc->_Jxx), BILERP(oc->_Jzz), BILERP(oc->_Jxz));
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
# undef BILERP
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_unlock(&oc->oceanmutex);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* use catmullrom interpolation rather than linear */
|
2012-04-29 15:47:02 +00:00
|
|
|
void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2012-04-29 15:47:02 +00:00
|
|
|
int i0, i1, i2, i3, j0, j1, j2, j3;
|
|
|
|
|
float frac_x, frac_z;
|
|
|
|
|
float uu, vv;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* first wrap the texture so 0 <= (u, v) < 1 */
|
2012-04-29 15:47:02 +00:00
|
|
|
u = fmod(u, 1.0f);
|
|
|
|
|
v = fmod(v, 1.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (u < 0) {
|
2011-11-13 16:10:01 +00:00
|
|
|
u += 1.0f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (v < 0) {
|
2011-11-13 16:10:01 +00:00
|
|
|
v += 1.0f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
uu = u * oc->_M;
|
|
|
|
|
vv = v * oc->_N;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
i1 = (int)floor(uu);
|
|
|
|
|
j1 = (int)floor(vv);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
i2 = (i1 + 1);
|
|
|
|
|
j2 = (j1 + 1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
frac_x = uu - i1;
|
|
|
|
|
frac_z = vv - j1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
i1 = i1 % oc->_M;
|
|
|
|
|
j1 = j1 % oc->_N;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
i2 = i2 % oc->_M;
|
|
|
|
|
j2 = j2 % oc->_N;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
i0 = (i1 - 1);
|
|
|
|
|
i3 = (i2 + 1);
|
2011-11-13 16:10:01 +00:00
|
|
|
i0 = i0 < 0 ? i0 + oc->_M : i0;
|
|
|
|
|
i3 = i3 >= oc->_M ? i3 - oc->_M : i3;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
j0 = (j1 - 1);
|
|
|
|
|
j3 = (j2 + 1);
|
2011-11-13 16:10:01 +00:00
|
|
|
j0 = j0 < 0 ? j0 + oc->_N : j0;
|
|
|
|
|
j3 = j3 >= oc->_N ? j3 - oc->_N : j3;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
# define INTERP(m) \
|
|
|
|
|
catrom(catrom(m[i0 * oc->_N + j0], \
|
|
|
|
|
m[i1 * oc->_N + j0], \
|
|
|
|
|
m[i2 * oc->_N + j0], \
|
|
|
|
|
m[i3 * oc->_N + j0], \
|
|
|
|
|
frac_x), \
|
|
|
|
|
catrom(m[i0 * oc->_N + j1], \
|
|
|
|
|
m[i1 * oc->_N + j1], \
|
|
|
|
|
m[i2 * oc->_N + j1], \
|
|
|
|
|
m[i3 * oc->_N + j1], \
|
|
|
|
|
frac_x), \
|
|
|
|
|
catrom(m[i0 * oc->_N + j2], \
|
|
|
|
|
m[i1 * oc->_N + j2], \
|
|
|
|
|
m[i2 * oc->_N + j2], \
|
|
|
|
|
m[i3 * oc->_N + j2], \
|
|
|
|
|
frac_x), \
|
|
|
|
|
catrom(m[i0 * oc->_N + j3], \
|
|
|
|
|
m[i1 * oc->_N + j3], \
|
|
|
|
|
m[i2 * oc->_N + j3], \
|
|
|
|
|
m[i3 * oc->_N + j3], \
|
|
|
|
|
frac_x), \
|
|
|
|
|
frac_z)
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
{
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_disp_y) {
|
2012-02-27 10:35:39 +00:00
|
|
|
ocr->disp[1] = INTERP(oc->_disp_y);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_normals) {
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->normal[0] = INTERP(oc->_N_x);
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->normal[1] = oc->_N_y /*INTERP(oc->_N_y) (MEM01)*/;
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->normal[2] = INTERP(oc->_N_z);
|
|
|
|
|
}
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_chop) {
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->disp[0] = INTERP(oc->_disp_x);
|
|
|
|
|
ocr->disp[2] = INTERP(oc->_disp_z);
|
|
|
|
|
}
|
2012-03-06 18:40:15 +00:00
|
|
|
else {
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->disp[0] = 0.0;
|
|
|
|
|
ocr->disp[2] = 0.0;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_jacobian) {
|
2012-04-29 15:47:02 +00:00
|
|
|
compute_eigenstuff(ocr, INTERP(oc->_Jxx), INTERP(oc->_Jzz), INTERP(oc->_Jxz));
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
# undef INTERP
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_unlock(&oc->oceanmutex);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
void BKE_ocean_eval_xz(struct Ocean *oc, struct OceanResult *ocr, float x, float z)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2012-05-12 19:18:02 +00:00
|
|
|
BKE_ocean_eval_uv(oc, ocr, x / oc->_Lx, z / oc->_Lz);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
void BKE_ocean_eval_xz_catrom(struct Ocean *oc, struct OceanResult *ocr, float x, float z)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2012-05-12 19:18:02 +00:00
|
|
|
BKE_ocean_eval_uv_catrom(oc, ocr, x / oc->_Lx, z / oc->_Lz);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* note that this doesn't wrap properly for i, j < 0, but its not really meant for that being
|
|
|
|
|
* just a way to get the raw data out to save in some image format. */
|
2012-04-29 15:47:02 +00:00
|
|
|
void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
|
|
|
|
i = abs(i) % oc->_M;
|
|
|
|
|
j = abs(j) % oc->_N;
|
|
|
|
|
|
2012-11-09 16:15:00 +00:00
|
|
|
ocr->disp[1] = oc->_do_disp_y ? (float)oc->_disp_y[i * oc->_N + j] : 0.0f;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_chop) {
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->disp[0] = oc->_disp_x[i * oc->_N + j];
|
|
|
|
|
ocr->disp[2] = oc->_disp_z[i * oc->_N + j];
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2012-03-06 18:40:15 +00:00
|
|
|
else {
|
2011-11-13 16:10:01 +00:00
|
|
|
ocr->disp[0] = 0.0f;
|
|
|
|
|
ocr->disp[2] = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_normals) {
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->normal[0] = oc->_N_x[i * oc->_N + j];
|
2012-10-27 10:42:28 +00:00
|
|
|
ocr->normal[1] = oc->_N_y /* oc->_N_y[i * oc->_N + j] (MEM01) */;
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->normal[2] = oc->_N_z[i * oc->_N + j];
|
2011-11-14 05:55:50 +00:00
|
|
|
|
|
|
|
|
normalize_v3(ocr->normal);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_jacobian) {
|
2012-05-12 19:18:02 +00:00
|
|
|
compute_eigenstuff(
|
|
|
|
|
ocr, oc->_Jxx[i * oc->_N + j], oc->_Jzz[i * oc->_N + j], oc->_Jxz[i * oc->_N + j]);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_unlock(&oc->oceanmutex);
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
typedef struct OceanSimulateData {
|
|
|
|
|
Ocean *o;
|
|
|
|
|
float t;
|
|
|
|
|
float scale;
|
|
|
|
|
float chop_amount;
|
|
|
|
|
} OceanSimulateData;
|
|
|
|
|
|
2018-01-10 12:49:51 +01:00
|
|
|
static void ocean_compute_htilda(void *__restrict userdata,
|
|
|
|
|
const int i,
|
2019-07-30 14:56:47 +02:00
|
|
|
const TaskParallelTLS *__restrict UNUSED(tls))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2015-12-06 17:37:10 +01:00
|
|
|
OceanSimulateData *osd = userdata;
|
|
|
|
|
const Ocean *o = osd->o;
|
|
|
|
|
const float scale = osd->scale;
|
|
|
|
|
const float t = osd->t;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
int j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Note the <= _N/2 here, see the FFTW documentation
|
2019-04-27 12:07:07 +10:00
|
|
|
* about the mechanics of the complex->real fft storage. */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_complex exp_param1;
|
|
|
|
|
fftw_complex exp_param2;
|
|
|
|
|
fftw_complex conj_param;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
init_complex(exp_param1, 0.0, omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
|
|
|
|
|
init_complex(exp_param2, 0.0, -omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
|
|
|
|
|
exp_complex(exp_param1, exp_param1);
|
|
|
|
|
exp_complex(exp_param2, exp_param2);
|
|
|
|
|
conj_complex(conj_param, o->_h0_minus[i * o->_N + j]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
mul_complex_c(exp_param1, o->_h0[i * o->_N + j], exp_param1);
|
|
|
|
|
mul_complex_c(exp_param2, conj_param, exp_param2);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
add_comlex_c(o->_htilda[i * (1 + o->_N / 2) + j], exp_param1, exp_param2);
|
|
|
|
|
mul_complex_f(o->_fft_in[i * (1 + o->_N / 2) + j], o->_htilda[i * (1 + o->_N / 2) + j], scale);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 07:59:23 +02:00
|
|
|
static void ocean_compute_displacement_y(TaskPool *__restrict pool, void *UNUSED(taskdata))
|
2015-12-06 17:37:10 +01:00
|
|
|
{
|
2020-04-21 15:36:35 +02:00
|
|
|
OceanSimulateData *osd = BLI_task_pool_user_data(pool);
|
2015-12-06 17:37:10 +01:00
|
|
|
const Ocean *o = osd->o;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_execute(o->_disp_y_plan);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 07:59:23 +02:00
|
|
|
static void ocean_compute_displacement_x(TaskPool *__restrict pool, void *UNUSED(taskdata))
|
2015-12-06 17:37:10 +01:00
|
|
|
{
|
2020-04-21 15:36:35 +02:00
|
|
|
OceanSimulateData *osd = BLI_task_pool_user_data(pool);
|
2015-12-06 17:37:10 +01:00
|
|
|
const Ocean *o = osd->o;
|
|
|
|
|
const float scale = osd->scale;
|
|
|
|
|
const float chop_amount = osd->chop_amount;
|
2011-11-13 12:17:27 +00:00
|
|
|
int i, j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_complex mul_param;
|
|
|
|
|
fftw_complex minus_i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
init_complex(minus_i, 0.0, -1.0);
|
|
|
|
|
init_complex(mul_param, -scale, 0);
|
|
|
|
|
mul_complex_f(mul_param, mul_param, chop_amount);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, minus_i);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
|
|
|
|
|
mul_complex_f(mul_param,
|
|
|
|
|
mul_param,
|
|
|
|
|
((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
|
|
|
|
|
0.0f :
|
|
|
|
|
o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
|
|
|
|
|
init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
|
|
|
|
fftw_execute(o->_disp_x_plan);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 07:59:23 +02:00
|
|
|
static void ocean_compute_displacement_z(TaskPool *__restrict pool, void *UNUSED(taskdata))
|
2015-12-06 17:37:10 +01:00
|
|
|
{
|
2020-04-21 15:36:35 +02:00
|
|
|
OceanSimulateData *osd = BLI_task_pool_user_data(pool);
|
2015-12-06 17:37:10 +01:00
|
|
|
const Ocean *o = osd->o;
|
|
|
|
|
const float scale = osd->scale;
|
|
|
|
|
const float chop_amount = osd->chop_amount;
|
|
|
|
|
int i, j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_complex mul_param;
|
|
|
|
|
fftw_complex minus_i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
init_complex(minus_i, 0.0, -1.0);
|
|
|
|
|
init_complex(mul_param, -scale, 0);
|
|
|
|
|
mul_complex_f(mul_param, mul_param, chop_amount);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, minus_i);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
|
|
|
|
|
mul_complex_f(mul_param,
|
|
|
|
|
mul_param,
|
|
|
|
|
((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
|
|
|
|
|
0.0f :
|
|
|
|
|
o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
|
|
|
|
|
init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
|
|
|
|
fftw_execute(o->_disp_z_plan);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 07:59:23 +02:00
|
|
|
static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, void *UNUSED(taskdata))
|
2015-12-06 17:37:10 +01:00
|
|
|
{
|
2020-04-21 15:36:35 +02:00
|
|
|
OceanSimulateData *osd = BLI_task_pool_user_data(pool);
|
2015-12-06 17:37:10 +01:00
|
|
|
const Ocean *o = osd->o;
|
|
|
|
|
const float chop_amount = osd->chop_amount;
|
|
|
|
|
int i, j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_complex mul_param;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
/* init_complex(mul_param, -scale, 0); */
|
|
|
|
|
init_complex(mul_param, -1, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
mul_complex_f(mul_param, mul_param, chop_amount);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
|
|
|
|
|
mul_complex_f(mul_param,
|
|
|
|
|
mul_param,
|
|
|
|
|
((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
|
|
|
|
|
0.0f :
|
|
|
|
|
o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
|
|
|
|
|
init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
|
|
|
|
fftw_execute(o->_Jxx_plan);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j < o->_N; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
o->_Jxx[i * o->_N + j] += 1.0;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 07:59:23 +02:00
|
|
|
static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, void *UNUSED(taskdata))
|
2015-12-06 17:37:10 +01:00
|
|
|
{
|
2020-04-21 15:36:35 +02:00
|
|
|
OceanSimulateData *osd = BLI_task_pool_user_data(pool);
|
2015-12-06 17:37:10 +01:00
|
|
|
const Ocean *o = osd->o;
|
|
|
|
|
const float chop_amount = osd->chop_amount;
|
|
|
|
|
int i, j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_complex mul_param;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
/* init_complex(mul_param, -scale, 0); */
|
|
|
|
|
init_complex(mul_param, -1, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
mul_complex_f(mul_param, mul_param, chop_amount);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
|
|
|
|
|
mul_complex_f(mul_param,
|
|
|
|
|
mul_param,
|
|
|
|
|
((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
|
|
|
|
|
0.0f :
|
|
|
|
|
o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
|
|
|
|
|
init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_execute(o->_Jzz_plan);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j < o->_N; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
o->_Jzz[i * o->_N + j] += 1.0;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 07:59:23 +02:00
|
|
|
static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, void *UNUSED(taskdata))
|
2015-12-06 17:37:10 +01:00
|
|
|
{
|
2020-04-21 15:36:35 +02:00
|
|
|
OceanSimulateData *osd = BLI_task_pool_user_data(pool);
|
2015-12-06 17:37:10 +01:00
|
|
|
const Ocean *o = osd->o;
|
|
|
|
|
const float chop_amount = osd->chop_amount;
|
|
|
|
|
int i, j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_complex mul_param;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
/* init_complex(mul_param, -scale, 0); */
|
|
|
|
|
init_complex(mul_param, -1, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
mul_complex_f(mul_param, mul_param, chop_amount);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
|
|
|
|
|
mul_complex_f(mul_param,
|
|
|
|
|
mul_param,
|
|
|
|
|
((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
|
|
|
|
|
0.0f :
|
|
|
|
|
o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
|
|
|
|
|
init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fftw_execute(o->_Jxz_plan);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 07:59:23 +02:00
|
|
|
static void ocean_compute_normal_x(TaskPool *__restrict pool, void *UNUSED(taskdata))
|
2015-12-06 17:37:10 +01:00
|
|
|
{
|
2020-04-21 15:36:35 +02:00
|
|
|
OceanSimulateData *osd = BLI_task_pool_user_data(pool);
|
2015-12-06 17:37:10 +01:00
|
|
|
const Ocean *o = osd->o;
|
|
|
|
|
int i, j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_complex mul_param;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
init_complex(mul_param, 0.0, -1.0);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
|
|
|
|
|
mul_complex_f(mul_param, mul_param, o->_kx[i]);
|
|
|
|
|
init_complex(o->_fft_in_nx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fftw_execute(o->_N_x_plan);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 07:59:23 +02:00
|
|
|
static void ocean_compute_normal_z(TaskPool *__restrict pool, void *UNUSED(taskdata))
|
2015-12-06 17:37:10 +01:00
|
|
|
{
|
2020-04-21 15:36:35 +02:00
|
|
|
OceanSimulateData *osd = BLI_task_pool_user_data(pool);
|
2015-12-06 17:37:10 +01:00
|
|
|
const Ocean *o = osd->o;
|
|
|
|
|
int i, j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2015-12-06 17:37:10 +01:00
|
|
|
fftw_complex mul_param;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
init_complex(mul_param, 0.0, -1.0);
|
|
|
|
|
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
|
|
|
|
|
mul_complex_f(mul_param, mul_param, o->_kz[i]);
|
|
|
|
|
init_complex(o->_fft_in_nz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fftw_execute(o->_N_z_plan);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount)
|
|
|
|
|
{
|
|
|
|
|
TaskPool *pool;
|
|
|
|
|
|
|
|
|
|
OceanSimulateData osd;
|
|
|
|
|
|
|
|
|
|
scale *= o->normalize_factor;
|
|
|
|
|
|
|
|
|
|
osd.o = o;
|
|
|
|
|
osd.t = t;
|
|
|
|
|
osd.scale = scale;
|
|
|
|
|
osd.chop_amount = chop_amount;
|
|
|
|
|
|
2021-06-08 09:37:45 +02:00
|
|
|
pool = BLI_task_pool_create(&osd, TASK_PRIORITY_HIGH, TASK_ISOLATION_ON);
|
2015-12-06 17:37:10 +01:00
|
|
|
|
|
|
|
|
BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
|
|
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Note about multi-threading here: we have to run a first set of computations (htilda one)
|
|
|
|
|
* before we can run all others, since they all depend on it.
|
|
|
|
|
* So we make a first parallelized forloop run for htilda,
|
|
|
|
|
* and then pack all other computations into a set of parallel tasks.
|
|
|
|
|
* This is not optimal in all cases,
|
|
|
|
|
* but remains reasonably simple and should be OK most of the time. */
|
2015-12-06 17:37:10 +01:00
|
|
|
|
|
|
|
|
/* compute a new htilda */
|
2019-07-30 14:56:47 +02:00
|
|
|
TaskParallelSettings settings;
|
2018-01-08 11:35:48 +01:00
|
|
|
BLI_parallel_range_settings_defaults(&settings);
|
|
|
|
|
settings.use_threading = (o->_M > 16);
|
|
|
|
|
BLI_task_parallel_range(0, o->_M, &osd, ocean_compute_htilda, &settings);
|
2015-12-06 17:37:10 +01:00
|
|
|
|
|
|
|
|
if (o->_do_disp_y) {
|
2020-04-09 15:51:44 +02:00
|
|
|
BLI_task_pool_push(pool, ocean_compute_displacement_y, NULL, false, NULL);
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (o->_do_chop) {
|
2020-04-09 15:51:44 +02:00
|
|
|
BLI_task_pool_push(pool, ocean_compute_displacement_x, NULL, false, NULL);
|
|
|
|
|
BLI_task_pool_push(pool, ocean_compute_displacement_z, NULL, false, NULL);
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (o->_do_jacobian) {
|
2020-04-09 15:51:44 +02:00
|
|
|
BLI_task_pool_push(pool, ocean_compute_jacobian_jxx, NULL, false, NULL);
|
|
|
|
|
BLI_task_pool_push(pool, ocean_compute_jacobian_jzz, NULL, false, NULL);
|
|
|
|
|
BLI_task_pool_push(pool, ocean_compute_jacobian_jxz, NULL, false, NULL);
|
2015-12-06 17:37:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (o->_do_normals) {
|
2020-04-09 15:51:44 +02:00
|
|
|
BLI_task_pool_push(pool, ocean_compute_normal_x, NULL, false, NULL);
|
|
|
|
|
BLI_task_pool_push(pool, ocean_compute_normal_z, NULL, false, NULL);
|
2015-12-06 17:37:10 +01:00
|
|
|
o->_N_y = 1.0f / scale;
|
|
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2015-12-06 17:37:10 +01:00
|
|
|
BLI_task_pool_work_and_wait(pool);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_unlock(&o->oceanmutex);
|
2015-12-06 17:37:10 +01:00
|
|
|
|
|
|
|
|
BLI_task_pool_free(pool);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
static void set_height_normalize_factor(struct Ocean *oc)
|
|
|
|
|
{
|
|
|
|
|
float res = 1.0;
|
|
|
|
|
float max_h = 0.0;
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
int i, j;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!oc->_do_disp_y) {
|
2011-11-13 12:17:27 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
oc->normalize_factor = 1.0;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
BKE_ocean_simulate(oc, 0.0, 1.0, 0);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < oc->_M; i++) {
|
|
|
|
|
for (j = 0; j < oc->_N; j++) {
|
2015-04-23 16:09:30 +10:00
|
|
|
if (max_h < fabs(oc->_disp_y[i * oc->_N + j])) {
|
|
|
|
|
max_h = fabs(oc->_disp_y[i * oc->_N + j]);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_unlock(&oc->oceanmutex);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (max_h == 0.0f) {
|
2013-01-02 16:03:58 +00:00
|
|
|
max_h = 0.00001f; /* just in case ... */
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
|
|
|
|
res = 1.0f / (max_h);
|
2011-11-13 12:17:27 +00:00
|
|
|
|
|
|
|
|
oc->normalize_factor = res;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
struct Ocean *BKE_ocean_add(void)
|
2012-05-17 23:21:11 +00:00
|
|
|
{
|
2011-11-13 12:17:27 +00:00
|
|
|
Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data");
|
|
|
|
|
|
|
|
|
|
BLI_rw_mutex_init(&oc->oceanmutex);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
return oc;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-03 10:08:31 -04:00
|
|
|
bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution)
|
2018-07-10 11:58:01 +02:00
|
|
|
{
|
|
|
|
|
if (omd->ocean) {
|
2020-08-03 15:33:32 -04:00
|
|
|
/* Check that the ocean has the same resolution than we want now. */
|
|
|
|
|
if (omd->ocean->_M == resolution * resolution) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
BKE_ocean_free(omd->ocean);
|
2018-07-10 11:58:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
omd->ocean = BKE_ocean_add();
|
2020-08-03 10:08:31 -04:00
|
|
|
BKE_ocean_init_from_modifier(omd->ocean, omd, resolution);
|
2018-07-10 11:58:01 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-03 10:08:31 -04:00
|
|
|
void BKE_ocean_init_from_modifier(struct Ocean *ocean,
|
|
|
|
|
struct OceanModifierData const *omd,
|
|
|
|
|
const int resolution)
|
2018-07-10 11:57:01 +02:00
|
|
|
{
|
2020-10-20 12:47:58 -05:00
|
|
|
short do_heightfield, do_chop, do_normals, do_jacobian, do_spray;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 11:57:01 +02:00
|
|
|
do_heightfield = true;
|
|
|
|
|
do_chop = (omd->chop_amount > 0);
|
|
|
|
|
do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
|
|
|
|
|
do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
|
2020-10-20 12:47:58 -05:00
|
|
|
do_spray = do_jacobian && (omd->flag & MOD_OCEAN_GENERATE_SPRAY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 11:57:01 +02:00
|
|
|
BKE_ocean_free_data(ocean);
|
2020-08-03 10:08:31 -04:00
|
|
|
|
2018-07-10 11:57:01 +02:00
|
|
|
BKE_ocean_init(ocean,
|
2020-08-03 10:08:31 -04:00
|
|
|
resolution * resolution,
|
|
|
|
|
resolution * resolution,
|
2018-07-10 11:57:01 +02:00
|
|
|
omd->spatial_size,
|
|
|
|
|
omd->spatial_size,
|
|
|
|
|
omd->wind_velocity,
|
|
|
|
|
omd->smallest_wave,
|
|
|
|
|
1.0,
|
|
|
|
|
omd->wave_direction,
|
|
|
|
|
omd->damp,
|
|
|
|
|
omd->wave_alignment,
|
|
|
|
|
omd->depth,
|
|
|
|
|
omd->time,
|
2020-03-12 13:35:22 +11:00
|
|
|
omd->spectrum,
|
|
|
|
|
omd->fetch_jonswap,
|
|
|
|
|
omd->sharpen_peak_jonswap,
|
2018-07-10 11:57:01 +02:00
|
|
|
do_heightfield,
|
|
|
|
|
do_chop,
|
2020-10-20 12:47:58 -05:00
|
|
|
do_spray,
|
2018-07-10 11:57:01 +02:00
|
|
|
do_normals,
|
|
|
|
|
do_jacobian,
|
|
|
|
|
omd->seed);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_init(struct Ocean *o,
|
|
|
|
|
int M,
|
|
|
|
|
int N,
|
|
|
|
|
float Lx,
|
|
|
|
|
float Lz,
|
2013-01-02 16:03:58 +00:00
|
|
|
float V,
|
2011-11-13 12:17:27 +00:00
|
|
|
float l,
|
2011-11-13 16:10:01 +00:00
|
|
|
float A,
|
|
|
|
|
float w,
|
|
|
|
|
float damp,
|
|
|
|
|
float alignment,
|
|
|
|
|
float depth,
|
|
|
|
|
float time,
|
2020-03-12 13:35:22 +11:00
|
|
|
int spectrum,
|
|
|
|
|
float fetch_jonswap,
|
|
|
|
|
float sharpen_peak_jonswap,
|
2011-11-13 16:10:01 +00:00
|
|
|
short do_height_field,
|
|
|
|
|
short do_chop,
|
2020-10-20 12:47:58 -05:00
|
|
|
short do_spray,
|
2011-11-13 16:10:01 +00:00
|
|
|
short do_normals,
|
|
|
|
|
short do_jacobian,
|
2013-01-02 16:03:58 +00:00
|
|
|
int seed)
|
2019-04-17 06:17:24 +02:00
|
|
|
{
|
2013-04-15 23:12:40 +00:00
|
|
|
RNG *rng;
|
2012-04-29 15:47:02 +00:00
|
|
|
int i, j, ii;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
o->_M = M;
|
2011-11-13 16:10:01 +00:00
|
|
|
o->_N = N;
|
|
|
|
|
o->_V = V;
|
|
|
|
|
o->_l = l;
|
|
|
|
|
o->_A = A;
|
|
|
|
|
o->_w = w;
|
2012-05-12 19:18:02 +00:00
|
|
|
o->_damp_reflections = 1.0f - damp;
|
2020-07-03 10:28:13 -04:00
|
|
|
o->_wind_alignment = alignment * 10.0f;
|
2011-11-13 16:10:01 +00:00
|
|
|
o->_depth = depth;
|
|
|
|
|
o->_Lx = Lx;
|
|
|
|
|
o->_Lz = Lz;
|
|
|
|
|
o->_wx = cos(w);
|
2012-05-12 19:18:02 +00:00
|
|
|
o->_wz = -sin(w); /* wave direction */
|
|
|
|
|
o->_L = V * V / GRAVITY; /* largest wave for a given velocity V */
|
|
|
|
|
o->time = time;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-12 13:35:22 +11:00
|
|
|
/* Spectrum to use. */
|
|
|
|
|
o->_spectrum = spectrum;
|
|
|
|
|
|
|
|
|
|
/* Common JONSWAP parameters. */
|
|
|
|
|
o->_fetch_jonswap = fetch_jonswap;
|
2020-07-03 10:28:13 -04:00
|
|
|
o->_sharpen_peak_jonswap = sharpen_peak_jonswap * 10.0f;
|
2020-03-12 13:35:22 +11:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
o->_do_disp_y = do_height_field;
|
|
|
|
|
o->_do_normals = do_normals;
|
2020-10-20 12:47:58 -05:00
|
|
|
o->_do_spray = do_spray;
|
2012-05-12 19:18:02 +00:00
|
|
|
o->_do_chop = do_chop;
|
|
|
|
|
o->_do_jacobian = do_jacobian;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
o->_k = (float *)MEM_mallocN(M * (1 + N / 2) * sizeof(float), "ocean_k");
|
|
|
|
|
o->_h0 = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0");
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_h0_minus = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus");
|
2011-11-13 16:10:01 +00:00
|
|
|
o->_kx = (float *)MEM_mallocN(o->_M * sizeof(float), "ocean_kx");
|
|
|
|
|
o->_kz = (float *)MEM_mallocN(o->_N * sizeof(float), "ocean_kz");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* make this robust in the face of erroneous usage */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (o->_Lx == 0.0f) {
|
2011-11-13 16:10:01 +00:00
|
|
|
o->_Lx = 0.001f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (o->_Lz == 0.0f) {
|
2011-11-13 16:10:01 +00:00
|
|
|
o->_Lz = 0.001f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* the +ve components and DC */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i <= o->_M / 2; i++) {
|
2012-05-12 19:18:02 +00:00
|
|
|
o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* the -ve components */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = o->_M - 1, ii = 0; i > o->_M / 2; i--, ii++) {
|
2011-11-13 16:10:01 +00:00
|
|
|
o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* the +ve components and DC */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i <= o->_N / 2; i++) {
|
2011-11-13 16:10:01 +00:00
|
|
|
o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* the -ve components */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = o->_N - 1, ii = 0; i > o->_N / 2; i--, ii++) {
|
2011-11-13 16:10:01 +00:00
|
|
|
o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* pre-calculate the k matrix */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j <= o->_N / 2; j++) {
|
2012-05-12 19:18:02 +00:00
|
|
|
o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-04-15 23:12:40 +00:00
|
|
|
rng = BLI_rng_new(seed);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < o->_M; i++) {
|
|
|
|
|
for (j = 0; j < o->_N; j++) {
|
2020-02-25 15:03:47 +01:00
|
|
|
/* This ensures we get a value tied to the surface location, avoiding dramatic surface
|
2021-05-18 14:02:41 +02:00
|
|
|
* change with changing resolution.
|
|
|
|
|
* Explicitly cast to signed int first to ensure consistent behavior on all processors,
|
|
|
|
|
* since behavior of float to unsigned int cast is undefined in C. */
|
|
|
|
|
const int hash_x = o->_kx[i] * 360.0f;
|
|
|
|
|
const int hash_z = o->_kz[j] * 360.0f;
|
|
|
|
|
int new_seed = seed + BLI_hash_int_2d(hash_x, hash_z);
|
2020-02-25 15:03:47 +01:00
|
|
|
|
|
|
|
|
BLI_rng_seed(rng, new_seed);
|
2013-04-15 23:12:40 +00:00
|
|
|
float r1 = gaussRand(rng);
|
|
|
|
|
float r2 = gaussRand(rng);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
fftw_complex r1r2;
|
|
|
|
|
init_complex(r1r2, r1, r2);
|
2020-03-12 13:35:22 +11:00
|
|
|
switch (o->_spectrum) {
|
|
|
|
|
case MOD_OCEAN_SPECTRUM_JONSWAP:
|
|
|
|
|
mul_complex_f(o->_h0[i * o->_N + j],
|
|
|
|
|
r1r2,
|
|
|
|
|
(float)(sqrt(BLI_ocean_spectrum_jonswap(o, o->_kx[i], o->_kz[j]) / 2.0f)));
|
|
|
|
|
mul_complex_f(
|
|
|
|
|
o->_h0_minus[i * o->_N + j],
|
|
|
|
|
r1r2,
|
|
|
|
|
(float)(sqrt(BLI_ocean_spectrum_jonswap(o, -o->_kx[i], -o->_kz[j]) / 2.0f)));
|
|
|
|
|
break;
|
|
|
|
|
case MOD_OCEAN_SPECTRUM_TEXEL_MARSEN_ARSLOE:
|
|
|
|
|
mul_complex_f(
|
|
|
|
|
o->_h0[i * o->_N + j],
|
|
|
|
|
r1r2,
|
|
|
|
|
(float)(sqrt(BLI_ocean_spectrum_texelmarsenarsloe(o, o->_kx[i], o->_kz[j]) / 2.0f)));
|
|
|
|
|
mul_complex_f(
|
|
|
|
|
o->_h0_minus[i * o->_N + j],
|
|
|
|
|
r1r2,
|
|
|
|
|
(float)(sqrt(BLI_ocean_spectrum_texelmarsenarsloe(o, -o->_kx[i], -o->_kz[j]) /
|
|
|
|
|
2.0f)));
|
|
|
|
|
break;
|
|
|
|
|
case MOD_OCEAN_SPECTRUM_PIERSON_MOSKOWITZ:
|
|
|
|
|
mul_complex_f(
|
|
|
|
|
o->_h0[i * o->_N + j],
|
|
|
|
|
r1r2,
|
|
|
|
|
(float)(sqrt(BLI_ocean_spectrum_piersonmoskowitz(o, o->_kx[i], o->_kz[j]) / 2.0f)));
|
|
|
|
|
mul_complex_f(
|
|
|
|
|
o->_h0_minus[i * o->_N + j],
|
|
|
|
|
r1r2,
|
|
|
|
|
(float)(sqrt(BLI_ocean_spectrum_piersonmoskowitz(o, -o->_kx[i], -o->_kz[j]) /
|
|
|
|
|
2.0f)));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
mul_complex_f(
|
|
|
|
|
o->_h0[i * o->_N + j], r1r2, (float)(sqrt(Ph(o, o->_kx[i], o->_kz[j]) / 2.0f)));
|
|
|
|
|
mul_complex_f(o->_h0_minus[i * o->_N + j],
|
|
|
|
|
r1r2,
|
|
|
|
|
(float)(sqrt(Ph(o, -o->_kx[i], -o->_kz[j]) / 2.0f)));
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_fft_in");
|
|
|
|
|
o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_htilda");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-02-16 01:13:46 +11:00
|
|
|
BLI_thread_lock(LOCK_FFTW);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (o->_do_disp_y) {
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
|
2012-04-29 15:47:02 +00:00
|
|
|
o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (o->_do_normals) {
|
2012-05-12 19:18:02 +00:00
|
|
|
o->_fft_in_nx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_fft_in_nx");
|
|
|
|
|
o->_fft_in_nz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_fft_in_nz");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
|
2012-07-29 00:20:28 +00:00
|
|
|
/* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE);
|
|
|
|
|
o->_N_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nz, o->_N_z, FFTW_ESTIMATE);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (o->_do_chop) {
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_fft_in_x = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_fft_in_x");
|
|
|
|
|
o->_fft_in_z = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_fft_in_z");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_disp_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x");
|
|
|
|
|
o->_disp_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
o->_disp_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_x, o->_disp_x, FFTW_ESTIMATE);
|
|
|
|
|
o->_disp_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_z, o->_disp_z, FFTW_ESTIMATE);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
if (o->_do_jacobian) {
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_fft_in_jxx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_fft_in_jxx");
|
|
|
|
|
o->_fft_in_jzz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_fft_in_jzz");
|
|
|
|
|
o->_fft_in_jxz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
|
|
|
|
|
"ocean_fft_in_jxz");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
o->_Jxx = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx");
|
|
|
|
|
o->_Jzz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz");
|
|
|
|
|
o->_Jxz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
o->_Jxx_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxx, o->_Jxx, FFTW_ESTIMATE);
|
|
|
|
|
o->_Jzz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jzz, o->_Jzz, FFTW_ESTIMATE);
|
|
|
|
|
o->_Jxz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxz, o->_Jxz, FFTW_ESTIMATE);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2014-03-01 20:46:58 +01:00
|
|
|
|
2018-02-16 01:13:46 +11:00
|
|
|
BLI_thread_unlock(LOCK_FFTW);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_unlock(&o->oceanmutex);
|
|
|
|
|
|
2011-11-13 16:10:01 +00:00
|
|
|
set_height_normalize_factor(o);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-04-15 23:12:40 +00:00
|
|
|
BLI_rng_free(rng);
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_free_data(struct Ocean *oc)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!oc) {
|
2012-03-24 06:18:31 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-02-16 01:13:46 +11:00
|
|
|
BLI_thread_lock(LOCK_FFTW);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_disp_y) {
|
2011-11-13 12:17:27 +00:00
|
|
|
fftw_destroy_plan(oc->_disp_y_plan);
|
|
|
|
|
MEM_freeN(oc->_disp_y);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_normals) {
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(oc->_fft_in_nx);
|
|
|
|
|
MEM_freeN(oc->_fft_in_nz);
|
|
|
|
|
fftw_destroy_plan(oc->_N_x_plan);
|
|
|
|
|
fftw_destroy_plan(oc->_N_z_plan);
|
|
|
|
|
MEM_freeN(oc->_N_x);
|
|
|
|
|
/*fftwf_free(oc->_N_y); (MEM01)*/
|
|
|
|
|
MEM_freeN(oc->_N_z);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_chop) {
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(oc->_fft_in_x);
|
|
|
|
|
MEM_freeN(oc->_fft_in_z);
|
|
|
|
|
fftw_destroy_plan(oc->_disp_x_plan);
|
|
|
|
|
fftw_destroy_plan(oc->_disp_z_plan);
|
|
|
|
|
MEM_freeN(oc->_disp_x);
|
|
|
|
|
MEM_freeN(oc->_disp_z);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (oc->_do_jacobian) {
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(oc->_fft_in_jxx);
|
|
|
|
|
MEM_freeN(oc->_fft_in_jzz);
|
|
|
|
|
MEM_freeN(oc->_fft_in_jxz);
|
|
|
|
|
fftw_destroy_plan(oc->_Jxx_plan);
|
|
|
|
|
fftw_destroy_plan(oc->_Jzz_plan);
|
|
|
|
|
fftw_destroy_plan(oc->_Jxz_plan);
|
|
|
|
|
MEM_freeN(oc->_Jxx);
|
|
|
|
|
MEM_freeN(oc->_Jzz);
|
|
|
|
|
MEM_freeN(oc->_Jxz);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-02-16 01:13:46 +11:00
|
|
|
BLI_thread_unlock(LOCK_FFTW);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (oc->_fft_in) {
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(oc->_fft_in);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-18 07:38:51 +00:00
|
|
|
/* check that ocean data has been initialized */
|
2011-11-13 12:17:27 +00:00
|
|
|
if (oc->_htilda) {
|
|
|
|
|
MEM_freeN(oc->_htilda);
|
|
|
|
|
MEM_freeN(oc->_k);
|
|
|
|
|
MEM_freeN(oc->_h0);
|
|
|
|
|
MEM_freeN(oc->_h0_minus);
|
|
|
|
|
MEM_freeN(oc->_kx);
|
|
|
|
|
MEM_freeN(oc->_kz);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_unlock(&oc->oceanmutex);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_free(struct Ocean *oc)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!oc) {
|
2012-03-24 06:18:31 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
BKE_ocean_free_data(oc);
|
2011-11-13 12:17:27 +00:00
|
|
|
BLI_rw_mutex_end(&oc->oceanmutex);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(oc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# undef GRAVITY
|
|
|
|
|
|
|
|
|
|
/* ********* Baking/Caching ********* */
|
|
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
# define CACHE_TYPE_DISPLACE 1
|
|
|
|
|
# define CACHE_TYPE_FOAM 2
|
|
|
|
|
# define CACHE_TYPE_NORMAL 3
|
2020-10-20 12:47:58 -05:00
|
|
|
# define CACHE_TYPE_SPRAY 4
|
|
|
|
|
# define CACHE_TYPE_SPRAY_INVERSE 5
|
2011-11-13 12:17:27 +00:00
|
|
|
|
2011-11-20 14:38:11 +00:00
|
|
|
static void cache_filename(
|
|
|
|
|
char *string, const char *path, const char *relbase, int frame, int type)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2011-11-13 15:17:24 +00:00
|
|
|
char cachepath[FILE_MAX];
|
|
|
|
|
const char *fname;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (type) {
|
2012-05-12 19:18:02 +00:00
|
|
|
case CACHE_TYPE_FOAM:
|
|
|
|
|
fname = "foam_";
|
|
|
|
|
break;
|
|
|
|
|
case CACHE_TYPE_NORMAL:
|
|
|
|
|
fname = "normal_";
|
|
|
|
|
break;
|
2020-10-20 12:47:58 -05:00
|
|
|
case CACHE_TYPE_SPRAY:
|
|
|
|
|
fname = "spray_";
|
|
|
|
|
break;
|
|
|
|
|
case CACHE_TYPE_SPRAY_INVERSE:
|
|
|
|
|
fname = "spray_inverse_";
|
|
|
|
|
break;
|
2012-05-12 19:18:02 +00:00
|
|
|
case CACHE_TYPE_DISPLACE:
|
|
|
|
|
default:
|
|
|
|
|
fname = "disp_";
|
|
|
|
|
break;
|
2011-11-13 16:10:01 +00:00
|
|
|
}
|
2011-11-13 15:17:24 +00:00
|
|
|
|
|
|
|
|
BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname);
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
BKE_image_path_from_imtype(
|
|
|
|
|
string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true, "");
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-22 18:03:33 +00:00
|
|
|
/* silly functions but useful to inline when the args do a lot of indirections */
|
|
|
|
|
MINLINE void rgb_to_rgba_unit_alpha(float r_rgba[4], const float rgb[3])
|
|
|
|
|
{
|
2012-05-12 19:18:02 +00:00
|
|
|
r_rgba[0] = rgb[0];
|
|
|
|
|
r_rgba[1] = rgb[1];
|
|
|
|
|
r_rgba[2] = rgb[2];
|
|
|
|
|
r_rgba[3] = 1.0f;
|
2011-11-22 18:03:33 +00:00
|
|
|
}
|
|
|
|
|
MINLINE void value_to_rgba_unit_alpha(float r_rgba[4], const float value)
|
|
|
|
|
{
|
2012-05-12 19:18:02 +00:00
|
|
|
r_rgba[0] = value;
|
|
|
|
|
r_rgba[1] = value;
|
|
|
|
|
r_rgba[2] = value;
|
|
|
|
|
r_rgba[3] = 1.0f;
|
2011-11-22 18:03:33 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_free_cache(struct OceanCache *och)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2012-05-12 19:18:02 +00:00
|
|
|
int i, f = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!och) {
|
2011-11-13 12:17:27 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_disp) {
|
2012-05-12 19:18:02 +00:00
|
|
|
for (i = och->start, f = 0; i <= och->end; i++, f++) {
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_disp[f]) {
|
|
|
|
|
IMB_freeImBuf(och->ibufs_disp[f]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN(och->ibufs_disp);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_foam) {
|
2012-05-12 19:18:02 +00:00
|
|
|
for (i = och->start, f = 0; i <= och->end; i++, f++) {
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_foam[f]) {
|
|
|
|
|
IMB_freeImBuf(och->ibufs_foam[f]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN(och->ibufs_foam);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-20 12:47:58 -05:00
|
|
|
if (och->ibufs_spray) {
|
|
|
|
|
for (i = och->start, f = 0; i <= och->end; i++, f++) {
|
|
|
|
|
if (och->ibufs_spray[f]) {
|
|
|
|
|
IMB_freeImBuf(och->ibufs_spray[f]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN(och->ibufs_spray);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (och->ibufs_spray_inverse) {
|
|
|
|
|
for (i = och->start, f = 0; i <= och->end; i++, f++) {
|
|
|
|
|
if (och->ibufs_spray_inverse[f]) {
|
|
|
|
|
IMB_freeImBuf(och->ibufs_spray_inverse[f]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN(och->ibufs_spray_inverse);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_norm) {
|
2012-05-12 19:18:02 +00:00
|
|
|
for (i = och->start, f = 0; i <= och->end; i++, f++) {
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_norm[f]) {
|
|
|
|
|
IMB_freeImBuf(och->ibufs_norm[f]);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
MEM_freeN(och->ibufs_norm);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (och->time) {
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(och->time);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(och);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
void BKE_ocean_cache_eval_uv(
|
|
|
|
|
struct OceanCache *och, struct OceanResult *ocr, int f, float u, float v)
|
|
|
|
|
{
|
|
|
|
|
int res_x = och->resolution_x;
|
|
|
|
|
int res_y = och->resolution_y;
|
|
|
|
|
float result[4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
u = fmod(u, 1.0);
|
|
|
|
|
v = fmod(v, 1.0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (u < 0) {
|
2011-11-13 12:17:27 +00:00
|
|
|
u += 1.0f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (v < 0) {
|
2011-11-13 16:10:01 +00:00
|
|
|
v += 1.0f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_disp[f]) {
|
2012-05-12 19:18:02 +00:00
|
|
|
ibuf_sample(och->ibufs_disp[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
|
2011-11-22 18:03:33 +00:00
|
|
|
copy_v3_v3(ocr->disp, result);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_foam[f]) {
|
2012-05-12 19:18:02 +00:00
|
|
|
ibuf_sample(och->ibufs_foam[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
|
2011-11-13 12:17:27 +00:00
|
|
|
ocr->foam = result[0];
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-20 12:47:58 -05:00
|
|
|
if (och->ibufs_spray[f]) {
|
|
|
|
|
ibuf_sample(och->ibufs_spray[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
|
|
|
|
|
copy_v3_v3(ocr->Eplus, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (och->ibufs_spray_inverse[f]) {
|
|
|
|
|
ibuf_sample(
|
|
|
|
|
och->ibufs_spray_inverse[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
|
|
|
|
|
copy_v3_v3(ocr->Eminus, result);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_norm[f]) {
|
2012-05-12 19:18:02 +00:00
|
|
|
ibuf_sample(och->ibufs_norm[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
|
2011-11-22 18:03:33 +00:00
|
|
|
copy_v3_v3(ocr->normal, result);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, int f, int i, int j)
|
2011-11-13 16:10:01 +00:00
|
|
|
{
|
2011-11-22 18:03:33 +00:00
|
|
|
const int res_x = och->resolution_x;
|
|
|
|
|
const int res_y = och->resolution_y;
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (i < 0) {
|
2012-05-12 19:18:02 +00:00
|
|
|
i = -i;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (j < 0) {
|
2012-05-12 19:18:02 +00:00
|
|
|
j = -j;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-22 18:03:33 +00:00
|
|
|
i = i % res_x;
|
|
|
|
|
j = j % res_y;
|
2011-11-13 12:17:27 +00:00
|
|
|
|
|
|
|
|
if (och->ibufs_disp[f]) {
|
2012-05-12 19:18:02 +00:00
|
|
|
copy_v3_v3(ocr->disp, &och->ibufs_disp[f]->rect_float[4 * (res_x * j + i)]);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_foam[f]) {
|
2012-05-12 19:18:02 +00:00
|
|
|
ocr->foam = och->ibufs_foam[f]->rect_float[4 * (res_x * j + i)];
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2020-10-20 12:47:58 -05:00
|
|
|
if (och->ibufs_spray[f]) {
|
|
|
|
|
copy_v3_v3(ocr->Eplus, &och->ibufs_spray[f]->rect_float[4 * (res_x * j + i)]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (och->ibufs_spray_inverse[f]) {
|
|
|
|
|
copy_v3_v3(ocr->Eminus, &och->ibufs_spray_inverse[f]->rect_float[4 * (res_x * j + i)]);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (och->ibufs_norm[f]) {
|
2012-05-12 19:18:02 +00:00
|
|
|
copy_v3_v3(ocr->normal, &och->ibufs_norm[f]->rect_float[4 * (res_x * j + i)]);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
struct OceanCache *BKE_ocean_init_cache(const char *bakepath,
|
|
|
|
|
const char *relbase,
|
|
|
|
|
int start,
|
|
|
|
|
int end,
|
|
|
|
|
float wave_scale,
|
2012-05-17 23:21:11 +00:00
|
|
|
float chop_amount,
|
|
|
|
|
float foam_coverage,
|
|
|
|
|
float foam_fade,
|
|
|
|
|
int resolution)
|
|
|
|
|
{
|
2011-11-13 12:17:27 +00:00
|
|
|
OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
och->bakepath = bakepath;
|
2011-11-20 14:38:11 +00:00
|
|
|
och->relbase = relbase;
|
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
och->start = start;
|
|
|
|
|
och->end = end;
|
|
|
|
|
och->duration = (end - start) + 1;
|
|
|
|
|
och->wave_scale = wave_scale;
|
|
|
|
|
och->chop_amount = chop_amount;
|
|
|
|
|
och->foam_coverage = foam_coverage;
|
|
|
|
|
och->foam_fade = foam_fade;
|
2012-05-12 19:18:02 +00:00
|
|
|
och->resolution_x = resolution * resolution;
|
|
|
|
|
och->resolution_y = resolution * resolution;
|
2011-11-13 12:17:27 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
och->ibufs_disp = MEM_callocN(sizeof(ImBuf *) * och->duration,
|
|
|
|
|
"displacement imbuf pointer array");
|
|
|
|
|
och->ibufs_foam = MEM_callocN(sizeof(ImBuf *) * och->duration, "foam imbuf pointer array");
|
2020-10-20 12:47:58 -05:00
|
|
|
och->ibufs_spray = MEM_callocN(sizeof(ImBuf *) * och->duration, "spray imbuf pointer array");
|
|
|
|
|
och->ibufs_spray_inverse = MEM_callocN(sizeof(ImBuf *) * och->duration,
|
|
|
|
|
"spray_inverse imbuf pointer array");
|
2012-05-12 19:18:02 +00:00
|
|
|
och->ibufs_norm = MEM_callocN(sizeof(ImBuf *) * och->duration, "normal imbuf pointer array");
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
och->time = NULL;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
return och;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_simulate_cache(struct OceanCache *och, int frame)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
char string[FILE_MAX];
|
|
|
|
|
int f = frame;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
/* ibufs array is zero based, but filenames are based on frame numbers */
|
|
|
|
|
/* still need to clamp frame numbers to valid range of images on disk though */
|
|
|
|
|
CLAMP(frame, och->start, och->end);
|
2013-01-02 16:03:58 +00:00
|
|
|
f = frame - och->start; /* shift to 0 based */
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
/* if image is already loaded in mem, return */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (och->ibufs_disp[f] != NULL) {
|
2012-05-12 19:18:02 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Use default color spaces since we know for sure cache
|
|
|
|
|
* files were saved with default settings too. */
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-20 14:38:11 +00:00
|
|
|
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
och->ibufs_disp[f] = IMB_loadiffname(string, 0, NULL);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-20 14:38:11 +00:00
|
|
|
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2020-10-20 12:47:58 -05:00
|
|
|
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_SPRAY);
|
|
|
|
|
och->ibufs_spray[f] = IMB_loadiffname(string, 0, NULL);
|
|
|
|
|
|
|
|
|
|
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_SPRAY_INVERSE);
|
|
|
|
|
och->ibufs_spray_inverse[f] = IMB_loadiffname(string, 0, NULL);
|
|
|
|
|
|
2011-11-20 14:38:11 +00:00
|
|
|
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_bake(struct Ocean *o,
|
|
|
|
|
struct OceanCache *och,
|
|
|
|
|
void (*update_cb)(void *, float progress, int *cancel),
|
2013-01-02 16:03:58 +00:00
|
|
|
void *update_cb_data)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2011-11-14 05:55:50 +00:00
|
|
|
/* note: some of these values remain uninitialized unless certain options
|
|
|
|
|
* are enabled, take care that BKE_ocean_eval_ij() initializes a member
|
|
|
|
|
* before use - campbell */
|
|
|
|
|
OceanResult ocr;
|
|
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
ImageFormatData imf = {0};
|
2011-11-21 20:19:58 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
int f, i = 0, x, y, cancel = 0;
|
2011-11-13 12:17:27 +00:00
|
|
|
float progress;
|
2011-11-14 05:55:50 +00:00
|
|
|
|
2020-10-20 12:47:58 -05:00
|
|
|
ImBuf *ibuf_foam, *ibuf_disp, *ibuf_normal, *ibuf_spray, *ibuf_spray_inverse;
|
2011-11-13 12:17:27 +00:00
|
|
|
float *prev_foam;
|
|
|
|
|
int res_x = och->resolution_x;
|
|
|
|
|
int res_y = och->resolution_y;
|
|
|
|
|
char string[FILE_MAX];
|
2019-05-01 11:09:22 +10:00
|
|
|
// RNG *rng;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!o) {
|
2011-11-13 12:17:27 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (o->_do_jacobian) {
|
2012-05-12 19:18:02 +00:00
|
|
|
prev_foam = MEM_callocN(res_x * res_y * sizeof(float), "previous frame foam bake data");
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-12 19:18:02 +00:00
|
|
|
prev_foam = NULL;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-05-01 11:09:22 +10:00
|
|
|
// rng = BLI_rng_new(0);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-21 20:19:58 +00:00
|
|
|
/* setup image format */
|
2012-05-12 19:18:02 +00:00
|
|
|
imf.imtype = R_IMF_IMTYPE_OPENEXR;
|
|
|
|
|
imf.depth = R_IMF_CHAN_DEPTH_16;
|
|
|
|
|
imf.exr_codec = R_IMF_EXR_CODEC_ZIP;
|
2011-11-21 20:19:58 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
for (f = och->start, i = 0; f <= och->end; f++, i++) {
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
/* create a new imbuf to store image for this frame */
|
|
|
|
|
ibuf_foam = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
|
|
|
|
|
ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
|
|
|
|
|
ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
|
2020-10-20 12:47:58 -05:00
|
|
|
ibuf_spray = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
|
|
|
|
|
ibuf_spray_inverse = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
BKE_ocean_simulate(o, och->time[i], och->wave_scale, och->chop_amount);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
/* add new foam */
|
2012-05-12 19:18:02 +00:00
|
|
|
for (y = 0; y < res_y; y++) {
|
|
|
|
|
for (x = 0; x < res_x; x++) {
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
BKE_ocean_eval_ij(o, &ocr, x, y);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-14 05:55:50 +00:00
|
|
|
/* add to the image */
|
2012-05-12 19:18:02 +00:00
|
|
|
rgb_to_rgba_unit_alpha(&ibuf_disp->rect_float[4 * (res_x * y + x)], ocr.disp);
|
2011-11-14 05:55:50 +00:00
|
|
|
|
|
|
|
|
if (o->_do_jacobian) {
|
|
|
|
|
/* TODO, cleanup unused code - campbell */
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
float /*r, */ /* UNUSED */ pr = 0.0f, foam_result;
|
2011-11-14 05:55:50 +00:00
|
|
|
float neg_disp, neg_eplus;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-14 05:55:50 +00:00
|
|
|
ocr.foam = BKE_ocean_jminus_to_foam(ocr.Jminus, och->foam_coverage);
|
2011-11-13 12:17:27 +00:00
|
|
|
|
2011-11-14 05:55:50 +00:00
|
|
|
/* accumulate previous value for this cell */
|
|
|
|
|
if (i > 0) {
|
2012-05-12 19:18:02 +00:00
|
|
|
pr = prev_foam[res_x * y + x];
|
2011-11-14 05:55:50 +00:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2013-04-15 23:12:40 +00:00
|
|
|
/* r = BLI_rng_get_float(rng); */ /* UNUSED */ /* randomly reduce foam */
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* pr = pr * och->foam_fade; */ /* overall fade */
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Remember ocean coord sys is Y up!
|
|
|
|
|
* break up the foam where height (Y) is low (wave valley),
|
|
|
|
|
* and X and Z displacement is greatest. */
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
neg_disp = ocr.disp[1] < 0.0f ? 1.0f + ocr.disp[1] : 1.0f;
|
2011-11-14 05:55:50 +00:00
|
|
|
neg_disp = neg_disp < 0.0f ? 0.0f : neg_disp;
|
2011-11-13 12:17:27 +00:00
|
|
|
|
2011-11-14 05:55:50 +00:00
|
|
|
/* foam, 'ocr.Eplus' only initialized with do_jacobian */
|
2012-05-12 19:18:02 +00:00
|
|
|
neg_eplus = ocr.Eplus[2] < 0.0f ? 1.0f + ocr.Eplus[2] : 1.0f;
|
|
|
|
|
neg_eplus = neg_eplus < 0.0f ? 0.0f : neg_eplus;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (pr < 1.0f) {
|
2013-01-02 16:03:58 +00:00
|
|
|
pr *= pr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-14 05:55:50 +00:00
|
|
|
pr *= och->foam_fade * (0.75f + neg_eplus * 0.25f);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* A full clamping should not be needed! */
|
|
|
|
|
foam_result = min_ff(pr + ocr.foam, 1.0f);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
prev_foam[res_x * y + x] = foam_result;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/*foam_result = min_ff(foam_result, 1.0f); */
|
|
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4 * (res_x * y + x)], foam_result);
|
2020-10-20 12:47:58 -05:00
|
|
|
|
|
|
|
|
/* spray map baking */
|
|
|
|
|
if (o->_do_spray) {
|
|
|
|
|
rgb_to_rgba_unit_alpha(&ibuf_spray->rect_float[4 * (res_x * y + x)], ocr.Eplus);
|
|
|
|
|
rgb_to_rgba_unit_alpha(&ibuf_spray_inverse->rect_float[4 * (res_x * y + x)],
|
|
|
|
|
ocr.Eminus);
|
|
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (o->_do_normals) {
|
2012-05-12 19:18:02 +00:00
|
|
|
rgb_to_rgba_unit_alpha(&ibuf_normal->rect_float[4 * (res_x * y + x)], ocr.normal);
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
/* write the images */
|
2011-11-20 14:38:11 +00:00
|
|
|
cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_DISPLACE);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (0 == BKE_imbuf_write(ibuf_disp, string, &imf)) {
|
2011-11-13 12:17:27 +00:00
|
|
|
printf("Cannot save Displacement File Output to %s\n", string);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (o->_do_jacobian) {
|
2012-05-20 19:49:27 +00:00
|
|
|
cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_FOAM);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (0 == BKE_imbuf_write(ibuf_foam, string, &imf)) {
|
2011-11-13 12:17:27 +00:00
|
|
|
printf("Cannot save Foam File Output to %s\n", string);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-10-20 12:47:58 -05:00
|
|
|
|
|
|
|
|
if (o->_do_spray) {
|
|
|
|
|
cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_SPRAY);
|
|
|
|
|
if (0 == BKE_imbuf_write(ibuf_spray, string, &imf)) {
|
|
|
|
|
printf("Cannot save Spray File Output to %s\n", string);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_SPRAY_INVERSE);
|
|
|
|
|
if (0 == BKE_imbuf_write(ibuf_spray_inverse, string, &imf)) {
|
|
|
|
|
printf("Cannot save Spray Inverse File Output to %s\n", string);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (o->_do_normals) {
|
2012-05-20 19:49:27 +00:00
|
|
|
cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_NORMAL);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (0 == BKE_imbuf_write(ibuf_normal, string, &imf)) {
|
2011-11-13 12:17:27 +00:00
|
|
|
printf("Cannot save Normal File Output to %s\n", string);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
IMB_freeImBuf(ibuf_disp);
|
|
|
|
|
IMB_freeImBuf(ibuf_foam);
|
|
|
|
|
IMB_freeImBuf(ibuf_normal);
|
2020-10-20 12:47:58 -05:00
|
|
|
IMB_freeImBuf(ibuf_spray);
|
|
|
|
|
IMB_freeImBuf(ibuf_spray_inverse);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
progress = (f - och->start) / (float)och->duration;
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
update_cb(update_cb_data, progress, &cancel);
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
if (cancel) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (prev_foam) {
|
2011-11-14 05:55:50 +00:00
|
|
|
MEM_freeN(prev_foam);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-05-01 11:09:22 +10:00
|
|
|
// BLI_rng_free(rng);
|
2011-11-13 12:17:27 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2019-05-01 11:09:22 +10:00
|
|
|
// BLI_rng_free(rng);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (prev_foam) {
|
2011-11-14 05:55:50 +00:00
|
|
|
MEM_freeN(prev_foam);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
och->baked = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
#else /* WITH_OCEANSIM */
|
2011-11-13 12:17:27 +00:00
|
|
|
|
2011-12-17 00:52:36 +00:00
|
|
|
float BKE_ocean_jminus_to_foam(float UNUSED(jminus), float UNUSED(coverage))
|
|
|
|
|
{
|
2011-11-13 12:17:27 +00:00
|
|
|
return 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
void BKE_ocean_eval_uv(struct Ocean *UNUSED(oc),
|
|
|
|
|
struct OceanResult *UNUSED(ocr),
|
|
|
|
|
float UNUSED(u),
|
|
|
|
|
float UNUSED(v))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
/* use catmullrom interpolation rather than linear */
|
|
|
|
|
void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc),
|
|
|
|
|
struct OceanResult *UNUSED(ocr),
|
|
|
|
|
float UNUSED(u),
|
|
|
|
|
float UNUSED(v))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
void BKE_ocean_eval_xz(struct Ocean *UNUSED(oc),
|
|
|
|
|
struct OceanResult *UNUSED(ocr),
|
|
|
|
|
float UNUSED(x),
|
|
|
|
|
float UNUSED(z))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc),
|
|
|
|
|
struct OceanResult *UNUSED(ocr),
|
|
|
|
|
float UNUSED(x),
|
|
|
|
|
float UNUSED(z))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
void BKE_ocean_eval_ij(struct Ocean *UNUSED(oc),
|
|
|
|
|
struct OceanResult *UNUSED(ocr),
|
|
|
|
|
int UNUSED(i),
|
|
|
|
|
int UNUSED(j))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_simulate(struct Ocean *UNUSED(o),
|
|
|
|
|
float UNUSED(t),
|
|
|
|
|
float UNUSED(scale),
|
|
|
|
|
float UNUSED(chop_amount))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
struct Ocean *BKE_ocean_add(void)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data");
|
|
|
|
|
|
|
|
|
|
return oc;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_init(struct Ocean *UNUSED(o),
|
|
|
|
|
int UNUSED(M),
|
|
|
|
|
int UNUSED(N),
|
|
|
|
|
float UNUSED(Lx),
|
|
|
|
|
float UNUSED(Lz),
|
2013-01-02 16:03:58 +00:00
|
|
|
float UNUSED(V),
|
|
|
|
|
float UNUSED(l),
|
|
|
|
|
float UNUSED(A),
|
|
|
|
|
float UNUSED(w),
|
|
|
|
|
float UNUSED(damp),
|
|
|
|
|
float UNUSED(alignment),
|
|
|
|
|
float UNUSED(depth),
|
|
|
|
|
float UNUSED(time),
|
2020-03-12 13:35:22 +11:00
|
|
|
int UNUSED(spectrum),
|
|
|
|
|
float UNUSED(fetch_jonswap),
|
|
|
|
|
float UNUSED(sharpen_peak_jonswap),
|
2013-01-02 16:03:58 +00:00
|
|
|
short UNUSED(do_height_field),
|
|
|
|
|
short UNUSED(do_chop),
|
2020-10-20 12:47:58 -05:00
|
|
|
short UNUSED(do_spray),
|
2013-01-02 16:03:58 +00:00
|
|
|
short UNUSED(do_normals),
|
|
|
|
|
short UNUSED(do_jacobian),
|
|
|
|
|
int UNUSED(seed))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_free_data(struct Ocean *UNUSED(oc))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_free(struct Ocean *oc)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!oc) {
|
2012-03-24 06:18:31 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(oc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ********* Baking/Caching ********* */
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_free_cache(struct OceanCache *och)
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!och) {
|
2011-11-13 12:17:27 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
MEM_freeN(och);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och),
|
|
|
|
|
struct OceanResult *UNUSED(ocr),
|
|
|
|
|
int UNUSED(f),
|
|
|
|
|
float UNUSED(u),
|
|
|
|
|
float UNUSED(v))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-02 16:03:58 +00:00
|
|
|
void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och),
|
|
|
|
|
struct OceanResult *UNUSED(ocr),
|
|
|
|
|
int UNUSED(f),
|
|
|
|
|
int UNUSED(i),
|
|
|
|
|
int UNUSED(j))
|
2011-11-13 16:10:01 +00:00
|
|
|
{
|
2011-11-13 12:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
OceanCache *BKE_ocean_init_cache(const char *UNUSED(bakepath),
|
|
|
|
|
const char *UNUSED(relbase),
|
|
|
|
|
int UNUSED(start),
|
2013-01-02 16:03:58 +00:00
|
|
|
int UNUSED(end),
|
|
|
|
|
float UNUSED(wave_scale),
|
|
|
|
|
float UNUSED(chop_amount),
|
|
|
|
|
float UNUSED(foam_coverage),
|
|
|
|
|
float UNUSED(foam_fade),
|
|
|
|
|
int UNUSED(resolution))
|
2012-05-17 23:21:11 +00:00
|
|
|
{
|
2011-11-13 12:17:27 +00:00
|
|
|
OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
|
2011-11-13 16:10:01 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
return och;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_simulate_cache(struct OceanCache *UNUSED(och), int UNUSED(frame))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 15:18:52 +11:00
|
|
|
void BKE_ocean_bake(struct Ocean *UNUSED(o),
|
|
|
|
|
struct OceanCache *UNUSED(och),
|
2013-01-02 16:03:58 +00:00
|
|
|
void (*update_cb)(void *, float progress, int *cancel),
|
|
|
|
|
void *UNUSED(update_cb_data))
|
2011-11-13 12:17:27 +00:00
|
|
|
{
|
|
|
|
|
/* unused */
|
|
|
|
|
(void)update_cb;
|
|
|
|
|
}
|
2018-07-10 11:58:01 +02:00
|
|
|
|
|
|
|
|
void BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean),
|
2020-08-03 10:08:31 -04:00
|
|
|
struct OceanModifierData const *UNUSED(omd),
|
|
|
|
|
int UNUSED(resolution))
|
2018-07-10 11:58:01 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-24 21:57:13 +00:00
|
|
|
#endif /* WITH_OCEANSIM */
|
2018-07-05 16:23:35 +02:00
|
|
|
|
|
|
|
|
void BKE_ocean_free_modifier_cache(struct OceanModifierData *omd)
|
|
|
|
|
{
|
|
|
|
|
BKE_ocean_free_cache(omd->oceancache);
|
|
|
|
|
omd->oceancache = NULL;
|
|
|
|
|
omd->cached = false;
|
|
|
|
|
}
|