forked from bartvdbraak/blender
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
This commit is contained in:
parent
ecb58629f2
commit
967d25ac1c
4
intern/smoke/extern/smoke_API.h
vendored
4
intern/smoke/extern/smoke_API.h
vendored
@ -38,10 +38,10 @@ 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, float dt);
|
||||
struct FLUID_3D *smoke_init(int *res, float *p0);
|
||||
void smoke_free(struct FLUID_3D *fluid);
|
||||
|
||||
void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta);
|
||||
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 *smoke_get_density(struct FLUID_3D *fluid);
|
||||
|
@ -35,23 +35,15 @@
|
||||
#include <omp.h>
|
||||
#endif // PARALLEL
|
||||
|
||||
// boundary conditions of the fluid domain
|
||||
#define DOMAIN_BC_FRONT 0 // z
|
||||
#define DOMAIN_BC_TOP 1 // y
|
||||
#define DOMAIN_BC_LEFT 1 // x
|
||||
#define DOMAIN_BC_BACK DOMAIN_BC_FRONT
|
||||
#define DOMAIN_BC_BOTTOM DOMAIN_BC_TOP
|
||||
#define DOMAIN_BC_RIGHT DOMAIN_BC_LEFT
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
FLUID_3D::FLUID_3D(int *res, float *p0, float dt) :
|
||||
_xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f), _dt(dt)
|
||||
FLUID_3D::FLUID_3D(int *res, float *p0) :
|
||||
_xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f)
|
||||
{
|
||||
// set simulation consts
|
||||
// _dt = dt; // 0.10
|
||||
_dt = DT_DEFAULT; // just in case. set in step from a RNA factor
|
||||
|
||||
// start point of array
|
||||
_p0[0] = p0[0];
|
||||
@ -61,7 +53,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dt) :
|
||||
_iterations = 100;
|
||||
_tempAmb = 0;
|
||||
_heatDiffusion = 1e-3;
|
||||
_vorticityEps = 2.0;
|
||||
_totalTime = 0.0f;
|
||||
_totalSteps = 0;
|
||||
_res = Vec3Int(_xRes,_yRes,_zRes);
|
||||
@ -77,9 +68,9 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dt) :
|
||||
|
||||
// scale the constants according to the refinement of the grid
|
||||
_dx = 1.0f / (float)_maxRes;
|
||||
float scaling = 64.0f / _maxRes;
|
||||
scaling = (scaling < 1.0f) ? 1.0f : scaling;
|
||||
_vorticityEps /= scaling;
|
||||
_constantScaling = 64.0f / _maxRes;
|
||||
_constantScaling = (_constantScaling < 1.0f) ? 1.0f : _constantScaling;
|
||||
_vorticityEps = 2.0f / _constantScaling; // Just in case set a default value
|
||||
|
||||
// allocate arrays
|
||||
_totalCells = _xRes * _yRes * _zRes;
|
||||
@ -126,30 +117,42 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dt) :
|
||||
_obstacles[x] = false;
|
||||
}
|
||||
|
||||
// boundary conditions of the fluid domain
|
||||
// set default values -> vertically non-colliding
|
||||
_domainBcFront = true;
|
||||
_domainBcTop = false;
|
||||
_domainBcLeft = true;
|
||||
_domainBcBack = _domainBcFront;
|
||||
_domainBcBottom = _domainBcTop;
|
||||
_domainBcRight = _domainBcLeft;
|
||||
|
||||
_colloPrev = 1; // default value
|
||||
|
||||
|
||||
// set side obstacles
|
||||
int index;
|
||||
for (int y = 0; y < _yRes; y++)
|
||||
for (int x = 0; x < _xRes; x++)
|
||||
{
|
||||
// front slab
|
||||
// bottom slab
|
||||
index = x + y * _xRes;
|
||||
if(DOMAIN_BC_FRONT==1) _obstacles[index] = 1;
|
||||
if(_domainBcBottom==1) _obstacles[index] = 1;
|
||||
|
||||
// back slab
|
||||
// top slab
|
||||
index += _totalCells - _slabSize;
|
||||
if(DOMAIN_BC_BACK==1) _obstacles[index] = 1;
|
||||
if(_domainBcTop==1) _obstacles[index] = 1;
|
||||
}
|
||||
|
||||
for (int z = 0; z < _zRes; z++)
|
||||
for (int x = 0; x < _xRes; x++)
|
||||
{
|
||||
// bottom slab
|
||||
// front slab
|
||||
index = x + z * _slabSize;
|
||||
if(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1;
|
||||
if(_domainBcFront==1) _obstacles[index] = 1;
|
||||
|
||||
// top slab
|
||||
// back slab
|
||||
index += _slabSize - _xRes;
|
||||
if(DOMAIN_BC_TOP==1) _obstacles[index] = 1;
|
||||
if(_domainBcBack==1) _obstacles[index] = 1;
|
||||
}
|
||||
|
||||
for (int z = 0; z < _zRes; z++)
|
||||
@ -157,12 +160,13 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dt) :
|
||||
{
|
||||
// left slab
|
||||
index = y * _xRes + z * _slabSize;
|
||||
if(DOMAIN_BC_LEFT==1) _obstacles[index] = 1;
|
||||
if(_domainBcLeft==1) _obstacles[index] = 1;
|
||||
|
||||
// right slab
|
||||
index += _xRes - 1;
|
||||
if(DOMAIN_BC_RIGHT==1) _obstacles[index] = 1;
|
||||
if(_domainBcRight==1) _obstacles[index] = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FLUID_3D::~FLUID_3D()
|
||||
@ -193,17 +197,32 @@ FLUID_3D::~FLUID_3D()
|
||||
}
|
||||
|
||||
// init direct access functions from blender
|
||||
void FLUID_3D::initBlenderRNA(float *alpha, float *beta)
|
||||
void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision)
|
||||
{
|
||||
_alpha = alpha;
|
||||
_beta = beta;
|
||||
_dtFactor = dt_factor;
|
||||
_vorticityRNA = vorticity;
|
||||
_borderColli = borderCollision;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// step simulation once
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void FLUID_3D::step()
|
||||
void FLUID_3D::step(float dt)
|
||||
{
|
||||
// If border rules have been changed
|
||||
if (_colloPrev != *_borderColli) {
|
||||
setBorderCollisions();
|
||||
}
|
||||
|
||||
|
||||
// set delta time by dt_factor
|
||||
_dt = (*_dtFactor) * dt;
|
||||
// set vorticity from RNA value
|
||||
_vorticityEps = (*_vorticityRNA)/_constantScaling;
|
||||
|
||||
|
||||
#if PARALLEL==1
|
||||
int threadval = 1;
|
||||
threadval = omp_get_max_threads();
|
||||
@ -246,6 +265,13 @@ void FLUID_3D::step()
|
||||
#pragma omp single
|
||||
{
|
||||
#endif
|
||||
/*
|
||||
* addForce() changed Temp values to preserve thread safety
|
||||
* (previous functions in per thread loop still needed
|
||||
* original velocity data)
|
||||
*
|
||||
* So swap temp values to velocity
|
||||
*/
|
||||
SWAP_POINTERS(_xVelocity, _xVelocityTemp);
|
||||
SWAP_POINTERS(_yVelocity, _yVelocityTemp);
|
||||
SWAP_POINTERS(_zVelocity, _zVelocityTemp);
|
||||
@ -276,6 +302,10 @@ void FLUID_3D::step()
|
||||
#pragma omp single
|
||||
{
|
||||
#endif
|
||||
/*
|
||||
* For thread safety use "Old" to read
|
||||
* "current" values but still allow changing values.
|
||||
*/
|
||||
SWAP_POINTERS(_xVelocity, _xVelocityOld);
|
||||
SWAP_POINTERS(_yVelocity, _yVelocityOld);
|
||||
SWAP_POINTERS(_zVelocity, _zVelocityOld);
|
||||
@ -334,6 +364,10 @@ void FLUID_3D::step()
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* swap final velocity back to Velocity array
|
||||
* from temp xForce storage
|
||||
*/
|
||||
SWAP_POINTERS(_xVelocity, _xForce);
|
||||
SWAP_POINTERS(_yVelocity, _yForce);
|
||||
SWAP_POINTERS(_zVelocity, _zForce);
|
||||
@ -351,6 +385,88 @@ void FLUID_3D::step()
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Set border collision model from RNA setting
|
||||
|
||||
void FLUID_3D::setBorderCollisions() {
|
||||
|
||||
|
||||
_colloPrev = *_borderColli; // saving the current value
|
||||
|
||||
// boundary conditions of the fluid domain
|
||||
if (_colloPrev == 0)
|
||||
{
|
||||
// No collisions
|
||||
_domainBcFront = false;
|
||||
_domainBcTop = false;
|
||||
_domainBcLeft = false;
|
||||
}
|
||||
else if (_colloPrev == 2)
|
||||
{
|
||||
// Collide with all sides
|
||||
_domainBcFront = true;
|
||||
_domainBcTop = true;
|
||||
_domainBcLeft = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default values: Collide with "walls", but not top and bottom
|
||||
_domainBcFront = true;
|
||||
_domainBcTop = false;
|
||||
_domainBcLeft = true;
|
||||
}
|
||||
|
||||
_domainBcBack = _domainBcFront;
|
||||
_domainBcBottom = _domainBcTop;
|
||||
_domainBcRight = _domainBcLeft;
|
||||
|
||||
|
||||
|
||||
// set side obstacles
|
||||
int index;
|
||||
for (int y = 0; y < _yRes; y++)
|
||||
for (int x = 0; x < _xRes; x++)
|
||||
{
|
||||
// front slab
|
||||
index = x + y * _xRes;
|
||||
if(_domainBcBottom==1) _obstacles[index] = 1;
|
||||
else _obstacles[index] = 0;
|
||||
|
||||
// back slab
|
||||
index += _totalCells - _slabSize;
|
||||
if(_domainBcTop==1) _obstacles[index] = 1;
|
||||
else _obstacles[index] = 0;
|
||||
}
|
||||
|
||||
for (int z = 0; z < _zRes; z++)
|
||||
for (int x = 0; x < _xRes; x++)
|
||||
{
|
||||
// bottom slab
|
||||
index = x + z * _slabSize;
|
||||
if(_domainBcFront==1) _obstacles[index] = 1;
|
||||
else _obstacles[index] = 0;
|
||||
|
||||
// top slab
|
||||
index += _slabSize - _xRes;
|
||||
if(_domainBcBack==1) _obstacles[index] = 1;
|
||||
else _obstacles[index] = 0;
|
||||
}
|
||||
|
||||
for (int z = 0; z < _zRes; z++)
|
||||
for (int y = 0; y < _yRes; y++)
|
||||
{
|
||||
// left slab
|
||||
index = y * _xRes + z * _slabSize;
|
||||
if(_domainBcLeft==1) _obstacles[index] = 1;
|
||||
else _obstacles[index] = 0;
|
||||
|
||||
// right slab
|
||||
index += _xRes - 1;
|
||||
if(_domainBcRight==1) _obstacles[index] = 1;
|
||||
else _obstacles[index] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// helper function to dampen co-located grid artifacts of given arrays in intervals
|
||||
// (only needed for velocity, strength (w) depends on testcase...
|
||||
@ -428,6 +544,10 @@ void FLUID_3D::artificialDampingExactSL(int pos) {
|
||||
for (y = 1; y < _res[1]-1; y++)
|
||||
for (x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
|
||||
index = x + y*_res[0] + posslab;
|
||||
/*
|
||||
* Uses xForce as temporary storage to allow other threads to read
|
||||
* old values from xVelocityTemp
|
||||
*/
|
||||
_xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
|
||||
_xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
|
||||
_xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
|
||||
@ -450,6 +570,11 @@ void FLUID_3D::artificialDampingExactSL(int pos) {
|
||||
for (y = 1; y < _res[1]-1; y++)
|
||||
for (x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
|
||||
index = x + y*_res[0] + posslab;
|
||||
|
||||
/*
|
||||
* Uses xForce as temporary storage to allow other threads to read
|
||||
* old values from xVelocityTemp
|
||||
*/
|
||||
_xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
|
||||
_xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
|
||||
_xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
|
||||
@ -661,13 +786,13 @@ void FLUID_3D::project()
|
||||
setObstacleBoundaries(_pressure, 0, _zRes);
|
||||
|
||||
// copy out the boundaries
|
||||
if(DOMAIN_BC_LEFT == 0) setNeumannX(_xVelocity, _res, 0, _zRes);
|
||||
if(_domainBcLeft == 0) setNeumannX(_xVelocity, _res, 0, _zRes);
|
||||
else setZeroX(_xVelocity, _res, 0, _zRes);
|
||||
|
||||
if(DOMAIN_BC_TOP == 0) setNeumannY(_yVelocity, _res, 0, _zRes);
|
||||
if(_domainBcFront == 0) setNeumannY(_yVelocity, _res, 0, _zRes);
|
||||
else setZeroY(_yVelocity, _res, 0, _zRes);
|
||||
|
||||
if(DOMAIN_BC_FRONT == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
|
||||
if(_domainBcTop == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
|
||||
else setZeroZ(_zVelocity, _res, 0, _zRes);
|
||||
|
||||
// calculate divergence
|
||||
@ -1060,13 +1185,13 @@ void FLUID_3D::advectMacCormackBegin(int zBegin, int zEnd)
|
||||
{
|
||||
Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
|
||||
|
||||
if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocityOld, res, zBegin, zEnd);
|
||||
if(_domainBcLeft == 0) copyBorderX(_xVelocityOld, res, zBegin, zEnd);
|
||||
else setZeroX(_xVelocityOld, res, zBegin, zEnd);
|
||||
|
||||
if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
|
||||
if(_domainBcFront == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
|
||||
else setZeroY(_yVelocityOld, res, zBegin, zEnd);
|
||||
|
||||
if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
|
||||
if(_domainBcTop == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
|
||||
else setZeroZ(_zVelocityOld, res, zBegin, zEnd);
|
||||
}
|
||||
|
||||
@ -1114,13 +1239,13 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd);
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd);
|
||||
|
||||
if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
|
||||
if(_domainBcLeft == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
|
||||
else setZeroX(_xVelocityTemp, res, zBegin, zEnd);
|
||||
|
||||
if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
|
||||
if(_domainBcFront == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
|
||||
else setZeroY(_yVelocityTemp, res, zBegin, zEnd);
|
||||
|
||||
if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
|
||||
if(_domainBcTop == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
|
||||
else setZeroZ(_zVelocityTemp, res, zBegin, zEnd);
|
||||
|
||||
setZeroBorder(_density, res, zBegin, zEnd);
|
||||
|
@ -36,6 +36,9 @@
|
||||
// #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;
|
||||
@ -43,11 +46,11 @@ class WTURBULENCE;
|
||||
class FLUID_3D
|
||||
{
|
||||
public:
|
||||
FLUID_3D(int *res, /* int amplify, */ float *p0, float dt);
|
||||
FLUID_3D(int *res, /* int amplify, */ float *p0);
|
||||
FLUID_3D() {};
|
||||
virtual ~FLUID_3D();
|
||||
|
||||
void initBlenderRNA(float *alpha, float *beta);
|
||||
void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli);
|
||||
|
||||
// create & allocate vector noise advection
|
||||
void initVectorNoise(int amplify);
|
||||
@ -55,7 +58,7 @@ class FLUID_3D
|
||||
void addSmokeColumn();
|
||||
static void addSmokeTestCase(float* field, Vec3Int res);
|
||||
|
||||
void step();
|
||||
void step(float dt);
|
||||
void addObstacle(OBSTACLE* obstacle);
|
||||
|
||||
const float* xVelocity() { return _xVelocity; };
|
||||
@ -111,11 +114,25 @@ class FLUID_3D
|
||||
|
||||
// simulation constants
|
||||
float _dt;
|
||||
float *_dtFactor;
|
||||
float _vorticityEps;
|
||||
float _heatDiffusion;
|
||||
float *_vorticityRNA; // RNA-pointer.
|
||||
float *_alpha; // for the buoyancy density term <-- as pointer to get blender RNA in here
|
||||
float *_beta; // was _buoyancy <-- as pointer to get blender RNA in here
|
||||
float _tempAmb; /* ambient temperature */
|
||||
float _constantScaling;
|
||||
|
||||
bool _domainBcFront; // z
|
||||
bool _domainBcTop; // y
|
||||
bool _domainBcLeft; // x
|
||||
bool _domainBcBack; // DOMAIN_BC_FRONT
|
||||
bool _domainBcBottom; // DOMAIN_BC_TOP
|
||||
bool _domainBcRight; // DOMAIN_BC_LEFT
|
||||
int *_borderColli; // border collision rules <-- as pointer to get blender RNA in here
|
||||
int _colloPrev; // To track whether value has been changed (to not
|
||||
// have to recalibrate borders if nothing has changed
|
||||
void setBorderCollisions();
|
||||
|
||||
// WTURBULENCE object, if active
|
||||
// WTURBULENCE* _wTurbulence;
|
||||
|
@ -33,10 +33,10 @@
|
||||
#include <math.h>
|
||||
|
||||
// y in smoke is z in blender
|
||||
extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dt)
|
||||
extern "C" FLUID_3D *smoke_init(int *res, float *p0)
|
||||
{
|
||||
// smoke lib uses y as top-bottom/vertical axis where blender uses z
|
||||
FLUID_3D *fluid = new FLUID_3D(res, p0, dt);
|
||||
FLUID_3D *fluid = new FLUID_3D(res, p0);
|
||||
|
||||
// printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
|
||||
|
||||
@ -77,7 +77,36 @@ extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z
|
||||
|
||||
extern "C" void smoke_step(FLUID_3D *fluid, size_t framenr)
|
||||
{
|
||||
fluid->step();
|
||||
/* 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 */
|
||||
|
||||
const 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
|
||||
@ -85,9 +114,9 @@ extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
|
||||
wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles);
|
||||
}
|
||||
|
||||
extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta)
|
||||
extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli)
|
||||
{
|
||||
fluid->initBlenderRNA(alpha, beta);
|
||||
fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli);
|
||||
}
|
||||
|
||||
extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
|
||||
|
@ -78,14 +78,17 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel):
|
||||
col = split.column()
|
||||
col.label(text="Resolution:")
|
||||
col.prop(domain, "maxres", text="Divisions")
|
||||
col.label(text="Particle:")
|
||||
col.prop(domain, "initial_velocity", text="Initial Velocity")
|
||||
col.label(text="Time:")
|
||||
col.prop(domain, "time_scale", text="Scale")
|
||||
col.label(text="Border Collisions:")
|
||||
col.prop(domain, "smoke_domain_colli", text="")
|
||||
|
||||
if wide_ui:
|
||||
col = split.column()
|
||||
col.label(text="Behavior:")
|
||||
col.prop(domain, "alpha")
|
||||
col.prop(domain, "beta")
|
||||
col.prop(domain, "vorticity")
|
||||
col.prop(domain, "dissolve_smoke", text="Dissolve")
|
||||
sub = col.column()
|
||||
sub.active = domain.dissolve_smoke
|
||||
@ -93,24 +96,31 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel):
|
||||
sub.prop(domain, "dissolve_smoke_log", text="Slow")
|
||||
|
||||
elif md.smoke_type == 'FLOW':
|
||||
|
||||
flow = md.flow_settings
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(flow, "outflow")
|
||||
col.label(text="Particle System:")
|
||||
col.label(text="Particle:")
|
||||
col.prop_object(flow, "psys", ob, "particle_systems", text="")
|
||||
|
||||
if md.flow_settings.outflow:
|
||||
if wide_ui:
|
||||
col = split.column()
|
||||
else:
|
||||
if wide_ui:
|
||||
col = split.column()
|
||||
col.label(text="Behavior:")
|
||||
col.prop(flow, "temperature")
|
||||
col.prop(flow, "density")
|
||||
sub = col.column()
|
||||
sub.active = not md.flow_settings.outflow
|
||||
|
||||
sub.prop(flow, "initial_velocity", text="Initial Velocity")
|
||||
sub = sub.column()
|
||||
sub.active = flow.initial_velocity
|
||||
sub.prop(flow, "velocity_multiplier", text="Multiplier")
|
||||
|
||||
if wide_ui:
|
||||
sub = split.column()
|
||||
sub.active = not md.flow_settings.outflow
|
||||
sub.label(text="Behavior:")
|
||||
sub.prop(flow, "temperature")
|
||||
sub.prop(flow, "density")
|
||||
sub.prop(flow, "absolute")
|
||||
|
||||
#elif md.smoke_type == 'COLLISION':
|
||||
# layout.separator()
|
||||
@ -191,6 +201,7 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel):
|
||||
col = split.column()
|
||||
col.label(text="Resolution:")
|
||||
col.prop(md, "amplify", text="Divisions")
|
||||
col.prop(md, "smoothemitter")
|
||||
col.prop(md, "viewhighres")
|
||||
|
||||
if wide_ui:
|
||||
|
@ -45,7 +45,7 @@ struct Scene;
|
||||
struct Main;
|
||||
|
||||
#define BLENDER_VERSION 253
|
||||
#define BLENDER_SUBVERSION 0
|
||||
#define BLENDER_SUBVERSION 1
|
||||
|
||||
#define BLENDER_MINVERSION 250
|
||||
#define BLENDER_MINSUBVERSION 0
|
||||
|
@ -220,7 +220,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive
|
||||
|
||||
// printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
|
||||
// dt max is 0.1
|
||||
smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, 0.1);
|
||||
smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0);
|
||||
smd->time = scene->r.cfra;
|
||||
|
||||
if(smd->domain->flags & MOD_SMOKE_HIGHRES)
|
||||
@ -237,7 +237,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive
|
||||
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));
|
||||
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)
|
||||
{
|
||||
@ -713,12 +713,16 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
|
||||
smd->domain->omega = 1.0;
|
||||
smd->domain->alpha = -0.001;
|
||||
smd->domain->beta = 0.1;
|
||||
smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG;
|
||||
smd->domain->time_scale = 1.0;
|
||||
smd->domain->vorticity = 2.0;
|
||||
smd->domain->border_collisions = 1; // vertically non-colliding
|
||||
smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG | MOD_SMOKE_HIGH_SMOOTH;
|
||||
smd->domain->strength = 2.0;
|
||||
smd->domain->noise = MOD_SMOKE_NOISEWAVE;
|
||||
smd->domain->diss_speed = 5;
|
||||
// init view3d buffer
|
||||
smd->domain->viewsettings = 0;
|
||||
// init 3dview buffer
|
||||
|
||||
smd->domain->viewsettings = MOD_SMOKE_VIEW_SHOWBIG;
|
||||
smd->domain->effector_weights = BKE_add_effector_weights(NULL);
|
||||
}
|
||||
else if(smd->type & MOD_SMOKE_TYPE_FLOW)
|
||||
@ -733,6 +737,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
|
||||
/* set some standard values */
|
||||
smd->flow->density = 1.0;
|
||||
smd->flow->temp = 1.0;
|
||||
smd->flow->flags = MOD_SMOKE_FLOW_ABSOLUTE;
|
||||
smd->flow->vel_multi = 1.0;
|
||||
|
||||
smd->flow->psys = NULL;
|
||||
|
||||
@ -872,6 +878,26 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
|
||||
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;
|
||||
|
||||
// initialize temp emission map
|
||||
if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
|
||||
{
|
||||
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
|
||||
for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++)
|
||||
@ -905,33 +931,21 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
|
||||
// heat[index] += sfs->temp * 0.1;
|
||||
// density[index] += sfs->density * 0.1;
|
||||
heat[index] = sfs->temp;
|
||||
density[index] = sfs->density;
|
||||
|
||||
// Add emitter density to temp emission map
|
||||
temp_emission_map[index] = sfs->density;
|
||||
|
||||
|
||||
// Uses particle velocity as initial velocity for smoke
|
||||
if(smd->domain->flags & MOD_SMOKE_INITVELOCITY) {
|
||||
velocity_x[index] = pa->state.vel[0];
|
||||
velocity_y[index] = pa->state.vel[1];
|
||||
velocity_z[index] = pa->state.vel[2];
|
||||
if(sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) {
|
||||
|
||||
velocity_x[index] = pa->state.vel[0]*sfs->vel_multi;
|
||||
velocity_y[index] = pa->state.vel[1]*sfs->vel_multi;
|
||||
velocity_z[index] = pa->state.vel[2]*sfs->vel_multi;
|
||||
|
||||
}
|
||||
|
||||
// obstacle[index] |= 2;
|
||||
// we need different handling for the high-res feature
|
||||
if(bigdensity)
|
||||
{
|
||||
// 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] = sfs->density;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow
|
||||
{
|
||||
@ -955,8 +969,135 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
|
||||
bigdensity[index] = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // 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(smd->domain->wt, bigres);
|
||||
block_size = smd->domain->amplify + 1; // high res block size
|
||||
|
||||
|
||||
// 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++)
|
||||
{
|
||||
|
||||
// neighbour cell emission densities (for high resolution smoke smooth interpolation)
|
||||
float c000, c001, c010, c011, c100, c101, c110, c111;
|
||||
|
||||
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) {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;
|
||||
}
|
||||
|
||||
smoke_turbulence_get_res(smd->domain->wt, bigres);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
} // end of hires loop
|
||||
|
||||
} // end of low res loop
|
||||
|
||||
// free temporary emission map
|
||||
if (temp_emission_map) MEM_freeN(temp_emission_map);
|
||||
|
||||
} // end emission
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -11066,6 +11066,60 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
if (main->versionfile < 253 || (main->versionfile == 253 && main->subversionfile < 1))
|
||||
{
|
||||
Object *ob;
|
||||
|
||||
for(ob = main->object.first; ob; ob = ob->id.next) {
|
||||
ModifierData *md;
|
||||
for(md= ob->modifiers.first; md; md= md->next) {
|
||||
if (md->type == eModifierType_Smoke) {
|
||||
SmokeModifierData *smd = (SmokeModifierData *)md;
|
||||
|
||||
if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
|
||||
{
|
||||
GroupObject *go = NULL;
|
||||
Base *base = NULL;
|
||||
Scene *scene = NULL;
|
||||
|
||||
smd->domain->vorticity = 2.0f;
|
||||
smd->domain->time_scale = 1.0f;
|
||||
|
||||
if(!(smd->domain->flags & (1<<4)))
|
||||
continue;
|
||||
|
||||
/* delete old MOD_SMOKE_INITVELOCITY flag */
|
||||
smd->domain->flags &= ~(1<<4);
|
||||
|
||||
/* for now just add it to all flow objects in the scene */
|
||||
{
|
||||
Object *ob2;
|
||||
for(ob2 = main->object.first; ob2; ob2 = ob2->id.next) {
|
||||
ModifierData *md2;
|
||||
for(md2= ob2->modifiers.first; md2; md2= md2->next) {
|
||||
if (md2->type == eModifierType_Smoke) {
|
||||
SmokeModifierData *smd2 = (SmokeModifierData *)md2;
|
||||
|
||||
if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
|
||||
{
|
||||
smd2->flow->flags |= MOD_SMOKE_FLOW_INITVELOCITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
|
||||
{
|
||||
smd->flow->vel_multi = 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* put compatibility code here until next subversion bump */
|
||||
{
|
||||
}
|
||||
|
@ -450,7 +450,7 @@ void draw_volume(Scene *scene, ARegion *ar, View3D *v3d, Base *base, GPUTexture
|
||||
}
|
||||
|
||||
tend();
|
||||
printf ( "Draw Time: %f\n",( float ) tval() );
|
||||
// printf ( "Draw Time: %f\n",( float ) tval() );
|
||||
|
||||
if(tex_shadow)
|
||||
GPU_texture_unbind(tex_shadow);
|
||||
|
@ -33,8 +33,8 @@
|
||||
#define MOD_SMOKE_HIGHRES (1<<1) /* enable high resolution */
|
||||
#define MOD_SMOKE_DISSOLVE (1<<2) /* let smoke dissolve */
|
||||
#define MOD_SMOKE_DISSOLVE_LOG (1<<3) /* using 1/x for dissolve */
|
||||
#define MOD_SMOKE_INITVELOCITY (1<<4) /* passes particles speed to
|
||||
the smoke*/
|
||||
|
||||
#define MOD_SMOKE_HIGH_SMOOTH (1<<5) /* smoothens high res emission*/
|
||||
|
||||
/* noise */
|
||||
#define MOD_SMOKE_NOISEWAVE (1<<0)
|
||||
@ -47,6 +47,11 @@
|
||||
#define SM_CACHE_LIGHT 0
|
||||
#define SM_CACHE_HEAVY 1
|
||||
|
||||
/* domain border collision */
|
||||
#define SM_BORDER_OPEN 0
|
||||
#define SM_BORDER_VERTICAL 1
|
||||
#define SM_BORDER_CLOSED 2
|
||||
|
||||
typedef struct SmokeDomainSettings {
|
||||
struct SmokeModifierData *smd; /* for fast RNA access */
|
||||
struct FLUID_3D *fluid;
|
||||
@ -84,6 +89,10 @@ typedef struct SmokeDomainSettings {
|
||||
struct PointCache *point_cache[2]; /* definition is in DNA_object_force.h */
|
||||
struct ListBase ptcaches[2];
|
||||
struct EffectorWeights *effector_weights;
|
||||
int border_collisions; /* How domain border collisions are handled */
|
||||
float time_scale;
|
||||
float vorticity;
|
||||
int pad2;
|
||||
} SmokeDomainSettings;
|
||||
|
||||
|
||||
@ -92,18 +101,25 @@ typedef struct SmokeDomainSettings {
|
||||
/* type */
|
||||
#define MOD_SMOKE_FLOW_TYPE_OUTFLOW (1<<1)
|
||||
|
||||
/* flags */
|
||||
#define MOD_SMOKE_FLOW_ABSOLUTE (1<<1) /*old style emission*/
|
||||
#define MOD_SMOKE_FLOW_INITVELOCITY (1<<2) /* passes particles speed to
|
||||
the smoke*/
|
||||
|
||||
|
||||
typedef struct SmokeFlowSettings {
|
||||
struct SmokeModifierData *smd; /* for fast RNA access */
|
||||
struct ParticleSystem *psys;
|
||||
float density;
|
||||
float temp; /* delta temperature (temp - ambient temp) */
|
||||
float velocity[3]; /* UNUSED, velocity taken from particles */
|
||||
float velocity[2]; /* UNUSED, velocity taken from particles */
|
||||
float vel_multi; // Multiplier for particle velocity
|
||||
float vgrp_heat_scale[2]; /* min and max scaling for vgroup_heat */
|
||||
short vgroup_flow; /* where inflow/outflow happens - red=1=action */
|
||||
short vgroup_density;
|
||||
short vgroup_heat;
|
||||
short type; /* inflow =0 or outflow = 1 */
|
||||
int pad;
|
||||
int flags; /* absolute emission etc*/
|
||||
} SmokeFlowSettings;
|
||||
|
||||
/*
|
||||
|
@ -87,10 +87,15 @@ EnumPropertyItem modifier_type_items[] ={
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_smoke_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_pointcache.h"
|
||||
|
||||
static void rna_UVProject_projectors_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
@ -216,6 +221,9 @@ static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
SmokeModifierData *smd= (SmokeModifierData *)ptr->data;
|
||||
Object *ob= (Object*)ptr->id.data;
|
||||
ParticleSystemModifierData *psmd = NULL;
|
||||
ParticleSystem *psys = NULL;
|
||||
ParticleSettings *part = NULL;
|
||||
|
||||
// nothing changed
|
||||
if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
|
||||
@ -226,9 +234,32 @@ static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
|
||||
switch (smd->type) {
|
||||
case MOD_SMOKE_TYPE_DOMAIN:
|
||||
ob->dt = OB_WIRE;
|
||||
ob->dt = OB_BOUNDBOX;
|
||||
break;
|
||||
case MOD_SMOKE_TYPE_FLOW:
|
||||
for(psys=ob->particlesystem.first; psys; psys=psys->next)
|
||||
if(psys->part->type == PART_EMITTER)
|
||||
break;
|
||||
if(ob->type == OB_MESH && !psys) {
|
||||
/* add particle system */
|
||||
psmd = object_add_particle_system(scene, ob, NULL);
|
||||
if(psmd)
|
||||
{
|
||||
psys = psmd->psys;
|
||||
part = psys->part;
|
||||
part->flag |= PART_UNBORN;
|
||||
part->lifetime = 1.0f;
|
||||
part->sta = 1.0f;
|
||||
part->end = 250.0f;
|
||||
part->ren_as = PART_DRAW_NOT;
|
||||
part->phystype = PART_PHYS_NO;
|
||||
sprintf(psys->name, "SmokeParticles");
|
||||
psys->recalc |= (PSYS_RECALC_RESET|PSYS_RECALC_PHYS);
|
||||
DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA);
|
||||
}
|
||||
}
|
||||
if(smd->flow)
|
||||
smd->flow->psys = psys;
|
||||
case MOD_SMOKE_TYPE_COLL:
|
||||
case 0:
|
||||
default:
|
||||
|
@ -120,6 +120,12 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
{SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem smoke_domain_colli_items[] = {
|
||||
{SM_BORDER_OPEN, "BORDEROPEN", 0, "Open", "Smoke doesn't collide with any border"},
|
||||
{SM_BORDER_VERTICAL, "BORDERVERTICAL", 0, "Vertically Open", "Smoke doesn't collide with top and bottom sides"},
|
||||
{SM_BORDER_CLOSED, "BORDERCLOSED", 0, "Collide All", "Smoke collides with every side"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna = RNA_def_struct(brna, "SmokeDomainSettings", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Domain Settings", "Smoke domain settings");
|
||||
RNA_def_struct_sdna(srna, "SmokeDomainSettings");
|
||||
@ -192,8 +198,8 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "strength");
|
||||
RNA_def_property_range(prop, 1.0, 10.0);
|
||||
RNA_def_property_ui_range(prop, 1.0, 10.0, 1, 2);
|
||||
RNA_def_property_range(prop, 0.0, 10.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 2);
|
||||
RNA_def_property_ui_text(prop, "Strength", "Strength of wavelet noise");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
@ -204,11 +210,6 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "initial_velocity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_INITVELOCITY);
|
||||
RNA_def_property_ui_text(prop, "Initial Velocity", "Smoke inherits it's velocity from the emitter particle");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "dissolve_smoke", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE);
|
||||
RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time");
|
||||
@ -241,12 +242,36 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "smoke_domain_colli", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "border_collisions");
|
||||
RNA_def_property_enum_items(prop, smoke_domain_colli_items);
|
||||
RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "EffectorWeights");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Effector Weights", "");
|
||||
|
||||
prop= RNA_def_property(srna, "smoothemitter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGH_SMOOTH);
|
||||
RNA_def_property_ui_text(prop, "Smooth Emitter", "Smoothens emitted smoke to avoid blockiness.");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "time_scale");
|
||||
RNA_def_property_range(prop, 0.2, 1.5);
|
||||
RNA_def_property_ui_range(prop, 0.2, 1.5, 0.02, 5);
|
||||
RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "vorticity");
|
||||
RNA_def_property_range(prop, 0.01, 4.0);
|
||||
RNA_def_property_ui_range(prop, 0.01, 4.0, 0.02, 5);
|
||||
RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence/rotation in fluid.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
}
|
||||
|
||||
static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
@ -284,6 +309,23 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "type", MOD_SMOKE_FLOW_TYPE_OUTFLOW);
|
||||
RNA_def_property_ui_text(prop, "Outflow", "Deletes smoke from simulation");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "absolute", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_ABSOLUTE);
|
||||
RNA_def_property_ui_text(prop, "Absolute Density", "Only allows given density value in emitter area.");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "initial_velocity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_INITVELOCITY);
|
||||
RNA_def_property_ui_text(prop, "Initial Velocity", "Smoke inherits it's velocity from the emitter particle");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "velocity_multiplier", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "vel_multi");
|
||||
RNA_def_property_range(prop, -2.0, 2.0);
|
||||
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
|
||||
RNA_def_property_ui_text(prop, "Multiplier", "Multiplier to adjust velocity passed to smoke");
|
||||
RNA_def_property_update(prop, 0, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_smoke_coll_settings(BlenderRNA *brna)
|
||||
|
Loading…
Reference in New Issue
Block a user