ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_mist.c
Revision: 2.1
Committed: Fri Dec 8 21:27:10 1995 UTC (28 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

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 MAXSLIST 32 /* maximum sources to check */
47     #define RELAYDELIM '>' /* relay delimiter character */
48    
49     extern COLOR cextinction; /* global coefficient of extinction */
50     extern double salbedo; /* global scattering albedo */
51     extern double seccg; /* global scattering eccentricity */
52    
53    
54     static int
55     inslist(sl, n) /* return index of source n if it's in list sl */
56     register int *sl;
57     register int n;
58     {
59     register int i;
60    
61     for (i = sl[0]; i > 0; i--)
62     if (sl[i] == n)
63     return(i);
64     return(0);
65     }
66    
67    
68     static int
69     srcmatch(sn, id) /* check for an id match on a light source */
70     register int sn;
71     char *id;
72     {
73     extern char *index();
74     register char *cp;
75     again:
76     if (source[sn].so == NULL) /* just in case */
77     return(0);
78     if ((cp = index(id, RELAYDELIM)) != NULL) { /* relay source */
79     if (!(source[sn].sflags & SVIRTUAL))
80     return(0);
81     *cp = '\0';
82     if (strcmp(id, source[sn].so->oname)) {
83     *cp = RELAYDELIM;
84     return(0);
85     }
86     *cp = RELAYDELIM;
87     id = cp + 1; /* recurse */
88     sn = source[sn].sa.sv.sn;
89     goto again;
90     }
91     if (source[sn].sflags & SVIRTUAL)
92     return(0);
93     return(!strcmp(id, source[sn].so->oname));
94     }
95    
96    
97     m_mist(m, r) /* process a ray entering or leaving some mist */
98     OBJREC *m;
99     register RAY *r;
100     {
101     RAY p;
102     int *myslist = NULL;
103     int newslist[MAXSLIST+1];
104     COLOR mext;
105     double re, ge, be;
106     register int i, j;
107     /* check arguments */
108     if (m->oargs.nfargs > 5)
109     objerror(m, USER, "bad arguments");
110     if (m->oargs.nsargs > MAXSLIST)
111     objerror(m, USER, "too many sources in list");
112     /* get source indices */
113     if (m->oargs.nsargs > 0 && (myslist = (int *)m->os) == NULL) {
114     myslist = (int *)malloc((m->oargs.nsargs+1)*sizeof(int));
115     if (myslist == NULL)
116     goto memerr;
117     myslist[0] = m->oargs.nsargs; /* size is first in set */
118     for (j = myslist[0]; j > 0; j--) {
119     i = nsources; /* look up each source id */
120     while (i--)
121     if (srcmatch(i, m->oargs.sarg[j-1]))
122     break;
123     if (i < 0) {
124     sprintf(errmsg, "unknown source \"%s\"",
125     m->oargs.sarg[j-1]);
126     objerror(m, WARNING, errmsg);
127     } else
128     myslist[j] = i;
129     }
130     m->os = (char *)myslist;
131     }
132     if (m->oargs.nfargs > 2) { /* compute extinction */
133     setcolor(mext, m->oargs.farg[0], m->oargs.farg[1],
134     m->oargs.farg[2]);
135     raytexture(r, m->omod); /* get modifiers */
136     multcolor(mext, r->pcol);
137     } else
138     setcolor(mext, 0., 0., 0.);
139     /* start transmitted ray */
140     if (rayorigin(&p, r, TRANS, 1.) < 0)
141     return(1);
142     VCOPY(p.rdir, r->rdir);
143     p.slights = newslist;
144     if (r->slights != NULL)
145     for (j = r->slights[0]; j >= 0; j--)
146     p.slights[j] = r->slights[j];
147     else
148     p.slights[0] = 0;
149     if (r->rod > 0.) { /* entering ray */
150     addcolor(p.cext, mext);
151     if (m->oargs.nfargs > 3)
152     p.albedo = m->oargs.farg[3];
153     if (m->oargs.nfargs > 4)
154     p.gecc = m->oargs.farg[4];
155     if (myslist != NULL) /* add to list */
156     for (j = myslist[0]; j > 0; j--)
157     if (!inslist(p.slights, myslist[j])) {
158     if (p.slights[0] >= MAXSLIST)
159     error(USER,
160     "scattering source list overflow");
161     p.slights[++p.slights[0]] = myslist[j];
162     }
163     } else { /* leaving ray */
164     re = colval(r->cext,RED) - colval(mext,RED);
165     ge = colval(r->cext,GRN) - colval(mext,GRN);
166     be = colval(r->cext,BLU) - colval(mext,BLU);
167     setcolor(p.cext, re<0. ? 0. : re,
168     ge<0. ? 0. : ge,
169     be<0. ? 0. : be);
170     if (m->oargs.nfargs > 3)
171     p.albedo = salbedo;
172     if (m->oargs.nfargs > 4)
173     p.gecc = seccg;
174     if (myslist != NULL) { /* delete from list */
175     for (j = myslist[0]; j > 0; j--)
176     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     p.slights[0] = i;
182     }
183     }
184     rayvalue(&p); /* calls rayparticipate() */
185     copycolor(r->rcol, p.rcol); /* return value */
186     r->rt = r->rot + p.rt;
187     return(1);
188     memerr:
189     error(SYSTEM, "out of memory in m_mist");
190     }