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 >
C/C++ Source or Header  |  1989-04-04  |  7KB  |  236 lines

  1. /************************************************************************
  2.  *                                    *
  3.  *            Copyright (c) 1988, David B. Wecker            *
  4.  *                All Rights Reserved                *
  5.  *                                    *
  6.  * This file is part of DBW_uRAY                    *
  7.  *                                    *
  8.  * DBW_uRAY is distributed in the hope that it will be useful, but    *
  9.  * WITHOUT ANY WARRANTY. No author or distributor accepts        *
  10.  * responsibility to anyone for the consequences of using it or for    *
  11.  * whether it serves any particular purpose or works at all, unless    *
  12.  * he says so in writing. Refer to the DBW_uRAY General Public        *
  13.  * License for full details.                        *
  14.  *                                    *
  15.  * Everyone is granted permission to copy, modify and redistribute    *
  16.  * DBW_uRAY, but only under the conditions described in the        *
  17.  * DBW_uRAY General Public License. A copy of this license is        *
  18.  * supposed to have been given to you along with DBW_uRAY so you    *
  19.  * can know your rights and responsibilities. It should be in a file    *
  20.  * named COPYING. Among other things, the copyright notice and this    *
  21.  * notice must be preserved on all copies.                *
  22.  ************************************************************************
  23.  *                                    *
  24.  * Authors:                                *
  25.  *    DBW - David B. Wecker                        *
  26.  *                                    *
  27.  * Versions:                                *
  28.  *    V1.0 881023 DBW    - First released version            *
  29.  *    V1.1 881110 DBW - Fixed scan coherence code            *
  30.  *    V1.2 881125 DBW - Removed ALL scan coherence code (useless)    *
  31.  *              added "fat" extent boxes            *
  32.  *                                    *
  33.  ************************************************************************/
  34.  
  35. #include "uray.h"
  36.  
  37. /************************************************************************/
  38. /********************* All ray tracing is in this module ****************/
  39. /************************************************************************/
  40.  
  41.  
  42. /* See if object s has 1 or more lights shining on it */
  43. void getlights(s,intersect,normal,diffuse,newdir,color)
  44. NODE    *s;
  45. VEC    intersect,normal,diffuse,newdir,color;
  46.     {
  47.     register NODE    *l;
  48.     register FLTDBL    dist, eta, eta2;
  49.     VEC            lint,ldir,v1;
  50.     int            i;
  51.     LIGHT        *lp;
  52.     FLTDBL        tmin;
  53.  
  54.     /* Look at each light */
  55.     for (lp=lights; lp; lp = lp->next) {
  56.  
  57.     /* get the dir,distance to the light */
  58.     l = lp->child;
  59.     vcomb(-1.0,intersect,l->cen,ldir);
  60.     dist = vdot(ldir,ldir);
  61.     vscale(1.0/sqrt(dist),ldir,ldir);
  62.  
  63.     /* if not a point source, compute new light intensity */
  64.     if (l->att->dist > 0.0) {
  65.  
  66.         /* get the distance to the light */
  67.         if (dist == 0.0) dist = 0.0001;
  68.  
  69.         /* use inverse square law to factor intensity */
  70.         vscale(l->att->dist / dist,l->att->color,lint);
  71.         }
  72.     else vcopy(l->att->color,lint);
  73.  
  74.     /* see if there are any reflections to do */
  75.     eta = eta2 = 0.0;
  76.     if (s->att->kd > 0.0) eta  = vdot(normal,ldir);
  77.     if (s->att->ks > 0.0) eta2 = vdot(ldir,newdir);
  78.     if (eta > 0.00 || eta2 > 0.00)
  79.         if (intersection(intersect, ldir, &tmin) != l)
  80.         eta = eta2 = 0.0;
  81.  
  82.     /* do diffuse reflections */
  83.     if (eta > 0.00) {
  84.         vmul(lint,diffuse,v1);
  85.         eta *= s->att->kd*l->att->kl;
  86.         vcomb(eta,v1,color,color);
  87.         }
  88.  
  89.     /* do specular reflections */
  90.     if (eta2 > 0.00) {
  91.         if (s->att->kf == 0.0) eta = 1000.0;
  92.         else {
  93.         eta = 2.0/s->att->kf;
  94.         if (eta < 1.0) eta = 1.0;
  95.         }
  96.         eta2  = pow(eta2,eta);
  97.         eta2 *= s->att->ks*l->att->kl;
  98.         if (eta2 > TOL) {
  99.         vcomb(eta2,lint,color,color);
  100.         }
  101.         }
  102.     }
  103.     }
  104.  
  105. /* Do any specular reflections off of object s */
  106. void getspecular(level,atten,s,d,normal,intersect,dir,newdir,color)
  107. NODE    *s;
  108. FLTDBL    d,atten;
  109. VEC    normal,intersect,dir,newdir,color;
  110.     {
  111.     FLTDBL  eta;
  112.     VEC        newcolor;
  113.  
  114.     /* and see where it goes */
  115.     trace(level,atten,intersect,newdir,newcolor);
  116.  
  117.     /* scale by specular factor */
  118.     vscale(s->att->ks,newcolor,newcolor);
  119.  
  120.     /* Add sparkle */
  121.     eta = vdot(normal,newdir);
  122.     if (eta >= 0.0) {
  123.     eta = 1.0 - eta;
  124.     eta = eta * eta * eta * eta * eta;
  125.     vcomb(eta,newcolor,newcolor,newcolor);
  126.     }
  127.     vcomb(1.0,newcolor,color,color);
  128.     }
  129.  
  130. /* If object is transparent, compute what's on the other side */
  131. void gettrans(level,atten,s,eflip,d,normal,intersect,dir,color)
  132. NODE        *s;
  133. FLTDBL        d,atten;
  134. VEC        normal,intersect,dir,color;
  135.     {
  136.     FLTDBL    eta;
  137.     VEC        v1;
  138.  
  139.     /* get the correct index of refrection */
  140.     if (eflip)  eta = 1.0 / s->att->ir;
  141.     else    eta = s->att->ir;
  142.  
  143.     /* compute the angle of the new ray */
  144.     vcomb(d,normal,dir,v1);
  145.     vscale(eta,v1,v1);
  146.     eta = vdot(v1,v1);
  147.  
  148.     /* make sure that we aren't past critical angle */
  149.     if (eta < 1.0) {
  150.  
  151.     /* get the vector through the surface */
  152.     vcomb(-sqrt(1.0-eta),normal,v1,v1);
  153.  
  154.     /* see who's visable */
  155.     trace(level,atten,intersect,v1,v1);
  156.  
  157.     /* add it to the return color */
  158.     vcomb(s->att->kt, v1, color, color);
  159.     }
  160.     }
  161.  
  162. /* main raytrace routine */
  163. void trace(level, atten, frm, dir, retval)
  164. VEC    frm, dir, retval;
  165. FLTDBL    atten;
  166.     {
  167.     register NODE   *s;
  168.     register FLTDBL  d, eta;
  169.     register FLTDBL  latten;
  170.     VEC         normal, color, diffuse, v1, v2, intersect, newdir;
  171.     int         eflip;
  172.     FLTDBL  tmin;
  173.  
  174.     /* have we recursed too far? */
  175.     if (++level == depth) {
  176.     vcopy(BLACK,retval);
  177.     return; 
  178.     }
  179.  
  180.     /* If we don't hit anything then return background */
  181.     if (!(s = intersection(frm, dir, &tmin))) {
  182.     getamb(frm,dir,retval);
  183.         return;
  184.     }
  185.  
  186.     /* get the intersection point */
  187.     vcomb(tmin, dir, frm, intersect);
  188.  
  189.     /* compute the surface normal */
  190.     d = findnormal(s,dir,intersect,normal,&eflip);
  191.  
  192.     /* get a base diffuse level (if necessary) */
  193.     if (s->att->kl > 0.0 || s->att->kd > 0.0) {
  194.  
  195.     /* get base color (procedural texture) of the object */
  196.     gettex(s,intersect,normal,diffuse);
  197.  
  198.     /* if we're a light, then use the light amount else the base amount */
  199.     if (s->att->kl > 0.0) {
  200.         vscale(s->att->kl,diffuse,color);
  201.         }
  202.     else {
  203.         vscale(base,diffuse,color);
  204.         }
  205.     }
  206.  
  207.     /* otherwise start out with no color */
  208.     else {
  209.     vcopy(BLACK,color);
  210.     }
  211.  
  212.     /* bounce the ray off the surface for specular/mirror reflection */
  213.     if (s->att->ks > 0.0 || s->att->kd > 0.0) {
  214.     vcomb(2.0*d,normal,dir,newdir);
  215.     }
  216.  
  217.     /* Do mirror/specular computations */
  218.     if ((latten = s->att->ks*atten) > 0.01) {
  219.     getspecular(level,latten,s,d,normal,intersect,dir,newdir,color);
  220.     }
  221.  
  222.     /* Do reflection computations (any lights shining on this point?) */
  223.     if (s->att->kd > 0.0 || s->att->ks > 0.0) {
  224.     getlights(s,intersect,normal,diffuse,newdir,color);
  225.     }
  226.  
  227.     /* compute transparency (if necessary) */
  228.     if ((latten = s->att->kt*atten) > 0.01 && s->att->ir != 1.0) {
  229.     gettrans(level,latten,s,eflip,d,normal,intersect,dir,color);
  230.     }
  231.  
  232.     /* return the results */
  233.     vcopy(color,retval);
  234.     }
  235.  
  236.