Blender  V2.59
smoke_API.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: smoke_API.cpp 35159 2011-02-25 11:50:46Z jesterking $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2009 by Daniel Genrich
00021  * All rights reserved.
00022  *
00023  * Contributor(s): Daniel Genrich
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include "FLUID_3D.h"
00034 #include "WTURBULENCE.h"
00035 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <math.h>
00039 
00040 // y in smoke is z in blender
00041 extern "C" FLUID_3D *smoke_init(int *res, float *p0)
00042 {
00043         // smoke lib uses y as top-bottom/vertical axis where blender uses z
00044         FLUID_3D *fluid = new FLUID_3D(res, p0);
00045 
00046         // printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
00047 
00048         return fluid;
00049 }
00050 
00051 extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype)
00052 {
00053         // initialize wavelet turbulence
00054         if(amplify)
00055                 return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype);
00056         else 
00057                 return NULL;
00058 }
00059 
00060 extern "C" void smoke_free(FLUID_3D *fluid)
00061 {
00062         delete fluid;
00063         fluid = NULL;
00064 }
00065 
00066 extern "C" void smoke_turbulence_free(WTURBULENCE *wt)
00067 {
00068          delete wt;
00069          wt = NULL;
00070 }
00071 
00072 extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
00073 {
00074         // // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1];
00075         return x + y * max_x + z * max_x*max_y;
00076 }
00077 
00078 extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z, int max_z */)
00079 {
00080         return x + y * max_x;
00081 }
00082 
00083 extern "C" void smoke_step(FLUID_3D *fluid, size_t framenr, float fps)
00084 {
00085         /* stability values copied from wturbulence.cpp */
00086         const int maxSubSteps = 25;
00087         const float maxVel = 0.5f; /* TODO: maybe 0.5 is still too high, please confirm! -dg */
00088 
00089         float dt = DT_DEFAULT;
00090         float maxVelMag = 0.0f;
00091         int totalSubsteps;
00092         int substep = 0;
00093         float dtSubdiv;
00094 
00095         /* get max velocity and lower the dt value if it is too high */
00096         size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
00097 
00098         for(size_t i = 0; i < size; i++)
00099         {
00100                 float vtemp = (fluid->_xVelocity[i]*fluid->_xVelocity[i]+fluid->_yVelocity[i]*fluid->_yVelocity[i]+fluid->_zVelocity[i]*fluid->_zVelocity[i]);
00101                 if(vtemp > maxVelMag)
00102                         maxVelMag = vtemp;
00103         }
00104 
00105         /* adapt timestep for different framerates, dt = 0.1 is at 25fps */
00106         dt *= (25.0f / fps);
00107 
00108         maxVelMag = sqrt(maxVelMag) * dt * (*(fluid->_dtFactor));
00109         totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */
00110         totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
00111         totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
00112         dtSubdiv = (float)dt / (float)totalSubsteps;
00113 
00114         // printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
00115 
00116         for(substep = 0; substep < totalSubsteps; substep++)
00117                 fluid->step(dtSubdiv);
00118 }
00119 
00120 extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
00121 {
00122         wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles); 
00123 }
00124 
00125 extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli)
00126 {
00127         fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli);
00128 }
00129 
00130 extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
00131 {
00132         float *density = fluid->_density;
00133         //float *densityOld = fluid->_densityOld;
00134         float *heat = fluid->_heat;
00135 
00136         if(log)
00137         {
00138                 /* max density/speed = dydx */
00139                 float dydx = 1.0 / (float)speed;
00140                 size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
00141 
00142                 for(size_t i = 0; i < size; i++)
00143                 {
00144                         density[i] *= (1.0 - dydx);
00145 
00146                         if(density[i] < 0.0f)
00147                                 density[i] = 0.0f;
00148 
00149                         heat[i] *= (1.0 - dydx);
00150 
00151                         /*if(heat[i] < 0.0f)
00152                                 heat[i] = 0.0f;*/
00153                 }
00154         }
00155         else // linear falloff
00156         {
00157                 /* max density/speed = dydx */
00158                 float dydx = 1.0 / (float)speed;
00159                 size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
00160 
00161                 for(size_t i = 0; i < size; i++)
00162                 {
00163                         density[i] -= dydx;
00164 
00165                         if(density[i] < 0.0f)
00166                                 density[i] = 0.0f;
00167 
00168                         if(abs(heat[i]) < dydx) heat[i] = 0.0f;
00169                         else if (heat[i]>0.0f) heat[i] -= dydx;
00170                         else if (heat[i]<0.0f) heat[i] += dydx;
00171                                 
00172                 }
00173         }
00174 }
00175 
00176 extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log)
00177 {
00178         float *density = wt->getDensityBig();
00179         Vec3Int r = wt->getResBig();
00180 
00181         if(log)
00182         {
00183                 /* max density/speed = dydx */
00184                 float dydx = 1.0 / (float)speed;
00185                 size_t size= r[0] * r[1] * r[2];
00186 
00187                 for(size_t i = 0; i < size; i++)
00188                 {
00189                         density[i] *= (1.0 - dydx);
00190 
00191                         if(density[i] < 0.0f)
00192                                 density[i] = 0.0f;
00193                 }
00194         }
00195         else // linear falloff
00196         {
00197                 /* max density/speed = dydx */
00198                 float dydx = 1.0 / (float)speed;
00199                 size_t size= r[0] * r[1] * r[2];
00200 
00201                 for(size_t i = 0; i < size; i++)
00202                 {
00203                         density[i] -= dydx;
00204 
00205                         if(density[i] < 0.0f)
00206                                 density[i] = 0.0f;                              
00207                 }
00208         }
00209 }
00210 
00211 extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength)
00212 {
00213         wt->initBlenderRNA(strength);
00214 }
00215 
00216 template < class T > inline T ABS( T a ) {
00217         return (0 < a) ? a : -a ;
00218 }
00219 
00220 extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles)
00221 {
00222         *dens = fluid->_density;
00223         *densold = fluid->_densityOld;
00224         *heat = fluid->_heat;
00225         *heatold = fluid->_heatOld;
00226         *vx = fluid->_xVelocity;
00227         *vy = fluid->_yVelocity;
00228         *vz = fluid->_zVelocity;
00229         *vxold = fluid->_xVelocityOld;
00230         *vyold = fluid->_yVelocityOld;
00231         *vzold = fluid->_zVelocityOld;
00232         *obstacles = fluid->_obstacles;
00233         dt = &(fluid->_dt);
00234         dx = &(fluid->_dx);
00235 
00236 }
00237 
00238 extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw)
00239 {
00240         if(!wt)
00241                 return;
00242 
00243         *dens = wt->_densityBig;
00244         *densold = wt->_densityBigOld;
00245         *tcu = wt->_tcU;
00246         *tcv = wt->_tcV;
00247         *tcw = wt->_tcW;
00248 }
00249 
00250 extern "C" float *smoke_get_density(FLUID_3D *fluid)
00251 {
00252         return fluid->_density;
00253 }
00254 
00255 extern "C" float *smoke_get_heat(FLUID_3D *fluid)
00256 {
00257         return fluid->_heat;
00258 }
00259 
00260 extern "C" float *smoke_get_velocity_x(FLUID_3D *fluid)
00261 {
00262         return fluid->_xVelocity;
00263 }
00264 
00265 extern "C" float *smoke_get_velocity_y(FLUID_3D *fluid)
00266 {
00267         return fluid->_yVelocity;
00268 }
00269 
00270 extern "C" float *smoke_get_velocity_z(FLUID_3D *fluid)
00271 {
00272         return fluid->_zVelocity;
00273 }
00274 
00275 extern "C" float *smoke_get_force_x(FLUID_3D *fluid)
00276 {
00277         return fluid->_xForce;
00278 }
00279 
00280 extern "C" float *smoke_get_force_y(FLUID_3D *fluid)
00281 {
00282         return fluid->_yForce;
00283 }
00284 
00285 extern "C" float *smoke_get_force_z(FLUID_3D *fluid)
00286 {
00287         return fluid->_zForce;
00288 }
00289 
00290 extern "C" float *smoke_turbulence_get_density(WTURBULENCE *wt)
00291 {
00292         return wt ? wt->getDensityBig() : NULL;
00293 }
00294 
00295 extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res)
00296 {
00297         if(wt)
00298         {
00299                 Vec3Int r = wt->getResBig();
00300                 res[0] = r[0];
00301                 res[1] = r[1];
00302                 res[2] = r[2];
00303         }
00304 }
00305 
00306 extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
00307 {
00308         return fluid->_obstacles;
00309 }
00310 
00311 extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
00312 {
00313         wt->setNoise(type);
00314 }