softbodies again

unnesting aerodynamics from edge collision
cleaning up softbody.c
that is:
removing old todos in comments
adding some new :)
This commit is contained in:
Jens Ole Wund 2006-10-14 19:03:06 +00:00
parent bc10cf38b9
commit 03be45c8c0
2 changed files with 78 additions and 122 deletions

@ -96,12 +96,7 @@ typedef struct BodyPoint {
typedef struct BodySpring { typedef struct BodySpring {
int v1, v2; int v1, v2;
float len, strength; float len, strength;
float ext_force[3]; float ext_force[3]; /* edges colliding and sailing */
/* ^^^^^^^^^ for collision now,
but could be used for forces depending on orientations
such as wind --> project the lenght on the (relative) wind
via inner product force -> sin(<v_wind-v_spring,v1-v2>)
*/
short order; short order;
short flag; short flag;
} BodySpring; } BodySpring;
@ -169,7 +164,7 @@ static float sb_time_scale(Object *ob)
/*+++ collider caching and dicing +++*/ /*+++ collider caching and dicing +++*/
/******************** /********************
for each target object/face the ortho bounding box (OBB) is stored for each target object/face the axis aligned bounding box (AABB) is stored
faces paralell to global axes faces paralell to global axes
so only simple "value" in [min,max] ckecks are used so only simple "value" in [min,max] ckecks are used
float operations still float operations still
@ -443,12 +438,6 @@ void ccd_build_deflector_cache(Object *vertexowner)
if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) { if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
ob= base->object; ob= base->object;
if((vertexowner) && (ob == vertexowner)){ if((vertexowner) && (ob == vertexowner)){
/* duuh thats myself! */
/* anyhow to do some clever caching with o frozen version */
/*
if(ob->pd && ob->pd->deflect) {
ob->sumohandle=ccd_mesh_make_self(ob);
} no self intersection test yet*/
/* if vertexowner is given we don't want to check collision with owner object */ /* if vertexowner is given we don't want to check collision with owner object */
base = base->next; base = base->next;
continue; continue;
@ -558,7 +547,6 @@ static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int ad
int a,b,c,notthis,v0; int a,b,c,notthis,v0;
if (!sb->bspring){return;} /* we are 2nd order here so 1rst should have been build :) */ if (!sb->bspring){return;} /* we are 2nd order here so 1rst should have been build :) */
/* first run counting second run adding */ /* first run counting second run adding */
/*run all body points*/
*counter = 0; *counter = 0;
if (addsprings) bs3 = ob->soft->bspring+ob->soft->totspring; if (addsprings) bs3 = ob->soft->bspring+ob->soft->totspring;
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
@ -619,9 +607,8 @@ static void add_2nd_order_springs(Object *ob,float stiffness)
int counter = 0; int counter = 0;
BodySpring *bs_new; BodySpring *bs_new;
add_2nd_order_roller(ob,stiffness,&counter,0); add_2nd_order_roller(ob,stiffness,&counter,0); /* counting */
if (counter) { if (counter) {
/* printf("Added %d springs \n", counter); */
/* resize spring-array to hold additional springs */ /* resize spring-array to hold additional springs */
bs_new= MEM_callocN( (ob->soft->totspring + counter )*sizeof(BodySpring), "bodyspring"); bs_new= MEM_callocN( (ob->soft->totspring + counter )*sizeof(BodySpring), "bodyspring");
memcpy(bs_new,ob->soft->bspring,(ob->soft->totspring )*sizeof(BodySpring)); memcpy(bs_new,ob->soft->bspring,(ob->soft->totspring )*sizeof(BodySpring));
@ -630,11 +617,9 @@ static void add_2nd_order_springs(Object *ob,float stiffness)
MEM_freeN(ob->soft->bspring); MEM_freeN(ob->soft->bspring);
ob->soft->bspring = bs_new; ob->soft->bspring = bs_new;
add_2nd_order_roller(ob,stiffness,&counter,1); /* adding */
add_2nd_order_roller(ob,stiffness,&counter,1);
ob->soft->totspring +=counter ; ob->soft->totspring +=counter ;
} }
} }
static void add_bp_springlist(BodyPoint *bp,int springID) static void add_bp_springlist(BodyPoint *bp,int springID)
@ -683,7 +668,6 @@ static void build_bps_springlist(Object *ob)
add_bp_springlist(bp,sb->totspring -b); add_bp_springlist(bp,sb->totspring -b);
} }
}/*for springs*/ }/*for springs*/
/* if (bp->nofsprings) printf(" node %d has %d spring links\n",a,bp->nofsprings);*/
}/*for bp*/ }/*for bp*/
} }
@ -732,7 +716,6 @@ static void calculate_collision_balls(Object *ob)
} }
} }
else bp->colball=0; else bp->colball=0;
/* printf("CB %f \n",bp->colball); */
}/*for bp*/ }/*for bp*/
} }
@ -771,6 +754,8 @@ static void renew_softbody(Object *ob, int totpoint, int totspring)
bp->nofsprings= 0; bp->nofsprings= 0;
bp->springs= NULL; bp->springs= NULL;
bp->contactfrict = 0.0f; bp->contactfrict = 0.0f;
bp->colball = 0.0f;
} }
} }
} }
@ -854,9 +839,7 @@ static void Vec3PlusStVec(float *v, float s, float *v1)
v[2] += s*v1[2]; v[2] += s*v1[2];
} }
/* BEGIN the spring external section*/ /* +++ the spring external section*/
//#if (0)
int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp, int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp,
float force[3], unsigned int par_layer,struct Object *vertexowner) float force[3], unsigned int par_layer,struct Object *vertexowner)
@ -946,8 +929,6 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp
} }
} }
/* switch origin to be nv2*/ /* switch origin to be nv2*/
VECSUB(edge1, nv1, nv2); VECSUB(edge1, nv1, nv2);
VECSUB(edge2, nv3, nv2); VECSUB(edge2, nv3, nv2);
@ -998,8 +979,6 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp
return deflected; return deflected;
} }
//#endif
void scan_for_ext_spring_forces(Object *ob) void scan_for_ext_spring_forces(Object *ob)
{ {
@ -1015,53 +994,57 @@ void scan_for_ext_spring_forces(Object *ob)
BodySpring *bs = &sb->bspring[a]; BodySpring *bs = &sb->bspring[a];
bs->ext_force[0]=bs->ext_force[1]=bs->ext_force[2]=0.0f; bs->ext_force[0]=bs->ext_force[1]=bs->ext_force[2]=0.0f;
feedback[0]=feedback[1]=feedback[2]=0.0f; feedback[0]=feedback[1]=feedback[2]=0.0f;
bs->flag &= ~BSF_INTERSECT; bs->flag &= ~BSF_INTERSECT;
/* +++ springs colliding */
if (bs->order ==1){ if (bs->order ==1){
if ( sb_detect_edge_collisionCached (sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos, /* +++ springs colliding */
&damp,feedback,ob->lay,ob)){ if (ob->softflag & OB_SB_EDGECOLL){
VecAddf(bs->ext_force,bs->ext_force,feedback); if ( sb_detect_edge_collisionCached (sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos,
bs->flag |= BSF_INTERSECT; &damp,feedback,ob->lay,ob)){
VecAddf(bs->ext_force,bs->ext_force,feedback);
} bs->flag |= BSF_INTERSECT;
/* ---- springs colliding */
/* +++ springs seeing wind ... n stuff depending on their orientation*/ }
}
/* ---- springs colliding */
/* +++ springs seeing wind ... n stuff depending on their orientation*/
/* note we don't use sb->mediafrict but use sb->aeroedge for magnitude of effect*/
if(sb->aeroedge){ if(sb->aeroedge){
float vel[3],sp[3],pr[3],force[3]; float vel[3],sp[3],pr[3],force[3];
float f,windfactor = 1.0f; float f,windfactor = 1.0f;
/*see if we have wind*/ /*see if we have wind*/
if(do_effector) { if(do_effector) {
float speed[3],pos[3]; float speed[3],pos[3];
VecMidf(pos, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos); VecMidf(pos, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos);
VecMidf(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec); VecMidf(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec);
pdDoEffectors(do_effector, pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); pdDoEffectors(do_effector, pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);
VecMulf(speed,windfactor); /*oh_ole*/ VecMulf(speed,windfactor);
VecAddf(vel,vel,speed); VecAddf(vel,vel,speed);
} }
/* media in rest */ /* media in rest */
else{ else{
VECADD(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec); VECADD(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec);
} }
f = Normalise(vel); f = Normalise(vel);
f = -0.0001f*f*f*sb->aeroedge; f = -0.0001f*f*f*sb->aeroedge;
/* todo add a nice angle dependant function */
/* look up one at bergman scheafer */
VECSUB(sp, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos); VECSUB(sp, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos);
Projf(pr,vel,sp); Projf(pr,vel,sp);
VECSUB(vel,vel,pr); VECSUB(vel,vel,pr);
Normalise(vel); Normalise(vel);
Vec3PlusStVec(bs->ext_force,f,vel); Vec3PlusStVec(bs->ext_force,f,vel);
} }
/* --- springs seeing wind */
/* --- springs seeing wind */
} }
} }
} }
if(do_effector) if(do_effector)
pdEndEffectors(do_effector); pdEndEffectors(do_effector);
} }
/* END the spring external section*/ /* --- the spring external section*/
int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *damp, int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *damp,
float force[3], unsigned int par_layer,struct Object *vertexowner) float force[3], unsigned int par_layer,struct Object *vertexowner)
@ -1157,8 +1140,6 @@ int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *
} }
} }
/* switch origin to be nv2*/ /* switch origin to be nv2*/
VECSUB(edge1, nv1, nv2); VECSUB(edge1, nv1, nv2);
VECSUB(edge2, nv3, nv2); VECSUB(edge2, nv3, nv2);
@ -1203,7 +1184,6 @@ int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *
mface++; mface++;
mima++; mima++;
}/* while a */ }/* while a */
/* give it away */
} /* if(ob->pd && ob->pd->deflect) */ } /* if(ob->pd && ob->pd->deflect) */
}/* if (base->object->type==OB_MESH && (base->lay & par_layer)) { */ }/* if (base->object->type==OB_MESH && (base->lay & par_layer)) { */
base = base->next; base = base->next;
@ -1249,7 +1229,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
ListBase *do_effector; ListBase *do_effector;
float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3]; float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3];
float fieldfactor = 1000.0f, windfactor = 250.0f; float fieldfactor = 1000.0f, windfactor = 250.0f;
int a, b, do_deflector,do_selfcollision,do_springcollision; int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero;
/* clear forces */ /* clear forces */
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
@ -1258,18 +1238,19 @@ static void softbody_calc_forces(Object *ob, float forcetime)
gravity = sb->grav * sb_grav_force_scale(ob); gravity = sb->grav * sb_grav_force_scale(ob);
/* check! */ /* check conditions for various options */
do_deflector= is_there_deflection(ob->lay); do_deflector= is_there_deflection(ob->lay);
do_effector= pdInitEffectors(ob,NULL); do_effector= pdInitEffectors(ob,NULL);
do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
bproot= sb->bpoint; /* need this for proper spring addressing */ bproot= sb->bpoint; /* need this for proper spring addressing */
if (do_springcollision) scan_for_ext_spring_forces(ob); if (do_springcollision || do_aero) scan_for_ext_spring_forces(ob);
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
/* naive ball self collision */ /* naive ball self collision */
@ -1284,12 +1265,12 @@ static void softbody_calc_forces(Object *ob, float forcetime)
float compare; float compare;
for(c=sb->totpoint, obp= sb->bpoint; c>0; c--, obp++) { for(c=sb->totpoint, obp= sb->bpoint; c>0; c--, obp++) {
if (c < a ) continue; /* exploit force(a,b) == force(b,a) part1/2 */ if (c < a ) continue; /* exploit force(a,b) == -force(b,a) part1/2 */
compare = (obp->colball + bp->colball); compare = (obp->colball + bp->colball);
VecSubf(def, bp->pos, obp->pos); VecSubf(def, bp->pos, obp->pos);
distance = Normalise(def); distance = Normalise(def);
if (distance < compare ){ if (distance < compare ){
/* exclude body points attached with a spring */ /* exclude body points attached with a spring */
attached = 0; attached = 0;
for(b=obp->nofsprings;b>0;b--){ for(b=obp->nofsprings;b>0;b--){
bs = sb->bspring + obp->springs[b-1]; bs = sb->bspring + obp->springs[b-1];
@ -1298,37 +1279,26 @@ static void softbody_calc_forces(Object *ob, float forcetime)
continue;} continue;}
} }
if (!attached){ if (!attached){
/* would need another UI parameter defining fricton on self contact */
float ccfriction = sb->balldamp;
float f = tune/(distance) + tune/(compare*compare)*distance - 2.0f*tune/compare ; float f = tune/(distance) + tune/(compare*compare)*distance - 2.0f*tune/compare ;
VecMidf(velcenter, bp->vec, obp->vec); VecMidf(velcenter, bp->vec, obp->vec);
VecSubf(dvel,velcenter,bp->vec); VecSubf(dvel,velcenter,bp->vec);
VecMulf(dvel,sb->nodemass); VecMulf(dvel,sb->nodemass);
Vec3PlusStVec(bp->force,ccfriction,dvel); Vec3PlusStVec(bp->force,sb->balldamp,dvel);
Vec3PlusStVec(bp->force,f*(1.0f-ccfriction),def); Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
/* exploit force(a,b) == force(b,a) part2/2 */ /* exploit force(a,b) == -force(b,a) part2/2 */
VecSubf(dvel,velcenter,obp->vec);
VecSubf(dvel,velcenter,obp->vec); VecMulf(dvel,sb->nodemass);
VecMulf(dvel,sb->nodemass);
Vec3PlusStVec(obp->force,ccfriction,dvel); Vec3PlusStVec(obp->force,sb->balldamp,dvel);
Vec3PlusStVec(obp->force,-f*(1.0f-ccfriction),def); Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
//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 */ /* naive ball self collision done */
if(bp->goal < SOFTGOALSNAP){ /* ommit this bp when it snaps */ if(bp->goal < SOFTGOALSNAP){ /* ommit this bp when it snaps */
float auxvect[3]; float auxvect[3];
@ -1372,13 +1342,11 @@ static void softbody_calc_forces(Object *ob, float forcetime)
pdDoEffectors(do_effector, bp->pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); pdDoEffectors(do_effector, bp->pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);
/* note: now we have wind as motion of media, so we can do anisotropic stuff here, */
/* if we had vertex normals here(BM) */
/* apply forcefield*/ /* apply forcefield*/
VecMulf(force,fieldfactor* eval_sb_fric_force_scale); VecMulf(force,fieldfactor* eval_sb_fric_force_scale);
VECADD(bp->force, bp->force, force); VECADD(bp->force, bp->force, force);
/* friction in moving media */ /* BP friction in moving media */
kd= sb->mediafrict* eval_sb_fric_force_scale; kd= sb->mediafrict* eval_sb_fric_force_scale;
bp->force[0] -= kd * (bp->vec[0] + windfactor*speed[0]/eval_sb_fric_force_scale); bp->force[0] -= kd * (bp->vec[0] + windfactor*speed[0]/eval_sb_fric_force_scale);
bp->force[1] -= kd * (bp->vec[1] + windfactor*speed[1]/eval_sb_fric_force_scale); bp->force[1] -= kd * (bp->vec[1] + windfactor*speed[1]/eval_sb_fric_force_scale);
@ -1387,7 +1355,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
} }
else { else {
/* friction in media (not) moving*/ /* BP friction in media (not) moving*/
kd= sb->mediafrict* sb_fric_force_scale(ob); kd= sb->mediafrict* sb_fric_force_scale(ob);
/* assume it to be proportional to actual velocity */ /* assume it to be proportional to actual velocity */
bp->force[0]-= bp->vec[0]*kd; bp->force[0]-= bp->vec[0]*kd;
@ -1396,11 +1364,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
/* friction in media done */ /* friction in media done */
} }
/*other forces*/ /* +++cached collision targets */
/* this is the place where other forces can be added
yes, constraints and collision stuff should go here too (read baraff papers on that!)
*/
/* moving collision targets */
if(do_deflector) { if(do_deflector) {
float defforce[3] = {0.0f,0.0f,0.0f}, collisionpos[3],facenormal[3], cf = 1.0f; float defforce[3] = {0.0f,0.0f,0.0f}, collisionpos[3],facenormal[3], cf = 1.0f;
kd = 1.0f; kd = 1.0f;
@ -1412,27 +1376,19 @@ static void softbody_calc_forces(Object *ob, float forcetime)
else{ else{
bp->contactfrict = 0.0f; bp->contactfrict = 0.0f;
} }
} }
else else
{ {
bp->contactfrict = 0.0f; bp->contactfrict = 0.0f;
} }
/* ---cached collision targets */
/*other forces done*/ /* +++springs */
/* nice things could be done with anisotropic friction
like wind/air resistance in normal direction
--> having a piece of cloth sailing down
but this needs to have a *valid* vertex normal
*valid* means to be calulated on time axis
hrms .. may be a rough one could be used as well .. let's see
*/
if(ob->softflag & OB_SB_EDGES) { if(ob->softflag & OB_SB_EDGES) {
if (sb->bspring){ /* spring list exists at all ? */ if (sb->bspring){ /* spring list exists at all ? */
for(b=bp->nofsprings;b>0;b--){ for(b=bp->nofsprings;b>0;b--){
bs = sb->bspring + bp->springs[b-1]; bs = sb->bspring + bp->springs[b-1];
if (do_springcollision){ if (do_springcollision || do_aero){
VecAddf(bp->force,bp->force,bs->ext_force); VecAddf(bp->force,bp->force,bs->ext_force);
if (bs->flag & BSF_INTERSECT) if (bs->flag & BSF_INTERSECT)
bp->contactfrict = 0.9f; /* another ad hoc magic */ bp->contactfrict = 0.9f; /* another ad hoc magic */
@ -1485,12 +1441,12 @@ static void softbody_calc_forces(Object *ob, float forcetime)
}/* loop springs */ }/* loop springs */
}/* existing spring list */ }/* existing spring list */
}/*any edges*/ }/*any edges*/
/* ---springs */
}/*omit on snap */ }/*omit on snap */
}/*loop all bp's*/ }/*loop all bp's*/
/* cleanup */
if(do_effector)
pdEndEffectors(do_effector);
/* cleanup */
if(do_effector) pdEndEffectors(do_effector);
} }
@ -1563,7 +1519,8 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
maxerr = MAX2(maxerr,ABS(dx[0] - bp->prevdx[0])); maxerr = MAX2(maxerr,ABS(dx[0] - bp->prevdx[0]));
maxerr = MAX2(maxerr,ABS(dx[1] - bp->prevdx[1])); maxerr = MAX2(maxerr,ABS(dx[1] - bp->prevdx[1]));
maxerr = MAX2(maxerr,ABS(dx[2] - bp->prevdx[2])); maxerr = MAX2(maxerr,ABS(dx[2] - bp->prevdx[2]));
/* kind of hack .. while inside collision target .. make movement more *viscous* */ /* weak point: not knowing anything about targets dynamics we assume it to be resting */
/* while inside collision target .. make movement more *viscous* */
if (bp->contactfrict > 0.0f){ if (bp->contactfrict > 0.0f){
bp->vec[0] *= (1.0f - bp->contactfrict); bp->vec[0] *= (1.0f - bp->contactfrict);
bp->vec[1] *= (1.0f - bp->contactfrict); bp->vec[1] *= (1.0f - bp->contactfrict);

@ -2329,11 +2329,10 @@ static void object_softbodies(Object *ob)
uiDefButS(block, ROW, B_DIFF, "Min",130,150,60,20, &sb->sbc_mode, 4.0,(float)2, 0, 0, "Minimal Spring lenght * Ball Size"); uiDefButS(block, ROW, B_DIFF, "Min",130,150,60,20, &sb->sbc_mode, 4.0,(float)2, 0, 0, "Minimal Spring lenght * Ball Size");
uiDefButS(block, ROW, B_DIFF, "Max",190,150,60,20, &sb->sbc_mode, 4.0,(float)3, 0, 0, "Maximal Spring lenght * Ball Size"); uiDefButS(block, ROW, B_DIFF, "Max",190,150,60,20, &sb->sbc_mode, 4.0,(float)3, 0, 0, "Maximal Spring lenght * Ball Size");
uiDefButS(block, ROW, B_DIFF, "AvMiMa",250,150,60,20, &sb->sbc_mode, 4.0,(float)4, 0, 0, "(Min+Max)/2 * Ball Size"); uiDefButS(block, ROW, B_DIFF, "AvMiMa",250,150,60,20, &sb->sbc_mode, 4.0,(float)4, 0, 0, "(Min+Max)/2 * Ball Size");
uiDefButF(block, NUM, B_DIFF, "B Stiff:", 10,130,150,20, &sb->ballstiff, 0.001, 100.0, 10, 0, ""); uiDefButF(block, NUM, B_DIFF, "B Stiff:", 10,130,150,20, &sb->ballstiff, 0.001, 100.0, 10, 0, "Ball inflating presure");
uiDefButF(block, NUM, B_DIFF, "B Damp:", 160,130,150,20, &sb->balldamp, 0.001, 1.0, 10, 0, ""); uiDefButF(block, NUM, B_DIFF, "B Damp:", 160,130,150,20, &sb->balldamp, 0.001, 1.0, 10, 0, "Blending to inelastic collision");
uiDefButS(block, NUM, B_DIFF, "Aero:", 160,110,150,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "");
uiBlockEndAlign(block); uiBlockEndAlign(block);
uiDefButS(block, NUM, B_DIFF, "Aero:", 10,100,150,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'");
} }
/* OTHER OBJECTS COLLISION STUFF */ /* OTHER OBJECTS COLLISION STUFF */
if (ob->type==OB_MESH){ if (ob->type==OB_MESH){