Fix for # 2655

Now triangles and quads of _any_ shape collide nicly with softbodies.
Some tricks don't work in a non euclidian geometry !
Had to brush up that dusty knowlege a bit :)

thanks efbie & ton
This commit is contained in:
2005-06-06 18:52:07 +00:00
parent 9abdd362b7
commit 91b5992b49

View File

@@ -1519,8 +1519,8 @@ int object_wave(Object *ob)
}
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,struct Object *vertexowner)
float facenormal[3], float *damp, float force[3], int mode,
float cur_time, unsigned int par_layer,struct Object *vertexowner)
{
Base *base;
Object *ob, *deflection_object = NULL;
@@ -1534,17 +1534,16 @@ int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
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 declaration rules when WIP is finished (BM)
float u,v,len_u,len_v;
// i'm going to rearrange it to declaration rules when WIP is finished (BM)
float innerfacethickness = -0.5f;
float outerfacethickness = 0.2f;
float ee = 5.0f;
float ff = 0.1f;
float fa;
min_t = 200000;
/* The first part of the code, finding the first intersected face*/
base= G.scene->base.first;
while (base) {
@@ -1552,27 +1551,27 @@ int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
if(base->object->type==OB_MESH && (base->lay & par_layer)) {
ob= base->object;
if((vertexowner) && (ob == vertexowner)){
/* if vertexowner is given
* we don't want to check collision with owner object */
/* if vertexowner is given
* we don't want to check collision with owner object */
base = base->next;
continue;
}
/* 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;
/* need to have user control for that since it depends on model scale */
/* need to have user control for that since it depends on model scale */
innerfacethickness =-ob->pd->pdef_sbift;
outerfacethickness =ob->pd->pdef_sboft;
fa = (ff*outerfacethickness-outerfacethickness);
fa *= fa;
fa = 1.0f/fa;
fa = (ff*outerfacethickness-outerfacethickness);
fa *= fa;
fa = 1.0f/fa;
if(ob->parent==NULL && ob->ipo==NULL) { // static
if(ob->sumohandle==NULL) cache_object_vertices(ob);
@@ -1593,11 +1592,11 @@ int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
obloc[2] = ob->obmat[3][2];
/* not cachable */
vcache= NULL;
}
while (a--) {
if(vcache) {
v1= vcache+ 3*(mface->v1);
VECCOPY(nv1, v1);
@@ -1614,18 +1613,18 @@ int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
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);
@@ -1633,39 +1632,31 @@ int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
}
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);
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
facedist = Inpf(dv1,d_nvect);
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);
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
dv2[0] = opco[0] - 2.0f*facedist*d_nvect[0];
dv2[1] = opco[1] - 2.0f*facedist*d_nvect[1];
dv2[2] = opco[2] - 2.0f*facedist*d_nvect[2];
if ( linetriangle( opco, dv2, nv1, nv2, nv3, &t)){
force_mag_norm =(float)exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force_mag_norm =(float)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_sbdamp;
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
@@ -1674,31 +1665,24 @@ int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
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);
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
facedist = Inpf(dv1,d_nvect);
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 =(float)exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
dv2[0] = opco[0] - 2.0f*facedist*d_nvect[0];
dv2[1] = opco[1] - 2.0f*facedist*d_nvect[1];
dv2[2] = opco[2] - 2.0f*facedist*d_nvect[2];
if ( linetriangle( opco, dv2, nv1, nv3, nv4, &t)){
force_mag_norm =(float)exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =(float)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_sbdamp;
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];
}
}
@@ -1707,58 +1691,58 @@ int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
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) {
//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 = 2;
deflected_now = 1;
}
}
}
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);
// 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;
}
}
}
}
} // not -100
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);
}
}
}
mface++;
}
}
}
base = base->next;
} // while (base)
if (mode == 1){ // face
return deflected;
}
}
if (mode == 2){ // edge intrusion test
if (deflected) {
VECSUB(edge1, dv1, dv2);
@@ -1770,14 +1754,7 @@ int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
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;
}
VECCOPY(facenormal,d_nvect);
}
}
return deflected;