Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
194 lines (165 sloc) 6.05 KB
/*
* ANSI C code from the article
* "Intersecting a Ray with a Cylinder"
* by Joseph M. Cychosz and Warren N. Waggenspack, Jr.,
* (3ksnn64@ecn.purdue.edu, mewagg@mewnw.dnet.lsu.edu)
* in "Graphics Gems IV", Academic Press, 1994
*/
#include "GraphicsGems.h"
#include <math.h>
#include <float.h>
/* ---- intcyl - Intersect a ray with a cylinder. --------------------- */
/* */
/* */
/* Description: */
/* Intcyl determines the intersection of a ray with a */
/* cylinder. */
/* */
/* On entry: */
/* raybase = The base point of the intersecting ray. */
/* raycos = The direction cosines of the above ray. (unit) */
/* base = The base location of the cylinder. */
/* axis = The axis of symmetry for the cylinder. (unit) */
/* radius = The radius of the cylinder. */
/* */
/* On return: */
/* in = The entering distance of the intersection. */
/* out = The leaving distance of the intersection. */
/* */
/* Returns: True if the ray intersects the cylinder. */
/* */
/* Note: In and/or out may be negative indicating the */
/* cylinder is located behind the origin of the ray. */
/* */
/* -------------------------------------------------------------------- */
boolean intcyl (raybase,raycos,base,axis,radius,in,out)
Point3 *raybase; /* Base of the intersection ray */
Vector3 *raycos; /* Direction cosines of the ray */
Point3 *base; /* Base of the cylinder */
Vector3 *axis; /* Axis of the cylinder */
double radius; /* Radius of the cylinder */
double *in; /* Entering distance */
double *out; /* Leaving distance */
{
boolean hit; /* True if ray intersects cyl */
Vector3 RC; /* Ray base to cylinder base */
double d; /* Shortest distance between */
/* the ray and the cylinder */
double t, s; /* Distances along the ray */
Vector3 n, D, O;
double ln;
#ifndef HUGE
#define HUGE FLT_MAX
#endif
const double pinf = HUGE; /* Positive infinity */
RC.x = raybase->x - base->x;
RC.y = raybase->y - base->y;
RC.z = raybase->z - base->z;
V3Cross (raycos,axis,&n);
if ( (ln = V3Length (&n)) == 0. ) { /* ray parallel to cyl */
d = V3Dot (&RC,axis);
D.x = RC.x - d*axis->x;
D.y = RC.y - d*axis->y;
D.z = RC.z - d*axis->z;
d = V3Length (&D);
*in = -pinf;
*out = pinf;
return (d <= radius); /* true if ray is in cyl*/
}
V3Normalize (&n);
d = fabs (V3Dot (&RC,&n)); /* shortest distance */
hit = (d <= radius);
if (hit) { /* if ray hits cylinder */
V3Cross (&RC,axis,&O);
t = - V3Dot (&O,&n) / ln;
V3Cross (&n,axis,&O);
V3Normalize (&O);
s = fabs (sqrt(radius*radius - d*d) / V3Dot (raycos,&O));
*in = t - s; /* entering distance */
*out = t + s; /* exiting distance */
}
return (hit);
}
/* ---- clipobj - Clip object with plane pair. ------------------------ */
/* */
/* */
/* Description: */
/* Clipobj clips the supplied infinite object with two */
/* (a top and a bottom) bounding planes. */
/* */
/* On entry: */
/* raybase = The base point of the intersecting ray. */
/* raycos = The direction cosines of the above ray. (unit) */
/* bot = The normal and perpendicular distance of the */
/* bottom plane. */
/* top = The normal and perpendicular distance of the */
/* top plane. */
/* objin = The entering distance of the intersection with */
/* the object. */
/* objout = The exiting distance of the intersection with */
/* the object. */
/* */
/* On return: */
/* objin = The entering distance of the intersection. */
/* objout = The exiting distance of the intersection. */
/* surfin = The identifier for the entering surface. */
/* surfout = The identifier for the leaving surface. */
/* */
/* Returns: True if the ray intersects the bounded object. */
/* */
/* -------------------------------------------------------------------- */
#define SIDE 0 /* Object surface */
#define BOT 1 /* Bottom end-cap surface */
#define TOP 2 /* Top end-cap surface */
typedef struct { /* Plane: ax + by + cz + d = 0 */
double a ,b ,c, d;
} Plane;
boolean clipobj (raybase,raycos,bot,top,objin,objout,surfin,surfout)
Point3 *raybase; /* Base of the intersection ray */
Vector3 *raycos; /* Direction cosines of the ray */
Plane *bot; /* Bottom end-cap plane */
Plane *top; /* Top end-cap plane */
double *objin; /* Entering distance */
double *objout; /* Exiting distance */
int *surfin; /* Entering surface identifier */
int *surfout; /* Exiting surface identifier */
{
double dc, dw, t;
double in, out; /* Object intersection dists. */
*surfin = *surfout = SIDE;
in = *objin;
out = *objout;
/* Intersect the ray with the bottom end-cap plane. */
dc = bot->a*raycos->x + bot->b*raycos->y + bot->c*raycos->z;
dw = bot->a*raybase->x + bot->b*raybase->y + bot->c*raybase->z + bot->d;
if ( dc == 0.0 ) { /* If parallel to bottom plane */
if ( dw >= 0. ) return (FALSE);
} else {
t = - dw / dc;
if ( dc >= 0.0 ) { /* If far plane */
if ( t > in && t < out ) { out = t; *surfout = BOT; }
if ( t < in ) return (FALSE);
} else { /* If near plane */
if ( t > in && t < out ) { in = t; *surfin = BOT; }
if ( t > out ) return (FALSE);
}
}
/* Intersect the ray with the top end-cap plane. */
dc = top->a*raycos->x + top->b*raycos->y + top->c*raycos->z;
dw = top->a*raybase->x + top->b*raybase->y + top->c*raybase->z + top->d;
if ( dc == 0.0 ) { /* If parallel to top plane */
if ( dw >= 0. ) return (FALSE);
} else {
t = - dw / dc;
if ( dc >= 0.0 ) { /* If far plane */
if ( t > in && t < out ) { out = t; *surfout = TOP; }
if ( t < in ) return (FALSE);
} else { /* If near plane */
if ( t > in && t < out ) { in = t; *surfin = TOP; }
if ( t > out ) return (FALSE);
}
}
*objin = in;
*objout = out;
return (in < out);
}