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,
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

@ -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 {

@ -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;
}

@ -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,7 +299,29 @@ 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 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 last_ob = -1;
@ -312,160 +335,14 @@ static int sb_deflect_particle(Object *ob,float *actpos, float *futurepos,float
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, dummy, dummy , 2,
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)
{
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
*/
// 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;
}