Smoke: Support for moving obstacles. (Merge from Smoke2 branch)
authorDaniel Genrich <daniel.genrich@gmx.net>
Sat, 28 Apr 2012 21:46:43 +0000 (21:46 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Sat, 28 Apr 2012 21:46:43 +0000 (21:46 +0000)
Sponsored by the Blender Development Fund.
http://www.blender.org/blenderorg/blender-foundation/development-fund/

Remarks:
The original code was not designed to support moving obstacles so I had to introduce some velocity constraints into the code to prevent smoke from exploding. If this causes problems with "fire" emulation, please let me know.

intern/smoke/extern/smoke_API.h
intern/smoke/intern/FLUID_3D.cpp
intern/smoke/intern/FLUID_3D.h
intern/smoke/intern/OBSTACLE.h
intern/smoke/intern/WTURBULENCE.cpp
intern/smoke/intern/smoke_API.cpp
release/scripts/startup/bl_ui/properties_physics_smoke.py
source/blender/blenkernel/intern/smoke.c
source/blender/makesdna/DNA_smoke_types.h
source/blender/makesrna/intern/rna_smoke.c

index 9d5dfd988233d62d5a96b8e1f91a96607057da40..a0eb1bf38e0c92825a94d41615a45d3f2317d34d 100644 (file)
@@ -41,11 +41,11 @@ struct FLUID_3D;
 void smoke_export(struct 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);
 
 // low res
-struct FLUID_3D *smoke_init(int *res, float *p0);
+struct FLUID_3D *smoke_init(int *res, float *p0, float dtdef);
 void smoke_free(struct FLUID_3D *fluid);
 
 void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli);
-void smoke_step(struct FLUID_3D *fluid, size_t framenr, float fps);
+void smoke_step(struct FLUID_3D *fluid, float dtSubdiv);
 
 float *smoke_get_density(struct FLUID_3D *fluid);
 float *smoke_get_heat(struct FLUID_3D *fluid);
@@ -53,6 +53,9 @@ float *smoke_get_velocity_x(struct FLUID_3D *fluid);
 float *smoke_get_velocity_y(struct FLUID_3D *fluid);
 float *smoke_get_velocity_z(struct FLUID_3D *fluid);
 
+/* Moving obstacle velocity provided by blender */
+void smoke_get_ob_velocity(struct FLUID_3D *fluid, float **x, float **y, float **z);
+
 float *smoke_get_force_x(struct FLUID_3D *fluid);
 float *smoke_get_force_y(struct FLUID_3D *fluid);
 float *smoke_get_force_z(struct FLUID_3D *fluid);
index 9f036cc6d2fe859429db818ff3ae9e2a3d62fbe1..04971f898e93388b4c42cebabd991b5928605bc5 100644 (file)
@@ -34,6 +34,8 @@
 #include "SPHERE.h"
 #include <zlib.h>
 
+#include "float.h"
+
 #if PARALLEL==1
 #include <omp.h>
 #endif // PARALLEL 
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
 
-FLUID_3D::FLUID_3D(int *res, float *p0) :
+FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
        _xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f)
 {
        // set simulation consts
-       _dt = DT_DEFAULT;       // just in case. set in step from a RNA factor
+       _dt = dtdef;    // just in case. set in step from a RNA factor
        
        // start point of array
        _p0[0] = p0[0];
@@ -81,6 +83,9 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
        _xVelocity    = new float[_totalCells];
        _yVelocity    = new float[_totalCells];
        _zVelocity    = new float[_totalCells];
+       _xVelocityOb  = new float[_totalCells];
+       _yVelocityOb  = new float[_totalCells];
+       _zVelocityOb  = new float[_totalCells];
        _xVelocityOld = new float[_totalCells];
        _yVelocityOld = new float[_totalCells];
        _zVelocityOld = new float[_totalCells];
@@ -111,6 +116,9 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
                _xVelocity[x]    = 0.0f;
                _yVelocity[x]    = 0.0f;
                _zVelocity[x]    = 0.0f;
+               _xVelocityOb[x]  = 0.0f;
+               _yVelocityOb[x]  = 0.0f;
+               _zVelocityOb[x]  = 0.0f;
                _xVelocityOld[x] = 0.0f;
                _yVelocityOld[x] = 0.0f;
                _zVelocityOld[x] = 0.0f;
@@ -131,9 +139,15 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
 
        _colloPrev = 1; // default value
 
+       setBorderObstacles(); // walls
+
+}
 
+void FLUID_3D::setBorderObstacles()
+{
+       
        // set side obstacles
-       int index;
+       unsigned int index;
        for (int y = 0; y < _yRes; y++)
        for (int x = 0; x < _xRes; x++)
        {
@@ -169,7 +183,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
                index += _xRes - 1;
                if(_domainBcRight==1) _obstacles[index] = 1;
        }
-
 }
 
 FLUID_3D::~FLUID_3D()
@@ -177,6 +190,9 @@ FLUID_3D::~FLUID_3D()
        if (_xVelocity) delete[] _xVelocity;
        if (_yVelocity) delete[] _yVelocity;
        if (_zVelocity) delete[] _zVelocity;
+       if (_xVelocityOb) delete[] _xVelocityOb;
+       if (_yVelocityOb) delete[] _yVelocityOb;
+       if (_zVelocityOb) delete[] _zVelocityOb;
        if (_xVelocityOld) delete[] _xVelocityOld;
        if (_yVelocityOld) delete[] _yVelocityOld;
        if (_zVelocityOld) delete[] _zVelocityOld;
@@ -214,10 +230,18 @@ void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float
 //////////////////////////////////////////////////////////////////////
 void FLUID_3D::step(float dt)
 {
+#if 0
        // If border rules have been changed
        if (_colloPrev != *_borderColli) {
+               printf("Border collisions changed\n");
+               
+               // DG TODO: Need to check that no animated obstacle flags are overwritten
                setBorderCollisions();
        }
+#endif
+
+       // DG: TODO for the moment redo border for every timestep since it's been deleted every time by moving obstacles
+       setBorderCollisions();
 
 
        // set delta time by dt_factor
@@ -786,6 +810,7 @@ void FLUID_3D::project()
        memset(_pressure, 0, sizeof(float)*_totalCells);
        memset(_divergence, 0, sizeof(float)*_totalCells);
        
+       // set velocity and pressure inside of obstacles to zero
        setObstacleBoundaries(_pressure, 0, _zRes);
        
        // copy out the boundaries
@@ -798,12 +823,49 @@ void FLUID_3D::project()
        if(_domainBcTop == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
        else setZeroZ(_zVelocity, _res, 0, _zRes);
 
+       /*
+       {
+               float maxx = 0, maxy = 0, maxz = 0;
+               for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
+               {
+                       if(_xVelocity[i] > maxx)
+                               maxx = _xVelocity[i];
+                       if(_yVelocity[i] > maxy)
+                               maxy = _yVelocity[i];
+                       if(_zVelocity[i] > maxz)
+                               maxz = _zVelocity[i];
+               }
+               printf("Max velx: %f, vely: %f, velz: %f\n", maxx, maxy, maxz);
+       }
+       */
+
+       /*
+       {
+               float maxvalue = 0;
+               for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
+               {
+                       if(_heat[i] > maxvalue)
+                               maxvalue = _heat[i];
+
+               }
+               printf("Max heat: %f\n", maxvalue);
+       }
+       */
+
        // calculate divergence
        index = _slabSize + _xRes + 1;
        for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
                for (y = 1; y < _yRes - 1; y++, index += 2)
                        for (x = 1; x < _xRes - 1; x++, index++)
                        {
+                               
+                               if(_obstacles[index])
+                               {
+                                       _divergence[index] = 0.0f;
+                                       continue;
+                               }
+                               
+
                                float xright = _xVelocity[index + 1];
                                float xleft  = _xVelocity[index - 1];
                                float yup    = _yVelocity[index + _xRes];
@@ -811,26 +873,82 @@ void FLUID_3D::project()
                                float ztop   = _zVelocity[index + _slabSize];
                                float zbottom = _zVelocity[index - _slabSize];
 
-                               if(_obstacles[index+1]) xright = - _xVelocity[index];
+                               if(_obstacles[index+1]) xright = - _xVelocity[index]; // DG: +=
                                if(_obstacles[index-1]) xleft  = - _xVelocity[index];
                                if(_obstacles[index+_xRes]) yup    = - _yVelocity[index];
                                if(_obstacles[index-_xRes]) ydown  = - _yVelocity[index];
                                if(_obstacles[index+_slabSize]) ztop    = - _zVelocity[index];
                                if(_obstacles[index-_slabSize]) zbottom = - _zVelocity[index];
 
+                               if(_obstacles[index+1] & 8)                     xright  += _xVelocityOb[index + 1];
+                               if(_obstacles[index-1] & 8)                     xleft   += _xVelocityOb[index - 1];
+                               if(_obstacles[index+_xRes] & 8)         yup             += _yVelocityOb[index + _xRes];
+                               if(_obstacles[index-_xRes] & 8)         ydown   += _yVelocityOb[index - _xRes];
+                               if(_obstacles[index+_slabSize] & 8) ztop    += _zVelocityOb[index + _slabSize];
+                               if(_obstacles[index-_slabSize] & 8) zbottom += _zVelocityOb[index - _slabSize];
+
                                _divergence[index] = -_dx * 0.5f * (
                                                xright - xleft +
                                                yup - ydown +
                                                ztop - zbottom );
 
-                               // DG: commenting this helps CG to get a better start, 10-20% speed improvement
-                               // _pressure[index] = 0.0f;
+                               // Pressure is zero anyway since now a local array is used
+                               _pressure[index] = 0.0f;
                        }
+
+
+       /*
+       {
+               float maxvalue = 0;
+               for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
+               {
+                       if(_divergence[i] > maxvalue)
+                               maxvalue = _divergence[i];
+
+               }
+               printf("Max divergence: %f\n", maxvalue);
+       }
+       */
+
        copyBorderAll(_pressure, 0, _zRes);
 
+       /*
+       {
+               float maxvalue = 0;
+               for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
+               {
+                       if(_pressure[i] > maxvalue)
+                               maxvalue = _pressure[i];
+               }
+               printf("Max pressure BEFORE: %f\n", maxvalue);
+       }
+       */
+
        // solve Poisson equation
        solvePressurePre(_pressure, _divergence, _obstacles);
 
+       {
+               float maxvalue = 0;
+               for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
+               {
+                       if(_pressure[i] > maxvalue)
+                               maxvalue = _pressure[i];
+
+                       /* HACK: Animated collision object sometimes result in a non converging solvePressurePre() */ 
+                       if(_pressure[i] > _dx * _dt)
+                               _pressure[i] = _dx * _dt;
+                       else if(_pressure[i] < -_dx * _dt)
+                               _pressure[i] = -_dx * _dt;
+
+                       // if(_obstacle[i] && _pressure[i] != 0.0)
+                       //      printf("BAD PRESSURE i\n");
+
+                       // if(_pressure[i]>1)
+                       //      printf("index: %d\n", i);
+               }
+               // printf("Max pressure: %f, dx: %f\n", maxvalue, _dx);
+       }
+
        setObstaclePressure(_pressure, 0, _zRes);
 
        // project out solution
@@ -848,12 +966,74 @@ void FLUID_3D::project()
                                }
                        }
 
+       setObstacleVelocity(0, _zRes);
+
        if (_pressure) delete[] _pressure;
        if (_divergence) delete[] _divergence;
 }
 
+//////////////////////////////////////////////////////////////////////
+// calculate the obstacle velocity at boundary
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setObstacleVelocity(int zBegin, int zEnd)
+{
+       
+       // completely TODO <-- who wrote this and what is here TODO? DG
 
+       const size_t index_ = _slabSize + _xRes + 1;
+
+       //int vIndex=_slabSize + _xRes + 1;
+
+       int bb=0;
+       int bt=0;
+
+       if (zBegin == 0) {bb = 1;}
+       if (zEnd == _zRes) {bt = 1;}
 
+       // tag remaining obstacle blocks
+       for (int z = zBegin + bb; z < zEnd - bt; z++)
+       {
+               size_t index = index_ +(z-1)*_slabSize;
+
+               for (int y = 1; y < _yRes - 1; y++, index += 2)
+               {
+                       for (int x = 1; x < _xRes - 1; x++, index++)
+               {
+                       if (!_obstacles[index])
+                       {
+                               // if(_obstacles[index+1]) xright = - _xVelocityOb[index]; 
+                               if((_obstacles[index - 1] & 8) && abs(_xVelocityOb[index - 1]) > FLT_EPSILON )
+                               {
+                                       // printf("velocity x!\n");
+                                       _xVelocity[index]  = _xVelocityOb[index - 1];
+                                       _xVelocity[index - 1]  = _xVelocityOb[index - 1];
+                               }
+                               // if(_obstacles[index+_xRes]) yup    = - _yVelocityOb[index];
+                               if((_obstacles[index - _xRes] & 8) && abs(_yVelocityOb[index - _xRes]) > FLT_EPSILON)
+                               {
+                                       // printf("velocity y!\n");
+                                       _yVelocity[index]  = _yVelocityOb[index - _xRes];
+                                       _yVelocity[index - _xRes]  = _yVelocityOb[index - _xRes];
+                               }
+                               // if(_obstacles[index+_slabSize]) ztop    = - _zVelocityOb[index];
+                               if((_obstacles[index - _slabSize] & 8) && abs(_zVelocityOb[index - _slabSize]) > FLT_EPSILON)
+                               {
+                                       // printf("velocity z!\n");
+                                       _zVelocity[index] = _zVelocityOb[index - _slabSize];
+                                       _zVelocity[index - _slabSize] = _zVelocityOb[index - _slabSize];
+                               }
+                       }
+                       else
+                       {
+                               _density[index] = 0;
+                       }
+                       //vIndex++;
+               }       // x loop
+               //vIndex += 2;
+               }       // y loop
+               //vIndex += 2 * _xRes;
+       }       // z loop
+}
 
 //////////////////////////////////////////////////////////////////////
 // diffuse heat
@@ -892,7 +1072,7 @@ void FLUID_3D::addObstacle(OBSTACLE* obstacle)
 void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
 {
 
-       // compleately TODO
+       // completely TODO <-- who wrote this and what is here TODO? DG
 
        const size_t index_ = _slabSize + _xRes + 1;
 
@@ -914,7 +1094,7 @@ void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
                        for (int x = 1; x < _xRes - 1; x++, index++)
                {
                        // could do cascade of ifs, but they are a pain
-                       if (_obstacles[index])
+                       if (_obstacles[index] /* && !(_obstacles[index] & 8) DG TODO TEST THIS CONDITION */)
                        {
                                const int top   = _obstacles[index + _slabSize];
                                const int bottom= _obstacles[index - _slabSize];
@@ -928,9 +1108,11 @@ void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
                                // const bool fully = (up && down);
                                //const bool fullx = (left && right);
 
+                               /*
                                _xVelocity[index] =
                                _yVelocity[index] =
                                _zVelocity[index] = 0.0f;
+                               */
                                _pressure[index] = 0.0f;
 
                                // average pressure neighbors
@@ -1253,7 +1435,35 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
 
        setZeroBorder(_density, res, zBegin, zEnd);
        setZeroBorder(_heat, res, zBegin, zEnd);
+#if 0
+       {
+       const size_t index_ = _slabSize + _xRes + 1;
+       int bb=0;
+       int bt=0;
+
+       if (zBegin == 0) {bb = 1;}
+       if (zEnd == _zRes) {bt = 1;}
+       
+       for (int z = zBegin + bb; z < zEnd - bt; z++)
+       {
+               size_t index = index_ +(z-1)*_slabSize;
 
+               for (int y = 1; y < _yRes - 1; y++, index += 2)
+               {
+                       for (int x = 1; x < _xRes - 1; x++, index++)
+                       {
+                               // clean custom velocities from moving obstacles again
+                               if (_obstacles[index])
+                               {
+                                       _xVelocity[index] =
+                                       _yVelocity[index] =
+                                       _zVelocity[index] = 0.0f;
+                               }
+                       }
+               }
+       }
+       }
+#endif
 
        /*int begin=zBegin * _slabSize;
        int end=begin + (zEnd - zBegin) * _slabSize;
index c9e18926fb2fa41541807a8ef227f0d15050cd5b..5704cba3ed4f73b3234429f4241379b70f4e3a21 100644 (file)
@@ -39,9 +39,6 @@
 // #include "WTURBULENCE.h"
 #include "VEC3.h"
 
-// timestep default value for nice appearance
-#define DT_DEFAULT 0.1f;
-
 using namespace std;
 using namespace BasicVector;
 class WTURBULENCE;
@@ -49,7 +46,7 @@ class WTURBULENCE;
 class FLUID_3D  
 {
        public:
-               FLUID_3D(int *res, /* int amplify, */ float *p0);
+               FLUID_3D(int *res, /* int amplify, */ float *p0, float dtdef);
                FLUID_3D() {};
                virtual ~FLUID_3D();
 
@@ -72,7 +69,7 @@ class FLUID_3D
                int yRes() const { return _yRes; };
                int zRes() const { return _zRes; };
 
-       public:  
+       public:
                // dimensions
                int _xRes, _yRes, _zRes, _maxRes;
                Vec3Int _res;
@@ -89,6 +86,8 @@ class FLUID_3D
                void artificialDampingSL(int zBegin, int zEnd);
                void artificialDampingExactSL(int pos);
 
+               void setBorderObstacles();
+
                // fields
                float* _density;
                float* _densityOld;
@@ -97,13 +96,17 @@ class FLUID_3D
                float* _xVelocity;
                float* _yVelocity;
                float* _zVelocity;
+               float* _xVelocityOb;
+               float* _yVelocityOb;
+               float* _zVelocityOb;
                float* _xVelocityOld;
                float* _yVelocityOld;
                float* _zVelocityOld;
                float* _xForce;
                float* _yForce;
                float* _zForce;
-               unsigned char*  _obstacles;
+               unsigned char*  _obstacles; /* only used (usefull) for static obstacles like domain boundaries */
+               unsigned char*  _obstaclesAnim;
 
                // Required for proper threading:
                float* _xVelocityTemp;
@@ -137,6 +140,8 @@ class FLUID_3D
                                                        // have to recalibrate borders if nothing has changed
                void setBorderCollisions();
 
+               void setObstacleVelocity(int zBegin, int zEnd);
+
                // WTURBULENCE object, if active
                // WTURBULENCE* _wTurbulence;
 
index 61d47b727f0982cdb2e6f6281ad2dcd87f107489..da8ec6be024540c6cffb8d70a7f8389e8be0d70a 100644 (file)
 #define OBSTACLE_H
 
 enum OBSTACLE_FLAGS {
-       EMPTY = 0, 
+       EMPTY = 0,
+       /* 1 is used to flag an object cell */
        MARCHED = 2, 
-       RETIRED = 4 
+       RETIRED = 4,
+       ANIMATED = 8,
 };  
 
 class OBSTACLE  
index cd18cf7b34441f53d7f8378b940c82a65862ed0a..83bec466c9f9b4673480c73900e127d6df35a8e0 100644 (file)
@@ -431,8 +431,11 @@ void WTURBULENCE::decomposeEnergy(float *_energy, float *_highFreqEnergy)
 // compute velocity from energies and march into obstacles
 // for wavelet decomposition
 ////////////////////////////////////////////////////////////////////// 
-void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float* zvel, unsigned char *obstacles) 
+void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float* zvel, unsigned char *origObstacles) 
 {
+  unsigned char *obstacles = new unsigned char[_totalCellsSm];
+  memcpy(obstacles, origObstacles, sizeof(unsigned char) * _totalCellsSm);
+
   // compute everywhere
   for (int x = 0; x < _totalCellsSm; x++) 
     _energy[x] = 0.5f * (xvel[x] * xvel[x] + yvel[x] * yvel[x] + zvel[x] * zvel[x]);
@@ -506,7 +509,9 @@ void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float*
     for (int y = 1; y < _yResSm - 1; y++, index += 2)
       for (int x = 1; x < _xResSm - 1; x++, index++)
         if (obstacles[index])
-          obstacles[index] = 1;
+          obstacles[index] = 1; // DG TODO ? animated obstacle flag?
+
+  free(obstacles);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
index a2f3c21bbbf3d2339c492287a31ec1c3e5570af8..78f7d35360a391ac7f3fec5c5750e4c17ff7b0fe 100644 (file)
@@ -19,6 +19,7 @@
  * All rights reserved.
  *
  * Contributor(s): Daniel Genrich
+ *                 Blender Foundation
  *
  * ***** END GPL LICENSE BLOCK *****
  */
 #include <math.h>
 
 // y in smoke is z in blender
-extern "C" FLUID_3D *smoke_init(int *res, float *p0)
+extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef)
 {
        // smoke lib uses y as top-bottom/vertical axis where blender uses z
-       FLUID_3D *fluid = new FLUID_3D(res, p0);
+       FLUID_3D *fluid = new FLUID_3D(res, p0, dtdef);
 
        // printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
 
@@ -78,41 +79,9 @@ extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z
        return x + y * max_x;
 }
 
-extern "C" void smoke_step(FLUID_3D *fluid, size_t framenr, float fps)
+extern "C" void smoke_step(FLUID_3D *fluid, float dtSubdiv)
 {
-       /* stability values copied from wturbulence.cpp */
-       const int maxSubSteps = 25;
-       const float maxVel = 0.5f; /* TODO: maybe 0.5 is still too high, please confirm! -dg */
-
-       float dt = DT_DEFAULT;
-       float maxVelMag = 0.0f;
-       int totalSubsteps;
-       int substep = 0;
-       float dtSubdiv;
-
-       /* get max velocity and lower the dt value if it is too high */
-       size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
-
-       for(size_t i = 0; i < size; i++)
-       {
-               float vtemp = (fluid->_xVelocity[i]*fluid->_xVelocity[i]+fluid->_yVelocity[i]*fluid->_yVelocity[i]+fluid->_zVelocity[i]*fluid->_zVelocity[i]);
-               if(vtemp > maxVelMag)
-                       maxVelMag = vtemp;
-       }
-
-       /* adapt timestep for different framerates, dt = 0.1 is at 25fps */
-       dt *= (25.0f / fps);
-
-       maxVelMag = sqrt(maxVelMag) * dt * (*(fluid->_dtFactor));
-       totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */
-       totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
-       totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
-       dtSubdiv = (float)dt / (float)totalSubsteps;
-
-       // printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
-
-       for(substep = 0; substep < totalSubsteps; substep++)
-               fluid->step(dtSubdiv);
+       fluid->step(dtSubdiv);
 }
 
 extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
@@ -307,6 +276,18 @@ extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
        return fluid->_obstacles;
 }
 
+extern "C" void smoke_get_ob_velocity(struct FLUID_3D *fluid, float **x, float **y, float **z)
+{
+       *x = fluid->_xVelocityOb;
+       *y = fluid->_yVelocityOb;
+       *z = fluid->_zVelocityOb;
+}
+
+extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid)
+{
+       return fluid->_obstaclesAnim;
+}
+
 extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
 {
        wt->setNoise(type);
index 9f760f2f0243c5cd1afa71ed457f2bcd81b25ae4..d3ab616a793c771fc0e7aca6b974a3a09a221755 100644 (file)
@@ -100,6 +100,15 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
             sub.prop(flow, "use_absolute")
             sub.prop(flow, "density")
             sub.prop(flow, "temperature")
+            
+        elif md.smoke_type == 'COLLISION':
+            coll = md.coll_settings
+
+            split = layout.split()
+
+            col = split.column()
+            col.prop(coll, "collision_type")
+        
 
 
 class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
index 9d13397859d87c84e5d11c8c8d0df41d8d668a1f..f3939a2ebfc1ba2be0036158bb8929d66432b56f 100644 (file)
@@ -21,6 +21,7 @@
  * The Original Code is: all of this file.
  *
  * Contributor(s): Daniel Genrich
+ *                 Blender Foundation
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -53,6 +54,7 @@
 
 #include "BKE_bvhutils.h"
 #include "BKE_cdderivedmesh.h"
+#include "BKE_collision.h"
 #include "BKE_customdata.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_effect.h"
@@ -118,7 +120,6 @@ static void tend ( void )
        gettimeofday ( &_tend,&tz );
 }
 
-#if 0 // unused
 static double tval()
 {
        double t1, t2;
@@ -127,14 +128,16 @@ static double tval()
        return t2-t1;
 }
 #endif
-#endif
 
 struct Object;
 struct Scene;
 struct DerivedMesh;
 struct SmokeModifierData;
 
-#define TRI_UVOFFSET (1.0 / 4.0)
+#define TRI_UVOFFSET (1./4.)
+
+// timestep default value for nice appearance 0.1f
+#define DT_DEFAULT 0.1f
 
 /* forward declerations */
 static void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *tris, int numfaces, int numtris, int **tridivs, float cell_len);
@@ -159,7 +162,7 @@ void smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Obje
 
 static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm)
 {
-       if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
+       if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
        {
                size_t i;
                float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
@@ -171,7 +174,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
                res = smd->domain->maxres;
 
                // get BB of domain
-               for (i = 0; i < dm->getNumVerts(dm); i++)
+               for(i = 0; i < dm->getNumVerts(dm); i++)
                {
                        float tmp[3];
 
@@ -198,32 +201,32 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
                // printf("size: %f, %f, %f\n", size[0], size[1], size[2]);
 
                // prevent crash when initializing a plane as domain
-               if ((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
+               if((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
                        return 0;
 
-               if (size[0] > size[1])
+               if(size[0] > size[1])
                {
-                       if (size[0] > size[2])
+                       if(size[0] > size[2])
                        {
                                scale = res / size[0];
-                               smd->domain->dx = size[0] / res;
+                               smd->domain->dx = size[0] / res; // dx is in global coords
                                smd->domain->res[0] = res;
                                smd->domain->res[1] = (int)(size[1] * scale + 0.5);
                                smd->domain->res[2] = (int)(size[2] * scale + 0.5);
                        }
                        else {
                                scale = res / size[2];
-                               smd->domain->dx = size[2] / res;
+                               smd->domain->dx = size[2] / res; // dx is in global coords
                                smd->domain->res[2] = res;
                                smd->domain->res[0] = (int)(size[0] * scale + 0.5);
                                smd->domain->res[1] = (int)(size[1] * scale + 0.5);
                        }
                }
                else {
-                       if (size[1] > size[2])
+                       if(size[1] > size[2])
                        {
                                scale = res / size[1];
-                               smd->domain->dx = size[1] / res;
+                               smd->domain->dx = size[1] / res; // dx is in global coords
                                smd->domain->res[1] = res;
                                smd->domain->res[0] = (int)(size[0] * scale + 0.5);
                                smd->domain->res[2] = (int)(size[2] * scale + 0.5);
@@ -243,10 +246,10 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
 
                // 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->p0);
+               smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, DT_DEFAULT);
                smd->time = scene->r.cfra;
 
-               if (smd->domain->flags & MOD_SMOKE_HIGHRES)
+               if(smd->domain->flags & MOD_SMOKE_HIGHRES)
                {
                        smd->domain->wt = smoke_turbulence_init(smd->domain->res, smd->domain->amplify + 1, smd->domain->noise);
                        smd->domain->res_wt[0] = smd->domain->res[0] * (smd->domain->amplify + 1);
@@ -257,19 +260,19 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
                        // printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n");
                }
 
-               if (!smd->domain->shadow)
+               if(!smd->domain->shadow)
                        smd->domain->shadow = MEM_callocN(sizeof(float) * smd->domain->res[0] * smd->domain->res[1] * smd->domain->res[2], "SmokeDomainShadow");
 
                smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta), &(smd->domain->time_scale), &(smd->domain->vorticity), &(smd->domain->border_collisions));
 
-               if (smd->domain->wt)    
+               if(smd->domain->wt)     
                {
                        smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength));
                        // printf("smoke_initWaveletBlenderRNA\n");
                }
                return 1;
        }
-       else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
+       else if((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
        {
                // handle flow object here
                // XXX TODO
@@ -288,7 +291,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
                }
 
 /*
-               if (!smd->flow->bvh)
+               if(!smd->flow->bvh)
                {
                        // smd->flow->bvh = MEM_callocN(sizeof(BVHTreeFromMesh), "smoke_bvhfromfaces");
                        // bvhtree_from_mesh_faces(smd->flow->bvh, dm, 0.0, 2, 6);
@@ -301,28 +304,33 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
 
                return 1;
        }
-       else if ((smd->type & MOD_SMOKE_TYPE_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)
+
+               if(!smd->coll)
+               {
                        smokeModifier_createType(smd);
+               }
 
-               if (!smd->coll->points)
+               if(!smd->coll->points)
                {
                        // init collision points
                        SmokeCollSettings *scs = smd->coll;
 
+                       smd->time = scene->r.cfra;
+
                        // copy obmat
                        copy_m4_m4(scs->mat, ob->obmat);
                        copy_m4_m4(scs->mat_old, ob->obmat);
 
                        DM_ensure_tessface(dm);
                        fill_scs_points(ob, dm, scs);
+
+                       // DEBUG printf("scs->dx: %f\n", scs->dx);
                }
 
-               if (!smd->coll->bvhtree)
+               if(!smd->coll->bvhtree)
                {
                        smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
                }
@@ -337,50 +345,52 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
        MVert *mvert = dm->getVertArray(dm);
        MFace *mface = dm->getTessFaceArray(dm);
        int i = 0, divs = 0;
-       int *tridivs = NULL;
-       float cell_len = 1.0 / 50.0; // for res = 50
+
+       // DG TODO: need to do this dynamically according to the domain object!
+       float cell_len = scs->dx;
        int newdivs = 0;
        int quads = 0, facecounter = 0;
 
        // count quads
-       for (i = 0; i < dm->getNumTessFaces(dm); i++)
+       for(i = 0; i < dm->getNumTessFaces(dm); i++)
        {
-               if (mface[i].v4)
+               if(mface[i].v4)
                        quads++;
        }
 
-       calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface,  dm->getNumTessFaces(dm), dm->getNumTessFaces(dm) + quads, &tridivs, cell_len);
+       scs->numtris = dm->getNumTessFaces(dm) + quads;
+       scs->tridivs = NULL;
+       calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface,  dm->getNumTessFaces(dm), scs->numtris, &(scs->tridivs), cell_len);
 
        // count triangle divisions
-       for (i = 0; i < dm->getNumTessFaces(dm) + quads; i++)
+       for(i = 0; i < dm->getNumTessFaces(dm) + quads; i++)
        {
-               divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1);
+               divs += (scs->tridivs[3 * i] + 1) * (scs->tridivs[3 * i + 1] + 1) * (scs->tridivs[3 * i + 2] + 1);
        }
 
-       // printf("divs: %d\n", divs);
-
        scs->points = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPoints");
+       scs->points_old = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPointsOld");
 
-       for (i = 0; i < dm->getNumVerts(dm); i++)
+       for(i = 0; i < dm->getNumVerts(dm); i++)
        {
                float tmpvec[3];
                copy_v3_v3(tmpvec, mvert[i].co);
-               mul_m4_v3(ob->obmat, tmpvec);
+               // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
                copy_v3_v3(&scs->points[i * 3], tmpvec);
        }
        
-       for (i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
+       for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
        {
                int again = 0;
                do
                {
                        int j, k;
-                       int divs1 = tridivs[3 * facecounter + 0];
-                       int divs2 = tridivs[3 * facecounter + 1];
-                       //int divs3 = tridivs[3 * facecounter + 2];
+                       int divs1 = scs->tridivs[3 * facecounter + 0];
+                       int divs2 = scs->tridivs[3 * facecounter + 1];
+                       //int divs3 = scs->tridivs[3 * facecounter + 2];
                        float side1[3], side2[3], trinormorg[3], trinorm[3];
                        
-                       if (again == 1 && mface[i].v4)
+                       if(again == 1 && mface[i].v4)
                        {
                                sub_v3_v3v3(side1,  mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co);
                                sub_v3_v3v3(side2,  mvert[ mface[i].v4 ].co, mvert[ mface[i].v1 ].co);
@@ -395,23 +405,23 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
                        copy_v3_v3(trinorm, trinormorg);
                        mul_v3_fl(trinorm, 0.25 * cell_len);
 
-                       for (j = 0; j <= divs1; j++)
+                       for(j = 0; j <= divs1; j++)
                        {
-                               for (k = 0; k <= divs2; k++)
+                               for(k = 0; k <= divs2; k++)
                                {
                                        float p1[3], p2[3], p3[3], p[3]={0,0,0}; 
                                        const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0);
                                        const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0);
                                        float tmpvec[3];
                                        
-                                       if (uf+vf > 1.0) 
+                                       if(uf+vf > 1.0) 
                                        {
                                                // printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
                                                continue;
                                        }
 
                                        copy_v3_v3(p1, mvert[ mface[i].v1 ].co);
-                                       if (again == 1 && mface[i].v4)
+                                       if(again == 1 && mface[i].v4)
                                        {
                                                copy_v3_v3(p2, mvert[ mface[i].v3 ].co);
                                                copy_v3_v3(p3, mvert[ mface[i].v4 ].co);
@@ -428,40 +438,211 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
                                        add_v3_v3v3(p, p1, p2);
                                        add_v3_v3(p, p3);
 
-                                       if (newdivs > divs)
+                                       if(newdivs > divs)
                                                printf("mem problem\n");
 
                                        // mMovPoints.push_back(p + trinorm);
                                        add_v3_v3v3(tmpvec, p, trinorm);
-                                       mul_m4_v3(ob->obmat, tmpvec);
+                                       // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
                                        copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
                                        newdivs++;
 
-                                       if (newdivs > divs)
+                                       if(newdivs > divs)
                                                printf("mem problem\n");
 
                                        // mMovPoints.push_back(p - trinorm);
                                        copy_v3_v3(tmpvec, p);
                                        sub_v3_v3(tmpvec, trinorm);
-                                       mul_m4_v3(ob->obmat, tmpvec);
+                                       // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
                                        copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
                                        newdivs++;
                                }
                        }
 
-                       if (again == 0 && mface[i].v4)
+                       if(again == 0 && mface[i].v4)
                                again++;
                        else
                                again = 0;
 
                        facecounter++;
 
-               } while (again!=0);
+               } while(again!=0);
        }
 
+       scs->numverts = dm->getNumVerts(dm);
+       // DG TODO: also save triangle count?
+
        scs->numpoints = dm->getNumVerts(dm) + newdivs;
 
-       MEM_freeN(tridivs);
+       for(i = 0; i < scs->numpoints * 3; i++)
+       {
+               scs->points_old[i] = scs->points[i];
+       }
+}
+
+
+static void fill_scs_points_anim(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
+{
+       MVert *mvert = dm->getVertArray(dm);
+       MFace *mface = dm->getTessFaceArray(dm);
+       int quads = 0, numtris = 0, facecounter = 0;
+       unsigned int i = 0;
+       int divs = 0, newdivs = 0;
+       
+       // DG TODO: need to do this dynamically according to the domain object!
+       float cell_len = scs->dx;
+
+       // count quads
+       for(i = 0; i < dm->getNumTessFaces(dm); i++)
+       {
+               if(mface[i].v4)
+                       quads++;
+       }
+
+       numtris = dm->getNumTessFaces(dm) + quads;
+
+       // check if mesh changed topology
+       if(scs->numtris != numtris)
+               return;
+       if(scs->numverts != dm->getNumVerts(dm))
+               return;
+
+       // update new positions
+       for(i = 0; i < dm->getNumVerts(dm); i++)
+       {
+               float tmpvec[3];
+               copy_v3_v3(tmpvec, mvert[i].co);
+               copy_v3_v3(&scs->points[i * 3], tmpvec);
+       }
+
+       // for every triangle // update div points
+       for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
+       {
+               int again = 0;
+               do
+               {
+                       int j, k;
+                       int divs1 = scs->tridivs[3 * facecounter + 0];
+                       int divs2 = scs->tridivs[3 * facecounter + 1];
+                       float srcside1[3], srcside2[3], destside1[3], destside2[3], src_trinormorg[3], dest_trinormorg[3], src_trinorm[3], dest_trinorm[3];
+                       
+                       if(again == 1 && mface[i].v4)
+                       {
+                               sub_v3_v3v3(srcside1,  &scs->points_old[mface[i].v3 * 3], &scs->points_old[mface[i].v1 * 3]);
+                               sub_v3_v3v3(destside1,  &scs->points[mface[i].v3 * 3], &scs->points[mface[i].v1 * 3]);
+
+                               sub_v3_v3v3(srcside2,  &scs->points_old[mface[i].v4 * 3], &scs->points_old[mface[i].v1 * 3]);
+                               sub_v3_v3v3(destside2,  &scs->points[mface[i].v4 * 3], &scs->points[mface[i].v1 * 3]);
+                       }
+                       else {
+                               sub_v3_v3v3(srcside1,  &scs->points_old[mface[i].v2 * 3], &scs->points_old[mface[i].v1 * 3]);
+                               sub_v3_v3v3(destside1,  &scs->points[mface[i].v2 * 3], &scs->points[mface[i].v1 * 3]);
+
+                               sub_v3_v3v3(srcside2,  &scs->points_old[mface[i].v3 * 3], &scs->points_old[mface[i].v1 * 3]);
+                               sub_v3_v3v3(destside2,  &scs->points[mface[i].v3 * 3], &scs->points[mface[i].v1 * 3]);
+                       }
+
+                       cross_v3_v3v3(src_trinormorg, srcside1, srcside2);
+                       cross_v3_v3v3(dest_trinormorg, destside1, destside2);
+
+                       normalize_v3(src_trinormorg);
+                       normalize_v3(dest_trinormorg);
+
+                       copy_v3_v3(src_trinorm, src_trinormorg);
+                       copy_v3_v3(dest_trinorm, dest_trinormorg);
+
+                       mul_v3_fl(src_trinorm, 0.25 * cell_len);
+                       mul_v3_fl(dest_trinorm, 0.25 * cell_len);
+
+                       for(j = 0; j <= divs1; j++)
+                       {
+                               for(k = 0; k <= divs2; k++)
+                               {
+                                       float src_p1[3], src_p2[3], src_p3[3], src_p[3]={0,0,0};
+                                       float dest_p1[3], dest_p2[3], dest_p3[3], dest_p[3]={0,0,0};
+                                       const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0);
+                                       const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0);
+                                       float src_tmpvec[3], dest_tmpvec[3];
+                                       
+                                       if(uf+vf > 1.0) 
+                                       {
+                                               // printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
+                                               continue;
+                                       }
+
+                                       copy_v3_v3(src_p1, &scs->points_old[mface[i].v1 * 3]);
+                                       copy_v3_v3(dest_p1, &scs->points[mface[i].v1 * 3]);
+                                       if(again == 1 && mface[i].v4)
+                                       {
+                                               copy_v3_v3(src_p2, &scs->points_old[mface[i].v3 * 3]);
+                                               copy_v3_v3(dest_p2, &scs->points[mface[i].v3 * 3]);
+
+                                               copy_v3_v3(src_p3,&scs->points_old[mface[i].v4 * 3]);
+                                               copy_v3_v3(dest_p3, &scs->points[mface[i].v4 * 3]);
+                                       }
+                                       else {
+                                               copy_v3_v3(src_p2, &scs->points_old[mface[i].v2 * 3]);
+                                               copy_v3_v3(dest_p2, &scs->points[mface[i].v2 * 3]);
+                                               copy_v3_v3(src_p3, &scs->points_old[mface[i].v3 * 3]);
+                                               copy_v3_v3(dest_p3, &scs->points[mface[i].v3 * 3]);
+                                       }
+
+                                       mul_v3_fl(src_p1, (1.0-uf-vf));
+                                       mul_v3_fl(dest_p1, (1.0-uf-vf));
+
+                                       mul_v3_fl(src_p2, uf);
+                                       mul_v3_fl(dest_p2, uf);
+
+                                       mul_v3_fl(src_p3, vf);
+                                       mul_v3_fl(dest_p3, vf);
+
+                                       add_v3_v3v3(src_p, src_p1, src_p2);
+                                       add_v3_v3v3(dest_p, dest_p1, dest_p2);
+
+                                       add_v3_v3(src_p, src_p3);
+                                       add_v3_v3(dest_p, dest_p3);
+
+                                       if(newdivs > divs)
+                                               printf("mem problem\n");
+
+                                       // mMovPoints.push_back(p + trinorm);
+                                       add_v3_v3v3(src_tmpvec, src_p, src_trinorm);
+                                       add_v3_v3v3(dest_tmpvec, dest_p, dest_trinorm);
+
+                                       // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
+                                       copy_v3_v3(&scs->points_old[3 * (dm->getNumVerts(dm) + newdivs)], src_tmpvec);
+                                       copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], dest_tmpvec);
+                                       newdivs++;
+
+                                       if(newdivs > divs)
+                                               printf("mem problem\n");
+
+                                       // mMovPoints.push_back(p - trinorm);
+                                       copy_v3_v3(src_tmpvec, src_p);
+                                       copy_v3_v3(dest_tmpvec, dest_p);
+
+                                       sub_v3_v3(src_tmpvec, src_trinorm);
+                                       sub_v3_v3(dest_tmpvec, dest_trinorm);
+
+                                       // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
+                                       copy_v3_v3(&scs->points_old[3 * (dm->getNumVerts(dm) + newdivs)], src_tmpvec);
+                                       copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], dest_tmpvec);
+                                       newdivs++;
+                               }
+                       }
+
+                       if(again == 0 && mface[i].v4)
+                               again++;
+                       else
+                               again = 0;
+
+                       facecounter++;
+
+               } while(again!=0);
+       }
+
+       // scs->numpoints = dm->getNumVerts(dm) + newdivs;
+
 }
 
 /*! init triangle divisions */
@@ -472,22 +653,22 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
        // mTriangleDivs3.resize( faces.size() );
 
        size_t i = 0, facecounter = 0;
-       float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale);
+       float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale); get max scale value
        float maxpart = ABS(maxscale[0]);
        float scaleFac = 0;
        float fsTri = 0;
-       if (ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
-       if (ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
+       if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
+       if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
        scaleFac = 1.0 / maxpart;
        // featureSize = mLevel[mMaxRefine].nodeSize
-       fsTri = cell_len * 0.5 * scaleFac;
+       fsTri = cell_len * 0.75 * scaleFac; // fsTri = cell_len * 0.9;
 
-       if (*tridivs)
+       if(*tridivs)
                MEM_freeN(*tridivs);
 
        *tridivs = MEM_callocN(sizeof(int) * numtris * 3, "Smoke_Tridivs");
 
-       for (i = 0, facecounter = 0; i < numfaces; i++) 
+       for(i = 0, facecounter = 0; i < numfaces; i++) 
        {
                float p0[3], p1[3], p2[3];
                float side1[3];
@@ -506,21 +687,22 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
                sub_v3_v3v3(side2, p2, p0);
                sub_v3_v3v3(side3, p1, p2);
 
-               if (dot_v3v3(side1, side1) > fsTri*fsTri)
+               if(dot_v3v3(side1, side1) > fsTri*fsTri)
                { 
                        float tmp = normalize_v3(side1);
                        divs1 = (int)ceil(tmp/fsTri); 
                }
-               if (dot_v3v3(side2, side2) > fsTri*fsTri)
+               if(dot_v3v3(side2, side2) > fsTri*fsTri)
                { 
                        float tmp = normalize_v3(side2);
                        divs2 = (int)ceil(tmp/fsTri); 
                        
-                       /*
+                       /*              
                        // debug
-                       if (i==0)
+                       if(i==0)
                                printf("b tmp: %f, fsTri: %f, divs2: %d\n", tmp, fsTri, divs2);
                        */
+                       
                }
 
                (*tridivs)[3 * facecounter + 0] = divs1;
@@ -528,7 +710,7 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
                (*tridivs)[3 * facecounter + 2] = divs3;
 
                // TODO quad case
-               if (faces[i].v4)
+               if(faces[i].v4)
                {
                        divs1=0, divs2=0, divs3=0;
 
@@ -545,12 +727,12 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
                        sub_v3_v3v3(side2, p2, p0);
                        sub_v3_v3v3(side3, p1, p2);
 
-                       if (dot_v3v3(side1, side1) > fsTri*fsTri)
+                       if(dot_v3v3(side1, side1) > fsTri*fsTri)
                        { 
                                float tmp = normalize_v3(side1);
                                divs1 = (int)ceil(tmp/fsTri); 
                        }
-                       if (dot_v3v3(side2, side2) > fsTri*fsTri)
+                       if(dot_v3v3(side2, side2) > fsTri*fsTri)
                        { 
                                float tmp = normalize_v3(side2);
                                divs2 = (int)ceil(tmp/fsTri); 
@@ -568,19 +750,19 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
 
 static void smokeModifier_freeDomain(SmokeModifierData *smd)
 {
-       if (smd->domain)
+       if(smd->domain)
        {
-               if (smd->domain->shadow)
+               if(smd->domain->shadow)
                                MEM_freeN(smd->domain->shadow);
                        smd->domain->shadow = NULL;
 
-               if (smd->domain->fluid)
+               if(smd->domain->fluid)
                        smoke_free(smd->domain->fluid);
 
-               if (smd->domain->wt)
+               if(smd->domain->wt)
                        smoke_turbulence_free(smd->domain->wt);
 
-               if (smd->domain->effector_weights)
+               if(smd->domain->effector_weights)
                                MEM_freeN(smd->domain->effector_weights);
                smd->domain->effector_weights = NULL;
 
@@ -594,10 +776,10 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd)
 
 static void smokeModifier_freeFlow(SmokeModifierData *smd)
 {
-       if (smd->flow)
+       if(smd->flow)
        {
 /*
-               if (smd->flow->bvh)
+               if(smd->flow->bvh)
                {
                        free_bvhtree_from_mesh(smd->flow->bvh);
                        MEM_freeN(smd->flow->bvh);
@@ -611,22 +793,37 @@ static void smokeModifier_freeFlow(SmokeModifierData *smd)
 
 static void smokeModifier_freeCollision(SmokeModifierData *smd)
 {
-       if (smd->coll)
+       if(smd->coll)
        {
-               if (smd->coll->points)
+               SmokeCollSettings *scs = smd->coll;
+
+               if(scs->numpoints)
                {
-                       MEM_freeN(smd->coll->points);
-                       smd->coll->points = NULL;
+                       if(scs->points)
+                       {
+                               MEM_freeN(scs->points);
+                               scs->points = NULL;
+                       }
+                       if(scs->points_old)
+                       {
+                               MEM_freeN(scs->points_old);
+                               scs->points_old = NULL;
+                       }
+                       if(scs->tridivs)
+                       {
+                               MEM_freeN(scs->tridivs);
+                               scs->tridivs = NULL;
+                       }
                }
 
-               if (smd->coll->bvhtree)
+               if(scs->bvhtree)
                {
-                       BLI_bvhtree_free(smd->coll->bvhtree);
-                       smd->coll->bvhtree = NULL;
+                       BLI_bvhtree_free(scs->bvhtree);
+                       scs->bvhtree = NULL;
                }
 
 #ifdef USE_SMOKE_COLLISION_DM
-               if (smd->coll->dm)
+               if(smd->coll->dm)
                        smd->coll->dm->release(smd->coll->dm);
                smd->coll->dm = NULL;
 #endif
@@ -638,7 +835,7 @@ static void smokeModifier_freeCollision(SmokeModifierData *smd)
 
 void smokeModifier_reset_turbulence(struct SmokeModifierData *smd)
 {
-       if (smd && smd->domain && smd->domain->wt)
+       if(smd && smd->domain && smd->domain->wt)
        {
                smoke_turbulence_free(smd->domain->wt);
                smd->domain->wt = NULL;
@@ -647,15 +844,15 @@ void smokeModifier_reset_turbulence(struct SmokeModifierData *smd)
 
 void smokeModifier_reset(struct SmokeModifierData *smd)
 {
-       if (smd)
+       if(smd)
        {
-               if (smd->domain)
+               if(smd->domain)
                {
-                       if (smd->domain->shadow)
+                       if(smd->domain->shadow)
                                MEM_freeN(smd->domain->shadow);
                        smd->domain->shadow = NULL;
 
-                       if (smd->domain->fluid)
+                       if(smd->domain->fluid)
                        {
                                smoke_free(smd->domain->fluid);
                                smd->domain->fluid = NULL;
@@ -667,10 +864,10 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
 
                        // printf("reset domain end\n");
                }
-               else if (smd->flow)
+               else if(smd->flow)
                {
                        /*
-                       if (smd->flow->bvh)
+                       if(smd->flow->bvh)
                        {
                                free_bvhtree_from_mesh(smd->flow->bvh);
                                MEM_freeN(smd->flow->bvh);
@@ -678,33 +875,33 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
                        smd->flow->bvh = NULL;
                        */
                }
-               else if (smd->coll)
+               else if(smd->coll)
                {
-                       if (smd->coll->points)
-                       {
-                               MEM_freeN(smd->coll->points);
-                               smd->coll->points = NULL;
-                       }
+                       SmokeCollSettings *scs = smd->coll;
 
-                       if (smd->coll->bvhtree)
+                       if(scs->numpoints && scs->points)
                        {
-                               BLI_bvhtree_free(smd->coll->bvhtree);
-                               smd->coll->bvhtree = NULL;
+                               MEM_freeN(scs->points);
+                               scs->points = NULL;
+                       
+                               if(scs->points_old)
+                               {
+                                       MEM_freeN(scs->points_old);
+                                       scs->points_old = NULL;
+                               }
+                               if(scs->tridivs)
+                               {
+                                       MEM_freeN(scs->tridivs);
+                                       scs->tridivs = NULL;
+                               }
                        }
-
-#ifdef USE_SMOKE_COLLISION_DM
-                       if (smd->coll->dm)
-                               smd->coll->dm->release(smd->coll->dm);
-                       smd->coll->dm = NULL;
-#endif
-
                }
        }
 }
 
 void smokeModifier_free (SmokeModifierData *smd)
 {
-       if (smd)
+       if(smd)
        {
                smokeModifier_freeDomain(smd);
                smokeModifier_freeFlow(smd);
@@ -714,11 +911,11 @@ void smokeModifier_free (SmokeModifierData *smd)
 
 void smokeModifier_createType(struct SmokeModifierData *smd)
 {
-       if (smd)
+       if(smd)
        {
-               if (smd->type & MOD_SMOKE_TYPE_DOMAIN)
+               if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
                {
-                       if (smd->domain)
+                       if(smd->domain)
                                smokeModifier_freeDomain(smd);
 
                        smd->domain = MEM_callocN(sizeof(SmokeDomainSettings), "SmokeDomain");
@@ -745,7 +942,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
                        smd->domain->beta = 0.1;
                        smd->domain->time_scale = 1.0;
                        smd->domain->vorticity = 2.0;
-                       smd->domain->border_collisions = 1;             // vertically non-colliding
+                       smd->domain->border_collisions = SM_BORDER_OPEN; // open domain
                        smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG | MOD_SMOKE_HIGH_SMOOTH;
                        smd->domain->strength = 2.0;
                        smd->domain->noise = MOD_SMOKE_NOISEWAVE;
@@ -755,9 +952,9 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
                        smd->domain->viewsettings = MOD_SMOKE_VIEW_SHOWBIG;
                        smd->domain->effector_weights = BKE_add_effector_weights(NULL);
                }
-               else if (smd->type & MOD_SMOKE_TYPE_FLOW)
+               else if(smd->type & MOD_SMOKE_TYPE_FLOW)
                {
-                       if (smd->flow)
+                       if(smd->flow)
                                smokeModifier_freeFlow(smd);
 
                        smd->flow = MEM_callocN(sizeof(SmokeFlowSettings), "SmokeFlow");
@@ -773,17 +970,23 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
                        smd->flow->psys = NULL;
 
                }
-               else if (smd->type & MOD_SMOKE_TYPE_COLL)
+               else if(smd->type & MOD_SMOKE_TYPE_COLL)
                {
-                       if (smd->coll)
+                       if(smd->coll)
                                smokeModifier_freeCollision(smd);
 
                        smd->coll = MEM_callocN(sizeof(SmokeCollSettings), "SmokeColl");
 
                        smd->coll->smd = smd;
                        smd->coll->points = NULL;
+                       smd->coll->points_old = NULL;
+                       smd->coll->tridivs = NULL;
+                       smd->coll->vel = NULL;
                        smd->coll->numpoints = 0;
+                       smd->coll->numtris = 0;
                        smd->coll->bvhtree = NULL;
+                       smd->coll->type = 0; // static obstacle
+                       smd->coll->dx = 1.0f / 50.0f;
 
 #ifdef USE_SMOKE_COLLISION_DM
                        smd->coll->dm = NULL;
@@ -818,7 +1021,7 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
                
                MEM_freeN(tsmd->domain->effector_weights);
                tsmd->domain->effector_weights = MEM_dupallocN(smd->domain->effector_weights);
-       }
+       } 
        else if (tsmd->flow) {
                tsmd->flow->density = smd->flow->density;
                tsmd->flow->temp = smd->flow->temp;
@@ -845,15 +1048,15 @@ static int get_lamp(Scene *scene, float *light)
        int found_lamp = 0;
 
        // try to find a lamp, preferably local
-       for (base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) {
-               if (base_tmp->object->type == OB_LAMP) {
+       for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) {
+               if(base_tmp->object->type == OB_LAMP) {
                        Lamp *la = base_tmp->object->data;
 
-                       if (la->type == LA_LOCAL) {
+                       if(la->type == LA_LOCAL) {
                                copy_v3_v3(light, base_tmp->object->obmat[3]);
                                return 1;
                        }
-                       else if (!found_lamp) {
+                       else if(!found_lamp) {
                                copy_v3_v3(light, base_tmp->object->obmat[3]);
                                found_lamp = 1;
                        }
@@ -865,497 +1068,603 @@ static int get_lamp(Scene *scene, float *light)
 
 static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
 {
+#if 0
        SmokeDomainSettings *sds = smd->domain;
        GroupObject *go = NULL;                 
-       Base *base = NULL;      
+       Base *base = NULL;
 
-       // do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells
-       if (1)
+       /* do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells */
+       if(1)
        {
-               Object *otherobj = NULL;
-               ModifierData *md = NULL;
+               unsigned int i;
+               Object **collobjs = NULL;
+               unsigned int numcollobj = 0;
+               collobjs = get_collisionobjects(scene, ob, sds->coll_group, &numcollobj);
 
-               if (sds->coll_group) // we use groups since we have 2 domains
-                       go = sds->coll_group->gobject.first;
-               else
-                       base = scene->base.first;
-
-               while (base || go)
+               for(i = 0; i < numcollobj; i++)
                {
-                       otherobj = NULL;
-                       if (sds->coll_group) 
-                       {                                               
-                               if (go->ob)                                                     
-                                       otherobj = go->ob;                                      
-                       }                                       
-                       else                                            
-                               otherobj = base->object;                                        
-                       if (!otherobj)                                  
-                       {                                               
-                               if (sds->coll_group)                                                    
-                                       go = go->next;                                          
-                               else                                                    
-                                       base= base->next;                                               
-                               continue;                                       
-                       }                       
-                       md = modifiers_findByType(otherobj, eModifierType_Smoke);
+                       Object *collob= collobjs[i];
+                       SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke);                
                        
                        // check for active smoke modifier
-                       if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))                                   
+                       // if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
+                       // SmokeModifierData *smd2 = (SmokeModifierData *)md;
+
+                       if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points && smd2->coll->points_old)
                        {
-                               SmokeModifierData *smd2 = (SmokeModifierData *)md;
+                               // ??? anything to do here?
+
+                               // TODO: only something to do for ANIMATED obstacles: need to update positions
+
+                       }
+               }
+
+               if(collobjs)
+                       MEM_freeN(collobjs);
+       }
+
+#endif
+}
 
-                               if ((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points)
+/* Animated obstacles: dx_step = ((x_new - x_old) / totalsteps) * substep */
+static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt, int substep, int totalsteps)
+{
+       Object **collobjs = NULL;
+       unsigned int numcollobj = 0;
+
+       unsigned int collIndex;
+       unsigned char *obstacles = smoke_get_obstacle(sds->fluid);
+       float *velx = NULL;
+       float *vely = NULL;
+       float *velz = NULL;
+       float *velxOrig = smoke_get_velocity_x(sds->fluid);
+       float *velyOrig = smoke_get_velocity_y(sds->fluid);
+       float *velzOrig = smoke_get_velocity_z(sds->fluid);
+       // float *density = smoke_get_density(sds->fluid);
+       unsigned int z;
+
+       smoke_get_ob_velocity(sds->fluid, &velx, &vely, &velz);
+
+       // TODO: delete old obstacle flags
+       for(z = 0; z < sds->res[0] * sds->res[1] * sds->res[2]; z++)
+       {
+               if(obstacles[z])
+               {
+                       // density[z] = 0;
+
+                       velxOrig[z] = 0;
+                       velyOrig[z] = 0;
+                       velzOrig[z] = 0;
+               }
+
+               if(obstacles[z] & 8) // Do not delete static obstacles
+               {
+                       obstacles[z] = 0;
+               }
+
+               velx[z] = 0;
+               vely[z] = 0;
+               velz[z] = 0;
+       }
+
+       collobjs = get_collisionobjects(scene, ob, sds->coll_group, &numcollobj, eModifierType_Smoke);
+
+       // update obstacle tags in cells
+       for(collIndex = 0; collIndex < numcollobj; collIndex++)
+       {
+               Object *collob= collobjs[collIndex];
+               SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke);
+
+               // DG TODO: check if modifier is active?
+               
+               if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points && smd2->coll->points_old)
+               {
+                       SmokeCollSettings *scs = smd2->coll;
+                       unsigned int i;
+
+                       /*
+                       // DG TODO: support static cobstacles, but basicly we could even support static + rigid with one set of code
+                       if(scs->type > SM_COLL_STATIC)
+                       */
+
+                       /* Handle collisions */
+                       for(i = 0; i < scs->numpoints; i++)
+                       {
+                               // 1. get corresponding cell
+                               int cell[3];
+                               float pos[3], oldpos[3], vel[3];
+                               float cPos[3], cOldpos[3]; /* current position in substeps */
+                               int badcell = 0;
+                               size_t index;
+                               int j;
+
+                               // translate local points into global positions
+                               copy_v3_v3(cPos, &scs->points[3 * i]);
+                               mul_m4_v3(scs->mat, cPos);
+                               copy_v3_v3(pos, cPos);
+
+                               copy_v3_v3(cOldpos, &scs->points_old[3 * i]);
+                               mul_m4_v3(scs->mat_old, cOldpos);
+                               copy_v3_v3(oldpos, cOldpos);
+
+                               /* support for rigid bodies, armatures etc */
                                {
-                                       // we got nice collision object
-                                       SmokeCollSettings *scs = smd2->coll;
-                                       size_t i, j;
-                                       unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid);
+                                       float tmp[3];
 
-                                       for (i = 0; i < scs->numpoints; i++)
-                                       {
-                                               int badcell = 0;
-                                               size_t index = 0;
-                                               int cell[3];
+                                       /* x_current = x_old + (x_new - x_old) * step_current / steps_total */
+                                       float mulStep = (float)(((float)substep) / ((float)totalsteps));
 
-                                               // 1. get corresponding cell
-                                               get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, &scs->points[3 * i], cell, 0);
-                                       
-                                               // 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))
-                                                       {
-                                                               badcell = 1;
-                                                               break;
-                                                       }
-                                                                                                                               
-                                                       if (badcell)                                                                    
-                                                               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]);
-                                                                                                               
-                                               // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]);                                                                
-                                               // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index);                                                                                                                                   
-                                               obstacles[index] = 1;
-                                               // for moving gobstacles                                                                
-                                               /*
-                                               const LbmFloat maxVelVal = 0.1666;
-                                               const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5;
-
-                                               LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); 
-                                               {                                                               
-                                               const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5;                                                                
-                                               USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz);                                                                 
-                                               if (usqr>maxusqr) {                                                                     
-                                               // cutoff at maxVelVal                                                                  
-                                               for (int jj=0; jj<3; jj++) {                                                                            
-                                               if (objvel[jj] > 0.0) objvel[jj] =  maxVelVal;
-                                               if (objvel[jj] < 0.0) objvel[jj] = -maxVelVal;
-                                               }                                                               
-                                               } 
-                                               }                                                               
-                                               const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) );                                                          
-                                               const LbmVec oldov=objvel; // debug                                                             
-                                               objvel = vec2L((*pNormals)[n]) *dp;                                                             
-                                               */
+                                       sub_v3_v3v3(tmp, cPos, cOldpos);
+                                       mul_v3_fl(tmp, mulStep);
+                                       add_v3_v3(cOldpos, tmp);
+                               }
+
+                               sub_v3_v3v3(vel, pos, oldpos);
+                               /* Scale velocity to incorperate the object movement during this step */
+                               mul_v3_fl(vel, 1.0 / (totalsteps * dt));
+                               // mul_v3_fl(vel, 1.0 / dt);
+
+                               // DG TODO: cap velocity to maxVelMag (or maxvel)
+
+                               // oldpos + velocity * dt = newpos
+                               get_cell(sds->p0, sds->res, sds->dx, cOldpos /* use current position here instead of "pos" */, cell, 0);
+
+                               // 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))
+                                       {
+                                               badcell = 1;
+                                               break;
                                        }
+                                                                                                               
+                               if(badcell)
+                                       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]);
+
+                               // Don't overwrite existing obstacles
+                               if(obstacles[index])
+                                       continue;
+                                                                                               
+                               // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]);                                                                
+                               // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index);                                                                                                                                   
+                               obstacles[index] = 1 | 8 /* ANIMATED */;
+
+                               if(len_v3(vel) > FLT_EPSILON)
+                               {
+                                       // Collision object is moving
+
+                                       velx[index] = vel[0]; // use "+="?
+                                       vely[index] = vel[1];
+                                       velz[index] = vel[2];
                                }
                        }
-
-                       if (sds->coll_group)
-                               go = go->next;
-                       else
-                               base= base->next;
                }
        }
 
-       // do flows and fluids
-       if (1)                  
+       if(collobjs)
+               MEM_freeN(collobjs);
+}
+
+static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float time)
+{
+       Object **flowobjs = NULL;
+       unsigned int numflowobj = 0;
+       unsigned int flowIndex;
+
+       flowobjs = get_collisionobjects(scene, ob, sds->fluid_group, &numflowobj, eModifierType_Smoke);
+
+       // update obstacle tags in cells
+       for(flowIndex = 0; flowIndex < numflowobj; flowIndex++)
        {
-               Object *otherobj = NULL;                                
-               ModifierData *md = NULL;
-               if (sds->fluid_group) // we use groups since we have 2 domains
-                       go = sds->fluid_group->gobject.first;                           
-               else                                    
-                       base = scene->base.first;
-               while (base || go)
-               {                                       
-                       otherobj = NULL;
-                       if (sds->fluid_group) 
-                       {
-                               if (go->ob)                                                     
-                                       otherobj = go->ob;                                      
-                       }                                       
-                       else                                            
-                               otherobj = base->object;
-                       if (!otherobj)
-                       {
-                               if (sds->fluid_group)
-                                       go = go->next;
-                               else
-                                       base= base->next;
+               Object *collob= flowobjs[flowIndex];
+               SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke);
 
-                               continue;
-                       }
+               // check for initialized smoke object
+               if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)                                            
+               {
+                       // we got nice flow object
+                       SmokeFlowSettings *sfs = smd2->flow;
 
-                       md = modifiers_findByType(otherobj, eModifierType_Smoke);
-                       
-                       // check for active smoke modifier
-                       if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
+                       if(sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected
                        {
-                               SmokeModifierData *smd2 = (SmokeModifierData *)md;
-                               
-                               // check for initialized smoke object
-                               if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)                                           
+                               ParticleSimulationData sim;
+                               ParticleSystem *psys = sfs->psys;
+                               int totpart=psys->totpart, totchild;
+                               int p = 0;                                                              
+                               float *density = smoke_get_density(sds->fluid);                                                         
+                               float *bigdensity = smoke_turbulence_get_density(sds->wt);                                                              
+                               float *heat = smoke_get_heat(sds->fluid);                                                               
+                               float *velocity_x = smoke_get_velocity_x(sds->fluid);                                                           
+                               float *velocity_y = smoke_get_velocity_y(sds->fluid);                                                           
+                               float *velocity_z = smoke_get_velocity_z(sds->fluid);                                                           
+                               unsigned char *obstacle = smoke_get_obstacle(sds->fluid);                                                       
+                               // DG TODO UNUSED unsigned char *obstacleAnim = smoke_get_obstacle_anim(sds->fluid);
+                               int bigres[3];
+                               short absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE);
+                               short high_emission_smoothing = bigdensity ? (sds->flags & MOD_SMOKE_HIGH_SMOOTH) : 0;
+
+                               /*
+                               * A temporary volume map used to store whole emissive
+                               * area to be added to smoke density and interpolated
+                               * for high resolution smoke.
+                               */
+                               float *temp_emission_map = NULL;
+
+                               sim.scene = scene;
+                               sim.ob = collob;
+                               sim.psys = psys;
+
+                               // initialize temp emission map
+                               if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
                                {
-                                       // we got nice flow object
-                                       SmokeFlowSettings *sfs = smd2->flow;
-                                       
-                                       if (sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected
+                                       int i;
+                                       temp_emission_map = MEM_callocN(sizeof(float) * sds->res[0]*sds->res[1]*sds->res[2], "SmokeTempEmission");
+                                       // set whole volume to 0.0f
+                                       for (i=0; i<sds->res[0]*sds->res[1]*sds->res[2]; i++) {
+                                               temp_emission_map[i] = 0.0f;
+                                       }
+                               }
+
+                               // mostly copied from particle code                                                             
+                               if(psys->part->type==PART_HAIR)
+                               {
+                                       /*
+                                       if(psys->childcache)
                                        {
-                                               ParticleSimulationData sim;
-                                               ParticleSystem *psys = sfs->psys;
-                                               int totpart=psys->totpart, totchild;
-                                               int p = 0;                                                              
-                                               float *density = smoke_get_density(sds->fluid);                                                         
-                                               float *bigdensity = smoke_turbulence_get_density(sds->wt);                                                              
-                                               float *heat = smoke_get_heat(sds->fluid);                                                               
-                                               float *velocity_x = smoke_get_velocity_x(sds->fluid);                                                           
-                                               float *velocity_y = smoke_get_velocity_y(sds->fluid);                                                           
-                                               float *velocity_z = smoke_get_velocity_z(sds->fluid);                                                           
-                                               unsigned char *obstacle = smoke_get_obstacle(sds->fluid);                                                               
-                                               int bigres[3];
-                                               short absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE);
-                                               short high_emission_smoothing = bigdensity ? (smd->domain->flags & MOD_SMOKE_HIGH_SMOOTH) : 0;
-
-                                               /*
-                                               * A temporary volume map used to store whole emissive
-                                               * area to be added to smoke density and interpolated
-                                               * for high resolution smoke.
-                                               */
-                                               float *temp_emission_map = NULL;
-
-                                               sim.scene = scene;
-                                               sim.ob = otherobj;
-                                               sim.psys = psys;
-
-                                               // initialize temp emission map
-                                               if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
+                                       totchild = psys->totchildcache;
+                                       }
+                                       else
+                                       */
+
+                                       // TODO: PART_HAIR not supported whatsoever
+                                       totchild=0;
+                               }
+                               else
+                                       totchild=psys->totchild*psys->part->disp/100;
+
+                               for(p=0; p<totpart+totchild; p++)                                                               
+                               {
+                                       int cell[3];
+                                       size_t i = 0;
+                                       size_t index = 0;
+                                       int badcell = 0;
+                                       ParticleKey state;
+
+                                       if(p < totpart)
+                                       {
+                                               if(psys->particles[p].flag & (PARS_NO_DISP|PARS_UNEXIST))
+                                                       continue;
+                                       }
+                                       else {
+                                               /* handle child particle */
+                                               ChildParticle *cpa = &psys->child[p - totpart];
+
+                                               if(psys->particles[cpa->parent].flag & (PARS_NO_DISP|PARS_UNEXIST))
+                                                       continue;
+                                       }
+
+                                       state.time = time;
+                                       if(psys_get_particle_state(&sim, p, &state, 0) == 0)
+                                               continue;
+
+                                       // copy_v3_v3(pos, pa->state.co);
+                                       // mul_m4_v3(ob->imat, pos);
+                                       // 1. get corresponding cell
+                                       get_cell(sds->p0, sds->res, sds->dx, state.co, cell, 0);                                                                                                                                        
+                                       // 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))                                                                                
+                                               {                                                                                       
+                                                       badcell = 1;                                                                                    
+                                                       break;                                                                          
+                                               }                                                                       
+                                       }                                                                                                                                                       
+                                       if(badcell)                                                                             
+                                               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]);                                                                                                                                           
+                                       if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // this is inflow
+                                       {                                                                               
+                                               // heat[index] += sfs->temp * 0.1;                                                                              
+                                               // density[index] += sfs->density * 0.1;
+                                               heat[index] = sfs->temp;
+
+                                               // Add emitter density to temp emission map
+                                               temp_emission_map[index] = sfs->density;
+
+                                               // Uses particle velocity as initial velocity for smoke
+                                               if(sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO))
                                                {
-                                                       int i;
-                                                       temp_emission_map = MEM_callocN(sizeof(float) * sds->res[0]*sds->res[1]*sds->res[2], "SmokeTempEmission");
-                                                       // set whole volume to 0.0f
-                                                       for (i=0; i<sds->res[0]*sds->res[1]*sds->res[2]; i++) {
-                                                               temp_emission_map[i] = 0.0f;
-                                                       }
-                                               }
-                                                                                                               
-                                               // mostly copied from particle code                                                             
-                                               if (psys->part->type==PART_HAIR)
+                                                       velocity_x[index] = state.vel[0]*sfs->vel_multi;
+                                                       velocity_y[index] = state.vel[1]*sfs->vel_multi;
+                                                       velocity_z[index] = state.vel[2]*sfs->vel_multi;
+                                               }                                                                               
+                                       }                                                                       
+                                       else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow                                                                     
+                                       {                                                                               
+                                               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)
                                                {
-                                                       /*
-                                                       if (psys->childcache)
-                                                       {
-                                                               totchild = psys->totchildcache;
-                                                       }
-                                                       else
-                                                       */
-
-                                                       // TODO: PART_HAIR not supported whatsoever
-                                                       totchild=0;
+                                                       // init all surrounding cells according to amplification, too                                                                                   
+                                                       int i, j, k;
+                                                       smoke_turbulence_get_res(sds->wt, bigres);
+
+                                                       for(i = 0; i < sds->amplify + 1; i++)
+                                                               for(j = 0; j < sds->amplify + 1; j++)
+                                                                       for(k = 0; k < sds->amplify + 1; k++)
+                                                                       {                                                                                                               
+                                                                               index = smoke_get_index((sds->amplify + 1)* cell[0] + i, bigres[0], (sds->amplify + 1)* cell[1] + j, bigres[1], (sds->amplify + 1)* cell[2] + k);                                                                                                               
+                                                                               bigdensity[index] = 0.f;                                                                                                        
+                                                                       }                                                                               
                                                }
-                                               else
-                                                       totchild=psys->totchild*psys->part->disp/100;
-                                               
-                                               for (p=0; p<totpart+totchild; p++)                                                              
-                                               {
-                                                       int cell[3];
-                                                       size_t i = 0;
-                                                       size_t index = 0;
-                                                       int badcell = 0;
-                                                       ParticleKey state;
+                                       }
+                               }       // particles loop
+
+                               // apply emission values
+                               if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) 
+                               {
+                                       // initialize variables
+                                       int ii, jj, kk, x, y, z, block_size;
+                                       size_t index, index_big;
+
+                                       smoke_turbulence_get_res(sds->wt, bigres);
+                                       block_size = sds->amplify + 1;  // high res block size
 
-                                                       if (p < totpart)
+                                       // loop through every low res cell
+                                       for(x = 0; x < sds->res[0]; x++)
+                                               for(y = 0; y < sds->res[1]; y++)
+                                                       for(z = 0; z < sds->res[2]; z++)                                                                                                        
                                                        {
-                                                               if (psys->particles[p].flag & (PARS_NO_DISP|PARS_UNEXIST))
-                                                                       continue;
-                                                       }
-                                                       else {
-                                                               /* handle child particle */
-                                                               ChildParticle *cpa = &psys->child[p - totpart];
-                                       
-                                                               if (psys->particles[cpa->parent].flag & (PARS_NO_DISP|PARS_UNEXIST))
-                                                                       continue;
-                                                       }
+                                                               // neighbor cell emission densities (for high resolution smoke smooth interpolation)
+                                                               float c000, c001, c010, c011,  c100, c101, c110, c111;
 
-                                                       state.time = smd->time;
-                                                       if (psys_get_particle_state(&sim, p, &state, 0) == 0)
-                                                               continue;
-                                                                                               
-                                                       // copy_v3_v3(pos, pa->state.co);
-                                                       // mul_m4_v3(ob->imat, pos);
-                                                       // 1. get corresponding cell
-                                                       get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, state.co, cell, 0);                                                                                                                                        
-                                                       // 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))                                                                               
-                                                               {                                                                                       
-                                                                       badcell = 1;                                                                                    
-                                                                       break;                                                                          
-                                                               }                                                                       
-                                                       }                                                                                                                                                       
-                                                       if (badcell)                                                                            
-                                                               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]);                                                                                                                                           
-                                                       if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // this is inflow
-                                                       {                                                                               
-                                                               // heat[index] += sfs->temp * 0.1;                                                                              
-                                                               // density[index] += sfs->density * 0.1;
-                                                               heat[index] = sfs->temp;
-                                                               
-                                                               // Add emitter density to temp emission map
-                                                               temp_emission_map[index] = sfs->density;
-
-                                                               // Uses particle velocity as initial velocity for smoke
-                                                               if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO))
-                                                               {
-                                                                       velocity_x[index] = state.vel[0]*sfs->vel_multi;
-                                                                       velocity_y[index] = state.vel[1]*sfs->vel_multi;
-                                                                       velocity_z[index] = state.vel[2]*sfs->vel_multi;
-                                                               }                                                                               
-                                                       }                                                                       
-                                                       else if (sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow                                                                    
-                                                       {                                                                               
-                                                               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)
+                                                               c000 = (x>0 && y>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z-1)] : 0;
+                                                               c001 = (x>0 && y>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z)] : 0;
+                                                               c010 = (x>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z-1)] : 0;
+                                                               c011 = (x>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z)] : 0;
+
+                                                               c100 = (y>0 && z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z-1)] : 0;
+                                                               c101 = (y>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z)] : 0;
+                                                               c110 = (z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z-1)] : 0;
+                                                               c111 = temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z)]; // this cell
+
+                                                               // get cell index
+                                                               index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
+
+                                                               // add emission to low resolution density
+                                                               if (absolute_flow) 
                                                                {
-                                                                       // init all surrounding cells according to amplification, too                                                                                   
-                                                                       int i, j, k;
-                                                                       smoke_turbulence_get_res(smd->domain->wt, bigres);
-
-                                                                       for (i = 0; i < smd->domain->amplify + 1; i++)
-                                                                               for (j = 0; j < smd->domain->amplify + 1; j++)
-                                                                                       for (k = 0; k < smd->domain->amplify + 1; k++)
-                                                                                       {                                                                                                               
-                                                                                               index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k);                                                                                                               
-                                                                                               bigdensity[index] = 0.f;                                                                                                        
-                                                                                       }                                                                               
+                                                                       if (temp_emission_map[index]>0) 
+                                                                               density[index] = temp_emission_map[index];
                                                                }
-                                                       }
-                                                       }       // particles loop
+                                                               else 
+                                                               {
+                                                                       density[index] += temp_emission_map[index];
 
+                                                                       if (density[index]>1) 
+                                                                               density[index]=1.0f;
+                                                               }
 
-                                                       // apply emission values
-                                                       if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) {
+                                                               smoke_turbulence_get_res(sds->wt, bigres);
 
-                                                               // initialize variables
-                                                               int ii, jj, kk, x, y, z, block_size;
-                                                               size_t index, index_big;
+                                                               /* loop through high res blocks if high res enabled */
+                                                               if (bigdensity)
+                                                                       for(ii = 0; ii < block_size; ii++)
+                                                                               for(jj = 0; jj < block_size; jj++)
+                                                                                       for(kk = 0; kk < block_size; kk++)                                                                                                      
+                                                                                       {
 
-                                                               smoke_turbulence_get_res(smd->domain->wt, bigres);
-                                                               block_size = smd->domain->amplify + 1;  // high res block size
+                                                                                               float fx,fy,fz, interpolated_value;
+                                                                                               int shift_x, shift_y, shift_z;
 
 
-                                                                       // loop through every low res cell
-                                                                       for (x = 0; x < sds->res[0]; x++)
-                                                                               for (y = 0; y < sds->res[1]; y++)
-                                                                                       for (z = 0; z < sds->res[2]; z++)                                                                                                       
-                                                                                       {
+                                                                                               /*
+                                                                                               * Do volume interpolation if emitter smoothing
+                                                                                               * is enabled
+                                                                                               */
+                                                                                               if (high_emission_smoothing) 
+                                                                                               {
+                                                                                                       // convert block position to relative
+                                                                                                       // for interpolation smoothing
+                                                                                                       fx = (float)ii/block_size + 0.5f/block_size;
+                                                                                                       fy = (float)jj/block_size + 0.5f/block_size;
+                                                                                                       fz = (float)kk/block_size + 0.5f/block_size;
+
+                                                                                                       // calculate trilinear interpolation
+                                                                                                       interpolated_value = c000 * (1-fx) * (1-fy) * (1-fz) +
+                                                                                                               c100 * fx * (1-fy) * (1-fz) +
+                                                                                                               c010 * (1-fx) * fy * (1-fz) +
+                                                                                                               c001 * (1-fx) * (1-fy) * fz +
+                                                                                                               c101 * fx * (1-fy) * fz +
+                                                                                                               c011 * (1-fx) * fy * fz +
+                                                                                                               c110 * fx * fy * (1-fz) +
+                                                                                                               c111 * fx * fy * fz;
+
+
+                                                                                                       // add some contrast / sharpness
+                                                                                                       // depending on hi-res block size
+
+                                                                                                       interpolated_value = (interpolated_value-0.4f*sfs->density)*(block_size/2) + 0.4f*sfs->density;
+                                                                                                       if (interpolated_value<0.0f) interpolated_value = 0.0f;
+                                                                                                       if (interpolated_value>1.0f) interpolated_value = 1.0f;
+
+                                                                                                       // shift smoke block index
+                                                                                                       // (because pixel center is actually
+                                                                                                       // in halfway of the low res block)
+                                                                                                       shift_x = (x < 1) ? 0 : block_size/2;
+                                                                                                       shift_y = (y < 1) ? 0 : block_size/2;
+                                                                                                       shift_z = (z < 1) ? 0 : block_size/2;
+                                                                                               }
+                                                                                               else 
+                                                                                               {
+                                                                                                       // without interpolation use same low resolution
+                                                                                                       // block value for all hi-res blocks
+                                                                                                       interpolated_value = c111;
+                                                                                                       shift_x = 0;
+                                                                                                       shift_y = 0;
+                                                                                                       shift_z = 0;
+                                                                                               }
 
-                                                                                               // neighbor cell emission densities (for high resolution smoke smooth interpolation)
-                                                                                               float c000, c001, c010, c011,  c100, c101, c110, c111;
+                                                                                               // get shifted index for current high resolution block
+                                                                                               index_big = smoke_get_index(block_size * x + ii - shift_x, bigres[0], block_size * y + jj - shift_y, bigres[1], block_size * z + kk - shift_z);                                                                                                         
 
-                                                                                               c000 = (x>0 && y>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z-1)] : 0;
-                                                                                               c001 = (x>0 && y>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z)] : 0;
-                                                                                               c010 = (x>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z-1)] : 0;
-                                                                                               c011 = (x>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z)] : 0;
+                                                                                               // add emission data to high resolution density
+                                                                                               if (absolute_flow) 
+                                                                                               {
+                                                                                                       if (interpolated_value > 0) 
+                                                                                                               bigdensity[index_big] = interpolated_value;
+                                                                                               }
+                                                                                               else 
+                                                                                               {
+                                                                                                       bigdensity[index_big] += interpolated_value;
 
-                                                                                               c100 = (y>0 && z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z-1)] : 0;
-                                                                                               c101 = (y>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z)] : 0;
-                                                                                               c110 = (z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z-1)] : 0;
-                                                                                               c111 = temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z)];                   // this cell
+                                                                                                       if (bigdensity[index_big]>1) 
+                                                                                                               bigdensity[index_big]=1.0f;
+                                                                                               }
+                                                                                       } // end of hires loop
 
+                                                       } // end of low res loop
 
+                                                       // free temporary emission map
+                                                       if (temp_emission_map) 
+                                                               MEM_freeN(temp_emission_map);
 
-                                                                                               // get cell index
-                                                                                               index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
+                               } // end emission
+                       }
+               }
+       }
 
-                                                                                               // add emission to low resolution density
-                                                                                               if (absolute_flow) {if (temp_emission_map[index]>0) density[index] = temp_emission_map[index];}
-                                                                                               else {
-                                                                                                       density[index] += temp_emission_map[index];
-                                                                                                       if (density[index]>1) density[index]=1.0f;
-                                                                                               }
+       if(flowobjs)
+               MEM_freeN(flowobjs);
+}
 
-                                                                                               smoke_turbulence_get_res(smd->domain->wt, bigres);
+static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt)
+{
+       ListBase *effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights);
 
+       if(effectors)
+       {
+               float *density = smoke_get_density(sds->fluid);
+               float *force_x = smoke_get_force_x(sds->fluid);
+               float *force_y = smoke_get_force_y(sds->fluid);
+               float *force_z = smoke_get_force_z(sds->fluid);
+               float *velocity_x = smoke_get_velocity_x(sds->fluid);
+               float *velocity_y = smoke_get_velocity_y(sds->fluid);
+               float *velocity_z = smoke_get_velocity_z(sds->fluid);
+               unsigned char *obstacle = smoke_get_obstacle(sds->fluid);
+               int x, y, z;
+
+               // precalculate wind forces
+               for(x = 0; x < sds->res[0]; x++)
+                       for(y = 0; y < sds->res[1]; y++)
+                               for(z = 0; z < sds->res[2]; z++)
+               {       
+                       EffectedPoint epoint;
+                       float voxelCenter[3] = {0,0,0} , vel[3] = {0,0,0} , retvel[3] = {0,0,0};
+                       unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
+
+                       if((density[index] < FLT_EPSILON) || obstacle[index])                                   
+                               continue;       
+
+                       vel[0] = velocity_x[index];
+                       vel[1] = velocity_y[index];
+                       vel[2] = velocity_z[index];
+
+                       voxelCenter[0] = sds->p0[0] + sds->dx *  x + sds->dx * 0.5;
+                       voxelCenter[1] = sds->p0[1] + sds->dx *  y + sds->dx * 0.5;
+                       voxelCenter[2] = sds->p0[2] + sds->dx *  z + sds->dx * 0.5;
+
+                       pd_point_from_loc(scene, voxelCenter, vel, index, &epoint);
+                       pdDoEffectors(effectors, NULL, sds->effector_weights, &epoint, retvel, NULL);
+
+                       // TODO dg - do in force!
+                       force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0); 
+                       force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0); 
+                       force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0);
+               }
+       }
 
+       pdEndEffectors(&effectors);
+}
 
-                                                                                               /*
-                                                                                               loop through high res blocks if high res enabled
-                                                                                               */
-                                                                                               if (bigdensity)
-                                                                                               for (ii = 0; ii < block_size; ii++)
-                                                                                                       for (jj = 0; jj < block_size; jj++)
-                                                                                                               for (kk = 0; kk < block_size; kk++)                                                                                                     
-                                                                                                               {
-
-                                                                                                               float fx,fy,fz, interpolated_value;
-                                                                                                               int shift_x, shift_y, shift_z;
-
-
-                                                                                                               /*
-                                                                                                               * Do volume interpolation if emitter smoothing
-                                                                                                               * is enabled
-                                                                                                               */
-                                                                                                               if (high_emission_smoothing) {
-                                                                                                                       // convert block position to relative
-                                                                                                                       // for interpolation smoothing
-                                                                                                                       fx = (float)ii/block_size + 0.5f/block_size;
-                                                                                                                       fy = (float)jj/block_size + 0.5f/block_size;
-                                                                                                                       fz = (float)kk/block_size + 0.5f/block_size;
-
-                                                                                                                       // calculate trilinear interpolation
-                                                                                                                       interpolated_value = c000 * (1-fx) * (1-fy) * (1-fz) +
-                                                                                                                       c100 * fx * (1-fy) * (1-fz) +
-                                                                                                                       c010 * (1-fx) * fy * (1-fz) +
-                                                                                                                       c001 * (1-fx) * (1-fy) * fz +
-                                                                                                                       c101 * fx * (1-fy) * fz +
-                                                                                                                       c011 * (1-fx) * fy * fz +
-                                                                                                                       c110 * fx * fy * (1-fz) +
-                                                                                                                       c111 * fx * fy * fz;
-
-
-                                                                                                                       // add some contrast / sharpness
-                                                                                                                       // depending on hi-res block size
-
-                                                                                                                       interpolated_value = (interpolated_value-0.4f*sfs->density)*(block_size/2) + 0.4f*sfs->density;
-                                                                                                                       if (interpolated_value<0.0f) interpolated_value = 0.0f;
-                                                                                                                       if (interpolated_value>1.0f) interpolated_value = 1.0f;
-
-                                                                                                                       // shift smoke block index
-                                                                                                                       // (because pixel center is actually
-                                                                                                                       // in halfway of the low res block)
-                                                                                                                       shift_x = (x < 1) ? 0 : block_size/2;
-                                                                                                                       shift_y = (y < 1) ? 0 : block_size/2;
-                                                                                                                       shift_z = (z < 1) ? 0 : block_size/2;
-                                                                                                               }
-                                                                                                               else {
-                                                                                                                       // without interpolation use same low resolution
-                                                                                                                       // block value for all hi-res blocks
-                                                                                                                       interpolated_value = c111;
-                                                                                                                       shift_x = 0;
-                                                                                                                       shift_y = 0;
-                                                                                                                       shift_z = 0;
-                                                                                                               }
-
-                                                                                                               // get shifted index for current high resolution block
-                                                                                                               index_big = smoke_get_index(block_size * x + ii - shift_x, bigres[0], block_size * y + jj - shift_y, bigres[1], block_size * z + kk - shift_z);                                                                                                         
-                                                                                                               
-                                                                                                               // add emission data to high resolution density
-                                                                                                               if (absolute_flow) {if (interpolated_value > 0) bigdensity[index_big] = interpolated_value;}
-                                                                                                               else {
-                                                                                                                       bigdensity[index_big] += interpolated_value;
-                                                                                                                       if (bigdensity[index_big]>1) bigdensity[index_big]=1.0f;
-                                                                                                               }
+static void step(Scene *scene, Object *ob, SmokeModifierData *smd, float fps)
+{
+       /* stability values copied from wturbulence.cpp */
+       const int maxSubSteps = 25;
+       float maxVel;
+       // maxVel should be 1.5 (1.5 cell max movement) * dx (cell size)
 
-                                                                                                               } // end of hires loop
+       float dt = DT_DEFAULT;
+       float maxVelMag = 0.0f;
+       int totalSubsteps;
+       int substep = 0;
+       float dtSubdiv;
 
-                                                                       }       // end of low res loop
+       SmokeDomainSettings *sds = smd->domain;
 
-                                                               // free temporary emission map
-                                                       if (temp_emission_map) MEM_freeN(temp_emission_map);
+       /* get max velocity and lower the dt value if it is too high */
+       size_t size= sds->res[0] * sds->res[1] * sds->res[2];
 
-                                                       }       // end emission
+       float *velX = smoke_get_velocity_x(sds->fluid);
+       float *velY = smoke_get_velocity_y(sds->fluid);
+       float *velZ = smoke_get_velocity_z(sds->fluid);
+       size_t i;
 
+       /* adapt timestep for different framerates, dt = 0.1 is at 25fps */
+       dt *= (25.0f / fps);
 
-                                                                               
-                               }                                                       
-                               else {                                                          
-                                       /*                                                              
-                                       for ()                                                          
-                                       {                                                                       
-                                               // no psys                                                                      
-                                               BVHTreeNearest nearest;
-                                               nearest.index = -1;
-                                               nearest.dist = FLT_MAX;
+       // printf("test maxVel: %f\n", (sds->dx * 1.5) / dt); // gives 0.9
+       maxVel = (sds->dx * 1.5);
 
-                                               BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh);
-                                       }*/                                                     
-                               }
-                       }                                               
-               }
-                       if (sds->fluid_group)
-                               go = go->next;
-                       else
-                               base= base->next;
-               }
+       for(i = 0; i < size; i++)
+       {
+               float vtemp = (velX[i]*velX[i]+velY[i]*velY[i]+velZ[i]*velZ[i]);
+               if(vtemp > maxVelMag)
+                       maxVelMag = vtemp;
        }
 
-       // do effectors
+       maxVelMag = sqrt(maxVelMag) * dt * sds->time_scale;
+       totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */
+       totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
+       totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
+
+       // totalSubsteps = 2.0f; // DEBUG
+
+       dtSubdiv = (float)dt / (float)totalSubsteps;
+
+       // printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
+
+       for(substep = 0; substep < totalSubsteps; substep++)
        {
-               ListBase *effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights);
+               // calc animated obstacle velocities
+               update_obstacles(scene, ob, sds, dtSubdiv, substep, totalSubsteps);
+               update_flowsfluids(scene, ob, sds, smd->time);
+               update_effectors(scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt
 
-               if (effectors)
-               {
-                       float *density = smoke_get_density(sds->fluid);
-                       float *force_x = smoke_get_force_x(sds->fluid);
-                       float *force_y = smoke_get_force_y(sds->fluid);
-                       float *force_z = smoke_get_force_z(sds->fluid);
-                       float *velocity_x = smoke_get_velocity_x(sds->fluid);
-                       float *velocity_y = smoke_get_velocity_y(sds->fluid);
-                       float *velocity_z = smoke_get_velocity_z(sds->fluid);
-                       int x, y, z;
-
-                       // precalculate wind forces
-                       for (x = 0; x < sds->res[0]; x++)
-                               for (y = 0; y < sds->res[1]; y++)
-                                       for (z = 0; z < sds->res[2]; z++)
-                       {       
-                               EffectedPoint epoint;
-                               float voxelCenter[3] = {0,0,0} , vel[3] = {0,0,0} , retvel[3] = {0,0,0};
-                               unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
-
-                               if (density[index] < FLT_EPSILON)                                       
-                                       continue;       
-
-                               vel[0] = velocity_x[index];
-                               vel[1] = velocity_y[index];
-                               vel[2] = velocity_z[index];
-
-                               voxelCenter[0] = sds->p0[0] + sds->dx *  x + sds->dx * 0.5;
-                               voxelCenter[1] = sds->p0[1] + sds->dx *  y + sds->dx * 0.5;
-                               voxelCenter[2] = sds->p0[2] + sds->dx *  z + sds->dx * 0.5;
-
-                               pd_point_from_loc(scene, voxelCenter, vel, index, &epoint);
-                               pdDoEffectors(effectors, NULL, sds->effector_weights, &epoint, retvel, NULL);
-
-                               // TODO dg - do in force!
-                               force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0); 
-                               force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0); 
-                               force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0);
-                       }
-               }
+               smoke_step(sds->fluid, dtSubdiv);
 
-               pdEndEffectors(&effectors);
-       }
+               // move animated obstacle: Done in update_obstacles() */
 
+               // where to delete old obstacles from array? Done in update_obstacles() */
+       }
 }
+
 void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
 {      
-       if ((smd->type & MOD_SMOKE_TYPE_FLOW))
+       if((smd->type & MOD_SMOKE_TYPE_FLOW))
        {
-               if (scene->r.cfra >= smd->time)
+               if(scene->r.cfra >= smd->time)
                        smokeModifier_init(smd, ob, scene, dm);
 
-               if (scene->r.cfra > smd->time)
+               if(scene->r.cfra > smd->time)
                {
                        // XXX TODO
                        smd->time = scene->r.cfra;
@@ -1366,40 +1675,102 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
                        copy_m4_m4(smd->flow->mat, ob->obmat);
                        */
                }
-               else if (scene->r.cfra < smd->time)
+               else if(scene->r.cfra < smd->time)
                {
                        smd->time = scene->r.cfra;
                        smokeModifier_reset(smd);
                }
        }
-       else if (smd->type & MOD_SMOKE_TYPE_COLL)
+       else if(smd->type & MOD_SMOKE_TYPE_COLL)
        {
-               if (scene->r.cfra >= smd->time)
+               /* Check if domain resolution changed */
+               /* DG TODO: can this be solved more elegant using dependancy graph? */
+               {
+                       SmokeCollSettings *scs = smd->coll;
+                       Base *base = scene->base.first;
+                       int changed = 0;
+                       float dx = FLT_MAX;
+                       int haveDomain = 0;
+
+                       for ( ; base; base = base->next) 
+                       {
+                               SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(base->object, eModifierType_Smoke);
+
+                               if (smd2 && (smd2->type & MOD_SMOKE_TYPE_DOMAIN) && smd2->domain)
+                               {
+                                       SmokeDomainSettings *sds = smd2->domain;
+
+                                       if(sds->dx < dx)
+                                       {
+                                               dx = sds->dx;
+                                               changed = 1;
+                                       }
+
+                                       haveDomain = 1;
+                               }
+                       }
+
+                       if(!haveDomain)
+                               return;
+                       
+                       if(changed)
+                       {
+                               if(dx != scs->dx)
+                               {
+                                       scs->dx = dx;
+                                       smokeModifier_reset(smd);
+                               }
+                       }
+               }
+
+               if(scene->r.cfra >= smd->time)
                        smokeModifier_init(smd, ob, scene, dm);
 
-               if (scene->r.cfra > smd->time)
+               if(scene->r.cfra > smd->time)
                {
-                       // XXX TODO
+                       unsigned int i;
+                       SmokeCollSettings *scs = smd->coll;
+                       float *points_old = scs->points_old;
+                       float *points = scs->points;
+                       unsigned int numpoints = scs->numpoints; 
+
+                       // XXX TODO <-- DG: what is TODO here?
                        smd->time = scene->r.cfra;
 
-#ifdef USE_SMOKE_COLLISION_DM
-                       if (smd->coll->dm)
-                               smd->coll->dm->release(smd->coll->dm);
+                       // rigid movement support
+                       copy_m4_m4(scs->mat_old, scs->mat);
+                       copy_m4_m4(scs->mat, ob->obmat);
 
-                       smd->coll->dm = CDDM_copy_from_tessface(dm);
-#endif
+                       if(scs->type != SM_COLL_ANIMATED) // if(not_animated)
+                       {
+                               // nothing to do, "mat" is already up to date
+                       }
+                       else
+                       {
+                               // XXX TODO: need to update positions + divs
 
-                       // rigid movement support
-                       copy_m4_m4(smd->coll->mat_old, smd->coll->mat);
-                       copy_m4_m4(smd->coll->mat, ob->obmat);
+                               if(scs->numverts != dm->getNumVerts(dm))
+                               {
+                                       // DG TODO: reset modifier?
+                                       return;
+                               }
+
+                               for(i = 0; i < numpoints * 3; i++)
+                               {
+                                       points_old[i] = points[i];
+                               }
+
+                               DM_ensure_tessface(dm);
+                               fill_scs_points_anim(ob, dm, scs);
+                       }
                }
-               else if (scene->r.cfra < smd->time)
+               else if(scene->r.cfra < smd->time)
                {
                        smd->time = scene->r.cfra;
                        smokeModifier_reset(smd);
                }
        }
-       else if (smd->type & MOD_SMOKE_TYPE_DOMAIN)
+       else if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
        {
                SmokeDomainSettings *sds = smd->domain;
                float light[3]; 
@@ -1416,14 +1787,14 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
                BKE_ptcache_id_from_smoke(&pid, ob, smd);
                BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
 
-               if (!smd->domain->fluid || framenr == startframe)
+               if(!smd->domain->fluid || framenr == startframe)
                {
                        BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
                        BKE_ptcache_validate(cache, framenr);
                        cache->flag &= ~PTCACHE_REDO_NEEDED;
                }
 
-               if (!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0)
+               if(!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0)
                        return;
 
                smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD;
@@ -1436,21 +1807,21 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
 
                // printf("startframe: %d, framenr: %d\n", startframe, framenr);
 
-               if (smokeModifier_init(smd, ob, scene, dm)==0)
+               if(smokeModifier_init(smd, ob, scene, dm)==0)
                {
                        printf("bad smokeModifier_init\n");
                        return;
                }
 
                /* try to read from cache */
-               if (BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) {
+               if(BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) {
                        BKE_ptcache_validate(cache, framenr);
                        smd->time = framenr;
                        return;
                }
                
                /* only calculate something when we advanced a single frame */
-               if (framenr != (int)smd->time+1)
+               if(framenr != (int)smd->time+1)
                        return;
 
                /* don't simulate if viewing start frame, but scene frame is not real start frame */
@@ -1462,14 +1833,14 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
                smoke_calc_domain(scene, ob, smd);
 
                /* if on second frame, write cache for first frame */
-               if ((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) {
+               if((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) {
                        // create shadows straight after domain initialization so we get nice shadows for startframe, too
-                       if (get_lamp(scene, light))
+                       if(get_lamp(scene, light))
                                smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx);
 
-                       if (sds->wt)
+                       if(sds->wt)
                        {
-                               if (sds->flags & MOD_SMOKE_DISSOLVE)
+                               if(sds->flags & MOD_SMOKE_DISSOLVE)
                                        smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
                                smoke_turbulence_step(sds->wt, sds->fluid);
                        }
@@ -1486,30 +1857,31 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
 
                // simulate the actual smoke (c++ code in intern/smoke)
                // DG: interesting commenting this line + deactivating loading of noise files
-               if (framenr!=startframe)
+               if(framenr!=startframe)
                {
-                       if (sds->flags & MOD_SMOKE_DISSOLVE)
+                       if(sds->flags & MOD_SMOKE_DISSOLVE)
                                smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
-                       smoke_step(sds->fluid, smd->time, scene->r.frs_sec / scene->r.frs_sec_base);
+                       
+                       step(scene, ob, smd, scene->r.frs_sec / scene->r.frs_sec_base);
                }
 
                // create shadows before writing cache so they get stored
-               if (get_lamp(scene, light))
+               if(get_lamp(scene, light))
                        smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx);
 
-               if (sds->wt)
+               if(sds->wt)
                {
-                       if (sds->flags & MOD_SMOKE_DISSOLVE)
+                       if(sds->flags & MOD_SMOKE_DISSOLVE)
                                smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
                        smoke_turbulence_step(sds->wt, sds->fluid);
                }
        
                BKE_ptcache_validate(cache, framenr);
-               if (framenr != startframe)
+               if(framenr != startframe)
                        BKE_ptcache_write(&pid, framenr);
 
                tend();
-               //printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() );
+               // printf ( "Frame: %d, Time: %f\n\n", (int)smd->time, ( float ) tval() );
        }
 }
 
@@ -1520,7 +1892,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix
        // T_ray *= T_vox
        *tRay *= exp(input[index]*correct);
        
-       if (result[index] < 0.0f)       
+       if(result[index] < 0.0f)        
        {
 #pragma omp critical           
                result[index] = *tRay;  
@@ -1574,7 +1946,7 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
                err_1 = dy2 - l;
                err_2 = dz2 - l;
                for (i = 0; i < l; i++) {
-                       if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
+                       if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
                                break;
                        if (err_1 > 0) {
                                pixel[1] += y_inc;
@@ -1588,12 +1960,12 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
                        err_2 += dz2;
                        pixel[0] += x_inc;
                }
-       }
+       } 
        else if ((m >= l) && (m >= n)) {
                err_1 = dx2 - m;
                err_2 = dz2 - m;
                for (i = 0; i < m; i++) {
-                       if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
+                       if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
                                break;
                        if (err_1 > 0) {
                                pixel[0] += x_inc;
@@ -1607,12 +1979,12 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
                        err_2 += dz2;
                        pixel[1] += y_inc;
                }
-       }
+       } 
        else {
                err_1 = dy2 - n;
                err_2 = dx2 - n;
                for (i = 0; i < n; i++) {
-                       if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
+                       if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
                                break;
                        if (err_1 > 0) {
                                pixel[1] += y_inc;
@@ -1654,7 +2026,7 @@ static void smoke_calc_transparency(float *result, float *input, float *p0, floa
        float bv[6];
        int a, z, slabsize=res[0]*res[1], size= res[0]*res[1]*res[2];
 
-       for (a=0; a<size; a++)
+       for(a=0; a<size; a++)
                result[a]= -1.0f;
 
        bv[0] = p0[0];
@@ -1667,27 +2039,27 @@ static void smoke_calc_transparency(float *result, float *input, float *p0, floa
        bv[5] = p1[2];
 
 #pragma omp parallel for schedule(static,1)
-       for (z = 0; z < res[2]; z++)
+       for(z = 0; z < res[2]; z++)
        {
                size_t index = z*slabsize;
                int x,y;
 
-               for (y = 0; y < res[1]; y++)
-                       for (x = 0; x < res[0]; x++, index++)
+               for(y = 0; y < res[1]; y++)
+                       for(x = 0; x < res[0]; x++, index++)
                        {
                                float voxelCenter[3];
                                float pos[3];
                                int cell[3];
                                float tRay = 1.0;
 
-                               if (result[index] >= 0.0f)                                      
+                               if(result[index] >= 0.0f)                                       
                                        continue;                                                               
                                voxelCenter[0] = p0[0] + dx *  x + dx * 0.5;
                                voxelCenter[1] = p0[1] + dx *  y + dx * 0.5;
                                voxelCenter[2] = p0[2] + dx *  z + dx * 0.5;
 
                                // get starting position (in voxel coords)
-                               if (BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON)
+                               if(BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON)
                                {
                                        // we're ouside
                                        get_cell(p0, res, dx, pos, cell, 1);
index 26b3a3e6c6242065dbdf90a0cdc8f1e6de5fc2c6..3e20b3538569cdcee5536a77d47326ca31796921 100644 (file)
 #define SM_BORDER_VERTICAL     1
 #define SM_BORDER_CLOSED       2
 
+/* collision types */
+#define SM_COLL_STATIC         0
+#define SM_COLL_RIGID          1
+#define SM_COLL_ANIMATED       2
+
 typedef struct SmokeDomainSettings {
        struct SmokeModifierData *smd; /* for fast RNA access */
        struct FLUID_3D *fluid;
@@ -137,15 +142,16 @@ typedef struct SmokeFlowSettings {
 typedef struct SmokeCollSettings {
        struct SmokeModifierData *smd; /* for fast RNA access */
        struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
-
-//     struct DerivedMesh *dm; // UNUSED, ifdef'd in code for now.
        float *points;
        float *points_old;
-       float *vel;
+       float *vel; // UNUSED
+       int *tridivs;
        float mat[4][4];
        float mat_old[4][4];
        int numpoints;
        int numverts; // check if mesh changed
+       int numtris;
+       float dx; /* global domain cell length taken from (scale / resolution) */
        short type; // static = 0, rigid = 1, dynamic = 2
        short pad;
        int pad2;
index 69d76c0e342ba7490d26b52ade34205a422ff362..b1fed62f87b82ea4b0ac00056cc9bd5b3c9f0cdc 100644 (file)
@@ -16,6 +16,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * Contributor(s): Daniel Genrich
+ *                 Blender Foundation
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -336,12 +337,25 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
 
 static void rna_def_smoke_coll_settings(BlenderRNA *brna)
 {
+       static EnumPropertyItem smoke_coll_type_items[] = {
+               {SM_COLL_STATIC, "COLLSTATIC", 0, "Static", "Non moving obstacle"},
+               {SM_COLL_RIGID, "COLLRIGID", 0, "Rigid", "Rigid obstacle"},
+               {SM_COLL_ANIMATED, "COLLANIMATED", 0, "Animated", "Animated obstacle"},
+               {0, NULL, 0, NULL, NULL}};
+
        StructRNA *srna;
+       PropertyRNA *prop;
 
        srna = RNA_def_struct(brna, "SmokeCollSettings", NULL);
        RNA_def_struct_ui_text(srna, "Collision Settings", "Smoke collision settings");
        RNA_def_struct_sdna(srna, "SmokeCollSettings");
        RNA_def_struct_path_func(srna, "rna_SmokeCollSettings_path");
+
+       prop = RNA_def_property(srna, "collision_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "type");
+       RNA_def_property_enum_items(prop, smoke_coll_type_items);
+       RNA_def_property_ui_text(prop, "Collision type", "Collision type");
+       RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
 }
 
 void RNA_def_smoke(BlenderRNA *brna)