home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / RT / M_DIRECT.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  5KB  |  210 lines

  1. /* Copyright (c) 1991 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)m_direct.c 2.3 5/15/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  * Routines for light-redirecting materials and
  9.  *   their associated virtual light sources
  10.  */
  11.  
  12. #include  "ray.h"
  13.  
  14. #include  "otypes.h"
  15.  
  16. #include  "source.h"
  17.  
  18. #include  "func.h"
  19.  
  20. /*
  21.  * The arguments for MAT_DIRECT1 are:
  22.  *
  23.  *    5+ coef1 dx1 dy1 dz1 funcfile transform..
  24.  *    0
  25.  *    n A1 A2 .. An
  26.  *
  27.  * The arguments for MAT_DIRECT2 are:
  28.  *
  29.  *    9+ coef1 dx1 dy1 dz1 coef2 dx2 dy2 dz2 funcfile transform..
  30.  *    0
  31.  *    n A1 A2 .. An
  32.  */
  33.  
  34.  
  35. int  dir_proj();
  36. VSMATERIAL  direct1_vs = {dir_proj, 1};
  37. VSMATERIAL  direct2_vs = {dir_proj, 2};
  38.  
  39. #define getdfunc(m)    ( (m)->otype == MAT_DIRECT1 ? \
  40.                 getfunc(m, 4, 0xf, 1) : \
  41.                 getfunc(m, 8, 0xff, 1) )
  42.  
  43.  
  44. m_direct(m, r)            /* shade redirected ray */
  45. register OBJREC  *m;
  46. register RAY  *r;
  47. {
  48.                     /* check if source ray */
  49.     if (r->rsrc >= 0 && source[r->rsrc].so != r->ro)
  50.         return;                /* got the wrong guy */
  51.                     /* compute first projection */
  52.     if (m->otype == MAT_DIRECT1 ||
  53.             (r->rsrc < 0 || source[r->rsrc].sa.sv.pn == 0))
  54.         redirect(m, r, 0);
  55.                     /* compute second projection */
  56.     if (m->otype == MAT_DIRECT2 &&
  57.             (r->rsrc < 0 || source[r->rsrc].sa.sv.pn == 1))
  58.         redirect(m, r, 1);
  59. }
  60.  
  61.  
  62. redirect(m, r, n)        /* compute n'th ray redirection */
  63. OBJREC  *m;
  64. RAY  *r;
  65. int  n;
  66. {
  67.     MFUNC  *mf;
  68.     register EPNODE  **va;
  69.     FVECT  nsdir;
  70.     RAY  nr;
  71.     double  coef;
  72.     register int  j;
  73.                     /* set up function */
  74.     mf = getdfunc(m);
  75.     setfunc(m, r);
  76.                     /* assign direction variable */
  77.     if (r->rsrc >= 0) {
  78.         register SRCREC  *sp = source + source[r->rsrc].sa.sv.sn;
  79.  
  80.         if (sp->sflags & SDISTANT)
  81.             VCOPY(nsdir, sp->sloc);
  82.         else {
  83.             for (j = 0; j < 3; j++)
  84.                 nsdir[j] = sp->sloc[j] - r->rop[j];
  85.             normalize(nsdir);
  86.         }
  87.         if (r->rox != NULL)
  88.             multv3(nsdir, nsdir, r->rox->b.xfm);
  89.         if (mf->b != &unitxf)
  90.             multv3(nsdir, nsdir, mf->b->xfm);
  91.     } else
  92.         nsdir[0] = nsdir[1] = nsdir[2] = 0.0;
  93.     varset("DxA", '=', nsdir[0]);
  94.     varset("DyA", '=', nsdir[1]);
  95.     varset("DzA", '=', nsdir[2]);
  96.                     /* compute coefficient */
  97.     errno = 0;
  98.     va = mf->ep + 4*n;
  99.     coef = evalue(va[0]);
  100.     if (errno)
  101.         goto computerr;
  102.     if (coef <= FTINY || rayorigin(&nr, r, TRANS, coef) < 0)
  103.         return(0);
  104.     va++;                /* compute direction */
  105.     for (j = 0; j < 3; j++) {
  106.         nr.rdir[j] = evalue(va[j]);
  107.         if (errno)
  108.             goto computerr;
  109.     }
  110.     if (mf->f != &unitxf)
  111.         multv3(nr.rdir, nr.rdir, mf->f->xfm);
  112.     if (r->rox != NULL)
  113.         multv3(nr.rdir, nr.rdir, r->rox->f.xfm);
  114.     if (normalize(nr.rdir) == 0.0)
  115.         goto computerr;
  116.                     /* compute value */
  117.     if (r->rsrc >= 0)
  118.         nr.rsrc = source[r->rsrc].sa.sv.sn;
  119.     rayvalue(&nr);
  120.     scalecolor(nr.rcol, coef);
  121.     addcolor(r->rcol, nr.rcol);
  122.     return(1);
  123. computerr:
  124.     objerror(m, WARNING, "compute error");
  125.     return(-1);
  126. }
  127.  
  128.  
  129. dir_proj(pm, o, s, n)        /* compute a director's projection */
  130. MAT4  pm;
  131. OBJREC  *o;
  132. SRCREC  *s;
  133. int  n;
  134. {
  135.     RAY  tr;
  136.     OBJREC  *m;
  137.     MFUNC  *mf;
  138.     EPNODE  **va;
  139.     FVECT  cent, newdir, nv, h;
  140.     double  coef, olddot, newdot, od;
  141.     register int  i, j;
  142.                 /* initialize test ray */
  143.     getmaxdisk(cent, o);
  144.     if (s->sflags & SDISTANT)
  145.         for (i = 0; i < 3; i++) {
  146.             tr.rdir[i] = -s->sloc[i];
  147.             tr.rorg[i] = cent[i] - tr.rdir[i];
  148.         }
  149.     else {
  150.         for (i = 0; i < 3; i++) {
  151.             tr.rdir[i] = cent[i] - s->sloc[i];
  152.             tr.rorg[i] = s->sloc[i];
  153.         }
  154.         if (normalize(tr.rdir) == 0.0)
  155.             return(0);        /* at source! */
  156.     }
  157.     od = getplaneq(nv, o);
  158.     olddot = DOT(tr.rdir, nv);
  159.     if (olddot <= FTINY && olddot >= -FTINY)
  160.         return(0);        /* old dir parallels plane */
  161.     rayorigin(&tr, NULL, PRIMARY, 1.0);
  162.     if (!(*ofun[o->otype].funp)(o, &tr))
  163.         return(0);        /* no intersection! */
  164.                 /* compute redirection */
  165.     m = vsmaterial(o);
  166.     mf = getdfunc(m);
  167.     setfunc(m, &tr);
  168.     varset("DxA", '=', 0.0);
  169.     varset("DyA", '=', 0.0);
  170.     varset("DzA", '=', 0.0);
  171.     errno = 0;
  172.     va = mf->ep + 4*n;
  173.     coef = evalue(va[0]);
  174.     if (errno)
  175.         goto computerr;
  176.     if (coef <= FTINY)
  177.         return(0);        /* insignificant */
  178.     va++;
  179.     for (i = 0; i < 3; i++) {
  180.         newdir[i] = evalue(va[i]);
  181.         if (errno)
  182.             goto computerr;
  183.     }
  184.     if (mf->f != &unitxf)
  185.         multv3(newdir, newdir, mf->f->xfm);
  186.                     /* normalization unnecessary */
  187.     newdot = DOT(newdir, nv);
  188.     if (newdot <= FTINY && newdot >= -FTINY)
  189.         return(0);        /* new dir parallels plane */
  190.                 /* everything OK -- compute shear */
  191.     for (i = 0; i < 3; i++)
  192.         h[i] = newdir[i]/newdot - tr.rdir[i]/olddot;
  193.     setident4(pm);
  194.     for (j = 0; j < 3; j++) {
  195.         for (i = 0; i < 3; i++)
  196.             pm[i][j] += nv[i]*h[j];
  197.         pm[3][j] = -od*h[j];
  198.     }
  199.     if (newdot > 0.0 ^ olddot > 0.0)    /* add mirroring */
  200.         for (j = 0; j < 3; j++) {
  201.             for (i = 0; i < 3; i++)
  202.                 pm[i][j] -= 2.*nv[i]*nv[j];
  203.             pm[3][j] += 2.*od*nv[j];
  204.         }
  205.     return(1);
  206. computerr:
  207.     objerror(m, WARNING, "projection compute error");
  208.     return(0);
  209. }
  210.