home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
231.lha
/
URay_v1.0
/
trace.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-04-04
|
7KB
|
236 lines
/************************************************************************
* *
* 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);
}