ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_direct.c
Revision: 2.13
Committed: Tue Apr 19 01:15:06 2005 UTC (19 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad4R1, rad4R0, rad3R8, rad3R9
Changes since 2.12: +6 -5 lines
Log Message:
Extensive changes to enable rtrace -oTW option for tracking ray contributions

File Contents

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