home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * Copyright (c) 1988, David B. Wecker *
- * All Rights Reserved *
- * *
- * This file is part of DBW_uRAY *
- * *
- * DBW_uRAY is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY. No author or distributor accepts *
- * responsibility to anyone for the consequences of using it or for *
- * whether it serves any particular purpose or works at all, unless *
- * he says so in writing. Refer to the DBW_uRAY General Public *
- * License for full details. *
- * *
- * Everyone is granted permission to copy, modify and redistribute *
- * DBW_uRAY, but only under the conditions described in the *
- * DBW_uRAY General Public License. A copy of this license is *
- * supposed to have been given to you along with DBW_uRAY so you *
- * can know your rights and responsibilities. It should be in a file *
- * named COPYING. Among other things, the copyright notice and this *
- * notice must be preserved on all copies. *
- ************************************************************************
- * *
- * Authors: *
- * DBW - David B. Wecker *
- * *
- * Versions: *
- * V1.0 881023 DBW - First released version *
- * V1.1 881110 DBW - Fixed scan coherence code *
- * V1.2 881125 DBW - Removed ALL scan coherence code (useless) *
- * added "fat" extent boxes *
- * *
- ************************************************************************/
-
- #include "uray.h"
-
- /************************************************************************/
- /********************* All ray tracing is in this module ****************/
- /************************************************************************/
-
-
- /* See if object s has 1 or more lights shining on it */
- void getlights(s,intersect,normal,diffuse,newdir,color)
- NODE *s;
- VEC intersect,normal,diffuse,newdir,color;
- {
- register NODE *l;
- register FLTDBL dist, eta, eta2;
- VEC lint,ldir,v1;
- int i;
- LIGHT *lp;
- FLTDBL tmin;
-
- /* Look at each light */
- for (lp=lights; lp; lp = lp->next) {
-
- /* get the dir,distance to the light */
- l = lp->child;
- vcomb(-1.0,intersect,l->cen,ldir);
- dist = vdot(ldir,ldir);
- vscale(1.0/sqrt(dist),ldir,ldir);
-
- /* if not a point source, compute new light intensity */
- if (l->att->dist > 0.0) {
-
- /* get the distance to the light */
- if (dist == 0.0) dist = 0.0001;
-
- /* use inverse square law to factor intensity */
- vscale(l->att->dist / dist,l->att->color,lint);
- }
- else vcopy(l->att->color,lint);
-
- /* see if there are any reflections to do */
- eta = eta2 = 0.0;
- if (s->att->kd > 0.0) eta = vdot(normal,ldir);
- if (s->att->ks > 0.0) eta2 = vdot(ldir,newdir);
- if (eta > 0.00 || eta2 > 0.00)
- if (intersection(intersect, ldir, &tmin) != l)
- eta = eta2 = 0.0;
-
- /* do diffuse reflections */
- if (eta > 0.00) {
- vmul(lint,diffuse,v1);
- eta *= s->att->kd*l->att->kl;
- vcomb(eta,v1,color,color);
- }
-
- /* do specular reflections */
- if (eta2 > 0.00) {
- if (s->att->kf == 0.0) eta = 1000.0;
- else {
- eta = 2.0/s->att->kf;
- if (eta < 1.0) eta = 1.0;
- }
- eta2 = pow(eta2,eta);
- eta2 *= s->att->ks*l->att->kl;
- if (eta2 > TOL) {
- vcomb(eta2,lint,color,color);
- }
- }
- }
- }
-
- /* Do any specular reflections off of object s */
- void getspecular(level,atten,s,d,normal,intersect,dir,newdir,color)
- NODE *s;
- FLTDBL d,atten;
- VEC normal,intersect,dir,newdir,color;
- {
- FLTDBL eta;
- VEC newcolor;
-
- /* and see where it goes */
- trace(level,atten,intersect,newdir,newcolor);
-
- /* scale by specular factor */
- vscale(s->att->ks,newcolor,newcolor);
-
- /* Add sparkle */
- eta = vdot(normal,newdir);
- if (eta >= 0.0) {
- eta = 1.0 - eta;
- eta = eta * eta * eta * eta * eta;
- vcomb(eta,newcolor,newcolor,newcolor);
- }
- vcomb(1.0,newcolor,color,color);
- }
-
- /* If object is transparent, compute what's on the other side */
- void gettrans(level,atten,s,eflip,d,normal,intersect,dir,color)
- NODE *s;
- FLTDBL d,atten;
- VEC normal,intersect,dir,color;
- {
- FLTDBL eta;
- VEC v1;
-
- /* get the correct index of refrection */
- if (eflip) eta = 1.0 / s->att->ir;
- else eta = s->att->ir;
-
- /* compute the angle of the new ray */
- vcomb(d,normal,dir,v1);
- vscale(eta,v1,v1);
- eta = vdot(v1,v1);
-
- /* make sure that we aren't past critical angle */
- if (eta < 1.0) {
-
- /* get the vector through the surface */
- vcomb(-sqrt(1.0-eta),normal,v1,v1);
-
- /* see who's visable */
- trace(level,atten,intersect,v1,v1);
-
- /* add it to the return color */
- vcomb(s->att->kt, v1, color, color);
- }
- }
-
- /* main raytrace routine */
- void trace(level, atten, frm, dir, retval)
- VEC frm, dir, retval;
- FLTDBL atten;
- {
- register NODE *s;
- register FLTDBL d, eta;
- register FLTDBL latten;
- VEC normal, color, diffuse, v1, v2, intersect, newdir;
- int eflip;
- FLTDBL tmin;
-
- /* have we recursed too far? */
- if (++level == depth) {
- vcopy(BLACK,retval);
- return;
- }
-
- /* If we don't hit anything then return background */
- if (!(s = intersection(frm, dir, &tmin))) {
- getamb(frm,dir,retval);
- return;
- }
-
- /* get the intersection point */
- vcomb(tmin, dir, frm, intersect);
-
- /* compute the surface normal */
- d = findnormal(s,dir,intersect,normal,&eflip);
-
- /* get a base diffuse level (if necessary) */
- if (s->att->kl > 0.0 || s->att->kd > 0.0) {
-
- /* get base color (procedural texture) of the object */
- gettex(s,intersect,normal,diffuse);
-
- /* if we're a light, then use the light amount else the base amount */
- if (s->att->kl > 0.0) {
- vscale(s->att->kl,diffuse,color);
- }
- else {
- vscale(base,diffuse,color);
- }
- }
-
- /* otherwise start out with no color */
- else {
- vcopy(BLACK,color);
- }
-
- /* bounce the ray off the surface for specular/mirror reflection */
- if (s->att->ks > 0.0 || s->att->kd > 0.0) {
- vcomb(2.0*d,normal,dir,newdir);
- }
-
- /* Do mirror/specular computations */
- if ((latten = s->att->ks*atten) > 0.01) {
- getspecular(level,latten,s,d,normal,intersect,dir,newdir,color);
- }
-
- /* Do reflection computations (any lights shining on this point?) */
- if (s->att->kd > 0.0 || s->att->ks > 0.0) {
- getlights(s,intersect,normal,diffuse,newdir,color);
- }
-
- /* compute transparency (if necessary) */
- if ((latten = s->att->kt*atten) > 0.01 && s->att->ir != 1.0) {
- gettrans(level,latten,s,eflip,d,normal,intersect,dir,color);
- }
-
- /* return the results */
- vcopy(color,retval);
- }
-
-