ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_mist.c
Revision: 2.9
Committed: Wed May 28 14:38:32 1997 UTC (26 years, 11 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.8: +3 -2 lines
Log Message:
made source list overflow an internal error

File Contents

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