ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_direct.c
Revision: 2.8
Committed: Sat Feb 22 02:07:28 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.7: +63 -5 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Routines for light-redirecting materials and
6 * their associated virtual light sources
7 */
8
9 /* ====================================================================
10 * The Radiance Software License, Version 1.0
11 *
12 * Copyright (c) 1990 - 2002 The Regents of the University of California,
13 * through Lawrence Berkeley National Laboratory. All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 *
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in
24 * the documentation and/or other materials provided with the
25 * distribution.
26 *
27 * 3. The end-user documentation included with the redistribution,
28 * if any, must include the following acknowledgment:
29 * "This product includes Radiance software
30 * (http://radsite.lbl.gov/)
31 * developed by the Lawrence Berkeley National Laboratory
32 * (http://www.lbl.gov/)."
33 * Alternately, this acknowledgment may appear in the software itself,
34 * if and wherever such third-party acknowledgments normally appear.
35 *
36 * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
37 * and "The Regents of the University of California" must
38 * not be used to endorse or promote products derived from this
39 * software without prior written permission. For written
40 * permission, please contact [email protected].
41 *
42 * 5. Products derived from this software may not be called "Radiance",
43 * nor may "Radiance" appear in their name, without prior written
44 * permission of Lawrence Berkeley National Laboratory.
45 *
46 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
47 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
49 * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
50 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
53 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
55 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
56 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 * ====================================================================
59 *
60 * This software consists of voluntary contributions made by many
61 * individuals on behalf of Lawrence Berkeley National Laboratory. For more
62 * information on Lawrence Berkeley National Laboratory, please see
63 * <http://www.lbl.gov/>.
64 */
65
66 #include "ray.h"
67
68 #include "otypes.h"
69
70 #include "source.h"
71
72 #include "func.h"
73
74 /*
75 * The arguments for MAT_DIRECT1 are:
76 *
77 * 5+ coef1 dx1 dy1 dz1 funcfile transform..
78 * 0
79 * n A1 A2 .. An
80 *
81 * The arguments for MAT_DIRECT2 are:
82 *
83 * 9+ coef1 dx1 dy1 dz1 coef2 dx2 dy2 dz2 funcfile transform..
84 * 0
85 * n A1 A2 .. An
86 */
87
88
89 static int dir_proj();
90
91 VSMATERIAL direct1_vs = {dir_proj, 1};
92 VSMATERIAL direct2_vs = {dir_proj, 2};
93
94 #define getdfunc(m) ( (m)->otype == MAT_DIRECT1 ? \
95 getfunc(m, 4, 0xf, 1) : \
96 getfunc(m, 8, 0xff, 1) )
97
98
99 int
100 m_direct(m, r) /* shade redirected ray */
101 register OBJREC *m;
102 register RAY *r;
103 {
104 /* check if source ray */
105 if (r->rsrc >= 0 && source[r->rsrc].so != r->ro)
106 return(1); /* got the wrong guy */
107 /* compute first projection */
108 if (m->otype == MAT_DIRECT1 ||
109 (r->rsrc < 0 || source[r->rsrc].sa.sv.pn == 0))
110 redirect(m, r, 0);
111 /* compute second projection */
112 if (m->otype == MAT_DIRECT2 &&
113 (r->rsrc < 0 || source[r->rsrc].sa.sv.pn == 1))
114 redirect(m, r, 1);
115 return(1);
116 }
117
118
119 int
120 redirect(m, r, n) /* compute n'th ray redirection */
121 OBJREC *m;
122 RAY *r;
123 int n;
124 {
125 MFUNC *mf;
126 register EPNODE **va;
127 FVECT nsdir;
128 RAY nr;
129 double coef;
130 register int j;
131 /* set up function */
132 mf = getdfunc(m);
133 setfunc(m, r);
134 /* assign direction variable */
135 if (r->rsrc >= 0) {
136 register SRCREC *sp = source + source[r->rsrc].sa.sv.sn;
137
138 if (sp->sflags & SDISTANT)
139 VCOPY(nsdir, sp->sloc);
140 else {
141 for (j = 0; j < 3; j++)
142 nsdir[j] = sp->sloc[j] - r->rop[j];
143 normalize(nsdir);
144 }
145 multv3(nsdir, nsdir, funcxf.xfm);
146 varset("DxA", '=', nsdir[0]/funcxf.sca);
147 varset("DyA", '=', nsdir[1]/funcxf.sca);
148 varset("DzA", '=', nsdir[2]/funcxf.sca);
149 } else {
150 varset("DxA", '=', 0.0);
151 varset("DyA", '=', 0.0);
152 varset("DzA", '=', 0.0);
153 }
154 /* compute coefficient */
155 errno = 0;
156 va = mf->ep + 4*n;
157 coef = evalue(va[0]);
158 if (errno)
159 goto computerr;
160 if (coef <= FTINY || rayorigin(&nr, r, TRANS, coef) < 0)
161 return(0);
162 va++; /* compute direction */
163 for (j = 0; j < 3; j++) {
164 nr.rdir[j] = evalue(va[j]);
165 if (errno)
166 goto computerr;
167 }
168 if (mf->f != &unitxf)
169 multv3(nr.rdir, nr.rdir, mf->f->xfm);
170 if (r->rox != NULL)
171 multv3(nr.rdir, nr.rdir, r->rox->f.xfm);
172 if (normalize(nr.rdir) == 0.0)
173 goto computerr;
174 /* compute value */
175 if (r->rsrc >= 0)
176 nr.rsrc = source[r->rsrc].sa.sv.sn;
177 rayvalue(&nr);
178 scalecolor(nr.rcol, coef);
179 addcolor(r->rcol, nr.rcol);
180 if (r->ro != NULL && isflat(r->ro->otype))
181 r->rt = r->rot + nr.rt;
182 return(1);
183 computerr:
184 objerror(m, WARNING, "compute error");
185 return(-1);
186 }
187
188
189 static int
190 dir_proj(pm, o, s, n) /* compute a director's projection */
191 MAT4 pm;
192 OBJREC *o;
193 SRCREC *s;
194 int n;
195 {
196 RAY tr;
197 OBJREC *m;
198 MFUNC *mf;
199 EPNODE **va;
200 FVECT cent, newdir, nv, h;
201 double coef, olddot, newdot, od;
202 register int i, j;
203 /* initialize test ray */
204 getmaxdisk(cent, o);
205 if (s->sflags & SDISTANT)
206 for (i = 0; i < 3; i++) {
207 tr.rdir[i] = -s->sloc[i];
208 tr.rorg[i] = cent[i] - tr.rdir[i];
209 }
210 else {
211 for (i = 0; i < 3; i++) {
212 tr.rdir[i] = cent[i] - s->sloc[i];
213 tr.rorg[i] = s->sloc[i];
214 }
215 if (normalize(tr.rdir) == 0.0)
216 return(0); /* at source! */
217 }
218 od = getplaneq(nv, o);
219 olddot = DOT(tr.rdir, nv);
220 if (olddot <= FTINY && olddot >= -FTINY)
221 return(0); /* old dir parallels plane */
222 tr.rmax = 0.0;
223 rayorigin(&tr, NULL, PRIMARY, 1.0);
224 if (!(*ofun[o->otype].funp)(o, &tr))
225 return(0); /* no intersection! */
226 /* compute redirection */
227 m = vsmaterial(o);
228 mf = getdfunc(m);
229 setfunc(m, &tr);
230 varset("DxA", '=', 0.0);
231 varset("DyA", '=', 0.0);
232 varset("DzA", '=', 0.0);
233 errno = 0;
234 va = mf->ep + 4*n;
235 coef = evalue(va[0]);
236 if (errno)
237 goto computerr;
238 if (coef <= FTINY)
239 return(0); /* insignificant */
240 va++;
241 for (i = 0; i < 3; i++) {
242 newdir[i] = evalue(va[i]);
243 if (errno)
244 goto computerr;
245 }
246 if (mf->f != &unitxf)
247 multv3(newdir, newdir, mf->f->xfm);
248 /* normalization unnecessary */
249 newdot = DOT(newdir, nv);
250 if (newdot <= FTINY && newdot >= -FTINY)
251 return(0); /* new dir parallels plane */
252 /* everything OK -- compute shear */
253 for (i = 0; i < 3; i++)
254 h[i] = newdir[i]/newdot - tr.rdir[i]/olddot;
255 setident4(pm);
256 for (j = 0; j < 3; j++) {
257 for (i = 0; i < 3; i++)
258 pm[i][j] += nv[i]*h[j];
259 pm[3][j] = -od*h[j];
260 }
261 if (newdot > 0.0 ^ olddot > 0.0) /* add mirroring */
262 for (j = 0; j < 3; j++) {
263 for (i = 0; i < 3; i++)
264 pm[i][j] -= 2.*nv[i]*nv[j];
265 pm[3][j] += 2.*od*nv[j];
266 }
267 return(1);
268 computerr:
269 objerror(m, WARNING, "projection compute error");
270 return(0);
271 }