diff options
author | Jens Ole Wund <bjornmose@gmx.net> | 2005-04-19 01:51:45 +0400 |
---|---|---|
committer | Jens Ole Wund <bjornmose@gmx.net> | 2005-04-19 01:51:45 +0400 |
commit | 1d47d662f9c6b5a2bcaec90b1a4ff78781107553 (patch) | |
tree | 47f95a887d81844a172cd7470b188a82c90b0e91 /source | |
parent | 99ee8915969ad4cdb55c88c025e674f4c1cb89fd (diff) |
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
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_effect.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_softbody.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/effect.c | 294 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/softbody.c | 415 |
4 files changed, 368 insertions, 347 deletions
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index e7eca88535c..4d5ab274fc5 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -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, 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 diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index 09be644c9e7..e612769c305 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -39,6 +39,7 @@ typedef struct BodyPoint { float weight, goal; float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */ int nofsprings; int *springs; + float contactfrict; } BodyPoint; typedef struct BodySpring { diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 5f77d40530c..46b6e330754 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -607,6 +607,8 @@ int pdDoDeflection(float opco[3], float npco[3], float opno[3], obloc[0] = ob->obmat[3][0]; obloc[1] = ob->obmat[3][1]; obloc[2] = ob->obmat[3][2]; + vcache= NULL; + } while (a--) { @@ -646,7 +648,9 @@ int pdDoDeflection(float opco[3], float npco[3], float opno[3], } deflected_now = 0; - + + + // 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) ) { @@ -694,34 +698,6 @@ 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 */ @@ -1540,3 +1516,263 @@ int object_wave(Object *ob) } 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; +} + diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index e6d6dd7c341..ab5e50d9440 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -87,6 +87,7 @@ extern int get_defgroup_num (Object *ob, bDeformGroup *dg); // removes *unnecessary* stiffnes from ODE system #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 /* local prototypes */ @@ -298,174 +299,50 @@ 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) +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 dummy[3],s_actpos[3], s_futurepos[3]; + 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 (slip) *slip *= 0.98f; if (bounce) *bounce *= 1.5f; - deflected= pdDoDeflection(s_actpos, s_futurepos, collisionpos, - facenormal, sb->ctime, dummy , -1, + 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); } -#if 0 -static int sb_deflect_test(float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *slip ,float *bounce) +/* 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 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; - - 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; + + + deflected= SoftBodyDetectCollision(s_actpos, s_futurepos, collisionpos, + facenormal, dummy, dummy , 2, + G.scene->r.cfra, ob->lay, &last_ob, &last_fc, &same_fc); + return(deflected); + } -#endif - - +*/ +// some functions removed here .. to help HOS on next merge (BM) #define USES_FIELD 1 #define USES_DEFLECT 2 @@ -521,7 +398,7 @@ static void softbody_calc_forces(Object *ob, float forcetime) /* calulate damping forces generated by goals*/ VecSubf(velgoal,bp->origS, bp->origE); 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]); bp->force[1]-= kd * (velgoal[1] + bp->vec[1]); @@ -538,7 +415,7 @@ static void softbody_calc_forces(Object *ob, float forcetime) /* gravitation */ bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */ - + /* particle field & vortex */ if(do_effector & USES_FIELD) { 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); /* apply speed. note; deflector can give 'speed' only.... */ /* nooo! we never alter free variables :bp->vec bp->pos in here ! - * this will ruin adative stepsize AHA heun! (BM) - * VECADD(bp->vec, bp->vec, speed); - */ - /* friction in moving media */ - - kd= sb->mediafrict* eval_sb_fric_force_scale; + * this will ruin adative stepsize AHA heun! (BM) + * VECADD(bp->vec, bp->vec, speed); + */ + /* friction in moving media */ + + 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*/ @@ -575,42 +452,38 @@ static void softbody_calc_forces(Object *ob, float forcetime) bp->force[2]-= bp->vec[2]*kd; /* friction in media done */ } - + /*other forces*/ /* this is the place where other forces can be added yes, constraints and collision stuff should go here too (read baraff papers on that!) */ -#if 0 - /* copied from particles... doesn't work really! */ + /* try to match moving collision targets */ + /* master switch to turn collision off (BM)*/ + //if(0) { if(do_effector & USES_DEFLECT) { - int deflected; - int last_ob = -1; - int last_fc = -1; - int same_fc = 0; - float last[3], lastv[3]; - int finish_defs = 1; - int def_count = 0; + /*sorry for decl. here i'll move 'em up when WIP is done (BM) */ + float defforce[3]; + float collisionpos[3],facenormal[3]; + float cf = 1.0f; + float bounce = 0.5f; + kd = 1.0f; + defforce[0] = 0.0f; + defforce[1] = 0.0f; + defforce[2] = 0.0f; - VecSubf(last, bp->pos, bp->vec); - VECCOPY(lastv, bp->vec); - - while (finish_defs) { - deflected= pdDoDeflection(last, bp->pos, lastv, - 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; - } + if (sb_deflect_face(ob,bp->pos, bp->pos, collisionpos, facenormal,defforce,&cf,&bounce)){ + bp->force[0] += defforce[0]*kd; + bp->force[1] += defforce[1]*kd; + bp->force[2] += defforce[2]*kd; + bp->contactfrict = cf; + } + else{ + bp->contactfrict = 0.0f; } + } -#endif + /*other forces done*/ - /* nice things could be done with anisotropic friction like wind/air resistance in normal direction --> 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 hrms .. may be a rough one could be used as well .. let's see */ - + if(ob->softflag & OB_SB_EDGES) { - if (1){ /* big mesh optimization */ - /* run over attached inner spring list */ - if (sb->bspring){ // spring list exists at all ? - 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->bspring){ // spring list exists at all ? + 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) ){ @@ -691,17 +523,25 @@ static void softbody_calc_forces(Object *ob, float forcetime) 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); + Vec3PlusStVec(bp->force,+forcefactor,sd); } - }// no snap - }//for - }// if use edges - } - } + }/* loop springs */ + }/* existing spring list */ + }/*any edges*/ + }/*omit on snap */ + }/*loop all bp's*/ } 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 timeovermass; float maxerr = 0.0; - int a; + int a, do_effector; forcetime *= sb_time_scale(ob); + /* check! */ + do_effector= is_there_deflection(ob->lay); // claim a minimum mass for vertex 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[1] - bp->prevdx[1])); maxerr = MAX2(maxerr,ABS(dx[2] - bp->prevdx[2])); - } - else { VECADD(bp->pos, bp->pos, dx);} - if(1) { - - // 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.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])); - - /* */ - - +/* kind of hack .. while inside collision target .. make movement more *viscous* */ + if (bp->contactfrict > 0.0f){ + bp->vec[0] *= (1.0 - bp->contactfrict); + bp->vec[1] *= (1.0 - bp->contactfrict); + bp->vec[2] *= (1.0 - bp->contactfrict); } } - } - - - - + else { VECADD(bp->pos, bp->pos, dx);} +// experimental particle collision suff was here .. just to help HOS on next merge (BM) }//snap } //for 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->springs= NULL; + bp->contactfrict = 0.0f; } |