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 (4 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: renderopts.c,v 2.25 2024/04/05 17:52:20 greg Exp $";
3 #endif
4 /*
5 * renderopts.c - process common rendering options
6 *
7 * External symbols declared in ray.h
8 */
9
10 #include "copyright.h"
11
12 #include "ray.h"
13 #include "paths.h"
14 #include "pmapopt.h"
15
16 extern char *progname; /* global argv[0] */
17
18 char RFeatureList[2048] = /* newline-separated feature list */
19 "VirtualSources\nSecondarySources\nSourceSubsampling\n"
20 "SourceVisibility\nAmbientModifierSelection\n"
21 "PathTracing\nRussianRoulette\nLowDiscrepancySeq\n"
22 "SpecularSampling\nMaterialMixtures\nAntimatter\nBackFaceVisibility\n"
23 "ScatteringModels=WGMD,Ashikhmin-Shirley\n"
24 "TabulatedBSDFs=DataFile,KlemsXML,TensorTreeXML,+ViewPeakExtraction\n"
25 "Instancing=Octree,TriangleMesh\nAliases\n"
26 #if MAXCSAMP>3
27 "Hyperspectral\n"
28 #endif
29 #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 if (!(n = cp - subfeat))
79 continue; /* empty subfeature */
80 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 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
122 int
123 getrenderopt( /* get next render option */
124 int ac,
125 char *av[]
126 )
127 {
128 #define check(ol,al) if (av[0][ol] || \
129 badarg(ac-1,av+1,al)) \
130 return(-1)
131 #define check_bool(olen,var) switch (av[0][olen]) { \
132 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 case 'u': /* uncorrelated sampling */
146 check_bool(2,rand_samp);
147 return(0);
148 case 'b': /* back face vis. */
149 if (av[0][2] == 'v') {
150 check_bool(3,backvis);
151 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 check_bool(3,directvis);
178 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 case 's': /* sampling */
192 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 check_bool(2,do_irrad);
211 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 rval = wordfile(amblp, AMBLLEN-(amblp-amblist),
253 getpath(av[1],getrlibpath(),R_OK));
254 if (rval < 0) {
255 sprintf(errmsg,
256 "cannot open ambient include file \"%s\"", av[1]);
257 error(SYSTEM, errmsg);
258 }
259 amblp += rval;
260 } else {
261 *amblp++ = savqstr(av[1]);
262 *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 rval = wordfile(amblp, AMBLLEN-(amblp-amblist),
274 getpath(av[1],getrlibpath(),R_OK));
275 if (rval < 0) {
276 sprintf(errmsg,
277 "cannot open ambient exclude file \"%s\"", av[1]);
278 error(SYSTEM, errmsg);
279 }
280 amblp += rval;
281 } else {
282 *amblp++ = savqstr(av[1]);
283 *amblp = NULL;
284 }
285 return(1);
286 case 'f': /* file */
287 check(3,"s");
288 ambfile = savqstr(av[1]);
289 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 #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 return(2);
328 }
329 break;
330 #endif
331 }
332
333 /* PMAP: Parse photon mapping options */
334 return(getPmapRenderOpt(ac, av));
335
336 /* return(-1); */ /* unknown option */
337
338 #undef check
339 #undef check_bool
340 }
341
342
343 void
344 print_rdefaults(void) /* print default render values to stdout */
345 {
346 printf(do_irrad ? "-i+\t\t\t\t# irradiance calculation on\n" :
347 "-i-\t\t\t\t# irradiance calculation off\n");
348 printf(rand_samp ? "-u+\t\t\t\t# uncorrelated Monte Carlo sampling\n" :
349 "-u-\t\t\t\t# correlated quasi-Monte Carlo sampling\n");
350 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 printf("-ss %f\t\t\t# specular sampling\n", specjitter);
361 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 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 printf("-lr %-9d\t\t\t# limit reflection%s\n", maxdepth,
384 maxdepth<=0 ? " (Russian roulette)" : "");
385 printf("-lw %.2e\t\t\t# limit weight\n", minweight);
386
387 /* PMAP: output photon map defaults */
388 printPmapDefaults();
389 }