home *** CD-ROM | disk | FTP | other *** search
- /*
- * lights.c -- standard routines for lights
- *
- * (c) by Han-Wen Nienhuys, 1993 <hanwen@stack.urc.tue.nl>
- *
- * 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.
- */
-
- #include <math.h>
- #include <stdio.h>
- #include "ray.h"
- #include "proto.h"
- #include "extern.h"
-
- extern struct methods my_methods;
-
- PRIVATE void add_light(object *l);
-
- PRIVATE bool
- all_light_intersections(dqueue * q, object *o, struct ray *r, int flags, bool *isinside)
- {
- return FALSE;
- }
-
- PUBLIC void
- make_light_list(object *o)
- {
-
- for (; o != NULL; o = o->next)
- switch (o->type) {
- case LIGHTSOURCE:
- add_light(o);
- break;
- case COMPOSITE:
- make_light_list(o->data.composite->contents);
- break;
- }
- }
-
- PRIVATE vector
- light_normal(struct intersect i, vector loc)
- {
- assert(FALSE);
- }
-
- PRIVATE bool
- inside_light(object *o, vector i)
- {
- assert(FALSE);
- }
-
- PRIVATE void
- init_light(struct light_data *p)
- {
- int i;
-
- setvector(p->org, 0, 0, 0);
-
- setvector(p->direction, 0, 0, 0);
- p->tightness = 1.0;
- p->spotlight = FALSE;
- p->lcolor.r = p->lcolor.g = p->lcolor.b = 1.0;
- p->attenuation_exp = 0.0;
- p->radius = 0.0;
-
-
- for (i = 0; i < MAXCACHE; i++)
- p->scache[i] = NULL;
- }
-
- PRIVATE struct light_data *
- get_new_light(void)
- {
- struct light_data *p;
-
- p = ALLOC(struct light_data);
-
- CHECK_MEM(p, my_methods.name);
- init_light(p);
-
- return p;
- }
-
- PRIVATE void
- scale_light(object *o, vector s)
- {
- struct light_data *l = o->data.light;
- vector inv;
-
- vcproduct(l->org, l->org, s);
- inv.x = 1 / s.x;
- inv.y = 1 / s.y;
- inv.z = 1 / s.z;
- vcproduct(l->direction, l->direction, inv);
- }
-
- PRIVATE void
- rotate_light(object *o, matrix rotmat)
- {
- struct light_data *l = o->data.light;
-
- rotate_vector(&l->org, rotmat);
- rotate_vector(&l->direction, rotmat);
- }
-
- PRIVATE void
- translate_light(object *o, vector t)
- {
- struct light_data *l = o->data.light;
-
- vadd(l->org, l->org, t);
- }
-
- PRIVATE void
- copy_light(object *dst, object *src)
- {
- assert(dst != NULL && src != NULL);
-
- if (dst->type != LIGHTSOURCE)
- dst->data.light = get_new_light();
- *dst->data.light = *src->data.light;
- dst->type = src->type;
- }
-
- PRIVATE void
- free_light(object *s)
- {
- free((void *) s->data.light);
- s->type = NOSHAPE;
- }
-
- PRIVATE void
- print_light(object *o)
- {
- #ifdef DEBUG
- struct light_data *l = o->data.light;
-
- if (l->spotlight)
- printf("\tSPOTLIGHT\n");
-
- print_v("origin", l->org);
- print_c("color", l->lcolor);
- printf("attenuation %lf, radius %lf\n",
- l->attenuation_exp, l->radius);
-
- if (l->spotlight) {
- printf("tightness %lf ", l->tightness);
- print_v("direction", l->direction);
- }
- #endif
- }
-
- PUBLIC void
- print_light_list(void)
- {
- object *p;
-
- for (p = first_light; p != NULL; p = p->next)
- print_light(p);
- }
-
- PRIVATE void
- precompute_light(object *o)
- {
- my_methods.howmuch++;
- global_stats.prims++;
- }
-
- PRIVATE struct methods my_methods =
- {
- all_light_intersections,
- light_normal,
- copy_light,
- inside_light,
- rotate_light,
- translate_light,
- scale_light,
- free_light,
- print_light,
- precompute_light,
- "lightsource"
- /* hit and test are variables relating to the shadowray tests. */
- };
-
- PUBLIC object *
- get_new_light_object(void)
- {
- object *o;
-
- o = get_new_object();
-
- o->data.light = get_new_light();
- o->methods = &my_methods;
- o->type = LIGHTSOURCE;
-
- return o;
- }
-
- /* uhoh! */
- PRIVATE void
- add_light(object *l)
- {
- object *p;
-
- p = first_light;
- first_light = get_new_object();
- first_light->type = LIGHTSOURCE;
- first_light->methods = &my_methods;
- first_light->next = p;
- first_light->data.light = l->data.light; /* don't copy light,
- * pointer to it is enough */
- }
-
- PUBLIC color
- light_color(struct light_data *l, vector a)
- {
- vector d;
- double intensity,
- dot;
-
- if (l->spotlight) {
- vsub(d, a, l->org);
- norm(d, d);
-
- dot = vdot(d, l->direction);
- if (dot < 0) /* this can happen, if the lighted point
- * is not in the direction of the
- * spotlight */
- dot = 0;
-
- intensity = pow(dot, l->tightness);
- return scolorproduct(intensity, l->lcolor);
- } else
- return l->lcolor;
- }
-