[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [32842] trunk/blender/source/blender/ blenkernel: Oops, particle collisions didn' t take simulation subframes into account at all.

Janne Karhu jhkarh at gmail.com
Tue Nov 2 22:16:42 CET 2010


Revision: 32842
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=32842
Author:   jhk
Date:     2010-11-02 22:16:41 +0100 (Tue, 02 Nov 2010)

Log Message:
-----------
Oops, particle collisions didn't take simulation subframes into account at all.
* This caused nearly all particles to leak through the collision surface if simulation subframes were used and the collision object was moving.
* In addition to fixing this I also did some more cleanup of the collision code and refined some of the comments.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_particle.h
    trunk/blender/source/blender/blenkernel/intern/boids.c
    trunk/blender/source/blender/blenkernel/intern/particle_system.c

Modified: trunk/blender/source/blender/blenkernel/BKE_particle.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_particle.h	2010-11-02 15:21:43 UTC (rev 32841)
+++ trunk/blender/source/blender/blenkernel/BKE_particle.h	2010-11-02 21:16:41 UTC (rev 32842)
@@ -171,7 +171,9 @@
 	float co1[3], co2[3]; // ray start and end points
 	float ve1[3], ve2[3]; // particle velocities
 	float ray_len; // original length of co2-co1, needed for collision time evaluation
-	float t;	// time of previous collision, needed for substracting face velocity
+	float f;	// time factor of previous collision, needed for substracting face velocity
+	float cfra; // start of the timestep (during frame change, since previous integer frame)
+	float dfra; // duration of timestep in frames
 } ParticleCollision;
 
 typedef struct ParticleDrawData {

Modified: trunk/blender/source/blender/blenkernel/intern/boids.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/boids.c	2010-11-02 15:21:43 UTC (rev 32841)
+++ trunk/blender/source/blender/blenkernel/intern/boids.c	2010-11-02 21:16:41 UTC (rev 32842)
@@ -205,7 +205,9 @@
 		add_v3_v3v3(col.co2, pa->prev_state.co, pa->prev_state.vel);
 		sub_v3_v3v3(ray_dir, col.co2, col.co1);
 		mul_v3_fl(ray_dir, acbr->look_ahead);
-		col.t = 0.0f;
+		col.f = 0.0f;
+		col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+		col.dfra = bbd->dfra;
 		hit.index = -1;
 		hit.dist = col.ray_len = len_v3(ray_dir);
 
@@ -772,7 +774,9 @@
 		sub_v3_v3v3(col.co2, pa->state.co, zvec);
 		sub_v3_v3(col.co2, zvec);
 		sub_v3_v3v3(ray_dir, col.co2, col.co1);
-		col.t = 0.0f;
+		col.f = 0.0f;
+		col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+		col.dfra = bbd->dfra;
 		hit.index = -1;
 		hit.dist = col.ray_len = len_v3(ray_dir);
 
@@ -796,7 +800,9 @@
 		sub_v3_v3v3(col.co2, pa->state.co, zvec);
 		sub_v3_v3(col.co2, zvec);
 		sub_v3_v3v3(ray_dir, col.co2, col.co1);
-		col.t = 0.0f;
+		col.f = 0.0f;
+		col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+		col.dfra = bbd->dfra;
 		hit.index = -1;
 		hit.dist = col.ray_len = len_v3(ray_dir);
 

Modified: trunk/blender/source/blender/blenkernel/intern/particle_system.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/particle_system.c	2010-11-02 15:21:43 UTC (rev 32841)
+++ trunk/blender/source/blender/blenkernel/intern/particle_system.c	2010-11-02 21:16:41 UTC (rev 32842)
@@ -2777,23 +2777,26 @@
 	MVert *x = col->md->x;
 	MVert *v = col->md->current_v;
 	float vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], t;
+	float x0[3], x1[3], x2[3], x3[3];
+	float *t0=x0, *t1=x1, *t2=x2, *t3=(face->v4 ? x3 : NULL);
 
-	float *t0, *t1, *t2, *t3;
-	t0 = x[ face->v1 ].co;
-	t1 = x[ face->v2 ].co;
-	t2 = x[ face->v3 ].co;
-	t3 = face->v4 ? x[ face->v4].co : NULL;
+	/* move collision face to start of timestep */
+	madd_v3_v3v3fl(t0, x[face->v1].co, v[face->v1].co, col->cfra);
+	madd_v3_v3v3fl(t1, x[face->v2].co, v[face->v2].co, col->cfra);
+	madd_v3_v3v3fl(t2, x[face->v3].co, v[face->v3].co, col->cfra);
+	if(t3)
+		madd_v3_v3v3fl(t3, x[face->v4].co, v[face->v4].co, col->cfra);
 
 	/* calculate average velocity of face */
-	VECCOPY(vel, v[ face->v1 ].co);
-	VECADD(vel, vel, v[ face->v2 ].co);
-	VECADD(vel, vel, v[ face->v3 ].co);
-	mul_v3_fl(vel, 0.33334f);
+	copy_v3_v3(vel, v[ face->v1 ].co);
+	add_v3_v3(vel, v[ face->v2 ].co);
+	add_v3_v3(vel, v[ face->v3 ].co);
+	mul_v3_fl(vel, 0.33334f*col->dfra);
 
 	/* substract face velocity, in other words convert to 
 	   a coordinate system where only the particle moves */
-	VECADDFAC(co1, col->co1, vel, -col->t);
-	VECSUB(co2, col->co2, vel);
+	madd_v3_v3v3fl(co1, col->co1, vel, -col->f);
+	sub_v3_v3v3(co2, col->co2, vel);
 
 	do
 	{	
@@ -2875,7 +2878,7 @@
 	copy_v3_v3(col.co2, pa->state.co);
 	copy_v3_v3(col.ve1, pa->prev_state.vel);
 	copy_v3_v3(col.ve2, pa->state.vel);
-	col.t = 0.0f;
+	col.f = 0.0f;
 
 	/* override for boids */
 	if(part->phystype == PART_PHYS_BOIDS) {
@@ -2893,6 +2896,9 @@
 		hit.index = -1;
 		hit.dist = col.ray_len = len_v3(ray_dir);
 
+		col.cfra = fmod(cfra-dfra, 1.0f);
+		col.dfra = dfra;
+
 		/* even if particle is stationary we want to check for moving colliders */
 		/* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */
 		if(hit.dist == 0.0f)
@@ -2917,11 +2923,11 @@
 		/* 2. */
 		if(hit.index>=0) {
 			PartDeflect *pd = col.hit_ob->pd;
-			float co[3]; /* point of collision */
-			float x = hit.dist/col.ray_len; /* location of collision between this iteration */
-			float df = col.t + x * (1.0f - col.t); /* time of collision between frame change*/
-			float dt1 = (df - col.t) * timestep; /* iteration time of collision (in seconds) */
-			float dt2 = (1.0f - df) * timestep; /* time left after collision (in seconds) */
+			float co[3];							/* point of collision */
+			float x = hit.dist/col.ray_len;			/* location factor of collision between this iteration */
+			float f = col.f + x * (1.0f - col.f);	/* time factor of collision between timestep */
+			float dt1 = (f - col.f) * timestep;		/* time since previous collision (in seconds) */
+			float dt2 = (1.0f - f) * timestep;		/* time left after collision (in seconds) */
 			int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */
 
 			deflections++;
@@ -2935,12 +2941,12 @@
 			/* particle dies in collision */
 			if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) {
 				pa->alive = PARS_DYING;
-				pa->dietime = pa->state.time + (cfra - pa->state.time) * df;
+				pa->dietime = pa->state.time + (cfra - pa->state.time) * f;
 
 				copy_v3_v3(pa->state.co, co);
-				interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, df);
-				interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, df);
-				interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, df);
+				interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, f);
+				interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, f);
+				interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, f);
 
 				/* particle is dead so we don't need to calculate further */
 				return;
@@ -3073,7 +3079,7 @@
 					copy_v3_v3(col.ve1, v0);
 					copy_v3_v3(col.ve2, pa->state.vel);
 
-					col.t = df;
+					col.f = f;
 				}
 				else {
 					/* final chance to prevent failure, so stick to the surface and hope for the best */





More information about the Bf-blender-cvs mailing list