[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [56665] trunk/blender: Smoke: Add new " Full Sample" option to high resolution smoke panel.

Miika Hamalainen blender at miikah.org
Fri May 10 18:18:01 CEST 2013


Revision: 56665
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=56665
Author:   miikah
Date:     2013-05-10 16:18:00 +0000 (Fri, 10 May 2013)
Log Message:
-----------
Smoke: Add new "Full Sample" option to high resolution smoke panel.

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.

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

Modified: trunk/blender/release/scripts/startup/bl_operators/object_quick_effects.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_operators/object_quick_effects.py	2013-05-10 15:56:32 UTC (rev 56664)
+++ trunk/blender/release/scripts/startup/bl_operators/object_quick_effects.py	2013-05-10 16:18:00 UTC (rev 56665)
@@ -363,6 +363,7 @@
 
         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 @@
         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()

Modified: trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py	2013-05-10 15:56:32 UTC (rev 56664)
+++ trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py	2013-05-10 16:18:00 UTC (rev 56665)
@@ -244,7 +244,8 @@
         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:")

Modified: trunk/blender/source/blender/blenkernel/BKE_blender.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_blender.h	2013-05-10 15:56:32 UTC (rev 56664)
+++ trunk/blender/source/blender/blenkernel/BKE_blender.h	2013-05-10 16:18:00 UTC (rev 56665)
@@ -42,7 +42,7 @@
  * 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

Modified: trunk/blender/source/blender/blenkernel/intern/smoke.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/smoke.c	2013-05-10 15:56:32 UTC (rev 56664)
+++ trunk/blender/source/blender/blenkernel/intern/smoke.c	2013-05-10 16:18:00 UTC (rev 56665)
@@ -525,6 +525,7 @@
 			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 @@
 
 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 @@
 {
 	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 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 @@
 	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 @@
 
 		/* 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 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 @@
 
 		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 @@
 		mul_m4_v3(flow_ob->obmat, flow_center);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list