ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rpict.c
Revision: 2.30
Committed: Thu Oct 28 15:24:19 1993 UTC (30 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.29: +30 -10 lines
Log Message:
fixed time reporting for non-BSD machines(?)

File Contents

# Content
1 /* Copyright (c) 1992 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * rpict.c - routines and variables for picture generation.
9 *
10 * 8/14/85
11 */
12
13 #include "ray.h"
14
15 #ifndef NIX
16 #ifdef BSD
17 #include <sys/time.h>
18 #include <sys/resource.h>
19 #else
20 #include <sys/types.h>
21 #include <sys/times.h>
22 #include <limits.h>
23 #endif
24 #endif
25
26 #include <signal.h>
27
28 #include "view.h"
29
30 #include "resolu.h"
31
32 #include "random.h"
33
34 #include "paths.h"
35
36 #define RFTEMPLATE "rfXXXXXX"
37
38 #ifndef SIGCONT
39 #define SIGCONT SIGIO
40 #endif
41
42 int dimlist[MAXDIM]; /* sampling dimensions */
43 int ndims = 0; /* number of sampling dimensions */
44 int samplendx; /* sample index number */
45
46 VIEW ourview = STDVIEW; /* view parameters */
47 int hresolu = 512; /* horizontal resolution */
48 int vresolu = 512; /* vertical resolution */
49 double pixaspect = 1.0; /* pixel aspect ratio */
50
51 int psample = 4; /* pixel sample size */
52 double maxdiff = .05; /* max. difference for interpolation */
53 double dstrpix = 0.67; /* square pixel distribution */
54
55 double dstrsrc = 0.0; /* square source distribution */
56 double shadthresh = .05; /* shadow threshold */
57 double shadcert = .5; /* shadow certainty */
58 int directrelay = 1; /* number of source relays */
59 int vspretest = 512; /* virtual source pretest density */
60 int directvis = 1; /* sources visible? */
61 double srcsizerat = .25; /* maximum ratio source size/dist. */
62
63 double specthresh = .15; /* specular sampling threshold */
64 double specjitter = 1.; /* specular sampling jitter */
65
66 int maxdepth = 6; /* maximum recursion depth */
67 double minweight = 5e-3; /* minimum ray weight */
68
69 COLOR ambval = BLKCOLOR; /* ambient value */
70 double ambacc = 0.2; /* ambient accuracy */
71 int ambres = 32; /* ambient resolution */
72 int ambdiv = 128; /* ambient divisions */
73 int ambssamp = 0; /* ambient super-samples */
74 int ambounce = 0; /* ambient bounces */
75 char *amblist[128]; /* ambient include/exclude list */
76 int ambincl = -1; /* include == 1, exclude == 0 */
77
78 #ifdef MSDOS
79 int ralrm = 60; /* seconds between reports */
80 #else
81 int ralrm = 0; /* seconds between reports */
82 #endif
83
84 double pctdone = 0.0; /* percentage done */
85
86 long tlastrept = 0L; /* time at last report */
87
88 extern long time();
89 extern long tstart; /* starting time */
90
91 extern unsigned long nrays; /* number of rays traced */
92
93 #define MAXDIV 16 /* maximum sample size */
94
95 #define pixjitter() (.5+dstrpix*(.5-frandom()))
96
97 static int hres, vres; /* resolution for this frame */
98
99 extern char *mktemp();
100
101 double pixvalue();
102
103 #ifdef NIX
104 #define file_exists(f) (access(f,F_OK)==0)
105 #else
106 #include <sys/types.h>
107 #include <sys/stat.h>
108 int
109 file_exists(fname) /* ordinary file exists? */
110 char *fname;
111 {
112 struct stat sbuf;
113 if (stat(fname, &sbuf) < 0) return(0);
114 return((sbuf.st_mode & S_IFREG) != 0);
115 }
116 #endif
117
118
119 quit(code) /* quit program */
120 int code;
121 {
122 if (code) /* report status */
123 report();
124 headclean(); /* delete header file */
125 pfclean(); /* clean up persist files */
126 exit(code);
127 }
128
129
130 #ifndef NIX
131 report() /* report progress */
132 {
133 char hostname[128];
134 double u, s;
135 #ifdef BSD
136 struct rusage rubuf;
137 #else
138 struct tms tbuf;
139 #endif
140
141 tlastrept = time((long *)0);
142 #ifdef BSD
143 getrusage(RUSAGE_SELF, &rubuf);
144 u = rubuf.ru_utime.tv_sec + rubuf.ru_utime.tv_usec/1e6;
145 s = rubuf.ru_stime.tv_sec + rubuf.ru_stime.tv_usec/1e6;
146 getrusage(RUSAGE_CHILDREN, &rubuf);
147 u += rubuf.ru_utime.tv_sec + rubuf.ru_utime.tv_usec/1e6;
148 s += rubuf.ru_stime.tv_sec + rubuf.ru_stime.tv_usec/1e6;
149 #else
150 times(&tbuf);
151 u = ( tbuf.tms_utime + tbuf.tms_cutime ) / CLK_TCK;
152 s = ( tbuf.tms_stime + tbuf.tms_cstime ) / CLK_TCK;
153 #endif
154 gethostname(hostname, sizeof(hostname));
155
156 sprintf(errmsg,
157 "%lu rays, %4.2f%% after %.3fu %.3fs %.3fr hours on %s\n",
158 nrays, pctdone, u/3600., s/3600.,
159 (tlastrept-tstart)/3600., hostname);
160 eputs(errmsg);
161 }
162 #else
163 report() /* report progress */
164 {
165 tlastrept = time((long *)0);
166 sprintf(errmsg, "%lu rays, %4.2f%% after %5.4f hours\n",
167 nrays, pctdone, (tlastrept-tstart)/3600.0);
168 eputs(errmsg);
169 signal(SIGCONT, report);
170 }
171 #endif
172
173
174 rpict(seq, pout, zout, prvr) /* generate image(s) */
175 int seq;
176 char *pout, *zout, *prvr;
177 /*
178 * If seq is greater than zero, then we will render a sequence of
179 * images based on view parameter strings read from the standard input.
180 * If pout is NULL, then all images will be sent to the standard ouput.
181 * If seq is greater than zero and prvr is an integer, then it is the
182 * frame number at which rendering should begin. Preceeding view parameter
183 * strings will be skipped in the input.
184 * If pout and prvr are the same, prvr is renamed to avoid overwriting.
185 * Note that pout and zout should contain %d format specifications for
186 * sequenced file naming.
187 */
188 {
189 extern char *rindex(), *strncpy(), *strcat(), *strcpy();
190 char fbuf[128], fbuf2[128];
191 int npicts;
192 register char *cp;
193 RESOLU rs;
194 double pa;
195 /* check sampling */
196 if (psample < 1)
197 psample = 1;
198 else if (psample > MAXDIV) {
199 sprintf(errmsg, "pixel sampling reduced from %d to %d",
200 psample, MAXDIV);
201 error(WARNING, errmsg);
202 psample = MAXDIV;
203 }
204 /* get starting frame */
205 if (seq <= 0)
206 seq = 0;
207 else if (prvr != NULL && isint(prvr)) {
208 register int rn; /* skip to specified view */
209 if ((rn = atoi(prvr)) < seq)
210 error(USER, "recover frame less than start frame");
211 if (pout == NULL)
212 error(USER, "missing output file specification");
213 for ( ; seq < rn; seq++)
214 if (nextview(stdin) == EOF)
215 error(USER, "unexpected EOF on view input");
216 prvr = fbuf; /* mark for renaming */
217 }
218 if (pout != NULL & prvr != NULL) {
219 sprintf(fbuf, pout, seq);
220 if (!strcmp(prvr, fbuf)) { /* rename */
221 strcpy(fbuf2, fbuf);
222 for (cp = fbuf2; *cp; cp++)
223 ;
224 while (cp > fbuf2 && !ISDIRSEP(cp[-1]))
225 cp--;
226 strcpy(cp, RFTEMPLATE);
227 prvr = mktemp(fbuf2);
228 if (rename(fbuf, prvr) < 0)
229 if (errno == ENOENT) { /* ghost file */
230 sprintf(errmsg,
231 "new output file \"%s\"",
232 fbuf);
233 error(WARNING, errmsg);
234 prvr = NULL;
235 } else { /* serious error */
236 sprintf(errmsg,
237 "cannot rename \"%s\" to \"%s\"",
238 fbuf, prvr);
239 error(SYSTEM, errmsg);
240 }
241 }
242 }
243 npicts = 0; /* render sequence */
244 do {
245 if (seq && nextview(stdin) == EOF)
246 break;
247 pctdone = 0.0;
248 if (pout != NULL) {
249 sprintf(fbuf, pout, seq);
250 if (file_exists(fbuf)) {
251 if (prvr != NULL || !strcmp(fbuf, pout)) {
252 sprintf(errmsg,
253 "output file \"%s\" exists",
254 fbuf);
255 error(USER, errmsg);
256 }
257 continue; /* don't clobber */
258 }
259 if (freopen(fbuf, "w", stdout) == NULL) {
260 sprintf(errmsg,
261 "cannot open output file \"%s\"", fbuf);
262 error(SYSTEM, errmsg);
263 }
264 #ifdef MSDOS
265 setmode(fileno(stdout), O_BINARY);
266 #endif
267 dupheader();
268 }
269 hres = hresolu; vres = vresolu; pa = pixaspect;
270 if (prvr != NULL)
271 if (viewfile(prvr, &ourview, &rs) <= 0
272 || rs.or != PIXSTANDARD) {
273 sprintf(errmsg,
274 "cannot recover view parameters from \"%s\"", prvr);
275 error(WARNING, errmsg);
276 } else {
277 pa = 0.0;
278 hres = scanlen(&rs);
279 vres = numscans(&rs);
280 }
281 if ((cp = setview(&ourview)) != NULL)
282 error(USER, cp);
283 normaspect(viewaspect(&ourview), &pa, &hres, &vres);
284 if (seq) {
285 if (ralrm > 0) {
286 fprintf(stderr, "FRAME %d:", seq);
287 fprintview(&ourview, stderr);
288 putc('\n', stderr);
289 fflush(stderr);
290 }
291 printf("FRAME=%d\n", seq);
292 }
293 fputs(VIEWSTR, stdout);
294 fprintview(&ourview, stdout);
295 putchar('\n');
296 if (pa < .99 || pa > 1.01)
297 fputaspect(pa, stdout);
298 fputformat(COLRFMT, stdout);
299 putchar('\n');
300 if (zout != NULL)
301 sprintf(cp=fbuf, zout, seq);
302 else
303 cp = NULL;
304 render(cp, prvr);
305 prvr = NULL;
306 npicts++;
307 } while (seq++);
308 /* check that we did something */
309 if (npicts == 0)
310 error(WARNING, "no output produced");
311 }
312
313
314 nextview(fp) /* get next view from fp */
315 FILE *fp;
316 {
317 char linebuf[256];
318
319 while (fgets(linebuf, sizeof(linebuf), fp) != NULL)
320 if (isview(linebuf) && sscanview(&ourview, linebuf) > 0)
321 return(0);
322 return(EOF);
323 }
324
325
326 render(zfile, oldfile) /* render the scene */
327 char *zfile, *oldfile;
328 {
329 extern long lseek();
330 COLOR *scanbar[MAXDIV+1]; /* scanline arrays of pixel values */
331 float *zbar[MAXDIV+1]; /* z values */
332 char *sampdens; /* previous sample density */
333 int ypos; /* current scanline */
334 int ystep; /* current y step size */
335 int hstep; /* h step size */
336 int zfd;
337 COLOR *colptr;
338 float *zptr;
339 register int i;
340 /* allocate scanlines */
341 for (i = 0; i <= psample; i++) {
342 scanbar[i] = (COLOR *)malloc(hres*sizeof(COLOR));
343 if (scanbar[i] == NULL)
344 goto memerr;
345 }
346 hstep = (psample*140+49)/99; /* quincunx sampling */
347 ystep = (psample*99+70)/140;
348 if (hstep > 2) {
349 i = hres/hstep + 2;
350 if ((sampdens = malloc(i)) == NULL)
351 goto memerr;
352 while (i--)
353 sampdens[i] = hstep;
354 } else
355 sampdens = NULL;
356 /* open z-file */
357 if (zfile != NULL) {
358 if ((zfd = open(zfile, O_WRONLY|O_CREAT, 0666)) == -1) {
359 sprintf(errmsg, "cannot open z-file \"%s\"", zfile);
360 error(SYSTEM, errmsg);
361 }
362 #ifdef MSDOS
363 setmode(zfd, O_BINARY);
364 #endif
365 for (i = 0; i <= psample; i++) {
366 zbar[i] = (float *)malloc(hres*sizeof(float));
367 if (zbar[i] == NULL)
368 goto memerr;
369 }
370 } else {
371 zfd = -1;
372 for (i = 0; i <= psample; i++)
373 zbar[i] = NULL;
374 }
375 /* write out boundaries */
376 fprtresolu(hres, vres, stdout);
377 /* recover file and compute first */
378 i = salvage(oldfile);
379 if (zfd != -1 && i > 0 &&
380 lseek(zfd, (long)i*hres*sizeof(float), 0) == -1)
381 error(SYSTEM, "z-file seek error in render");
382 pctdone = 100.0*i/vres;
383 if (ralrm > 0) /* report init stats */
384 report();
385 #ifndef BSD
386 else
387 #endif
388 signal(SIGCONT, report);
389 ypos = vres-1 - i;
390 fillscanline(scanbar[0], zbar[0], sampdens, hres, ypos, hstep);
391 /* compute scanlines */
392 for (ypos -= ystep; ypos > -ystep; ypos -= ystep) {
393 /* bottom adjust? */
394 if (ypos < 0) {
395 ystep += ypos;
396 ypos = 0;
397 }
398 colptr = scanbar[ystep]; /* move base to top */
399 scanbar[ystep] = scanbar[0];
400 scanbar[0] = colptr;
401 zptr = zbar[ystep];
402 zbar[ystep] = zbar[0];
403 zbar[0] = zptr;
404 /* fill base line */
405 fillscanline(scanbar[0], zbar[0], sampdens,
406 hres, ypos, hstep);
407 /* fill bar */
408 fillscanbar(scanbar, zbar, hres, ypos, ystep);
409 /* write it out */
410 #ifndef BSD
411 signal(SIGCONT, SIG_IGN); /* don't interrupt writes */
412 #endif
413 for (i = ystep; i > 0; i--) {
414 if (zfd != -1 && write(zfd, (char *)zbar[i],
415 hres*sizeof(float))
416 < hres*sizeof(float))
417 goto writerr;
418 if (fwritescan(scanbar[i], hres, stdout) < 0)
419 goto writerr;
420 }
421 if (fflush(stdout) == EOF)
422 goto writerr;
423 /* record progress */
424 pctdone = 100.0*(vres-1-ypos)/vres;
425 if (ralrm > 0 && time((long *)0) >= tlastrept+ralrm)
426 report();
427 #ifndef BSD
428 else
429 signal(SIGCONT, report);
430 #endif
431 }
432 /* clean up */
433 signal(SIGCONT, SIG_IGN);
434 if (zfd != -1) {
435 if (write(zfd, (char *)zbar[0], hres*sizeof(float))
436 < hres*sizeof(float))
437 goto writerr;
438 if (close(zfd) == -1)
439 goto writerr;
440 for (i = 0; i <= psample; i++)
441 free((char *)zbar[i]);
442 }
443 fwritescan(scanbar[0], hres, stdout);
444 if (fflush(stdout) == EOF)
445 goto writerr;
446 for (i = 0; i <= psample; i++)
447 free((char *)scanbar[i]);
448 if (sampdens != NULL)
449 free(sampdens);
450 pctdone = 100.0;
451 if (ralrm > 0)
452 report();
453 signal(SIGCONT, SIG_DFL);
454 return;
455 writerr:
456 error(SYSTEM, "write error in render");
457 memerr:
458 error(SYSTEM, "out of memory in render");
459 }
460
461
462 fillscanline(scanline, zline, sd, xres, y, xstep) /* fill scan at y */
463 register COLOR *scanline;
464 register float *zline;
465 register char *sd;
466 int xres, y, xstep;
467 {
468 static int nc = 0; /* number of calls */
469 int bl = xstep, b = xstep;
470 double z;
471 register int i;
472
473 z = pixvalue(scanline[0], 0, y);
474 if (zline) zline[0] = z;
475 /* zig-zag start for quincunx pattern */
476 for (i = ++nc & 1 ? xstep : xstep/2; i < xres-1+xstep; i += xstep) {
477 if (i >= xres) {
478 xstep += xres-1-i;
479 i = xres-1;
480 }
481 z = pixvalue(scanline[i], i, y);
482 if (zline) zline[i] = z;
483 if (sd) b = sd[0] > sd[1] ? sd[0] : sd[1];
484 if (i <= xstep)
485 b = fillsample(scanline, zline, 0, y, i, 0, b/2);
486 else
487 b = fillsample(scanline+i-xstep,
488 zline ? zline+i-xstep : NULL,
489 i-xstep, y, xstep, 0, b/2);
490 if (sd) *sd++ = nc & 1 ? bl : b;
491 bl = b;
492 }
493 if (sd && nc & 1) *sd = bl;
494 }
495
496
497 fillscanbar(scanbar, zbar, xres, y, ysize) /* fill interior */
498 register COLOR *scanbar[];
499 register float *zbar[];
500 int xres, y, ysize;
501 {
502 COLOR vline[MAXDIV+1];
503 float zline[MAXDIV+1];
504 int b = ysize;
505 register int i, j;
506
507 for (i = 0; i < xres; i++) {
508
509 copycolor(vline[0], scanbar[0][i]);
510 copycolor(vline[ysize], scanbar[ysize][i]);
511 if (zbar[0]) {
512 zline[0] = zbar[0][i];
513 zline[ysize] = zbar[ysize][i];
514 }
515
516 b = fillsample(vline, zbar[0] ? zline : NULL,
517 i, y, 0, ysize, b/2);
518
519 for (j = 1; j < ysize; j++)
520 copycolor(scanbar[j][i], vline[j]);
521 if (zbar[0])
522 for (j = 1; j < ysize; j++)
523 zbar[j][i] = zline[j];
524 }
525 }
526
527
528 int
529 fillsample(colline, zline, x, y, xlen, ylen, b) /* fill interior points */
530 register COLOR *colline;
531 register float *zline;
532 int x, y;
533 int xlen, ylen;
534 int b;
535 {
536 double ratio;
537 double z;
538 COLOR ctmp;
539 int ncut;
540 register int len;
541
542 if (xlen > 0) /* x or y length is zero */
543 len = xlen;
544 else
545 len = ylen;
546
547 if (len <= 1) /* limit recursion */
548 return(0);
549
550 if (b > 0
551 || (zline && 2.*fabs(zline[0]-zline[len]) > maxdiff*(zline[0]+zline[len]))
552 || bigdiff(colline[0], colline[len], maxdiff)) {
553
554 z = pixvalue(colline[len>>1], x + (xlen>>1), y + (ylen>>1));
555 if (zline) zline[len>>1] = z;
556 ncut = 1;
557
558 } else { /* interpolate */
559
560 copycolor(colline[len>>1], colline[len]);
561 ratio = (double)(len>>1) / len;
562 scalecolor(colline[len>>1], ratio);
563 if (zline) zline[len>>1] = zline[len] * ratio;
564 ratio = 1.0 - ratio;
565 copycolor(ctmp, colline[0]);
566 scalecolor(ctmp, ratio);
567 addcolor(colline[len>>1], ctmp);
568 if (zline) zline[len>>1] += zline[0] * ratio;
569 ncut = 0;
570 }
571 /* recurse */
572 ncut += fillsample(colline, zline, x, y, xlen>>1, ylen>>1, (b-1)/2);
573
574 ncut += fillsample(colline+(len>>1), zline ? zline+(len>>1) : NULL,
575 x+(xlen>>1), y+(ylen>>1),
576 xlen-(xlen>>1), ylen-(ylen>>1), b/2);
577
578 return(ncut);
579 }
580
581
582 double
583 pixvalue(col, x, y) /* compute pixel value */
584 COLOR col; /* returned color */
585 int x, y; /* pixel position */
586 {
587 static RAY thisray;
588
589 if (viewray(thisray.rorg, thisray.rdir, &ourview,
590 (x+pixjitter())/hres, (y+pixjitter())/vres) < 0) {
591 setcolor(col, 0.0, 0.0, 0.0);
592 return(0.0);
593 }
594
595 rayorigin(&thisray, NULL, PRIMARY, 1.0);
596
597 samplendx = pixnumber(x,y,hres,vres); /* set pixel index */
598
599 rayvalue(&thisray); /* trace ray */
600
601 copycolor(col, thisray.rcol); /* return color */
602
603 return(thisray.rt); /* return distance */
604 }
605
606
607 int
608 salvage(oldfile) /* salvage scanlines from killed program */
609 char *oldfile;
610 {
611 COLR *scanline;
612 FILE *fp;
613 int x, y;
614
615 if (oldfile == NULL)
616 return(0);
617
618 if ((fp = fopen(oldfile, "r")) == NULL) {
619 sprintf(errmsg, "cannot open recover file \"%s\"", oldfile);
620 error(WARNING, errmsg);
621 return(0);
622 }
623 #ifdef MSDOS
624 setmode(fileno(fp), O_BINARY);
625 #endif
626 /* discard header */
627 getheader(fp, NULL, NULL);
628 /* get picture size */
629 if (!fscnresolu(&x, &y, fp)) {
630 sprintf(errmsg, "bad recover file \"%s\" - not removed",
631 oldfile);
632 error(WARNING, errmsg);
633 fclose(fp);
634 return(0);
635 }
636
637 if (x != hres || y != vres) {
638 sprintf(errmsg, "resolution mismatch in recover file \"%s\"",
639 oldfile);
640 error(USER, errmsg);
641 }
642
643 scanline = (COLR *)malloc(hres*sizeof(COLR));
644 if (scanline == NULL)
645 error(SYSTEM, "out of memory in salvage");
646 for (y = 0; y < vres; y++) {
647 if (freadcolrs(scanline, hres, fp) < 0)
648 break;
649 if (fwritecolrs(scanline, hres, stdout) < 0)
650 goto writerr;
651 }
652 if (fflush(stdout) == EOF)
653 goto writerr;
654 free((char *)scanline);
655 fclose(fp);
656 unlink(oldfile);
657 return(y);
658 writerr:
659 sprintf(errmsg, "write error during recovery of \"%s\"", oldfile);
660 error(SYSTEM, errmsg);
661 }
662
663
664 int
665 pixnumber(x, y, xres, yres) /* compute pixel index (brushed) */
666 register int x, y;
667 int xres, yres;
668 {
669 x -= y;
670 while (x < 0)
671 x += xres;
672 return((((x>>2)*yres + y) << 2) + (x & 3));
673 }