Back to index

radiance  4R0+20100331
m_direct.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: m_direct.c,v 2.13 2005/04/19 01:15:06 greg Exp $";
00003 #endif
00004 /*
00005  * Routines for light-redirecting materials and
00006  *   their associated virtual light sources
00007  */
00008 
00009 #include "copyright.h"
00010 
00011 #include  "ray.h"
00012 #include  "otypes.h"
00013 #include  "rtotypes.h"
00014 #include  "source.h"
00015 #include  "func.h"
00016 
00017 /*
00018  * The arguments for MAT_DIRECT1 are:
00019  *
00020  *     5+ coef1 dx1 dy1 dz1 funcfile transform..
00021  *     0
00022  *     n A1 A2 .. An
00023  *
00024  * The arguments for MAT_DIRECT2 are:
00025  *
00026  *     9+ coef1 dx1 dy1 dz1 coef2 dx2 dy2 dz2 funcfile transform..
00027  *     0
00028  *     n A1 A2 .. An
00029  */
00030 
00031 static int redirect(OBJREC  *m, RAY  *r, int  n);
00032 static int dir_proj(MAT4  pm, OBJREC  *o, SRCREC  *s, int  n);
00033 
00034 VSMATERIAL  direct1_vs = {dir_proj, 1};
00035 VSMATERIAL  direct2_vs = {dir_proj, 2};
00036 
00037 #define getdfunc(m)  ( (m)->otype == MAT_DIRECT1 ? \
00038                             getfunc(m, 4, 0xf, 1) : \
00039                             getfunc(m, 8, 0xff, 1) )
00040 
00041 
00042 extern int
00043 m_direct(                   /* shade redirected ray */
00044        register OBJREC  *m,
00045        register RAY  *r
00046 )
00047 {
00048                                    /* check if source ray */
00049        if (r->rsrc >= 0 && source[r->rsrc].so != r->ro)
00050               return(1);                  /* got the wrong guy */
00051                                    /* compute first projection */
00052        if (m->otype == MAT_DIRECT1 ||
00053                      (r->rsrc < 0 || source[r->rsrc].sa.sv.pn == 0))
00054               redirect(m, r, 0);
00055                                    /* compute second projection */
00056        if (m->otype == MAT_DIRECT2 &&
00057                      (r->rsrc < 0 || source[r->rsrc].sa.sv.pn == 1))
00058               redirect(m, r, 1);
00059        return(1);
00060 }
00061 
00062 
00063 static int
00064 redirect(            /* compute n'th ray redirection */
00065        OBJREC  *m,
00066        RAY  *r,
00067        int  n
00068 )
00069 {
00070        MFUNC  *mf;
00071        register EPNODE  **va;
00072        FVECT  nsdir;
00073        RAY  nr;
00074        double  coef;
00075        register int  j;
00076                                    /* set up function */
00077        mf = getdfunc(m);
00078        setfunc(m, r);
00079                                    /* assign direction variable */
00080        if (r->rsrc >= 0) {
00081               register SRCREC  *sp = source + source[r->rsrc].sa.sv.sn;
00082 
00083               if (sp->sflags & SDISTANT)
00084                      VCOPY(nsdir, sp->sloc);
00085               else {
00086                      for (j = 0; j < 3; j++)
00087                             nsdir[j] = sp->sloc[j] - r->rop[j];
00088                      normalize(nsdir);
00089               }
00090               multv3(nsdir, nsdir, funcxf.xfm);
00091               varset("DxA", '=', nsdir[0]/funcxf.sca);
00092               varset("DyA", '=', nsdir[1]/funcxf.sca);
00093               varset("DzA", '=', nsdir[2]/funcxf.sca);
00094        } else {
00095               varset("DxA", '=', 0.0);
00096               varset("DyA", '=', 0.0);
00097               varset("DzA", '=', 0.0);
00098        }
00099                                    /* compute coefficient */
00100        errno = 0;
00101        va = mf->ep + 4*n;
00102        coef = evalue(va[0]);
00103        if ((errno == EDOM) | (errno == ERANGE))
00104               goto computerr;
00105        setcolor(nr.rcoef, coef, coef, coef);
00106        if (rayorigin(&nr, TRANS, r, nr.rcoef) < 0)
00107               return(0);
00108        va++;                       /* compute direction */
00109        for (j = 0; j < 3; j++) {
00110               nr.rdir[j] = evalue(va[j]);
00111               if (errno == EDOM || errno == ERANGE)
00112                      goto computerr;
00113        }
00114        if (mf->f != &unitxf)
00115               multv3(nr.rdir, nr.rdir, mf->f->xfm);
00116        if (r->rox != NULL)
00117               multv3(nr.rdir, nr.rdir, r->rox->f.xfm);
00118        if (normalize(nr.rdir) == 0.0)
00119               goto computerr;
00120                                    /* compute value */
00121        if (r->rsrc >= 0)
00122               nr.rsrc = source[r->rsrc].sa.sv.sn;
00123        rayvalue(&nr);
00124        multcolor(nr.rcol, nr.rcoef);
00125        addcolor(r->rcol, nr.rcol);
00126        if (r->ro != NULL && isflat(r->ro->otype))
00127               r->rt = r->rot + nr.rt;
00128        return(1);
00129 computerr:
00130        objerror(m, WARNING, "compute error");
00131        return(-1);
00132 }
00133 
00134 
00135 static int
00136 dir_proj(            /* compute a director's projection */
00137        MAT4  pm,
00138        OBJREC  *o,
00139        SRCREC  *s,
00140        int  n
00141 )
00142 {
00143        RAY  tr;
00144        OBJREC  *m;
00145        MFUNC  *mf;
00146        EPNODE  **va;
00147        FVECT  cent, newdir, nv, h;
00148        double  coef, olddot, newdot, od;
00149        register int  i, j;
00150                             /* initialize test ray */
00151        getmaxdisk(cent, o);
00152        if (s->sflags & SDISTANT)
00153               for (i = 0; i < 3; i++) {
00154                      tr.rdir[i] = -s->sloc[i];
00155                      tr.rorg[i] = cent[i] - tr.rdir[i];
00156               }
00157        else {
00158               for (i = 0; i < 3; i++) {
00159                      tr.rdir[i] = cent[i] - s->sloc[i];
00160                      tr.rorg[i] = s->sloc[i];
00161               }
00162               if (normalize(tr.rdir) == 0.0)
00163                      return(0);           /* at source! */
00164        }
00165        od = getplaneq(nv, o);
00166        olddot = DOT(tr.rdir, nv);
00167        if (olddot <= FTINY && olddot >= -FTINY)
00168               return(0);           /* old dir parallels plane */
00169        tr.rmax = 0.0;
00170        rayorigin(&tr, PRIMARY, NULL, NULL);
00171        if (!(*ofun[o->otype].funp)(o, &tr))
00172               return(0);           /* no intersection! */
00173                             /* compute redirection */
00174        m = vsmaterial(o);
00175        mf = getdfunc(m);
00176        setfunc(m, &tr);
00177        varset("DxA", '=', 0.0);
00178        varset("DyA", '=', 0.0);
00179        varset("DzA", '=', 0.0);
00180        errno = 0;
00181        va = mf->ep + 4*n;
00182        coef = evalue(va[0]);
00183        if (errno == EDOM || errno == ERANGE)
00184               goto computerr;
00185        if (coef <= FTINY)
00186               return(0);           /* insignificant */
00187        va++;
00188        for (i = 0; i < 3; i++) {
00189               newdir[i] = evalue(va[i]);
00190               if (errno == EDOM || errno == ERANGE)
00191                      goto computerr;
00192        }
00193        if (mf->f != &unitxf)
00194               multv3(newdir, newdir, mf->f->xfm);
00195                                    /* normalization unnecessary */
00196        newdot = DOT(newdir, nv);
00197        if (newdot <= FTINY && newdot >= -FTINY)
00198               return(0);           /* new dir parallels plane */
00199                             /* everything OK -- compute shear */
00200        for (i = 0; i < 3; i++)
00201               h[i] = newdir[i]/newdot - tr.rdir[i]/olddot;
00202        setident4(pm);
00203        for (j = 0; j < 3; j++) {
00204               for (i = 0; i < 3; i++)
00205                      pm[i][j] += nv[i]*h[j];
00206               pm[3][j] = -od*h[j];
00207        }
00208        if ((newdot > 0.0) ^ (olddot > 0.0))      /* add mirroring */
00209               for (j = 0; j < 3; j++) {
00210                      for (i = 0; i < 3; i++)
00211                             pm[i][j] -= 2.*nv[i]*nv[j];
00212                      pm[3][j] += 2.*od*nv[j];
00213               }
00214        return(1);
00215 computerr:
00216        objerror(m, WARNING, "projection compute error");
00217        return(0);
00218 }