home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* raycone.c */
- /* */
- /* Cone / ray intersection routine. *
- /* Modified from Optik v(1.2e) (C) 1987 John Amanatides & Andrew Woo */
- /* */
- /* Copyright (C) 1992, Bernard Kwok */
- /* All rights reserved. */
- /* Revision 1.0 */
- /* May, 1992 */
- /**********************************************************************/
- #include <stdio.h>
- #include <math.h>
- #include "geo.h"
- #include "struct.h"
- #include "ray.h"
- #include "misc.h"
- #include "io.h"
-
- extern RayStats_Type RayStats;
- extern OptionType Option;
-
- /**********************************************************************/
- /* Ray trace cone intersection */
- /* ray : ray to check */
- /* hit : intersection (if any) */
- /* node : node to intersect with */
- /**********************************************************************/
- void RayCone(ray, hit, node)
- register Ray *ray;
- register HitData *hit;
- register Objectt *node;
- {
- double a,b,c,r1,r2,t,discrim,x,y,z;
- Vector v1, v2;
-
- RayStats.rayCone++;
- if(Option.debug)
- printf("\t\tRay-Cone: (%g,%g,%g) -> (%g,%g,%g)\n",
- ray->origin.x, ray->origin.y, ray->origin.z,
- ray->dir.x, ray->dir.y, ray->dir.z);
-
- /* Find a,b,c of at**2 +bt +c. a = x^2 + y^2,
- * b = 2(x0x + y0y), and c = (x0^2 + y0^2 -1
- */
- a = ray->dir.x*ray->dir.x + ray->dir.y*ray->dir.y -ray->dir.z*ray->dir.z;
- b = 2.0*(ray->origin.x*ray->dir.x + ray->origin.y*ray->dir.y +
- ray->dir.z - ray->origin.z*ray->dir.z);
- c = ray->origin.x*ray->origin.x + ray->origin.y*ray->origin.y -1.0 +
- 2.0*ray->origin.z - ray->origin.z*ray->origin.z;
-
- /* Calculate discriminant */
- discrim= b*b -4.*a*c;
- if(discrim > 0.) {
- /* find closest intersection (also watch for stability) */
- if(b < 0.0) {
- r2= (-b + sqrt(discrim)) / (2.0 * a);
- r1= c/(a*r2);
- } else {
- r1= (-b - sqrt(discrim)) / (2.0 * a);
- r2= c/(a*r1);
- }
- if(r1 <= MIN_DISTANCE) /* for round-off errors */
- t= r2;
- else t= r1;
-
- if( t > MIN_DISTANCE && t < hit->distance) {
- z= ray->origin.z + t*ray->dir.z;
- if (z > 0.0 && z < 1.0) {
-
- /* Store hit information */
- RayStats.intCone++;
- if (Option.visibility == FORM_FACTOR)
- ray->visible = 0.0;
- Store_HitInter(hit, node, (ray->origin.x + t*ray->dir.x),
- (ray->origin.y + t*ray->dir.y), z);
- if(!ray->shadow) {
- v1.x = -hit->intersect.y;
- v1.y = hit->intersect.x;
- v1.z= 0.0;
- v2.x = -hit->intersect.x;
- v2.y = -hit->intersect.y;
- v2.z= 1.0 - z;
- hit->normal = cross(v1, v2);
- hit->texture = hit->intersect;
- }
- }
- }
- }
-
-
- /* Check the disk part of the cone */
- if (Option.visibility == FORM_FACTOR)
- if (ray->visible == 0.0)
- return;
- if(ray->dir.z < -DAMN_SMALL || ray->dir.z > DAMN_SMALL) {
- t= -ray->origin.z / ray->dir.z;
- if(t > MIN_DISTANCE && t < hit->distance) {
- x= ray->origin.x + t*ray->dir.x;
- y= ray->origin.y + t*ray->dir.y;
-
- /* Store hit information */
- if(x*x + y*y < 1.0) {
- RayStats.intCone++;
- if (Option.visibility == FORM_FACTOR)
- ray->visible = 0.0;
- Store_HitInter(hit, node, t, x, y, 0.0);
- if(!ray->shadow) {
- Store_HitNorm(hit, 0.0, 0.0, -1.0);
- hit->texture= hit->intersect;
- }
- }
- }
- }
- }
-