Ha I fix it Delfi.
This bug was indtruduce when we were working on the convex optimization,
if you remember we made a modification to teh collsion tree buildes so that allow more strict faces to be consided convex.
when I did that the tolerance I was using for raycasting convex faces was rendered too big,
and the caster was considering a hit if a line hit a polygon close to an edge but outside the polygon.
now the faces are more correct an the tolernace became too large.
ideally it should be zero, but that will fail in faces sharing the same edge, I made the adjustment and now it is fine.
I will make a new buils and post it tonight, I have to go out now.
here is the ray cast function tha newton uses.
- Code: Select all
dgFloat32 RayTest::PolygonIntersect (const dgVector& normal, const dgFloat32* const polygon, dgInt32 strideInBytes, const dgInt32* const indexArray, dgInt32 indexCount) const
{
_ASSERTE (m_p0.m_w == m_p1.m_w);
dgFloat32 dist = normal % m_diff;
if (dist < m_dirError) {
dgInt32 stride = strideInBytes / sizeof (dgFloat32);
dgVector v0 (&polygon[indexArray[indexCount - 1] * stride]);
dgVector p0v0 (v0 - m_p0);
dgFloat32 tOut = normal % p0v0;
// this only work for convex polygons and for single side faces
// walk the polygon around the edges and calculate the volume
if ((tOut < dgFloat32 (0.0f)) && (tOut > dist)) {
for (dgInt32 i = 0; i < indexCount; i ++) {
dgInt32 i2 = indexArray[i] * stride;
dgVector v1 (&polygon[i2]);
dgVector p0v1 (v1 - m_p0);
// calculate the volume formed by the line and the edge of the polygon
dgFloat32 alpha = (m_diff * p0v1) % p0v0;
// if a least one volume is negative it means the line crosses the polygon outside this edge and do not hit the face
if (alpha < DG_RAY_TOL_ERROR) {
return dgFloat32 (1.2f);
}
p0v0 = p0v1;
}
//the line is to the left of all the polygon edges,
//then the intersetion is the the point we the line interset the plane of the polygon
tOut = tOut / dist;
_ASSERTE (tOut >= dgFloat32 (0.0f));
_ASSERTE (tOut <= dgFloat32 (1.0f));
return tOut;
}
}
return dgFloat32 (1.2f);
}
DG_RAY_TOL_ERROR ws 0.01, now it is 0.001 and that seems to work fine now.
BTW the function is perhaps the fastest and most robust ray/polygon interceion you can fine anywhere,
in fact the optimized version in SSE is about 32 instructions in the inner loop but it does 4 edges per iteration for an average of 8 intructions per edge of a face.
the limitation is that it only works for convex single sided polygons.
This the reason why in Newton all collisions only works on single sided faces, it is because most function are like that.
as you can see, if the polygon was allowed to be double sided then the sign of the triple scalar product
dgFloat32 alpha = (m_diff * p0v1) % p0v0;
will have not meaning