no code changes (i hope)

review of lyrics/epics to replace '//' comments by /*ones*/
+ adaptive step size in a nutshell  comment
This commit is contained in:
Jens Ole Wund 2005-11-19 21:35:06 +00:00
parent 54c032440f
commit b6c5b24f4f

@ -100,12 +100,13 @@ typedef struct BodySpring {
#define SOFTGOALSNAP 0.999f #define SOFTGOALSNAP 0.999f
// if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp /* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp
// removes *unnecessary* stiffnes from ODE system removes *unnecessary* stiffnes from ODE system
#define HEUNWARNLIMIT 1 // 50 would be fine i think for detecting severe *stiff* stuff */
#define HEUNWARNLIMIT 1 /* 50 would be fine i think for detecting severe *stiff* stuff */
float SoftHeunTol = 1.0f; // humm .. this should be calculated from sb parameters and sizes float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
/* local prototypes */ /* local prototypes */
static void free_softbody_intern(SoftBody *sb); static void free_softbody_intern(SoftBody *sb);
@ -115,31 +116,35 @@ static void Vec3PlusStVec(float *v, float s, float *v1);
/*+++ frame based timing +++*/ /*+++ frame based timing +++*/
//physical unit of force is [kg * m / sec^2] /*physical unit of force is [kg * m / sec^2]*/
static float sb_grav_force_scale(Object *ob) static float sb_grav_force_scale(Object *ob)
// since unit of g is [m/sec^2] and F = mass * g we rescale unit mass of node to 1 gramm /* since unit of g is [m/sec^2] and F = mass * g we rescale unit mass of node to 1 gramm
// put it to a function here, so we can add user options later without touching simulation code put it to a function here, so we can add user options later without touching simulation code
*/
{ {
return (0.001f); return (0.001f);
} }
static float sb_fric_force_scale(Object *ob) static float sb_fric_force_scale(Object *ob)
// rescaling unit of drag [1 / sec] to somehow reasonable /* rescaling unit of drag [1 / sec] to somehow reasonable
// put it to a function here, so we can add user options later without touching simulation code put it to a function here, so we can add user options later without touching simulation code
*/
{ {
return (0.01f); return (0.01f);
} }
static float sb_time_scale(Object *ob) static float sb_time_scale(Object *ob)
// defining the frames to *real* time relation /* defining the frames to *real* time relation */
{ {
SoftBody *sb= ob->soft; // is supposed to be there SoftBody *sb= ob->soft; /* is supposed to be there */
if (sb){ if (sb){
return(sb->physics_speed); //hrms .. this could be IPO as well :) return(sb->physics_speed);
// estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)] /*hrms .. this could be IPO as well :)
// 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
// theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM) 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames
theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM)
*/
} }
return (1.0f); return (1.0f);
/* /*
@ -236,12 +241,12 @@ it is O(N^2) so scanning for springs every iteration is too expensive
*/ */
static void build_bps_springlist(Object *ob) static void build_bps_springlist(Object *ob)
{ {
SoftBody *sb= ob->soft; // is supposed to be there SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp; BodyPoint *bp;
BodySpring *bs; BodySpring *bs;
int a,b; int a,b;
if (sb==NULL) return; // paranoya check if (sb==NULL) return; /* paranoya check */
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
/* scan for attached inner springs */ /* scan for attached inner springs */
@ -252,9 +257,9 @@ static void build_bps_springlist(Object *ob)
if (( (sb->totpoint-a) == bs->v2) ){ if (( (sb->totpoint-a) == bs->v2) ){
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); /* if (bp->nofsprings) printf(" node %d has %d spring links\n",a,bp->nofsprings);*/
}//for bp }/*for bp*/
} }
@ -380,7 +385,7 @@ int sb_detect_collision(float opco[3], float facenormal[3], float *damp,
fa = 1.0f/fa; fa = 1.0f/fa;
copyob = ob; copyob = ob;
if(1) { // so maybe someone wants overkill to collide with subsurfed if(1) { /* so maybe someone wants overkill to collide with subsurfed */
dm = mesh_get_derived_deform(copyob, &dmNeedsFree); dm = mesh_get_derived_deform(copyob, &dmNeedsFree);
} else { } else {
dm = mesh_get_derived_final(copyob, &dmNeedsFree); dm = mesh_get_derived_final(copyob, &dmNeedsFree);
@ -417,10 +422,10 @@ int sb_detect_collision(float opco[3], float facenormal[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);
VECSUB(dv1,opco,nv2); // abuse dv1 to have vertex in question at *origin* of triangle VECSUB(dv1,opco,nv2); /* abuse dv1 to have vertex in question at *origin* of triangle */
Crossf(d_nvect, edge2, edge1); Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect); n_mag = Normalise(d_nvect);
@ -439,11 +444,11 @@ int sb_detect_collision(float opco[3], float facenormal[3], float *damp,
deflected = 2; deflected = 2;
} }
} }
if (mface->v4){ // quad if (mface->v4){ /* quad */
// switch origin to be nv4 /* switch origin to be nv4 */
VECSUB(edge1, nv3, nv4); VECSUB(edge1, nv3, nv4);
VECSUB(edge2, nv1, nv4); VECSUB(edge2, nv1, nv4);
VECSUB(dv1,opco,nv4); // abuse dv1 to have vertex in question at *origin* of triangle VECSUB(dv1,opco,nv4); /* abuse dv1 to have vertex in question at *origin* of triangle */
Crossf(d_nvect, edge2, edge1); Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect); n_mag = Normalise(d_nvect);
@ -466,7 +471,7 @@ int sb_detect_collision(float opco[3], float facenormal[3], float *damp,
} }
mface++; mface++;
}//while a }/* while a */
/* give it away */ /* give it away */
if (disp_mesh) { if (disp_mesh) {
displistmesh_free(disp_mesh); displistmesh_free(disp_mesh);
@ -474,10 +479,10 @@ int sb_detect_collision(float opco[3], float facenormal[3], float *damp,
if (dm) { if (dm) {
if (dmNeedsFree) dm->release(dm); if (dmNeedsFree) dm->release(dm);
} }
} // 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;
} // while (base) } /* while (base) */
return deflected; return deflected;
@ -523,7 +528,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
/* rule we never alter free variables :bp->vec bp->pos in here ! /* rule we never alter free variables :bp->vec bp->pos in here !
* this will ruin adaptive stepsize AKA heun! (BM) * this will ruin adaptive stepsize AKA heun! (BM)
*/ */
SoftBody *sb= ob->soft; // is supposed to be there SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp; BodyPoint *bp;
BodyPoint *bproot; BodyPoint *bproot;
BodySpring *bs; BodySpring *bs;
@ -547,8 +552,8 @@ static void softbody_calc_forces(Object *ob, float forcetime)
bproot= sb->bpoint; /* need this for proper spring addressing */ bproot= sb->bpoint; /* need this for proper spring addressing */
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { 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 i snaps */
float auxvect[3]; // aux unit vector float auxvect[3];
float velgoal[3]; float velgoal[3];
float absvel =0, projvel= 0; float absvel =0, projvel= 0;
@ -564,7 +569,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
VecSubf(velgoal,bp->origS, bp->origE); VecSubf(velgoal,bp->origS, bp->origE);
kd = sb->goalfrict * sb_fric_force_scale(ob) ; kd = sb->goalfrict * sb_fric_force_scale(ob) ;
if (forcetime > 0.0 ) { // make sure friction does not become rocket motor on time reversal if (forcetime > 0.0 ) { /* make sure friction does not become rocket motor on time reversal */
bp->force[0]-= kd * (velgoal[0] + bp->vec[0]); bp->force[0]-= kd * (velgoal[0] + bp->vec[0]);
bp->force[1]-= kd * (velgoal[1] + bp->vec[1]); bp->force[1]-= kd * (velgoal[1] + bp->vec[1]);
bp->force[2]-= kd * (velgoal[2] + bp->vec[2]); bp->force[2]-= kd * (velgoal[2] + bp->vec[2]);
@ -585,7 +590,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
if(do_effector) { if(do_effector) {
float force[3]= {0.0f, 0.0f, 0.0f}; float force[3]= {0.0f, 0.0f, 0.0f};
float speed[3]= {0.0f, 0.0f, 0.0f}; float speed[3]= {0.0f, 0.0f, 0.0f};
float eval_sb_fric_force_scale = sb_fric_force_scale(ob); // just for calling functio once float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
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);
@ -642,7 +647,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
*/ */
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 (( (sb->totpoint-a) == bs->v1) ){ if (( (sb->totpoint-a) == bs->v1) ){
@ -650,7 +655,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
VecSubf(sd,(bproot+bs->v2)->pos, bp->pos); VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
Normalise(sd); Normalise(sd);
// friction stuff V1 /* friction stuff V1 */
VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec); VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
kd = sb->infrict * sb_fric_force_scale(ob); kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalise(velgoal); absvel = Normalise(velgoal);
@ -672,7 +677,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
VecSubf(sd,bp->pos,(bproot+bs->v1)->pos); VecSubf(sd,bp->pos,(bproot+bs->v1)->pos);
Normalise(sd); Normalise(sd);
// friction stuff V2 /* friction stuff V2 */
VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec); VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
kd = sb->infrict * sb_fric_force_scale(ob); kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalise(velgoal); absvel = Normalise(velgoal);
@ -703,7 +708,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
/* time evolution */ /* time evolution */
/* actually does an explicit euler step mode == 0 */ /* actually does an explicit euler step mode == 0 */
/* or heun ~ 2nd order runge-kutta steps, mode 1,2 */ /* or heun ~ 2nd order runge-kutta steps, mode 1,2 */
SoftBody *sb= ob->soft; // is supposed to be there SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp; BodyPoint *bp;
float dx[3],dv[3]; float dx[3],dv[3];
float timeovermass; float timeovermass;
@ -712,7 +717,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
forcetime *= sb_time_scale(ob); forcetime *= sb_time_scale(ob);
// claim a minimum mass for vertex /* claim a minimum mass for vertex */
if (sb->nodemass > 0.09999f) timeovermass = forcetime/sb->nodemass; if (sb->nodemass > 0.09999f) timeovermass = forcetime/sb->nodemass;
else timeovermass = forcetime/0.09999f; else timeovermass = forcetime/0.09999f;
@ -774,8 +779,8 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
} }
} }
else { VECADD(bp->pos, bp->pos, dx);} else { VECADD(bp->pos, bp->pos, dx);}
}//snap }/*snap*/
} //for } /*for*/
if (err){ /* so step size will be controlled by biggest difference in slope */ if (err){ /* so step size will be controlled by biggest difference in slope */
*err = maxerr; *err = maxerr;
@ -785,7 +790,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
/* used by heun when it overshoots */ /* used by heun when it overshoots */
static void softbody_restore_prev_step(Object *ob) static void softbody_restore_prev_step(Object *ob)
{ {
SoftBody *sb= ob->soft; // is supposed to be there SoftBody *sb= ob->soft; /* is supposed to be there*/
BodyPoint *bp; BodyPoint *bp;
int a; int a;
@ -798,7 +803,7 @@ static void softbody_restore_prev_step(Object *ob)
static void softbody_apply_goalsnap(Object *ob) static void softbody_apply_goalsnap(Object *ob)
{ {
SoftBody *sb= ob->soft; // is supposed to be there SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp; BodyPoint *bp;
int a; int a;
@ -928,7 +933,7 @@ static void mesh_to_softbody(Object *ob)
if((ob->softflag & OB_SB_GOAL) && sb->vertgroup) { if((ob->softflag & OB_SB_GOAL) && sb->vertgroup) {
get_scalar_from_vertexgroup(ob, a,(short) (sb->vertgroup-1), &bp->goal); get_scalar_from_vertexgroup(ob, a,(short) (sb->vertgroup-1), &bp->goal);
// do this always, regardless successfull read from vertex group /* do this always, regardless successfull read from vertex group */
bp->goal= sb->mingoal + bp->goal*goalfac; bp->goal= sb->mingoal + bp->goal*goalfac;
} }
/* a little ad hoc changing the goal control to be less *sharp* */ /* a little ad hoc changing the goal control to be less *sharp* */
@ -1209,7 +1214,7 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts)
for(a=0; a<numVerts; a++, bp++) { for(a=0; a<numVerts; a++, bp++) {
VECCOPY(vertexCos[a], bp->pos); VECCOPY(vertexCos[a], bp->pos);
Mat4MulVecfl(ob->imat, vertexCos[a]); // softbody is in global coords Mat4MulVecfl(ob->imat, vertexCos[a]); /* softbody is in global coords */
} }
} }
@ -1219,7 +1224,7 @@ static int softbody_baked_step(Object *ob, float framenr, float (*vertexCos)[3],
SoftBody *sb= ob->soft; SoftBody *sb= ob->soft;
SBVertex *key0, *key1, *key2, *key3; SBVertex *key0, *key1, *key2, *key3;
BodyPoint *bp; BodyPoint *bp;
float data[4], sfra, efra, cfra, dfra, fac; // start, end, current, delta float data[4], sfra, efra, cfra, dfra, fac; /* start, end, current, delta */
int ofs1, a; int ofs1, a;
/* precondition check */ /* precondition check */
@ -1253,7 +1258,7 @@ static int softbody_baked_step(Object *ob, float framenr, float (*vertexCos)[3],
else key3= key2; else key3= key2;
} }
sb->ctime= cfra; // needed? sb->ctime= cfra; /* needed? */
/* timing */ /* timing */
fac= ((cfra-sfra)/dfra) - (float)ofs1; fac= ((cfra-sfra)/dfra) - (float)ofs1;
@ -1278,7 +1283,7 @@ static void softbody_baked_add(Object *ob, float framenr)
SoftBody *sb= ob->soft; SoftBody *sb= ob->soft;
SBVertex *key; SBVertex *key;
BodyPoint *bp; BodyPoint *bp;
float sfra, efra, cfra, dfra, fac1; // start, end, current, delta float sfra, efra, cfra, dfra, fac1; /* start, end, current, delta */
int ofs1, a; int ofs1, a;
/* convert cfra time to system time */ /* convert cfra time to system time */
@ -1288,8 +1293,8 @@ static void softbody_baked_add(Object *ob, float framenr)
dfra= (float)sb->interval; dfra= (float)sb->interval;
if(sb->totkey==0) { if(sb->totkey==0) {
if(sb->sfra >= sb->efra) return; // safety, UI or py setting allows if(sb->sfra >= sb->efra) return; /* safety, UI or py setting allows *
if(sb->interval<1) sb->interval= 1; // just be sure if(sb->interval<1) sb->interval= 1; /* just be sure */
sb->totkey= 1 + (int)(ceil( (efra-sfra)/dfra ) ); sb->totkey= 1 + (int)(ceil( (efra-sfra)/dfra ) );
sb->keys= MEM_callocN( sizeof(void *)*sb->totkey, "sb keys"); sb->keys= MEM_callocN( sizeof(void *)*sb->totkey, "sb keys");
@ -1395,11 +1400,11 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
/* This part only sets goals and springs, based on original mesh/curve/lattice data. /* This part only sets goals and springs, based on original mesh/curve/lattice data.
Copying coordinates happens in next chunk by setting softbody flag OB_SB_RESET */ Copying coordinates happens in next chunk by setting softbody flag OB_SB_RESET */
/* remake softbody if: */ /* remake softbody if: */
if( (ob->softflag & OB_SB_REDO) || // signal after weightpainting if( (ob->softflag & OB_SB_REDO) || /* signal after weightpainting */
(ob->soft==NULL) || // just to be nice we allow full init (ob->soft==NULL) || /* just to be nice we allow full init */
(ob->soft->bpoint==NULL) || // after reading new file, or acceptable as signal to refresh (ob->soft->bpoint==NULL) || /* after reading new file, or acceptable as signal to refresh */
(numVerts!=ob->soft->totpoint) || // should never happen, just to be safe (numVerts!=ob->soft->totpoint) || /* should never happen, just to be safe */
((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) // happens when in UI edges was set ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) /* happens when in UI edges was set */
{ {
switch(ob->type) { switch(ob->type) {
case OB_MESH: case OB_MESH:
@ -1445,24 +1450,42 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
/* update the vertex locations */ /* update the vertex locations */
if (dtime!=0.0) { if (dtime!=0.0) {
for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
/* store where goals are now */
VECCOPY(bp->origS, bp->origE); VECCOPY(bp->origS, bp->origE);
/* copy the position of the goals at desired end time */
VECCOPY(bp->origE, vertexCos[a]); VECCOPY(bp->origE, vertexCos[a]);
Mat4MulVecfl(ob->obmat, bp->origE); /* vertexCos came from local world, go global */
VECCOPY(bp->origT, bp->origE); Mat4MulVecfl(ob->obmat, bp->origE);
/* just to be save give bp->origT a defined value
will be calulated in interpolate_exciter()*/
VECCOPY(bp->origT, bp->origE);
} }
} }
/* see if we need to interrupt integration stream */
// G.scene->r.framelen corrects for frame-mapping, so this is actually 10 frames for UI if((ob->softflag&OB_SB_RESET) || /* got a reset signal */
if((ob->softflag&OB_SB_RESET) || dtime<0.0 || dtime>=9.9*G.scene->r.framelen) { dtime<0.0 || /* back in time */
dtime>=9.9*G.scene->r.framelen) /* too far forward in time --> goals won't be accurate enough */
{
for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
VECCOPY(bp->pos, vertexCos[a]); VECCOPY(bp->pos, vertexCos[a]);
Mat4MulVecfl(ob->obmat, bp->pos); // yep, sofbody is global coords Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
VECCOPY(bp->origS, bp->pos); VECCOPY(bp->origS, bp->pos);
VECCOPY(bp->origE, bp->pos); VECCOPY(bp->origE, bp->pos);
VECCOPY(bp->origT, bp->pos); VECCOPY(bp->origT, bp->pos);
bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0f; bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0f;
// no idea about the Heun stuff! (ton) /* the bp->prev*'s are for rolling back from a canceled try to propagate in time
adaptive step size algo in a nutshell:
1. set sheduled time step to new dtime
2. try to advance the sheduled time step, beeing optimistic execute it
3. check for success
3.a we 're fine continue, may be we can increase sheduled time again ?? if so, do so!
3.b we did exceed error limit --> roll back, shorten the sheduled time and try again at 2.
4. check if we did reach dtime
4.a nope we need to do some more at 2.
4.b yup we're done
*/
VECCOPY(bp->prevpos, bp->pos); VECCOPY(bp->prevpos, bp->pos);
VECCOPY(bp->prevvec, bp->vec); VECCOPY(bp->prevvec, bp->vec);
VECCOPY(bp->prevdx, bp->vec); VECCOPY(bp->prevdx, bp->vec);
@ -1472,40 +1495,36 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
ob->softflag &= ~OB_SB_RESET; ob->softflag &= ~OB_SB_RESET;
} }
else if(dtime>0.0) { else if(dtime>0.0) {
if (TRUE) { // RSOL1 always true now (ton) if (TRUE) { /* */
/* special case of 2nd order Runge-Kutta type AKA Heun */ /* special case of 2nd order Runge-Kutta type AKA Heun */
float timedone =0.0; // how far did we get without violating error condition float timedone =0.0; /* how far did we get without violating error condition */
/* loops = counter for emergency brake /* loops = counter for emergency brake
* we don't want to lock up the system if physics fail * we don't want to lock up the system if physics fail
*/ */
int loops =0 ; int loops =0 ;
SoftHeunTol = sb->rklimit; // humm .. this should be calculated from sb parameters and sizes SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */
forcetime = dtime; /* hope for integrating in one step */ forcetime = dtime; /* hope for integrating in one step */
while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ) while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) )
{ {
if (ABS(dtime) > 9.0 ){ /* set goals in time */
if(G.f & G_DEBUG) printf("SB_STEPSIZE \n");
break; // sorry but i must assume goal movement can't be interpolated any more
}
//set goals in time
interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime))); interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime)));
// do predictive euler step /* do predictive euler step */
softbody_calc_forces(ob, forcetime); softbody_calc_forces(ob, forcetime);
softbody_apply_forces(ob, forcetime, 1, NULL); softbody_apply_forces(ob, forcetime, 1, NULL);
// crop new slope values to do averaged slope step /* crop new slope values to do averaged slope step */
softbody_calc_forces(ob, forcetime); softbody_calc_forces(ob, forcetime);
softbody_apply_forces(ob, forcetime, 2, &err); softbody_apply_forces(ob, forcetime, 2, &err);
softbody_apply_goalsnap(ob); softbody_apply_goalsnap(ob);
if (err > SoftHeunTol){ // error needs to be scaled to some quantity if (err > SoftHeunTol){ /* error needs to be scaled to some quantity */
softbody_restore_prev_step(ob); softbody_restore_prev_step(ob);
forcetime /= 2.0; forcetime /= 2.0;
} }
else { else {
float newtime = forcetime * 1.1f; // hope for 1.1 times better conditions in next step float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */
if (err > SoftHeunTol/2.0){ // stay with this stepsize unless err really small if (err > SoftHeunTol/2.0){ /* stay with this stepsize unless err really small */
newtime = forcetime; newtime = forcetime;
} }
timedone += forcetime; timedone += forcetime;
@ -1516,7 +1535,7 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
} }
loops++; loops++;
} }
// move snapped to final position /* move snapped to final position */
interpolate_exciter(ob, 2, 2); interpolate_exciter(ob, 2, 2);
softbody_apply_goalsnap(ob); softbody_apply_goalsnap(ob);