home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / raytrace / dbw_render / source / c / VAL < prev   
Encoding:
Text File  |  1992-10-23  |  15.0 KB  |  386 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *                  Copyright (c) 1987, David B. Wecker                 *
  4.  *                          All Rights Reserved                         *
  5.  *                                                                      *
  6.  * This file is part of DBW_Render                                      *
  7.  *                                                                      *
  8.  * DBW_Render 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_Render General Public        *
  13.  * License for full details.                                            *
  14.  *                                                                      *
  15.  * Everyone is granted permission to copy, modify and redistribute      *
  16.  * DBW_Render, but only under the conditions described in the           *
  17.  * DBW_Render General Public License. A copy of this license is         *
  18.  * supposed to have been given to you along with DBW_Render 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. #define MODULE_VAL
  25. #include "ray.h"
  26.  
  27. void getval(val,np,p,d,atten,ambientlight)
  28. vector      val,
  29.   p,
  30.   d;
  31. node        *np;
  32. float       atten;
  33. int         ambientlight;
  34. {
  35.      vector      pseudodirection,
  36.      pseudointensity,
  37.      tp,
  38.      lightdir,
  39.      lightint,
  40.      penumbra,
  41.      transparency,
  42.      best_p,
  43.      nval,
  44.      n,
  45.      r,
  46.      temp,
  47.      specintensity,
  48.      diffuse,
  49.      v1;
  50.      float       best_t,
  51.        ndotdir,
  52.        t,
  53.        texture,
  54.        td,
  55.        pointdist,
  56.        umbscale;
  57.      float       ndotd,
  58.        ambientscale;
  59.      int         hitnext,
  60.        lit,
  61.        i,
  62.        itd;
  63.      node        *bouncenp,
  64.      *occlude;
  65.      vector      light_atten[MAXLIT];
  66.      int         l_objcounter;
  67.      float       l_distances[MAXOBJ];
  68.      node        *l_objpairs[MAXOBJ];
  69.      vector      l_points[MAXOBJ];
  70.  
  71.      if (allopaque == 0) 
  72.      { /* If not opaque,then save the ray intersection list */
  73.           l_objcounter = g_objcounter;
  74.           for (i = 0; i < l_objcounter; i++) 
  75.           {
  76.                l_distances[i] = g_distances[i];
  77.                l_objpairs[i] = g_objpairs[i];
  78.                veccopy(g_points[i],l_points[i]);
  79.           }
  80.      }
  81.  
  82.      veczero(val);  /* start with output value of zero */
  83.  
  84.      findnormal(np,p,n);
  85.      ndotd = DOT(n,d);
  86.      if (ndotd > 0.0) 
  87.      {          /* We're looking at surface's back side */
  88.           ndotd = -ndotd;
  89.           n[0] = -n[0];  /* Flip the normal */
  90.           n[1] = -n[1];
  91.           n[2] = -n[2];
  92.      }
  93.  
  94.      /* Initialize the light attenuation values with 'not-yet-computed' flag */
  95.  
  96.      for (lit = 0; lit < numlits; lit++)
  97.           light_atten[lit][0] = -99.9;
  98.  
  99.      /* Apply procedural texture */
  100.      gettex(diffuse,np,p,n);
  101.  
  102.      /*---------------------------------------------------------------------*/
  103.      /* Compute diffuse reflection intensity */
  104.  
  105.      if (diffuse[0] > 0.01 || diffuse[1] > 0.01 || diffuse[2] > 0.01) 
  106.      {
  107.  
  108.           /* First,compute light shining directly on this point */
  109.           for (lit = 0; lit < numlits; lit++) 
  110.           { 
  111.                veccopy(light[lit].direction,lightdir);
  112.                veccopy(light[lit].intensity,lightint);
  113.  
  114.                pointdist = 0.0;
  115.  
  116.                if (light[lit].kind != 0) 
  117.                { /* If point source,compute local direction */
  118.                     vecsub(lightdir,p,lightdir);
  119.                     pointdist = NORM(lightdir);  /* distance to point light source */
  120.                     if (pointdist == 0.0)
  121.                          pointdist = 0.01;
  122.                     umbscale  = light[lit].distscale;
  123.                     umbscale /= pointdist * pointdist;
  124.                     vecscale(umbscale,lightint,lightint);
  125.                     CV(rnd(),rnd(),rnd(),penumbra);
  126.                     if (rnd() < 0.5)
  127.                          penumbra[0] = -penumbra[0];
  128.                     if (rnd() < 0.5)
  129.                          penumbra[1] = -penumbra[1];
  130.                     if (rnd() < 0.5)
  131.                          penumbra[2] = -penumbra[2];
  132.                     normalize(penumbra);  /* penumbra is now random unit vector */
  133.  
  134.                     umbscale  = rnd();
  135.                     umbscale -= 0.05;
  136.                     umbscale *= light[lit].radius;
  137.                     vecscale(umbscale,penumbra,penumbra);
  138.                     vecsum(penumbra,lightdir,lightdir);
  139.                     normalize(lightdir);
  140.                }
  141.  
  142.                /* Now that we know where the light is shining from,compute diffuse
  143.                (lamertian) reflection */
  144.  
  145.                ndotdir = DOT(n,lightdir);
  146.                if (ndotdir > 0.0) 
  147.                {
  148.                     vecmul(lightint,diffuse,nval);
  149.                     vecscale(ndotdir,nval,nval);
  150.                }
  151.                else
  152.                {
  153.                     veczero(nval);  /* self shadowing -- backside of spheres,etc. */
  154.                }
  155.  
  156.                /* If the computed diffuse surface brightness is above a certain
  157.                threshold level,then compute the shadow attenuation */
  158.  
  159.                if (nval[0] > 0.01 || nval[1] > 0.01 || nval[2] > 0.01) 
  160.                {
  161.                     getatten(light_atten[lit],p,lightdir,lit,pointdist);
  162.                     vecmul(nval,light_atten[lit],nval); /* attenuate */
  163.                }
  164.                vecsum(nval,val,val);  /* Sum up for all light sources */
  165.           } /* for */
  166.  
  167.           /*---------------------------------------------------------------------*/
  168.           /* Next,compute light shining indirectly from any surfaces on this    */
  169.           /* point.  This is done to approximate true ambient illumination.      */
  170.  
  171.           for (lit = 0; lit < ambientlight; lit++) 
  172.           {
  173.                ambientscale = 1.0 / (float) ambientlight;
  174.                /* ?? not sure how to factor in distance from diffuse reflector */
  175.  
  176.                CV(rnd(),rnd(),rnd(),lightdir);
  177.                if (rnd() < 0.5)
  178.                     lightdir[0] = -lightdir[0];
  179.                if (rnd() < 0.5)
  180.                     lightdir[1] = -lightdir[1];
  181.                if (rnd() < 0.5)
  182.                     lightdir[2] = -lightdir[2];
  183.                normalize(lightdir);  /* lightdir is now random unit vector */
  184.  
  185.                ndotdir = DOT(n,lightdir);
  186.                if (ndotdir < 0.0) 
  187.                { /* if not in upper hemisphere,invert it */
  188.                     lightdir[0] = -lightdir[0];
  189.                     lightdir[1] = -lightdir[1];
  190.                     lightdir[2] = -lightdir[2];
  191.                     ndotdir = -ndotdir;
  192.                }
  193.  
  194.                /* okay,now the direction is known.  What is visible there? */
  195.                dodirection(nval,p,lightdir,ambientscale,
  196.                  ambientlight * amblitnum / amblitdenom);
  197.  
  198.                val[0] += nval[0] * ndotdir * diffuse[0];
  199.                val[1] += nval[1] * ndotdir * diffuse[1];
  200.                val[2] += nval[2] * ndotdir * diffuse[2];
  201.  
  202.           } /* for */
  203.  
  204.  
  205.           /*---------------------------------------------------------------------*/
  206.           /* Next,compute light shining indirectly from mirrors on this point   */
  207.  
  208.           if (dopseudo) 
  209.           {
  210.                for (lit = 0; lit < numlits; lit++) 
  211.                { /* for each true light... */
  212.                     bouncenp = root;
  213.                     while (bouncenp) 
  214.                     { /* for each possible mirror... */
  215.                          if (bouncelighting(pseudointensity,pseudodirection,bouncenp,lit)
  216.                            && bouncenp != np) 
  217.                          { /* don't check reflections from ourselves */
  218.                               /* Okay,this object reflects light.  Does any of it reach us? */
  219.                               CV(1.0,1.0,1.0,transparency);
  220. #ifdef MCH_AMIGA
  221.                               occlude = 1L;
  222. #else
  223.                               occlude = (node *)1L;
  224. #endif
  225.                               hitnext = 0;
  226.                               all_intersects(p,pseudodirection,0);
  227.  
  228.                               while (occlude &&  (transparency[0] > 0.01 ||
  229.                                 transparency[1] > 0.01 ||
  230.                                 transparency[2] > 0.01)) 
  231.                               {
  232.                                    if (occlude = get_next_intersection(hitnext,best_p,&best_t)) 
  233.                                    {
  234.                                         /* pseudolight intersects an object,see if any passes through */
  235.                                         if (occlude == bouncenp)
  236.                                              occlude = 0;  /* hit the mirror causing the pseudolight,stop */
  237.                                         else
  238.                                         {
  239.                                              vecmul(transparency,occlude->attr.tra,
  240.                                                transparency);
  241.                                              hitnext++;
  242.                                         }
  243.                                    }
  244.                                    else
  245.                                    {
  246.                                         /* no more objects to intersect -- we didn't intersect the mirror
  247.                                         that is causing the pseudolight,so cancel the pseudolight */
  248.                                         veczero(transparency);
  249.                                    }
  250.                               }
  251.  
  252.                               if (transparency[0] > 0.01 || transparency[1] > 0.01 ||
  253.                                 transparency[2] > 0.01) 
  254.                               {
  255.                                    ndotdir = DOT(n,pseudodirection);
  256.                                    if (ndotdir > 0.0) 
  257.                                    {
  258.                                         for (i = 0; i < 3; i++)
  259.                                              val[i] += transparency[i] * pseudointensity[i] * 
  260.                                                ndotdir * diffuse[i];
  261.                                    }
  262.                               }
  263.                          } /* if */
  264.                          bouncenp = bouncenp->next;  /* next possible mirror */
  265.                     } /* while */
  266.                } /* for */
  267.           } /* if dopseudo */
  268.      } /* if any diffuse reflectivity */
  269.  
  270.      /*---------------------------------------------------------------------*/
  271.      /* Compute mirror & specular reflection intensity */
  272.  
  273.      atten *= np->attr.ref;  /* factor in the object's relative reflectivity */
  274.  
  275.      if (atten > 0.01) 
  276.      { /* Is object meaningfully reflective still */
  277.           vecscale(2 * ndotd,n,r);
  278.           vecsub(d,r,r);
  279.  
  280.           dodirection(nval,p,r,atten,ambientlight);  /* Mirror reflection */
  281.           vecscale(atten,nval,nval);  /* attenuate by reflectivity coeff */
  282.  
  283.           /* We really want Fresnel angle factor here,but... */
  284.           if (np->kind == SPHERE) 
  285.           { /* Add sparkle */
  286.                t = DOT(n,r);
  287.                if (t >= 0.0) 
  288.                {
  289.                     veccopy(nval,specintensity);
  290.                     t = 1.0 - t;
  291.                     t = t * t * t * t * t;
  292.                     vecscale(t,specintensity,specintensity);
  293.                     vecsum(nval,specintensity,nval);
  294.                }
  295.           }
  296.  
  297.           /* Compute specular reflection intensity */
  298.  
  299.           for (lit = 0; lit < numlits; lit++) 
  300.           {
  301.                veccopy(light[lit].direction,lightdir);
  302.                veccopy(light[lit].intensity,lightint);
  303.                pointdist = 0.0;
  304.  
  305.                if (light[lit].kind != 0) 
  306.                { /* If point source,compute local direction */
  307.                     vecsub(lightdir,p,lightdir);
  308.                     pointdist = NORM(lightdir);  /* distance to point light source */
  309.                     if (pointdist == 0.0)
  310.                          pointdist = 0.01;
  311.                     umbscale  = light[lit].distscale;
  312.                     umbscale /= pointdist * pointdist;
  313.                     vecscale(umbscale,lightint,lightint);
  314.                     normalize(lightdir);
  315.                }
  316.  
  317.                t = DOT(lightdir,r);
  318.                if (t > 0.0) 
  319.                {              /* Check self-shadowing */
  320.                     if (np->attr.fuz == 0.0)
  321.                          td = 1000.0;  /* extremely smooth mirror */
  322.                     else
  323.                     {
  324.                          td = 2.0/np->attr.fuz;  /* calc specular decay rate based on fuz */
  325.                          if (td < 1.0)
  326.                               td = 1.0;
  327.                     }
  328.  
  329.                     t = pow(t,td)  /* calc reflectivity for desired gloss */
  330.                       * atten;  /* attenuate specular reflections by reflectivity coeff */
  331.  
  332.                     if (t > 0.01) 
  333.                     { /* specular coefficient is meaningful,add it */
  334.                          /* first compute shadowing of light source causing specular refl. */
  335.                          if (light_atten[lit][0] < 0.0)  /* Not already computed,compute */
  336.                               getatten(light_atten[lit],p,lightdir,lit,pointdist);
  337.  
  338.                          nval[0] += lightint[0] * light_atten[lit][0] * t;
  339.                          nval[1] += lightint[1] * light_atten[lit][1] * t;
  340.                          nval[2] += lightint[2] * light_atten[lit][2] * t;
  341.                     }
  342.                }
  343.           }
  344.  
  345.           vecsum(nval,val,val); /* Add mirror/specular reflections to running total */
  346.      } /* if reflective atten is non-zero */
  347.  
  348.  
  349.  
  350.      /*----------------------------------------------------------------------*/
  351.      /* Add in the object's ambient intensity */
  352.      if (ambscale < 0.0) 
  353.      {
  354.           vecsum(np->attr.amb,val,val);
  355.      }
  356.      else
  357.      { /* use specified computed ambient */
  358.           val[0] += diffuse[0] * ambscale;
  359.           val[1] += diffuse[1] * ambscale;
  360.           val[2] += diffuse[2] * ambscale;
  361.      }
  362.  
  363.      /*---------------------------------------------------------------------*/
  364.      /* Apply any post-process global texture functions */
  365.  
  366.      if (numhazes > 0) 
  367.      {
  368.           /* Blend the final color toward the specified haze color */
  369.           vecsub(p,eye,temp);
  370.           texture  = NORM(temp);  /* distance to point from eye */
  371.           texture /= haze[numhazes-1].distscale;  /* scaled according to user */
  372.           blendcolor(val,haze[numhazes-1].color,texture,val);
  373.      }
  374.  
  375.      if (allopaque == 0) 
  376.      { /* If not opaque,then restore the ray intersection list */
  377.           g_objcounter = l_objcounter;
  378.           for (i = 0; i < g_objcounter; i++) 
  379.           {
  380.                g_distances[i] = l_distances[i];
  381.                g_objpairs[i] = l_objpairs[i];
  382.                veccopy(l_points[i],g_points[i]);
  383.           }
  384.      }
  385. }
  386.