[ODE] (flat) cylinder-plane collide generates more contacts than specified
Patrik Stellmann
patrik at volleynet.de
Sat Aug 2 01:56:01 2003
This is a multi-part message in MIME format.
--------------080506090508010404050707
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
I just noticed that the cylinder-plane collider doesn't care about the
maximal number or contacts it may create. No surprise that this results
in writing to memory not meant to be used for contacts...
However, I added some checks for that without knowing if the result is
really as it shold be, but for my cases, either maximal 1 contact (to
check if there is collision) or up to 20 contacts (for actually creating
contact geoms) it works...
--------------080506090508010404050707
Content-Type: text/plain;
name="dCollideCylPlane.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="dCollideCylPlane.cpp"
int dCollideCylPlane
(
dxGeom *o1, dxGeom *o2, int flags,
dContactGeom *contact, int skip){
dIASSERT (skip >= (int)sizeof(dContactGeom));
dIASSERT (dGeomGetClass(o1) == dCylinderClassUser);
dIASSERT (dGeomGetClass(o2) == dPlaneClass);
contact->g1 = const_cast<dxGeom*> (o1);
contact->g2 = const_cast<dxGeom*> (o2);
const unsigned int maxret = (flags & NUMC_MASK); // <<<< MODIFIED
unsigned int ret = 0;
dReal radius;
dReal hlz;
dGeomCylinderGetParams(o1,&radius,&hlz);
hlz /= 2;
const dReal *R = dGeomGetRotation(o1);// rotation of cylinder
const dReal* p = dGeomGetPosition(o1);
dVector4 n; // normal vector
dReal pp;
dGeomPlaneGetParams (o2, n);
pp=n[3];
dReal cos1,sin1;
cos1=dFabs(dDOT14(n,R+1));
cos1=cos1<REAL(1.) ? cos1 : REAL(1.); //cos1 may slightly exeed 1.f
sin1=sqrtf(REAL(1.)-cos1*cos1);
//////////////////////////////
dReal sidePr=cos1*hlz+sin1*radius;
dReal dist=-pp+dDOT(n,p);
dReal outDepth=sidePr-dist;
if(outDepth<0.f) return 0;
dVector3 pos;
/////////////////////////////////////////// from geom.cpp dCollideBP
dReal Q1 = dDOT14(n,R+0);
dReal Q2 = dDOT14(n,R+1);
dReal Q3 = dDOT14(n,R+2);
dReal factor =sqrtf(Q1*Q1+Q3*Q3);
factor= factor ? factor :1.f;
dReal A1 = radius * Q1/factor;
dReal A2 = hlz*Q2;
dReal A3 = radius * Q3/factor;
pos[0]=p[0];
pos[1]=p[1];
pos[2]=p[2];
pos[0]-= A1*R[0];
pos[1]-= A1*R[4];
pos[2]-= A1*R[8];
pos[0]-= A3*R[2];
pos[1]-= A3*R[6];
pos[2]-= A3*R[10];
pos[0]-= A2>0 ? hlz*R[1]:-hlz*R[1];
pos[1]-= A2>0 ? hlz*R[5]:-hlz*R[5];
pos[2]-= A2>0 ? hlz*R[9]:-hlz*R[9];
contact->pos[0] = pos[0];
contact->pos[1] = pos[1];
contact->pos[2] = pos[2];
contact->depth = outDepth;
if (ret < maxret - 1) // <<<< MODIFIED
{
ret=1;
if(dFabs(Q2)>M_SQRT1_2)
{
CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*A1*R[0];
CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*A1*R[4];
CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*A1*R[8];
CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q1*2.f*A1);
if ((ret < maxret - 1) && // <<<< MODIFIED
(CONTACT(contact,ret*skip)->depth>0.f))
ret++;
CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*A3*R[2];
CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*A3*R[6];
CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*A3*R[10];
CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q3*2.f*A3);
if ((ret < maxret - 1) && // <<<< MODIFIED
(CONTACT(contact,ret*skip)->depth>0.f))
ret++;
}
else
{
CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*(A2>0 ? hlz*R[1]:-hlz*R[1]);
CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*(A2>0 ? hlz*R[5]:-hlz*R[5]);
CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*(A2>0 ? hlz*R[9]:-hlz*R[9]);
CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q2*2.f*A2);
if ((ret < maxret - 1) && // <<<< MODIFIED
(CONTACT(contact,ret*skip)->depth>0.f))
ret++;
}
}
for (unsigned int i=0; i<ret; i++) {
CONTACT(contact,i*skip)->g1 = const_cast<dxGeom*> (o1);
CONTACT(contact,i*skip)->g2 = const_cast<dxGeom*> (o2);
CONTACT(contact,i*skip)->normal[0] =n[0];
CONTACT(contact,i*skip)->normal[1] =n[1];
CONTACT(contact,i*skip)->normal[2] =n[2];
}
return ret;
}
--------------080506090508010404050707--