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.