/* Sample implementation of the line segment—triangle intersection test
* presented in the paper:
*
* Fast 3D Line Segment—Triangle Intersection Test
* Nick Chirkov
* journal of graphics tools 10(3):13-18, 2005
*
*/
struct RAYTRI
{
double org[3];
double end[3];
double dir[3];
double v0[3],v1[3],v2[3];
struct PLANE
{
double x, y, z, d;
enum MAIN_AXIS { X, Y, Z };
MAIN_AXIS type;
};
PLANE plane;
};
int c2005(const RAYTRI* rt)
{
double signSrc = rt->plane.x*rt->org[0] + rt->plane.y*rt->org[1] + rt->plane.z*rt->org[2] - rt->plane.d;
double signDst = rt->plane.x*rt->end[0] + rt->plane.y*rt->end[1] + rt->plane.z*rt->end[2] - rt->plane.d;
if(signSrc*signDst > 0.0) return 0;
double d = signSrc - signDst;
if(rt->plane.type==RAYTRI::PLANE::X)
{
double e0y = rt->v1[1] - rt->v0[1];
double e0z = rt->v1[2] - rt->v0[2];
double e1y = rt->v2[1] - rt->v0[1];
double e1z = rt->v2[2] - rt->v0[2];
double basey = rt->org[1] - rt->v0[1];
double basez = rt->org[2] - rt->v0[2];
double adelx = signSrc*(e0y * rt->dir[2] - e0z * rt->dir[1]);
if( (adelx + d*(e0y*basez - e0z*basey)) * ( signSrc*(rt->dir[1]*e1z - rt->dir[2]*e1y) + d*(basey*e1z - basez*e1y)) > 0.0)
{
double e2y = rt->v1[1] - rt->v2[1];
double e2z = rt->v1[2] - rt->v2[2];
basey = rt->org[1] - rt->v1[1];
basez = rt->org[2] - rt->v1[2];
if( (adelx + d*(e0y*basez - e0z*basey)) * ( signSrc*(rt->dir[1]*e2z - rt->dir[2]*e2y) + d*(basey*e2z - basez*e2y)) > 0.0) return 1;
}
}
else
if(rt->plane.type==RAYTRI::PLANE::Y)
{
double e0x = rt->v1[0] - rt->v0[0];
double e0z = rt->v1[2] - rt->v0[2];
double e1x = rt->v2[0] - rt->v0[0];
double e1z = rt->v2[2] - rt->v0[2];
double basex = rt->org[0] - rt->v0[0];
double basez = rt->org[2] - rt->v0[2];
double adely = signSrc*(e0z * rt->dir[0] - e0x * rt->dir[2]);
if( (adely + d*(e0z*basex - e0x*basez)) * ( signSrc*(rt->dir[2]*e1x - rt->dir[0]*e1z) + d*(basez*e1x - basex*e1z)) > 0.0)
{
double e2x = rt->v1[0] - rt->v2[0];
double e2z = rt->v1[2] - rt->v2[2];
basex = rt->org[0] - rt->v1[0];
basez = rt->org[2] - rt->v1[2];
if( (adely + d*(e0z*basex - e0x*basez)) * ( signSrc*(rt->dir[2]*e2x - rt->dir[0]*e2z) + d*(basez*e2x - basex*e2z)) > 0.0) return 1;
}
}
else
{
double e0x = rt->v1[0] - rt->v0[0];
double e0y = rt->v1[1] - rt->v0[1];
double e1x = rt->v2[0] - rt->v0[0];
double e1y = rt->v2[1] - rt->v0[1];
double basex = rt->org[0] - rt->v0[0];
double basey = rt->org[1] - rt->v0[1];
double adelz = signSrc*(e0x * rt->dir[1] - e0y * rt->dir[0]);
if( (adelz + d*(e0x*basey - e0y*basex)) * ( signSrc*(rt->dir[0]*e1y - rt->dir[1]*e1x) + d*(basex*e1y - basey*e1x)) > 0.0)
{
double e2x = rt->v1[0] - rt->v2[0];
double e2y = rt->v1[1] - rt->v2[1];
basex = rt->org[0] - rt->v1[0];
basey = rt->org[1] - rt->v1[1];
if( (adelz + d*(e0x*basey - e0y*basex)) * ( signSrc*(rt->dir[0]*e2y - rt->dir[1]*e2x) + d*(basex*e2y - basey*e2x)) > 0.0) return 1;
}
}
return 0;
}