ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/renderopts.c
Revision: 2.26
Committed: Fri Apr 5 17:55:25 2024 UTC (6 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.25: +3 -2 lines
Log Message:
fix: Added check for empty subfeature that could cause memory read-past-end

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.26 static const char RCSid[] = "$Id: renderopts.c,v 2.25 2024/04/05 17:52:20 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * renderopts.c - process common rendering options
6     *
7     * External symbols declared in ray.h
8     */
9    
10 greg 2.2 #include "copyright.h"
11 greg 2.1
12     #include "ray.h"
13 greg 2.5 #include "paths.h"
14 greg 2.16 #include "pmapopt.h"
15 greg 2.1
16 greg 2.19 extern char *progname; /* global argv[0] */
17    
18     char RFeatureList[2048] = /* newline-separated feature list */
19 greg 2.20 "VirtualSources\nSecondarySources\nSourceSubsampling\n"
20     "SourceVisibility\nAmbientModifierSelection\n"
21     "PathTracing\nRussianRoulette\nLowDiscrepancySeq\n"
22     "SpecularSampling\nMaterialMixtures\nAntimatter\nBackFaceVisibility\n"
23 greg 2.22 "ScatteringModels=WGMD,Ashikhmin-Shirley\n"
24 greg 2.19 "TabulatedBSDFs=DataFile,KlemsXML,TensorTreeXML,+ViewPeakExtraction\n"
25     "Instancing=Octree,TriangleMesh\nAliases\n"
26 greg 2.23 #if MAXCSAMP>3
27     "Hyperspectral\n"
28     #endif
29 greg 2.19 #if !defined(SHADCACHE) || SHADCACHE > 0
30     "ShadowCache\n"
31     #endif
32     #ifdef DISPERSE
33     "DielectricDispersion\n"
34     #endif
35     /* PMAP_FEATURES XXX @Roland: need to define this in pmapopt.h */
36     ;
37    
38    
39     static char *
40     get_feature( /* find a specific feature (with optional sublist) */
41     const char *feat
42     )
43     {
44     char *cp = RFeatureList;
45     int n = 0;
46    
47     while ((feat[n] != '\0') & (feat[n] != '='))
48     n++;
49     if (!n)
50     return(NULL);
51     while (*cp) {
52     if (!strncmp(cp, feat, n) && (cp[n] == '\n') | !feat[n] | (cp[n] == feat[n]))
53     return(cp);
54     while (*cp++ != '\n')
55     ;
56     }
57     return(NULL);
58     }
59    
60    
61     static int
62     match_subfeatures( /* check if subfeatures are supported */
63     char *mysublist,
64     char *reqs
65     )
66     {
67     if (mysublist)
68     mysublist = strchr(mysublist, '=');
69     if (!mysublist++ | !reqs)
70     return(0); /* not a feature list */
71     while (*reqs) { /* check each of their subfeature requests */
72     char subfeat[64];
73     char *cp = subfeat;
74     int n;
75     while (*reqs && (*cp = *reqs++) != ',')
76     cp++;
77     *cp = '\0';
78 greg 2.26 if (!(n = cp - subfeat))
79     continue; /* empty subfeature */
80 greg 2.25 for (cp = mysublist; (cp = strstr(cp, subfeat)) != NULL; cp++)
81     if ((cp[-1] == ',') | (cp[-1] == '=') &&
82     (cp[n] == ',') | (cp[n] == '\n'))
83     break; /* match */
84     if (!cp)
85 greg 2.19 return(0); /* missing this one! */
86     }
87     return(1); /* matched them all */
88     }
89    
90    
91     int
92     feature_status( /* report active feature list / check specifics */
93     int ac,
94     char *av[]
95     )
96     {
97     if (ac <= 0) /* report entire list? */
98     fputs(RFeatureList, stdout);
99    
100     for ( ; ac-- > 0; av++) { /* check each argument */
101     char *cp;
102     if (!*av[0]) continue;
103     if ((cp = strchr(av[0], '=')) != NULL) {
104     if (!match_subfeatures(get_feature(av[0]), cp+1))
105     goto missing_feature;
106     } else if ((cp = get_feature(av[0])) != NULL) {
107     char *tp = strchr(cp, '=');
108     if (tp && tp < strchr(cp, '\n'))
109     do
110     fputc(*cp, stdout);
111     while (*cp++ != '\n');
112     } else
113     goto missing_feature;
114     }
115     return(0); /* return satisfactory status */
116     missing_feature: /* or report error */
117     fprintf(stderr, "%s: missing feature - %s\n", progname, av[0]);
118     return(1);
119     }
120    
121 greg 2.1
122 greg 2.15 int
123 schorsch 2.4 getrenderopt( /* get next render option */
124     int ac,
125     char *av[]
126     )
127 greg 2.1 {
128     #define check(ol,al) if (av[0][ol] || \
129     badarg(ac-1,av+1,al)) \
130     return(-1)
131 schorsch 2.17 #define check_bool(olen,var) switch (av[0][olen]) { \
132 greg 2.1 case '\0': var = !var; break; \
133     case 'y': case 'Y': case 't': case 'T': \
134     case '+': case '1': var = 1; break; \
135     case 'n': case 'N': case 'f': case 'F': \
136     case '-': case '0': var = 0; break; \
137     default: return(-1); }
138     static char **amblp; /* pointer to build ambient list */
139     int rval;
140     /* is it even an option? */
141     if (ac < 1 || av[0] == NULL || av[0][0] != '-')
142     return(-1);
143     /* check if it's one we know */
144     switch (av[0][1]) {
145 greg 2.10 case 'u': /* uncorrelated sampling */
146 schorsch 2.17 check_bool(2,rand_samp);
147 greg 2.9 return(0);
148 greg 2.1 case 'b': /* back face vis. */
149     if (av[0][2] == 'v') {
150 schorsch 2.17 check_bool(3,backvis);
151 greg 2.1 return(0);
152     }
153     break;
154     case 'd': /* direct */
155     switch (av[0][2]) {
156     case 't': /* threshold */
157     check(3,"f");
158     shadthresh = atof(av[1]);
159     return(1);
160     case 'c': /* certainty */
161     check(3,"f");
162     shadcert = atof(av[1]);
163     return(1);
164     case 'j': /* jitter */
165     check(3,"f");
166     dstrsrc = atof(av[1]);
167     return(1);
168     case 'r': /* relays */
169     check(3,"i");
170     directrelay = atoi(av[1]);
171     return(1);
172     case 'p': /* pretest */
173     check(3,"i");
174     vspretest = atoi(av[1]);
175     return(1);
176     case 'v': /* visibility */
177 schorsch 2.17 check_bool(3,directvis);
178 greg 2.1 return(0);
179     case 's': /* size */
180     check(3,"f");
181     srcsizerat = atof(av[1]);
182     return(1);
183     }
184     break;
185     case 's': /* specular */
186     switch (av[0][2]) {
187     case 't': /* threshold */
188     check(3,"f");
189     specthresh = atof(av[1]);
190     return(1);
191 greg 2.14 case 's': /* sampling */
192 greg 2.1 check(3,"f");
193     specjitter = atof(av[1]);
194     return(1);
195     }
196     break;
197     case 'l': /* limit */
198     switch (av[0][2]) {
199     case 'r': /* recursion */
200     check(3,"i");
201     maxdepth = atoi(av[1]);
202     return(1);
203     case 'w': /* weight */
204     check(3,"f");
205     minweight = atof(av[1]);
206     return(1);
207     }
208     break;
209     case 'i': /* irradiance */
210 schorsch 2.17 check_bool(2,do_irrad);
211 greg 2.1 return(0);
212     case 'a': /* ambient */
213     switch (av[0][2]) {
214     case 'v': /* value */
215     check(3,"fff");
216     setcolor(ambval, atof(av[1]),
217     atof(av[2]),
218     atof(av[3]));
219     return(3);
220     case 'w': /* weight */
221     check(3,"i");
222     ambvwt = atoi(av[1]);
223     return(1);
224     case 'a': /* accuracy */
225     check(3,"f");
226     ambacc = atof(av[1]);
227     return(1);
228     case 'r': /* resolution */
229     check(3,"i");
230     ambres = atoi(av[1]);
231     return(1);
232     case 'd': /* divisions */
233     check(3,"i");
234     ambdiv = atoi(av[1]);
235     return(1);
236     case 's': /* super-samp */
237     check(3,"i");
238     ambssamp = atoi(av[1]);
239     return(1);
240     case 'b': /* bounces */
241     check(3,"i");
242     ambounce = atoi(av[1]);
243     return(1);
244     case 'i': /* include */
245     case 'I':
246     check(3,"s");
247     if (ambincl != 1) {
248     ambincl = 1;
249     amblp = amblist;
250     }
251     if (av[0][2] == 'I') { /* file */
252 greg 2.18 rval = wordfile(amblp, AMBLLEN-(amblp-amblist),
253 greg 2.3 getpath(av[1],getrlibpath(),R_OK));
254 greg 2.1 if (rval < 0) {
255     sprintf(errmsg,
256 greg 2.7 "cannot open ambient include file \"%s\"", av[1]);
257 greg 2.1 error(SYSTEM, errmsg);
258     }
259     amblp += rval;
260     } else {
261 greg 2.6 *amblp++ = savqstr(av[1]);
262 greg 2.1 *amblp = NULL;
263     }
264     return(1);
265     case 'e': /* exclude */
266     case 'E':
267     check(3,"s");
268     if (ambincl != 0) {
269     ambincl = 0;
270     amblp = amblist;
271     }
272     if (av[0][2] == 'E') { /* file */
273 greg 2.18 rval = wordfile(amblp, AMBLLEN-(amblp-amblist),
274 greg 2.3 getpath(av[1],getrlibpath(),R_OK));
275 greg 2.1 if (rval < 0) {
276     sprintf(errmsg,
277 greg 2.7 "cannot open ambient exclude file \"%s\"", av[1]);
278 greg 2.1 error(SYSTEM, errmsg);
279     }
280     amblp += rval;
281     } else {
282 greg 2.6 *amblp++ = savqstr(av[1]);
283 greg 2.1 *amblp = NULL;
284     }
285     return(1);
286     case 'f': /* file */
287     check(3,"s");
288 greg 2.6 ambfile = savqstr(av[1]);
289 greg 2.1 return(1);
290     }
291     break;
292     case 'm': /* medium */
293     switch (av[0][2]) {
294     case 'e': /* extinction */
295     check(3,"fff");
296     setcolor(cextinction, atof(av[1]),
297     atof(av[2]),
298     atof(av[3]));
299     return(3);
300     case 'a': /* albedo */
301     check(3,"fff");
302     setcolor(salbedo, atof(av[1]),
303     atof(av[2]),
304     atof(av[3]));
305     return(3);
306     case 'g': /* eccentr. */
307     check(3,"f");
308     seccg = atof(av[1]);
309     return(1);
310     case 's': /* sampling */
311     check(3,"f");
312     ssampdist = atof(av[1]);
313     return(1);
314     }
315     break;
316 greg 2.23 #if MAXCSAMP>3
317     case 'c': /* spectral sampling */
318     switch (av[0][2]) {
319     case 's': /* spectral bin count */
320     check(3,"i");
321     NCSAMP = atoi(av[1]);
322     return(1);
323     case 'w': /* wavelength extrema */
324     check(3,"ff");
325     WLPART[0] = atof(av[1]);
326     WLPART[3] = atof(av[2]);
327 greg 2.24 return(2);
328 greg 2.23 }
329     break;
330     #endif
331 greg 2.1 }
332 greg 2.16
333     /* PMAP: Parse photon mapping options */
334     return(getPmapRenderOpt(ac, av));
335    
336     /* return(-1); */ /* unknown option */
337 greg 2.1
338     #undef check
339 schorsch 2.17 #undef check_bool
340 greg 2.1 }
341    
342    
343 greg 2.15 void
344 schorsch 2.4 print_rdefaults(void) /* print default render values to stdout */
345 greg 2.1 {
346     printf(do_irrad ? "-i+\t\t\t\t# irradiance calculation on\n" :
347     "-i-\t\t\t\t# irradiance calculation off\n");
348 greg 2.11 printf(rand_samp ? "-u+\t\t\t\t# uncorrelated Monte Carlo sampling\n" :
349 greg 2.12 "-u-\t\t\t\t# correlated quasi-Monte Carlo sampling\n");
350 greg 2.1 printf(backvis ? "-bv+\t\t\t\t# back face visibility on\n" :
351     "-bv-\t\t\t\t# back face visibility off\n");
352     printf("-dt %f\t\t\t# direct threshold\n", shadthresh);
353     printf("-dc %f\t\t\t# direct certainty\n", shadcert);
354     printf("-dj %f\t\t\t# direct jitter\n", dstrsrc);
355     printf("-ds %f\t\t\t# direct sampling\n", srcsizerat);
356     printf("-dr %-9d\t\t\t# direct relays\n", directrelay);
357     printf("-dp %-9d\t\t\t# direct pretest density\n", vspretest);
358     printf(directvis ? "-dv+\t\t\t\t# direct visibility on\n" :
359     "-dv-\t\t\t\t# direct visibility off\n");
360 greg 2.14 printf("-ss %f\t\t\t# specular sampling\n", specjitter);
361 greg 2.1 printf("-st %f\t\t\t# specular threshold\n", specthresh);
362     printf("-av %f %f %f\t# ambient value\n", colval(ambval,RED),
363     colval(ambval,GRN), colval(ambval, BLU));
364     printf("-aw %-9d\t\t\t# ambient value weight\n", ambvwt);
365     printf("-ab %-9d\t\t\t# ambient bounces\n", ambounce);
366     printf("-aa %f\t\t\t# ambient accuracy\n", ambacc);
367     printf("-ar %-9d\t\t\t# ambient resolution\n", ambres);
368     printf("-ad %-9d\t\t\t# ambient divisions\n", ambdiv);
369     printf("-as %-9d\t\t\t# ambient super-samples\n", ambssamp);
370     printf("-me %.2e %.2e %.2e\t# mist extinction coefficient\n",
371     colval(cextinction,RED),
372     colval(cextinction,GRN),
373     colval(cextinction,BLU));
374     printf("-ma %f %f %f\t# mist scattering albedo\n", colval(salbedo,RED),
375     colval(salbedo,GRN), colval(salbedo,BLU));
376     printf("-mg %f\t\t\t# mist scattering eccentricity\n", seccg);
377     printf("-ms %f\t\t\t# mist sampling distance\n", ssampdist);
378 greg 2.23 if (NCSAMP > 3) {
379     printf("-cs %-2d\t\t\t\t# number of spectral bins\n", NCSAMP);
380     printf("-cw %3.0f %3.0f\t\t\t# wavelength limits (nm)\n",
381     WLPART[3], WLPART[0]);
382     }
383 greg 2.8 printf("-lr %-9d\t\t\t# limit reflection%s\n", maxdepth,
384     maxdepth<=0 ? " (Russian roulette)" : "");
385 greg 2.13 printf("-lw %.2e\t\t\t# limit weight\n", minweight);
386 greg 2.16
387     /* PMAP: output photon map defaults */
388     printPmapDefaults();
389 greg 2.1 }