| 1 | 
greg | 
1.1 | 
#ifndef lint | 
| 2 | 
greg | 
2.10 | 
static const char       RCSid[] = "$Id$"; | 
| 3 | 
greg | 
1.1 | 
#endif | 
| 4 | 
  | 
  | 
/* | 
| 5 | 
  | 
  | 
 *  glass.c - simpler shading function for thin glass surfaces. | 
| 6 | 
greg | 
2.10 | 
 */ | 
| 7 | 
  | 
  | 
 | 
| 8 | 
greg | 
2.11 | 
#include "copyright.h" | 
| 9 | 
greg | 
1.1 | 
 | 
| 10 | 
  | 
  | 
#include  "ray.h" | 
| 11 | 
  | 
  | 
 | 
| 12 | 
greg | 
2.8 | 
#include  "otypes.h" | 
| 13 | 
  | 
  | 
 | 
| 14 | 
greg | 
1.1 | 
/* | 
| 15 | 
  | 
  | 
 *  This definition of glass provides for a quick calculation | 
| 16 | 
  | 
  | 
 *  using a single surface where two closely spaced parallel | 
| 17 | 
  | 
  | 
 *  dielectric surfaces would otherwise be used.  The chief | 
| 18 | 
  | 
  | 
 *  advantage to using this material is speed, since internal | 
| 19 | 
  | 
  | 
 *  reflections are avoided. | 
| 20 | 
  | 
  | 
 * | 
| 21 | 
  | 
  | 
 *  The specification for glass is as follows: | 
| 22 | 
  | 
  | 
 * | 
| 23 | 
  | 
  | 
 *      modifier glass id | 
| 24 | 
  | 
  | 
 *      0 | 
| 25 | 
  | 
  | 
 *      0 | 
| 26 | 
greg | 
2.9 | 
 *      3+ red grn blu [refractive_index] | 
| 27 | 
greg | 
1.1 | 
 * | 
| 28 | 
  | 
  | 
 *  The color is used for the transmission at normal incidence. | 
| 29 | 
greg | 
2.5 | 
 *  To compute transmissivity (tn) from transmittance (Tn) use: | 
| 30 | 
greg | 
1.1 | 
 * | 
| 31 | 
  | 
  | 
 *      tn = (sqrt(.8402528435+.0072522239*Tn*Tn)-.9166530661)/.0036261119/Tn | 
| 32 | 
  | 
  | 
 * | 
| 33 | 
greg | 
2.5 | 
 *  The transmissivity of standard 88% transmittance glass is 0.96. | 
| 34 | 
greg | 
1.12 | 
 *  A refractive index other than the default can be used by giving | 
| 35 | 
  | 
  | 
 *  it as the fourth real argument.  The above formula no longer applies. | 
| 36 | 
  | 
  | 
 * | 
| 37 | 
greg | 
1.1 | 
 *  If we appear to hit the back side of the surface, then we | 
| 38 | 
  | 
  | 
 *  turn the normal around. | 
| 39 | 
  | 
  | 
 */ | 
| 40 | 
  | 
  | 
 | 
| 41 | 
  | 
  | 
#define  RINDEX         1.52            /* refractive index of glass */ | 
| 42 | 
  | 
  | 
 | 
| 43 | 
  | 
  | 
 | 
| 44 | 
  | 
  | 
m_glass(m, r)           /* color a ray which hit a thin glass surface */ | 
| 45 | 
  | 
  | 
OBJREC  *m; | 
| 46 | 
  | 
  | 
register RAY  *r; | 
| 47 | 
  | 
  | 
{ | 
| 48 | 
  | 
  | 
        COLOR  mcolor; | 
| 49 | 
  | 
  | 
        double  pdot; | 
| 50 | 
  | 
  | 
        FVECT  pnorm; | 
| 51 | 
greg | 
1.12 | 
        double  rindex, cos2; | 
| 52 | 
greg | 
1.1 | 
        COLOR  trans, refl; | 
| 53 | 
greg | 
2.8 | 
        int  hastexture; | 
| 54 | 
greg | 
1.11 | 
        double  d, r1e, r1m; | 
| 55 | 
greg | 
1.7 | 
        double  transtest, transdist; | 
| 56 | 
greg | 
2.8 | 
        double  mirtest, mirdist; | 
| 57 | 
greg | 
1.1 | 
        RAY  p; | 
| 58 | 
  | 
  | 
        register int  i; | 
| 59 | 
greg | 
1.12 | 
                                                /* check arguments */ | 
| 60 | 
  | 
  | 
        if (m->oargs.nfargs == 3) | 
| 61 | 
  | 
  | 
                rindex = RINDEX;                /* default value of n */ | 
| 62 | 
  | 
  | 
        else if (m->oargs.nfargs == 4) | 
| 63 | 
  | 
  | 
                rindex = m->oargs.farg[3];      /* use their value */ | 
| 64 | 
  | 
  | 
        else | 
| 65 | 
greg | 
1.1 | 
                objerror(m, USER, "bad arguments"); | 
| 66 | 
  | 
  | 
 | 
| 67 | 
  | 
  | 
        setcolor(mcolor, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); | 
| 68 | 
  | 
  | 
 | 
| 69 | 
  | 
  | 
        if (r->rod < 0.0)                       /* reorient if necessary */ | 
| 70 | 
  | 
  | 
                flipsurface(r); | 
| 71 | 
greg | 
2.8 | 
        mirtest = transtest = 0; | 
| 72 | 
  | 
  | 
        mirdist = transdist = r->rot; | 
| 73 | 
greg | 
1.1 | 
                                                /* get modifiers */ | 
| 74 | 
  | 
  | 
        raytexture(r, m->omod); | 
| 75 | 
greg | 
2.8 | 
        if (hastexture = DOT(r->pert,r->pert) > FTINY*FTINY) | 
| 76 | 
  | 
  | 
                pdot = raynormal(pnorm, r); | 
| 77 | 
  | 
  | 
        else { | 
| 78 | 
  | 
  | 
                VCOPY(pnorm, r->ron); | 
| 79 | 
  | 
  | 
                pdot = r->rod; | 
| 80 | 
  | 
  | 
        } | 
| 81 | 
greg | 
1.1 | 
                                                /* angular transmission */ | 
| 82 | 
greg | 
1.12 | 
        cos2 = sqrt( (1.0-1.0/(rindex*rindex)) + | 
| 83 | 
  | 
  | 
                     pdot*pdot/(rindex*rindex) ); | 
| 84 | 
greg | 
1.1 | 
        setcolor(mcolor, pow(colval(mcolor,RED), 1.0/cos2), | 
| 85 | 
  | 
  | 
                         pow(colval(mcolor,GRN), 1.0/cos2), | 
| 86 | 
  | 
  | 
                         pow(colval(mcolor,BLU), 1.0/cos2)); | 
| 87 | 
  | 
  | 
 | 
| 88 | 
  | 
  | 
                                                /* compute reflection */ | 
| 89 | 
greg | 
1.12 | 
        r1e = (pdot - rindex*cos2) / (pdot + rindex*cos2); | 
| 90 | 
greg | 
1.11 | 
        r1e *= r1e; | 
| 91 | 
greg | 
1.12 | 
        r1m = (1.0/pdot - rindex/cos2) / (1.0/pdot + rindex/cos2); | 
| 92 | 
greg | 
1.11 | 
        r1m *= r1m; | 
| 93 | 
greg | 
1.1 | 
                                                /* compute transmittance */ | 
| 94 | 
  | 
  | 
        for (i = 0; i < 3; i++) { | 
| 95 | 
  | 
  | 
                d = colval(mcolor, i); | 
| 96 | 
greg | 
1.11 | 
                colval(trans,i) = .5*(1.0-r1e)*(1.0-r1e)*d/(1.0-r1e*r1e*d*d); | 
| 97 | 
  | 
  | 
                colval(trans,i) += .5*(1.0-r1m)*(1.0-r1m)*d/(1.0-r1m*r1m*d*d); | 
| 98 | 
greg | 
1.1 | 
        } | 
| 99 | 
  | 
  | 
                                                /* transmitted ray */ | 
| 100 | 
greg | 
1.2 | 
        if (rayorigin(&p, r, TRANS, bright(trans)) == 0) { | 
| 101 | 
greg | 
2.8 | 
                if (!(r->crtype & SHADOW) && hastexture) { | 
| 102 | 
greg | 
1.7 | 
                        for (i = 0; i < 3; i++)         /* perturb direction */ | 
| 103 | 
greg | 
2.2 | 
                                p.rdir[i] = r->rdir[i] + | 
| 104 | 
  | 
  | 
                                                2.*(1.-rindex)*r->pert[i]; | 
| 105 | 
greg | 
2.4 | 
                        if (normalize(p.rdir) == 0.0) { | 
| 106 | 
  | 
  | 
                                objerror(m, WARNING, "bad perturbation"); | 
| 107 | 
  | 
  | 
                                VCOPY(p.rdir, r->rdir); | 
| 108 | 
  | 
  | 
                        } | 
| 109 | 
greg | 
1.8 | 
                } else { | 
| 110 | 
  | 
  | 
                        VCOPY(p.rdir, r->rdir); | 
| 111 | 
greg | 
1.7 | 
                        transtest = 2; | 
| 112 | 
greg | 
1.8 | 
                } | 
| 113 | 
greg | 
1.1 | 
                rayvalue(&p); | 
| 114 | 
  | 
  | 
                multcolor(p.rcol, r->pcol);     /* modify */ | 
| 115 | 
  | 
  | 
                multcolor(p.rcol, trans); | 
| 116 | 
  | 
  | 
                addcolor(r->rcol, p.rcol); | 
| 117 | 
greg | 
1.7 | 
                transtest *= bright(p.rcol); | 
| 118 | 
  | 
  | 
                transdist = r->rot + p.rt; | 
| 119 | 
greg | 
1.1 | 
        } | 
| 120 | 
greg | 
1.3 | 
 | 
| 121 | 
greg | 
2.8 | 
        if (r->crtype & SHADOW) {               /* skip reflected ray */ | 
| 122 | 
  | 
  | 
                r->rt = transdist; | 
| 123 | 
greg | 
2.7 | 
                return(1); | 
| 124 | 
greg | 
2.8 | 
        } | 
| 125 | 
greg | 
1.1 | 
                                                /* compute reflectance */ | 
| 126 | 
  | 
  | 
        for (i = 0; i < 3; i++) { | 
| 127 | 
  | 
  | 
                d = colval(mcolor, i); | 
| 128 | 
  | 
  | 
                d *= d; | 
| 129 | 
greg | 
1.11 | 
                colval(refl,i) = .5*r1e*(1.0+(1.0-2.0*r1e)*d)/(1.0-r1e*r1e*d); | 
| 130 | 
  | 
  | 
                colval(refl,i) += .5*r1m*(1.0+(1.0-2.0*r1m)*d)/(1.0-r1m*r1m*d); | 
| 131 | 
greg | 
1.1 | 
        } | 
| 132 | 
  | 
  | 
                                                /* reflected ray */ | 
| 133 | 
greg | 
1.2 | 
        if (rayorigin(&p, r, REFLECTED, bright(refl)) == 0) { | 
| 134 | 
greg | 
1.1 | 
                for (i = 0; i < 3; i++) | 
| 135 | 
  | 
  | 
                        p.rdir[i] = r->rdir[i] + 2.0*pdot*pnorm[i]; | 
| 136 | 
  | 
  | 
                rayvalue(&p); | 
| 137 | 
  | 
  | 
                multcolor(p.rcol, refl); | 
| 138 | 
  | 
  | 
                addcolor(r->rcol, p.rcol); | 
| 139 | 
greg | 
2.8 | 
                if (!hastexture && r->ro != NULL && isflat(r->ro->otype)) { | 
| 140 | 
  | 
  | 
                        mirtest = 2.0*bright(p.rcol); | 
| 141 | 
  | 
  | 
                        mirdist = r->rot + p.rt; | 
| 142 | 
  | 
  | 
                } | 
| 143 | 
greg | 
1.1 | 
        } | 
| 144 | 
greg | 
2.8 | 
                                        /* check distance */ | 
| 145 | 
  | 
  | 
        d = bright(r->rcol); | 
| 146 | 
  | 
  | 
        if (transtest > d) | 
| 147 | 
greg | 
1.7 | 
                r->rt = transdist; | 
| 148 | 
greg | 
2.8 | 
        else if (mirtest > d) | 
| 149 | 
  | 
  | 
                r->rt = mirdist; | 
| 150 | 
greg | 
2.7 | 
        return(1); | 
| 151 | 
greg | 
1.1 | 
} |