- Made SoftBody work with Particle Force Fields.
authorTon Roosendaal <ton@blender.org>
Mon, 4 Apr 2005 18:09:47 +0000 (18:09 +0000)
committerTon Roosendaal <ton@blender.org>
Mon, 4 Apr 2005 18:09:47 +0000 (18:09 +0000)
- 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).

source/blender/blenkernel/BKE_effect.h
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/softbody.c
source/blender/makesdna/DNA_effect_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/src/buttons_object.c
source/blender/src/drawobject.c

index 21663b39dd389a5044089173ca4acef3dff7925c..a5ca3708a226dda93e392b12031b73bb83c69924 100644 (file)
@@ -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
 
index 6fe6b708f58bad0fed9f0fe6a03e1d988e1cd835..d811b5c0fbb1bb07cc0c7379a4c2369a29faff88 100644 (file)
@@ -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) {
index 240dfffa4385699e92c8dbb6911c40d97c25f463..30e244eee9368e27362b38cebfae5c9770678752 100644 (file)
@@ -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;
+               }
+       }
+       
 }
 
index 86dd2f299c3592f3f05deeb11c45f85555f883ba..dc3118b7f73ba6175fbd88712b25e66a6022e811 100644 (file)
 #define WAV_Y                  4
 #define WAV_CYCL               8
 
-       /* Effector Fields types */
-#define PFIELD_FORCE   1
-#define PFIELD_VORTEX  2
-#define PFIELD_MAGNET  3
-
 typedef struct Effect {
        struct Effect *next, *prev;
        short type, flag, buttype, rt;
index fb11938c442b0d972da24a40b1e43d61598323a6..1e1c0760889e2a7badbacd7774703869fa536ec9 100644 (file)
@@ -80,17 +80,30 @@ typedef struct LBuf {
 } LBuf;
 
 typedef struct PartDeflect {
-       short deflect;        /* Deflection flag - does mesh deflect particles*/
-       short forcefield;      /* Force flag, do the vertices attract / repel particles ? */
-
-       float pdef_damp;     /* Damping factor for particle deflection       */
-       float pdef_rdamp;    /* Random element of damping for deflection     */
-       float pdef_perm;     /* Chance of particle passing through mesh      */
+       short deflect;          /* Deflection flag - does mesh deflect particles*/
+       short forcefield;       /* Force field type, do the vertices attract / repel particles ? */
+       short flag;                     /* general settings flag */
+       short pad;
+       
+       float pdef_damp;        /* Damping factor for particle deflection       */
+       float pdef_rdamp;       /* Random element of damping for deflection     */
+       float pdef_perm;        /* Chance of particle passing through mesh      */
 
-       float f_strength;    /* The strength of the force (+ or - )       */
-       float f_power;       /* The power law - real gravitation is 2 (square)  */
+       float f_strength;       /* The strength of the force (+ or - )       */
+       float f_power;          /* The power law - real gravitation is 2 (square)  */
+       float maxdist;          /* if indicated, use this maximum */
 } PartDeflect;
 
+/* pd->forcefield:  Effector Fields types */
+#define PFIELD_FORCE   1
+#define PFIELD_VORTEX  2
+#define PFIELD_MAGNET  3
+#define PFIELD_WIND            4
+
+/* pd->flag: various settings */
+#define PFIELD_USEMAX  1
+
+
 typedef struct SoftBody {
        /* dynamic data */
        int totpoint, totspring;
index 7081e7540ac4b97980fbf69b970589c63278e03f..2fe7b758eb6600c46510792f367492a89204a90e 100644 (file)
@@ -1428,21 +1428,27 @@ static void object_panel_deflectors(Object *ob)
        }
        
        if(ob->pd) {
+               PartDeflect *pd= ob->pd;
+               
                uiBlockBeginAlign(block);
+               uiDefButS(block, ROW, REDRAWVIEW3D, "None",                     10,160,50,20, &pd->forcefield, 1.0, 0, 0, 0, "No force");
+               uiDefButS(block, ROW, REDRAWVIEW3D, "Wind",                     60,160,50,20, &pd->forcefield, 1.0, PFIELD_WIND, 0, 0, "Constant force applied in direction of Object Z axis");
+               uiDefButS(block, ROW, REDRAWVIEW3D, "Force field",      110,160,100,20, &pd->forcefield, 1.0, PFIELD_FORCE, 0, 0, "Object center attracts or repels particles");
+               uiDefButS(block, ROW, REDRAWVIEW3D, "Vortex field",     210,160,100,20, &pd->forcefield, 1.0, PFIELD_VORTEX, 0, 0, "Particles swirl around Z-axis of the object");
 
-               uiDefButS(block, ROW, REDRAWVIEW3D, "None",     10,160,200,20, &ob->pd->forcefield, 1.0, 0, 0, 0, "No force");
-               uiDefButS(block, ROW, REDRAWVIEW3D, "Force field",      10,140,200,20, &ob->pd->forcefield, 1.0, PFIELD_FORCE, 0, 0, "Object center attracts or repels particles");
-               uiDefButS(block, ROW, REDRAWVIEW3D, "Vortex field",     10,120,200,20, &ob->pd->forcefield, 1.0, PFIELD_VORTEX, 0, 0, "Particles swirl around Z-axis of the object");
+               uiBlockBeginAlign(block);
+               uiDefButF(block, NUM, REDRAWVIEW3D, "Strength: ",       10,130,150,20, &pd->f_strength, -1000, 1000, 1000, 0, "Strength of force field");
+               uiDefButF(block, NUM, REDRAWVIEW3D, "Fall-off: ",       160,130,150,20, &pd->f_power, 0, 10, 100, 0, "Falloff power (real gravitational fallof = 2)");
+               uiDefButBitS(block, TOG, PFIELD_USEMAX, REDRAWVIEW3D, "Use MaxDist",    10,110,150,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
+               uiDefButF(block, NUM, REDRAWVIEW3D, "MaxDist: ",        160,110,150,20, &pd->maxdist, 0, 1000.0, 100, 0, "Maximum distance for the field to work");
 
-               uiDefButF(block, NUM, REDRAWVIEW3D, "Strength: ",       10,100,200,20, &ob->pd->f_strength, -1000, 1000, 1000, 0, "Strength of force field");
-               uiDefButF(block, NUM, REDRAWVIEW3D, "Fall-off: ",       10,80,200,20, &ob->pd->f_power, 0, 10, 100, 0, "Falloff power (real gravitational fallof = 2)");
                /* only meshes collide now */
                if(ob->type==OB_MESH) {
                        uiBlockBeginAlign(block);
-                       uiDefButS(block, TOG|BIT|0, B_DIFF, "Deflection",10,50,200,20, &ob->pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
-                       uiDefButF(block, NUM, B_DIFF, "Damping: ",      10,30,200,20, &ob->pd->pdef_damp, 0.0, 1.0, 10, 0, "Amount of damping during particle collision");
-                       uiDefButF(block, NUM, B_DIFF, "Rnd Damping: ",  10,10,200,20, &ob->pd->pdef_rdamp, 0.0, 1.0, 10, 0, "Random variation of damping");
-                       uiDefButF(block, NUM, B_DIFF, "Permeability: ",         10,-10,200,20, &ob->pd->pdef_perm, 0.0, 1.0, 10, 0, "Chance that the particle will pass through the mesh");
+                       uiDefButS(block, TOG|BIT|0, B_DIFF, "Deflection",10,50,200,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
+                       uiDefButF(block, NUM, B_DIFF, "Damping: ",      10,30,200,20, &pd->pdef_damp, 0.0, 1.0, 10, 0, "Amount of damping during particle collision");
+                       uiDefButF(block, NUM, B_DIFF, "Rnd Damping: ",  10,10,200,20, &pd->pdef_rdamp, 0.0, 1.0, 10, 0, "Random variation of damping");
+                       uiDefButF(block, NUM, B_DIFF, "Permeability: ",         10,-10,200,20, &pd->pdef_perm, 0.0, 1.0, 10, 0, "Chance that the particle will pass through the mesh");
                }
                uiBlockEndAlign(block);
        }
index cc4a7043cdeaed6127199c0805667bfd6d587281..309cc7b449ebce67f3eb1bf0f92eed4ee39de70d 100644 (file)
@@ -2997,20 +2997,49 @@ static void drawmball(Object *ob, int dt)
 
 static void draw_forcefield(Object *ob)
 {
+       PartDeflect *pd= ob->pd;
        float imat[4][4], tmat[4][4];
        float vec[3]= {0.0, 0.0, 0.0};
        
-       if (ob->pd->forcefield == PFIELD_FORCE) {
+       /* calculus here, is reused in PFIELD_FORCE */
+       mygetmatrix(tmat);
+       Mat4Invert(imat, tmat);
+//     Normalise(imat[0]);             // we don't do this because field doesnt scale either... apart from wind!
+//     Normalise(imat[1]);
+       
+       if(pd->flag & PFIELD_USEMAX) {
+               setlinestyle(3);
+               BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
+               drawcircball(vec, pd->maxdist, imat);
+               setlinestyle(0);
+       }
+       if (pd->forcefield == PFIELD_WIND) {
+               float force_val;
+               
+               Mat4One(tmat);
+               BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
+               
+               if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+                       force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
+               else 
+                       force_val = pd->f_strength;
+               force_val*= 0.1;
+               drawcircball(vec, 1.0, tmat);
+               vec[2]= 0.5*force_val;
+               drawcircball(vec, 1.0, tmat);
+               vec[2]= 1.0*force_val;
+               drawcircball(vec, 1.0, tmat);
+               vec[2]= 1.5*force_val;
+               drawcircball(vec, 1.0, tmat);
+               
+       }
+       else if (pd->forcefield == PFIELD_FORCE) {
                float ffall_val;
 
-               mygetmatrix(tmat);
-               Mat4Invert(imat, tmat);
-               Normalise(imat[0]);
-               Normalise(imat[1]);
                if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
                        ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
                else 
-                       ffall_val = ob->pd->f_power;
+                       ffall_val = pd->f_power;
 
                BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
                drawcircball(vec, 1.0, imat);
@@ -3019,19 +3048,19 @@ static void draw_forcefield(Object *ob)
                BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
                drawcircball(vec, 2.0, imat);
        }
-       else if (ob->pd->forcefield == PFIELD_VORTEX) {
+       else if (pd->forcefield == PFIELD_VORTEX) {
                float ffall_val, force_val;
 
                Mat4One(imat);
                if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
                        ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
                else 
-                       ffall_val = ob->pd->f_power;
+                       ffall_val = pd->f_power;
 
                if (has_ipo_code(ob->ipo, OB_PD_FSTR))
                        force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
                else 
-                       force_val = ob->pd->f_strength;
+                       force_val = pd->f_strength;
 
                BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
                if (force_val < 0) {