[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [44044] trunk/blender/source/blender/ blenkernel/intern: Fix [#29265] Particle Instance: Create Along Paths + Children inconsistent with actual children hair particles

Janne Karhu jhkarh at gmail.com
Sun Feb 12 01:25:59 CET 2012


Revision: 44044
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=44044
Author:   jhk
Date:     2012-02-12 00:25:52 +0000 (Sun, 12 Feb 2012)
Log Message:
-----------
Fix [#29265] Particle Instance: Create Along Paths + Children inconsistent with actual children hair particles
* Hair particle rotations weren't calculated properly for particle locations along a path and the "particle on path" calculations were not correct in many other ways too.
* Now the particle's location along a path is interpolated directly from the cached paths if it exist. These paths are always correctly calculated.
* Paths are now cached if a particle instance modifier using the particle system with the path option exists.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/particle.c
    trunk/blender/source/blender/blenkernel/intern/particle_system.c

Modified: trunk/blender/source/blender/blenkernel/intern/particle.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/particle.c	2012-02-12 00:09:48 UTC (rev 44043)
+++ trunk/blender/source/blender/blenkernel/intern/particle.c	2012-02-12 00:25:52 UTC (rev 44044)
@@ -1365,6 +1365,35 @@
 	if(pind->keyed || pind->cache || point_vel)
 		mul_v3_fl(result->vel, 1.f/invdt);
 }
+
+static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCacheKey *result)
+{
+	int i=0;
+	ParticleCacheKey *cur = first;
+
+	/* scale the requested time to fit the entire path even if the path is cut early */
+	t *= (first+first->steps)->time;
+
+	while(i<first->steps && cur->time < t)
+		cur++;
+
+	if(cur->time == t)
+		*result = *cur;
+	else {
+		float dt = (t-(cur-1)->time)/(cur->time-(cur-1)->time);
+		interp_v3_v3v3(result->co, (cur-1)->co, cur->co, dt);
+		interp_v3_v3v3(result->vel, (cur-1)->vel, cur->vel, dt);
+		interp_qt_qtqt(result->rot, (cur-1)->rot, cur->rot, dt);
+		result->time = t;
+	}
+
+	/* first is actual base rotation, others are incremental from first */
+	if(cur==first || cur-1==first)
+		copy_qt_qt(result->rot, first->rot);
+	else
+		mul_qt_qtqt(result->rot, first->rot, result->rot);
+}
+
 /************************************************/
 /*			Particles on a dm					*/
 /************************************************/
@@ -2648,6 +2677,8 @@
 			/* offset the child from the parent position */
 			offset_child(cpa, (ParticleKey*)(key[0]+k), par_rot, (ParticleKey*)child, part->childflat, part->childrad);
 		}
+
+		child->time = (float)k/(float)ctx->steps;
 	}
 
 	/* apply effectors */
@@ -3009,6 +3040,8 @@
 
 			if(k==1)
 				copy_v3_v3((ca-1)->vel, ca->vel);
+
+			ca->time = (float)k/(float)steps;
 		}
 		/* First rotation is based on emitting face orientation.
 		 * This is way better than having flipping rotations resulting
@@ -4013,84 +4046,105 @@
 	CLAMP(t, 0.0f, 1.0f);
 
 	if(p<totpart){
-		pa = psys->particles + p;
-		pind.keyed = keyed;
-		pind.cache = cached ? psys->pointcache : NULL;
-		pind.epoint = NULL;
-		pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
-		/* pind.dm disabled in editmode means we dont get effectors taken into
-		 * account when subdividing for instance */
-		pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm;
-		init_particle_interpolation(sim->ob, psys, pa, &pind);
-		do_particle_interpolation(psys, p, pa, t, &pind, state);
-
-		if(pind.dm) {
-			mul_m4_v3(sim->ob->obmat, state->co);
-			mul_mat3_m4_v3(sim->ob->obmat, state->vel);
+		/* interpolate pathcache directly if it exist */
+		if(psys->pathcache) {
+			ParticleCacheKey result;
+			interpolate_pathcache(psys->pathcache[p], t, &result);
+			copy_v3_v3(state->co, result.co);
+			copy_v3_v3(state->vel, result.vel);
+			copy_qt_qt(state->rot, result.rot);
 		}
-		else if(!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
-			if((pa->flag & PARS_REKEY)==0) {
-				psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat);
-				mul_m4_v3(hairmat, state->co);
-				mul_mat3_m4_v3(hairmat, state->vel);
+		/* otherwise interpolate with other means */
+		else {
+			pa = psys->particles + p;
 
-				if(sim->psys->effectors && (part->flag & PART_CHILD_GUIDE)==0) {
-					do_guides(sim->psys->effectors, state, p, state->time);
-					/* TODO: proper velocity handling */
-				}
+			pind.keyed = keyed;
+			pind.cache = cached ? psys->pointcache : NULL;
+			pind.epoint = NULL;
+			pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
+			/* pind.dm disabled in editmode means we dont get effectors taken into
+			 * account when subdividing for instance */
+			pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm;
+			init_particle_interpolation(sim->ob, psys, pa, &pind);
+			do_particle_interpolation(psys, p, pa, t, &pind, state);
 
-				if(psys->lattice && edit==0)
-					calc_latt_deform(psys->lattice, state->co,1.0f);
+			if(pind.dm) {
+				mul_m4_v3(sim->ob->obmat, state->co);
+				mul_mat3_m4_v3(sim->ob->obmat, state->vel);
 			}
+			else if(!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
+				if((pa->flag & PARS_REKEY)==0) {
+					psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat);
+					mul_m4_v3(hairmat, state->co);
+					mul_mat3_m4_v3(hairmat, state->vel);
+
+					if(sim->psys->effectors && (part->flag & PART_CHILD_GUIDE)==0) {
+						do_guides(sim->psys->effectors, state, p, state->time);
+						/* TODO: proper velocity handling */
+					}
+
+					if(psys->lattice && edit==0)
+						calc_latt_deform(psys->lattice, state->co,1.0f);
+				}
+			}
 		}
 	}
 	else if(totchild){
 		//invert_m4_m4(imat,ob->obmat);
 
-		cpa=psys->child+p-totpart;
+		/* interpolate childcache directly if it exists */
+		if(psys->childcache) {
+			ParticleCacheKey result;
+			interpolate_pathcache(psys->childcache[p-totpart], t, &result);
+			copy_v3_v3(state->co, result.co);
+			copy_v3_v3(state->vel, result.vel);
+			copy_qt_qt(state->rot, result.rot);
+		}
+		else {
+			cpa=psys->child+p-totpart;
 
-		if(state->time < 0.0f)
-			t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
+			if(state->time < 0.0f)
+				t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
 		
-		if(totchild && part->childtype==PART_CHILD_FACES){
-			/* part->parents could still be 0 so we can't test with totparent */
-			between=1;
-		}
-		if(between){
-			int w = 0;
-			float foffset;
-
-			/* get parent states */
-			while(w<4 && cpa->pa[w]>=0){
-				keys[w].time = state->time;
-				psys_get_particle_on_path(sim, cpa->pa[w], keys+w, 1);
-				w++;
+			if(totchild && part->childtype==PART_CHILD_FACES){
+				/* part->parents could still be 0 so we can't test with totparent */
+				between=1;
 			}
+			if(between){
+				int w = 0;
+				float foffset;
 
-			/* get the original coordinates (orco) for texture usage */
-			cpa_num=cpa->num;
+				/* get parent states */
+				while(w<4 && cpa->pa[w]>=0){
+					keys[w].time = state->time;
+					psys_get_particle_on_path(sim, cpa->pa[w], keys+w, 1);
+					w++;
+				}
+
+				/* get the original coordinates (orco) for texture usage */
+				cpa_num=cpa->num;
 			
-			foffset= cpa->foffset;
-			cpa_fuv = cpa->fuv;
-			cpa_from = PART_FROM_FACE;
+				foffset= cpa->foffset;
+				cpa_fuv = cpa->fuv;
+				cpa_from = PART_FROM_FACE;
 
-			psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,0,0,0,orco,0);
+				psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,0,0,0,orco,0);
 
-			/* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
-			//copy_v3_v3(cpa_1st,co);
+				/* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
+				//copy_v3_v3(cpa_1st,co);
 
-			//mul_m4_v3(ob->obmat,cpa_1st);
+				//mul_m4_v3(ob->obmat,cpa_1st);
 
-			pa = psys->particles + cpa->parent;
+				pa = psys->particles + cpa->parent;
 
-			if(part->type == PART_HAIR)
-				psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
-			else
-				unit_m4(hairmat);
+				if(part->type == PART_HAIR)
+					psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
+				else
+					unit_m4(hairmat);
 
-			pa=0;
-		}
-		else{
+				pa=0;
+			}
+																					else{
 			/* get the parent state */
 			keys->time = state->time;
 			psys_get_particle_on_path(sim, cpa->parent, keys,1);
@@ -4114,74 +4168,75 @@
 			}
 		}
 
-		/* correct child ipo timing */
-#if 0 // XXX old animation system
-		if((part->flag&PART_ABS_TIME)==0 && part->ipo){
-			calc_ipo(part->ipo, 100.0f*t);
-			execute_ipo((ID *)part, part->ipo);
-		}
-#endif // XXX old animation system
+			/* correct child ipo timing */
+	#if 0 // XXX old animation system
+			if((part->flag&PART_ABS_TIME)==0 && part->ipo){
+				calc_ipo(part->ipo, 100.0f*t);
+				execute_ipo((ID *)part, part->ipo);
+			}
+	#endif // XXX old animation system
 		
-		/* get different child parameters from textures & vgroups */
-		memset(&ctx, 0, sizeof(ParticleThreadContext));
-		ctx.sim = *sim;
-		ctx.dm = psmd->dm;
-		ctx.ma = ma;
-		/* TODO: assign vertex groups */
-		get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
+			/* get different child parameters from textures & vgroups */
+			memset(&ctx, 0, sizeof(ParticleThreadContext));
+			ctx.sim = *sim;
+			ctx.dm = psmd->dm;
+			ctx.ma = ma;
+			/* TODO: assign vertex groups */
+			get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
 
-		if(between){
-			int w=0;
+			if(between){
+				int w=0;
 
-			state->co[0] = state->co[1] = state->co[2] = 0.0f;
-			state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
+				state->co[0] = state->co[1] = state->co[2] = 0.0f;
+				state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
 
-			/* child position is the weighted sum of parent positions */
-			while(w<4 && cpa->pa[w]>=0){
-				state->co[0] += cpa->w[w] * keys[w].co[0];
-				state->co[1] += cpa->w[w] * keys[w].co[1];
-				state->co[2] += cpa->w[w] * keys[w].co[2];
+				/* child position is the weighted sum of parent positions */
+				while(w<4 && cpa->pa[w]>=0){
+					state->co[0] += cpa->w[w] * keys[w].co[0];
+					state->co[1] += cpa->w[w] * keys[w].co[1];
+					state->co[2] += cpa->w[w] * keys[w].co[2];
 
-				state->vel[0] += cpa->w[w] * keys[w].vel[0];
-				state->vel[1] += cpa->w[w] * keys[w].vel[1];
-				state->vel[2] += cpa->w[w] * keys[w].vel[2];
-				w++;
+					state->vel[0] += cpa->w[w] * keys[w].vel[0];
+					state->vel[1] += cpa->w[w] * keys[w].vel[1];
+					state->vel[2] += cpa->w[w] * keys[w].vel[2];
+					w++;
+				}
+				/* apply offset for correct positioning */
+				//add_v3_v3(state->co, cpa_1st);
 			}
-			/* apply offset for correct positioning */
-			//add_v3_v3(state->co, cpa_1st);
-		}
-		else{
-			/* offset the child from the parent position */
-			offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad);
-		}
+			else{
+				/* offset the child from the parent position */
+				offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad);
+			}
 
-		par = keys;
+			par = keys;
 
-		if(vel)
-			copy_particle_key(&tstate, state, 1);
+			if(vel)
+				copy_particle_key(&tstate, state, 1);
 
-		/* apply different deformations to the child path */

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list