[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16168] trunk/blender/source/blender: a) New unified effector system by Janne (jahka) + Me (genscher): particle and cloth/sb don't use different systems anymore.

Daniel Genrich daniel.genrich at gmx.net
Mon Aug 18 13:09:27 CEST 2008


Revision: 16168
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16168
Author:   genscher
Date:     2008-08-18 13:09:27 +0200 (Mon, 18 Aug 2008)

Log Message:
-----------
a) New unified effector system by Janne (jahka) + Me (genscher): particle and cloth/sb don't use different systems anymore. b) cloth wind corrected for new system c) Wind has noise option now d) @ Bjornmose: since the old factors are gone SB doesn't need to divide by 1000 etc. anymore. I didn't want to touch your code - you might like to take a look at it :) 

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_effect.h
    trunk/blender/source/blender/blenkernel/intern/effect.c
    trunk/blender/source/blender/blenkernel/intern/implicit.c
    trunk/blender/source/blender/blenkernel/intern/particle_system.c
    trunk/blender/source/blender/blenlib/BLI_rand.h
    trunk/blender/source/blender/blenlib/intern/rand.c
    trunk/blender/source/blender/blenloader/intern/readfile.c
    trunk/blender/source/blender/makesdna/DNA_object_force.h
    trunk/blender/source/blender/src/buttons_object.c

Modified: trunk/blender/source/blender/blenkernel/BKE_effect.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_effect.h	2008-08-18 10:48:37 UTC (rev 16167)
+++ trunk/blender/source/blender/blenkernel/BKE_effect.h	2008-08-18 11:09:27 UTC (rev 16168)
@@ -37,6 +37,7 @@
 struct ListBase;
 struct Particle;
 struct Group;
+struct RNG;
 
 typedef struct pEffectorCache {
 	struct pEffectorCache *next, *prev;
@@ -64,7 +65,12 @@
 void			pdEndEffectors(struct ListBase *lb);
 void			pdDoEffectors(struct ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags);
 
+/* required for particle_system.c */
+void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise);
+float effector_falloff(struct PartDeflect *pd, float *eff_velocity, float *vec_to_part);
 
 
+
+
 #endif
 

Modified: trunk/blender/source/blender/blenkernel/intern/effect.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/effect.c	2008-08-18 10:48:37 UTC (rev 16167)
+++ trunk/blender/source/blender/blenkernel/intern/effect.c	2008-08-18 11:09:27 UTC (rev 16168)
@@ -157,6 +157,13 @@
 		}
 	}
 	else if(pd->forcefield) {
+		
+		if(pd->forcefield == PFIELD_WIND)
+		{
+			pd->rng = rng_new(1);
+			rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed
+		}
+	
 		ec= MEM_callocN(sizeof(pEffectorCache), "effector cache");
 		ec->ob= ob;
 		BLI_addtail(lb, ec);
@@ -205,13 +212,189 @@
 		pEffectorCache *ec;
 		/* restore full copy */
 		for(ec= lb->first; ec; ec= ec->next)
+		{
+			if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND))
+				rng_free(ec->ob->pd->rng);
+			
 			*(ec->ob)= ec->obcopy;
+		}
 
 		BLI_freelistN(lb);
 	}
 }
 
 
+/************************************************/
+/*			Effectors		*/
+/************************************************/
+
+// noise function for wind e.g.
+static float wind_func(struct RNG *rng, float strength)
+{
+	int random = (rng_getInt(rng)+1) % 65535; // max 2357
+	float force = rng_getFloat(rng) + 1.0f;
+	float ret;
+	float sign = 0;
+	
+	sign = (random > 32000.0) ? 1.0: -1.0; // dividing by 2 is not giving equal sign distribution
+	
+	ret = sign*((float)random / force)*strength/65535.0f;
+	
+	return ret;
+}
+
+
+static float falloff_func(float fac, int usemin, float mindist, int usemax, float maxdist, float power)
+{
+	if(!usemin)
+		mindist= 0.0f;
+
+	if(fac < mindist) {
+		return 1.0f;
+	}
+	else if(usemax) {
+		if(fac>maxdist || (maxdist-mindist)<=0.0f)
+			return 0.0f;
+
+		fac= (fac-mindist)/(maxdist-mindist);
+		return 1.0f - (float)pow((double)fac, (double)power);
+	}
+	else
+		return pow((double)1.0f+fac-mindist, (double)-power);
+}
+
+static float falloff_func_dist(PartDeflect *pd, float fac)
+{
+	return falloff_func(fac, pd->flag&PFIELD_USEMIN, pd->mindist, pd->flag&PFIELD_USEMAX, pd->maxdist, pd->f_power);
+}
+
+static float falloff_func_rad(PartDeflect *pd, float fac)
+{
+	return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r);
+}
+
+float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part)
+{
+	float eff_dir[3], temp[3];
+	float falloff=1.0, fac, r_fac;
+	
+	VecCopyf(eff_dir,eff_velocity);
+	Normalize(eff_dir);
+
+	if(pd->flag & PFIELD_POSZ && Inpf(eff_dir,vec_to_part)<0.0f)
+		falloff=0.0f;
+	else switch(pd->falloff){
+		case PFIELD_FALL_SPHERE:
+			fac=VecLength(vec_to_part);
+			falloff= falloff_func_dist(pd, fac);
+			break;
+
+		case PFIELD_FALL_TUBE:
+			fac=Inpf(vec_to_part,eff_dir);
+			falloff= falloff_func_dist(pd, ABS(fac));
+			if(falloff == 0.0f)
+				break;
+
+			VECADDFAC(temp,vec_to_part,eff_dir,-fac);
+			r_fac=VecLength(temp);
+			falloff*= falloff_func_rad(pd, r_fac);
+			break;
+		case PFIELD_FALL_CONE:
+			fac=Inpf(vec_to_part,eff_dir);
+			falloff= falloff_func_dist(pd, ABS(fac));
+			if(falloff == 0.0f)
+				break;
+
+			r_fac=saacos(fac/VecLength(vec_to_part))*180.0f/(float)M_PI;
+			falloff*= falloff_func_rad(pd, r_fac);
+
+			break;
+	}
+
+	return falloff;
+}
+
+void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise)
+{
+	float mag_vec[3]={0,0,0};
+	float temp[3], temp2[3];
+	float eff_vel[3];
+	float wind = 0;
+
+	VecCopyf(eff_vel,eff_velocity);
+	Normalize(eff_vel);
+
+	switch(type){
+		case PFIELD_WIND:
+			VECCOPY(mag_vec,eff_vel);
+			
+			// add wind noise here
+			if(noise> 0.0f)
+				wind = wind_func(rng, noise);
+
+			VecMulf(mag_vec,(force_val+wind)*falloff);
+			VecAddf(field,field,mag_vec);
+			break;
+
+		case PFIELD_FORCE:
+			if(planar)
+				Projf(mag_vec,vec_to_part,eff_vel);
+			else
+				VecCopyf(mag_vec,vec_to_part);
+
+			VecMulf(mag_vec,force_val*falloff);
+			VecAddf(field,field,mag_vec);
+			break;
+
+		case PFIELD_VORTEX:
+			Crossf(mag_vec,eff_vel,vec_to_part);
+			Normalize(mag_vec);
+
+			VecMulf(mag_vec,force_val*distance*falloff);
+			VecAddf(field,field,mag_vec);
+
+			break;
+		case PFIELD_MAGNET:
+			if(planar)
+				VecCopyf(temp,eff_vel);
+			else
+				/* magnetic field of a moving charge */
+				Crossf(temp,eff_vel,vec_to_part);
+
+			Crossf(temp2,velocity,temp);
+			VecAddf(mag_vec,mag_vec,temp2);
+
+			VecMulf(mag_vec,force_val*falloff);
+			VecAddf(field,field,mag_vec);
+			break;
+		case PFIELD_HARMONIC:
+			if(planar)
+				Projf(mag_vec,vec_to_part,eff_vel);
+			else
+				VecCopyf(mag_vec,vec_to_part);
+
+			VecMulf(mag_vec,force_val*falloff);
+			VecSubf(field,field,mag_vec);
+
+			VecCopyf(mag_vec,velocity);
+			/* 1.9 is an experimental value to get critical damping at damp=1.0 */
+			VecMulf(mag_vec,damp*1.9f*(float)sqrt(force_val));
+			VecSubf(field,field,mag_vec);
+			break;
+		case PFIELD_NUCLEAR:
+			/*pow here is root of cosine expression below*/
+			//rad=(float)pow(2.0,-1.0/power)*distance/size;
+			//VECCOPY(mag_vec,vec_to_part);
+			//Normalize(mag_vec);
+			//VecMulf(mag_vec,(float)cos(3.0*M_PI/2.0*(1.0-1.0/(pow(rad,power)+1.0)))/(rad+0.2f));
+			//VECADDFAC(field,field,mag_vec,force_val);
+			break;
+	}
+}
+
+
+
+
 /*  -------- pdDoEffectors() --------
     generic force/speed system, now used for particles and softbodies
 	lb			= listbase with objects that take part in effecting
@@ -244,13 +427,10 @@
 	pEffectorCache *ec;
 	PartDeflect *pd;
 	float vect_to_vert[3];
-	float f_force, force_vec[3];
 	float *obloc;
-	float distance, force_val, ffall_val;
-	float guidecollect[3], guidedist= 0.0f;
-	int cur_frame;
 	
-	guidecollect[0]= guidecollect[1]= guidecollect[2]=0.0f;
+	float distance, vec_to_part[3];
+	float falloff;
 
 	/* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
 	/* Check for min distance here? (yes would be cool to add that, ton) */
@@ -261,178 +441,32 @@
 		pd= ob->pd;
 			
 		/* Get IPO force strength and fall off values here */
-		if (has_ipo_code(ob->ipo, OB_PD_FSTR))
-			force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, cur_time);
-		else 
-			force_val = pd->f_strength;
-		
-		if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
-			ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, cur_time);
-		else 
-			ffall_val = pd->f_power;
+		where_is_object_time(ob,cur_time);
 			
-		/* Need to set r.cfra for paths (investigate, ton) (uses ob->ctime now, ton) */
-		if(ob->ctime!=cur_time) {
-			cur_frame = G.scene->r.cfra;
-			G.scene->r.cfra = (int)cur_time;
-			where_is_object_time(ob, cur_time);
-			G.scene->r.cfra = cur_frame;
-		}
-			
 		/* use center of object for distance calculus */
 		obloc= ob->obmat[3];
 		VECSUB(vect_to_vert, obloc, opco);
 		distance = VecLength(vect_to_vert);
-			
-		if((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist && pd->forcefield != PFIELD_GUIDE)
-			;	/* don't do anything */
-		else if((pd->flag & PFIELD_USEMIN) && distance<pd->mindist && pd->forcefield != PFIELD_GUIDE)
-			;	/* don't do anything */
-		else if(pd->forcefield == PFIELD_WIND) {
-			VECCOPY(force_vec, ob->obmat[2]);
-			
-			/* wind works harder perpendicular to normal, would be nice for softbody later (ton) */
-			
-			/* Limit minimum distance to vertex so that */
-			/* the force is not too big */
-			if (distance < 0.001) distance = 0.001f;
-			f_force = (force_val)*(1/(1000 * (float)pow((double)distance, (double)ffall_val)));
-			/* this option for softbody only */
-			if(flags && PE_WIND_AS_SPEED){
-				speed[0] -= (force_vec[0] * f_force );
-				speed[1] -= (force_vec[1] * f_force );
-				speed[2] -= (force_vec[2] * f_force );
-			}
-			else{
-				force[0] += force_vec[0]*f_force;
-				force[1] += force_vec[1]*f_force;
-				force[2] += force_vec[2]*f_force;
-			}
-		}
-		else if(pd->forcefield == PFIELD_FORCE) {
-			
-			/* only use center of object */
-			obloc= ob->obmat[3];
+		
+		VecSubf(vec_to_part, opco, ob->obmat[3]);
+		distance = VecLength(vec_to_part);
 
-			/* Now calculate the gravitational force */
-			VECSUB(vect_to_vert, obloc, opco);
-			distance = VecLength(vect_to_vert);
+		falloff=effector_falloff(pd,ob->obmat[2],vec_to_part);
 
-			/* Limit minimum distance to vertex so that */
-			/* the force is not too big */
-			if (distance < 0.001) distance = 0.001f;
-			f_force = (force_val)*(1.0/(1000.0 * (float)pow((double)distance, (double)ffall_val)));
-			force[0] += (vect_to_vert[0] * f_force );
-			force[1] += (vect_to_vert[1] * f_force );
-			force[2] += (vect_to_vert[2] * f_force );
-		}
-		else if(pd->forcefield == PFIELD_VORTEX) {
-			float vortexvec[3];
+		if(falloff<=0.0f)
+			;	/* don't do anything */
+		else {
+			float field[3]={0,0,0}, tmp[3];
+			VECCOPY(field, force);
+			do_physical_effector(pd->forcefield,pd->f_strength,distance,
+								falloff,pd->f_dist,pd->f_damp,ob->obmat[2],vec_to_part,
+								speed,force,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise);
 			
-			/* only use center of object */
-			obloc= ob->obmat[3];
-
-			/* Now calculate the vortex force */
-			VECSUB(vect_to_vert, obloc, opco);
-			distance = VecLength(vect_to_vert);
-
-			Crossf(force_vec, ob->obmat[2], vect_to_vert);
-			Normalize(force_vec);
-
-			/* Limit minimum distance to vertex so that */
-			/* the force is not too big */
-			if (distance < 0.001) distance = 0.001f;

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list