From 967d25ac1c269f28ab793f7c63edb9fd540dd5cf Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 27 Jul 2010 14:53:20 +0000 Subject: =?UTF-8?q?Smoke=20Patch=20+=20additions:=20a)=20Applying=20patch?= =?UTF-8?q?=20#22765=20by=20Miika=20H=C3=A4m=C3=A4l=C3=A4inen=20(domain=20?= =?UTF-8?q?border=20collision=20settings,=20vorticity=20settings,=20time?= =?UTF-8?q?=20scale,=20non=20absolute=20density,=20smooth=20high=20res=20e?= =?UTF-8?q?mitter,=20initial=20velocity=20multiplier,=20high=20res=20stren?= =?UTF-8?q?gth=20available=20to=20be=20set=20to=200),=20b)=20Additions=20b?= =?UTF-8?q?y=20me:=20--Initial=20velocity=20is=20now=20per=20flow=20object?= =?UTF-8?q?,=20not=20per=20domain;=20--Using=20boundingbox=20as=20standard?= =?UTF-8?q?=20display=20mode=20for=20domains=20(was=20wire=20before);=20--?= =?UTF-8?q?When=20adding=20a=20flow=20object,=20an=20initial=20nice=20Smok?= =?UTF-8?q?eParticle=20system=20is=20added=20too=20with=20nice=20initial?= =?UTF-8?q?=20settings=20(life=3D1,=20no=5Frender,=20unborn,=20etc)=20fitt?= =?UTF-8?q?ing=20smoke=20simulation;=20--Adaptive=20timesteps=20introduced?= =?UTF-8?q?=20to=20the=20smoke=20sim=20(depending=20on=20the=20magnitude?= =?UTF-8?q?=20of=20the=20velocity)=20because=20it=20was=20quite=20unstable?= =?UTF-8?q?=20when=20used=20for=20fire=20simulations,=20still=20needs=20to?= =?UTF-8?q?=20be=20tested=20and=20will=20also=20slow=20down=20some=20simul?= =?UTF-8?q?ations.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- intern/smoke/extern/smoke_API.h | 4 +- intern/smoke/intern/FLUID_3D.cpp | 197 +++++++++++++++++---- intern/smoke/intern/FLUID_3D.h | 23 ++- intern/smoke/intern/smoke_API.cpp | 39 ++++- release/scripts/ui/properties_physics_smoke.py | 35 ++-- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/intern/smoke.c | 207 +++++++++++++++++++---- source/blender/blenloader/intern/readfile.c | 54 ++++++ source/blender/editors/space_view3d/drawvolume.c | 2 +- source/blender/makesdna/DNA_smoke_types.h | 24 ++- source/blender/makesrna/intern/rna_modifier.c | 33 +++- source/blender/makesrna/intern/rna_smoke.c | 56 +++++- 12 files changed, 571 insertions(+), 105 deletions(-) diff --git a/intern/smoke/extern/smoke_API.h b/intern/smoke/extern/smoke_API.h index 3e296fd7c90..d1012eef76e 100644 --- a/intern/smoke/extern/smoke_API.h +++ b/intern/smoke/extern/smoke_API.h @@ -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); diff --git a/intern/smoke/intern/FLUID_3D.cpp b/intern/smoke/intern/FLUID_3D.cpp index 4ac960b5ef0..05fbb918d24 100644 --- a/intern/smoke/intern/FLUID_3D.cpp +++ b/intern/smoke/intern/FLUID_3D.cpp @@ -35,23 +35,15 @@ #include #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); diff --git a/intern/smoke/intern/FLUID_3D.h b/intern/smoke/intern/FLUID_3D.h index 6ca50b2c032..c244180ee57 100644 --- a/intern/smoke/intern/FLUID_3D.h +++ b/intern/smoke/intern/FLUID_3D.h @@ -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; diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp index 427f4d53171..23c12c17014 100644 --- a/intern/smoke/intern/smoke_API.cpp +++ b/intern/smoke/intern/smoke_API.cpp @@ -33,10 +33,10 @@ #include // 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) diff --git a/release/scripts/ui/properties_physics_smoke.py b/release/scripts/ui/properties_physics_smoke.py index c5357c515de..ffc9caec979 100644 --- a/release/scripts/ui/properties_physics_smoke.py +++ b/release/scripts/ui/properties_physics_smoke.py @@ -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: diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 4e299accffc..189cd61d5a8 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -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 diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 7424026354a..193512b11dc 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -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; @@ -862,7 +868,7 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) { ParticleSystem *psys = sfs->psys; ParticleSettings *part=psys->part; - ParticleData *pa = NULL; + ParticleData *pa = NULL; int p = 0; float *density = smoke_get_density(sds->fluid); float *bigdensity = smoke_turbulence_get_density(sds->wt); @@ -871,7 +877,27 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) 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]; + 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; ires[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; ptotpart; 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]; - } - - // 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; + if(sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) { - smoke_turbulence_get_res(smd->domain->wt, bigres); + 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; + + } + - 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 { @@ -954,9 +968,136 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) 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; } - } - } // particles loop - } + } + } + } // 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 { @@ -970,7 +1111,7 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh); }*/ - } + } } } if(sds->fluid_group) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 71a9fc2e844..3227d4b25bb 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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 */ { } diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 420f2d77fed..79b22f41e30 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -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); diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index 46e5c10be3b..b8be51b378f 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -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; /* diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index dfd9c2f434c..dcf20a3531d 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -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: diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index d4ff98e9701..56049ea15ce 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -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) -- cgit v1.2.3