Smoke:
[blender.git] / source / blender / blenkernel / intern / smoke.c
index 416a208468b44f23393c8d0de0d22f5af46ad059..c619c3e25ab0a0a77df39d3b25113bc624e30123 100644 (file)
@@ -29,6 +29,8 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/* Part of the code copied from elbeem fluid library, copyright by Nils Thuerey */
+
 #include <GL/glew.h>
 
 #include "MEM_guardedalloc.h"
@@ -197,7 +199,9 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive
                        }
                }
 
-               printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
+               // TODO: put in failsafe if res<=0 - dg
+
+               // printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
 
                // dt max is 0.1
                smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->amplify, smd->domain->p0, smd->domain->p1, 2.5 / FPS);
@@ -220,10 +224,14 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive
 
                return 1;
        }
-       else if((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll)
+       else if((smd->type & MOD_SMOKE_TYPE_COLL))
        {
                smd->time = scene->r.cfra;
 
+               // todo: delete this when loading colls work -dg
+               if(!smd->coll)
+                       smokeModifier_createType(smd);
+
                if(!smd->coll->points)
                {
                        // init collision points
@@ -472,7 +480,7 @@ void smokeModifier_freeDomain(SmokeModifierData *smd)
                // free visualisation buffers
                if(smd->domain->bind)
                {
-                       glDeleteTextures(smd->domain->max_textures, smd->domain->bind);
+                       glDeleteTextures(smd->domain->max_textures, (GLuint *)smd->domain->bind);
                        MEM_freeN(smd->domain->bind);
                }
                smd->domain->max_textures = 0; // unnecessary but let's be sure
@@ -528,7 +536,7 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
                        // free visualisation buffers
                        if(smd->domain->bind)
                        {
-                               glDeleteTextures(smd->domain->max_textures, smd->domain->bind);
+                               glDeleteTextures(smd->domain->max_textures, (GLuint *)smd->domain->bind);
                                MEM_freeN(smd->domain->bind);
                                smd->domain->bind = NULL;
                        }
@@ -598,8 +606,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
                        smd->domain->eff_group = NULL;
                        smd->domain->fluid_group = NULL;
                        smd->domain->coll_group = NULL;
-                       smd->domain->maxres = 48;
-                       smd->domain->amplify = 4;
+                       smd->domain->maxres = 32;
+                       smd->domain->amplify = 2;
                        smd->domain->omega = 0.5;
                        smd->domain->alpha = -0.001;
                        smd->domain->beta = 0.1;
@@ -650,9 +658,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
 void smoke_calc_transparency(struct SmokeModifierData *smd, float *light, int big);
 
 void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
-{
-       int new = 0;
-
+{      
        if(scene->r.cfra >= smd->time)
                smokeModifier_init(smd, ob, scene, dm);
 
@@ -769,7 +775,6 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
                                                                for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++)
                                                                {
                                                                        int cell[3];
-                                                                       int valid = 1;
                                                                        size_t i = 0;
                                                                        size_t index = 0;
                                                                        
@@ -786,33 +791,57 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
                                                                
                                                                        // check if cell is valid (in the domain boundary)
                                                                        for(i = 0; i < 3; i++)
+                                                                       {
                                                                                if((cell[i] > sds->res[i] - 1) || (cell[i] < 0))
-                                                                                       valid = 0;
-                                                                       
-                                                                       if(!valid)
-                                                                               continue;
+                                                                                       continue;
+                                                                       }
                                                                        
                                                                        // 2. set cell values (heat, density and velocity)
-                                                                       index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2], sds->res[2]);
+                                                                       index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
                                                                        
-                                                                       heat[index] = sfs->temp;
-                                                                       density[index] = sfs->density;
-                                                                       velocity_x[index] = pa->state.vel[0];
-                                                                       velocity_y[index] = pa->state.vel[1];
-                                                                       velocity_z[index] = pa->state.vel[2];
-
-                                                                       // we need different handling for the high-res feature
-                                                                       if(bigdensity)
+                                                                       if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) // this is inflow
+                                                                       {
+                                                                               heat[index] = sfs->temp;
+                                                                               density[index] = sfs->density;
+                                                                               velocity_x[index] = pa->state.vel[0];
+                                                                               velocity_y[index] = pa->state.vel[1];
+                                                                               velocity_z[index] = pa->state.vel[2];
+
+                                                                               // we need different handling for the high-res feature
+                                                                               if(bigdensity)
+                                                                               {
+                                                                                       // init all surrounding cells according to amplification, too
+                                                                                       int i, j, k;
+                                                                                       for(i = 0; i < smd->domain->amplify; i++)
+                                                                                               for(j = 0; j < smd->domain->amplify; j++)
+                                                                                                       for(k = 0; k < smd->domain->amplify; k++)
+                                                                                                       {
+                                                                                                               index = smoke_get_index(smd->domain->amplify * cell[0] + i, bigres[0], smd->domain->amplify * cell[1] + j, bigres[1], smd->domain->amplify * cell[2] + k);
+                                                                                                               bigdensity[index] = sfs->density;
+                                                                                                       }
+                                                                               }
+                                                                       }
+                                                                       else // outflow
                                                                        {
-                                                                               // init all surrounding cells according to amplification, too
-                                                                               int i, j, k;
-                                                                               for(i = 0; i < smd->domain->amplify; i++)
-                                                                                       for(j = 0; j < smd->domain->amplify; j++)
-                                                                                               for(k = 0; k < smd->domain->amplify; k++)
-                                                                                               {
-                                                                                                       index = smoke_get_index(smd->domain->amplify * cell[0] + i, bigres[0], smd->domain->amplify * cell[1] + j, bigres[1], smd->domain->amplify * cell[2] + k, bigres[2]);
-                                                                                                       bigdensity[index] = sfs->density;
-                                                                                               }
+                                                                               heat[index] = 0.f;
+                                                                               density[index] = 0.f;
+                                                                               velocity_x[index] = 0.f;
+                                                                               velocity_y[index] = 0.f;
+                                                                               velocity_z[index] = 0.f;
+
+                                                                               // we need different handling for the high-res feature
+                                                                               if(bigdensity)
+                                                                               {
+                                                                                       // init all surrounding cells according to amplification, too
+                                                                                       int i, j, k;
+                                                                                       for(i = 0; i < smd->domain->amplify; i++)
+                                                                                               for(j = 0; j < smd->domain->amplify; j++)
+                                                                                                       for(k = 0; k < smd->domain->amplify; k++)
+                                                                                                       {
+                                                                                                               index = smoke_get_index(smd->domain->amplify * cell[0] + i, bigres[0], smd->domain->amplify * cell[1] + j, bigres[1], smd->domain->amplify * cell[2] + k);
+                                                                                                               bigdensity[index] = 0.f;
+                                                                                                       }
+                                                                               }
                                                                        }
                                                                }
                                                        }       
@@ -888,7 +917,6 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
                                                        // we got nice collision object
                                                        SmokeCollSettings *scs = smd2->coll;
                                                        int cell[3];
-                                                       int valid = 1;
                                                        size_t index = 0;
                                                        size_t i, j;
                                                        unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid);
@@ -901,13 +929,10 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
                                                                // check if cell is valid (in the domain boundary)
                                                                for(j = 0; j < 3; j++)
                                                                        if((cell[j] > sds->res[j] - 1) || (cell[j] < 0))
-                                                                               valid = 0;
-                                                               
-                                                               if(!valid)
-                                                                       continue;
+                                                                               continue;
                                                                
                                                                // 2. set cell values (heat, density and velocity)
-                                                               index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2], sds->res[2]);
+                                                               index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
                                                                        
                                                                obstacles[index] = 1;
 
@@ -964,7 +989,6 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
 void smoke_prepare_View(SmokeModifierData *smd, float *light)
 {
        float *density = NULL;
-       size_t i = 0;
        int x, y, z;
 
        if(!smd->domain->tray)
@@ -986,12 +1010,12 @@ void smoke_prepare_View(SmokeModifierData *smd, float *light)
                                {
                                        size_t index;
 
-                                       index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z, smd->domain->res[2]);
+                                       index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z);
                                        // Transparency computation
                                        // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4
                                        // T_vox = exp(-C_ext * h)
                                        // C_ext/sigma_t = density * C_ext
-                                       smoke_set_tvox(smd, index, exp(-density[index] * smd->domain->dx));
+                                       smoke_set_tvox(smd, index, exp(-density[index] * 4.0 * smd->domain->dx));
        }
        smoke_calc_transparency(smd, light, 0);
 }
@@ -1023,7 +1047,7 @@ void smoke_prepare_bigView(SmokeModifierData *smd, float *light)
                // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4
                // T_vox = exp(-C_ext * h)
                // C_ext/sigma_t = density * C_ext
-               smoke_set_bigtvox(smd, i, exp(-density[i] * smd->domain->dx / smd->domain->amplify) );
+               smoke_set_bigtvox(smd, i, exp(-density[i] * 4.0 * smd->domain->dx / smd->domain->amplify) );
        }
        smoke_calc_transparency(smd, light, 1);
 }
@@ -1091,7 +1115,7 @@ long long smoke_get_mem_req(int xres, int yres, int zres, int amplify)
 static void calc_voxel_transp(SmokeModifierData *smd, int *pixel, float *tRay)
 {
        // printf("Pixel(%d, %d, %d)\n", pixel[0], pixel[1], pixel[2]);
-       const size_t index = smoke_get_index(pixel[0], smd->domain->res[0], pixel[1], smd->domain->res[1], pixel[2], smd->domain->res[2]);
+       const size_t index = smoke_get_index(pixel[0], smd->domain->res[0], pixel[1], smd->domain->res[1], pixel[2]);
 
        // T_ray *= T_vox
        *tRay *= smoke_get_tvox(smd, index);
@@ -1103,7 +1127,7 @@ static void calc_voxel_transp_big(SmokeModifierData *smd, int *pixel, float *tRa
        size_t index;
 
        smoke_get_bigres(smd->domain->fluid, bigres);
-       index = smoke_get_index(pixel[0], bigres[0], pixel[1], bigres[1], pixel[2], bigres[2]);
+       index = smoke_get_index(pixel[0], bigres[0], pixel[1], bigres[1], pixel[2]);
 
        /*
        if(index > bigres[0]*bigres[1]*bigres[2])
@@ -1145,7 +1169,7 @@ static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, i
                                calc_voxel_transp(smd, pixel, tRay);
                        else
                                calc_voxel_transp_big(smd, pixel, tRay);
-               if(tRay < 0)
+               if(*tRay < 0.0f)
                        return;
             if (err_1 > 0) {
                 pixel[1] += y_inc;
@@ -1167,7 +1191,7 @@ static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, i
                                calc_voxel_transp(smd, pixel, tRay);
                        else
                                calc_voxel_transp_big(smd, pixel, tRay);
-               if(tRay < 0)
+               if(*tRay < 0.0f)
                        return;
             if (err_1 > 0) {
                 pixel[0] += x_inc;
@@ -1189,7 +1213,7 @@ static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, i
                                calc_voxel_transp(smd, pixel, tRay);
                        else
                                calc_voxel_transp_big(smd, pixel, tRay);
-               if(tRay < 0)
+               if(*tRay < 0.0f)
                        return;
             if (err_1 > 0) {
                 pixel[1] += y_inc;
@@ -1219,15 +1243,15 @@ static void get_cell(struct SmokeModifierData *smd, float *pos, int *cell, int c
 
        if(correct)
        {
-               cell[0] = MIN2(smd->domain->res[0] - 1, MAX2(0, (int)(tmp[0] + 0.5)));
-               cell[1] = MIN2(smd->domain->res[1] - 1, MAX2(0, (int)(tmp[1] + 0.5)));
-               cell[2] = MIN2(smd->domain->res[2] - 1, MAX2(0, (int)(tmp[2] + 0.5)));
+               cell[0] = MIN2(smd->domain->res[0] - 1, MAX2(0, (int)floor(tmp[0])));
+               cell[1] = MIN2(smd->domain->res[1] - 1, MAX2(0, (int)floor(tmp[1])));
+               cell[2] = MIN2(smd->domain->res[2] - 1, MAX2(0, (int)floor(tmp[2])));
        }
        else
        {
-               cell[0] = (int)(tmp[0] + 0.5);
-               cell[1] = (int)(tmp[1] + 0.5);
-               cell[2] = (int)(tmp[2] + 0.5);
+               cell[0] = (int)floor(tmp[0]);
+               cell[1] = (int)floor(tmp[1]);
+               cell[2] = (int)floor(tmp[2]);
        }
 }
 static void get_bigcell(struct SmokeModifierData *smd, float *pos, int *cell, int correct)
@@ -1242,15 +1266,15 @@ static void get_bigcell(struct SmokeModifierData *smd, float *pos, int *cell, in
 
        if(correct)
        {
-               cell[0] = MIN2(res[0] - 1, MAX2(0, (int)(tmp[0] + 0.5)));
-               cell[1] = MIN2(res[1] - 1, MAX2(0, (int)(tmp[1] + 0.5)));
-               cell[2] = MIN2(res[2] - 1, MAX2(0, (int)(tmp[2] + 0.5)));
+               cell[0] = MIN2(res[0] - 1, MAX2(0, (int)floor(tmp[0])));
+               cell[1] = MIN2(res[1] - 1, MAX2(0, (int)floor(tmp[1])));
+               cell[2] = MIN2(res[2] - 1, MAX2(0, (int)floor(tmp[2])));
        }
        else
        {
-               cell[0] = (int)(tmp[0] + 0.5);
-               cell[1] = (int)(tmp[1] + 0.5);
-               cell[2] = (int)(tmp[2] + 0.5);
+               cell[0] = (int)floor(tmp[0]);
+               cell[1] = (int)floor(tmp[1]);
+               cell[2] = (int)floor(tmp[2]);
        }
 }
 
@@ -1301,7 +1325,7 @@ void smoke_calc_transparency(struct SmokeModifierData *smd, float *light, int bi
                                int cell[3];
                                float tRay = 1.0;
 
-                               index = smoke_get_index(x, res[0], y, res[1], z, res[2]);
+                               index = smoke_get_index(x, res[0], y, res[1], z);
 
                                // voxelCenter = m_voxelarray[i].GetCenter();
                                voxelCenter[0] = smd->domain->p0[0] + smd->domain->dx * bigfactor * x + smd->domain->dx * bigfactor * 0.5;