home *** CD-ROM | disk | FTP | other *** search
- /*
- * intersect.c -- main intersection routines
- *
- * (c) 1993, 1994 by Han-Wen Nienhuys <hanwen@stack.urc.tue.nl>
- *
- * This file is based on work by George Kyriazis (1988).
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*
- * snelheids winst: bijhouden of een stilstaand object al getraced is.
- */
-
- #include <math.h>
- #include "ray.h"
- #include "proto.h"
- #include "extern.h"
-
- /*
- * Shadow check. Check if the ray from the intersection point to the
- * light, intersection any objects inbetween. If it does, we have a
- * shadow. One improvement that can be made is to check the transparencies
- * of all the intersecting objects and make the shadow have a different
- * intensity depending on the transparency of the objects
- */
-
- PUBLIC bool
- shadow_test(struct ray r, double ldistance, object *light_object, int recursion)
- {
- dqueue *q;
- object *op;
- bool hit;
- struct light_data *light = light_object->data.light;
-
-
- r.maxt = INFTY;
- r.mint = ldistance;
-
-
- /* intersect everything in scene */
- q = get_new_queue();
- light_object->methods->test++;
-
- /* do caching ? */
- if (recursion < MAXCACHE && light->scache[recursion] != NULL) {
- object *last;
-
- global_stats.cachetest++;
-
- /* avoid intersecting CSG parts; stop if we find a composite */
- for (op = light->scache[recursion]; op->type != COMPOSITE; op = op->daddy)
- last = op;
-
- if (intersect_object(q, last, &r, FALSE) && q->t < ldistance) {
- free_queue(q);
- light_object->methods->hit++;
- global_stats.cachehit++;
- return TRUE;
- } else {
- global_stats.cachemiss++;
- light->scache[recursion] = NULL;
- }
- }
- global_stats.shadowtest++;
- line_stats.raytest++;
-
- /* check whole scene */
- if (intersect_object(q, thescene, &r, FALSE)) {
-
- /* found intersection */
- line_stats.rayintersections++;
-
- if (q->t >= ldistance) {/* there is nothing blocking the object */
-
- if (recursion < MAXCACHE) /* should we cache it? */
- light->scache[recursion] = NULL;
-
- hit = FALSE;
- } else {
-
- light_object->methods->hit++;
- if (recursion < MAXCACHE)
- light->scache[recursion] = q->obj;
-
- hit = TRUE;
- }
- } else {
- hit = FALSE; /* no intersections found */
-
- /* clear cache */
- if (recursion < MAXCACHE)
- light->scache[recursion] = NULL;
- }
- free_queue(q);
-
- return hit;
- }
-
-
- /*
- * intersect(): intersect everything in the whole scene, and then fill in
- * the intersection details.
- */
- PUBLIC struct intersect
- intersect(struct ray r)
- {
- struct intersect i;
- struct ray transray;
- object *op;
- dqueue *q;
- vector moved;
-
- line_stats.raytest++;
- switch (r.type) {
- case R_EYE:
- line_stats.eyerays++;
- break;
- case R_REFLECT:
- line_stats.reflected++;
- break;
- case R_REFRACT:
- line_stats.refracted++;
- break;
- default:
- assert(FALSE);
- }
-
-
- /* intersect everything in scene */
- r.maxt = INFTY;
- r.mint = 0;
-
- q = get_new_queue();
- intersect_object(q, thescene, &r, FALSE);
- i.q_ent = *q;
- free_queue(q);
-
- op = i.q_ent.obj;
-
- if (op == NULL)
- return i; /* nothing was found */
-
- line_stats.rayintersections++;
- setvector(moved, 0.0, 0.0, 0.0);
-
-
- /* What was the translated ray? */
- svproduct(moved, -Time, op->speed);
- vadd(transray.pos, r.pos, moved);
-
-
- /*
- * translation doesn't affect direction, so just copy the dir vector
- */
- transray.dir = r.dir;
-
- /*
- * determine the intersection point.
- *
- * i.x = t*transray.dir + transray.pos + obj->speed * Time = t*r.dir +
- * r.pos - speed*Time + speed*Time = t*r.dir + r.pos
- */
-
- svproduct(i.x, i.q_ent.t, r.dir);
- vadd(i.x, i.x, r.pos);
- vadd(i.objectx, i.x, moved);
-
- /*
- * determine normal at intersection point
- */
-
-
- i.n = i.objectn = i.q_ent.obj->methods->normal_method(i, i.objectx);
-
- if (i.q_ent.obj->inverted)
- vneg(i.n, i.n);
-
- return i;
- }
-