Cleanup: remove redundant doxygen \file argument
[blender.git] / intern / smoke / intern / smoke_API.cpp
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 by Daniel Genrich
17  * All rights reserved.
18  */
19
20 /** \file \ingroup smoke
21  */
22
23 #include "FLUID_3D.h"
24 #include "WTURBULENCE.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <math.h>
29
30 #include "../extern/smoke_API.h"  /* to ensure valid prototypes */
31
32 extern "C" FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, int use_fire, int use_colors)
33 {
34         FLUID_3D *fluid = new FLUID_3D(res, dx, dtdef, use_heat, use_fire, use_colors);
35         return fluid;
36 }
37
38 extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, const char *noisefile_path, int use_fire, int use_colors)
39 {
40         if (amplify)
41                 return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype, noisefile_path, use_fire, use_colors);
42         else 
43                 return NULL;
44 }
45
46 extern "C" void smoke_free(FLUID_3D *fluid)
47 {
48         delete fluid;
49         fluid = NULL;
50 }
51
52 extern "C" void smoke_turbulence_free(WTURBULENCE *wt)
53 {
54          delete wt;
55          wt = NULL;
56 }
57
58 extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
59 {
60         return x + y * max_x + z * max_x*max_y;
61 }
62
63 extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z, int max_z */)
64 {
65         return x + y * max_x;
66 }
67
68 extern "C" void smoke_step(FLUID_3D *fluid, float gravity[3], float dtSubdiv)
69 {
70         if (fluid->_fuel) {
71                 fluid->processBurn(fluid->_fuel, fluid->_density, fluid->_react, fluid->_heat,
72                                                    fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, (*fluid->_dtFactor)*dtSubdiv);
73         }
74         fluid->step(dtSubdiv, gravity);
75
76         if (fluid->_fuel) {
77                 fluid->updateFlame(fluid->_react, fluid->_flame, fluid->_totalCells);
78         }
79 }
80
81 extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
82 {
83         if (wt->_fuelBig) {
84                 fluid->processBurn(wt->_fuelBig, wt->_densityBig, wt->_reactBig, 0,
85                                                    wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, fluid->_dt);
86         }
87         wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles);
88
89         if (wt->_fuelBig) {
90                 fluid->updateFlame(wt->_reactBig, wt->_flameBig, wt->_totalCellsBig);
91         }
92 }
93
94 extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate,
95                                                                          float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp)
96 {
97         fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli, burning_rate, flame_smoke, flame_smoke_color, flame_vorticity, flame_ignition_temp, flame_max_temp);
98 }
99
100 extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength)
101 {
102         wt->initBlenderRNA(strength);
103 }
104
105 static void data_dissolve(float *density, float *heat, float *r, float *g, float *b, int total_cells, int speed, int log)
106 {
107         if (log) {
108                 /* max density/speed = dydx */
109                 float fac = 1.0f - (1.0f / (float)speed);
110
111                 for(size_t i = 0; i < total_cells; i++)
112                 {
113                         /* density */
114                         density[i] *= fac;
115
116                         /* heat */
117                         if (heat) {
118                                 heat[i] *= fac;
119                         }
120
121                         /* color */
122                         if (r) {
123                                 r[i] *= fac;
124                                 g[i] *= fac;
125                                 b[i] *= fac;
126                         }
127                 }
128         }
129         else // linear falloff
130         {
131                 /* max density/speed = dydx */
132                 float dydx = 1.0f / (float)speed;
133
134                 for(size_t i = 0; i < total_cells; i++)
135                 {
136                         float d = density[i];
137                         /* density */
138                         density[i] -= dydx;
139                         if (density[i] < 0.0f)
140                                 density[i] = 0.0f;
141
142                         /* heat */
143                         if (heat) {
144                                 if      (abs(heat[i]) < dydx) heat[i] = 0.0f;
145                                 else if (heat[i] > 0.0f) heat[i] -= dydx;
146                                 else if (heat[i] < 0.0f) heat[i] += dydx;
147                         }
148
149                         /* color */
150                         if (r && d) {
151                                 r[i] *= (density[i]/d);
152                                 g[i] *= (density[i]/d);
153                                 b[i] *= (density[i]/d);
154                         }
155                                 
156                 }
157         }
158 }
159
160 extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
161 {
162         data_dissolve(fluid->_density, fluid->_heat, fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, speed, log);
163 }
164
165 extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log)
166 {
167         data_dissolve(wt->_densityBig, 0, wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, speed, log);
168 }
169
170 extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens, float **react, float **flame, float **fuel, float **heat, 
171                                                          float **heatold, float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles)
172 {
173         *dens = fluid->_density;
174         if(fuel)
175                 *fuel = fluid->_fuel;
176         if(react)
177                 *react = fluid->_react;
178         if(flame)
179                 *flame = fluid->_flame;
180         if(heat)
181                 *heat = fluid->_heat;
182         if(heatold)
183                 *heatold = fluid->_heatOld;
184         *vx = fluid->_xVelocity;
185         *vy = fluid->_yVelocity;
186         *vz = fluid->_zVelocity;
187         if(r)
188                 *r = fluid->_color_r;
189         if(g)
190                 *g = fluid->_color_g;
191         if(b)
192                 *b = fluid->_color_b;
193         *obstacles = fluid->_obstacles;
194         *dt = fluid->_dt;
195         *dx = fluid->_dx;
196 }
197
198 extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **react, float **flame, float **fuel,
199                                         float **r, float **g, float **b , float **tcu, float **tcv, float **tcw)
200 {
201         if (!wt)
202                 return;
203
204         *dens = wt->_densityBig;
205         if(fuel)
206                 *fuel = wt->_fuelBig;
207         if(react)
208                 *react = wt->_reactBig;
209         if(flame)
210                 *flame = wt->_flameBig;
211         if(r)
212                 *r = wt->_color_rBig;
213         if(g)
214                 *g = wt->_color_gBig;
215         if(b)
216                 *b = wt->_color_bBig;
217         *tcu = wt->_tcU;
218         *tcv = wt->_tcV;
219         *tcw = wt->_tcW;
220 }
221
222 extern "C" float *smoke_get_density(FLUID_3D *fluid)
223 {
224         return fluid->_density;
225 }
226
227 extern "C" float *smoke_get_fuel(FLUID_3D *fluid)
228 {
229         return fluid->_fuel;
230 }
231
232 extern "C" float *smoke_get_react(FLUID_3D *fluid)
233 {
234         return fluid->_react;
235 }
236
237 extern "C" float *smoke_get_heat(FLUID_3D *fluid)
238 {
239         return fluid->_heat;
240 }
241
242 extern "C" float *smoke_get_velocity_x(FLUID_3D *fluid)
243 {
244         return fluid->_xVelocity;
245 }
246
247 extern "C" float *smoke_get_velocity_y(FLUID_3D *fluid)
248 {
249         return fluid->_yVelocity;
250 }
251
252 extern "C" float *smoke_get_velocity_z(FLUID_3D *fluid)
253 {
254         return fluid->_zVelocity;
255 }
256
257 extern "C" float *smoke_get_force_x(FLUID_3D *fluid)
258 {
259         return fluid->_xForce;
260 }
261
262 extern "C" float *smoke_get_force_y(FLUID_3D *fluid)
263 {
264         return fluid->_yForce;
265 }
266
267 extern "C" float *smoke_get_force_z(FLUID_3D *fluid)
268 {
269         return fluid->_zForce;
270 }
271
272 extern "C" float *smoke_get_flame(FLUID_3D *fluid)
273 {
274         return fluid->_flame;
275 }
276
277 extern "C" float *smoke_get_color_r(FLUID_3D *fluid)
278 {
279         return fluid->_color_r;
280 }
281
282 extern "C" float *smoke_get_color_g(FLUID_3D *fluid)
283 {
284         return fluid->_color_g;
285 }
286
287 extern "C" float *smoke_get_color_b(FLUID_3D *fluid)
288 {
289         return fluid->_color_b;
290 }
291
292 static void get_rgba(float *r, float *g, float *b, float *a, int total_cells, float *data, int sequential)
293 {
294         int i;
295         int m = 4, i_g = 1, i_b = 2, i_a = 3;
296         /* sequential data */
297         if (sequential) {
298                 m = 1;
299                 i_g *= total_cells;
300                 i_b *= total_cells;
301                 i_a *= total_cells;
302         }
303
304         for (i=0; i<total_cells; i++) {
305                 float alpha = a[i];
306                 if (alpha) {
307                         data[i*m  ] = r[i];
308                         data[i*m+i_g] = g[i];
309                         data[i*m+i_b] = b[i];
310                 }
311                 else {
312                         data[i*m  ] = data[i*m+i_g] = data[i*m+i_b] = 0.0f;
313                 }
314                 data[i*m+i_a] = alpha;
315         }
316 }
317
318 extern "C" void smoke_get_rgba(FLUID_3D *fluid, float *data, int sequential)
319 {
320         get_rgba(fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_density, fluid->_totalCells, data, sequential);
321 }
322
323 extern "C" void smoke_turbulence_get_rgba(WTURBULENCE *wt, float *data, int sequential)
324 {
325         get_rgba(wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_densityBig, wt->_totalCellsBig, data, sequential);
326 }
327
328 /* get a single color premultiplied voxel grid */
329 static void get_rgba_from_density(float color[3], float *a, int total_cells, float *data, int sequential)
330 {
331         int i;
332         int m = 4, i_g = 1, i_b = 2, i_a = 3;
333         /* sequential data */
334         if (sequential) {
335                 m = 1;
336                 i_g *= total_cells;
337                 i_b *= total_cells;
338                 i_a *= total_cells;
339         }
340
341         for (i=0; i<total_cells; i++) {
342                 float alpha = a[i];
343                 if (alpha) {
344                         data[i*m  ] = color[0] * alpha;
345                         data[i*m+i_g] = color[1] * alpha;
346                         data[i*m+i_b] = color[2] * alpha;
347                 }
348                 else {
349                         data[i*m  ] = data[i*m+i_g] = data[i*m+i_b] = 0.0f;
350                 }
351                 data[i*m+i_a] = alpha;
352         }
353 }
354
355 extern "C" void smoke_get_rgba_from_density(FLUID_3D *fluid, float color[3], float *data, int sequential)
356 {
357         get_rgba_from_density(color, fluid->_density, fluid->_totalCells, data, sequential);
358 }
359
360 extern "C" void smoke_turbulence_get_rgba_from_density(WTURBULENCE *wt, float color[3], float *data, int sequential)
361 {
362         get_rgba_from_density(color, wt->_densityBig, wt->_totalCellsBig, data, sequential);
363 }
364
365 extern "C" float *smoke_turbulence_get_density(WTURBULENCE *wt)
366 {
367         return wt ? wt->getDensityBig() : NULL;
368 }
369
370 extern "C" float *smoke_turbulence_get_fuel(WTURBULENCE *wt)
371 {
372         return wt ? wt->getFuelBig() : NULL;
373 }
374
375 extern "C" float *smoke_turbulence_get_react(WTURBULENCE *wt)
376 {
377         return wt ? wt->_reactBig : NULL;
378 }
379
380 extern "C" float *smoke_turbulence_get_color_r(WTURBULENCE *wt)
381 {
382         return wt ? wt->_color_rBig : NULL;
383 }
384
385 extern "C" float *smoke_turbulence_get_color_g(WTURBULENCE *wt)
386 {
387         return wt ? wt->_color_gBig : NULL;
388 }
389
390 extern "C" float *smoke_turbulence_get_color_b(WTURBULENCE *wt)
391 {
392         return wt ? wt->_color_bBig : NULL;
393 }
394
395 extern "C" float *smoke_turbulence_get_flame(WTURBULENCE *wt)
396 {
397         return wt ? wt->getFlameBig() : NULL;
398 }
399
400 extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res)
401 {
402         if (wt) {
403                 Vec3Int r = wt->getResBig();
404                 res[0] = r[0];
405                 res[1] = r[1];
406                 res[2] = r[2];
407         }
408 }
409
410 extern "C" int smoke_turbulence_get_cells(WTURBULENCE *wt)
411 {
412         if (wt) {
413                 Vec3Int r = wt->getResBig();
414                 return r[0] * r[1] * r[2];
415         }
416         return 0;
417 }
418
419 extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
420 {
421         return fluid->_obstacles;
422 }
423
424 extern "C" void smoke_get_ob_velocity(FLUID_3D *fluid, float **x, float **y, float **z)
425 {
426         *x = fluid->_xVelocityOb;
427         *y = fluid->_yVelocityOb;
428         *z = fluid->_zVelocityOb;
429 }
430
431 #if 0
432 extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid)
433 {
434         return fluid->_obstaclesAnim;
435 }
436 #endif
437
438 extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type, const char *noisefile_path)
439 {
440         wt->setNoise(type, noisefile_path);
441 }
442
443 extern "C" int smoke_has_heat(FLUID_3D *fluid)
444 {
445         return (fluid->_heat) ? 1 : 0;
446 }
447
448 extern "C" int smoke_has_fuel(FLUID_3D *fluid)
449 {
450         return (fluid->_fuel) ? 1 : 0;
451 }
452
453 extern "C" int smoke_has_colors(FLUID_3D *fluid)
454 {
455         return (fluid->_color_r && fluid->_color_g && fluid->_color_b) ? 1 : 0;
456 }
457
458 extern "C" int smoke_turbulence_has_fuel(WTURBULENCE *wt)
459 {
460         return (wt->_fuelBig) ? 1 : 0;
461 }
462
463 extern "C" int smoke_turbulence_has_colors(WTURBULENCE *wt)
464 {
465         return (wt->_color_rBig && wt->_color_gBig && wt->_color_bBig) ? 1 : 0;
466 }
467
468 /* additional field initialization */
469 extern "C" void smoke_ensure_heat(FLUID_3D *fluid)
470 {
471         if (fluid) {
472                 fluid->initHeat();
473         }
474 }
475
476 extern "C" void smoke_ensure_fire(FLUID_3D *fluid, WTURBULENCE *wt)
477 {
478         if (fluid) {
479                 fluid->initFire();
480         }
481         if (wt) {
482                 wt->initFire();
483         }
484 }
485
486 extern "C" void smoke_ensure_colors(FLUID_3D *fluid, WTURBULENCE *wt, float init_r, float init_g, float init_b)
487 {
488         if (fluid) {
489                 fluid->initColors(init_r, init_g, init_b);
490         }
491         if (wt) {
492                 wt->initColors(init_r, init_g, init_b);
493         }
494 }