From 14f62c132136ba8696cf204fb421ba4f10414a6a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 8 Oct 2009 10:18:14 +0000 Subject: [PATCH] Smoke: * Enable external forces like e.g. wind --- intern/smoke/extern/smoke_API.h | 4 ++ intern/smoke/intern/FLUID_3D.cpp | 14 ++--- intern/smoke/intern/smoke_API.cpp | 15 +++++ release/scripts/ui/buttons_physics_smoke.py | 15 ++++- source/blender/blenkernel/intern/smoke.c | 58 ++++++++++++++++---- source/blender/blenloader/intern/readfile.c | 7 +++ source/blender/blenloader/intern/writefile.c | 3 + source/blender/makesdna/DNA_smoke_types.h | 3 +- source/blender/makesrna/intern/rna_smoke.c | 5 ++ 9 files changed, 105 insertions(+), 19 deletions(-) diff --git a/intern/smoke/extern/smoke_API.h b/intern/smoke/extern/smoke_API.h index 5607df70cf3..ea106c81303 100644 --- a/intern/smoke/extern/smoke_API.h +++ b/intern/smoke/extern/smoke_API.h @@ -50,6 +50,10 @@ float *smoke_get_velocity_x(struct FLUID_3D *fluid); float *smoke_get_velocity_y(struct FLUID_3D *fluid); float *smoke_get_velocity_z(struct FLUID_3D *fluid); +float *smoke_get_force_x(struct FLUID_3D *fluid); +float *smoke_get_force_y(struct FLUID_3D *fluid); +float *smoke_get_force_z(struct FLUID_3D *fluid); + 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); diff --git a/intern/smoke/intern/FLUID_3D.cpp b/intern/smoke/intern/FLUID_3D.cpp index bb2227801c7..729d73bb4f3 100644 --- a/intern/smoke/intern/FLUID_3D.cpp +++ b/intern/smoke/intern/FLUID_3D.cpp @@ -184,13 +184,6 @@ void FLUID_3D::step() { // addSmokeTestCase(_density, _res); // addSmokeTestCase(_heat, _res); - - // wipe forces - for (int i = 0; i < _totalCells; i++) - { - _xForce[i] = _yForce[i] = _zForce[i] = 0.0f; - // _obstacles[i] &= ~2; - } wipeBoundaries(); @@ -232,6 +225,13 @@ void FLUID_3D::step() // todo xxx dg: only clear obstacles, not boundaries // memset(_obstacles, 0, sizeof(unsigned char)*_xRes*_yRes*_zRes); + + // wipe forces + // for external forces we can't do it at the beginning of this function but at the end + for (int i = 0; i < _totalCells; i++) + { + _xForce[i] = _yForce[i] = _zForce[i] = 0.0f; + } } ////////////////////////////////////////////////////////////////////// diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp index 67df6e805d8..2d1d590fcc0 100644 --- a/intern/smoke/intern/smoke_API.cpp +++ b/intern/smoke/intern/smoke_API.cpp @@ -235,6 +235,21 @@ extern "C" float *smoke_get_velocity_z(FLUID_3D *fluid) return fluid->_zVelocity; } +extern "C" float *smoke_get_force_x(FLUID_3D *fluid) +{ + return fluid->_xForce; +} + +extern "C" float *smoke_get_force_y(FLUID_3D *fluid) +{ + return fluid->_yForce; +} + +extern "C" float *smoke_get_force_z(FLUID_3D *fluid) +{ + return fluid->_zForce; +} + extern "C" float *smoke_turbulence_get_density(WTURBULENCE *wt) { return wt ? wt->getDensityBig() : NULL; diff --git a/release/scripts/ui/buttons_physics_smoke.py b/release/scripts/ui/buttons_physics_smoke.py index 1541b0bae14..53a7ec9c10c 100644 --- a/release/scripts/ui/buttons_physics_smoke.py +++ b/release/scripts/ui/buttons_physics_smoke.py @@ -1,7 +1,8 @@ import bpy -from buttons_particle import point_cache_ui +from buttons_physics_common import point_cache_ui +from buttons_physics_common import effector_weights_ui class PhysicButtonsPanel(bpy.types.Panel): __space_type__ = 'PROPERTIES' @@ -171,8 +172,20 @@ class PHYSICS_PT_smoke_cache_highres(PhysicButtonsPanel): cache = md.point_cache_high point_cache_ui(self, cache, cache.baked==False, 0, 1) + +class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel): + __label__ = "Smoke Field Weights" + __default_closed__ = True + + def poll(self, context): + return (context.smoke) + + def draw(self, context): + domain = context.smoke.domain_settings + effector_weights_ui(self, domain.effector_weights) bpy.types.register(PHYSICS_PT_smoke) +bpy.types.register(PHYSICS_PT_smoke_field_weights) bpy.types.register(PHYSICS_PT_smoke_cache) bpy.types.register(PHYSICS_PT_smoke_highres) bpy.types.register(PHYSICS_PT_smoke_groups) diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index f1fae4fa678..c1e79651c59 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -53,6 +53,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" #include "BKE_DerivedMesh.h" +#include "BKE_effect.h" #include "BKE_modifier.h" #include "BKE_particle.h" #include "BKE_pointcache.h" @@ -547,6 +548,10 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd) if(smd->domain->wt) smoke_turbulence_free(smd->domain->wt); + if(smd->domain->effector_weights) + MEM_freeN(smd->domain->effector_weights); + smd->domain->effector_weights = NULL; + BKE_ptcache_free_list(&(smd->domain->ptcaches[0])); smd->domain->point_cache[0] = NULL; BKE_ptcache_free_list(&(smd->domain->ptcaches[1])); @@ -714,6 +719,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->diss_speed = 5; // init 3dview buffer smd->domain->viewsettings = 0; + smd->domain->effector_weights = BKE_add_effector_weights(NULL); } else if(smd->type & MOD_SMOKE_TYPE_FLOW) { @@ -938,21 +944,53 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) } // do effectors - /* - if(sds->eff_group) { - for(go = sds->eff_group->gobject.first; go; go = go->next) + ListBase *effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights); + + if(effectors) { - if(go->ob) - { - if(ob->pd) - { - - } + float *density = smoke_get_density(sds->fluid); + float *force_x = smoke_get_force_x(sds->fluid); + float *force_y = smoke_get_force_y(sds->fluid); + float *force_z = smoke_get_force_z(sds->fluid); + float *velocity_x = smoke_get_velocity_x(sds->fluid); + float *velocity_y = smoke_get_velocity_y(sds->fluid); + float *velocity_z = smoke_get_velocity_z(sds->fluid); + int x, y, z; + + // precalculate wind forces + for(x = 0; x < sds->res[0]; x++) + for(y = 0; y < sds->res[1]; y++) + for(z = 0; z < sds->res[2]; z++) + { + EffectedPoint epoint; + float voxelCenter[3], vel[3], retvel[3]; + + unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z); + + if(density[index] < FLT_EPSILON) + continue; + + vel[0] = velocity_x[index]; + vel[1] = velocity_y[index]; + vel[2] = velocity_z[index]; + + voxelCenter[0] = sds->p0[0] + sds->dx * x + sds->dx * 0.5; + voxelCenter[1] = sds->p0[1] + sds->dx * y + sds->dx * 0.5; + voxelCenter[2] = sds->p0[2] + sds->dx * z + sds->dx * 0.5; + + pd_point_from_loc(scene, voxelCenter, vel, index, &epoint); + pdDoEffectors(effectors, NULL, sds->effector_weights, &epoint, retvel, NULL); + + // TODO dg - do in force! + force_x[index] += MIN2(MAX2(-1.0, retvel[0] * 0.002), 1.0); + force_y[index] += MIN2(MAX2(-1.0, retvel[1] * 0.002), 1.0); + force_z[index] += MIN2(MAX2(-1.0, retvel[2] * 0.002), 1.0); } } + + pdEndEffectors(&effectors); } - */ // do collisions if(1) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 989e2b3fa9e..a832cae161b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3655,6 +3655,8 @@ static void lib_link_object(FileData *fd, Main *main) smd->domain->coll_group = newlibadr_us(fd, ob->id.lib, smd->domain->coll_group); smd->domain->eff_group = newlibadr_us(fd, ob->id.lib, smd->domain->eff_group); smd->domain->fluid_group = newlibadr_us(fd, ob->id.lib, smd->domain->fluid_group); + + smd->domain->effector_weights->group = newlibadr(fd, ob->id.lib, smd->domain->effector_weights->group); } } @@ -3784,6 +3786,11 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) smd->domain->tex_shadow = NULL; smd->domain->tex_wt = NULL; + if(smd->domain->effector_weights) + smd->domain->effector_weights = newdataadr(fd, smd->domain->effector_weights); + else + smd->domain->effector_weights = BKE_add_effector_weights(NULL); + direct_link_pointcache_list(fd, &(smd->domain->ptcaches[0]), &(smd->domain->point_cache[0])); direct_link_pointcache_list(fd, &(smd->domain->ptcaches[1]), &(smd->domain->point_cache[1])); } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index c92c0909d3b..25cbd4b65e7 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1153,7 +1153,10 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) SmokeModifierData *smd = (SmokeModifierData*) md; if(smd->type & MOD_SMOKE_TYPE_DOMAIN) + { writestruct(wd, DATA, "SmokeDomainSettings", 1, smd->domain); + writestruct(wd, DATA, "EffectorWeights", 1, smd->domain->effector_weights); + } else if(smd->type & MOD_SMOKE_TYPE_FLOW) writestruct(wd, DATA, "SmokeFlowSettings", 1, smd->flow); else if(smd->type & MOD_SMOKE_TYPE_COLL) diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index 4e4714cdaa1..6cf308aa0ad 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -45,7 +45,7 @@ typedef struct SmokeDomainSettings { struct SmokeModifierData *smd; /* for fast RNA access */ struct FLUID_3D *fluid; struct Group *fluid_group; - struct Group *eff_group; // effector group for e.g. wind force + struct Group *eff_group; // UNUSED struct Group *coll_group; // collision objects group struct WTURBULENCE *wt; // WTURBULENCE object, if active struct GPUTexture *tex; @@ -75,6 +75,7 @@ typedef struct SmokeDomainSettings { int v3dnum; struct PointCache *point_cache[2]; /* definition is in DNA_object_force.h */ struct ListBase ptcaches[2]; + struct EffectorWeights *effector_weights; } SmokeDomainSettings; diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 7bccd685c1d..c8193bb4005 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -220,6 +220,11 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "point_cache[1]"); RNA_def_property_ui_text(prop, "Point Cache", ""); + + 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", ""); } static void rna_def_smoke_flow_settings(BlenderRNA *brna)