ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rpict.c
Revision: 2.52
Committed: Sat Feb 22 02:07:29 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.51: +90 -21 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * rpict.c - routines and variables for picture generation.
6 */
7
8 /* ====================================================================
9 * The Radiance Software License, Version 1.0
10 *
11 * Copyright (c) 1990 - 2002 The Regents of the University of California,
12 * through Lawrence Berkeley National Laboratory. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in
23 * the documentation and/or other materials provided with the
24 * distribution.
25 *
26 * 3. The end-user documentation included with the redistribution,
27 * if any, must include the following acknowledgment:
28 * "This product includes Radiance software
29 * (http://radsite.lbl.gov/)
30 * developed by the Lawrence Berkeley National Laboratory
31 * (http://www.lbl.gov/)."
32 * Alternately, this acknowledgment may appear in the software itself,
33 * if and wherever such third-party acknowledgments normally appear.
34 *
35 * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36 * and "The Regents of the University of California" must
37 * not be used to endorse or promote products derived from this
38 * software without prior written permission. For written
39 * permission, please contact [email protected].
40 *
41 * 5. Products derived from this software may not be called "Radiance",
42 * nor may "Radiance" appear in their name, without prior written
43 * permission of Lawrence Berkeley National Laboratory.
44 *
45 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48 * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 * ====================================================================
58 *
59 * This software consists of voluntary contributions made by many
60 * individuals on behalf of Lawrence Berkeley National Laboratory. For more
61 * information on Lawrence Berkeley National Laboratory, please see
62 * <http://www.lbl.gov/>.
63 */
64
65 #include "ray.h"
66
67 #include <sys/types.h>
68
69 #ifndef NIX
70 #ifdef BSD
71 #include <sys/time.h>
72 #include <sys/resource.h>
73 #else
74 #include <sys/times.h>
75 #include <unistd.h>
76 #endif
77 #endif
78
79 extern time_t time();
80
81 #include <signal.h>
82
83 #include "view.h"
84
85 #include "random.h"
86
87 #include "paths.h"
88
89 #define RFTEMPLATE "rfXXXXXX"
90
91 #ifndef SIGCONT
92 #define SIGCONT SIGIO
93 #endif
94
95 CUBE thescene; /* our scene */
96 OBJECT nsceneobjs; /* number of objects in our scene */
97
98 int dimlist[MAXDIM]; /* sampling dimensions */
99 int ndims = 0; /* number of sampling dimensions */
100 int samplendx; /* sample index number */
101
102 extern void ambnotify();
103 void (*addobjnotify[])() = {ambnotify, NULL};
104
105 VIEW ourview = STDVIEW; /* view parameters */
106 int hresolu = 512; /* horizontal resolution */
107 int vresolu = 512; /* vertical resolution */
108 double pixaspect = 1.0; /* pixel aspect ratio */
109
110 int psample = 4; /* pixel sample size */
111 double maxdiff = .05; /* max. difference for interpolation */
112 double dstrpix = 0.67; /* square pixel distribution */
113
114 double mblur = 0.; /* motion blur parameter */
115
116 void (*trace)() = NULL; /* trace call */
117
118 int do_irrad = 0; /* compute irradiance? */
119
120 double dstrsrc = 0.0; /* square source distribution */
121 double shadthresh = .05; /* shadow threshold */
122 double shadcert = .5; /* shadow certainty */
123 int directrelay = 1; /* number of source relays */
124 int vspretest = 512; /* virtual source pretest density */
125 int directvis = 1; /* sources visible? */
126 double srcsizerat = .25; /* maximum ratio source size/dist. */
127
128 COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
129 COLOR salbedo = BLKCOLOR; /* global scattering albedo */
130 double seccg = 0.; /* global scattering eccentricity */
131 double ssampdist = 0.; /* scatter sampling distance */
132
133 double specthresh = .15; /* specular sampling threshold */
134 double specjitter = 1.; /* specular sampling jitter */
135
136 int backvis = 1; /* back face visibility */
137
138 int maxdepth = 6; /* maximum recursion depth */
139 double minweight = 5e-3; /* minimum ray weight */
140
141 char *ambfile = NULL; /* ambient file name */
142 COLOR ambval = BLKCOLOR; /* ambient value */
143 int ambvwt = 0; /* initial weight for ambient value */
144 double ambacc = 0.2; /* ambient accuracy */
145 int ambres = 32; /* ambient resolution */
146 int ambdiv = 128; /* ambient divisions */
147 int ambssamp = 0; /* ambient super-samples */
148 int ambounce = 0; /* ambient bounces */
149 char *amblist[128]; /* ambient include/exclude list */
150 int ambincl = -1; /* include == 1, exclude == 0 */
151
152 int ralrm = 0; /* seconds between reports */
153
154 double pctdone = 0.0; /* percentage done */
155 time_t tlastrept = 0L; /* time at last report */
156 time_t tstart; /* starting time */
157
158 #define MAXDIV 16 /* maximum sample size */
159
160 #define pixjitter() (.5+dstrpix*(.5-frandom()))
161
162 int hres, vres; /* resolution for this frame */
163
164 static VIEW lastview; /* the previous view input */
165
166 extern char *mktemp();
167
168 void report();
169
170 double pixvalue();
171
172 #ifdef NIX
173 #define file_exists(f) (access(f,F_OK)==0)
174 #else
175 #include <sys/types.h>
176 #include <sys/stat.h>
177 int
178 file_exists(fname) /* ordinary file exists? */
179 char *fname;
180 {
181 struct stat sbuf;
182 if (stat(fname, &sbuf) < 0) return(0);
183 return((sbuf.st_mode & S_IFREG) != 0);
184 }
185 #endif
186
187
188 void
189 quit(code) /* quit program */
190 int code;
191 {
192 if (code) /* report status */
193 report();
194 #ifndef NIX
195 headclean(); /* delete header file */
196 pfclean(); /* clean up persist files */
197 #endif
198 exit(code);
199 }
200
201
202 #ifndef NIX
203 void
204 report() /* report progress */
205 {
206 extern char *myhostname();
207 double u, s;
208 #ifdef BSD
209 struct rusage rubuf;
210 #else
211 struct tms tbuf;
212 double period;
213 #endif
214
215 tlastrept = time((time_t *)NULL);
216 #ifdef BSD
217 getrusage(RUSAGE_SELF, &rubuf);
218 u = rubuf.ru_utime.tv_sec + rubuf.ru_utime.tv_usec/1e6;
219 s = rubuf.ru_stime.tv_sec + rubuf.ru_stime.tv_usec/1e6;
220 getrusage(RUSAGE_CHILDREN, &rubuf);
221 u += rubuf.ru_utime.tv_sec + rubuf.ru_utime.tv_usec/1e6;
222 s += rubuf.ru_stime.tv_sec + rubuf.ru_stime.tv_usec/1e6;
223 #else
224 times(&tbuf);
225 #ifdef _SC_CLK_TCK
226 period = 1.0 / sysconf(_SC_CLK_TCK);
227 #else
228 period = 1.0 / 60.0;
229 #endif
230 u = ( tbuf.tms_utime + tbuf.tms_cutime ) * period;
231 s = ( tbuf.tms_stime + tbuf.tms_cstime ) * period;
232 #endif
233
234 sprintf(errmsg,
235 "%lu rays, %4.2f%% after %.3fu %.3fs %.3fr hours on %s\n",
236 nrays, pctdone, u/3600., s/3600.,
237 (tlastrept-tstart)/3600., myhostname());
238 eputs(errmsg);
239 #ifndef BSD
240 signal(SIGCONT, report);
241 #endif
242 }
243 #else
244 void
245 report() /* report progress */
246 {
247 tlastrept = time((time_t *)NULL);
248 sprintf(errmsg, "%lu rays, %4.2f%% after %5.4f hours\n",
249 nrays, pctdone, (tlastrept-tstart)/3600.0);
250 eputs(errmsg);
251 }
252 #endif
253
254
255 void
256 rpict(seq, pout, zout, prvr) /* generate image(s) */
257 int seq;
258 char *pout, *zout, *prvr;
259 /*
260 * If seq is greater than zero, then we will render a sequence of
261 * images based on view parameter strings read from the standard input.
262 * If pout is NULL, then all images will be sent to the standard ouput.
263 * If seq is greater than zero and prvr is an integer, then it is the
264 * frame number at which rendering should begin. Preceeding view parameter
265 * strings will be skipped in the input.
266 * If pout and prvr are the same, prvr is renamed to avoid overwriting.
267 * Note that pout and zout should contain %d format specifications for
268 * sequenced file naming.
269 */
270 {
271 extern char *rindex(), *strncpy(), *strcat(), *strcpy();
272 char fbuf[128], fbuf2[128];
273 int npicts;
274 register char *cp;
275 RESOLU rs;
276 double pa;
277 /* check sampling */
278 if (psample < 1)
279 psample = 1;
280 else if (psample > MAXDIV) {
281 sprintf(errmsg, "pixel sampling reduced from %d to %d",
282 psample, MAXDIV);
283 error(WARNING, errmsg);
284 psample = MAXDIV;
285 }
286 /* get starting frame */
287 if (seq <= 0)
288 seq = 0;
289 else if (prvr != NULL && isint(prvr)) {
290 register int rn; /* skip to specified view */
291 if ((rn = atoi(prvr)) < seq)
292 error(USER, "recover frame less than start frame");
293 if (pout == NULL)
294 error(USER, "missing output file specification");
295 for ( ; seq < rn; seq++)
296 if (nextview(stdin) == EOF)
297 error(USER, "unexpected EOF on view input");
298 setview(&ourview);
299 prvr = fbuf; /* mark for renaming */
300 }
301 if (pout != NULL & prvr != NULL) {
302 sprintf(fbuf, pout, seq);
303 if (!strcmp(prvr, fbuf)) { /* rename */
304 strcpy(fbuf2, fbuf);
305 for (cp = fbuf2; *cp; cp++)
306 ;
307 while (cp > fbuf2 && !ISDIRSEP(cp[-1]))
308 cp--;
309 strcpy(cp, RFTEMPLATE);
310 prvr = mktemp(fbuf2);
311 if (rename(fbuf, prvr) < 0)
312 if (errno == ENOENT) { /* ghost file */
313 sprintf(errmsg,
314 "new output file \"%s\"",
315 fbuf);
316 error(WARNING, errmsg);
317 prvr = NULL;
318 } else { /* serious error */
319 sprintf(errmsg,
320 "cannot rename \"%s\" to \"%s\"",
321 fbuf, prvr);
322 error(SYSTEM, errmsg);
323 }
324 }
325 }
326 npicts = 0; /* render sequence */
327 do {
328 if (seq && nextview(stdin) == EOF)
329 break;
330 pctdone = 0.0;
331 if (pout != NULL) {
332 sprintf(fbuf, pout, seq);
333 if (file_exists(fbuf)) {
334 if (prvr != NULL || !strcmp(fbuf, pout)) {
335 sprintf(errmsg,
336 "output file \"%s\" exists",
337 fbuf);
338 error(USER, errmsg);
339 }
340 setview(&ourview);
341 continue; /* don't clobber */
342 }
343 if (freopen(fbuf, "w", stdout) == NULL) {
344 sprintf(errmsg,
345 "cannot open output file \"%s\"", fbuf);
346 error(SYSTEM, errmsg);
347 }
348 #ifdef MSDOS
349 setmode(fileno(stdout), O_BINARY);
350 #endif
351 dupheader();
352 }
353 hres = hresolu; vres = vresolu; pa = pixaspect;
354 if (prvr != NULL)
355 if (viewfile(prvr, &ourview, &rs) <= 0
356 || rs.rt != PIXSTANDARD) {
357 sprintf(errmsg,
358 "cannot recover view parameters from \"%s\"", prvr);
359 error(WARNING, errmsg);
360 } else {
361 pa = 0.0;
362 hres = scanlen(&rs);
363 vres = numscans(&rs);
364 }
365 if ((cp = setview(&ourview)) != NULL)
366 error(USER, cp);
367 normaspect(viewaspect(&ourview), &pa, &hres, &vres);
368 if (seq) {
369 if (ralrm > 0) {
370 fprintf(stderr, "FRAME %d:", seq);
371 fprintview(&ourview, stderr);
372 putc('\n', stderr);
373 fflush(stderr);
374 }
375 printf("FRAME=%d\n", seq);
376 }
377 fputs(VIEWSTR, stdout);
378 fprintview(&ourview, stdout);
379 putchar('\n');
380 if (pa < .99 || pa > 1.01)
381 fputaspect(pa, stdout);
382 fputformat(COLRFMT, stdout);
383 putchar('\n');
384 if (zout != NULL)
385 sprintf(cp=fbuf, zout, seq);
386 else
387 cp = NULL;
388 render(cp, prvr);
389 prvr = NULL;
390 npicts++;
391 } while (seq++);
392 /* check that we did something */
393 if (npicts == 0)
394 error(WARNING, "no output produced");
395 }
396
397
398 nextview(fp) /* get next view from fp */
399 FILE *fp;
400 {
401 char linebuf[256];
402
403 copystruct(&lastview, &ourview);
404 while (fgets(linebuf, sizeof(linebuf), fp) != NULL)
405 if (isview(linebuf) && sscanview(&ourview, linebuf) > 0)
406 return(0);
407 return(EOF);
408 }
409
410
411 render(zfile, oldfile) /* render the scene */
412 char *zfile, *oldfile;
413 {
414 COLOR *scanbar[MAXDIV+1]; /* scanline arrays of pixel values */
415 float *zbar[MAXDIV+1]; /* z values */
416 char *sampdens; /* previous sample density */
417 int ypos; /* current scanline */
418 int ystep; /* current y step size */
419 int hstep; /* h step size */
420 int zfd;
421 COLOR *colptr;
422 float *zptr;
423 register int i;
424 /* check for empty image */
425 if (hres <= 0 || vres <= 0) {
426 error(WARNING, "empty output picture");
427 fprtresolu(0, 0, stdout);
428 return;
429 }
430 /* allocate scanlines */
431 for (i = 0; i <= psample; i++) {
432 scanbar[i] = (COLOR *)malloc(hres*sizeof(COLOR));
433 if (scanbar[i] == NULL)
434 goto memerr;
435 }
436 hstep = (psample*140+49)/99; /* quincunx sampling */
437 ystep = (psample*99+70)/140;
438 if (hstep > 2) {
439 i = hres/hstep + 2;
440 if ((sampdens = (char *)malloc(i)) == NULL)
441 goto memerr;
442 while (i--)
443 sampdens[i] = hstep;
444 } else
445 sampdens = NULL;
446 /* open z-file */
447 if (zfile != NULL) {
448 if ((zfd = open(zfile, O_WRONLY|O_CREAT, 0666)) == -1) {
449 sprintf(errmsg, "cannot open z-file \"%s\"", zfile);
450 error(SYSTEM, errmsg);
451 }
452 #ifdef MSDOS
453 setmode(zfd, O_BINARY);
454 #endif
455 for (i = 0; i <= psample; i++) {
456 zbar[i] = (float *)malloc(hres*sizeof(float));
457 if (zbar[i] == NULL)
458 goto memerr;
459 }
460 } else {
461 zfd = -1;
462 for (i = 0; i <= psample; i++)
463 zbar[i] = NULL;
464 }
465 /* write out boundaries */
466 fprtresolu(hres, vres, stdout);
467 /* recover file and compute first */
468 i = salvage(oldfile);
469 if (i >= vres)
470 goto alldone;
471 if (zfd != -1 && i > 0 &&
472 lseek(zfd, (off_t)i*hres*sizeof(float), 0) < 0)
473 error(SYSTEM, "z-file seek error in render");
474 pctdone = 100.0*i/vres;
475 if (ralrm > 0) /* report init stats */
476 report();
477 #ifndef BSD
478 else
479 #endif
480 signal(SIGCONT, report);
481 ypos = vres-1 - i; /* initialize sampling */
482 if (directvis)
483 init_drawsources(psample);
484 fillscanline(scanbar[0], zbar[0], sampdens, hres, ypos, hstep);
485 /* compute scanlines */
486 for (ypos -= ystep; ypos > -ystep; ypos -= ystep) {
487 /* bottom adjust? */
488 if (ypos < 0) {
489 ystep += ypos;
490 ypos = 0;
491 }
492 colptr = scanbar[ystep]; /* move base to top */
493 scanbar[ystep] = scanbar[0];
494 scanbar[0] = colptr;
495 zptr = zbar[ystep];
496 zbar[ystep] = zbar[0];
497 zbar[0] = zptr;
498 /* fill base line */
499 fillscanline(scanbar[0], zbar[0], sampdens,
500 hres, ypos, hstep);
501 /* fill bar */
502 fillscanbar(scanbar, zbar, hres, ypos, ystep);
503 if (directvis) /* add bitty sources */
504 drawsources(scanbar, zbar, 0, hres, ypos, ystep);
505 /* write it out */
506 #ifndef BSD
507 signal(SIGCONT, SIG_IGN); /* don't interrupt writes */
508 #endif
509 for (i = ystep; i > 0; i--) {
510 if (zfd != -1 && write(zfd, (char *)zbar[i],
511 hres*sizeof(float))
512 < hres*sizeof(float))
513 goto writerr;
514 if (fwritescan(scanbar[i], hres, stdout) < 0)
515 goto writerr;
516 }
517 if (fflush(stdout) == EOF)
518 goto writerr;
519 /* record progress */
520 pctdone = 100.0*(vres-1-ypos)/vres;
521 if (ralrm > 0 && time((time_t *)NULL) >= tlastrept+ralrm)
522 report();
523 #ifndef BSD
524 else
525 signal(SIGCONT, report);
526 #endif
527 }
528 /* clean up */
529 signal(SIGCONT, SIG_IGN);
530 if (zfd != -1 && write(zfd, (char *)zbar[0], hres*sizeof(float))
531 < hres*sizeof(float))
532 goto writerr;
533 fwritescan(scanbar[0], hres, stdout);
534 if (fflush(stdout) == EOF)
535 goto writerr;
536 alldone:
537 if (zfd != -1) {
538 if (close(zfd) == -1)
539 goto writerr;
540 for (i = 0; i <= psample; i++)
541 free((void *)zbar[i]);
542 }
543 for (i = 0; i <= psample; i++)
544 free((void *)scanbar[i]);
545 if (sampdens != NULL)
546 free(sampdens);
547 pctdone = 100.0;
548 if (ralrm > 0)
549 report();
550 signal(SIGCONT, SIG_DFL);
551 return;
552 writerr:
553 error(SYSTEM, "write error in render");
554 memerr:
555 error(SYSTEM, "out of memory in render");
556 }
557
558
559 fillscanline(scanline, zline, sd, xres, y, xstep) /* fill scan at y */
560 register COLOR *scanline;
561 register float *zline;
562 register char *sd;
563 int xres, y, xstep;
564 {
565 static int nc = 0; /* number of calls */
566 int bl = xstep, b = xstep;
567 double z;
568 register int i;
569
570 z = pixvalue(scanline[0], 0, y);
571 if (zline) zline[0] = z;
572 /* zig-zag start for quincunx pattern */
573 for (i = ++nc & 1 ? xstep : xstep/2; i < xres-1+xstep; i += xstep) {
574 if (i >= xres) {
575 xstep += xres-1-i;
576 i = xres-1;
577 }
578 z = pixvalue(scanline[i], i, y);
579 if (zline) zline[i] = z;
580 if (sd) b = sd[0] > sd[1] ? sd[0] : sd[1];
581 if (i <= xstep)
582 b = fillsample(scanline, zline, 0, y, i, 0, b/2);
583 else
584 b = fillsample(scanline+i-xstep,
585 zline ? zline+i-xstep : (float *)NULL,
586 i-xstep, y, xstep, 0, b/2);
587 if (sd) *sd++ = nc & 1 ? bl : b;
588 bl = b;
589 }
590 if (sd && nc & 1) *sd = bl;
591 }
592
593
594 fillscanbar(scanbar, zbar, xres, y, ysize) /* fill interior */
595 register COLOR *scanbar[];
596 register float *zbar[];
597 int xres, y, ysize;
598 {
599 COLOR vline[MAXDIV+1];
600 float zline[MAXDIV+1];
601 int b = ysize;
602 register int i, j;
603
604 for (i = 0; i < xres; i++) {
605 copycolor(vline[0], scanbar[0][i]);
606 copycolor(vline[ysize], scanbar[ysize][i]);
607 if (zbar[0]) {
608 zline[0] = zbar[0][i];
609 zline[ysize] = zbar[ysize][i];
610 }
611 b = fillsample(vline, zbar[0] ? zline : (float *)NULL,
612 i, y, 0, ysize, b/2);
613
614 for (j = 1; j < ysize; j++)
615 copycolor(scanbar[j][i], vline[j]);
616 if (zbar[0])
617 for (j = 1; j < ysize; j++)
618 zbar[j][i] = zline[j];
619 }
620 }
621
622
623 int
624 fillsample(colline, zline, x, y, xlen, ylen, b) /* fill interior points */
625 register COLOR *colline;
626 register float *zline;
627 int x, y;
628 int xlen, ylen;
629 int b;
630 {
631 double ratio;
632 double z;
633 COLOR ctmp;
634 int ncut;
635 register int len;
636
637 if (xlen > 0) /* x or y length is zero */
638 len = xlen;
639 else
640 len = ylen;
641
642 if (len <= 1) /* limit recursion */
643 return(0);
644
645 if (b > 0 ||
646 (zline && 2.*fabs(zline[0]-zline[len]) > maxdiff*(zline[0]+zline[len]))
647 || bigdiff(colline[0], colline[len], maxdiff)) {
648
649 z = pixvalue(colline[len>>1], x + (xlen>>1), y + (ylen>>1));
650 if (zline) zline[len>>1] = z;
651 ncut = 1;
652 } else { /* interpolate */
653 copycolor(colline[len>>1], colline[len]);
654 ratio = (double)(len>>1) / len;
655 scalecolor(colline[len>>1], ratio);
656 if (zline) zline[len>>1] = zline[len] * ratio;
657 ratio = 1.0 - ratio;
658 copycolor(ctmp, colline[0]);
659 scalecolor(ctmp, ratio);
660 addcolor(colline[len>>1], ctmp);
661 if (zline) zline[len>>1] += zline[0] * ratio;
662 ncut = 0;
663 }
664 /* recurse */
665 ncut += fillsample(colline, zline, x, y, xlen>>1, ylen>>1, (b-1)/2);
666
667 ncut += fillsample(colline+(len>>1),
668 zline ? zline+(len>>1) : (float *)NULL,
669 x+(xlen>>1), y+(ylen>>1),
670 xlen-(xlen>>1), ylen-(ylen>>1), b/2);
671
672 return(ncut);
673 }
674
675
676 double
677 pixvalue(col, x, y) /* compute pixel value */
678 COLOR col; /* returned color */
679 int x, y; /* pixel position */
680 {
681 RAY thisray;
682 FVECT lorg, ldir;
683 double hpos, vpos, lmax, d;
684 /* compute view ray */
685 hpos = (x+pixjitter())/hres;
686 vpos = (y+pixjitter())/vres;
687 if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir,
688 &ourview, hpos, vpos)) < -FTINY) {
689 setcolor(col, 0.0, 0.0, 0.0);
690 return(0.0);
691 }
692
693 samplendx = pixnumber(x,y,hres,vres); /* set pixel index */
694
695 /* optional motion blur */
696 if (lastview.type && mblur > FTINY && (lmax = viewray(lorg, ldir,
697 &lastview, hpos, vpos)) >= -FTINY) {
698 register int i;
699 register double d = mblur*(.5-urand(281+samplendx));
700
701 thisray.rmax = (1.-d)*thisray.rmax + d*lmax;
702 for (i = 3; i--; ) {
703 thisray.rorg[i] = (1.-d)*thisray.rorg[i] + d*lorg[i];
704 thisray.rdir[i] = (1.-d)*thisray.rdir[i] + d*ldir[i];
705 }
706 if (normalize(thisray.rdir) == 0.0)
707 return(0.0);
708 }
709
710 rayorigin(&thisray, NULL, PRIMARY, 1.0);
711
712 rayvalue(&thisray); /* trace ray */
713
714 copycolor(col, thisray.rcol); /* return color */
715
716 return(thisray.rt); /* return distance */
717 }
718
719
720 int
721 salvage(oldfile) /* salvage scanlines from killed program */
722 char *oldfile;
723 {
724 COLR *scanline;
725 FILE *fp;
726 int x, y;
727
728 if (oldfile == NULL)
729 goto gotzip;
730
731 if ((fp = fopen(oldfile, "r")) == NULL) {
732 sprintf(errmsg, "cannot open recover file \"%s\"", oldfile);
733 error(WARNING, errmsg);
734 goto gotzip;
735 }
736 #ifdef MSDOS
737 setmode(fileno(fp), O_BINARY);
738 #endif
739 /* discard header */
740 getheader(fp, NULL, NULL);
741 /* get picture size */
742 if (!fscnresolu(&x, &y, fp)) {
743 sprintf(errmsg, "bad recover file \"%s\" - not removed",
744 oldfile);
745 error(WARNING, errmsg);
746 fclose(fp);
747 goto gotzip;
748 }
749
750 if (x != hres || y != vres) {
751 sprintf(errmsg, "resolution mismatch in recover file \"%s\"",
752 oldfile);
753 error(USER, errmsg);
754 }
755
756 scanline = (COLR *)malloc(hres*sizeof(COLR));
757 if (scanline == NULL)
758 error(SYSTEM, "out of memory in salvage");
759 for (y = 0; y < vres; y++) {
760 if (freadcolrs(scanline, hres, fp) < 0)
761 break;
762 if (fwritecolrs(scanline, hres, stdout) < 0)
763 goto writerr;
764 }
765 if (fflush(stdout) == EOF)
766 goto writerr;
767 free((void *)scanline);
768 fclose(fp);
769 unlink(oldfile);
770 return(y);
771 gotzip:
772 if (fflush(stdout) == EOF)
773 error(SYSTEM, "error writing picture header");
774 return(0);
775 writerr:
776 sprintf(errmsg, "write error during recovery of \"%s\"", oldfile);
777 error(SYSTEM, errmsg);
778 }
779
780
781 int
782 pixnumber(x, y, xres, yres) /* compute pixel index (brushed) */
783 register int x, y;
784 int xres, yres;
785 {
786 x -= y;
787 while (x < 0)
788 x += xres;
789 return((((x>>2)*yres + y) << 2) + (x & 3));
790 }