Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributors: Matt Ebb, Hamed Zaghaghi 00022 * Based on original code by Drew Whitehouse / Houdini Ocean Toolkit 00023 * OpenMP hints by Christian Schnellhammer 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00028 00029 #include <math.h> 00030 #include <stdlib.h> 00031 00032 #include <string.h> 00033 00034 #include "MEM_guardedalloc.h" 00035 00036 #include "DNA_scene_types.h" 00037 00038 #include "BKE_image.h" 00039 #include "BKE_ocean.h" 00040 #include "BKE_utildefines.h" 00041 00042 #include "BKE_global.h" // XXX TESTING 00043 00044 #include "BLI_math_base.h" 00045 #include "BLI_math_inline.h" 00046 #include "BLI_rand.h" 00047 #include "BLI_string.h" 00048 #include "BLI_threads.h" 00049 #include "BLI_path_util.h" 00050 #include "BLI_utildefines.h" 00051 00052 #include "IMB_imbuf.h" 00053 #include "IMB_imbuf_types.h" 00054 00055 #include "RE_render_ext.h" 00056 00057 #ifdef WITH_OCEANSIM 00058 00059 // Ocean code 00060 #include "fftw3.h" 00061 00062 #define GRAVITY 9.81f 00063 00064 typedef struct Ocean { 00065 /* ********* input parameters to the sim ********* */ 00066 float _V; 00067 float _l; 00068 float _w; 00069 float _A; 00070 float _damp_reflections; 00071 float _wind_alignment; 00072 float _depth; 00073 00074 float _wx; 00075 float _wz; 00076 00077 float _L; 00078 00079 /* dimensions of computational grid */ 00080 int _M; 00081 int _N; 00082 00083 /* spatial size of computational grid */ 00084 float _Lx; 00085 float _Lz; 00086 00087 float normalize_factor; // init w 00088 float time; 00089 00090 short _do_disp_y; 00091 short _do_normals; 00092 short _do_chop; 00093 short _do_jacobian; 00094 00095 /* mutex for threaded texture access */ 00096 ThreadRWMutex oceanmutex; 00097 00098 /* ********* sim data arrays ********* */ 00099 00100 /* two dimensional arrays of complex */ 00101 fftw_complex *_fft_in; // init w sim w 00102 fftw_complex *_fft_in_x; // init w sim w 00103 fftw_complex *_fft_in_z; // init w sim w 00104 fftw_complex *_fft_in_jxx; // init w sim w 00105 fftw_complex *_fft_in_jzz; // init w sim w 00106 fftw_complex *_fft_in_jxz; // init w sim w 00107 fftw_complex *_fft_in_nx; // init w sim w 00108 fftw_complex *_fft_in_nz; // init w sim w 00109 fftw_complex *_htilda; // init w sim w (only once) 00110 00111 /* fftw "plans" */ 00112 fftw_plan _disp_y_plan; // init w sim r 00113 fftw_plan _disp_x_plan; // init w sim r 00114 fftw_plan _disp_z_plan; // init w sim r 00115 fftw_plan _N_x_plan; // init w sim r 00116 fftw_plan _N_z_plan; // init w sim r 00117 fftw_plan _Jxx_plan; // init w sim r 00118 fftw_plan _Jxz_plan; // init w sim r 00119 fftw_plan _Jzz_plan; // init w sim r 00120 00121 /* two dimensional arrays of float */ 00122 double * _disp_y; // init w sim w via plan? 00123 double * _N_x; // init w sim w via plan? 00124 /*float * _N_y; all member of this array has same values, so convert this array to a float to reduce memory usage (MEM01)*/ 00125 double _N_y; // sim w ********* can be rearranged? 00126 double * _N_z; // init w sim w via plan? 00127 double * _disp_x; // init w sim w via plan? 00128 double * _disp_z; // init w sim w via plan? 00129 00130 /* two dimensional arrays of float */ 00131 /* Jacobian and minimum eigenvalue */ 00132 double * _Jxx; // init w sim w 00133 double * _Jzz; // init w sim w 00134 double * _Jxz; // init w sim w 00135 00136 /* one dimensional float array */ 00137 float * _kx; // init w sim r 00138 float * _kz; // init w sim r 00139 00140 /* two dimensional complex array */ 00141 fftw_complex * _h0; // init w sim r 00142 fftw_complex * _h0_minus; // init w sim r 00143 00144 /* two dimensional float array */ 00145 float * _k; // init w sim r 00146 } Ocean; 00147 00148 00149 00150 static float nextfr(float min, float max) 00151 { 00152 return BLI_frand()*(min-max)+max; 00153 } 00154 00155 static float gaussRand (void) 00156 { 00157 float x; // Note: to avoid numerical problems with very small 00158 float y; // numbers, we make these variables singe-precision 00159 float length2; // floats, but later we call the double-precision log() 00160 // and sqrt() functions instead of logf() and sqrtf(). 00161 do 00162 { 00163 x = (float) (nextfr (-1, 1)); 00164 y = (float)(nextfr (-1, 1)); 00165 length2 = x * x + y * y; 00166 } 00167 while (length2 >= 1 || length2 == 0); 00168 00169 return x * sqrtf(-2.0f * logf(length2) / length2); 00170 } 00171 00175 MINLINE float lerp(float a,float b,float f) 00176 { 00177 return a + (b-a)*f; 00178 } 00179 00180 MINLINE float catrom(float p0,float p1,float p2,float p3,float f) 00181 { 00182 return 0.5f *((2.0f * p1) + 00183 (-p0 + p2) * f + 00184 (2.0f*p0 - 5.0f*p1 + 4.0f*p2 - p3) * f*f + 00185 (-p0 + 3.0f*p1- 3.0f*p2 + p3) * f*f*f); 00186 } 00187 00188 MINLINE float omega(float k, float depth) 00189 { 00190 return sqrt(GRAVITY*k * tanh(k*depth)); 00191 } 00192 00193 // modified Phillips spectrum 00194 static float Ph(struct Ocean* o, float kx,float kz ) 00195 { 00196 float tmp; 00197 float k2 = kx*kx + kz*kz; 00198 00199 if (k2 == 0.0f) 00200 { 00201 return 0.0f; // no DC component 00202 } 00203 00204 // damp out the waves going in the direction opposite the wind 00205 tmp = (o->_wx * kx + o->_wz * kz)/sqrtf(k2); 00206 if (tmp < 0) 00207 { 00208 tmp *= o->_damp_reflections; 00209 } 00210 00211 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); 00212 } 00213 00214 static void compute_eigenstuff(struct OceanResult *ocr, float jxx,float jzz,float jxz) 00215 { 00216 float a,b,qplus,qminus; 00217 a = jxx + jzz; 00218 b = sqrt((jxx - jzz)*(jxx - jzz) + 4 * jxz * jxz); 00219 00220 ocr->Jminus = 0.5f*(a-b); 00221 ocr->Jplus = 0.5f*(a+b); 00222 00223 qplus = (ocr->Jplus - jxx)/jxz; 00224 qminus = (ocr->Jminus - jxx)/jxz; 00225 00226 a = sqrt(1 + qplus*qplus); 00227 b = sqrt(1 + qminus*qminus); 00228 00229 ocr->Eplus[0] = 1.0f/ a; 00230 ocr->Eplus[1] = 0.0f; 00231 ocr->Eplus[2] = qplus/a; 00232 00233 ocr->Eminus[0] = 1.0f/b; 00234 ocr->Eminus[1] = 0.0f; 00235 ocr->Eminus[2] = qminus/b; 00236 } 00237 00238 /* 00239 * instead of Complex.h 00240 * in fftw.h "fftw_complex" typedefed as double[2] 00241 * below you can see functions are needed to work with such complex numbers. 00242 * */ 00243 static void init_complex(fftw_complex cmpl, float real, float image) 00244 { 00245 cmpl[0] = real; 00246 cmpl[1] = image; 00247 } 00248 00249 #if 0 // unused 00250 static void add_complex_f(fftw_complex res, fftw_complex cmpl, float f) 00251 { 00252 res[0] = cmpl[0] + f; 00253 res[1] = cmpl[1]; 00254 } 00255 #endif 00256 00257 static void add_comlex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) 00258 { 00259 res[0] = cmpl1[0] + cmpl2[0]; 00260 res[1] = cmpl1[1] + cmpl2[1]; 00261 } 00262 00263 static void mul_complex_f(fftw_complex res, fftw_complex cmpl, float f) 00264 { 00265 res[0] = cmpl[0]*f; 00266 res[1] = cmpl[1]*f; 00267 } 00268 00269 static void mul_complex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) 00270 { 00271 fftwf_complex temp; 00272 temp[0] = cmpl1[0]*cmpl2[0]-cmpl1[1]*cmpl2[1]; 00273 temp[1] = cmpl1[0]*cmpl2[1]+cmpl1[1]*cmpl2[0]; 00274 res[0] = temp[0]; 00275 res[1] = temp[1]; 00276 } 00277 00278 static float real_c(fftw_complex cmpl) 00279 { 00280 return cmpl[0]; 00281 } 00282 00283 static float image_c(fftw_complex cmpl) 00284 { 00285 return cmpl[1]; 00286 } 00287 00288 static void conj_complex(fftw_complex res, fftw_complex cmpl1) 00289 { 00290 res[0] = cmpl1[0]; 00291 res[1] = -cmpl1[1]; 00292 } 00293 00294 static void exp_complex(fftw_complex res, fftw_complex cmpl) 00295 { 00296 float r = expf(cmpl[0]); 00297 00298 res[0] = cos(cmpl[1])*r; 00299 res[1] = sin(cmpl[1])*r; 00300 } 00301 00302 float BKE_ocean_jminus_to_foam(float jminus, float coverage) 00303 { 00304 float foam = jminus * -0.005f + coverage; 00305 CLAMP(foam, 0.0f, 1.0f); 00306 return foam*foam; 00307 } 00308 00309 void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u,float v) 00310 { 00311 int i0,i1,j0,j1; 00312 float frac_x,frac_z; 00313 float uu,vv; 00314 00315 // first wrap the texture so 0 <= (u,v) < 1 00316 u = fmodf(u,1.0f); 00317 v = fmodf(v,1.0f); 00318 00319 if (u < 0) u += 1.0f; 00320 if (v < 0) v += 1.0f; 00321 00322 BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); 00323 00324 uu = u * oc->_M; 00325 vv = v * oc->_N; 00326 00327 i0 = (int)floor(uu); 00328 j0 = (int)floor(vv); 00329 00330 i1 = (i0 + 1); 00331 j1 = (j0 + 1); 00332 00333 frac_x = uu - i0; 00334 frac_z = vv - j0; 00335 00336 i0 = i0 % oc->_M; 00337 j0 = j0 % oc->_N; 00338 00339 i1 = i1 % oc->_M; 00340 j1 = j1 % oc->_N; 00341 00342 00343 #define BILERP(m) (lerp(lerp(m[i0*oc->_N+j0],m[i1*oc->_N+j0],frac_x),lerp(m[i0*oc->_N+j1],m[i1*oc->_N+j1],frac_x),frac_z)) 00344 { 00345 if (oc->_do_disp_y) { 00346 ocr->disp[1] = BILERP(oc->_disp_y); 00347 } 00348 00349 if (oc->_do_normals) { 00350 ocr->normal[0] = BILERP(oc->_N_x); 00351 ocr->normal[1] = oc->_N_y/*BILERP(oc->_N_y) (MEM01)*/; 00352 ocr->normal[2] = BILERP(oc->_N_z); 00353 } 00354 00355 if (oc->_do_chop) { 00356 ocr->disp[0] = BILERP(oc->_disp_x); 00357 ocr->disp[2] = BILERP(oc->_disp_z); 00358 } else { 00359 ocr->disp[0] = 0.0; 00360 ocr->disp[2] = 0.0; 00361 } 00362 00363 if (oc->_do_jacobian) { 00364 compute_eigenstuff(ocr, BILERP(oc->_Jxx),BILERP(oc->_Jzz),BILERP(oc->_Jxz)); 00365 } 00366 } 00367 #undef BILERP 00368 00369 BLI_rw_mutex_unlock(&oc->oceanmutex); 00370 } 00371 00372 // use catmullrom interpolation rather than linear 00373 void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u,float v) 00374 { 00375 int i0,i1,i2,i3,j0,j1,j2,j3; 00376 float frac_x,frac_z; 00377 float uu,vv; 00378 00379 // first wrap the texture so 0 <= (u,v) < 1 00380 u = fmod(u,1.0f); 00381 v = fmod(v,1.0f); 00382 00383 if (u < 0) u += 1.0f; 00384 if (v < 0) v += 1.0f; 00385 00386 BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); 00387 00388 uu = u * oc->_M; 00389 vv = v * oc->_N; 00390 00391 i1 = (int)floor(uu); 00392 j1 = (int)floor(vv); 00393 00394 i2 = (i1 + 1); 00395 j2 = (j1 + 1); 00396 00397 frac_x = uu - i1; 00398 frac_z = vv - j1; 00399 00400 i1 = i1 % oc->_M; 00401 j1 = j1 % oc->_N; 00402 00403 i2 = i2 % oc->_M; 00404 j2 = j2 % oc->_N; 00405 00406 i0 = (i1-1); 00407 i3 = (i2+1); 00408 i0 = i0 < 0 ? i0 + oc->_M : i0; 00409 i3 = i3 >= oc->_M ? i3 - oc->_M : i3; 00410 00411 j0 = (j1-1); 00412 j3 = (j2+1); 00413 j0 = j0 < 0 ? j0 + oc->_N : j0; 00414 j3 = j3 >= oc->_N ? j3 - oc->_N : j3; 00415 00416 #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),\ 00417 catrom(m[i0*oc->_N+j1],m[i1*oc->_N+j1],m[i2*oc->_N+j1],m[i3*oc->_N+j1],frac_x),\ 00418 catrom(m[i0*oc->_N+j2],m[i1*oc->_N+j2],m[i2*oc->_N+j2],m[i3*oc->_N+j2],frac_x),\ 00419 catrom(m[i0*oc->_N+j3],m[i1*oc->_N+j3],m[i2*oc->_N+j3],m[i3*oc->_N+j3],frac_x),\ 00420 frac_z) 00421 00422 { 00423 if (oc->_do_disp_y) 00424 { 00425 ocr->disp[1] = INTERP(oc->_disp_y) ; 00426 } 00427 if (oc->_do_normals) 00428 { 00429 ocr->normal[0] = INTERP(oc->_N_x); 00430 ocr->normal[1] = oc->_N_y/*INTERP(oc->_N_y) (MEM01)*/; 00431 ocr->normal[2] = INTERP(oc->_N_z); 00432 } 00433 if (oc->_do_chop) 00434 { 00435 ocr->disp[0] = INTERP(oc->_disp_x); 00436 ocr->disp[2] = INTERP(oc->_disp_z); 00437 } 00438 else 00439 { 00440 ocr->disp[0] = 0.0; 00441 ocr->disp[2] = 0.0; 00442 } 00443 00444 if (oc->_do_jacobian) 00445 { 00446 compute_eigenstuff(ocr, INTERP(oc->_Jxx),INTERP(oc->_Jzz),INTERP(oc->_Jxz)); 00447 } 00448 } 00449 #undef INTERP 00450 00451 BLI_rw_mutex_unlock(&oc->oceanmutex); 00452 00453 } 00454 00455 void BKE_ocean_eval_xz(struct Ocean *oc, struct OceanResult *ocr, float x,float z) 00456 { 00457 BKE_ocean_eval_uv(oc, ocr, x/oc->_Lx,z/oc->_Lz); 00458 } 00459 00460 void BKE_ocean_eval_xz_catrom(struct Ocean *oc, struct OceanResult *ocr, float x,float z) 00461 { 00462 BKE_ocean_eval_uv_catrom(oc, ocr, x/oc->_Lx,z/oc->_Lz); 00463 } 00464 00465 // note that this doesn't wrap properly for i,j < 0, but its 00466 // not really meant for that being just a way to get the raw data out 00467 // to save in some image format. 00468 void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i,int j) 00469 { 00470 BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); 00471 00472 i = abs(i) % oc->_M; 00473 j = abs(j) % oc->_N; 00474 00475 ocr->disp[1] = oc->_do_disp_y ? oc->_disp_y[i*oc->_N+j] : 0.0f; 00476 00477 if (oc->_do_chop) 00478 { 00479 ocr->disp[0] = oc->_disp_x[i*oc->_N+j]; 00480 ocr->disp[2] = oc->_disp_z[i*oc->_N+j]; 00481 } 00482 else 00483 { 00484 ocr->disp[0] = 0.0f; 00485 ocr->disp[2] = 0.0f; 00486 } 00487 00488 if (oc->_do_normals) 00489 { 00490 ocr->normal[0] = oc->_N_x[i*oc->_N+j]; 00491 ocr->normal[1] = oc->_N_y/*oc->_N_y[i*oc->_N+j] (MEM01)*/; 00492 ocr->normal[2] = oc->_N_z[i*oc->_N+j]; 00493 00494 normalize_v3(ocr->normal); 00495 } 00496 00497 if (oc->_do_jacobian) 00498 { 00499 compute_eigenstuff(ocr, oc->_Jxx[i*oc->_N+j],oc->_Jzz[i*oc->_N+j],oc->_Jxz[i*oc->_N+j]); 00500 } 00501 00502 BLI_rw_mutex_unlock(&oc->oceanmutex); 00503 } 00504 00505 void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount) 00506 { 00507 int i, j; 00508 00509 scale *= o->normalize_factor; 00510 00511 BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); 00512 00513 // compute a new htilda 00514 #pragma omp parallel for private(i, j) 00515 for (i = 0 ; i < o->_M ; ++i) 00516 { 00517 // note the <= _N/2 here, see the fftw doco about 00518 // the mechanics of the complex->real fft storage 00519 for ( j = 0 ; j <= o->_N / 2 ; ++j) 00520 { 00521 fftw_complex exp_param1; 00522 fftw_complex exp_param2; 00523 fftw_complex conj_param; 00524 00525 00526 init_complex(exp_param1, 0.0, omega(o->_k[i*(1+o->_N/2)+j],o->_depth)*t); 00527 init_complex(exp_param2, 0.0, -omega(o->_k[i*(1+o->_N/2)+j],o->_depth)*t); 00528 exp_complex(exp_param1, exp_param1); 00529 exp_complex(exp_param2, exp_param2); 00530 conj_complex(conj_param, o->_h0_minus[i*o->_N+j]); 00531 00532 mul_complex_c(exp_param1, o->_h0[i*o->_N+j], exp_param1); 00533 mul_complex_c(exp_param2, conj_param, exp_param2); 00534 00535 add_comlex_c(o->_htilda[i*(1+o->_N/2)+j], exp_param1, exp_param2); 00536 mul_complex_f(o->_fft_in[i*(1+o->_N/2)+j], o->_htilda[i*(1+o->_N/2)+j], scale); 00537 } 00538 } 00539 00540 #pragma omp parallel sections private(i, j) 00541 { 00542 00543 #pragma omp section 00544 { 00545 if (o->_do_disp_y) 00546 { 00547 // y displacement 00548 fftw_execute(o->_disp_y_plan); 00549 } 00550 } // section 1 00551 00552 #pragma omp section 00553 { 00554 if (o->_do_chop) 00555 { 00556 // x displacement 00557 for ( i = 0 ; i < o->_M ; ++i) 00558 { 00559 for ( j = 0 ; j <= o->_N / 2 ; ++j) 00560 { 00561 fftw_complex mul_param; 00562 fftw_complex minus_i; 00563 00564 init_complex(minus_i, 0.0, -1.0); 00565 init_complex(mul_param, -scale, 0); 00566 mul_complex_f(mul_param, mul_param, chop_amount); 00567 mul_complex_c(mul_param, mul_param, minus_i); 00568 mul_complex_c(mul_param, mul_param, o->_htilda[i*(1+o->_N/2)+j]); 00569 mul_complex_f(mul_param, mul_param, (o->_k[i*(1+o->_N/2)+j] == 0.0 ? 0.0 : o->_kx[i] / o->_k[i*(1+o->_N/2)+j])); 00570 init_complex(o->_fft_in_x[i*(1+o->_N/2)+j], real_c(mul_param), image_c(mul_param)); 00571 } 00572 } 00573 fftw_execute(o->_disp_x_plan); 00574 } 00575 } //section 2 00576 00577 #pragma omp section 00578 { 00579 if (o->_do_chop) 00580 { 00581 // z displacement 00582 for ( i = 0 ; i < o->_M ; ++i) 00583 { 00584 for ( j = 0 ; j <= o->_N / 2 ; ++j) 00585 { 00586 fftw_complex mul_param; 00587 fftw_complex minus_i; 00588 00589 init_complex(minus_i, 0.0, -1.0); 00590 init_complex(mul_param, -scale, 0); 00591 mul_complex_f(mul_param, mul_param, chop_amount); 00592 mul_complex_c(mul_param, mul_param, minus_i); 00593 mul_complex_c(mul_param, mul_param, o->_htilda[i*(1+o->_N/2)+j]); 00594 mul_complex_f(mul_param, mul_param, (o->_k[i*(1+o->_N/2)+j] == 0.0 ? 0.0 : o->_kz[j] / o->_k[i*(1+o->_N/2)+j])); 00595 init_complex(o->_fft_in_z[i*(1+o->_N/2)+j], real_c(mul_param), image_c(mul_param)); 00596 } 00597 } 00598 fftw_execute(o->_disp_z_plan); 00599 } 00600 } // section 3 00601 00602 #pragma omp section 00603 { 00604 if (o->_do_jacobian) 00605 { 00606 // Jxx 00607 for ( i = 0 ; i < o->_M ; ++i) 00608 { 00609 for ( j = 0 ; j <= o->_N / 2 ; ++j) 00610 { 00611 fftw_complex mul_param; 00612 00613 //init_complex(mul_param, -scale, 0); 00614 init_complex(mul_param, -1, 0); 00615 00616 mul_complex_f(mul_param, mul_param, chop_amount); 00617 mul_complex_c(mul_param, mul_param, o->_htilda[i*(1+o->_N/2)+j]); 00618 mul_complex_f(mul_param, mul_param, (o->_k[i*(1+o->_N/2)+j] == 0.0 ? 0.0 : o->_kx[i]*o->_kx[i] / o->_k[i*(1+o->_N/2)+j])); 00619 init_complex(o->_fft_in_jxx[i*(1+o->_N/2)+j], real_c(mul_param), image_c(mul_param)); 00620 } 00621 } 00622 fftw_execute(o->_Jxx_plan); 00623 00624 for ( i = 0 ; i < o->_M ; ++i) 00625 { 00626 for ( j = 0 ; j < o->_N ; ++j) 00627 { 00628 o->_Jxx[i*o->_N+j] += 1.0; 00629 } 00630 } 00631 } 00632 } // section 4 00633 00634 #pragma omp section 00635 { 00636 if (o->_do_jacobian) 00637 { 00638 // Jzz 00639 for ( i = 0 ; i < o->_M ; ++i) 00640 { 00641 for ( j = 0 ; j <= o->_N / 2 ; ++j) 00642 { 00643 fftw_complex mul_param; 00644 00645 //init_complex(mul_param, -scale, 0); 00646 init_complex(mul_param, -1, 0); 00647 00648 mul_complex_f(mul_param, mul_param, chop_amount); 00649 mul_complex_c(mul_param, mul_param, o->_htilda[i*(1+o->_N/2)+j]); 00650 mul_complex_f(mul_param, mul_param, (o->_k[i*(1+o->_N/2)+j] == 0.0 ? 0.0 : o->_kz[j]*o->_kz[j] / o->_k[i*(1+o->_N/2)+j])); 00651 init_complex(o->_fft_in_jzz[i*(1+o->_N/2)+j], real_c(mul_param), image_c(mul_param)); 00652 } 00653 } 00654 fftw_execute(o->_Jzz_plan); 00655 for ( i = 0 ; i < o->_M ; ++i) 00656 { 00657 for ( j = 0 ; j < o->_N ; ++j) 00658 { 00659 o->_Jzz[i*o->_N+j] += 1.0; 00660 } 00661 } 00662 } 00663 } // section 5 00664 00665 #pragma omp section 00666 { 00667 if (o->_do_jacobian) 00668 { 00669 // Jxz 00670 for ( i = 0 ; i < o->_M ; ++i) 00671 { 00672 for ( j = 0 ; j <= o->_N / 2 ; ++j) 00673 { 00674 fftw_complex mul_param; 00675 00676 //init_complex(mul_param, -scale, 0); 00677 init_complex(mul_param, -1, 0); 00678 00679 mul_complex_f(mul_param, mul_param, chop_amount); 00680 mul_complex_c(mul_param, mul_param, o->_htilda[i*(1+o->_N/2)+j]); 00681 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])); 00682 init_complex(o->_fft_in_jxz[i*(1+o->_N/2)+j], real_c(mul_param), image_c(mul_param)); 00683 } 00684 } 00685 fftw_execute(o->_Jxz_plan); 00686 } 00687 } // section 6 00688 00689 #pragma omp section 00690 { 00691 // fft normals 00692 if (o->_do_normals) 00693 { 00694 for ( i = 0 ; i < o->_M ; ++i) 00695 { 00696 for ( j = 0 ; j <= o->_N / 2 ; ++j) 00697 { 00698 fftw_complex mul_param; 00699 00700 init_complex(mul_param, 0.0, -1.0); 00701 mul_complex_c(mul_param, mul_param, o->_htilda[i*(1+o->_N/2)+j]); 00702 mul_complex_f(mul_param, mul_param, o->_kx[i]); 00703 init_complex(o->_fft_in_nx[i*(1+o->_N/2)+j], real_c(mul_param), image_c(mul_param)); 00704 } 00705 } 00706 fftw_execute(o->_N_x_plan); 00707 00708 } 00709 } // section 7 00710 00711 #pragma omp section 00712 { 00713 if (o->_do_normals) 00714 { 00715 for ( i = 0 ; i < o->_M ; ++i) 00716 { 00717 for ( j = 0 ; j <= o->_N / 2 ; ++j) 00718 { 00719 fftw_complex mul_param; 00720 00721 init_complex(mul_param, 0.0, -1.0); 00722 mul_complex_c(mul_param, mul_param, o->_htilda[i*(1+o->_N/2)+j]); 00723 mul_complex_f(mul_param, mul_param, o->_kz[i]); 00724 init_complex(o->_fft_in_nz[i*(1+o->_N/2)+j], real_c(mul_param), image_c(mul_param)); 00725 } 00726 } 00727 fftw_execute(o->_N_z_plan); 00728 00729 /*for ( i = 0 ; i < o->_M ; ++i) 00730 { 00731 for ( j = 0 ; j < o->_N ; ++j) 00732 { 00733 o->_N_y[i*o->_N+j] = 1.0f/scale; 00734 } 00735 } 00736 (MEM01)*/ 00737 o->_N_y = 1.0f/scale; 00738 } 00739 } // section 8 00740 00741 } // omp sections 00742 00743 BLI_rw_mutex_unlock(&o->oceanmutex); 00744 } 00745 00746 static void set_height_normalize_factor(struct Ocean *oc) 00747 { 00748 float res = 1.0; 00749 float max_h = 0.0; 00750 00751 int i,j; 00752 00753 if (!oc->_do_disp_y) return; 00754 00755 oc->normalize_factor = 1.0; 00756 00757 BKE_simulate_ocean(oc, 0.0, 1.0, 0); 00758 00759 BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); 00760 00761 for (i = 0; i < oc->_M; ++i) 00762 { 00763 for (j = 0; j < oc->_N; ++j) 00764 { 00765 if( max_h < fabsf(oc->_disp_y[i*oc->_N+j])) 00766 { 00767 max_h = fabsf(oc->_disp_y[i*oc->_N+j]); 00768 } 00769 } 00770 } 00771 00772 BLI_rw_mutex_unlock(&oc->oceanmutex); 00773 00774 if (max_h == 0.0f) max_h = 0.00001f; // just in case ... 00775 00776 res = 1.0f / (max_h); 00777 00778 oc->normalize_factor = res; 00779 } 00780 00781 struct Ocean *BKE_add_ocean(void) 00782 { 00783 Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data"); 00784 00785 BLI_rw_mutex_init(&oc->oceanmutex); 00786 00787 return oc; 00788 } 00789 00790 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, 00791 float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed) 00792 { 00793 int i,j,ii; 00794 00795 BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); 00796 00797 o->_M = M; 00798 o->_N = N; 00799 o->_V = V; 00800 o->_l = l; 00801 o->_A = A; 00802 o->_w = w; 00803 o->_damp_reflections = 1.0f - damp; 00804 o->_wind_alignment = alignment; 00805 o->_depth = depth; 00806 o->_Lx = Lx; 00807 o->_Lz = Lz; 00808 o->_wx = cos(w); 00809 o->_wz = -sin(w); // wave direction 00810 o->_L = V*V / GRAVITY; // largest wave for a given velocity V 00811 o->time = time; 00812 00813 o->_do_disp_y = do_height_field; 00814 o->_do_normals = do_normals; 00815 o->_do_chop = do_chop; 00816 o->_do_jacobian = do_jacobian; 00817 00818 o->_k = (float*) MEM_mallocN(M * (1+N/2) * sizeof(float), "ocean_k"); 00819 o->_h0 = (fftw_complex*) MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0"); 00820 o->_h0_minus = (fftw_complex*) MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus"); 00821 o->_kx = (float*) MEM_mallocN(o->_M * sizeof(float), "ocean_kx"); 00822 o->_kz = (float*) MEM_mallocN(o->_N * sizeof(float), "ocean_kz"); 00823 00824 // make this robust in the face of erroneous usage 00825 if (o->_Lx == 0.0f) 00826 o->_Lx = 0.001f; 00827 00828 if (o->_Lz == 0.0f) 00829 o->_Lz = 0.001f; 00830 00831 // the +ve components and DC 00832 for (i = 0 ; i <= o->_M/2 ; ++i) 00833 o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx; 00834 00835 // the -ve components 00836 for (i = o->_M-1,ii=0 ; i > o->_M/2 ; --i,++ii) 00837 o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx; 00838 00839 // the +ve components and DC 00840 for (i = 0 ; i <= o->_N/2 ; ++i) 00841 o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz; 00842 00843 // the -ve components 00844 for (i = o->_N-1,ii=0 ; i > o->_N/2 ; --i,++ii) 00845 o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz; 00846 00847 // pre-calculate the k matrix 00848 for (i = 0 ; i < o->_M ; ++i) 00849 for (j = 0 ; j <= o->_N / 2 ; ++j) 00850 o->_k[i*(1+o->_N/2)+j] = sqrt(o->_kx[i]*o->_kx[i] + o->_kz[j]*o->_kz[j] ); 00851 00852 /*srand(seed);*/ 00853 BLI_srand(seed); 00854 00855 for (i = 0 ; i < o->_M ; ++i) 00856 { 00857 for (j = 0 ; j < o->_N ; ++j) 00858 { 00859 float r1 = gaussRand(); 00860 float r2 = gaussRand(); 00861 00862 fftw_complex r1r2; 00863 init_complex(r1r2, r1, r2); 00864 mul_complex_f(o->_h0[i*o->_N+j], r1r2, (float)(sqrt(Ph(o, o->_kx[i], o->_kz[j]) / 2.0f))); 00865 mul_complex_f(o->_h0_minus[i*o->_N+j], r1r2, (float)(sqrt(Ph(o, -o->_kx[i],-o->_kz[j]) / 2.0f))); 00866 } 00867 } 00868 00869 o->_fft_in = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_fft_in"); 00870 o->_htilda = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_htilda"); 00871 00872 if (o->_do_disp_y){ 00873 o->_disp_y = (double*) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y"); 00874 o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M,o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE); 00875 } 00876 00877 if (o->_do_normals){ 00878 o->_fft_in_nx = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_fft_in_nx"); 00879 o->_fft_in_nz = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_fft_in_nz"); 00880 00881 o->_N_x = (double*) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x"); 00882 /*o->_N_y = (float*) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01)*/ 00883 o->_N_z = (double*) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z"); 00884 00885 o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M,o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE); 00886 o->_N_z_plan = fftw_plan_dft_c2r_2d(o->_M,o->_N, o->_fft_in_nz, o->_N_z, FFTW_ESTIMATE); 00887 } 00888 00889 if (o->_do_chop){ 00890 o->_fft_in_x = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_fft_in_x"); 00891 o->_fft_in_z = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_fft_in_z"); 00892 00893 o->_disp_x = (double*) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x"); 00894 o->_disp_z = (double*) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z"); 00895 00896 o->_disp_x_plan = fftw_plan_dft_c2r_2d(o->_M,o->_N, o->_fft_in_x, o->_disp_x, FFTW_ESTIMATE); 00897 o->_disp_z_plan = fftw_plan_dft_c2r_2d(o->_M,o->_N, o->_fft_in_z, o->_disp_z, FFTW_ESTIMATE); 00898 } 00899 if (o->_do_jacobian){ 00900 o->_fft_in_jxx = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_fft_in_jxx"); 00901 o->_fft_in_jzz = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_fft_in_jzz"); 00902 o->_fft_in_jxz = (fftw_complex*) MEM_mallocN(o->_M * (1+o->_N/2) * sizeof(fftw_complex), "ocean_fft_in_jxz"); 00903 00904 o->_Jxx = (double*) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx"); 00905 o->_Jzz = (double*) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz"); 00906 o->_Jxz = (double*) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz"); 00907 00908 o->_Jxx_plan = fftw_plan_dft_c2r_2d(o->_M,o->_N, o->_fft_in_jxx, o->_Jxx, FFTW_ESTIMATE); 00909 o->_Jzz_plan = fftw_plan_dft_c2r_2d(o->_M,o->_N, o->_fft_in_jzz, o->_Jzz, FFTW_ESTIMATE); 00910 o->_Jxz_plan = fftw_plan_dft_c2r_2d(o->_M,o->_N, o->_fft_in_jxz, o->_Jxz, FFTW_ESTIMATE); 00911 } 00912 00913 BLI_rw_mutex_unlock(&o->oceanmutex); 00914 00915 set_height_normalize_factor(o); 00916 00917 } 00918 00919 void BKE_free_ocean_data(struct Ocean *oc) 00920 { 00921 if(!oc) return; 00922 00923 BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE); 00924 00925 if (oc->_do_disp_y) 00926 { 00927 fftw_destroy_plan(oc->_disp_y_plan); 00928 MEM_freeN(oc->_disp_y); 00929 } 00930 00931 if (oc->_do_normals) 00932 { 00933 MEM_freeN(oc->_fft_in_nx); 00934 MEM_freeN(oc->_fft_in_nz); 00935 fftw_destroy_plan(oc->_N_x_plan); 00936 fftw_destroy_plan(oc->_N_z_plan); 00937 MEM_freeN(oc->_N_x); 00938 /*fftwf_free(oc->_N_y); (MEM01)*/ 00939 MEM_freeN(oc->_N_z); 00940 } 00941 00942 if (oc->_do_chop) 00943 { 00944 MEM_freeN(oc->_fft_in_x); 00945 MEM_freeN(oc->_fft_in_z); 00946 fftw_destroy_plan(oc->_disp_x_plan); 00947 fftw_destroy_plan(oc->_disp_z_plan); 00948 MEM_freeN(oc->_disp_x); 00949 MEM_freeN(oc->_disp_z); 00950 } 00951 00952 if (oc->_do_jacobian) 00953 { 00954 MEM_freeN(oc->_fft_in_jxx); 00955 MEM_freeN(oc->_fft_in_jzz); 00956 MEM_freeN(oc->_fft_in_jxz); 00957 fftw_destroy_plan(oc->_Jxx_plan); 00958 fftw_destroy_plan(oc->_Jzz_plan); 00959 fftw_destroy_plan(oc->_Jxz_plan); 00960 MEM_freeN(oc->_Jxx); 00961 MEM_freeN(oc->_Jzz); 00962 MEM_freeN(oc->_Jxz); 00963 } 00964 00965 if (oc->_fft_in) 00966 MEM_freeN(oc->_fft_in); 00967 00968 /* check that ocean data has been initialised */ 00969 if (oc->_htilda) { 00970 MEM_freeN(oc->_htilda); 00971 MEM_freeN(oc->_k); 00972 MEM_freeN(oc->_h0); 00973 MEM_freeN(oc->_h0_minus); 00974 MEM_freeN(oc->_kx); 00975 MEM_freeN(oc->_kz); 00976 } 00977 00978 BLI_rw_mutex_unlock(&oc->oceanmutex); 00979 } 00980 00981 void BKE_free_ocean(struct Ocean *oc) 00982 { 00983 if(!oc) return; 00984 00985 BKE_free_ocean_data(oc); 00986 BLI_rw_mutex_end(&oc->oceanmutex); 00987 00988 MEM_freeN(oc); 00989 } 00990 00991 #undef GRAVITY 00992 00993 00994 /* ********* Baking/Caching ********* */ 00995 00996 00997 #define CACHE_TYPE_DISPLACE 1 00998 #define CACHE_TYPE_FOAM 2 00999 #define CACHE_TYPE_NORMAL 3 01000 01001 static void cache_filename(char *string, const char *path, const char *relbase, int frame, int type) 01002 { 01003 char cachepath[FILE_MAX]; 01004 const char *fname; 01005 01006 switch(type) { 01007 case CACHE_TYPE_FOAM: 01008 fname= "foam_"; 01009 break; 01010 case CACHE_TYPE_NORMAL: 01011 fname= "normal_"; 01012 break; 01013 case CACHE_TYPE_DISPLACE: 01014 default: 01015 fname= "disp_"; 01016 break; 01017 } 01018 01019 BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname); 01020 01021 BKE_makepicstring(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, 1, TRUE); 01022 } 01023 01024 /* silly functions but useful to inline when the args do a lot of indirections */ 01025 MINLINE void rgb_to_rgba_unit_alpha(float r_rgba[4], const float rgb[3]) 01026 { 01027 r_rgba[0]= rgb[0]; 01028 r_rgba[1]= rgb[1]; 01029 r_rgba[2]= rgb[2]; 01030 r_rgba[3]= 1.0f; 01031 } 01032 MINLINE void value_to_rgba_unit_alpha(float r_rgba[4], const float value) 01033 { 01034 r_rgba[0]= value; 01035 r_rgba[1]= value; 01036 r_rgba[2]= value; 01037 r_rgba[3]= 1.0f; 01038 } 01039 01040 void BKE_free_ocean_cache(struct OceanCache *och) 01041 { 01042 int i, f=0; 01043 01044 if (!och) return; 01045 01046 if (och->ibufs_disp) { 01047 for (i=och->start, f=0; i<=och->end; i++, f++) 01048 { 01049 if (och->ibufs_disp[f]) { 01050 IMB_freeImBuf(och->ibufs_disp[f]); 01051 } 01052 } 01053 MEM_freeN(och->ibufs_disp); 01054 } 01055 01056 if (och->ibufs_foam) { 01057 for (i=och->start, f=0; i<=och->end; i++, f++) 01058 { 01059 if (och->ibufs_foam[f]) { 01060 IMB_freeImBuf(och->ibufs_foam[f]); 01061 } 01062 } 01063 MEM_freeN(och->ibufs_foam); 01064 } 01065 01066 if (och->ibufs_norm) { 01067 for (i=och->start, f=0; i<=och->end; i++, f++) 01068 { 01069 if (och->ibufs_norm[f]) { 01070 IMB_freeImBuf(och->ibufs_norm[f]); 01071 } 01072 } 01073 MEM_freeN(och->ibufs_norm); 01074 } 01075 01076 if (och->time) 01077 MEM_freeN(och->time); 01078 MEM_freeN(och); 01079 } 01080 01081 void BKE_ocean_cache_eval_uv(struct OceanCache *och, struct OceanResult *ocr, int f, float u, float v) 01082 { 01083 int res_x = och->resolution_x; 01084 int res_y = och->resolution_y; 01085 float result[4]; 01086 01087 u = fmod(u, 1.0); 01088 v = fmod(v, 1.0); 01089 01090 if (u < 0) u += 1.0f; 01091 if (v < 0) v += 1.0f; 01092 01093 if (och->ibufs_disp[f]) { 01094 ibuf_sample(och->ibufs_disp[f], u, v, (1.0f/(float)res_x), (1.0f/(float)res_y), result); 01095 copy_v3_v3(ocr->disp, result); 01096 } 01097 01098 if (och->ibufs_foam[f]) { 01099 ibuf_sample(och->ibufs_foam[f], u, v, (1.0f/(float)res_x), (1.0f/(float)res_y), result); 01100 ocr->foam = result[0]; 01101 } 01102 01103 if (och->ibufs_norm[f]) { 01104 ibuf_sample(och->ibufs_norm[f], u, v, (1.0f/(float)res_x), (1.0f/(float)res_y), result); 01105 copy_v3_v3(ocr->normal, result); 01106 } 01107 } 01108 01109 void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, int f, int i, int j) 01110 { 01111 const int res_x = och->resolution_x; 01112 const int res_y = och->resolution_y; 01113 01114 if (i < 0) i= -i; 01115 if (j < 0) j= -j; 01116 01117 i = i % res_x; 01118 j = j % res_y; 01119 01120 if (och->ibufs_disp[f]) { 01121 copy_v3_v3(ocr->disp, &och->ibufs_disp[f]->rect_float[4*(res_x*j + i)]); 01122 } 01123 01124 if (och->ibufs_foam[f]) { 01125 ocr->foam = och->ibufs_foam[f]->rect_float[4*(res_x*j + i)]; 01126 } 01127 01128 if (och->ibufs_norm[f]) { 01129 copy_v3_v3(ocr->normal, &och->ibufs_norm[f]->rect_float[4*(res_x*j + i)]); 01130 } 01131 } 01132 01133 struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbase, 01134 int start, int end, float wave_scale, 01135 float chop_amount, float foam_coverage, float foam_fade, int resolution) 01136 { 01137 OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data"); 01138 01139 och->bakepath = bakepath; 01140 och->relbase = relbase; 01141 01142 och->start = start; 01143 och->end = end; 01144 och->duration = (end - start) + 1; 01145 och->wave_scale = wave_scale; 01146 och->chop_amount = chop_amount; 01147 och->foam_coverage = foam_coverage; 01148 och->foam_fade = foam_fade; 01149 och->resolution_x = resolution*resolution; 01150 och->resolution_y = resolution*resolution; 01151 01152 och->ibufs_disp = MEM_callocN(sizeof(ImBuf *)*och->duration, "displacement imbuf pointer array"); 01153 och->ibufs_foam = MEM_callocN(sizeof(ImBuf *)*och->duration, "foam imbuf pointer array"); 01154 och->ibufs_norm = MEM_callocN(sizeof(ImBuf *)*och->duration, "normal imbuf pointer array"); 01155 01156 och->time = NULL; 01157 01158 return och; 01159 } 01160 01161 void BKE_simulate_ocean_cache(struct OceanCache *och, int frame) 01162 { 01163 char string[FILE_MAX]; 01164 int f = frame; 01165 01166 /* ibufs array is zero based, but filenames are based on frame numbers */ 01167 /* still need to clamp frame numbers to valid range of images on disk though */ 01168 CLAMP(frame, och->start, och->end); 01169 f = frame - och->start; // shift to 0 based 01170 01171 /* if image is already loaded in mem, return */ 01172 if (och->ibufs_disp[f] != NULL ) return; 01173 01174 01175 cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE); 01176 och->ibufs_disp[f] = IMB_loadiffname(string, 0); 01177 //if (och->ibufs_disp[f] == NULL) printf("error loading %s \n", string); 01178 //else printf("loaded cache %s \n", string); 01179 01180 cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM); 01181 och->ibufs_foam[f] = IMB_loadiffname(string, 0); 01182 //if (och->ibufs_foam[f] == NULL) printf("error loading %s \n", string); 01183 //else printf("loaded cache %s \n", string); 01184 01185 cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL); 01186 och->ibufs_norm[f] = IMB_loadiffname(string, 0); 01187 //if (och->ibufs_norm[f] == NULL) printf("error loading %s \n", string); 01188 //else printf("loaded cache %s \n", string); 01189 } 01190 01191 01192 void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data) 01193 { 01194 /* note: some of these values remain uninitialized unless certain options 01195 * are enabled, take care that BKE_ocean_eval_ij() initializes a member 01196 * before use - campbell */ 01197 OceanResult ocr; 01198 01199 ImageFormatData imf= {0}; 01200 01201 int f, i=0, x, y, cancel=0; 01202 float progress; 01203 01204 ImBuf *ibuf_foam, *ibuf_disp, *ibuf_normal; 01205 float *prev_foam; 01206 int res_x = och->resolution_x; 01207 int res_y = och->resolution_y; 01208 char string[FILE_MAX]; 01209 01210 if (!o) return; 01211 01212 if (o->_do_jacobian) prev_foam = MEM_callocN(res_x*res_y*sizeof(float), "previous frame foam bake data"); 01213 else prev_foam = NULL; 01214 01215 BLI_srand(0); 01216 01217 /* setup image format */ 01218 imf.imtype= R_IMF_IMTYPE_OPENEXR; 01219 imf.depth= R_IMF_CHAN_DEPTH_16; 01220 imf.exr_codec= R_IMF_EXR_CODEC_ZIP; 01221 01222 for (f=och->start, i=0; f<=och->end; f++, i++) { 01223 01224 /* create a new imbuf to store image for this frame */ 01225 ibuf_foam = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); 01226 ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); 01227 ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); 01228 01229 ibuf_disp->profile = ibuf_foam->profile = ibuf_normal->profile = IB_PROFILE_LINEAR_RGB; 01230 01231 BKE_simulate_ocean(o, och->time[i], och->wave_scale, och->chop_amount); 01232 01233 /* add new foam */ 01234 for (y=0; y < res_y; y++) { 01235 for (x=0; x < res_x; x++) { 01236 01237 BKE_ocean_eval_ij(o, &ocr, x, y); 01238 01239 /* add to the image */ 01240 rgb_to_rgba_unit_alpha(&ibuf_disp->rect_float[4*(res_x*y + x)], ocr.disp); 01241 01242 if (o->_do_jacobian) { 01243 /* TODO, cleanup unused code - campbell */ 01244 01245 float /*r,*/ /* UNUSED */ pr=0.0f, foam_result; 01246 float neg_disp, neg_eplus; 01247 01248 ocr.foam = BKE_ocean_jminus_to_foam(ocr.Jminus, och->foam_coverage); 01249 01250 /* accumulate previous value for this cell */ 01251 if (i > 0) { 01252 pr = prev_foam[res_x*y + x]; 01253 } 01254 01255 /* r = BLI_frand(); */ /* UNUSED */ // randomly reduce foam 01256 01257 //pr = pr * och->foam_fade; // overall fade 01258 01259 // remember ocean coord sys is Y up! 01260 // break up the foam where height (Y) is low (wave valley), 01261 // and X and Z displacement is greatest 01262 01263 /* 01264 vec[0] = ocr.disp[0]; 01265 vec[1] = ocr.disp[2]; 01266 hor_stretch = len_v2(vec); 01267 CLAMP(hor_stretch, 0.0, 1.0); 01268 */ 01269 01270 neg_disp = ocr.disp[1] < 0.0f ? 1.0f+ocr.disp[1] : 1.0f; 01271 neg_disp = neg_disp < 0.0f ? 0.0f : neg_disp; 01272 01273 /* foam, 'ocr.Eplus' only initialized with do_jacobian */ 01274 neg_eplus = ocr.Eplus[2] < 0.0f ? 1.0f + ocr.Eplus[2]:1.0f; 01275 neg_eplus = neg_eplus<0.0f ? 0.0f : neg_eplus; 01276 01277 //if (ocr.disp[1] < 0.0 || r > och->foam_fade) 01278 // pr *= och->foam_fade; 01279 01280 01281 //pr = pr * (1.0 - hor_stretch) * ocr.disp[1]; 01282 //pr = pr * neg_disp * neg_eplus; 01283 01284 if (pr < 1.0f) pr *=pr; 01285 01286 pr *= och->foam_fade * (0.75f + neg_eplus * 0.25f); 01287 01288 01289 foam_result = pr + ocr.foam; 01290 01291 prev_foam[res_x*y + x] = foam_result; 01292 01293 value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4*(res_x*y + x)], foam_result); 01294 } 01295 01296 if (o->_do_normals) { 01297 rgb_to_rgba_unit_alpha(&ibuf_normal->rect_float[4*(res_x*y + x)], ocr.normal); 01298 } 01299 } 01300 } 01301 01302 /* write the images */ 01303 cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_DISPLACE); 01304 if(0 == BKE_write_ibuf(ibuf_disp, string, &imf)) 01305 printf("Cannot save Displacement File Output to %s\n", string); 01306 01307 if (o->_do_jacobian) { 01308 cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_FOAM); 01309 if(0 == BKE_write_ibuf(ibuf_foam, string, &imf)) 01310 printf("Cannot save Foam File Output to %s\n", string); 01311 } 01312 01313 if (o->_do_normals) { 01314 cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_NORMAL); 01315 if(0 == BKE_write_ibuf(ibuf_normal, string, &imf)) 01316 printf("Cannot save Normal File Output to %s\n", string); 01317 } 01318 01319 IMB_freeImBuf(ibuf_disp); 01320 IMB_freeImBuf(ibuf_foam); 01321 IMB_freeImBuf(ibuf_normal); 01322 01323 progress = (f - och->start) / (float)och->duration; 01324 01325 update_cb(update_cb_data, progress, &cancel); 01326 01327 if (cancel) { 01328 if (prev_foam) MEM_freeN(prev_foam); 01329 return; 01330 } 01331 } 01332 01333 if (prev_foam) MEM_freeN(prev_foam); 01334 och->baked = 1; 01335 } 01336 01337 #else // WITH_OCEANSIM 01338 01339 /* stub */ 01340 typedef struct Ocean { 01341 /* need some data here, C does not allow empty struct */ 01342 int stub; 01343 } Ocean; 01344 01345 01346 float BKE_ocean_jminus_to_foam(float UNUSED(jminus), float UNUSED(coverage)) 01347 { 01348 return 0.0f; 01349 } 01350 01351 void BKE_ocean_eval_uv(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(u),float UNUSED(v)) 01352 { 01353 } 01354 01355 // use catmullrom interpolation rather than linear 01356 void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(u),float UNUSED(v)) 01357 { 01358 } 01359 01360 void BKE_ocean_eval_xz(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(x),float UNUSED(z)) 01361 { 01362 } 01363 01364 void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(x),float UNUSED(z)) 01365 { 01366 } 01367 01368 void BKE_ocean_eval_ij(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), int UNUSED(i),int UNUSED(j)) 01369 { 01370 } 01371 01372 void BKE_simulate_ocean(struct Ocean *UNUSED(o), float UNUSED(t), float UNUSED(scale), float UNUSED(chop_amount)) 01373 { 01374 } 01375 01376 struct Ocean *BKE_add_ocean(void) 01377 { 01378 Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data"); 01379 01380 return oc; 01381 } 01382 01383 void BKE_init_ocean(struct Ocean* UNUSED(o), int UNUSED(M),int UNUSED(N), float UNUSED(Lx), float UNUSED(Lz), float UNUSED(V), float UNUSED(l), float UNUSED(A), float UNUSED(w), float UNUSED(damp), 01384 float UNUSED(alignment), float UNUSED(depth), float UNUSED(time), short UNUSED(do_height_field), short UNUSED(do_chop), short UNUSED(do_normals), short UNUSED(do_jacobian), int UNUSED(seed)) 01385 { 01386 } 01387 01388 void BKE_free_ocean_data(struct Ocean *UNUSED(oc)) 01389 { 01390 } 01391 01392 void BKE_free_ocean(struct Ocean *oc) 01393 { 01394 if(!oc) return; 01395 MEM_freeN(oc); 01396 } 01397 01398 01399 /* ********* Baking/Caching ********* */ 01400 01401 01402 void BKE_free_ocean_cache(struct OceanCache *och) 01403 { 01404 if (!och) return; 01405 01406 MEM_freeN(och); 01407 } 01408 01409 void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), float UNUSED(u), float UNUSED(v)) 01410 { 01411 } 01412 01413 void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), int UNUSED(i), int UNUSED(j)) 01414 { 01415 } 01416 01417 struct OceanCache *BKE_init_ocean_cache(const char *UNUSED(bakepath), const char *UNUSED(relbase), 01418 int UNUSED(start), int UNUSED(end), float UNUSED(wave_scale), 01419 float UNUSED(chop_amount), float UNUSED(foam_coverage), float UNUSED(foam_fade), int UNUSED(resolution)) 01420 { 01421 OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data"); 01422 01423 return och; 01424 } 01425 01426 void BKE_simulate_ocean_cache(struct OceanCache *UNUSED(och), int UNUSED(frame)) 01427 { 01428 } 01429 01430 void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data)) 01431 { 01432 /* unused */ 01433 (void)update_cb; 01434 } 01435 #endif // WITH_OCEANSIM