home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / formats / uray / code / texture.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-20  |  6.5 KB  |  222 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 LICENSE. 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.  *    V1.3 881203 DBW - Fixed single precision TOLerances        *
  33.  *                                    *
  34.  ************************************************************************/
  35.  
  36. #include "uray.h"
  37.  
  38. /************************************************************************/
  39. /**************** This module computes textures of objects **************/
  40. /************************************************************************/
  41.  
  42. /* get the procedure texture */
  43. void gettex(n,intersect,normal,diffuse)
  44. NODE    *n;
  45. VEC    intersect,normal,diffuse;
  46.     {
  47.     int        i,j,k;
  48.     FLTDBL  d;
  49.  
  50.     /* start with the default diffuse color */
  51.     vcopy(n->att->color,diffuse);
  52.     switch (n->att->tex) {
  53.  
  54.     /* no texture */
  55.     case 0:
  56.     break;
  57.  
  58.     /* checker board, p1 = alternate color, p2 = scale */
  59.     case 1:
  60.     for (i=j=0; i<3; i++) {
  61.         if (n->att->p2[i] > 0.0) {
  62.         k = (int)(intersect[i] / n->att->p2[i]);
  63.         if (k < 0) j -= k;
  64.         else       j += k;
  65.         }
  66.         }
  67.     if (j & 1) { vcopy(n->att->p1,diffuse);  }
  68.     break;
  69.  
  70.     /* random mottled texture, p1 = alternate color */
  71.     case 2:
  72.     for (i=0; i<3; i++) {
  73.         diffuse[i] *= (d=rnd());
  74.         diffuse[i] += (1.0-d) * n->att->p1[i];
  75.         }
  76.     break;
  77.  
  78.     /* blend textures */
  79.     case 3:        /* X axis blend, p1 = alternate color, p2 = coordinate */
  80.     case 4:        /* Y axis blend, p1 = alternate color, p2 = coordinate */
  81.     case 5:        /* Z axis blend, p1 = alternate color, p2 = coordinate */
  82.     i = n->att->tex - 3;
  83.     if (intersect[i] > n->att->p2[1])   d = n->att->p2[2] - n->att->p2[1];
  84.     else                     d = n->att->p2[0] - n->att->p2[1];
  85.  
  86.     if (d == 0.0) break;
  87.     d = (intersect[i] - n->att->p2[1]) / d;
  88.     
  89.     if (d > 1.0) d = 1.0;
  90.     if (d < 0.0) d = 0.0;
  91.  
  92.     for (i=0; i<3; i++) {
  93.         diffuse[i]    *= d;
  94.         diffuse[i]    += (1.0-d) * n->att->p1[i];
  95.         }
  96.     break;
  97.     }
  98.     }
  99.  
  100. /* return background value (computes sky and ground colors) */
  101. void getamb(frm, dir, retval)
  102. VEC frm, dir, retval;
  103.     {
  104.     FLTDBL  v;
  105.     int        i;
  106.  
  107.     if (dir[1] < 0.0) {
  108.     vcopy(GROUND,retval);
  109.     return;
  110.     }
  111.     if (dir[2] < 0.0)    v = 0.0;
  112.     else {
  113.     v = (1.0 - dir[1]) * dir[2];
  114.     if (v > 1.0) v = 1.0;
  115.     else         v *= v;
  116.     }
  117.     for (i=0; i<3; i++) {
  118.     retval[i]  = NEAR[i] * (1.0 - v);
  119.     retval[i] +=  FAR[i] * v;
  120.     }    
  121.     }
  122.  
  123. /* figure out ripple for current point inside of a wave surface */
  124. void calcripple(point,w,ripple)
  125. VEC    point;
  126. int    w;
  127. VEC    ripple;
  128.     {
  129.     FLTDBL  riprad,damper,tmp;
  130.     int        i,iriprad;
  131.  
  132.     riprad = 0.0;
  133.     for (i=0; i<3; i++) {
  134.     ripple[i] = tmp = waves[w].cen[i] - point[i];
  135.     riprad     += tmp * tmp;
  136.     }
  137.     /* unit vector pointing away from wave center */
  138.     vunit(ripple,ripple);
  139.  
  140.     riprad  =  sqrt(riprad);        /* distance from center to point */
  141.     riprad +=  waves[w].phase * waves[w].length;  /* move it */
  142.  
  143.     riprad /= waves[w].length;  /* scale half-wave crest to 0..1 */
  144.     if (waves[w].damp == 1.0)    damper = 1.0;
  145.     else            damper = pow(waves[w].damp,riprad);
  146.  
  147.     iriprad = (int)riprad;
  148.     if (iriprad & 1)  {/* negate it */
  149.     vscale(-1.0,ripple,ripple);
  150.     }
  151.     riprad -= (FLTDBL) iriprad;            /* just get fraction 0..1 */
  152.     riprad -= 0.5;                /* scale to -0.5 .. +0.5 */
  153.     if (riprad < 0.0) riprad = -riprad;        /* absolute value */
  154.     riprad  = 0.5 - riprad;            /* invert */
  155.     riprad *= damper;
  156.     riprad *= waves[w].amp;
  157.     vscale(riprad,ripple,ripple);        /* scale bend */
  158.     }
  159.  
  160. /* find surface normal for any object */
  161. FLTDBL findnormal(s,dir,intersect,normal,eflip)
  162. NODE    *s;
  163. VEC    dir,intersect,normal;
  164. int    *eflip;
  165.     {
  166.     int        i;
  167.     FLTDBL  d;
  168.     VEC        ripple,fuzzy;
  169.  
  170.     /* first get the standard normal */
  171.     switch (s->typ) {
  172.     case TYP_S:      spherenormal(intersect,s,normal); break;
  173.     default:     planenormal(s,normal);
  174.     }
  175.  
  176.     /* do any desired waves */
  177.     if (s->att->wave != -1) { /* don't bother checking if there's no waves*/
  178.     if (s->att->wave == -2) { /* fiddle with normal for all ripples */
  179.         for (i = 0; i < nwaves; i++) {
  180.         calcripple(intersect,i,ripple);  /* calculate the wave perturbation */
  181.         vadd(ripple,normal,normal);  /* add ripple bend to normal */
  182.         }
  183.         }
  184.  
  185.     /* fiddle with normal for one ripple */
  186.         else if (s->att->wave >= 0) {
  187.         calcripple(intersect,s->att->wave,ripple);  /* calc wave perturbation */
  188.         vadd(ripple,normal,normal);  /* add ripple bend to normal */
  189.         }
  190.     vunit(normal,normal);  /* make sure it's a unit vector after all that */
  191.     }
  192.  
  193.     /* Add any general normal perturbations */
  194.     if (s->att->kf > 0.0) {
  195.  
  196.     /* Perturb the normal randomly to produce fuzzy surfaces */
  197.     fuzzy[0] = rnd();  /* 0..1 */
  198.     fuzzy[1] = rnd();
  199.     fuzzy[2] = rnd();
  200.     if (rnd() < 0.5) fuzzy[0] = -fuzzy[0];
  201.     if (rnd() < 0.5) fuzzy[1] = -fuzzy[1];
  202.     if (rnd() < 0.5) fuzzy[2] = -fuzzy[2];
  203.  
  204.     /* 'fuzzy' is now approximately a random unit vector */
  205.     vcomb(rnd() * s->att->kf,fuzzy,normal,normal);
  206.     vunit(normal,normal);  /* make sure it's a unit vector after all that */
  207.     }
  208.  
  209.     /* make sure the normal is on the correct side of the surface */
  210.     d        = -vdot(dir,normal);
  211.     *eflip  = 0;
  212.     if (d < 0.0) {
  213.     vscale(-1.0, normal, normal);
  214.     *eflip    = 1;
  215.     d    = -d;
  216.     }
  217.  
  218.     return d;
  219.     }
  220.  
  221.  
  222.