complex multiply_complex(complex *a, complex *b) { return init_complex(a->x * b->x - a->y * b->y, a->x * b->y+ a->y * b->x); }
complex substract_complex(complex *a, complex *b) { return init_complex(a->x - b->x, a->y - b->y); }
void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp, float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed) { int i, j, ii; BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); o->_M = M; o->_N = N; o->_V = V; o->_l = l; o->_A = A; o->_w = w; o->_damp_reflections = 1.0f - damp; o->_wind_alignment = alignment; o->_depth = depth; o->_Lx = Lx; o->_Lz = Lz; o->_wx = cos(w); o->_wz = -sin(w); /* wave direction */ o->_L = V * V / GRAVITY; /* largest wave for a given velocity V */ o->time = time; o->_do_disp_y = do_height_field; o->_do_normals = do_normals; o->_do_chop = do_chop; o->_do_jacobian = do_jacobian; 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"); o->_h0_minus = (fftw_complex *) MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus"); o->_kx = (float *) MEM_mallocN(o->_M * sizeof(float), "ocean_kx"); o->_kz = (float *) MEM_mallocN(o->_N * sizeof(float), "ocean_kz"); /* make this robust in the face of erroneous usage */ if (o->_Lx == 0.0f) o->_Lx = 0.001f; if (o->_Lz == 0.0f) o->_Lz = 0.001f; /* the +ve components and DC */ for (i = 0; i <= o->_M / 2; ++i) o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx; /* the -ve components */ for (i = o->_M - 1, ii = 0; i > o->_M / 2; --i, ++ii) o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx; /* the +ve components and DC */ for (i = 0; i <= o->_N / 2; ++i) o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz; /* the -ve components */ for (i = o->_N - 1, ii = 0; i > o->_N / 2; --i, ++ii) o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz; /* pre-calculate the k matrix */ for (i = 0; i < o->_M; ++i) for (j = 0; j <= o->_N / 2; ++j) o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]); /*srand(seed);*/ BLI_srand(seed); for (i = 0; i < o->_M; ++i) { for (j = 0; j < o->_N; ++j) { float r1 = gaussRand(); float r2 = gaussRand(); fftw_complex r1r2; init_complex(r1r2, r1, r2); 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))); } } 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"); if (o->_do_disp_y) { o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y"); o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE); } if (o->_do_normals) { 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"); o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x"); /* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */ o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z"); 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); } if (o->_do_chop) { 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"); 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"); 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); } if (o->_do_jacobian) { 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"); 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"); 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); } BLI_rw_mutex_unlock(&o->oceanmutex); set_height_normalize_factor(o); }
complex add_complex(complex *a, complex *b) { return init_complex(a->x + b->x, a->y + b->y); }
void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount) { int i, j; scale *= o->normalize_factor; BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); /* compute a new htilda */ #pragma omp parallel for private(i, j) for (i = 0; i < o->_M; ++i) { /* note the <= _N/2 here, see the fftw doco about the mechanics of the complex->real fft storage */ for (j = 0; j <= o->_N / 2; ++j) { fftw_complex exp_param1; fftw_complex exp_param2; fftw_complex conj_param; 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]); mul_complex_c(exp_param1, o->_h0[i * o->_N + j], exp_param1); mul_complex_c(exp_param2, conj_param, exp_param2); 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); } } #pragma omp parallel sections private(i, j) { #pragma omp section { if (o->_do_disp_y) { /* y displacement */ fftw_execute(o->_disp_y_plan); } } /* section 1 */ #pragma omp section { if (o->_do_chop) { /* x displacement */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; fftw_complex minus_i; 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)); } } fftw_execute(o->_disp_x_plan); } } /* section 2 */ #pragma omp section { if (o->_do_chop) { /* z displacement */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; fftw_complex minus_i; 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)); } } fftw_execute(o->_disp_z_plan); } } /* section 3 */ #pragma omp section { if (o->_do_jacobian) { /* Jxx */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); 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)); } } fftw_execute(o->_Jxx_plan); for (i = 0; i < o->_M; ++i) { for (j = 0; j < o->_N; ++j) { o->_Jxx[i * o->_N + j] += 1.0; } } } } /* section 4 */ #pragma omp section { if (o->_do_jacobian) { /* Jzz */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); 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)); } } fftw_execute(o->_Jzz_plan); for (i = 0; i < o->_M; ++i) { for (j = 0; j < o->_N; ++j) { o->_Jzz[i * o->_N + j] += 1.0; } } } } /* section 5 */ #pragma omp section { if (o->_do_jacobian) { /* Jxz */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); 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); } } /* section 6 */ #pragma omp section { /* fft normals */ if (o->_do_normals) { for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; 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); } } /* section 7 */ #pragma omp section { if (o->_do_normals) { for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; 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); #if 0 for (i = 0; i < o->_M; ++i) { for (j = 0; j < o->_N; ++j) { o->_N_y[i * o->_N + j] = 1.0f / scale; } } (MEM01) #endif o->_N_y = 1.0f / scale; } } /* section 8 */ } /* omp sections */ BLI_rw_mutex_unlock(&o->oceanmutex); }