Smoke: Add new "Full Sample" option to high resolution smoke panel.
authorMiika Hamalainen <blender@miikah.org>
Fri, 10 May 2013 16:18:00 +0000 (16:18 +0000)
committerMiika Hamalainen <blender@miikah.org>
Fri, 10 May 2013 16:18:00 +0000 (16:18 +0000)
This is hopefully the ultimate solution against smoke blockiness near emitter.

Previously high resolution flow/emitter voxels were generated based on the low resolution ones. So if you had 32 resolution and 4 division high resolution, it still used smoke flow generated from those 32 resolution voxels. Now I introduced a new sampling method called "Full Sample" that generates full resolution flow for for high resolution domain as well.

Read more about it in my blog post: https://www.miikahweb.com/en/blog/2013/05/10/getting-rid-of-smoke-blockiness

Also changed "quick smoke" operator default voxel data interpolation mode to "Cubic B-Spline" to smoothen out it even more.

release/scripts/startup/bl_operators/object_quick_effects.py
release/scripts/startup/bl_ui/properties_physics_smoke.py
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/smoke.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_smoke_types.h
source/blender/makesrna/intern/rna_smoke.c

index 54527773ca0b043decf640bccaf21c1d22ba9ff8..765135d6f3d5c00c6fdf2551b5500c844991c906 100644 (file)
@@ -363,6 +363,7 @@ class QuickSmoke(Operator):
 
         tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
         tex.voxel_data.domain_object = obj
+        tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
 
         tex_slot = mat.texture_slots.add()
         tex_slot.texture = tex
@@ -375,6 +376,7 @@ class QuickSmoke(Operator):
         tex = bpy.data.textures.new("Flame", 'VOXEL_DATA')
         tex.voxel_data.domain_object = obj
         tex.voxel_data.smoke_data_type = 'SMOKEFLAME'
+        tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
         tex.use_color_ramp = True
 
         tex_slot = mat.texture_slots.add()
index 4a1b99ee81038cd79695e7f338095a22021931e5..842497fc74d0f772b6adeb920b6148cbd16f9be4 100644 (file)
@@ -244,7 +244,8 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
         col = split.column()
         col.label(text="Resolution:")
         col.prop(md, "amplify", text="Divisions")
-        col.prop(md, "use_smooth_emitter")
+        col.label(text="Flow Sampling:")
+        col.row().prop(md, "highres_sampling", text="")
 
         col = split.column()
         col.label(text="Noise Method:")
index 6048766194c45ff40ab2c117038e2b78591b2e48..07f0ff0aab75c214389559d0ffc485f659f81b81 100644 (file)
@@ -42,7 +42,7 @@ extern "C" {
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         267
-#define BLENDER_SUBVERSION      0
+#define BLENDER_SUBVERSION      1
 
 /* 262 was the last editmesh release but it has compatibility code for bmesh data */
 #define BLENDER_MINVERSION      262
index b61cd63f503ecf639865115cb7d38ad18baf3272..1d0ac507f31e15a565da126bbb4771706e80cafa 100644 (file)
@@ -525,6 +525,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
                        smd->domain->vorticity = 2.0;
                        smd->domain->border_collisions = SM_BORDER_OPEN; // open domain
                        smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG | MOD_SMOKE_HIGH_SMOOTH;
+                       smd->domain->highres_sampling = SM_HRES_FULLSAMPLE;
                        smd->domain->strength = 2.0;
                        smd->domain->noise = MOD_SMOKE_NOISEWAVE;
                        smd->domain->diss_speed = 5;
@@ -899,6 +900,7 @@ static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds,
 
 typedef struct EmissionMap {
        float *influence;
+       float *influence_high;
        float *velocity;
        int min[3], max[3], res[3];
        int total_cells, valid;
@@ -908,8 +910,10 @@ static void em_boundInsert(EmissionMap *em, float point[3])
 {
        int i = 0;
        if (!em->valid) {
-               VECCOPY(em->min, point);
-               VECCOPY(em->max, point);
+               for (; i < 3; i++) {
+                       em->min[i] = (int)floor(point[i]);
+                       em->max[i] = (int)ceil(point[i]);
+               }
                em->valid = 1;
        }
        else {
@@ -943,7 +947,7 @@ static void clampBoundsInDomain(SmokeDomainSettings *sds, int min[3], int max[3]
        }
 }
 
-static void em_allocateData(EmissionMap *em, int use_velocity)
+static void em_allocateData(EmissionMap *em, int use_velocity, int hires_mul)
 {
        int i, res[3];
 
@@ -959,12 +963,20 @@ static void em_allocateData(EmissionMap *em, int use_velocity)
        em->influence = MEM_callocN(sizeof(float) * em->total_cells, "smoke_flow_influence");
        if (use_velocity)
                em->velocity = MEM_callocN(sizeof(float) * em->total_cells * 3, "smoke_flow_velocity");
+
+       /* allocate high resolution map if required */
+       if (hires_mul > 1) {
+               int total_cells_high = em->total_cells * (hires_mul * hires_mul * hires_mul);
+               em->influence_high = MEM_callocN(sizeof(float) * total_cells_high, "smoke_flow_influence_high");
+       }
 }
 
 static void em_freeData(EmissionMap *em)
 {
        if (em->influence)
                MEM_freeN(em->influence);
+       if (em->influence_high)
+               MEM_freeN(em->influence_high);
        if (em->velocity)
                MEM_freeN(em->velocity);
 }
@@ -1034,7 +1046,7 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke
 
                /* set emission map */
                clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, 1, dt);
-               em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY);
+               em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY, 0);
 
                for (p = 0; p < valid_particles; p++)
                {
@@ -1096,6 +1108,131 @@ static void get_texture_value(Tex *texture, float tex_co[3], TexResult *texres)
        }
 }
 
+static void sample_derived_mesh(SmokeFlowSettings *sfs, MVert *mvert, MTFace *tface, MFace *mface, float *influence_map, float *velocity_map, int index, int base_res[3], float flow_center[3], BVHTreeFromMesh *treeData, float ray_start[3],
+                                                               float *vert_vel, int has_velocity, int defgrp_index, MDeformVert *dvert, float x, float y, float z)
+{
+       float ray_dir[3] = {1.0f, 0.0f, 0.0f};
+       BVHTreeRayHit hit = {0};
+       BVHTreeNearest nearest = {0};
+
+       float volume_factor = 0.0f;
+       float sample_str = 0.0f;
+
+       hit.index = -1;
+       hit.dist = 9999;
+       nearest.index = -1;
+       nearest.dist = sfs->surface_distance * sfs->surface_distance; /* find_nearest uses squared distance */
+
+       /* Check volume collision */
+       if (sfs->volume_density) {
+               if (BLI_bvhtree_ray_cast(treeData->tree, ray_start, ray_dir, 0.0f, &hit, treeData->raycast_callback, treeData) != -1) {
+                       float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
+                       /*  If ray and hit face normal are facing same direction
+                        *      hit point is inside a closed mesh. */
+                       if (dot >= 0) {
+                               /* Also cast a ray in opposite direction to make sure
+                                * point is at least surrounded by two faces */
+                               negate_v3(ray_dir);
+                               hit.index = -1;
+                               hit.dist = 9999;
+
+                               BLI_bvhtree_ray_cast(treeData->tree, ray_start, ray_dir, 0.0f, &hit, treeData->raycast_callback, treeData);
+                               if (hit.index != -1) {
+                                       volume_factor = sfs->volume_density;
+                               }
+                       }
+               }
+       }
+
+       /* find the nearest point on the mesh */
+       if (BLI_bvhtree_find_nearest(treeData->tree, ray_start, &nearest, treeData->nearest_callback, treeData) != -1) {
+               float weights[4];
+               int v1, v2, v3, f_index = nearest.index;
+               float n1[3], n2[3], n3[3], hit_normal[3];
+
+               /* emit from surface based on distance */
+               if (sfs->surface_distance) {
+                       sample_str = sqrtf(nearest.dist) / sfs->surface_distance;
+                       CLAMP(sample_str, 0.0f, 1.0f);
+                       sample_str = pow(1.0f - sample_str, 0.5f);
+               }
+               else
+                       sample_str = 0.0f;
+
+               /* calculate barycentric weights for nearest point */
+               v1 = mface[f_index].v1;
+               v2 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v3 : mface[f_index].v2;
+               v3 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v4 : mface[f_index].v3;
+               interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
+
+               if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
+                       /* apply normal directional velocity */
+                       if (sfs->vel_normal) {
+                               /* interpolate vertex normal vectors to get nearest point normal */
+                               normal_short_to_float_v3(n1, mvert[v1].no);
+                               normal_short_to_float_v3(n2, mvert[v2].no);
+                               normal_short_to_float_v3(n3, mvert[v3].no);
+                               interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights);
+                               normalize_v3(hit_normal);
+                               /* apply normal directional and random velocity
+                                * - TODO: random disabled for now since it doesnt really work well as pressure calc smoothens it out... */
+                               velocity_map[index * 3]   += hit_normal[0] * sfs->vel_normal * 0.25f;
+                               velocity_map[index * 3 + 1] += hit_normal[1] * sfs->vel_normal * 0.25f;
+                               velocity_map[index * 3 + 2] += hit_normal[2] * sfs->vel_normal * 0.25f;
+                               /* TODO: for fire emitted from mesh surface we can use
+                                *  Vf = Vs + (Ps/Pf - 1)*S to model gaseous expansion from solid to fuel */
+                       }
+                       /* apply object velocity */
+                       if (has_velocity && sfs->vel_multi) {
+                               float hit_vel[3];
+                               interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights);
+                               velocity_map[index * 3]   += hit_vel[0] * sfs->vel_multi;
+                               velocity_map[index * 3 + 1] += hit_vel[1] * sfs->vel_multi;
+                               velocity_map[index * 3 + 2] += hit_vel[2] * sfs->vel_multi;
+                       }
+               }
+
+               /* apply vertex group influence if used */
+               if (defgrp_index != -1 && dvert) {
+                       float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
+                                           defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
+                                           defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
+                       sample_str *= weight_mask;
+               }
+
+               /* apply emission texture */
+               if ((sfs->flags & MOD_SMOKE_FLOW_TEXTUREEMIT) && sfs->noise_texture) {
+                       float tex_co[3] = {0};
+                       TexResult texres;
+
+                       if (sfs->texture_type == MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO) {
+                               tex_co[0] = ((x - flow_center[0]) / base_res[0]) / sfs->texture_size;
+                               tex_co[1] = ((y - flow_center[1]) / base_res[1]) / sfs->texture_size;
+                               tex_co[2] = ((z - flow_center[2]) / base_res[2] - sfs->texture_offset) / sfs->texture_size;
+                       }
+                       else if (tface) {
+                               interp_v2_v2v2v2(tex_co, tface[f_index].uv[0], tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 2 : 1],
+                                                tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 3 : 2], weights);
+                               /* map between -1.0f and 1.0f */
+                               tex_co[0] = tex_co[0] * 2.0f - 1.0f;
+                               tex_co[1] = tex_co[1] * 2.0f - 1.0f;
+                               tex_co[2] = sfs->texture_offset;
+                       }
+                       texres.nor = NULL;
+                       get_texture_value(sfs->noise_texture, tex_co, &texres);
+                       sample_str *= texres.tin;
+               }
+       }
+
+       /* multiply initial velocity by emitter influence */
+       if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
+               mul_v3_fl(&velocity_map[index * 3], sample_str);
+       }
+
+       /* apply final influence based on volume factor */
+       influence_map[index] = MAX2(volume_factor, sample_str);
+}
+
 static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, float dt)
 {
        if (!sfs->dm) return;
@@ -1113,6 +1250,8 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo
 
                float *vert_vel = NULL;
                int has_velocity = 0;
+               float min[3], max[3], res[3];
+               int hires_multiplier = 1;
 
                CDDM_calc_normals(dm);
                mvert = dm->getVertArray(dm);
@@ -1165,141 +1304,57 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo
                mul_m4_v3(flow_ob->obmat, flow_center);
                smoke_pos_to_cell(sds, flow_center);
 
+               /* check need for high resolution map */
+               if ((sds->flags & MOD_SMOKE_HIGHRES) && (sds->highres_sampling == SM_HRES_FULLSAMPLE)) {
+                       hires_multiplier = sds->amplify + 1;
+               }
+
                /* set emission map */
                clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, sfs->surface_distance, dt);
-               em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY);
+               em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY, hires_multiplier);
+
+               /* setup loop bounds */
+               for (i = 0; i < 3; i++) {
+                       min[i] = em->min[i] * hires_multiplier;
+                       max[i] = em->max[i] * hires_multiplier;
+                       res[i] = em->res[i] * hires_multiplier;
+               }
 
                if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 6)) {
-                       #pragma omp parallel for schedule(static)
-                       for (z = em->min[2]; z < em->max[2]; z++) {
+                       //#pragma omp parallel for schedule(static)
+                       for (z = min[2]; z < max[2]; z++) {
                                int x, y;
-                               for (x = em->min[0]; x < em->max[0]; x++)
-                                       for (y = em->min[1]; y < em->max[1]; y++) {
-                                               int index = smoke_get_index(x - em->min[0], em->res[0], y - em->min[1], em->res[1], z - em->min[2]);
-
-                                               float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f};
-                                               float ray_dir[3] = {1.0f, 0.0f, 0.0f};
-
-                                               BVHTreeRayHit hit = {0};
-                                               BVHTreeNearest nearest = {0};
-
-                                               float volume_factor = 0.0f;
-                                               float sample_str = 0.0f;
-
-                                               hit.index = -1;
-                                               hit.dist = 9999;
-                                               nearest.index = -1;
-                                               nearest.dist = sfs->surface_distance * sfs->surface_distance; /* find_nearest uses squared distance */
-
-                                               /* Check volume collision */
-                                               if (sfs->volume_density) {
-                                                       if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) {
-                                                               float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
-                                                               /*  If ray and hit face normal are facing same direction
-                                                                *      hit point is inside a closed mesh. */
-                                                               if (dot >= 0) {
-                                                                       /* Also cast a ray in opposite direction to make sure
-                                                                        * point is at least surrounded by two faces */
-                                                                       negate_v3(ray_dir);
-                                                                       hit.index = -1;
-                                                                       hit.dist = 9999;
-
-                                                                       BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, treeData.raycast_callback, &treeData);
-                                                                       if (hit.index != -1) {
-                                                                               volume_factor = sfs->volume_density;
-                                                                               nearest.dist = hit.dist * hit.dist;
-                                                                       }
-                                                               }
-                                                       }
+                               for (x = min[0]; x < max[0]; x++)
+                                       for (y = min[1]; y < max[1]; y++) {
+                                               /* take low res samples where possible */
+                                               if (hires_multiplier <= 1 || !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
+                                                       /* get low res space coordinates */
+                                                       int lx = x / hires_multiplier;
+                                                       int ly = y / hires_multiplier;
+                                                       int lz = z / hires_multiplier;
+
+                                                       int index = smoke_get_index(lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
+                                                       float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
+
+                                                       sample_derived_mesh(sfs, mvert, tface, mface, em->influence, em->velocity, index, sds->base_res, flow_center, &treeData, ray_start,
+                                                                                               vert_vel, has_velocity, defgrp_index, dvert, (float)lx, (float)ly, (float)lz);
                                                }
 
-                                               /* find the nearest point on the mesh */
-                                               if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, treeData.nearest_callback, &treeData) != -1) {
-                                                       float weights[4];
-                                                       int v1, v2, v3, f_index = nearest.index;
-                                                       float n1[3], n2[3], n3[3], hit_normal[3];
-
-                                                       /* emit from surface based on distance */
-                                                       if (sfs->surface_distance) {
-                                                               sample_str = sqrtf(nearest.dist) / sfs->surface_distance;
-                                                               CLAMP(sample_str, 0.0f, 1.0f);
-                                                               sample_str = pow(1.0f - sample_str, 0.5f);
-                                                       }
-                                                       else
-                                                               sample_str = 0.0f;
-
-                                                       /* calculate barycentric weights for nearest point */
-                                                       v1 = mface[f_index].v1;
-                                                       v2 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v3 : mface[f_index].v2;
-                                                       v3 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v4 : mface[f_index].v3;
-                                                       interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
-
-                                                       if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) {
-                                                               /* apply normal directional velocity */
-                                                               if (sfs->vel_normal) {
-                                                                       /* interpolate vertex normal vectors to get nearest point normal */
-                                                                       normal_short_to_float_v3(n1, mvert[v1].no);
-                                                                       normal_short_to_float_v3(n2, mvert[v2].no);
-                                                                       normal_short_to_float_v3(n3, mvert[v3].no);
-                                                                       interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights);
-                                                                       normalize_v3(hit_normal);
-                                                                       /* apply normal directional and random velocity
-                                                                        * - TODO: random disabled for now since it doesnt really work well as pressure calc smoothens it out... */
-                                                                       em->velocity[index * 3]   += hit_normal[0] * sfs->vel_normal * 0.25f;
-                                                                       em->velocity[index * 3 + 1] += hit_normal[1] * sfs->vel_normal * 0.25f;
-                                                                       em->velocity[index * 3 + 2] += hit_normal[2] * sfs->vel_normal * 0.25f;
-                                                                       /* TODO: for fire emitted from mesh surface we can use
-                                                                        *  Vf = Vs + (Ps/Pf - 1)*S to model gaseous expansion from solid to fuel */
-                                                               }
-                                                               /* apply object velocity */
-                                                               if (has_velocity && sfs->vel_multi) {
-                                                                       float hit_vel[3];
-                                                                       interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights);
-                                                                       em->velocity[index * 3]   += hit_vel[0] * sfs->vel_multi;
-                                                                       em->velocity[index * 3 + 1] += hit_vel[1] * sfs->vel_multi;
-                                                                       em->velocity[index * 3 + 2] += hit_vel[2] * sfs->vel_multi;
-                                                               }
-                                                       }
-
-                                                       /* apply vertex group influence if used */
-                                                       if (defgrp_index != -1 && dvert) {
-                                                               float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
-                                                                                   defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
-                                                                                   defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
-                                                               sample_str *= weight_mask;
-                                                       }
-
-                                                       /* apply emission texture */
-                                                       if ((sfs->flags & MOD_SMOKE_FLOW_TEXTUREEMIT) && sfs->noise_texture) {
-                                                               float tex_co[3] = {0};
-                                                               TexResult texres;
+                                               /* take high res samples if required */
+                                               if (hires_multiplier > 1) {
+                                                       /* get low res space coordinates */
+                                                       float hr = 1.0f / ((float)hires_multiplier);
+                                                       float lx = ((float)x) * hr;
+                                                       float ly = ((float)y) * hr;
+                                                       float lz = ((float)z) * hr;
 
-                                                               if (sfs->texture_type == MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO) {
-                                                                       tex_co[0] = ((float)(x - flow_center[0]) / sds->base_res[0]) / sfs->texture_size;
-                                                                       tex_co[1] = ((float)(y - flow_center[1]) / sds->base_res[1]) / sfs->texture_size;
-                                                                       tex_co[2] = ((float)(z - flow_center[2]) / sds->base_res[2] - sfs->texture_offset) / sfs->texture_size;
-                                                               }
-                                                               else if (tface) {
-                                                                       interp_v2_v2v2v2(tex_co, tface[f_index].uv[0], tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 2 : 1],
-                                                                                        tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 3 : 2], weights);
-                                                                       /* map between -1.0f and 1.0f */
-                                                                       tex_co[0] = tex_co[0] * 2.0f - 1.0f;
-                                                                       tex_co[1] = tex_co[1] * 2.0f - 1.0f;
-                                                                       tex_co[2] = sfs->texture_offset;
-                                                               }
-                                                               texres.nor = NULL;
-                                                               get_texture_value(sfs->noise_texture, tex_co, &texres);
-                                                               sample_str *= texres.tin;
-                                                       }
-                                               }
+                                                       int index = smoke_get_index(x - min[0], res[0], y - min[1], res[1], z - min[2]);
+                                                       float ray_start[3] = {lx + 0.5f*hr, ly + 0.5f*hr, lz + 0.5f*hr};
 
-                                               /* multiply initial velocity by emitter influence */
-                                               if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) {
-                                                       mul_v3_fl(&em->velocity[index * 3], sample_str);
+                                                       sample_derived_mesh(sfs, mvert, tface, mface, em->influence_high, NULL, index, sds->base_res, flow_center, &treeData, ray_start,
+                                                                                               vert_vel, has_velocity, defgrp_index, dvert, lx, ly, lz); /* x,y,z needs to be always lowres */
                                                }
 
-                                               /* apply final influence based on volume factor */
-                                               em->influence[index] = MAX2(volume_factor, sample_str);
                                        }
                        }
                }
@@ -1808,9 +1863,9 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
                                //unsigned char *obstacle = smoke_get_obstacle(sds->fluid);
                                // DG TODO UNUSED unsigned char *obstacleAnim = smoke_get_obstacle_anim(sds->fluid);
                                int bigres[3];
-                               short high_emission_smoothing = (sds->flags & MOD_SMOKE_HIGH_SMOOTH);
                                float *velocity_map = em->velocity;
                                float *emission_map = em->influence;
+                               float *emission_map_high = em->influence_high;
 
                                int ii, jj, kk, gx, gy, gz, ex, ey, ez, dx, dy, dz, block_size;
                                size_t e_index, d_index, index_big;
@@ -1825,7 +1880,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
                                                        ey = gy - em->min[1];
                                                        ez = gz - em->min[2];
                                                        e_index = smoke_get_index(ex, em->res[0], ey, em->res[1], ez);
-                                                       if (!emission_map[e_index]) continue;
+
                                                        /* get domain index */
                                                        dx = gx - sds->res_min[0];
                                                        dy = gy - sds->res_min[1];
@@ -1872,14 +1927,20 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
                                                                                {
 
                                                                                        float fx, fy, fz, interpolated_value;
-                                                                                       int shift_x, shift_y, shift_z;
+                                                                                       int shift_x = 0, shift_y = 0, shift_z = 0;
 
 
-                                                                                       /*
-                                                                                        * Do volume interpolation if emitter smoothing
-                                                                                        * is enabled
-                                                                                        */
-                                                                                       if (high_emission_smoothing)
+                                                                                       /* Use full sample emission map if enabled and available */
+                                                                                       if ((sds->highres_sampling == SM_HRES_FULLSAMPLE) && emission_map_high) {
+                                                                                               interpolated_value = emission_map_high[smoke_get_index(ex * block_size + ii, em->res[0] * block_size, ey * block_size + jj, em->res[1] * block_size, ez * block_size + kk)]; // this cell
+                                                                                       }
+                                                                                       else if (sds->highres_sampling == SM_HRES_NEAREST) {
+                                                                                               /* without interpolation use same low resolution
+                                                                                                * block value for all hi-res blocks */
+                                                                                               interpolated_value = c111;
+                                                                                       }
+                                                                                       /* Fall back to interpolated */
+                                                                                       else
                                                                                        {
                                                                                                /* get relative block position
                                                                                                 * for interpolation smoothing */
@@ -1910,14 +1971,6 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
                                                                                                shift_y = (dy < 1) ? 0 : block_size / 2;
                                                                                                shift_z = (dz < 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 * dx + ii - shift_x, bigres[0], block_size * dy + jj - shift_y, bigres[1], block_size * dz + kk - shift_z);
index a76d7eaff6d069631873232aa726ec2a09efa5fc..ac583eaf73d5bc4d9e8533276ff785347da4dada 100644 (file)
@@ -9443,6 +9443,28 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
+       if (MAIN_VERSION_OLDER(main, 267, 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) {
+                                               if (smd->domain->flags && MOD_SMOKE_HIGH_SMOOTH) {
+                                                       smd->domain->highres_sampling = SM_HRES_LINEAR;
+                                               }
+                                               else {
+                                                       smd->domain->highres_sampling = SM_HRES_NEAREST;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
 
index fa31717b9e2f005af8868d08a4c6f9184183da72..042c43c5b93f66de11e1a1ee4a72e0223754ee16 100644 (file)
@@ -37,7 +37,7 @@
 #define MOD_SMOKE_DISSOLVE (1<<2) /* let smoke dissolve */
 #define MOD_SMOKE_DISSOLVE_LOG (1<<3) /* using 1/x for dissolve */
 
-#define MOD_SMOKE_HIGH_SMOOTH (1<<5) /* smoothens high res emission*/
+#define MOD_SMOKE_HIGH_SMOOTH (1<<5) /* -- Deprecated -- */
 #define MOD_SMOKE_FILE_LOAD (1<<6) /* flag for file load */
 #define MOD_SMOKE_ADAPTIVE_DOMAIN (1<<7)
 
 #define SM_COLL_RIGID          1
 #define SM_COLL_ANIMATED       2
 
+/* high resolution sampling types */
+#define SM_HRES_NEAREST                0
+#define SM_HRES_LINEAR         1
+#define SM_HRES_FULLSAMPLE     2
+
 /* smoke data fileds (active_fields) */
 #define SM_ACTIVE_HEAT         (1<<0)
 #define SM_ACTIVE_FIRE         (1<<1)
@@ -132,7 +137,7 @@ typedef struct SmokeDomainSettings {
        float vorticity;
        int active_fields;
        float active_color[3]; /* monitor color situation of simulation */
-       int pad;
+       int highres_sampling;
 
        /* flame parameters */
        float burning_rate, flame_smoke, flame_vorticity;
index 83a974137e82a2c50f60c96f3a66242ec0767428..66fd5186fc4e68713f948586f4a7c5be0d00c05b 100644 (file)
@@ -200,6 +200,13 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}
        };
 
+       static EnumPropertyItem smoke_highres_sampling_items[] = {
+               {SM_HRES_FULLSAMPLE, "FULLSAMPLE", 0, "Full Sample", ""},
+               {SM_HRES_LINEAR, "LINEAR", 0, "Linear", ""},
+               {SM_HRES_NEAREST, "NEAREST", 0, "Nearest", ""},
+               {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",
@@ -330,9 +337,9 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Effector Weights", "");
 
-       prop = RNA_def_property(srna, "use_smooth_emitter", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGH_SMOOTH);
-       RNA_def_property_ui_text(prop, "Smooth Emitter", "Smooth emitted smoke to avoid blockiness");
+       prop = RNA_def_property(srna, "highres_sampling", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, smoke_highres_sampling_items);
+       RNA_def_property_ui_text(prop, "Emitter", "Method for sampling the high resolution flow");
        RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
 
        prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
@@ -547,7 +554,7 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
 
        prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_range(prop, 0.5, 10.0);
+       RNA_def_property_range(prop, 0.0, 10.0);
        RNA_def_property_ui_range(prop, 0.5, 5.0, 0.05, 5);
        RNA_def_property_ui_text(prop, "Surface", "Maximum distance from mesh surface to emit smoke");
        RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");