forked from bartvdbraak/blender
Did put softbody time scaling stuff to functions,
so we can decide later what proper timing is meant to be. i've prepared something in static float sb_time_scale(Object *ob) [softbody.c] (ton :) ) 'hacked in' particle collision system to match softbodies needs naa .. i don't realy like the hack to int pdDoDeflection(..) in kernel .. effect.c (but it works :) ) so .. until we'll have a 'nice' collision detector this is what 'softbodies simulator can live with' did not remove intentionally test function static int sb_deflect_test(..) for further discussions http://mitglied.lycos.de/mosebjorn/hidden/ sbcol6.blend should work for a while
This commit is contained in:
parent
14fe1cb215
commit
c7b82c40c2
@ -688,6 +688,35 @@ int pdDoDeflection(float opco[3], float npco[3], float opno[3],
|
||||
base = base->next;
|
||||
}
|
||||
|
||||
if (def_depth = -1){ // evil hack to signal softbodies
|
||||
if (deflected) {
|
||||
VECSUB(edge1, dv1, dv2);
|
||||
VECSUB(edge2, dv3, dv2);
|
||||
Crossf(d_nvect, edge2, edge1);
|
||||
n_mag = Normalise(d_nvect);
|
||||
dk_plane = INPR(d_nvect, nv1);
|
||||
dk_point1 = INPR(d_nvect,opco);
|
||||
|
||||
VECSUB(d_intersect_vect, npco, opco);
|
||||
// abuse opno to return point of intersection
|
||||
opno[0] = opco[0] + (min_t * (npco[0] - opco[0]));
|
||||
opno[1] = opco[1] + (min_t * (npco[1] - opco[1]));
|
||||
opno[2] = opco[2] + (min_t * (npco[2] - opco[2]));
|
||||
|
||||
// abuse npno to return face normal
|
||||
VECCOPY(npno,d_nvect);
|
||||
{
|
||||
npno[0] *= -1.0f;
|
||||
npno[1] *= -1.0f;
|
||||
npno[2] *= -1.0f;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return(deflected);
|
||||
|
||||
}
|
||||
|
||||
/* Here's the point to do the permeability calculation */
|
||||
/* Set deflected to 0 if a random number is below the value */
|
||||
/* Get the permeability IPO here*/
|
||||
|
@ -88,20 +88,52 @@ extern int get_defgroup_num (Object *ob, bDeformGroup *dg);
|
||||
#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 rescale_grav_to_framerate = 1.0f; // since unit of g is [m/sec^2] we need translation from frames to physics time
|
||||
float rescale_friction_to_framerate = 1.0f; // since unit of drag is [kg/sec] we need translation from frames to physics time
|
||||
|
||||
/* local prototypes */
|
||||
static void softbody_scale_time(float steptime);
|
||||
//static void softbody_scale_time(float steptime);
|
||||
static int get_scalar_from_named_vertexgroup(Object *ob, char *name, int vertID, float *target);
|
||||
static void free_softbody_intern(SoftBody *sb);
|
||||
|
||||
static void softbody_scale_time(float steptime)
|
||||
|
||||
/*+++ frame based timing +++*/
|
||||
|
||||
//physical unit of force is [kg * m / sec^2]
|
||||
|
||||
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
|
||||
// put it to a function here, so we can add user options later without touching simulation code
|
||||
{
|
||||
rescale_grav_to_framerate = steptime*steptime;
|
||||
rescale_friction_to_framerate = steptime;
|
||||
return (0.001f);
|
||||
}
|
||||
|
||||
static float sb_fric_force_scale(Object *ob)
|
||||
// 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
|
||||
{
|
||||
return (0.01f);
|
||||
}
|
||||
|
||||
static float sb_time_scale(Object *ob)
|
||||
// defining the frames to *real* time relation
|
||||
{
|
||||
/*
|
||||
SoftBody *sb= ob->soft; // is supposed to be there
|
||||
if (sb){
|
||||
return(sb->physics_speed); //hrms .. this could be IPO as well :)
|
||||
// estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
|
||||
// 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);
|
||||
/*
|
||||
this would be frames/sec independant timing assuming 25 fps is default
|
||||
but does not work very well with NLA
|
||||
return (25.0f/G.scene->r.frs_sec)
|
||||
*/
|
||||
}
|
||||
/*--- frame based timing ---*/
|
||||
|
||||
|
||||
static int count_mesh_quads(Mesh *me)
|
||||
{
|
||||
@ -268,6 +300,175 @@ static void Vec3PlusStVec(float *v, float s, float *v1)
|
||||
v[2] += s*v1[2];
|
||||
}
|
||||
|
||||
static int sb_deflect_particle(Object *ob,float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *slip ,float *bounce)
|
||||
{
|
||||
int deflected;
|
||||
int last_ob = -1;
|
||||
int last_fc = -1;
|
||||
int same_fc = 0;
|
||||
float dummy[3],s_actpos[3], s_futurepos[3];
|
||||
SoftBody *sb= ob->soft; // is supposed to be there
|
||||
VECCOPY(s_actpos,actpos);
|
||||
VECCOPY(s_futurepos,futurepos);
|
||||
if (slip) *slip *= 0.98f;
|
||||
if (bounce) *bounce *= 1.5f;
|
||||
|
||||
|
||||
deflected= pdDoDeflection(actpos, futurepos, collisionpos,
|
||||
facenormal, sb->ctime, dummy , -1,
|
||||
G.scene->r.cfra, ob->lay, &last_ob, &last_fc, &same_fc);
|
||||
return(deflected);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int sb_deflect_test(float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *slip ,float *bounce)
|
||||
{
|
||||
|
||||
if (slip) *slip *= 0.98f;
|
||||
if (bounce) *bounce *= 1.5f;
|
||||
|
||||
if (
|
||||
( futurepos[0] > 0.0) && ( futurepos[0] < 1.0) // having unit square acting as defelecting region
|
||||
&& ( futurepos[1] > 0.0) && ( futurepos[1] < 1.0)
|
||||
&& ( (( futurepos[2] > 1.0) && ( actpos[2] <= 1.0)) //intersecting at z == 1;
|
||||
||(( futurepos[2] < 1.0) && ( actpos[2] >= 1.0))) )
|
||||
|
||||
{
|
||||
if (facenormal){
|
||||
facenormal[0] = 0.0f;
|
||||
facenormal[1] = 0.0f;
|
||||
facenormal[2] = -1.0f;
|
||||
}
|
||||
if (collisionpos){
|
||||
collisionpos[0] = (actpos[0] + futurepos[0])/2.0f;
|
||||
collisionpos[1] = (actpos[1] + futurepos[1])/2.0f;
|
||||
collisionpos[2] = 1.0f;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
if (
|
||||
( futurepos[0] > 0.0) && ( futurepos[0] < 1.0) // having unit square acting as defelecting region
|
||||
&& ( futurepos[1] > 0.0) && ( futurepos[1] < 1.0)
|
||||
&& ( (( futurepos[2] > 0.0) && ( actpos[2] <= 0.0)) //intersecting at z == 1;
|
||||
||(( futurepos[2] < 0.0) && ( actpos[2] >= 0.0)) ) )
|
||||
|
||||
{
|
||||
if (facenormal){
|
||||
facenormal[0] = 0.0f;
|
||||
facenormal[1] = 0.0f;
|
||||
if (futurepos[2] < 0.0)
|
||||
facenormal[2] = -1.0f;
|
||||
else facenormal[2] = 1.0f;
|
||||
}
|
||||
if (collisionpos){
|
||||
collisionpos[0] = (actpos[0] + futurepos[0])/2.0f;
|
||||
collisionpos[1] = (actpos[1] + futurepos[1])/2.0f;
|
||||
collisionpos[2] = 0.0f;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
if (
|
||||
( futurepos[2] > 0.0) && ( futurepos[2] < 1.0) // having unit square acting as defelecting region
|
||||
&& ( futurepos[1] > 0.0) && ( futurepos[1] < 1.0)
|
||||
&& (
|
||||
/* (( futurepos[0] > 1.0) && ( actpos[0] <= 1.0)) //intersecting at x == 1;
|
||||
||*/
|
||||
|
||||
/* experiment distinguish inside and outside*/
|
||||
|
||||
(( futurepos[0] < 1.0) && ( actpos[0] >= 1.0))) )
|
||||
|
||||
{
|
||||
if (facenormal){
|
||||
facenormal[0] = -1.0f;
|
||||
facenormal[1] = 0.0f;
|
||||
facenormal[2] = 0.0f;
|
||||
}
|
||||
if (collisionpos){
|
||||
collisionpos[0] = 1.0f;
|
||||
collisionpos[1] = (actpos[1] + futurepos[1])/2.0f;
|
||||
collisionpos[2] = (actpos[2] + futurepos[2])/2.0f;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
if (
|
||||
( futurepos[2] > 0.0) && ( futurepos[2] < 1.0) // having unit square acting as defelecting region
|
||||
&& ( futurepos[1] > 0.0) && ( futurepos[1] < 1.0)
|
||||
&& ( (( futurepos[0] > 0.0) && ( actpos[0] <= 0.0)) //intersecting at x == 0;
|
||||
||(( futurepos[0] < 0.0) && ( actpos[0] >= 0.0))) )
|
||||
|
||||
{
|
||||
if (facenormal){
|
||||
facenormal[0] = 1.0f;
|
||||
facenormal[1] = 0.0f;
|
||||
facenormal[2] = 0.0f;
|
||||
}
|
||||
if (collisionpos){
|
||||
collisionpos[0] = 0.0f;
|
||||
collisionpos[1] = (actpos[1] + futurepos[1])/2.0f;
|
||||
collisionpos[2] = (actpos[2] + futurepos[2])/2.0f;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
( futurepos[0] > 0.0) && ( futurepos[0] < 1.0) // having unit square acting as defelecting region
|
||||
&& ( futurepos[2] > 0.0) && ( futurepos[2] < 1.0)
|
||||
&& ( (( futurepos[1] > 0.0) && ( actpos[1] <= 0.0)) //intersecting at Y == 0;
|
||||
||(( futurepos[1] < 0.0) && ( actpos[1] >= 0.0))) )
|
||||
|
||||
{
|
||||
if (facenormal){
|
||||
facenormal[0] = 0.0f;
|
||||
facenormal[1] = 1.0f;
|
||||
facenormal[2] = 0.0f;
|
||||
}
|
||||
if (collisionpos){
|
||||
collisionpos[0] = (actpos[0] + futurepos[0])/2.0f;
|
||||
collisionpos[2] = (actpos[2] + futurepos[2])/2.0f;
|
||||
collisionpos[1] = 0.0f;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
if (
|
||||
( futurepos[0] > 0.0) && ( futurepos[0] < 1.0) // having unit square acting as defelecting region
|
||||
&& ( futurepos[2] > 0.0) && ( futurepos[2] < 1.0)
|
||||
&& ( (( futurepos[1] > 1.0) && ( actpos[1] <= 1.0)) //intersecting at Y == 0;
|
||||
||(( futurepos[1] < 1.0) && ( actpos[1] >= 1.0))) )
|
||||
|
||||
{
|
||||
if (facenormal){
|
||||
facenormal[0] = 0.0f;
|
||||
facenormal[1] = -1.0f;
|
||||
facenormal[2] = 0.0f;
|
||||
}
|
||||
if (collisionpos){
|
||||
collisionpos[0] = (actpos[0] + futurepos[0])/2.0f;
|
||||
collisionpos[2] = (actpos[2] + futurepos[2])/2.0f;
|
||||
collisionpos[1] = 1.0f;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define USES_FIELD 1
|
||||
#define USES_DEFLECT 2
|
||||
static int is_there_deflection(unsigned int layer)
|
||||
@ -299,7 +500,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
|
||||
bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
|
||||
}
|
||||
|
||||
gravity = sb->grav * rescale_grav_to_framerate;
|
||||
gravity = sb->grav * sb_grav_force_scale(ob);
|
||||
/* check! */
|
||||
do_effector= is_there_deflection(ob->lay);
|
||||
iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
|
||||
@ -321,7 +522,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
|
||||
bp->force[2]= ks*(auxvect[2]);
|
||||
/* calulate damping forces generated by goals*/
|
||||
VecSubf(velgoal,bp->origS, bp->origE);
|
||||
kd = sb->goalfrict * rescale_friction_to_framerate ;
|
||||
kd = sb->goalfrict * sb_fric_force_scale(ob) ;
|
||||
|
||||
if (forcetime > 0.0 ) { // make sure friction does not become rocket motor on time reversal
|
||||
bp->force[0]-= kd * (velgoal[0] + bp->vec[0]);
|
||||
@ -344,13 +545,14 @@ static void softbody_calc_forces(Object *ob, float forcetime)
|
||||
if(do_effector & USES_FIELD) {
|
||||
float force[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
|
||||
|
||||
pdDoEffector(bp->pos, force, speed, (float)G.scene->r.cfra, ob->lay,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 force */
|
||||
// VecMulf(force, rescale_grav_to_framerate); <- didn't work, made value far too low!
|
||||
VecMulf(force,25.0f* rescale_friction_to_framerate);
|
||||
VecMulf(force,25.0f* eval_sb_fric_force_scale);
|
||||
VECADD(bp->force, bp->force, force);
|
||||
/* apply speed. note; deflector can give 'speed' only.... */
|
||||
/* nooo! we never alter free variables :bp->vec bp->pos in here !
|
||||
@ -358,16 +560,17 @@ static void softbody_calc_forces(Object *ob, float forcetime)
|
||||
* VECADD(bp->vec, bp->vec, speed);
|
||||
*/
|
||||
/* friction in moving media */
|
||||
kd= sb->mediafrict* rescale_friction_to_framerate;
|
||||
bp->force[0] -= kd * (bp->vec[0] + speed[0]/rescale_friction_to_framerate);
|
||||
bp->force[1] -= kd * (bp->vec[1] + speed[1]/rescale_friction_to_framerate);
|
||||
bp->force[2] -= kd * (bp->vec[2] + speed[2]/rescale_friction_to_framerate);
|
||||
|
||||
kd= sb->mediafrict* eval_sb_fric_force_scale;
|
||||
bp->force[0] -= kd * (bp->vec[0] + speed[0]/eval_sb_fric_force_scale);
|
||||
bp->force[1] -= kd * (bp->vec[1] + speed[1]/eval_sb_fric_force_scale);
|
||||
bp->force[2] -= kd * (bp->vec[2] + speed[2]/eval_sb_fric_force_scale);
|
||||
/* now we'll have nice centrifugal effect for vortex */
|
||||
|
||||
}
|
||||
else {
|
||||
/* friction in media (not) moving*/
|
||||
kd= sb->mediafrict* rescale_friction_to_framerate;
|
||||
kd= sb->mediafrict* sb_fric_force_scale(ob);
|
||||
/* assume it to be proportional to actual velocity */
|
||||
bp->force[0]-= bp->vec[0]*kd;
|
||||
bp->force[1]-= bp->vec[1]*kd;
|
||||
@ -431,7 +634,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
|
||||
|
||||
// friction stuff V1
|
||||
VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
|
||||
kd = sb->infrict * rescale_friction_to_framerate ;
|
||||
kd = sb->infrict * sb_fric_force_scale(ob);
|
||||
absvel = Normalise(velgoal);
|
||||
projvel = ABS(Inpf(sd,velgoal));
|
||||
kd *= absvel * projvel;
|
||||
@ -453,7 +656,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
|
||||
|
||||
// friction stuff V2
|
||||
VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
|
||||
kd = sb->infrict * rescale_friction_to_framerate ;
|
||||
kd = sb->infrict * sb_fric_force_scale(ob);
|
||||
absvel = Normalise(velgoal);
|
||||
projvel = ABS(Inpf(sd,velgoal));
|
||||
kd *= absvel * projvel;
|
||||
@ -514,7 +717,10 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
|
||||
float timeovermass;
|
||||
float maxerr = 0.0;
|
||||
int a;
|
||||
|
||||
|
||||
forcetime *= sb_time_scale(ob);
|
||||
|
||||
// claim a minimum mass for vertex
|
||||
if (sb->nodemass > 0.09999f) timeovermass = forcetime/sb->nodemass;
|
||||
else timeovermass = forcetime/0.09999f;
|
||||
|
||||
@ -570,6 +776,74 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
|
||||
maxerr = MAX2(maxerr,ABS(dx[2] - bp->prevdx[2]));
|
||||
}
|
||||
else { VECADD(bp->pos, bp->pos, dx);}
|
||||
{
|
||||
|
||||
// experimental collision
|
||||
// we need the above calcualtions done though we'll over ride bp->pos bp->vel
|
||||
if (mode ==2){
|
||||
float vv[3],collisionpos[3],facenormal[3];
|
||||
float slip = 1.0f;
|
||||
float bounce = 1.0f;
|
||||
float projvel;
|
||||
float deswampingconstant = 0.1;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
slip = sb->slip; // parameter for tangetial interaction
|
||||
bounce = sb->bounce; // parameter for normal interaction
|
||||
*/
|
||||
// if (sb_deflect_test(bp->prevpos, bp->pos, collisionpos, facenormal,&slip,&bounce)){
|
||||
if (sb_deflect_particle(ob,bp->prevpos, bp->pos, collisionpos, facenormal,&slip,&bounce)){
|
||||
|
||||
|
||||
VecSubf(vv,bp->pos,bp->prevpos);
|
||||
projvel = ABS(Inpf(vv,facenormal));
|
||||
|
||||
|
||||
if (1) // mushy impact
|
||||
{
|
||||
float tangential_vel[3];
|
||||
float helper_vect[3];
|
||||
float hf;
|
||||
hf = Inpf(bp->vec,facenormal);
|
||||
/* make helper_vect vel along normal */
|
||||
helper_vect[0] = hf * facenormal[0];
|
||||
helper_vect[1] = hf * facenormal[1];
|
||||
helper_vect[2] = hf * facenormal[2];
|
||||
/* now we have a nice slip along vector */
|
||||
VecSubf(tangential_vel,bp->vec,helper_vect);
|
||||
|
||||
|
||||
|
||||
|
||||
bp->vec[0] = tangential_vel[0]* slip - (bounce * 2.0f * projvel * facenormal[0]);
|
||||
bp->vec[1] = tangential_vel[1]* slip - (bounce * 2.0f * projvel * facenormal[1]);
|
||||
bp->vec[2] = tangential_vel[2]* slip - (bounce * 2.0f * projvel * facenormal[2]);
|
||||
}
|
||||
else{
|
||||
// 100 % sticky surface
|
||||
bp->vec[0] = vv[0] - (bounce * 2.0f * projvel * facenormal[0]);
|
||||
bp->vec[1] = vv[1] - (bounce * 2.0f * projvel * facenormal[1]);
|
||||
bp->vec[2] = vv[2] - (bounce * 2.0f * projvel * facenormal[2]);
|
||||
}
|
||||
// pull our vertex out of the swamp .. not very accurate but who will notice
|
||||
bp->pos[0] = collisionpos[0] + deswampingconstant * bp->vec[0] ;
|
||||
bp->pos[1] = collisionpos[1] + deswampingconstant * bp->vec[1] ;
|
||||
bp->pos[2] = collisionpos[2] + deswampingconstant * bp->vec[2];
|
||||
maxerr = MAX2(maxerr,ABS(bounce*vv[0]));
|
||||
maxerr = MAX2(maxerr,ABS(bounce*vv[1]));
|
||||
maxerr = MAX2(maxerr,ABS(bounce*vv[2]));
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}//snap
|
||||
} //for
|
||||
@ -1086,7 +1360,6 @@ void sbObjectStep(Object *ob, float framenr)
|
||||
|
||||
/* checking time: */
|
||||
ctime= bsystem_time(ob, NULL, framenr, 0.0);
|
||||
softbody_scale_time(1.0f/G.scene->r.frs_sec); // translate frames/sec and lenghts unit to SI system
|
||||
dtime= ctime - sb->ctime;
|
||||
// bail out for negative or for large steps
|
||||
if(dtime<0.0 || dtime >= 9.9*G.scene->r.framelen) { // note: what is G.scene->r.framelen for ? (BM)
|
||||
|
Loading…
Reference in New Issue
Block a user