From 8e7b4039247419a34093b06b5a05c2423d2cab05 Mon Sep 17 00:00:00 2001 From: Jens Ole Wund Date: Thu, 28 Sep 2006 20:27:46 +0000 Subject: new softbody feature: simple (naive) self collision estimates a collision ball using the spring lenght to attached neighbours (idea stolen from old cloth modifier files, but i'm sure ZAZ and genscher won't mind) -- usefull for untangeling static cloth like objects -- may be used for cloth simulation with known limitations like 'tunnel effect' if objects are moving too fast ... demo -- volatile files http://www.wund.homepage.t-online.de/hidden/sb_without_selfcol.avi http://www.wund.homepage.t-online.de/hidden/sb_with_selfcoll.avi have fun BM --- source/blender/blenkernel/intern/softbody.c | 79 +++++++++++++++++++++++++++-- source/blender/makesdna/DNA_object_force.h | 1 + source/blender/src/buttons_object.c | 5 +- 3 files changed, 79 insertions(+), 6 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index ada8fb5cc21..eed086035ca 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -92,6 +92,7 @@ typedef struct BodyPoint { float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */ int nofsprings; int *springs; float contactfrict; + float colball; } BodyPoint; typedef struct BodySpring { @@ -673,6 +674,27 @@ static void build_bps_springlist(Object *ob) }/*for bp*/ } +static void calculate_collision_balls(Object *ob) +{ + SoftBody *sb= ob->soft; /* is supposed to be there */ + BodyPoint *bp; + BodySpring *bs; + int a,b; + + if (sb==NULL) return; /* paranoya check */ + + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + bp->colball=0; + for(b=bp->nofsprings;b>0;b--){ + bs = sb->bspring + bp->springs[b-1]; + bp->colball += bs->len; + } + if (bp->nofsprings != 0) bp->colball /= bp->nofsprings; + else bp->colball=0; + /* printf("collision ballsize %f \n",bp->colball); */ + }/*for bp*/ +} + /* creates new softbody if didn't exist yet, makes new points and springs arrays */ static void renew_softbody(Object *ob, int totpoint, int totspring) @@ -984,7 +1006,7 @@ static void softbody_calc_forces(Object *ob, float forcetime) ListBase *do_effector; float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3]; float fieldfactor = 1000.0f, windfactor = 250.0f; - int a, b, do_deflector; + int a, b, do_deflector; /* clear forces */ for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { @@ -1001,7 +1023,7 @@ static void softbody_calc_forces(Object *ob, float forcetime) bproot= sb->bpoint; /* need this for proper spring addressing */ for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { - if(bp->goal < SOFTGOALSNAP){ /* ommit this bp when i snaps */ + if(bp->goal < SOFTGOALSNAP){ /* ommit this bp when it snaps */ float auxvect[3]; float velgoal[3]; float absvel =0, projvel= 0; @@ -1084,7 +1106,57 @@ static void softbody_calc_forces(Object *ob, float forcetime) bp->contactfrict = 0.0f; } + } + else + { + bp->contactfrict = 0.0f; + } + /* naive ball self collision */ + if((ob->softflag & OB_SB_EDGES) && (sb->bspring) + && (ob->softflag & OB_SB_SELF)){ + int attached; + BodyPoint *obp; + int c,b; + float def[3]; + float tune2 = 0.5f; + float tune = 1.0f; + float distance; + float compare; + + for(c=sb->totpoint, obp= sb->bpoint; c>0; c--, obp++) { + + if (c < a ) continue; /* exploit force(a,b) == force(b,a) part1/2 */ + + compare = (obp->colball + bp->colball) * tune2; + VecSubf(def, bp->pos, obp->pos); + distance = Normalise(def); + + + if (distance < compare ){ + /* exclude body points attached with a spring */ + attached = 0; + for(b=obp->nofsprings;b>0;b--){ + bs = sb->bspring + obp->springs[b-1]; + if (( sb->totpoint-a == bs->v2) || ( sb->totpoint-a == bs->v1)){ + attached=1; + continue;} + + } + if (!attached){ + /* would need another UI parameter defining fricton on self contact */ + float ccfriction = 0.05; + float f = tune/(distance) + tune/(compare*compare)*distance - 2.0f*tune/compare ; + Vec3PlusStVec(bp->force,f,def); + if (bp->contactfrict == 0.0f) bp->contactfrict = ccfriction*compare/distance; + /* exploit force(a,b) == force(b,a) part2/2 */ + Vec3PlusStVec(obp->force,-f,def); + if (obp->contactfrict == 0.0f) obp->contactfrict = ccfriction*compare/distance; + } + + } + } } + /* naive ball self collision done */ /*other forces done*/ /* nice things could be done with anisotropic friction @@ -1147,7 +1219,6 @@ static void softbody_calc_forces(Object *ob, float forcetime) }/*any edges*/ }/*omit on snap */ }/*loop all bp's*/ - /* cleanup */ if(do_effector) pdEndEffectors(do_effector); @@ -1429,13 +1500,13 @@ static void mesh_to_softbody(Object *ob) } build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */ - /* insert *other second order* springs if desired */ if (sb->secondspring > 0.0000001f) { add_2nd_order_springs(ob,sb->secondspring); /* exploits the the first run of build_bps_springlist(ob);*/ build_bps_springlist(ob); /* yes we need to do it again*/ } springs_from_mesh(ob); /* write the 'rest'-lenght of the springs */ + calculate_collision_balls(ob); } } diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index b7bc74d524b..0508d7bac60 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -123,6 +123,7 @@ typedef struct SoftBody { #define OB_SB_BAKESET 64 #define OB_SB_BAKEDO 128 #define OB_SB_RESET 256 +#define OB_SB_SELF 512 #ifdef __cplusplus } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 983c6335407..749ff17c4e9 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2355,8 +2355,9 @@ static void object_softbodies(Object *ob) /* EDGE SPRING STUFF */ if(ob->type!=OB_SURF) { uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_SB_EDGES, B_SOFTBODY_CHANGE, "Use Edges", 10,30,150,20, &ob->softflag, 0, 0, 0, 0, "Use Edges as springs"); - uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads", 160,30,150,20, &ob->softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons"); + uiDefButBitS(block, TOG, OB_SB_EDGES, B_SOFTBODY_CHANGE, "Use Edges", 10,30,90,20, &ob->softflag, 0, 0, 0, 0, "Use Edges as springs"); + uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads", 110,30,90,20, &ob->softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons"); + uiDefButBitS(block, TOG, OB_SB_SELF, B_DIFF, "Self Collision", 220,30,90,20, &ob->softflag, 0, 0, 0, 0, "Use Edges as springs"); uiDefButF(block, NUM, B_DIFF, "E Stiff:", 10,10,150,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness"); uiDefButF(block, NUM, B_DIFF, "E Damp:", 160,10,150,20, &sb->infrict, 0.0, 50.0, 10, 0, "Edge spring friction"); uiBlockEndAlign(block); -- cgit v1.2.3