Smoke:
authorDaniel Genrich <daniel.genrich@gmx.net>
Thu, 8 Oct 2009 10:18:14 +0000 (10:18 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Thu, 8 Oct 2009 10:18:14 +0000 (10:18 +0000)
* Enable external forces like e.g. wind

intern/smoke/extern/smoke_API.h
intern/smoke/intern/FLUID_3D.cpp
intern/smoke/intern/smoke_API.cpp
release/scripts/ui/buttons_physics_smoke.py
source/blender/blenkernel/intern/smoke.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/makesdna/DNA_smoke_types.h
source/blender/makesrna/intern/rna_smoke.c

index 5607df70cf3b8273254fa006e627b3a8afd9110f..ea106c81303aecd234009a54e9e651edbc5d6694 100644 (file)
@@ -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);
index bb2227801c78406fc804ee1f65b015c9640cbd5d..729d73bb4f35d412f1078425014f8aa3b158e22d 100644 (file)
@@ -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;
+       }
 }
 
 //////////////////////////////////////////////////////////////////////
index 67df6e805d8965c0d1a20b407d8e318af5aeecc2..2d1d590fcc08cdbabe85ee7a3f411561b7e168fc 100644 (file)
@@ -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;
index 1541b0bae1456976a6437320f0804956c2b69c68..53a7ec9c10cd78c4ffebbf28270045eaa27287f6 100644 (file)
@@ -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)
index f1fae4fa678be0a1dab3a6b60de311b41f8f0bf8..c1e79651c59b22e8c7644fbf67c2da550dd92759 100644 (file)
@@ -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)
index 989e2b3fa9e506a991d1537a9e6ce239486f54df..a832cae161b74600ebef42071865a2022be18075 100644 (file)
@@ -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]));
                        }
index c92c0909d3bd02bd92ca51dde43d6e6c6991b085..25cbd4b65e72b46099436d24769ea533e57395eb 100644 (file)
@@ -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)
index 4e4714cdaa1d99047f97cbf099e5da47ccd3fc7d..6cf308aa0ad2b3f6d6d4702abee0533d9f41520c 100644 (file)
@@ -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;
 
 
index 7bccd685c1db238fa685b8dcb659505362c6701d..c8193bb4005dbfc4ea998ec6382794c1596130b5 100644 (file)
@@ -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)