This is intersect.c in view mode; [Download] [Up]
/*
* (c) 1988 by George Kyriazis
*/
/*
* Intersection routines
*/
#include "vector.h"
#include "ray.h"
#include <math.h>
/*
* Intersect ray with sphere
*/
struct intersect sphere(obj, r)
struct obj *obj;
struct ray r;
{
struct vector v;
struct vector n; /* normal vector */
struct intersect i;
double b, c, d;
double sol1, sol2;
struct vector center;
i.obj = NULL;
/* find out what the center is at this time */
center = svproduct( Time, obj->time );
center = vadd( obj->data.sphere.center, center );
v = vsub( r.pos, center );
b = 2 * vdot( r.dir, v );
c = vdot(v, v) - obj->data.sphere.radius;
d = b * b - 4 * c;
if( d < 0 )
return i;
d = sqrt(d);
sol1 = ( -b + d ) / 2;
sol2 = ( -b - d ) / 2;
if( sol1 <= 0 )
sol1 = sol2;
if( sol2 <= 0 )
sol2 = sol1;
i.t = (sol1 < sol2) ? sol1 : sol2 ;
/* if intersection is behind eye */
if(i.t <= 0)
return i;
i.obj = obj;
/* calculate the normal. It is just the direction of the radius */
n = vsub(vadd(r.pos, svproduct(i.t, r.dir)), center);
i.n = norm(n);
return i;
}
/*
* intersect ray with a quadrangle
*/
struct intersect quad(obj, r)
struct obj *obj;
struct ray r;
{
struct intersect i;
double x0, y0, z0;
double dx1, dy1, dz1, dx2, dy2, dz2, qx, qy, qz;
double alpha, a, b, t;
double d, dalpha, da, db;
struct vector n;
double pdx, pdy, pdz;
double size;
i.obj = NULL;
x0 = obj->data.quad.p1.x;
y0 = obj->data.quad.p1.y;
z0 = obj->data.quad.p1.z;
dx1 = x0 - obj->data.quad.p2.x;
dy1 = y0 - obj->data.quad.p2.y;
dz1 = z0 - obj->data.quad.p2.z;
dx2 = x0 - obj->data.quad.p3.x;
dy2 = y0 - obj->data.quad.p3.y;
dz2 = z0 - obj->data.quad.p3.z;
qx = r.dir.x;
qy = r.dir.y;
qz = r.dir.z;
d = qx * ( ( dy1 * dz2 ) - ( dy2 * dz1 ) )
- dx1 * ( ( qy * dz2 ) - ( qz * dy2 ) )
+ dx2 * ( ( qy * dz1 ) - ( qz * dy1 ) ) ;
/* if no intersection */
if( ABS(d) < MINT )
return i;
/* use the right time */
pdx = x0 - r.pos.x + Time * obj->time.x;
pdy = y0 - r.pos.y + Time * obj->time.y;
pdz = z0 - r.pos.z + Time * obj->time.z;
dalpha = pdx * ( ( dy1 * dz2 ) - ( dz1 * dy2 ) )
- dx1 * ( ( pdy * dz2 ) - ( pdz * dy2 ) )
+ dx2 * ( ( pdy * dz1 ) - ( pdz * dy1 ) ) ;
alpha = dalpha / d;
/* if intersection behind the eye */
if( alpha <= 0 )
return i;
da = qx * ( ( pdy * dz2 ) - ( pdz * dy2 ) )
- pdx * ( ( qy * dz2 ) - ( qz * dy2 ) )
+ dx2 * ( ( qy * pdz ) - ( qz * pdy ) ) ;
db = qx * ( ( dy1 * pdz ) - ( dz1 * pdy ) )
- dx1 * ( ( qy * pdz ) - ( qz * pdy ) )
+ pdx * ( ( qy * dz1 ) - ( qz * dy1 ) );
a = da / d;
b = db / d;
/* check if intersection within quad */
if( ( a < 0 ) || ( a > 1 ) )
return i;
if( ( b < 0 ) || ( b > 1 ) )
return i;
/* assign the object */
i.obj = obj;
i.t = alpha;
/* normal to the plane */
n.x = dy1 * dz2 - dy2 * dz1;
n.y = - ( dx1 * dz2 - dx2 * dz1 );
n.z = dx1 * dy2 - dx2 * dy1;
i.n = norm(n);
/* reverse the normal if desired */
if( vdot( i.n, r.dir ) > 0 )
i.n = vneg( i.n );
return i;
}
struct intersect intersect(r)
struct ray r;
{
int i;
struct intersect inter, intermin;
intermin.obj = NULL;
for(i = 0; i < noo; i++) {
objtestline++;
/* choose the appropriate routine for each object */
switch( obj[i].type ) {
case SPHERE:
inter = sphere( &obj[i], r);
break;
case SQUARE:
inter = quad( &obj[i], r);
break;
default:
inter.obj = NULL;
break;
}
/* update the minimum intersection distance if the new intersection */
/* exists (ray intersects the object), and the intersection distance */
/* is smaller that the one logged and also the object intersected is */
/* not the object that the ray is originating from. */
if( inter.obj &&
( !intermin.obj ||
(inter.t < intermin.t) ) &&
( inter.obj != r.obj ) )
intermin = inter;
}
return intermin;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.