forked from bartvdbraak/blender
Smoke: Support for moving obstacles. (Merge from Smoke2 branch)
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.
This commit is contained in:
parent
4465d2f419
commit
8bf8a128c2
7
intern/smoke/extern/smoke_API.h
vendored
7
intern/smoke/extern/smoke_API.h
vendored
@ -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);
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "SPHERE.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#include "float.h"
|
||||
|
||||
#if PARALLEL==1
|
||||
#include <omp.h>
|
||||
#endif // PARALLEL
|
||||
@ -42,11 +44,11 @@
|
||||
// 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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -27,9 +27,11 @@
|
||||
#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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -19,6 +19,7 @@
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Daniel Genrich
|
||||
* Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
@ -36,10 +37,10 @@
|
||||
#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);
|
||||
|
@ -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):
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,11 @@
|
||||
#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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user