|
Blender
V2.59
|
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 }