ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_mist.c
Revision: 2.15
Committed: Tue Mar 30 16:13:01 2004 UTC (20 years, 1 month ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.14: +23 -13 lines
Log Message:
Continued ANSIfication. There are only bits and pieces left now.

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.12 static const char RCSid[] = "$Id";
3 greg 2.1 #endif
4     /*
5     * Mist volumetric material.
6     */
7    
8 greg 2.11 #include "copyright.h"
9 greg 2.10
10 schorsch 2.13 #include <string.h>
11    
12 greg 2.1 #include "ray.h"
13     #include "source.h"
14 schorsch 2.15 #include "rtotypes.h"
15 greg 2.1
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 greg 2.6 * [ext_r ext_g ext_b [albedo_r albedo_g albedo_b [gecc]]]
38 greg 2.1 *
39     * The primaries indicate medium extinction per unit length (absorption
40 greg 2.5 * 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 greg 2.1 * 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 greg 2.7 #ifndef MAXSLIST
49     #define MAXSLIST 32 /* maximum sources to check */
50     #endif
51    
52 greg 2.1 #define RELAYDELIM '>' /* relay delimiter character */
53    
54 schorsch 2.15 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 greg 2.1
59     static int
60 schorsch 2.15 inslist( /* return index of source n if it's in list sl */
61     register int *sl,
62     register int n
63     )
64 greg 2.1 {
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 schorsch 2.15 srcmatch( /* check for an id match on a light source */
76     register SRCREC *sp,
77     register char *id
78     )
79 greg 2.1 {
80     register char *cp;
81 greg 2.2 /* check for relay sources */
82 schorsch 2.13 while ((cp = strchr(id, RELAYDELIM)) != NULL) {
83 greg 2.2 if (!(sp->sflags & SVIRTUAL) || sp->so == NULL)
84 greg 2.1 return(0);
85 greg 2.2 if (strncmp(id, sp->so->oname, cp-id) || sp->so->oname[cp-id])
86 greg 2.1 return(0);
87 greg 2.2 id = cp + 1; /* relay to next */
88     sp = source + sp->sa.sv.sn;
89 greg 2.1 }
90 greg 2.2 if (sp->sflags & SVIRTUAL || sp->so == NULL)
91 greg 2.1 return(0);
92 greg 2.2 return(!strcmp(id, sp->so->oname));
93 greg 2.1 }
94    
95    
96 greg 2.10 static void
97 schorsch 2.15 add2slist( /* add source list to ray's */
98     register RAY *r,
99     register int *sl
100     )
101 greg 2.2 {
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 gregl 2.9 error(INTERNAL,
113     "scattering source list overflow");
114 greg 2.2 r->slights[++r->slights[0]] = sl[i];
115     }
116     }
117    
118    
119 schorsch 2.15 extern int
120     m_mist( /* process a ray entering or leaving some mist */
121     OBJREC *m,
122     register RAY *r
123     )
124 greg 2.1 {
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 greg 2.8 if (m->oargs.nfargs > 7)
133 greg 2.1 objerror(m, USER, "bad arguments");
134     /* get source indices */
135 greg 2.4 if (m->oargs.nsargs > 0 && (myslist = (int *)m->os) == NULL) {
136 greg 2.2 if (m->oargs.nsargs > MAXSLIST)
137 gregl 2.9 objerror(m, INTERNAL, "too many sources in list");
138 greg 2.1 myslist = (int *)malloc((m->oargs.nsargs+1)*sizeof(int));
139     if (myslist == NULL)
140     goto memerr;
141 greg 2.2 myslist[0] = 0; /* size is first in list */
142     for (j = 0; j < m->oargs.nsargs; j++) {
143 greg 2.1 i = nsources; /* look up each source id */
144     while (i--)
145 greg 2.2 if (srcmatch(source+i, m->oargs.sarg[j]))
146 greg 2.1 break;
147     if (i < 0) {
148     sprintf(errmsg, "unknown source \"%s\"",
149 greg 2.2 m->oargs.sarg[j]);
150 greg 2.1 objerror(m, WARNING, errmsg);
151 greg 2.2 } else if (inslist(myslist, i)) {
152     sprintf(errmsg, "duplicate source \"%s\"",
153     m->oargs.sarg[j]);
154     objerror(m, WARNING, errmsg);
155 greg 2.1 } else
156 greg 2.2 myslist[++myslist[0]] = i;
157 greg 2.1 }
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 greg 2.2 if (r->slights != NULL) /* copy old list if one */
173 greg 2.1 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 greg 2.6 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 greg 2.2 add2slist(&p, myslist); /* add to list */
185     } else { /* leaving ray */
186     if (myslist != NULL) { /* delete from list */
187 greg 2.1 for (j = myslist[0]; j > 0; j--)
188 schorsch 2.14 if ( (i = inslist(p.slights, myslist[j])) )
189 greg 2.2 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 greg 2.6 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 greg 2.2 add2slist(r, myslist);
201     }
202     p.slights[0] = i;
203     }
204 greg 2.5 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 greg 2.6 if (m->oargs.nfargs > 5)
215     copycolor(p.albedo, salbedo);
216     if (m->oargs.nfargs > 6)
217 greg 2.1 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 schorsch 2.15 return 0; /* pro forma return */
226 greg 2.1 }