ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_mist.c
Revision: 2.10
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.9: +60 -9 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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.10 static const char RCSid[] = "$Id$";
3 greg 2.1 #endif
4     /*
5     * Mist volumetric material.
6     */
7    
8 greg 2.10 /* ====================================================================
9     * The Radiance Software License, Version 1.0
10     *
11     * Copyright (c) 1990 - 2002 The Regents of the University of California,
12     * through Lawrence Berkeley National Laboratory. All rights reserved.
13     *
14     * Redistribution and use in source and binary forms, with or without
15     * modification, are permitted provided that the following conditions
16     * are met:
17     *
18     * 1. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 2. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in
23     * the documentation and/or other materials provided with the
24     * distribution.
25     *
26     * 3. The end-user documentation included with the redistribution,
27     * if any, must include the following acknowledgment:
28     * "This product includes Radiance software
29     * (http://radsite.lbl.gov/)
30     * developed by the Lawrence Berkeley National Laboratory
31     * (http://www.lbl.gov/)."
32     * Alternately, this acknowledgment may appear in the software itself,
33     * if and wherever such third-party acknowledgments normally appear.
34     *
35     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36     * and "The Regents of the University of California" must
37     * not be used to endorse or promote products derived from this
38     * software without prior written permission. For written
39     * permission, please contact [email protected].
40     *
41     * 5. Products derived from this software may not be called "Radiance",
42     * nor may "Radiance" appear in their name, without prior written
43     * permission of Lawrence Berkeley National Laboratory.
44     *
45     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56     * SUCH DAMAGE.
57     * ====================================================================
58     *
59     * This software consists of voluntary contributions made by many
60     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
61     * information on Lawrence Berkeley National Laboratory, please see
62     * <http://www.lbl.gov/>.
63     */
64    
65 greg 2.1 #include "ray.h"
66    
67     #include "source.h"
68    
69     /*
70     * A mist volume is used to specify a region in the scene where a certain
71     * light source (or sources) is going to contribute to scattering. The
72     * material can add to the existing global medium, and override any ray
73     * settings for scattering albedo and eccentricity. Overlapping mist
74     * regions should agree w.r.t. albedo and eccentricity, and
75     * should have disjoint source lists.
76     *
77     * A pattern, if used, should compute the line integral of extinction,
78     * and will modify the first three arguments directly. This will tend
79     * to invalidate results when there are other objects intersected within
80     * the mist region.
81     *
82     * The string arguments for MAT_MIST are the identifiers for the important
83     * light sources, which will be looked up in the source array. The last
84     * source found matching a name is the one used. A relayed light source
85     * may be indicated by the relay surface name, followed by a '>' character,
86     * followed by the relayed source name (which may be another relay).
87     *
88     * Up to five real arguments may be given for MAT_MIST:
89     *
90 greg 2.6 * [ext_r ext_g ext_b [albedo_r albedo_g albedo_b [gecc]]]
91 greg 2.1 *
92     * The primaries indicate medium extinction per unit length (absorption
93 greg 2.5 * plus scattering), which is added to the global extinction coefficient, set
94     * by the -me option. The albedo is the ratio of scattering to extinction,
95 greg 2.1 * and is set globally by the -ma option (salbedo) and overridden here.
96     * The Heyney-Greenstein eccentricity parameter (-mg seccg) indicates how much
97     * scattering favors the forward direction. A value of 0 means isotropic
98     * scattering. A value approaching 1 indicates strong forward scattering.
99     */
100    
101 greg 2.7 #ifndef MAXSLIST
102     #define MAXSLIST 32 /* maximum sources to check */
103     #endif
104    
105 greg 2.1 #define RELAYDELIM '>' /* relay delimiter character */
106    
107    
108     static int
109     inslist(sl, n) /* return index of source n if it's in list sl */
110     register int *sl;
111     register int n;
112     {
113     register int i;
114    
115     for (i = sl[0]; i > 0; i--)
116     if (sl[i] == n)
117     return(i);
118     return(0);
119     }
120    
121    
122     static int
123 greg 2.2 srcmatch(sp, id) /* check for an id match on a light source */
124     register SRCREC *sp;
125     register char *id;
126 greg 2.1 {
127     extern char *index();
128     register char *cp;
129 greg 2.2 /* check for relay sources */
130     while ((cp = index(id, RELAYDELIM)) != NULL) {
131     if (!(sp->sflags & SVIRTUAL) || sp->so == NULL)
132 greg 2.1 return(0);
133 greg 2.2 if (strncmp(id, sp->so->oname, cp-id) || sp->so->oname[cp-id])
134 greg 2.1 return(0);
135 greg 2.2 id = cp + 1; /* relay to next */
136     sp = source + sp->sa.sv.sn;
137 greg 2.1 }
138 greg 2.2 if (sp->sflags & SVIRTUAL || sp->so == NULL)
139 greg 2.1 return(0);
140 greg 2.2 return(!strcmp(id, sp->so->oname));
141 greg 2.1 }
142    
143    
144 greg 2.10 static void
145 greg 2.2 add2slist(r, sl) /* add source list to ray's */
146     register RAY *r;
147     register int *sl;
148     {
149     static int slspare[MAXSLIST+1]; /* in case of emergence */
150     register int i;
151    
152     if (sl == NULL || sl[0] == 0) /* nothing to add */
153     return;
154     if (r->slights == NULL)
155     (r->slights = slspare)[0] = 0; /* just once per ray path */
156     for (i = sl[0]; i > 0; i--)
157     if (!inslist(r->slights, sl[i])) {
158     if (r->slights[0] >= MAXSLIST)
159 gregl 2.9 error(INTERNAL,
160     "scattering source list overflow");
161 greg 2.2 r->slights[++r->slights[0]] = sl[i];
162     }
163     }
164    
165    
166 greg 2.10 int
167 greg 2.1 m_mist(m, r) /* process a ray entering or leaving some mist */
168     OBJREC *m;
169     register RAY *r;
170     {
171     RAY p;
172     int *myslist = NULL;
173     int newslist[MAXSLIST+1];
174     COLOR mext;
175     double re, ge, be;
176     register int i, j;
177     /* check arguments */
178 greg 2.8 if (m->oargs.nfargs > 7)
179 greg 2.1 objerror(m, USER, "bad arguments");
180     /* get source indices */
181 greg 2.4 if (m->oargs.nsargs > 0 && (myslist = (int *)m->os) == NULL) {
182 greg 2.2 if (m->oargs.nsargs > MAXSLIST)
183 gregl 2.9 objerror(m, INTERNAL, "too many sources in list");
184 greg 2.1 myslist = (int *)malloc((m->oargs.nsargs+1)*sizeof(int));
185     if (myslist == NULL)
186     goto memerr;
187 greg 2.2 myslist[0] = 0; /* size is first in list */
188     for (j = 0; j < m->oargs.nsargs; j++) {
189 greg 2.1 i = nsources; /* look up each source id */
190     while (i--)
191 greg 2.2 if (srcmatch(source+i, m->oargs.sarg[j]))
192 greg 2.1 break;
193     if (i < 0) {
194     sprintf(errmsg, "unknown source \"%s\"",
195 greg 2.2 m->oargs.sarg[j]);
196 greg 2.1 objerror(m, WARNING, errmsg);
197 greg 2.2 } else if (inslist(myslist, i)) {
198     sprintf(errmsg, "duplicate source \"%s\"",
199     m->oargs.sarg[j]);
200     objerror(m, WARNING, errmsg);
201 greg 2.1 } else
202 greg 2.2 myslist[++myslist[0]] = i;
203 greg 2.1 }
204     m->os = (char *)myslist;
205     }
206     if (m->oargs.nfargs > 2) { /* compute extinction */
207     setcolor(mext, m->oargs.farg[0], m->oargs.farg[1],
208     m->oargs.farg[2]);
209     raytexture(r, m->omod); /* get modifiers */
210     multcolor(mext, r->pcol);
211     } else
212     setcolor(mext, 0., 0., 0.);
213     /* start transmitted ray */
214     if (rayorigin(&p, r, TRANS, 1.) < 0)
215     return(1);
216     VCOPY(p.rdir, r->rdir);
217     p.slights = newslist;
218 greg 2.2 if (r->slights != NULL) /* copy old list if one */
219 greg 2.1 for (j = r->slights[0]; j >= 0; j--)
220     p.slights[j] = r->slights[j];
221     else
222     p.slights[0] = 0;
223     if (r->rod > 0.) { /* entering ray */
224     addcolor(p.cext, mext);
225 greg 2.6 if (m->oargs.nfargs > 5)
226     setcolor(p.albedo, m->oargs.farg[3],
227     m->oargs.farg[4], m->oargs.farg[5]);
228     if (m->oargs.nfargs > 6)
229     p.gecc = m->oargs.farg[6];
230 greg 2.2 add2slist(&p, myslist); /* add to list */
231     } else { /* leaving ray */
232     if (myslist != NULL) { /* delete from list */
233 greg 2.1 for (j = myslist[0]; j > 0; j--)
234 greg 2.2 if (i = inslist(p.slights, myslist[j]))
235     p.slights[i] = -1;
236     for (i = 0, j = 1; j <= p.slights[0]; j++)
237     if (p.slights[j] != -1)
238     p.slights[++i] = p.slights[j];
239     if (p.slights[0] - i < myslist[0]) { /* fix old */
240     addcolor(r->cext, mext);
241 greg 2.6 if (m->oargs.nfargs > 5)
242     setcolor(r->albedo, m->oargs.farg[3],
243     m->oargs.farg[4], m->oargs.farg[5]);
244     if (m->oargs.nfargs > 6)
245     r->gecc = m->oargs.farg[6];
246 greg 2.2 add2slist(r, myslist);
247     }
248     p.slights[0] = i;
249     }
250 greg 2.5 if ((re = colval(r->cext,RED) - colval(mext,RED)) <
251     colval(cextinction,RED))
252     re = colval(cextinction,RED);
253     if ((ge = colval(r->cext,GRN) - colval(mext,GRN)) <
254     colval(cextinction,GRN))
255     ge = colval(cextinction,GRN);
256     if ((be = colval(r->cext,BLU) - colval(mext,BLU)) <
257     colval(cextinction,BLU))
258     be = colval(cextinction,BLU);
259     setcolor(p.cext, re, ge, be);
260 greg 2.6 if (m->oargs.nfargs > 5)
261     copycolor(p.albedo, salbedo);
262     if (m->oargs.nfargs > 6)
263 greg 2.1 p.gecc = seccg;
264     }
265     rayvalue(&p); /* calls rayparticipate() */
266     copycolor(r->rcol, p.rcol); /* return value */
267     r->rt = r->rot + p.rt;
268     return(1);
269     memerr:
270     error(SYSTEM, "out of memory in m_mist");
271     }