ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_mist.c
Revision: 2.4
Committed: Sun Dec 17 11:51:47 1995 UTC (28 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +1 -2 lines
Log Message:
bug fixes related to M_MIST type and source scattering
added MAXSSAMP macro to limit number of scatter samples

File Contents

# User Rev Content
1 greg 2.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 [gecc]]]
37     *
38     * The primaries indicate medium extinction per unit length (absorption
39     * plus scattering). 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     #define RELAYDELIM '>' /* relay delimiter character */
47    
48     extern COLOR cextinction; /* global coefficient of extinction */
49     extern double salbedo; /* global scattering albedo */
50     extern double seccg; /* global scattering eccentricity */
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 greg 2.2 srcmatch(sp, id) /* check for an id match on a light source */
69     register SRCREC *sp;
70     register char *id;
71 greg 2.1 {
72     extern char *index();
73     register char *cp;
74 greg 2.2 /* check for relay sources */
75     while ((cp = index(id, RELAYDELIM)) != NULL) {
76     if (!(sp->sflags & SVIRTUAL) || sp->so == NULL)
77 greg 2.1 return(0);
78 greg 2.2 if (strncmp(id, sp->so->oname, cp-id) || sp->so->oname[cp-id])
79 greg 2.1 return(0);
80 greg 2.2 id = cp + 1; /* relay to next */
81     sp = source + sp->sa.sv.sn;
82 greg 2.1 }
83 greg 2.2 if (sp->sflags & SVIRTUAL || sp->so == NULL)
84 greg 2.1 return(0);
85 greg 2.2 return(!strcmp(id, sp->so->oname));
86 greg 2.1 }
87    
88    
89 greg 2.2 static
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(USER, "scattering source list overflow");
105     r->slights[++r->slights[0]] = sl[i];
106     }
107     }
108    
109    
110 greg 2.1 m_mist(m, r) /* process a ray entering or leaving some mist */
111     OBJREC *m;
112     register RAY *r;
113     {
114     RAY p;
115     int *myslist = NULL;
116     int newslist[MAXSLIST+1];
117     COLOR mext;
118     double re, ge, be;
119     register int i, j;
120     /* check arguments */
121     if (m->oargs.nfargs > 5)
122     objerror(m, USER, "bad arguments");
123     /* get source indices */
124 greg 2.4 if (m->oargs.nsargs > 0 && (myslist = (int *)m->os) == NULL) {
125 greg 2.2 if (m->oargs.nsargs > MAXSLIST)
126     objerror(m, USER, "too many sources in list");
127 greg 2.1 myslist = (int *)malloc((m->oargs.nsargs+1)*sizeof(int));
128     if (myslist == NULL)
129     goto memerr;
130 greg 2.2 myslist[0] = 0; /* size is first in list */
131     for (j = 0; j < m->oargs.nsargs; j++) {
132 greg 2.1 i = nsources; /* look up each source id */
133     while (i--)
134 greg 2.2 if (srcmatch(source+i, m->oargs.sarg[j]))
135 greg 2.1 break;
136     if (i < 0) {
137     sprintf(errmsg, "unknown source \"%s\"",
138 greg 2.2 m->oargs.sarg[j]);
139 greg 2.1 objerror(m, WARNING, errmsg);
140 greg 2.2 } else if (inslist(myslist, i)) {
141     sprintf(errmsg, "duplicate source \"%s\"",
142     m->oargs.sarg[j]);
143     objerror(m, WARNING, errmsg);
144 greg 2.1 } else
145 greg 2.2 myslist[++myslist[0]] = i;
146 greg 2.1 }
147     m->os = (char *)myslist;
148     }
149     if (m->oargs.nfargs > 2) { /* compute extinction */
150     setcolor(mext, m->oargs.farg[0], m->oargs.farg[1],
151     m->oargs.farg[2]);
152     raytexture(r, m->omod); /* get modifiers */
153     multcolor(mext, r->pcol);
154     } else
155     setcolor(mext, 0., 0., 0.);
156     /* start transmitted ray */
157     if (rayorigin(&p, r, TRANS, 1.) < 0)
158     return(1);
159     VCOPY(p.rdir, r->rdir);
160     p.slights = newslist;
161 greg 2.2 if (r->slights != NULL) /* copy old list if one */
162 greg 2.1 for (j = r->slights[0]; j >= 0; j--)
163     p.slights[j] = r->slights[j];
164     else
165     p.slights[0] = 0;
166     if (r->rod > 0.) { /* entering ray */
167     addcolor(p.cext, mext);
168     if (m->oargs.nfargs > 3)
169     p.albedo = m->oargs.farg[3];
170     if (m->oargs.nfargs > 4)
171     p.gecc = m->oargs.farg[4];
172 greg 2.2 add2slist(&p, myslist); /* add to list */
173     } else { /* leaving ray */
174     if (myslist != NULL) { /* delete from list */
175 greg 2.1 for (j = myslist[0]; j > 0; j--)
176 greg 2.2 if (i = inslist(p.slights, myslist[j]))
177     p.slights[i] = -1;
178     for (i = 0, j = 1; j <= p.slights[0]; j++)
179     if (p.slights[j] != -1)
180     p.slights[++i] = p.slights[j];
181     if (p.slights[0] - i < myslist[0]) { /* fix old */
182     addcolor(r->cext, mext);
183     if (m->oargs.nfargs > 3)
184     r->albedo = m->oargs.farg[3];
185     if (m->oargs.nfargs > 4)
186     r->gecc = m->oargs.farg[4];
187     add2slist(r, myslist);
188     }
189     p.slights[0] = i;
190     }
191 greg 2.1 re = colval(r->cext,RED) - colval(mext,RED);
192     ge = colval(r->cext,GRN) - colval(mext,GRN);
193     be = colval(r->cext,BLU) - colval(mext,BLU);
194     setcolor(p.cext, re<0. ? 0. : re,
195     ge<0. ? 0. : ge,
196     be<0. ? 0. : be);
197     if (m->oargs.nfargs > 3)
198     p.albedo = salbedo;
199     if (m->oargs.nfargs > 4)
200     p.gecc = seccg;
201     }
202     rayvalue(&p); /* calls rayparticipate() */
203     copycolor(r->rcol, p.rcol); /* return value */
204     r->rt = r->rot + p.rt;
205     return(1);
206     memerr:
207     error(SYSTEM, "out of memory in m_mist");
208     }