ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_direct.c
Revision: 2.10
Committed: Wed Mar 5 16:16:53 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.9: +4 -4 lines
Log Message:
Made errno checking explicit after math calls to avoid spurious warnings

File Contents

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