home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * (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;
- }
-
-