removed my SB hack from particle collision code

(which still can't really handle moving targets)
leaving 2 bug fixes
1. multiple objects need a reset on cache variable
2. quads always need to be handled as 2 triangles
(since they don't need to share a plane)

added a collision detecting function in effect.c for SB
( no need to be there, but i did not find a better place )
but should handle 'moving targets' up to 0.2 blender units/frame

well .. important info in this case:
collision
uses 'face normal' to decide if *intrusion* happend
uses 'damping' of collision target to slow down movement
when *intrusion* happend

+some more removing unneeded code in softbody.c
This commit is contained in:
Jens Ole Wund 2005-04-18 21:51:45 +00:00
parent 99ee891596
commit 1d47d662f9
4 changed files with 371 additions and 350 deletions

@ -70,6 +70,11 @@ int pdDoDeflection(float opco[3], float npco[3], float opno[3],
float cur_time, unsigned int par_layer, int *last_object, float cur_time, unsigned int par_layer, int *last_object,
int *last_face, int *same_face); int *last_face, int *same_face);
int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
float facenormal[3], float *damp, float force[3], int mode,
float cur_time, unsigned int par_layer, int *last_object,
int *last_face, int *same_face);
#endif #endif

@ -39,6 +39,7 @@ typedef struct BodyPoint {
float weight, goal; float weight, goal;
float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */ float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */
int nofsprings; int *springs; int nofsprings; int *springs;
float contactfrict;
} BodyPoint; } BodyPoint;
typedef struct BodySpring { typedef struct BodySpring {

@ -607,6 +607,8 @@ int pdDoDeflection(float opco[3], float npco[3], float opno[3],
obloc[0] = ob->obmat[3][0]; obloc[0] = ob->obmat[3][0];
obloc[1] = ob->obmat[3][1]; obloc[1] = ob->obmat[3][1];
obloc[2] = ob->obmat[3][2]; obloc[2] = ob->obmat[3][2];
vcache= NULL;
} }
while (a--) { while (a--) {
@ -646,7 +648,9 @@ int pdDoDeflection(float opco[3], float npco[3], float opno[3],
} }
deflected_now = 0; deflected_now = 0;
// t= 0.5; // this is labda of line, can use it optimize quad intersection // t= 0.5; // this is labda of line, can use it optimize quad intersection
// sorry but no .. see below (BM) // sorry but no .. see below (BM)
if( linetriangle(opco, npco, nv1, nv2, nv3, &t) ) { if( linetriangle(opco, npco, nv1, nv2, nv3, &t) ) {
@ -694,34 +698,6 @@ int pdDoDeflection(float opco[3], float npco[3], float opno[3],
base = base->next; 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 */ /* Here's the point to do the permeability calculation */
/* Set deflected to 0 if a random number is below the value */ /* Set deflected to 0 if a random number is below the value */
@ -1540,3 +1516,263 @@ int object_wave(Object *ob)
} }
return 1; return 1;
} }
int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
float facenormal[3], float *damp, float force[3], int mode,
float cur_time, unsigned int par_layer, int *last_object,
int *last_face, int *same_face)
{
Base *base;
Object *ob, *deflection_object = NULL;
Mesh *def_mesh;
MFace *mface, *deflection_face = NULL;
float *v1, *v2, *v3, *v4, *vcache=NULL;
float mat[3][3];
float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], obloc[3];
float dv1[3], dv2[3], dv3[3];
float facedist,n_mag,t,t2, min_t,force_mag_norm;
int a, deflected=0, deflected_now=0;
short cur_frame;
int d_object=0, d_face=0, ds_object=0, ds_face=0;
// i'm going to rearrange it to declatation rules when WIP is finoshed (BM)
float u,v,len_u,len_v;
float innerfacethickness = -0.5f;
float outerfacethickness = 0.2f;
float ee = 5.0f;
float ff = 0.1f;
float fa;
fa = (ff*outerfacethickness-outerfacethickness);
fa *= fa;
fa = 1.0f/fa;
min_t = 200000;
/* The first part of the code, finding the first intersected face*/
base= G.scene->base.first;
while (base) {
/*Only proceed for mesh object in same layer */
if(base->object->type==OB_MESH && (base->lay & par_layer)) {
ob= base->object;
/* only with deflecting set */
if(ob->pd && ob->pd->deflect) {
def_mesh= ob->data;
d_object = d_object + 1;
d_face = d_face + 1;
mface= def_mesh->mface;
a = def_mesh->totface;
if(ob->parent==NULL && ob->ipo==NULL) { // static
if(ob->sumohandle==NULL) cache_object_vertices(ob);
vcache= ob->sumohandle;
}
else {
/*Find out where the object is at this 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;
/*Pass the values from ob->obmat to mat*/
/*and the location values to obloc */
Mat3CpyMat4(mat,ob->obmat);
obloc[0] = ob->obmat[3][0];
obloc[1] = ob->obmat[3][1];
obloc[2] = ob->obmat[3][2];
/* not cachable */
vcache= NULL;
}
while (a--) {
if(vcache) {
v1= vcache+ 3*(mface->v1);
VECCOPY(nv1, v1);
v1= vcache+ 3*(mface->v2);
VECCOPY(nv2, v1);
v1= vcache+ 3*(mface->v3);
VECCOPY(nv3, v1);
v1= vcache+ 3*(mface->v4);
VECCOPY(nv4, v1);
}
else {
/* Calculate the global co-ordinates of the vertices*/
v1= (def_mesh->mvert+(mface->v1))->co;
v2= (def_mesh->mvert+(mface->v2))->co;
v3= (def_mesh->mvert+(mface->v3))->co;
v4= (def_mesh->mvert+(mface->v4))->co;
VECCOPY(nv1, v1);
VECCOPY(nv2, v2);
VECCOPY(nv3, v3);
VECCOPY(nv4, v4);
/*Apply the objects deformation matrix*/
Mat3MulVecfl(mat, nv1);
Mat3MulVecfl(mat, nv2);
Mat3MulVecfl(mat, nv3);
Mat3MulVecfl(mat, nv4);
VECADD(nv1, nv1, obloc);
VECADD(nv2, nv2, obloc);
VECADD(nv3, nv3, obloc);
VECADD(nv4, nv4, obloc);
}
deflected_now = 0;
if (mode == 1){ // face intrusion test
// switch origin to be nv2
VECSUB(edge1, nv1, nv2);
VECSUB(edge2, nv3, nv2);
VECSUB(dv1,opco,nv2); // abuse dv1 to have vertex in question at *origin* of triangle
len_u=Normalise(edge1);
len_v=Normalise(edge2);
u = Inpf(dv1,edge1)/len_u;
v = Inpf(dv1,edge2)/len_v;
if ( (u >= 0.0f) && (v >= 0.0f) && ((u+v) <= 1.0)){ // inside prims defined by triangle and normal
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
// ok lets add force
facedist = Inpf(dv1,d_nvect);
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
//force_mag_norm =ee*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force_mag_norm =exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force[0] += force_mag_norm*d_nvect[0] ;
force[1] += force_mag_norm*d_nvect[1] ;
force[2] += force_mag_norm*d_nvect[2] ;
*damp=ob->pd->pdef_damp;
deflected = 2;
colco[0] = nv2[0] + len_u*u*edge1[0] + len_v*v*edge2[0];
colco[1] = nv2[1] + len_u*u*edge1[1] + len_v*v*edge2[1];
colco[2] = nv2[2] + len_u*u*edge1[2] + len_v*v*edge2[2];
}
}
if (mface->v4){ // quad
// switch origin to be nv4
VECSUB(edge1, nv3, nv4);
VECSUB(edge2, nv1, nv4);
VECSUB(dv1,opco,nv4); // abuse dv1 to have vertex in question at *origin* of triangle
len_u=Normalise(edge1);
len_v=Normalise(edge2);
u = Inpf(dv1,edge1)/len_u;
v = Inpf(dv1,edge2)/len_v;
if ( (u >= 0.0f) && (v >= 0.0f) && ((u+v) <= 1.0)){ // inside prims defined by triangle and normal
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
// ok lets add force
facedist = Inpf(dv1,d_nvect);
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
//force_mag_norm =ee*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force_mag_norm =exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force[0] += force_mag_norm*d_nvect[0] ;
force[1] += force_mag_norm*d_nvect[1] ;
force[2] += force_mag_norm*d_nvect[2] ;
*damp=ob->pd->pdef_damp;
deflected = 2;
colco[0] = nv4[0] + len_u*u*edge1[0] + len_v*v*edge2[0];
colco[1] = nv4[1] + len_u*u*edge1[1] + len_v*v*edge2[1];
colco[2] = nv4[2] + len_u*u*edge1[2] + len_v*v*edge2[2];
}
}
}
}
if (mode == 2){ // edge intrusion test
// t= 0.5; // this is labda of line, can use it optimize quad intersection
// sorry but no .. see below (BM)
if( linetriangle(opco, npco, nv1, nv2, nv3, &t) ) {
if (t < min_t) {
deflected = 1;
deflected_now = 1;
}
}
// else if (mface->v4 && (t>=0.0 && t<=1.0)) {
// no, you can't skip testing the other triangle
// it might give a smaller t on (close to) the edge .. this is numerics not esoteric maths :)
// note: the 2 triangles don't need to share a plane ! (BM)
if (mface->v4) {
if( linetriangle(opco, npco, nv1, nv3, nv4, &t2) ) {
if (t2 < min_t) {
deflected = 1;
deflected_now = 2;
}
}
}
if ((deflected_now > 0) && ((t < min_t) ||(t2 < min_t))) {
min_t = t;
ds_object = d_object;
ds_face = d_face;
deflection_object = ob;
deflection_face = mface;
if (deflected_now==1) {
min_t = t;
VECCOPY(dv1, nv1);
VECCOPY(dv2, nv2);
VECCOPY(dv3, nv3);
}
else {
min_t = t2;
VECCOPY(dv1, nv1);
VECCOPY(dv2, nv3);
VECCOPY(dv3, nv4);
}
}
} // not -100
mface++;
}
}
}
base = base->next;
} // while (base)
if (mode == 1){ // face
last_object = deflection_object;
return deflected;
}
if (mode == 2){ // edge intrusion test
if (deflected) {
VECSUB(edge1, dv1, dv2);
VECSUB(edge2, dv3, dv2);
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
// return point of intersection
colco[0] = opco[0] + (min_t * (npco[0] - opco[0]));
colco[1] = opco[1] + (min_t * (npco[1] - opco[1]));
colco[2] = opco[2] + (min_t * (npco[2] - opco[2]));
VECCOPY(facenormal,d_nvect);
{
facenormal[0] *= -1.0f;
facenormal[1] *= -1.0f;
facenormal[2] *= -1.0f;
}
}
}
return deflected;
}

@ -87,6 +87,7 @@ extern int get_defgroup_num (Object *ob, bDeformGroup *dg);
// 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 */
@ -298,7 +299,29 @@ static void Vec3PlusStVec(float *v, float s, float *v1)
v[2] += s*v1[2]; v[2] += s*v1[2];
} }
static int sb_deflect_particle(Object *ob,float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *slip ,float *bounce) static int sb_deflect_face(Object *ob,float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *force,float *cf ,float *bounce)
{
int deflected;
int last_ob = -1;
int last_fc = -1;
int same_fc = 0;
float s_actpos[3], s_futurepos[3];
SoftBody *sb= ob->soft; // is supposed to be there
VECCOPY(s_actpos,actpos);
if(futurepos)
VECCOPY(s_futurepos,futurepos);
if (bounce) *bounce *= 1.5f;
deflected= SoftBodyDetectCollision(s_actpos, s_futurepos, collisionpos,
facenormal, cf, force , 1,
G.scene->r.cfra, ob->lay, &last_ob, &last_fc, &same_fc);
return(deflected);
}
/* for future use (BM)
static int sb_deflect_edge_face(Object *ob,float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *slip ,float *bounce)
{ {
int deflected; int deflected;
int last_ob = -1; int last_ob = -1;
@ -312,160 +335,14 @@ static int sb_deflect_particle(Object *ob,float *actpos, float *futurepos,float
if (bounce) *bounce *= 1.5f; if (bounce) *bounce *= 1.5f;
deflected= pdDoDeflection(s_actpos, s_futurepos, collisionpos, deflected= SoftBodyDetectCollision(s_actpos, s_futurepos, collisionpos,
facenormal, sb->ctime, dummy , -1, facenormal, dummy, dummy , 2,
G.scene->r.cfra, ob->lay, &last_ob, &last_fc, &same_fc); G.scene->r.cfra, ob->lay, &last_ob, &last_fc, &same_fc);
return(deflected); return(deflected);
} }
*/
#if 0 // some functions removed here .. to help HOS on next merge (BM)
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;
}
#endif
#define USES_FIELD 1 #define USES_FIELD 1
#define USES_DEFLECT 2 #define USES_DEFLECT 2
@ -521,7 +398,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
/* calulate damping forces generated by goals*/ /* calulate damping forces generated by goals*/
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]);
@ -538,7 +415,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
/* gravitation */ /* gravitation */
bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */ bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */
/* particle field & vortex */ /* particle field & vortex */
if(do_effector & USES_FIELD) { if(do_effector & USES_FIELD) {
float force[3]= {0.0f, 0.0f, 0.0f}; float force[3]= {0.0f, 0.0f, 0.0f};
@ -554,17 +431,17 @@ static void softbody_calc_forces(Object *ob, float forcetime)
VECADD(bp->force, bp->force, force); VECADD(bp->force, bp->force, force);
/* apply speed. note; deflector can give 'speed' only.... */ /* apply speed. note; deflector can give 'speed' only.... */
/* nooo! we never alter free variables :bp->vec bp->pos in here ! /* nooo! we never alter free variables :bp->vec bp->pos in here !
* this will ruin adative stepsize AHA heun! (BM) * this will ruin adative stepsize AHA heun! (BM)
* VECADD(bp->vec, bp->vec, speed); * VECADD(bp->vec, bp->vec, speed);
*/ */
/* friction in moving media */ /* 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] + speed[0]/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[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); bp->force[2] -= kd * (bp->vec[2] + speed[2]/eval_sb_fric_force_scale);
/* now we'll have nice centrifugal effect for vortex */ /* now we'll have nice centrifugal effect for vortex */
} }
else { else {
/* friction in media (not) moving*/ /* friction in media (not) moving*/
@ -575,42 +452,38 @@ static void softbody_calc_forces(Object *ob, float forcetime)
bp->force[2]-= bp->vec[2]*kd; bp->force[2]-= bp->vec[2]*kd;
/* friction in media done */ /* friction in media done */
} }
/*other forces*/ /*other forces*/
/* this is the place where other forces can be added /* this is the place where other forces can be added
yes, constraints and collision stuff should go here too (read baraff papers on that!) yes, constraints and collision stuff should go here too (read baraff papers on that!)
*/ */
#if 0 /* try to match moving collision targets */
/* copied from particles... doesn't work really! */ /* master switch to turn collision off (BM)*/
//if(0) {
if(do_effector & USES_DEFLECT) { if(do_effector & USES_DEFLECT) {
int deflected; /*sorry for decl. here i'll move 'em up when WIP is done (BM) */
int last_ob = -1; float defforce[3];
int last_fc = -1; float collisionpos[3],facenormal[3];
int same_fc = 0; float cf = 1.0f;
float last[3], lastv[3]; float bounce = 0.5f;
int finish_defs = 1; kd = 1.0f;
int def_count = 0; defforce[0] = 0.0f;
defforce[1] = 0.0f;
defforce[2] = 0.0f;
VecSubf(last, bp->pos, bp->vec); if (sb_deflect_face(ob,bp->pos, bp->pos, collisionpos, facenormal,defforce,&cf,&bounce)){
VECCOPY(lastv, bp->vec); bp->force[0] += defforce[0]*kd;
bp->force[1] += defforce[1]*kd;
while (finish_defs) { bp->force[2] += defforce[2]*kd;
deflected= pdDoDeflection(last, bp->pos, lastv, bp->contactfrict = cf;
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;
}
} }
else{
bp->contactfrict = 0.0f;
}
} }
#endif
/*other forces done*/ /*other forces done*/
/* nice things could be done with anisotropic friction /* nice things could be done with anisotropic friction
like wind/air resistance in normal direction like wind/air resistance in normal direction
--> having a piece of cloth sailing down --> having a piece of cloth sailing down
@ -618,72 +491,31 @@ static void softbody_calc_forces(Object *ob, float forcetime)
*valid* means to be calulated on time axis *valid* means to be calulated on time axis
hrms .. may be a rough one could be used as well .. let's see 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 (1){ /* big mesh optimization */ if (sb->bspring){ // spring list exists at all ?
/* run over attached inner spring list */ for(b=bp->nofsprings;b>0;b--){
if (sb->bspring){ // spring list exists at all ? bs = sb->bspring + bp->springs[b-1];
for(b=bp->nofsprings;b>0;b--){
bs = sb->bspring + bp->springs[b-1];
if (( (sb->totpoint-a) == bs->v1) ){
actspringlen= VecLenf( (bproot+bs->v2)->pos, bp->pos);
VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
Normalise(sd);
// friction stuff V1
VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalise(velgoal);
projvel = ABS(Inpf(sd,velgoal));
kd *= absvel * projvel;
Vec3PlusStVec(bp->force,-kd,velgoal);
if(bs->len > 0.0) /* check for degenerated springs */
forcefactor = (bs->len - actspringlen)/bs->len * iks;
else
forcefactor = actspringlen * iks;
Vec3PlusStVec(bp->force,-forcefactor,sd);
}
if (( (sb->totpoint-a) == bs->v2) ){
actspringlen= VecLenf( (bproot+bs->v1)->pos, bp->pos);
VecSubf(sd,bp->pos,(bproot+bs->v1)->pos);
Normalise(sd);
// friction stuff V2
VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalise(velgoal);
projvel = ABS(Inpf(sd,velgoal));
kd *= absvel * projvel;
Vec3PlusStVec(bp->force,-kd,velgoal);
if(bs->len > 0.0)
forcefactor = (bs->len - actspringlen)/bs->len * iks;
else
forcefactor = actspringlen * iks;
Vec3PlusStVec(bp->force,+forcefactor,sd);
}
}
} //if spring list exists at all ?
}
else{ // this branch is not completly uptaded for friction stuff
/* scan for attached inner springs makes it a O(N^2) thing = bad !*/
/* obsolete .. but if someone wants to try the effect :) */
for(b=sb->totspring, bs= sb->bspring; b>0; b--, bs++) {
if (( (sb->totpoint-a) == bs->v1) ){ if (( (sb->totpoint-a) == bs->v1) ){
actspringlen= VecLenf( (bproot+bs->v2)->pos, bp->pos); actspringlen= VecLenf( (bproot+bs->v2)->pos, bp->pos);
VecSubf(sd,(bproot+bs->v2)->pos, bp->pos); VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
Normalise(sd); Normalise(sd);
// friction stuff V1
VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalise(velgoal);
projvel = ABS(Inpf(sd,velgoal));
kd *= absvel * projvel;
Vec3PlusStVec(bp->force,-kd,velgoal);
if(bs->len > 0.0) /* check for degenerated springs */ if(bs->len > 0.0) /* check for degenerated springs */
forcefactor = (bs->len - actspringlen)/bs->len * iks; forcefactor = (bs->len - actspringlen)/bs->len * iks;
else else
forcefactor = actspringlen * iks; forcefactor = actspringlen * iks;
Vec3PlusStVec(bp->force,-forcefactor,sd); Vec3PlusStVec(bp->force,-forcefactor,sd);
} }
if (( (sb->totpoint-a) == bs->v2) ){ if (( (sb->totpoint-a) == bs->v2) ){
@ -691,17 +523,25 @@ 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
VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
kd = sb->infrict * sb_fric_force_scale(ob);
absvel = Normalise(velgoal);
projvel = ABS(Inpf(sd,velgoal));
kd *= absvel * projvel;
Vec3PlusStVec(bp->force,-kd,velgoal);
if(bs->len > 0.0) if(bs->len > 0.0)
forcefactor = (bs->len - actspringlen)/bs->len * iks; forcefactor = (bs->len - actspringlen)/bs->len * iks;
else else
forcefactor = actspringlen * iks; forcefactor = actspringlen * iks;
Vec3PlusStVec(bp->force,+forcefactor,sd); Vec3PlusStVec(bp->force,+forcefactor,sd);
} }
}// no snap }/* loop springs */
}//for }/* existing spring list */
}// if use edges }/*any edges*/
} }/*omit on snap */
} }/*loop all bp's*/
} }
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err) static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err)
@ -714,9 +554,11 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
float dx[3],dv[3]; float dx[3],dv[3];
float timeovermass; float timeovermass;
float maxerr = 0.0; float maxerr = 0.0;
int a; int a, do_effector;
forcetime *= sb_time_scale(ob); forcetime *= sb_time_scale(ob);
/* check! */
do_effector= is_there_deflection(ob->lay);
// 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;
@ -772,79 +614,15 @@ 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* */
else { VECADD(bp->pos, bp->pos, dx);} if (bp->contactfrict > 0.0f){
if(1) { bp->vec[0] *= (1.0 - bp->contactfrict);
bp->vec[1] *= (1.0 - bp->contactfrict);
// experimental collision bp->vec[2] *= (1.0 - bp->contactfrict);
// 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.0001;
/*
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];
*/
bp->pos[0] = collisionpos[0] - deswampingconstant * facenormal[0] ;
bp->pos[1] = collisionpos[1] - deswampingconstant * facenormal[1] ;
bp->pos[2] = collisionpos[2] - deswampingconstant * facenormal[2];
maxerr = MAX2(maxerr,ABS(bounce*vv[0]));
maxerr = MAX2(maxerr,ABS(bounce*vv[1]));
maxerr = MAX2(maxerr,ABS(bounce*vv[2]));
/* */
} }
} }
} else { VECADD(bp->pos, bp->pos, dx);}
// experimental particle collision suff was here .. just to help HOS on next merge (BM)
}//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 */
@ -970,6 +748,7 @@ static void set_body_point(Object *ob, BodyPoint *bp, float *vec)
bp->nofsprings= 0; bp->nofsprings= 0;
bp->springs= NULL; bp->springs= NULL;
bp->contactfrict = 0.0f;
} }