ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rv2.c
Revision: 2.44
Committed: Tue Jan 18 00:33:16 2005 UTC (19 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.43: +5 -34 lines
Log Message:
Added -pd option for depth-of-field sampling and -vd focal distance entry

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rv2.c,v 2.43 2004/03/30 16:13:01 schorsch Exp $";
3 #endif
4 /*
5 * rv2.c - command routines used in tracing a view.
6 *
7 * External symbols declared in rpaint.h
8 */
9
10 #include "copyright.h"
11
12 #include <ctype.h>
13 #include <string.h>
14
15 #include "platform.h"
16 #include "ray.h"
17 #include "ambient.h"
18 #include "otypes.h"
19 #include "rpaint.h"
20
21 extern int psample; /* pixel sample size */
22 extern double maxdiff; /* max. sample difference */
23
24 #define CTRL(c) ((c)-'@')
25
26 #ifdef SMLFLT
27 #define sscanvec(s,v) (sscanf(s,"%f %f %f",v,v+1,v+2)==3)
28 #else
29 #define sscanvec(s,v) (sscanf(s,"%lf %lf %lf",v,v+1,v+2)==3)
30 #endif
31
32 extern char rifname[128]; /* rad input file name */
33
34 extern char *progname;
35 extern char *octname;
36
37
38 extern void
39 getframe( /* get a new frame */
40 char *s
41 )
42 {
43 if (getrect(s, &pframe) < 0)
44 return;
45 pdepth = 0;
46 }
47
48
49 extern void
50 getrepaint( /* get area and repaint */
51 char *s
52 )
53 {
54 RECT box;
55
56 if (getrect(s, &box) < 0)
57 return;
58 paintrect(&ptrunk, 0, 0, hresolu, vresolu, &box);
59 }
60
61
62 extern void
63 getview( /* get/show view parameters */
64 char *s
65 )
66 {
67 FILE *fp;
68 char buf[128];
69 char *fname;
70 int change = 0;
71 VIEW nv = ourview;
72
73 while (isspace(*s))
74 s++;
75 if (*s == '-') { /* command line parameters */
76 if (sscanview(&nv, s))
77 newview(&nv);
78 else
79 error(COMMAND, "bad view option(s)");
80 return;
81 }
82 if (sscanf(s, "%s", buf) == 1) { /* write parameters to a file */
83 if ((fname = getpath(buf, NULL, 0)) == NULL ||
84 (fp = fopen(fname, "a")) == NULL) {
85 sprintf(errmsg, "cannot open \"%s\"", buf);
86 error(COMMAND, errmsg);
87 return;
88 }
89 fputs(progname, fp);
90 fprintview(&ourview, fp);
91 fputs(sskip(s), fp);
92 putc('\n', fp);
93 fclose(fp);
94 return;
95 }
96 sprintf(buf, "view type (%c): ", ourview.type);
97 (*dev->comout)(buf);
98 (*dev->comin)(buf, NULL);
99 if (buf[0] == CTRL('C')) return;
100 if (buf[0] && buf[0] != ourview.type) {
101 nv.type = buf[0];
102 change++;
103 }
104 sprintf(buf, "view point (%.6g %.6g %.6g): ",
105 ourview.vp[0], ourview.vp[1], ourview.vp[2]);
106 (*dev->comout)(buf);
107 (*dev->comin)(buf, NULL);
108 if (buf[0] == CTRL('C')) return;
109 if (sscanvec(buf, nv.vp))
110 change++;
111 sprintf(buf, "view direction (%.6g %.6g %.6g): ",
112 ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
113 (*dev->comout)(buf);
114 (*dev->comin)(buf, NULL);
115 if (buf[0] == CTRL('C')) return;
116 if (sscanvec(buf, nv.vdir))
117 change++;
118 sprintf(buf, "view up (%.6g %.6g %.6g): ",
119 ourview.vup[0], ourview.vup[1], ourview.vup[2]);
120 (*dev->comout)(buf);
121 (*dev->comin)(buf, NULL);
122 if (buf[0] == CTRL('C')) return;
123 if (sscanvec(buf, nv.vup))
124 change++;
125 sprintf(buf, "view horiz and vert size (%.6g %.6g): ",
126 ourview.horiz, ourview.vert);
127 (*dev->comout)(buf);
128 (*dev->comin)(buf, NULL);
129 if (buf[0] == CTRL('C')) return;
130 if (sscanf(buf, "%lf %lf", &nv.horiz, &nv.vert) == 2)
131 change++;
132 sprintf(buf, "fore and aft clipping plane (%.6g %.6g): ",
133 ourview.vfore, ourview.vaft);
134 (*dev->comout)(buf);
135 (*dev->comin)(buf, NULL);
136 if (buf[0] == CTRL('C')) return;
137 if (sscanf(buf, "%lf %lf", &nv.vfore, &nv.vaft) == 2)
138 change++;
139 sprintf(buf, "view shift and lift (%.6g %.6g): ",
140 ourview.hoff, ourview.voff);
141 (*dev->comout)(buf);
142 (*dev->comin)(buf, NULL);
143 if (buf[0] == CTRL('C')) return;
144 if (sscanf(buf, "%lf %lf", &nv.hoff, &nv.voff) == 2)
145 change++;
146 if (change)
147 newview(&nv);
148 }
149
150
151 extern void
152 lastview( /* return to a previous view */
153 char *s
154 )
155 {
156 char buf[128];
157 char *fname;
158 int success;
159 VIEW nv;
160
161 if (sscanf(s, "%s", buf) == 1) { /* get parameters from a file */
162 nv = stdview;
163 if ((fname = getpath(buf, "", R_OK)) == NULL ||
164 (success = viewfile(fname, &nv, NULL)) == -1) {
165 sprintf(errmsg, "cannot open \"%s\"", buf);
166 error(COMMAND, errmsg);
167 return;
168 }
169 if (!success)
170 error(COMMAND, "wrong file format");
171 else
172 newview(&nv);
173 return;
174 }
175 if (oldview.type == 0) { /* no old view! */
176 error(COMMAND, "no previous view");
177 return;
178 }
179 nv = ourview;
180 ourview = oldview;
181 oldview = nv;
182 newimage();
183 }
184
185
186 extern void
187 saveview( /* save view to rad file */
188 char *s
189 )
190 {
191 char view[64];
192 char *fname;
193 FILE *fp;
194
195 if (*atos(view, sizeof(view), s)) {
196 if (isint(view)) {
197 error(COMMAND, "cannot write view by number");
198 return;
199 }
200 s = sskip(s);
201 }
202 while (isspace(*s))
203 s++;
204 if (*s)
205 atos(rifname, sizeof(rifname), s);
206 else if (rifname[0] == '\0') {
207 error(COMMAND, "no previous rad file");
208 return;
209 }
210 if ((fname = getpath(rifname, NULL, 0)) == NULL ||
211 (fp = fopen(fname, "a")) == NULL) {
212 sprintf(errmsg, "cannot open \"%s\"", rifname);
213 error(COMMAND, errmsg);
214 return;
215 }
216 fputs("view= ", fp);
217 fputs(view, fp);
218 fprintview(&ourview, fp);
219 putc('\n', fp);
220 fclose(fp);
221 }
222
223
224 extern void
225 loadview( /* load view from rad file */
226 char *s
227 )
228 {
229 char buf[512];
230 char *fname;
231 FILE *fp;
232 VIEW nv;
233
234 strcpy(buf, "rad -n -s -V -v ");
235 if (sscanf(s, "%s", buf+strlen(buf)) == 1)
236 s = sskip(s);
237 else
238 strcat(buf, "1");
239 if (*s)
240 atos(rifname, sizeof(rifname), s);
241 else if (rifname[0] == '\0') {
242 error(COMMAND, "no previous rad file");
243 return;
244 }
245 if ((fname = getpath(rifname, "", R_OK)) == NULL) {
246 sprintf(errmsg, "cannot access \"%s\"", rifname);
247 error(COMMAND, errmsg);
248 return;
249 }
250 sprintf(buf+strlen(buf), " %s", fname);
251 if ((fp = popen(buf, "r")) == NULL) {
252 error(COMMAND, "cannot run rad");
253 return;
254 }
255 buf[0] = '\0';
256 fgets(buf, sizeof(buf), fp);
257 pclose(fp);
258 nv = stdview;
259 if (!sscanview(&nv, buf)) {
260 error(COMMAND, "rad error -- no such view?");
261 return;
262 }
263 newview(&nv);
264 }
265
266
267 extern void
268 getaim( /* aim camera */
269 char *s
270 )
271 {
272 VIEW nv = ourview;
273 double zfact;
274
275 if (getinterest(s, 1, nv.vdir, &zfact) < 0)
276 return;
277 zoomview(&nv, zfact);
278 newview(&nv);
279 }
280
281
282 extern void
283 getmove( /* move camera */
284 char *s
285 )
286 {
287 FVECT vc;
288 double mag;
289
290 if (getinterest(s, 0, vc, &mag) < 0)
291 return;
292 moveview(0.0, 0.0, mag, vc);
293 }
294
295
296 extern void
297 getrotate( /* rotate camera */
298 char *s
299 )
300 {
301 VIEW nv = ourview;
302 FVECT v1;
303 double angle, elev, zfact;
304
305 elev = 0.0; zfact = 1.0;
306 if (sscanf(s, "%lf %lf %lf", &angle, &elev, &zfact) < 1) {
307 error(COMMAND, "missing angle");
308 return;
309 }
310 spinvector(nv.vdir, ourview.vdir, ourview.vup, angle*(PI/180.));
311 if (elev != 0.0) {
312 fcross(v1, nv.vdir, ourview.vup);
313 normalize(v1);
314 spinvector(nv.vdir, nv.vdir, v1, elev*(PI/180.));
315 }
316 zoomview(&nv, zfact);
317 newview(&nv);
318 }
319
320
321 extern void
322 getpivot( /* pivot viewpoint */
323 register char *s
324 )
325 {
326 FVECT vc;
327 double angle, elev, mag;
328
329 elev = 0.0;
330 if (sscanf(s, "%lf %lf", &angle, &elev) < 1) {
331 error(COMMAND, "missing angle");
332 return;
333 }
334 if (getinterest(sskip2(s,2), 0, vc, &mag) < 0)
335 return;
336 moveview(angle, elev, mag, vc);
337 }
338
339
340 extern void
341 getexposure( /* get new exposure */
342 char *s
343 )
344 {
345 char buf[128];
346 register char *cp;
347 RECT r;
348 int x, y;
349 register PNODE *p = &ptrunk;
350 int adapt = 0;
351 double e = 1.0;
352
353 for (cp = s; isspace(*cp); cp++)
354 ;
355 if (*cp == '@') {
356 adapt++;
357 while (isspace(*++cp))
358 ;
359 }
360 if (*cp == '\0') { /* normalize to point */
361 if (dev->getcur == NULL)
362 return;
363 (*dev->comout)("Pick point for exposure\n");
364 if ((*dev->getcur)(&x, &y) == ABORT)
365 return;
366 r.l = r.d = 0;
367 r.r = hresolu; r.u = vresolu;
368 p = findrect(x, y, &ptrunk, &r, -1);
369 } else {
370 if (*cp == '=') { /* absolute setting */
371 p = NULL;
372 e = 1.0/exposure;
373 for (cp++; isspace(*cp); cp++)
374 ;
375 if (*cp == '\0') { /* interactive */
376 sprintf(buf, "exposure (%f): ", exposure);
377 (*dev->comout)(buf);
378 (*dev->comin)(buf, NULL);
379 for (cp = buf; isspace(*cp); cp++)
380 ;
381 if (*cp == '\0')
382 return;
383 }
384 }
385 if (*cp == '+' || *cp == '-') /* f-stops */
386 e *= pow(2.0, atof(cp));
387 else /* multiplier */
388 e *= atof(cp);
389 }
390 if (p != NULL) { /* relative setting */
391 if (bright(p->v) < 1e-15) {
392 error(COMMAND, "cannot normalize to zero");
393 return;
394 }
395 if (adapt)
396 e *= 106./pow(1.219+pow(luminance(p->v)/exposure,.4),2.5)/exposure;
397 else
398 e *= 0.5 / bright(p->v);
399 }
400 if (e <= FTINY || fabs(1.0 - e) <= FTINY)
401 return;
402 scalepict(&ptrunk, e);
403 exposure *= e;
404 redraw();
405 }
406
407 typedef union {int i; double d; COLOR C;} *MyUptr;
408
409 extern int
410 getparam( /* get variable from user */
411 char *str,
412 char *dsc,
413 int typ,
414 void *p
415 )
416 {
417 register MyUptr ptr = (MyUptr)p;
418 int i0;
419 double d0, d1, d2;
420 char buf[48];
421
422 switch (typ) {
423 case 'i': /* integer */
424 if (sscanf(str, "%d", &i0) != 1) {
425 (*dev->comout)(dsc);
426 sprintf(buf, " (%d): ", ptr->i);
427 (*dev->comout)(buf);
428 (*dev->comin)(buf, NULL);
429 if (sscanf(buf, "%d", &i0) != 1)
430 return(0);
431 }
432 ptr->i = i0;
433 return(1);
434 case 'r': /* real */
435 if (sscanf(str, "%lf", &d0) != 1) {
436 (*dev->comout)(dsc);
437 sprintf(buf, " (%.6g): ", ptr->d);
438 (*dev->comout)(buf);
439 (*dev->comin)(buf, NULL);
440 if (sscanf(buf, "%lf", &d0) != 1)
441 return(0);
442 }
443 ptr->d = d0;
444 return(1);
445 case 'b': /* boolean */
446 if (sscanf(str, "%1s", buf) != 1) {
447 (*dev->comout)(dsc);
448 sprintf(buf, "? (%c): ", ptr->i ? 'y' : 'n');
449 (*dev->comout)(buf);
450 (*dev->comin)(buf, NULL);
451 if (buf[0] == '\0' ||
452 strchr("yY+1tTnN-0fF", buf[0]) == NULL)
453 return(0);
454 }
455 ptr->i = strchr("yY+1tT", buf[0]) != NULL;
456 return(1);
457 case 'C': /* color */
458 if (sscanf(str, "%lf %lf %lf", &d0, &d1, &d2) != 3) {
459 (*dev->comout)(dsc);
460 sprintf(buf, " (%.6g %.6g %.6g): ",
461 colval(ptr->C,RED),
462 colval(ptr->C,GRN),
463 colval(ptr->C,BLU));
464 (*dev->comout)(buf);
465 (*dev->comin)(buf, NULL);
466 if (sscanf(buf, "%lf %lf %lf", &d0, &d1, &d2) != 3)
467 return(0);
468 }
469 setcolor(ptr->C, d0, d1, d2);
470 return(1);
471 }
472 return 0; /* nothing matched */
473 }
474
475
476 extern void
477 setparam( /* get/set program parameter */
478 register char *s
479 )
480 {
481 char buf[128];
482
483 if (s[0] == '\0') {
484 (*dev->comout)(
485 "aa ab ad ar as av aw b dc dv dj ds dt i lr lw me ma mg ms ps pt sj st bv: ");
486 (*dev->comin)(buf, NULL);
487 s = buf;
488 }
489 switch (s[0]) {
490 case 'l': /* limit */
491 switch (s[1]) {
492 case 'w': /* weight */
493 getparam(s+2, "limit weight", 'r',
494 (void *)&minweight);
495 break;
496 case 'r': /* reflection */
497 getparam(s+2, "limit reflection", 'i',
498 (void *)&maxdepth);
499 break;
500 default:
501 goto badparam;
502 }
503 break;
504 case 'd': /* direct */
505 switch (s[1]) {
506 case 'j': /* jitter */
507 getparam(s+2, "direct jitter", 'r',
508 (void *)&dstrsrc);
509 break;
510 case 'c': /* certainty */
511 getparam(s+2, "direct certainty", 'r',
512 (void *)&shadcert);
513 break;
514 case 't': /* threshold */
515 getparam(s+2, "direct threshold", 'r',
516 (void *)&shadthresh);
517 break;
518 case 'v': /* visibility */
519 getparam(s+2, "direct visibility", 'b',
520 (void *)&directvis);
521 break;
522 case 's': /* sampling */
523 getparam(s+2, "direct sampling", 'r',
524 (void *)&srcsizerat);
525 break;
526 default:
527 goto badparam;
528 }
529 break;
530 case 'b': /* back faces or black and white */
531 switch (s[1]) {
532 case 'v': /* back face visibility */
533 getparam(s+2, "back face visibility", 'b',
534 (void *)&backvis);
535 break;
536 case '\0': /* black and white */
537 case ' ':
538 case 'y': case 'Y': case 't': case 'T': case '1': case '+':
539 case 'n': case 'N': case 'f': case 'F': case '0': case '-':
540 getparam(s+1, "black and white", 'b',
541 (void *)&greyscale);
542 break;
543 default:
544 goto badparam;
545 }
546 break;
547 case 'i': /* irradiance */
548 getparam(s+1, "irradiance", 'b',
549 (void *)&do_irrad);
550 break;
551 case 'a': /* ambient */
552 switch (s[1]) {
553 case 'v': /* value */
554 getparam(s+2, "ambient value", 'C',
555 (void *)ambval);
556 break;
557 case 'w': /* weight */
558 getparam(s+2, "ambient value weight", 'i',
559 (void *)&ambvwt);
560 break;
561 case 'a': /* accuracy */
562 if (getparam(s+2, "ambient accuracy", 'r',
563 (void *)&ambacc))
564 setambacc(ambacc);
565 break;
566 case 'd': /* divisions */
567 getparam(s+2, "ambient divisions", 'i',
568 (void *)&ambdiv);
569 break;
570 case 's': /* samples */
571 getparam(s+2, "ambient super-samples", 'i',
572 (void *)&ambssamp);
573 break;
574 case 'b': /* bounces */
575 getparam(s+2, "ambient bounces", 'i',
576 (void *)&ambounce);
577 break;
578 case 'r':
579 if (getparam(s+2, "ambient resolution", 'i',
580 (void *)&ambres))
581 setambres(ambres);
582 break;
583 default:
584 goto badparam;
585 }
586 break;
587 case 'm': /* medium */
588 switch (s[1]) {
589 case 'e': /* extinction coefficient */
590 getparam(s+2, "extinction coefficient", 'C',
591 (void *)cextinction);
592 break;
593 case 'a': /* scattering albedo */
594 getparam(s+2, "scattering albedo", 'C',
595 (void *)salbedo);
596 break;
597 case 'g': /* scattering eccentricity */
598 getparam(s+2, "scattering eccentricity", 'r',
599 (void *)&seccg);
600 break;
601 case 's': /* sampling distance */
602 getparam(s+2, "mist sampling distance", 'r',
603 (void *)&ssampdist);
604 break;
605 default:
606 goto badparam;
607 }
608 break;
609 case 'p': /* pixel */
610 switch (s[1]) {
611 case 's': /* sample */
612 if (getparam(s+2, "pixel sample", 'i',
613 (void *)&psample))
614 pdepth = 0;
615 break;
616 case 't': /* threshold */
617 if (getparam(s+2, "pixel threshold", 'r',
618 (void *)&maxdiff))
619 pdepth = 0;
620 break;
621 default:
622 goto badparam;
623 }
624 break;
625 case 's': /* specular */
626 switch (s[1]) {
627 case 'j': /* jitter */
628 getparam(s+2, "specular jitter", 'r',
629 (void *)&specjitter);
630 break;
631 case 't': /* threshold */
632 getparam(s+2, "specular threshold", 'r',
633 (void *)&specthresh);
634 break;
635 default:
636 goto badparam;
637 }
638 break;
639 case '\0': /* nothing */
640 break;
641 default:;
642 badparam:
643 *sskip(s) = '\0';
644 sprintf(errmsg, "%s: unknown variable", s);
645 error(COMMAND, errmsg);
646 break;
647 }
648 }
649
650
651 extern void
652 traceray(s) /* trace a single ray */
653 char *s;
654 {
655 char buf[128];
656 int x, y;
657 OBJREC *ino;
658 RAY thisray;
659
660 thisray.rmax = 0.0;
661
662 if (!sscanvec(s, thisray.rorg) ||
663 !sscanvec(sskip2(s,3), thisray.rdir)) {
664
665 if (dev->getcur == NULL)
666 return;
667 (*dev->comout)("Pick ray\n");
668 if ((*dev->getcur)(&x, &y) == ABORT)
669 return;
670
671 if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir,
672 &ourview, (x+.5)/hresolu, (y+.5)/vresolu)) < -FTINY) {
673 error(COMMAND, "not on image");
674 return;
675 }
676
677 } else if (normalize(thisray.rdir) == 0.0) {
678 error(COMMAND, "zero ray direction");
679 return;
680 }
681
682 rayorigin(&thisray, NULL, PRIMARY, 1.0);
683
684 rayvalue(&thisray);
685
686 if (thisray.ro == NULL)
687 (*dev->comout)("ray hit nothing");
688 else {
689 sprintf(buf, "ray hit %s%s %s \"%s\"",
690 thisray.rod < 0.0 ? "back of " : "",
691 thisray.ro->omod == OVOID ? VOIDID :
692 objptr(thisray.ro->omod)->oname,
693 ofun[thisray.ro->otype].funame,
694 thisray.ro->oname);
695 if ((ino = objptr(thisray.robj)) != thisray.ro)
696 sprintf(buf+strlen(buf), " in %s \"%s\"",
697 ofun[ino->otype].funame, ino->oname);
698 (*dev->comout)(buf);
699 (*dev->comin)(buf, NULL);
700 if (thisray.rot >= FHUGE)
701 (*dev->comout)("at infinity");
702 else {
703 sprintf(buf, "at (%.6g %.6g %.6g) (%.6g)",
704 thisray.rop[0], thisray.rop[1],
705 thisray.rop[2], thisray.rt);
706 (*dev->comout)(buf);
707 }
708 (*dev->comin)(buf, NULL);
709 sprintf(buf, "value (%.5g %.5g %.5g) (%.3gL)",
710 colval(thisray.rcol,RED),
711 colval(thisray.rcol,GRN),
712 colval(thisray.rcol,BLU),
713 luminance(thisray.rcol));
714 (*dev->comout)(buf);
715 }
716 (*dev->comin)(buf, NULL);
717 }
718
719
720 extern void
721 writepict(s) /* write the picture to a file */
722 char *s;
723 {
724 static char buf[128];
725 char *fname;
726 FILE *fp;
727 COLR *scanline;
728 int y;
729
730 while (isspace(*s))
731 s++;
732 if (*s)
733 atos(buf, sizeof(buf), s);
734 else if (buf[0] == '\0') {
735 error(COMMAND, "no file");
736 return;
737 }
738 if ((fname = getpath(buf, NULL, 0)) == NULL ||
739 (fp = fopen(fname, "w")) == NULL) {
740 sprintf(errmsg, "cannot open \"%s\"", buf);
741 error(COMMAND, errmsg);
742 return;
743 }
744 SET_FILE_BINARY(fp);
745 (*dev->comout)("writing \"");
746 (*dev->comout)(fname);
747 (*dev->comout)("\"...\n");
748 /* write header */
749 newheader("RADIANCE", fp);
750 fputs(progname, fp);
751 fprintview(&ourview, fp);
752 if (octname != NULL)
753 fprintf(fp, " %s\n", octname);
754 else
755 putc('\n', fp);
756 fprintf(fp, "SOFTWARE= %s\n", VersionID);
757 fputnow(fp);
758 if (exposure != 1.0)
759 fputexpos(exposure, fp);
760 if (dev->pixaspect != 1.0)
761 fputaspect(dev->pixaspect, fp);
762 fputformat(COLRFMT, fp);
763 putc('\n', fp);
764 fprtresolu(hresolu, vresolu, fp);
765
766 scanline = (COLR *)malloc(hresolu*sizeof(COLR));
767 if (scanline == NULL) {
768 error(COMMAND, "not enough memory!");
769 fclose(fp);
770 unlink(fname);
771 return;
772 }
773 for (y = vresolu-1; y >= 0; y--) {
774 getpictcolrs(y, scanline, &ptrunk, hresolu, vresolu);
775 if (fwritecolrs(scanline, hresolu, fp) < 0)
776 break;
777 }
778 free((void *)scanline);
779 if (fclose(fp) < 0)
780 error(COMMAND, "write error");
781 }