b45fef2650476fcc540d031337c0155dc3e3efe5
[blender.git] / intern / smoke / intern / smoke_API.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 by Daniel Genrich
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Genrich
22  *                 Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file smoke/intern/smoke_API.cpp
28  *  \ingroup smoke
29  */
30
31
32 #include "FLUID_3D.h"
33 #include "WTURBULENCE.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <math.h>
38
39 // y in smoke is z in blender
40 extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef)
41 {
42         // smoke lib uses y as top-bottom/vertical axis where blender uses z
43         FLUID_3D *fluid = new FLUID_3D(res, p0, dtdef);
44
45         // printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
46
47         return fluid;
48 }
49
50 extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype)
51 {
52         // initialize wavelet turbulence
53         if(amplify)
54                 return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype);
55         else 
56                 return NULL;
57 }
58
59 extern "C" void smoke_free(FLUID_3D *fluid)
60 {
61         delete fluid;
62         fluid = NULL;
63 }
64
65 extern "C" void smoke_turbulence_free(WTURBULENCE *wt)
66 {
67          delete wt;
68          wt = NULL;
69 }
70
71 extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
72 {
73         // // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1];
74         return x + y * max_x + z * max_x*max_y;
75 }
76
77 extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z, int max_z */)
78 {
79         return x + y * max_x;
80 }
81
82 extern "C" void smoke_step(FLUID_3D *fluid, float dtSubdiv)
83 {
84         fluid->step(dtSubdiv);
85 }
86
87 extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
88 {
89         wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles); 
90 }
91
92 extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli)
93 {
94         fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli);
95 }
96
97 extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
98 {
99         float *density = fluid->_density;
100         //float *densityOld = fluid->_densityOld;
101         float *heat = fluid->_heat;
102
103         if(log)
104         {
105                 /* max density/speed = dydx */
106                 float dydx = 1.0 / (float)speed;
107                 size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
108
109                 for(size_t i = 0; i < size; i++)
110                 {
111                         density[i] *= (1.0 - dydx);
112
113                         if(density[i] < 0.0f)
114                                 density[i] = 0.0f;
115
116                         heat[i] *= (1.0 - dydx);
117
118                         /*if(heat[i] < 0.0f)
119                                 heat[i] = 0.0f;*/
120                 }
121         }
122         else // linear falloff
123         {
124                 /* max density/speed = dydx */
125                 float dydx = 1.0 / (float)speed;
126                 size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
127
128                 for(size_t i = 0; i < size; i++)
129                 {
130                         density[i] -= dydx;
131
132                         if(density[i] < 0.0f)
133                                 density[i] = 0.0f;
134
135                         if(abs(heat[i]) < dydx) heat[i] = 0.0f;
136                         else if (heat[i]>0.0f) heat[i] -= dydx;
137                         else if (heat[i]<0.0f) heat[i] += dydx;
138                                 
139                 }
140         }
141 }
142
143 extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log)
144 {
145         float *density = wt->getDensityBig();
146         Vec3Int r = wt->getResBig();
147
148         if(log)
149         {
150                 /* max density/speed = dydx */
151                 float dydx = 1.0 / (float)speed;
152                 size_t size= r[0] * r[1] * r[2];
153
154                 for(size_t i = 0; i < size; i++)
155                 {
156                         density[i] *= (1.0 - dydx);
157
158                         if(density[i] < 0.0f)
159                                 density[i] = 0.0f;
160                 }
161         }
162         else // linear falloff
163         {
164                 /* max density/speed = dydx */
165                 float dydx = 1.0 / (float)speed;
166                 size_t size= r[0] * r[1] * r[2];
167
168                 for(size_t i = 0; i < size; i++)
169                 {
170                         density[i] -= dydx;
171
172                         if(density[i] < 0.0f)
173                                 density[i] = 0.0f;                              
174                 }
175         }
176 }
177
178 extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength)
179 {
180         wt->initBlenderRNA(strength);
181 }
182
183 template < class T > inline T ABS( T a )
184 {
185         return (0 < a) ? a : -a ;
186 }
187
188 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)
189 {
190         *dens = fluid->_density;
191         *densold = fluid->_densityOld;
192         *heat = fluid->_heat;
193         *heatold = fluid->_heatOld;
194         *vx = fluid->_xVelocity;
195         *vy = fluid->_yVelocity;
196         *vz = fluid->_zVelocity;
197         *vxold = fluid->_xVelocityOld;
198         *vyold = fluid->_yVelocityOld;
199         *vzold = fluid->_zVelocityOld;
200         *obstacles = fluid->_obstacles;
201         *dt = fluid->_dt;
202         *dx = fluid->_dx;
203
204 }
205
206 extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw)
207 {
208         if(!wt)
209                 return;
210
211         *dens = wt->_densityBig;
212         *densold = wt->_densityBigOld;
213         *tcu = wt->_tcU;
214         *tcv = wt->_tcV;
215         *tcw = wt->_tcW;
216 }
217
218 extern "C" float *smoke_get_density(FLUID_3D *fluid)
219 {
220         return fluid->_density;
221 }
222
223 extern "C" float *smoke_get_heat(FLUID_3D *fluid)
224 {
225         return fluid->_heat;
226 }
227
228 extern "C" float *smoke_get_velocity_x(FLUID_3D *fluid)
229 {
230         return fluid->_xVelocity;
231 }
232
233 extern "C" float *smoke_get_velocity_y(FLUID_3D *fluid)
234 {
235         return fluid->_yVelocity;
236 }
237
238 extern "C" float *smoke_get_velocity_z(FLUID_3D *fluid)
239 {
240         return fluid->_zVelocity;
241 }
242
243 extern "C" float *smoke_get_force_x(FLUID_3D *fluid)
244 {
245         return fluid->_xForce;
246 }
247
248 extern "C" float *smoke_get_force_y(FLUID_3D *fluid)
249 {
250         return fluid->_yForce;
251 }
252
253 extern "C" float *smoke_get_force_z(FLUID_3D *fluid)
254 {
255         return fluid->_zForce;
256 }
257
258 extern "C" float *smoke_turbulence_get_density(WTURBULENCE *wt)
259 {
260         return wt ? wt->getDensityBig() : NULL;
261 }
262
263 extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res)
264 {
265         if(wt)
266         {
267                 Vec3Int r = wt->getResBig();
268                 res[0] = r[0];
269                 res[1] = r[1];
270                 res[2] = r[2];
271         }
272 }
273
274 extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
275 {
276         return fluid->_obstacles;
277 }
278
279 extern "C" void smoke_get_ob_velocity(FLUID_3D *fluid, float **x, float **y, float **z)
280 {
281         *x = fluid->_xVelocityOb;
282         *y = fluid->_yVelocityOb;
283         *z = fluid->_zVelocityOb;
284 }
285
286 extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid)
287 {
288         return fluid->_obstaclesAnim;
289 }
290
291 extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
292 {
293         wt->setNoise(type);
294 }