Blender V2.61 - r43446

ocean.c

Go to the documentation of this file.
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