ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_mist.c
Revision: 2.12
Committed: Mon Mar 10 17:26:26 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.11: +1 -2 lines
Log Message:
Compile fixes for Linux

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