[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [56884] trunk/blender: Smoke simulator: Add flow subframes and ability to set custom particle size.

Miika Hamalainen blender at miikah.org
Fri May 17 19:45:38 CEST 2013


Revision: 56884
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=56884
Author:   miikah
Date:     2013-05-17 17:45:37 +0000 (Fri, 17 May 2013)
Log Message:
-----------
Smoke simulator: Add flow subframes and ability to set custom particle size.

Previously it was nearly impossible to have fast moving objects emitting smoke or they would just leave behind a row of smoke poofs instead of continious stream of smoke. Now it's possible to set number of subframes for each smoke flow.

Another new thing is ability to set size of smoke flow particles instead of using closest smoke cell. This also works with my earlier "full sample" commit, so no more blocky particles either. :)

For more info check my blog post: http://www.miikahweb.com/en/blog/2013/05/17/blender-smoke-subframes

This commit also includes couple of fixes I spotted while testing:
* Fix: dissolve was applied at different time for low res and high res simulations.
* Fix: full sample setting didn't get copied with domain.

Modified Paths:
--------------
    trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py
    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_ui/properties_physics_smoke.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py	2013-05-17 16:46:59 UTC (rev 56883)
+++ trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py	2013-05-17 17:45:37 UTC (rev 56884)
@@ -87,6 +87,10 @@
                 if flow.smoke_flow_source == "PARTICLES":
                     col.label(text="Particle System:")
                     col.prop_search(flow, "particle_system", ob, "particle_systems", text="")
+                    col.prop(flow, "use_particle_size", text="Set Size")
+                    sub = col.column()
+                    sub.active = flow.use_particle_size
+                    sub.prop(flow, "particle_size")
                 else:
                     col.prop(flow, "surface_distance")
                     col.prop(flow, "volume_density")
@@ -110,6 +114,8 @@
                     sub.prop(flow, "smoke_color")
                 if flow.smoke_flow_type in {'FIRE', 'BOTH'}:
                     sub.prop(flow, "fuel_amount")
+                sub.label(text="Sampling:")
+                sub.prop(flow, "subframes")
 
         elif md.smoke_type == 'COLLISION':
             coll = md.coll_settings

Modified: trunk/blender/source/blender/blenkernel/intern/smoke.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/smoke.c	2013-05-17 16:46:59 UTC (rev 56883)
+++ trunk/blender/source/blender/blenkernel/intern/smoke.c	2013-05-17 17:45:37 UTC (rev 56884)
@@ -54,6 +54,9 @@
 #include "BLI_utildefines.h"
 #include "BLI_voxel.h"
 
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
 #include "DNA_customdata_types.h"
 #include "DNA_group_types.h"
 #include "DNA_lamp_types.h"
@@ -65,16 +68,21 @@
 #include "DNA_scene_types.h"
 #include "DNA_smoke_types.h"
 
+#include "BKE_animsys.h"
+#include "BKE_armature.h"
 #include "BKE_bvhutils.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_collision.h"
+#include "BKE_constraint.h"
 #include "BKE_customdata.h"
 #include "BKE_deform.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_effect.h"
 #include "BKE_modifier.h"
+#include "BKE_object.h"
 #include "BKE_particle.h"
 #include "BKE_pointcache.h"
+#include "BKE_scene.h"
 #include "BKE_smoke.h"
 
 #include "RE_shader_ext.h"
@@ -561,11 +569,14 @@
 			smd->flow->density = 1.0f;
 			smd->flow->fuel_amount = 1.0f;
 			smd->flow->temp = 1.0f;
-			smd->flow->flags = MOD_SMOKE_FLOW_ABSOLUTE;
+			smd->flow->flags = MOD_SMOKE_FLOW_ABSOLUTE | MOD_SMOKE_FLOW_USE_PART_SIZE;
 			smd->flow->vel_multi = 1.0f;
+			smd->flow->volume_density = 0.0f;
 			smd->flow->surface_distance = 1.5f;
 			smd->flow->source = MOD_SMOKE_FLOW_SOURCE_MESH;
 			smd->flow->texture_size = 1.0f;
+			smd->flow->particle_size = 1.0f;
+			smd->flow->subframes = 0;
 
 			smd->flow->color[0] = 0.7f;
 			smd->flow->color[1] = 0.7f;
@@ -615,6 +626,7 @@
 		tsmd->domain->amplify = smd->domain->amplify;
 		tsmd->domain->maxres = smd->domain->maxres;
 		tsmd->domain->flags = smd->domain->flags;
+		tsmd->domain->highres_sampling = smd->domain->highres_sampling;
 		tsmd->domain->viewsettings = smd->domain->viewsettings;
 		tsmd->domain->noise = smd->domain->noise;
 		tsmd->domain->diss_speed = smd->domain->diss_speed;
@@ -648,6 +660,8 @@
 		tsmd->flow->temp = smd->flow->temp;
 		tsmd->flow->volume_density = smd->flow->volume_density;
 		tsmd->flow->surface_distance = smd->flow->surface_distance;
+		tsmd->flow->particle_size = smd->flow->particle_size;
+		tsmd->flow->subframes = smd->flow->subframes;
 
 		tsmd->flow->texture_size = smd->flow->texture_size;
 		tsmd->flow->texture_offset = smd->flow->texture_offset;
@@ -694,6 +708,10 @@
 	return found_lamp;
 }
 
+/**********************************************************
+ *	Obstacles
+ **********************************************************/
+
 static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds, SmokeCollSettings *scs, unsigned char *obstacle_map, float *velocityX, float *velocityY, float *velocityZ, float dt)
 {
 	if (!scs->dm) return;
@@ -898,11 +916,107 @@
 }
 
 
+/**********************************************************
+ *	Object subframe update method from dynamicpaint.c
+ **********************************************************/
+
+/* set "ignore cache" flag for all caches on this object */
+static void object_cacheIgnoreClear(Object *ob, int state)
+{
+	ListBase pidlist;
+	PTCacheID *pid;
+	BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+
+	for (pid = pidlist.first; pid; pid = pid->next) {
+		if (pid->cache) {
+			if (state)
+				pid->cache->flag |= PTCACHE_IGNORE_CLEAR;
+			else
+				pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR;
+		}
+	}
+
+	BLI_freelistN(&pidlist);
+}
+
+static int subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int parent_recursion, float frame)
+{
+	SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+	bConstraint *con;
+
+	/* if other is dynamic paint canvas, don't update */
+	if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN))
+		return 1;
+
+	/* if object has parents, update them too */
+	if (parent_recursion) {
+		int recursion = parent_recursion - 1;
+		int is_domain = 0;
+		if (ob->parent) is_domain += subframe_updateObject(scene, ob->parent, 0, recursion, frame);
+		if (ob->track) is_domain += subframe_updateObject(scene, ob->track, 0, recursion, frame);
+
+		/* skip subframe if object is parented
+		 *  to vertex of a dynamic paint canvas */
+		if (is_domain && (ob->partype == PARVERT1 || ob->partype == PARVERT3))
+			return 0;
+
+		/* also update constraint targets */
+		for (con = ob->constraints.first; con; con = con->next) {
+			bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+			ListBase targets = {NULL, NULL};
+
+			if (cti && cti->get_constraint_targets) {
+				bConstraintTarget *ct;
+				cti->get_constraint_targets(con, &targets);
+				for (ct = targets.first; ct; ct = ct->next) {
+					if (ct->tar)
+						subframe_updateObject(scene, ct->tar, 0, recursion, frame);
+				}
+				/* free temp targets */
+				if (cti->flush_constraint_targets)
+					cti->flush_constraint_targets(con, &targets, 0);
+			}
+		}
+	}
+
+	/* was originally OB_RECALC_ALL - TODO - which flags are really needed??? */
+	ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+	BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
+	if (update_mesh) {
+		/* ignore cache clear during subframe updates
+		 *  to not mess up cache validity */
+		object_cacheIgnoreClear(ob, 1);
+		BKE_object_handle_update(scene, ob);
+		object_cacheIgnoreClear(ob, 0);
+	}
+	else
+		BKE_object_where_is_calc_time(scene, ob, frame);
+
+	/* for curve following objects, parented curve has to be updated too */
+	if (ob->type == OB_CURVE) {
+		Curve *cu = ob->data;
+		BKE_animsys_evaluate_animdata(scene, &cu->id, cu->adt, frame, ADT_RECALC_ANIM);
+	}
+	/* and armatures... */
+	if (ob->type == OB_ARMATURE) {
+		bArmature *arm = ob->data;
+		BKE_animsys_evaluate_animdata(scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM);
+		BKE_pose_where_is(scene, ob);
+	}
+
+	return 0;
+}
+
+/**********************************************************
+ *	Flow emission code
+ **********************************************************/
+
 typedef struct EmissionMap {
 	float *influence;
 	float *influence_high;
 	float *velocity;
 	int min[3], max[3], res[3];
+	int hmin[3], hmax[3], hres[3];
 	int total_cells, valid;
 } EmissionMap;
 
@@ -935,7 +1049,7 @@
 
 		/* adapt to velocity */
 		if (min_vel && min_vel[i] < 0.0f) {
-			min[i] += (int)ceil(min_vel[i] * dt);
+			min[i] += (int)floor(min_vel[i] * dt);
 		}
 		if (max_vel && max_vel[i] > 0.0f) {
 			max[i] += (int)ceil(max_vel[i] * dt);
@@ -967,8 +1081,16 @@
 	/* allocate high resolution map if required */
 	if (hires_mul > 1) {
 		int total_cells_high = em->total_cells * (hires_mul * hires_mul * hires_mul);
+
+		for (i = 0; i < 3; i++) {
+			em->hmin[i] = em->min[i] * hires_mul;
+			em->hmax[i] = em->max[i] * hires_mul;
+			em->hres[i] = em->res[i] * hires_mul;
+		}
+
 		em->influence_high = MEM_callocN(sizeof(float) * total_cells_high, "smoke_flow_influence_high");
 	}
+	em->valid = 1;
 }
 
 static void em_freeData(EmissionMap *em)
@@ -981,8 +1103,108 @@
 		MEM_freeN(em->velocity);
 }
 
+static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int hires_multiplier, int additive, float sample_size)
+{
+	int i, x,y,z;
 
-static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, Scene *scene, float time, float dt)
+	/* copyfill input 1 struct and clear output for new allocation */
+	EmissionMap em1;
+	memcpy(&em1, output, sizeof(EmissionMap));
+	memset(output, 0, sizeof(EmissionMap));
+
+	for (i = 0; i < 3; i++) {
+		if (em1.valid) {
+			output->min[i] = MIN2(em1.min[i], em2->min[i]);
+			output->max[i] = MAX2(em1.max[i], em2->max[i]);
+		}
+		else {
+			output->min[i] = em2->min[i];
+			output->max[i] = em2->max[i];
+		}
+	}
+	/* allocate output map */
+	em_allocateData(output, (em1.velocity || em2->velocity), hires_multiplier);
+
+	/* base resolution inputs */
+	for (x = output->min[0]; x < output->max[0]; x++)
+		for (y = output->min[1]; y < output->max[1]; y++)
+			for (z = output->min[2]; z < output->max[2]; z++) {
+				int index_out = smoke_get_index(x - output->min[0], output->res[0], y - output->min[1], output->res[1], z - output->min[2]);
+
+				/* initialize with first input if in range */
+				if (x >= em1.min[0] && x < em1.max[0] &&
+					y >= em1.min[1] && y < em1.max[1] &&
+					z >= em1.min[2] && z < em1.max[2]) {
+					int index_in = smoke_get_index(x - em1.min[0], em1.res[0], y - em1.min[1], em1.res[1], z - em1.min[2]);
+
+					/* values */
+					output->influence[index_out] = em1.influence[index_in];
+					if (output->velocity) {
+						output->velocity[index_out] = em1.velocity[index_in];
+					}
+				}
+
+				/* apply second input if in range */
+				if (x >= em2->min[0] && x < em2->max[0] &&
+					y >= em2->min[1] && y < em2->max[1] &&
+					z >= em2->min[2] && z < em2->max[2]) {
+					int index_in = smoke_get_index(x - em2->min[0], em2->res[0], y - em2->min[1], em2->res[1], z - em2->min[2]);
+
+					/* values */
+					if (additive) {

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list