ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_mist.c
Revision: 2.16
Committed: Tue Sep 28 17:54:19 2004 UTC (19 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6, rad3R6P1
Changes since 2.15: +1 -1 lines
Log Message:
Fixed messed-up RCCS Id at top of file

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Mist volumetric material.
6 */
7
8 #include "copyright.h"
9
10 #include <string.h>
11
12 #include "ray.h"
13 #include "source.h"
14 #include "rtotypes.h"
15
16 /*
17 * A mist volume is used to specify a region in the scene where a certain
18 * light source (or sources) is going to contribute to scattering. The
19 * material can add to the existing global medium, and override any ray
20 * settings for scattering albedo and eccentricity. Overlapping mist
21 * regions should agree w.r.t. albedo and eccentricity, and
22 * should have disjoint source lists.
23 *
24 * A pattern, if used, should compute the line integral of extinction,
25 * and will modify the first three arguments directly. This will tend
26 * to invalidate results when there are other objects intersected within
27 * the mist region.
28 *
29 * The string arguments for MAT_MIST are the identifiers for the important
30 * light sources, which will be looked up in the source array. The last
31 * source found matching a name is the one used. A relayed light source
32 * may be indicated by the relay surface name, followed by a '>' character,
33 * followed by the relayed source name (which may be another relay).
34 *
35 * Up to five real arguments may be given for MAT_MIST:
36 *
37 * [ext_r ext_g ext_b [albedo_r albedo_g albedo_b [gecc]]]
38 *
39 * The primaries indicate medium extinction per unit length (absorption
40 * plus scattering), which is added to the global extinction coefficient, set
41 * by the -me option. The albedo is the ratio of scattering to extinction,
42 * and is set globally by the -ma option (salbedo) and overridden here.
43 * The Heyney-Greenstein eccentricity parameter (-mg seccg) indicates how much
44 * scattering favors the forward direction. A value of 0 means isotropic
45 * scattering. A value approaching 1 indicates strong forward scattering.
46 */
47
48 #ifndef MAXSLIST
49 #define MAXSLIST 32 /* maximum sources to check */
50 #endif
51
52 #define RELAYDELIM '>' /* relay delimiter character */
53
54 static int inslist(int *sl, int n);
55 static int srcmatch(SRCREC *sp, char *id);
56 static void add2slist(RAY *r, int *sl);
57
58
59 static int
60 inslist( /* return index of source n if it's in list sl */
61 register int *sl,
62 register int n
63 )
64 {
65 register int i;
66
67 for (i = sl[0]; i > 0; i--)
68 if (sl[i] == n)
69 return(i);
70 return(0);
71 }
72
73
74 static int
75 srcmatch( /* check for an id match on a light source */
76 register SRCREC *sp,
77 register char *id
78 )
79 {
80 register char *cp;
81 /* check for relay sources */
82 while ((cp = strchr(id, RELAYDELIM)) != NULL) {
83 if (!(sp->sflags & SVIRTUAL) || sp->so == NULL)
84 return(0);
85 if (strncmp(id, sp->so->oname, cp-id) || sp->so->oname[cp-id])
86 return(0);
87 id = cp + 1; /* relay to next */
88 sp = source + sp->sa.sv.sn;
89 }
90 if (sp->sflags & SVIRTUAL || sp->so == NULL)
91 return(0);
92 return(!strcmp(id, sp->so->oname));
93 }
94
95
96 static void
97 add2slist( /* add source list to ray's */
98 register RAY *r,
99 register int *sl
100 )
101 {
102 static int slspare[MAXSLIST+1]; /* in case of emergence */
103 register int i;
104
105 if (sl == NULL || sl[0] == 0) /* nothing to add */
106 return;
107 if (r->slights == NULL)
108 (r->slights = slspare)[0] = 0; /* just once per ray path */
109 for (i = sl[0]; i > 0; i--)
110 if (!inslist(r->slights, sl[i])) {
111 if (r->slights[0] >= MAXSLIST)
112 error(INTERNAL,
113 "scattering source list overflow");
114 r->slights[++r->slights[0]] = sl[i];
115 }
116 }
117
118
119 extern int
120 m_mist( /* process a ray entering or leaving some mist */
121 OBJREC *m,
122 register RAY *r
123 )
124 {
125 RAY p;
126 int *myslist = NULL;
127 int newslist[MAXSLIST+1];
128 COLOR mext;
129 double re, ge, be;
130 register int i, j;
131 /* check arguments */
132 if (m->oargs.nfargs > 7)
133 objerror(m, USER, "bad arguments");
134 /* get source indices */
135 if (m->oargs.nsargs > 0 && (myslist = (int *)m->os) == NULL) {
136 if (m->oargs.nsargs > MAXSLIST)
137 objerror(m, INTERNAL, "too many sources in list");
138 myslist = (int *)malloc((m->oargs.nsargs+1)*sizeof(int));
139 if (myslist == NULL)
140 goto memerr;
141 myslist[0] = 0; /* size is first in list */
142 for (j = 0; j < m->oargs.nsargs; j++) {
143 i = nsources; /* look up each source id */
144 while (i--)
145 if (srcmatch(source+i, m->oargs.sarg[j]))
146 break;
147 if (i < 0) {
148 sprintf(errmsg, "unknown source \"%s\"",
149 m->oargs.sarg[j]);
150 objerror(m, WARNING, errmsg);
151 } else if (inslist(myslist, i)) {
152 sprintf(errmsg, "duplicate source \"%s\"",
153 m->oargs.sarg[j]);
154 objerror(m, WARNING, errmsg);
155 } else
156 myslist[++myslist[0]] = i;
157 }
158 m->os = (char *)myslist;
159 }
160 if (m->oargs.nfargs > 2) { /* compute extinction */
161 setcolor(mext, m->oargs.farg[0], m->oargs.farg[1],
162 m->oargs.farg[2]);
163 raytexture(r, m->omod); /* get modifiers */
164 multcolor(mext, r->pcol);
165 } else
166 setcolor(mext, 0., 0., 0.);
167 /* start transmitted ray */
168 if (rayorigin(&p, r, TRANS, 1.) < 0)
169 return(1);
170 VCOPY(p.rdir, r->rdir);
171 p.slights = newslist;
172 if (r->slights != NULL) /* copy old list if one */
173 for (j = r->slights[0]; j >= 0; j--)
174 p.slights[j] = r->slights[j];
175 else
176 p.slights[0] = 0;
177 if (r->rod > 0.) { /* entering ray */
178 addcolor(p.cext, mext);
179 if (m->oargs.nfargs > 5)
180 setcolor(p.albedo, m->oargs.farg[3],
181 m->oargs.farg[4], m->oargs.farg[5]);
182 if (m->oargs.nfargs > 6)
183 p.gecc = m->oargs.farg[6];
184 add2slist(&p, myslist); /* add to list */
185 } else { /* leaving ray */
186 if (myslist != NULL) { /* delete from list */
187 for (j = myslist[0]; j > 0; j--)
188 if ( (i = inslist(p.slights, myslist[j])) )
189 p.slights[i] = -1;
190 for (i = 0, j = 1; j <= p.slights[0]; j++)
191 if (p.slights[j] != -1)
192 p.slights[++i] = p.slights[j];
193 if (p.slights[0] - i < myslist[0]) { /* fix old */
194 addcolor(r->cext, mext);
195 if (m->oargs.nfargs > 5)
196 setcolor(r->albedo, m->oargs.farg[3],
197 m->oargs.farg[4], m->oargs.farg[5]);
198 if (m->oargs.nfargs > 6)
199 r->gecc = m->oargs.farg[6];
200 add2slist(r, myslist);
201 }
202 p.slights[0] = i;
203 }
204 if ((re = colval(r->cext,RED) - colval(mext,RED)) <
205 colval(cextinction,RED))
206 re = colval(cextinction,RED);
207 if ((ge = colval(r->cext,GRN) - colval(mext,GRN)) <
208 colval(cextinction,GRN))
209 ge = colval(cextinction,GRN);
210 if ((be = colval(r->cext,BLU) - colval(mext,BLU)) <
211 colval(cextinction,BLU))
212 be = colval(cextinction,BLU);
213 setcolor(p.cext, re, ge, be);
214 if (m->oargs.nfargs > 5)
215 copycolor(p.albedo, salbedo);
216 if (m->oargs.nfargs > 6)
217 p.gecc = seccg;
218 }
219 rayvalue(&p); /* calls rayparticipate() */
220 copycolor(r->rcol, p.rcol); /* return value */
221 r->rt = r->rot + p.rt;
222 return(1);
223 memerr:
224 error(SYSTEM, "out of memory in m_mist");
225 return 0; /* pro forma return */
226 }