ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_mist.c
Revision: 2.11
Committed: Tue Feb 25 02:47:22 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.10: +1 -56 lines
Log Message:
Replaced inline copyright notice with #include "copyright.h"

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