diff options
-rw-r--r-- | intern/smoke/extern/smoke_API.h | 6 | ||||
-rw-r--r-- | intern/smoke/intern/FLUID_3D.cpp | 25 | ||||
-rw-r--r-- | intern/smoke/intern/FLUID_3D.h | 5 | ||||
-rw-r--r-- | intern/smoke/intern/FLUID_3D_STATIC.cpp | 4 | ||||
-rw-r--r-- | intern/smoke/intern/smoke_API.cpp | 102 | ||||
-rw-r--r-- | release/ui/buttons_physics_smoke.py | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/smoke.c | 81 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_smoke_types.h | 15 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_smoke.c | 19 |
9 files changed, 226 insertions, 39 deletions
diff --git a/intern/smoke/extern/smoke_API.h b/intern/smoke/extern/smoke_API.h index 52df3891ca0..f0dba3cc7a4 100644 --- a/intern/smoke/extern/smoke_API.h +++ b/intern/smoke/extern/smoke_API.h @@ -36,7 +36,7 @@ struct FLUID_3D *smoke_init(int *res, float *p0, float dt); void smoke_free(struct FLUID_3D *fluid); void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta); -void smoke_step(struct FLUID_3D *fluid); +void smoke_step(struct FLUID_3D *fluid, size_t framenr); float *smoke_get_density(struct FLUID_3D *fluid); float *smoke_get_heat(struct FLUID_3D *fluid); @@ -49,6 +49,8 @@ unsigned char *smoke_get_obstacle(struct FLUID_3D *fluid); size_t smoke_get_index(int x, int max_x, int y, int max_y, int z); size_t smoke_get_index2d(int x, int max_x, int y); +void smoke_dissolve(struct FLUID_3D *fluid, int speed, int log); + // wavelet turbulence functions struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype); void smoke_turbulence_free(struct WTURBULENCE *wt); @@ -59,6 +61,8 @@ void smoke_turbulence_get_res(struct WTURBULENCE *wt, int *res); void smoke_turbulence_set_noise(struct WTURBULENCE *wt, int type); void smoke_initWaveletBlenderRNA(struct WTURBULENCE *wt, float *strength); +void smoke_dissolve_wavelet(struct WTURBULENCE *wt, int speed, int log); + #ifdef __cplusplus } #endif diff --git a/intern/smoke/intern/FLUID_3D.cpp b/intern/smoke/intern/FLUID_3D.cpp index 0e1fe637bb8..8f72b1da536 100644 --- a/intern/smoke/intern/FLUID_3D.cpp +++ b/intern/smoke/intern/FLUID_3D.cpp @@ -101,6 +101,11 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dt) : _h = new float[_totalCells]; _Precond = new float[_totalCells]; + _spectrum = new unsigned char[256*4*16*16]; + + + // DG TODO: check if alloc went fine + for (int x = 0; x < _totalCells; x++) { _density[x] = 0.0f; @@ -202,6 +207,8 @@ FLUID_3D::~FLUID_3D() if (_obstacles) delete[] _obstacles; // if (_wTurbulence) delete _wTurbulence; + if(_spectrum) delete[] _spectrum; + printf("deleted fluid\n"); } @@ -219,7 +226,10 @@ void FLUID_3D::step() { // wipe forces for (int i = 0; i < _totalCells; i++) + { _xForce[i] = _yForce[i] = _zForce[i] = 0.0f; + _obstacles[i] &= ~2; + } wipeBoundaries(); @@ -683,16 +693,17 @@ void FLUID_3D::advectMacCormack() const float dt0 = _dt / _dx; // use force arrays as temp arrays - for (int x = 0; x < _totalCells; x++) - _xForce[x] = _yForce[x] = 0.0; + for (int x = 0; x < _totalCells; x++) + _xForce[x] = _yForce[x] = 0.0; + float* t1 = _xForce; float* t2 = _yForce; - advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, t1,t2, res, NULL); - advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, t1,t2, res, NULL); - advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, t1,t2, res, NULL); - advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, t1,t2, res, NULL); - advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, t1,t2, res, NULL); + advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, t1,t2, res, _obstacles); + advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, t1,t2, res, _obstacles); + advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, t1,t2, res, _obstacles); + advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, t1,t2, res, _obstacles); + advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, t1,t2, res, _obstacles); if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocity, res); else setZeroX(_xVelocity, res); diff --git a/intern/smoke/intern/FLUID_3D.h b/intern/smoke/intern/FLUID_3D.h index 614ea4e46de..f228abc05a9 100644 --- a/intern/smoke/intern/FLUID_3D.h +++ b/intern/smoke/intern/FLUID_3D.h @@ -99,6 +99,7 @@ class FLUID_3D float* _h; float* _Precond; unsigned char* _obstacles; + unsigned char *_spectrum; // CG fields float* _residual; @@ -161,13 +162,13 @@ class FLUID_3D static void advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz, float* oldField, float* newField, Vec3Int res); static void advectFieldMacCormack(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, - float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const float* obstacles); + float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const unsigned char* obstacles); // maccormack helper functions static void clampExtrema(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, float* oldField, float* newField, Vec3Int res); static void clampOutsideRays(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, - float* oldField, float* newField, Vec3Int res, const float* obstacles, const float *oldAdvection); + float* oldField, float* newField, Vec3Int res, const unsigned char* obstacles, const float *oldAdvection); // output helper functions // static void writeImageSliceXY(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.); diff --git a/intern/smoke/intern/FLUID_3D_STATIC.cpp b/intern/smoke/intern/FLUID_3D_STATIC.cpp index ebb351dc323..4474129beea 100644 --- a/intern/smoke/intern/FLUID_3D_STATIC.cpp +++ b/intern/smoke/intern/FLUID_3D_STATIC.cpp @@ -338,7 +338,7 @@ void FLUID_3D::advectFieldSemiLagrange(const float dt, const float* velx, const // comments are the pseudocode from selle's paper ////////////////////////////////////////////////////////////////////// void FLUID_3D::advectFieldMacCormack(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, - float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const float* obstacles) + float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const unsigned char* obstacles) { float* phiHatN = temp1; float* phiHatN1 = temp2; @@ -459,7 +459,7 @@ void FLUID_3D::clampExtrema(const float dt, const float* velx, const float* vely // incorrect ////////////////////////////////////////////////////////////////////// void FLUID_3D::clampOutsideRays(const float dt, const float* velx, const float* vely, const float* velz, - float* oldField, float* newField, Vec3Int res, const float* obstacles, const float *oldAdvection) + float* oldField, float* newField, Vec3Int res, const unsigned char* obstacles, const float *oldAdvection) { const int sx= res[0]; const int sy= res[1]; diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp index c4dd23146c2..7f90971f14d 100644 --- a/intern/smoke/intern/smoke_API.cpp +++ b/intern/smoke/intern/smoke_API.cpp @@ -63,7 +63,18 @@ extern "C" void smoke_turbulence_free(WTURBULENCE *wt) wt = NULL; } -extern "C" void smoke_step(FLUID_3D *fluid) +extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */) +{ + // // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1]; + return x + y * max_x + z * max_x*max_y; +} + +extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z, int max_z */) +{ + return x + y * max_x; +} + +extern "C" void smoke_step(FLUID_3D *fluid, size_t framenr) { fluid->step(); } @@ -79,6 +90,84 @@ extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta) fluid->initBlenderRNA(alpha, beta); } +extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log) +{ + float *density = fluid->_density; + float *densityOld = fluid->_densityOld; + float *heat = fluid->_heat; + + if(log) + { + /* max density/speed = dydx */ + float dydx = 1.0 / (float)speed; + + for(size_t i = 0; i < fluid->_xRes * fluid->_yRes * fluid->_zRes; i++) + { + density[i] *= (1.0 - dydx); + + if(density[i] < 0.0f) + density[i] = 0.0f; + + heat[i] *= (1.0 - dydx); + + if(heat[i] < 0.0f) + heat[i] = 0.0f; + } + } + else // linear falloff + { + /* max density/speed = dydx */ + float dydx = 1.0 / (float)speed; + + for(size_t i = 0; i < fluid->_xRes * fluid->_yRes * fluid->_zRes; i++) + { + density[i] -= dydx; + + if(density[i] < 0.0f) + density[i] = 0.0f; + + heat[i] -= dydx; + + if(heat[i] < 0.0f) + heat[i] = 0.0f; + + } + } +} + +extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log) +{ + float *density = wt->getDensityBig(); + Vec3Int r = wt->getResBig(); + + if(log) + { + /* max density/speed = dydx */ + float dydx = 1.0 / (float)speed; + + for(size_t i = 0; i < r[0] * r[1] * r[2]; i++) + { + density[i] *= (1.0 - dydx); + + if(density[i] < 0.0f) + density[i] = 0.0f; + } + } + else // linear falloff + { + /* max density/speed = dydx */ + float dydx = 1.0 / (float)speed; + + for(size_t i = 0; i < r[0] * r[1] * r[2]; i++) + { + density[i] -= dydx; + + if(density[i] < 0.0f) + density[i] = 0.0f; + } + } +} + extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength) { wt->initBlenderRNA(strength); @@ -134,17 +223,6 @@ extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid) return fluid->_obstacles; } -extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */) -{ - // // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1]; - return x + y * max_x + z * max_x*max_y; -} - -extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z, int max_z */) -{ - return x + y * max_x; -} - extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type) { wt->setNoise(type); diff --git a/release/ui/buttons_physics_smoke.py b/release/ui/buttons_physics_smoke.py index caafb3d58f2..5471030883e 100644 --- a/release/ui/buttons_physics_smoke.py +++ b/release/ui/buttons_physics_smoke.py @@ -72,6 +72,14 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel): sub = split.column() split = layout.split() + col = split.column() + col.itemR(md.domain_settings, "dissolve_smoke") + sub = col.column() + sub.active = md.domain_settings.dissolve_smoke + sub.itemR(md.domain_settings, "dissolve_speed") + sub.itemR(md.domain_settings, "dissolve_smoke_log") + + split = layout.split() col = split.column() col.itemL(text="Flow Group:") diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 8224f0dd3f3..9d4c75245cf 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -207,7 +207,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, 2.5 / FPS); + smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, 0.1); smd->domain->wt = smoke_turbulence_init(smd->domain->res, (smd->domain->flags & MOD_SMOKE_HIGHRES) ? (smd->domain->amplify + 1) : 0, smd->domain->noise); smd->time = scene->r.cfra; smd->domain->firstframe = smd->time; @@ -228,6 +228,17 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive // update particle lifetime to be one frame // smd->flow->psys->part->lifetime = scene->r.efra + 1; +/* + if(!smd->flow->bvh) + { + // smd->flow->bvh = MEM_callocN(sizeof(BVHTreeFromMesh), "smoke_bvhfromfaces"); + // bvhtree_from_mesh_faces(smd->flow->bvh, dm, 0.0, 2, 6); + + // copy obmat + // Mat4CpyMat4(smd->flow->mat, ob->obmat); + // Mat4CpyMat4(smd->flow->mat_old, ob->obmat); + } +*/ return 1; } @@ -527,6 +538,14 @@ void smokeModifier_freeFlow(SmokeModifierData *smd) { if(smd->flow) { +/* + if(smd->flow->bvh) + { + free_bvhtree_from_mesh(smd->flow->bvh); + MEM_freeN(smd->flow->bvh); + } + smd->flow->bvh = NULL; +*/ MEM_freeN(smd->flow); smd->flow = NULL; } @@ -604,7 +623,14 @@ void smokeModifier_reset(struct SmokeModifierData *smd) } else if(smd->flow) { - + /* + if(smd->flow->bvh) + { + free_bvhtree_from_mesh(smd->flow->bvh); + MEM_freeN(smd->flow->bvh); + } + smd->flow->bvh = NULL; + */ } else if(smd->coll) { @@ -662,11 +688,11 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->omega = 1.0; smd->domain->alpha = -0.001; smd->domain->beta = 0.1; - smd->domain->flags = 0; // MOD_SMOKE_DISSOLVE_INV; + smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG; smd->domain->strength = 2.0; smd->domain->noise = MOD_SMOKE_NOISEWAVE; smd->domain->visibility = 1; - // smd->domain->diss_speed = 50; + smd->domain->diss_speed = 5; // init 3dview buffer smd->domain->tvox = NULL; @@ -723,6 +749,12 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM { // XXX TODO smd->time = scene->r.cfra; + + // rigid movement support + /* + Mat4CpyMat4(smd->flow->mat_old, smd->flow->mat); + Mat4CpyMat4(smd->flow->mat, ob->obmat); + */ } else if(scene->r.cfra < smd->time) { @@ -763,8 +795,13 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM tstart(); - // if(sds->flags & MOD_SMOKE_DISSOLVE) - // smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG, sds->flags & MOD_SMOKE_DISSOLVE_INV); + if(sds->flags & MOD_SMOKE_DISSOLVE) + { + smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); + + if(sds->wt) + smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); + } /* reset view for new frame */ if(sds->viewsettings < MOD_SMOKE_VIEW_USEBIG) @@ -830,7 +867,10 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM float *velocity_x = smoke_get_velocity_x(sds->fluid); float *velocity_y = smoke_get_velocity_y(sds->fluid); float *velocity_z = smoke_get_velocity_z(sds->fluid); - int bigres[3]; + unsigned char *obstacle = smoke_get_obstacle(sds->fluid); + int bigres[3]; + + printf("found flow psys\n"); // mostly copied from particle code for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) @@ -867,15 +907,20 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM // 2. set cell values (heat, density and velocity) index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) // this is inflow + if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index] & 2)) // this is inflow { + // heat[index] += sfs->temp * 0.1; + // density[index] += sfs->density * 0.1; + heat[index] = sfs->temp; density[index] = sfs->density; + /* velocity_x[index] = pa->state.vel[0]; velocity_y[index] = pa->state.vel[1]; velocity_z[index] = pa->state.vel[2]; */ + obstacle[index] |= 2; // we need different handling for the high-res feature if(bigdensity) @@ -894,7 +939,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } } } - else // outflow + else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow { heat[index] = 0.f; density[index] = 0.f; @@ -920,7 +965,21 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } } } - } + } + else + { + /* + for() + { + // no psys + BVHTreeNearest nearest; + + nearest.index = -1; + nearest.dist = FLT_MAX; + + BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh); + }*/ + } } } @@ -1058,7 +1117,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM smd->time = scene->r.cfra; // simulate the actual smoke (c++ code in intern/smoke) - smoke_step(sds->fluid); + smoke_step(sds->fluid, smd->time); if(sds->wt) smoke_turbulence_step(sds->wt, sds->fluid); diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index 7d64862ba32..c7f49d3ddd2 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -30,7 +30,10 @@ #define DNA_SMOKE_TYPES_H /* flags */ -#define MOD_SMOKE_HIGHRES (1<<1) +#define MOD_SMOKE_HIGHRES (1<<1) /* compute high resolution */ +#define MOD_SMOKE_DISSOLVE (1<<2) /* let smoke dissolve */ +#define MOD_SMOKE_DISSOLVE_LOG (1<<3) /* using 1/x for dissolve */ + /* noise */ #define MOD_SMOKE_NOISEWAVE (1<<0) #define MOD_SMOKE_NOISEFFT (1<<1) @@ -75,8 +78,8 @@ typedef struct SmokeDomainSettings { int viewsettings; int max_textures; short noise; /* noise type: wave, curl, anisotropic */ - short pad2; - int pad; + short diss_percent; + int diss_speed;/* in frames */ float strength; struct WTURBULENCE *wt; // WTURBULENCE object, if active } SmokeDomainSettings; @@ -101,6 +104,12 @@ typedef struct SmokeFlowSettings { int pad; } SmokeFlowSettings; +/* + struct BVHTreeFromMesh *bvh; + float mat[4][4]; + float mat_old[4][4]; + */ + /* collision objects (filled with smoke) */ typedef struct SmokeCollSettings { struct SmokeModifierData *smd; /* for fast RNA access */ diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 1cd98ca3a9c..6f1babb495a 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -210,10 +210,27 @@ 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, -5.0, 5.0); + RNA_def_property_range(prop, 1.0, 10.0); RNA_def_property_ui_range(prop, 1.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"); + + prop= RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "diss_speed"); + RNA_def_property_range(prop, 1.0, 100.0); + RNA_def_property_ui_range(prop, 1.0, 1000.0, 1, 0); + RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed"); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, 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."); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL); + + prop= RNA_def_property(srna, "dissolve_smoke_log", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE_LOG); + RNA_def_property_ui_text(prop, "Logarithmic dissolve", "Using 1/x "); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL); } static void rna_def_smoke_flow_settings(BlenderRNA *brna) |