Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2005-04-04 22:09:47 +0400
committerTon Roosendaal <ton@blender.org>2005-04-04 22:09:47 +0400
commit7a377bcb05c2634a872208680aca80cc9e9a0c11 (patch)
tree787ce3fb287b9206f6a5084b25551c8fb2735979 /source/blender/blenkernel
parent04e4b72e063702dc16cf41dd97c5776d03742bde (diff)
- Made SoftBody work with Particle Force Fields.
- Added new (Particle) Deflector; type Wind. Wind gives constant directional force. It is animatable (Ipos) and reacts to Object scaling. Also uses FallOff. Works for particles and SoftBody quick movie check; http://www.blender.org/bf/0001_0250.avi test file is in download.blender.org/demo/test/wind_soft.blend - Added MaxDist option for forcefields, to control its influence better. Is drawn as circle in 3d window. Forcefields are a bit weak still... should react to scaling, or not; in that case drawing should indicate it (done for spherical field now).
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_effect.h8
-rw-r--r--source/blender/blenkernel/intern/effect.c122
-rw-r--r--source/blender/blenkernel/intern/softbody.c82
3 files changed, 157 insertions, 55 deletions
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index 21663b39dd3..a5ca3708a22 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -61,5 +61,13 @@ void build_particle_system(struct Object *ob);
void calc_wave_deform(struct WaveEff *wav, float ctime, float *co);
int object_wave(struct Object *ob);
+/* particle deflector */
+void pdDoEffector(float *opco, float *force, float *speed, float cur_time, unsigned int par_layer);
+int pdDoDeflection(float opco[3], float npco[3], float opno[3],
+ float npno[3], float life, float force[3], int def_depth,
+ float cur_time, unsigned int par_layer, int *last_object,
+ int *last_face, int *same_face);
+
+
#endif
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 6fe6b708f58..d811b5c0fbb 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -380,11 +380,18 @@ static int linetriangle(float p1[3], float p2[3], float v0[3], float v1[3], floa
return 1;
}
-static void get_effector(float opco[], float force[], float speed[], float cur_time, unsigned int par_layer)
+/* -------- pdDoEffector() --------
+ generic force/speed system, now used for particles and softbodies
+ opco = global coord, as input
+ force = force accumulator
+ speed = speed accumulator
+ cur_time = in frames
+ par_layer = layer the caller is in
+
+*/
+void pdDoEffector(float *opco, float *force, float *speed, float cur_time, unsigned int par_layer)
{
/*
- Particle effector field code
-
Modifies the force on a particle according to its
relation with the effector object
Different kind of effectors include:
@@ -397,46 +404,75 @@ static void get_effector(float opco[], float force[], float speed[], float cur_t
*/
Object *ob;
Base *base;
+ PartDeflect *pd;
float vect_to_vert[3];
float force_vec[3];
float f_force, distance;
- float obloc[3];
+ float *obloc;
float force_val, ffall_val;
short cur_frame;
/* Cycle through objects, get total of (1/(gravity_strength * dist^gravity_power)) */
- /* Check for min distance here? */
- base = G.scene->base.first;
- while (base) {
- if(base->lay & par_layer) {
+ /* Check for min distance here? (yes would be cool to add that, ton) */
+
+ for(base = G.scene->base.first; base; base= base->next) {
+ if( (base->lay & par_layer) && base->object->pd) {
ob= base->object;
- if(ob->pd && ob->pd->forcefield == PFIELD_FORCE) {
-
- /* Need to set r.cfra for paths (investigate, ton) */
+ pd= ob->pd;
+
+ /* checking if to continue or not */
+ if(pd->forcefield==0) continue;
+
+ /* 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;
+
+
+ /* 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 = (short)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)
+ ; /* don't do anything */
+ else if(pd->forcefield == PFIELD_WIND) {
+ VECCOPY(force_vec, ob->obmat[2]);
- /* only use center of object */
- obloc[0] = ob->obmat[3][0];
- obloc[1] = ob->obmat[3][1];
- obloc[2] = ob->obmat[3][2];
+ /* wind works harder perpendicular to normal, would be nice for softbody later (ton) */
- /* 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 = ob->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 = ob->pd->f_power;
+ /* 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)));
+
+ 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];
/* Now calculate the gravitational force */
VECSUB(vect_to_vert, obloc, opco);
- distance = Normalise(vect_to_vert);
+ distance = VecLength(vect_to_vert);
/* Limit minimum distance to vertex so that */
/* the force is not too big */
@@ -447,33 +483,14 @@ static void get_effector(float opco[], float force[], float speed[], float cur_t
force[2] += (vect_to_vert[2] * f_force );
}
- else if(ob->pd && ob->pd->forcefield == PFIELD_VORTEX) {
- /* Need to set r.cfra for paths (investigate, ton) */
- cur_frame = G.scene->r.cfra;
- G.scene->r.cfra = (short)cur_time;
- where_is_object_time(ob, cur_time);
- G.scene->r.cfra = cur_frame;
-
- /* only use center of object */
- obloc[0] = ob->obmat[3][0];
- obloc[1] = ob->obmat[3][1];
- obloc[2] = ob->obmat[3][2];
-
- /* 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 = ob->pd->f_strength;
+ else if(pd->forcefield == PFIELD_VORTEX) {
- if (has_ipo_code(ob->ipo, OB_PD_FFALL))
- ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, cur_time);
- else
- ffall_val = ob->pd->f_power;
+ /* only use center of object */
+ obloc= ob->obmat[3];
/* Now calculate the vortex force */
VECSUB(vect_to_vert, obloc, opco);
-
- distance = Normalise(vect_to_vert);
+ distance = VecLength(vect_to_vert);
Crossf(force_vec, ob->obmat[2], vect_to_vert);
Normalise(force_vec);
@@ -488,7 +505,6 @@ static void get_effector(float opco[], float force[], float speed[], float cur_t
}
}
- base = base->next;
}
}
@@ -513,7 +529,7 @@ static void cache_object_vertices(Object *ob)
}
}
-static int get_deflection(float opco[3], float npco[3], float opno[3],
+int pdDoDeflection(float opco[3], float npco[3], float opno[3],
float npno[3], float life, float force[3], int def_depth,
float cur_time, unsigned int par_layer, int *last_object,
int *last_face, int *same_face)
@@ -875,7 +891,7 @@ void make_particle_keys(int depth, int nr, PartEff *paf, Particle *part, float *
/* Check force field */
cur_time = pa->time;
- get_effector(opco, new_force, new_speed, cur_time, par_layer);
+ pdDoEffector(opco, new_force, new_speed, cur_time, par_layer);
/* new location */
pa->co[0]= opa->co[0] + deltalife * (opa->no[0] + new_speed[0] + 0.5f*new_force[0]);
@@ -910,7 +926,7 @@ void make_particle_keys(int depth, int nr, PartEff *paf, Particle *part, float *
/* Bail out if we've done the calculation 10 times - this seems ok */
/* for most scenes I've tested */
while (finish_defs) {
- deflected = get_deflection(opco, npco, opno, npno, life, new_force,
+ deflected = pdDoDeflection(opco, npco, opno, npno, life, new_force,
def_count, cur_time, par_layer,
&last_ob, &last_fc, &same_fc);
if (deflected) {
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 240dfffa438..30e244eee93 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -69,6 +69,7 @@ variables on the UI for now
#include "BLI_arithb.h"
#include "BKE_displist.h"
+#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_object.h"
#include "BKE_softbody.h"
@@ -268,6 +269,22 @@ static void Vec3PlusStVec(float *v, float s, float *v1)
v[2] += s*v1[2];
}
+#define USES_FIELD 1
+#define USES_DEFLECT 2
+static int is_there_deflection(unsigned int layer)
+{
+ Base *base;
+ int retval= 0;
+
+ for(base = G.scene->base.first; base; base= base->next) {
+ if( (base->lay & layer) && base->object->pd) {
+ if(base->object->pd->forcefield) retval |= USES_FIELD;
+ if(base->object->pd->deflect) retval |= USES_DEFLECT;
+ }
+ }
+ return retval;
+}
+
static void softbody_calc_forces(Object *ob, float dtime)
{
@@ -276,13 +293,16 @@ static void softbody_calc_forces(Object *ob, float dtime)
BodyPoint *bproot;
BodySpring *bs;
float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3];
- int a, b;
+ int a, b, do_effector;
/* clear forces */
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
}
+ /* check! */
+ do_effector= is_there_deflection(ob->lay);
+
gravity = sb->nodemass * sb->grav * rescale_grav_to_framerate;
iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
bproot= sb->bpoint; /* need this for proper spring addressing */
@@ -334,6 +354,49 @@ static void softbody_calc_forces(Object *ob, float dtime)
/* this is the place where other forces can be added
yes, constraints and collision stuff should go here too (read baraff papers on that!)
*/
+
+ /* particle field & deflectors */
+ if(do_effector & USES_FIELD) {
+ float force[3]= {0.0f, 0.0f, 0.0f};
+ float speed[3]= {0.0f, 0.0f, 0.0f};
+
+ pdDoEffector(bp->pos, force, speed, (float)G.scene->r.cfra, ob->lay);
+ /* apply force */
+ // VecMulf(force, rescale_grav_to_framerate); <- didn't work, made value far too low!
+ VECADD(bp->force, bp->force, force);
+ /* apply speed. note; deflector can give 'speed' only.... */
+ VecMulf(speed, rescale_grav_to_framerate);
+ VECADD(bp->vec, bp->vec, speed);
+ }
+#if 0
+ /* copied from particles... doesn't work really! */
+ if(do_effector & USES_DEFLECT) {
+ int deflected;
+ int last_ob = -1;
+ int last_fc = -1;
+ int same_fc = 0;
+ float last[3], lastv[3];
+ int finish_defs = 1;
+ int def_count = 0;
+
+ VecSubf(last, bp->pos, bp->vec);
+ VECCOPY(lastv, bp->vec);
+
+ while (finish_defs) {
+ deflected= pdDoDeflection(last, bp->pos, lastv,
+ bp->vec, dtime, bp->force, 0,
+ G.scene->r.cfra, ob->lay, &last_ob, &last_fc, &same_fc);
+ if (deflected) {
+ def_count = def_count + 1;
+ //deflection = 1;
+ if (def_count==10) finish_defs = 0;
+ }
+ else {
+ finish_defs = 0;
+ }
+ }
+ }
+#endif
/*other forces done*/
/* nice things could be done with anisotropic friction
@@ -974,7 +1037,7 @@ void sbObjectReset(Object *ob)
bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0f;
// no idea about the Heun stuff! (ton)
- VECCOPY(bp->prevpos, bp->vec);
+ VECCOPY(bp->prevpos, bp->pos);
VECCOPY(bp->prevvec, bp->vec);
VECCOPY(bp->prevdx, bp->vec);
VECCOPY(bp->prevdv, bp->vec);
@@ -987,6 +1050,7 @@ void sbObjectReset(Object *ob)
void sbObjectStep(Object *ob, float framenr)
{
SoftBody *sb;
+ Base *base;
float dtime;
int timescale,t;
float ctime, forcetime;
@@ -1003,6 +1067,11 @@ void sbObjectStep(Object *ob, float framenr)
/* still no points? go away */
if(sb->totpoint==0) return;
+ /* reset deflector cache, sumohandle is free, but its still sorta abuse... (ton) */
+ for(base= G.scene->base.first; base; base= base->next) {
+ base->object->sumohandle= NULL;
+ }
+
/* checking time: */
ctime= bsystem_time(ob, NULL, framenr, 0.0);
softbody_scale_time(steptime); // translate frames/sec and lenghts unit to SI system
@@ -1124,5 +1193,14 @@ void sbObjectStep(Object *ob, float framenr)
// so here it is !
softbody_to_object(ob);
}
+
+ /* reset deflector cache */
+ for(base= G.scene->base.first; base; base= base->next) {
+ if(base->object->sumohandle) {
+ MEM_freeN(base->object->sumohandle);
+ base->object->sumohandle= NULL;
+ }
+ }
+
}