ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rview.c
Revision: 2.18
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.17: +88 -14 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

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.18 static const char RCSid[] = "$Id$";
3 greg 1.1 #endif
4     /*
5     * rview.c - routines and variables for interactive view generation.
6     *
7 greg 2.18 * External symbols declared in rpaint.h
8     */
9    
10     /* ====================================================================
11     * The Radiance Software License, Version 1.0
12     *
13     * Copyright (c) 1990 - 2002 The Regents of the University of California,
14     * through Lawrence Berkeley National Laboratory. All rights reserved.
15     *
16     * Redistribution and use in source and binary forms, with or without
17     * modification, are permitted provided that the following conditions
18     * are met:
19     *
20     * 1. Redistributions of source code must retain the above copyright
21     * notice, this list of conditions and the following disclaimer.
22     *
23     * 2. Redistributions in binary form must reproduce the above copyright
24     * notice, this list of conditions and the following disclaimer in
25     * the documentation and/or other materials provided with the
26     * distribution.
27     *
28     * 3. The end-user documentation included with the redistribution,
29     * if any, must include the following acknowledgment:
30     * "This product includes Radiance software
31     * (http://radsite.lbl.gov/)
32     * developed by the Lawrence Berkeley National Laboratory
33     * (http://www.lbl.gov/)."
34     * Alternately, this acknowledgment may appear in the software itself,
35     * if and wherever such third-party acknowledgments normally appear.
36     *
37     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
38     * and "The Regents of the University of California" must
39     * not be used to endorse or promote products derived from this
40     * software without prior written permission. For written
41     * permission, please contact [email protected].
42     *
43     * 5. Products derived from this software may not be called "Radiance",
44     * nor may "Radiance" appear in their name, without prior written
45     * permission of Lawrence Berkeley National Laboratory.
46     *
47     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
48     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
51     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
54     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
56     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
57     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58     * SUCH DAMAGE.
59     * ====================================================================
60     *
61     * This software consists of voluntary contributions made by many
62     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
63     * information on Lawrence Berkeley National Laboratory, please see
64     * <http://www.lbl.gov/>.
65 greg 1.1 */
66    
67 greg 1.15 #include "ray.h"
68 greg 1.1
69     #include "rpaint.h"
70    
71     #include <signal.h>
72    
73     #include <ctype.h>
74    
75 greg 2.18 CUBE thescene; /* our scene */
76     OBJECT nsceneobjs; /* number of objects in our scene */
77 greg 1.15
78     int dimlist[MAXDIM]; /* sampling dimensions */
79     int ndims = 0; /* number of sampling dimensions */
80     int samplendx = 0; /* index for this sample */
81 greg 1.1
82 greg 2.18 extern void ambnotify();
83     void (*addobjnotify[])() = {ambnotify, NULL};
84    
85     VIEW ourview = STDVIEW; /* viewing parameters */
86     int hresolu, vresolu; /* image resolution */
87    
88     void (*trace)() = NULL; /* trace call */
89    
90     int do_irrad = 0; /* compute irradiance? */
91    
92 greg 1.1 int psample = 8; /* pixel sample size */
93 greg 2.8 double maxdiff = .15; /* max. sample difference */
94 greg 1.1
95 greg 2.8 double exposure = 1.0; /* exposure for scene */
96 greg 1.1
97 greg 2.8 double dstrsrc = 0.0; /* square source distribution */
98     double shadthresh = .1; /* shadow threshold */
99     double shadcert = .25; /* shadow certainty */
100 greg 1.16 int directrelay = 0; /* number of source relays */
101 greg 1.18 int vspretest = 128; /* virtual source pretest density */
102 greg 2.9 int directvis = 1; /* sources visible? */
103 greg 2.8 double srcsizerat = 0.; /* maximum ratio source size/dist. */
104 greg 2.15
105     COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
106 greg 2.17 COLOR salbedo = BLKCOLOR; /* global scattering albedo */
107 greg 2.15 double seccg = 0.; /* global scattering eccentricity */
108     double ssampdist = 0.; /* scatter sampling distance */
109 greg 1.1
110 greg 2.8 double specthresh = .3; /* specular sampling threshold */
111     double specjitter = 1.; /* specular sampling jitter */
112 greg 2.5
113 greg 2.14 int backvis = 1; /* back face visibility */
114    
115 greg 1.1 int maxdepth = 4; /* maximum recursion depth */
116 greg 2.8 double minweight = 1e-2; /* minimum ray weight */
117 greg 1.1
118 greg 2.18 char *ambfile = NULL; /* ambient file name */
119 greg 1.1 COLOR ambval = BLKCOLOR; /* ambient value */
120 greg 2.16 int ambvwt = 0; /* initial weight for ambient value */
121 greg 2.8 double ambacc = 0.2; /* ambient accuracy */
122 greg 1.5 int ambres = 8; /* ambient resolution */
123 greg 1.1 int ambdiv = 32; /* ambient divisions */
124     int ambssamp = 0; /* ambient super-samples */
125     int ambounce = 0; /* ambient bounces */
126     char *amblist[128]; /* ambient include/exclude list */
127     int ambincl = -1; /* include == 1, exclude == 0 */
128    
129     int greyscale = 0; /* map colors to brightness? */
130 greg 2.18 char *dvcname = dev_default; /* output device name */
131 greg 1.1
132     struct driver *dev = NULL; /* driver functions */
133    
134 greg 2.11 char rifname[128]; /* rad input file name */
135    
136 greg 1.1 VIEW oldview; /* previous view parameters */
137    
138     PNODE ptrunk; /* the base of our image */
139     RECT pframe; /* current frame boundaries */
140     int pdepth; /* image depth in current frame */
141    
142 greg 1.12 static char *reserve_mem = NULL; /* pre-allocated reserve memory */
143    
144 greg 1.20 #define RESERVE_AMT 32768 /* amount of memory to reserve */
145 greg 1.12
146 greg 2.8 #define CTRL(c) ((c)-'@')
147 greg 1.1
148    
149 greg 2.18 void
150 greg 1.1 quit(code) /* quit program */
151     int code;
152     {
153 greg 2.10 #ifdef MSTATS
154     if (code == 2 && errno == ENOMEM)
155     printmemstats(stderr);
156     #endif
157 greg 1.1 devclose();
158     exit(code);
159     }
160    
161    
162 greg 2.18 void
163 greg 1.1 devopen(dname) /* open device driver */
164     char *dname;
165     {
166 greg 1.6 extern char *progname, *octname;
167 greg 1.7 char *id;
168 greg 1.1 register int i;
169 greg 1.6
170 greg 1.7 id = octname!=NULL ? octname : progname;
171 greg 1.1 /* check device table */
172     for (i = 0; devtable[i].name; i++)
173     if (!strcmp(dname, devtable[i].name))
174 greg 1.7 if ((dev = (*devtable[i].init)(dname, id)) == NULL) {
175 greg 1.1 sprintf(errmsg, "cannot initialize %s", dname);
176     error(USER, errmsg);
177     } else
178     return;
179 greg 2.8 #ifndef NIX
180 greg 1.1 /* not there, try exec */
181 greg 1.7 if ((dev = comm_init(dname, id)) == NULL) {
182 greg 1.1 sprintf(errmsg, "cannot start device \"%s\"", dname);
183     error(USER, errmsg);
184     }
185 greg 2.8 #endif
186 greg 1.1 }
187    
188    
189 greg 2.18 void
190 greg 1.1 devclose() /* close our device */
191     {
192     if (dev != NULL)
193     (*dev->close)();
194     dev = NULL;
195     }
196    
197    
198 greg 2.18 void
199 greg 1.1 printdevices() /* print list of output devices */
200     {
201     register int i;
202    
203     for (i = 0; devtable[i].name; i++)
204     printf("%-16s # %s\n", devtable[i].name, devtable[i].descrip);
205     }
206    
207    
208 greg 2.18 void
209 greg 1.1 rview() /* do a view */
210     {
211     char buf[32];
212    
213 greg 2.18 devopen(dvcname); /* open device */
214 greg 1.14 newimage(); /* start image (calls fillreserves) */
215    
216 greg 1.1 for ( ; ; ) { /* quit in command() */
217 greg 1.14 while (hresolu <= 1<<pdepth && vresolu <= 1<<pdepth)
218 greg 1.1 command("done: ");
219 greg 1.14 while (reserve_mem == NULL)
220     command("out of memory: ");
221     errno = 0;
222     if (hresolu <= psample<<pdepth && vresolu <= psample<<pdepth) {
223 greg 1.1 sprintf(buf, "%d sampling...\n", 1<<pdepth);
224     (*dev->comout)(buf);
225     rsample();
226     } else {
227     sprintf(buf, "%d refining...\n", 1<<pdepth);
228     (*dev->comout)(buf);
229 greg 1.9 refine(&ptrunk, 0, 0, hresolu, vresolu, pdepth+1);
230 greg 1.1 }
231 greg 1.14 if (errno == ENOMEM) /* ran out of memory */
232     freereserves();
233     else if (dev->inpready) /* noticed some input */
234 greg 1.1 command(": ");
235 greg 1.14 else /* finished this depth */
236 greg 1.1 pdepth++;
237     }
238     }
239    
240    
241 greg 2.18 void
242 greg 1.14 fillreserves() /* fill memory reserves */
243 greg 1.12 {
244     if (reserve_mem != NULL)
245 greg 1.14 return;
246 greg 2.18 reserve_mem = (char *)malloc(RESERVE_AMT);
247 greg 1.12 }
248    
249    
250 greg 2.18 void
251 greg 1.14 freereserves() /* free memory reserves */
252 greg 1.12 {
253 greg 1.14 if (reserve_mem == NULL)
254     return;
255 greg 1.12 free(reserve_mem);
256     reserve_mem = NULL;
257     }
258    
259    
260 greg 2.18 void
261 greg 1.1 command(prompt) /* get/execute command */
262     char *prompt;
263     {
264 greg 2.8 #define badcom(s) strncmp(s, inpbuf, args-inpbuf-1)
265 greg 1.1 char inpbuf[256];
266     char *args;
267     again:
268 greg 1.10 (*dev->comin)(inpbuf, prompt); /* get command + arguments */
269 greg 1.1 for (args = inpbuf; *args && *args != ' '; args++)
270     ;
271     if (*args) *args++ = '\0';
272     else *++args = '\0';
273    
274     switch (inpbuf[0]) {
275 greg 2.10 case 'f': /* new frame (or free mem.) */
276     if (badcom("frame")) {
277     if (badcom("free"))
278     goto commerr;
279     free_objmem();
280     break;
281     }
282 greg 1.1 getframe(args);
283     break;
284     case 'v': /* view */
285     if (badcom("view"))
286     goto commerr;
287     getview(args);
288     break;
289     case 'l': /* last view */
290     if (badcom("last"))
291     goto commerr;
292     lastview(args);
293 greg 2.11 break;
294     case 'V': /* save view */
295     if (badcom("V"))
296     goto commerr;
297     saveview(args);
298     break;
299     case 'L': /* load view */
300     if (badcom("L"))
301     goto commerr;
302     loadview(args);
303 greg 1.1 break;
304     case 'e': /* exposure */
305     if (badcom("exposure"))
306     goto commerr;
307     getexposure(args);
308     break;
309     case 's': /* set a parameter */
310 greg 2.13 if (badcom("set")) {
311     #ifdef SIGTSTP
312     if (!badcom("stop"))
313     goto dostop;
314     #endif
315 greg 1.1 goto commerr;
316 greg 2.13 }
317 greg 1.1 setparam(args);
318     break;
319     case 'n': /* new picture */
320     if (badcom("new"))
321     goto commerr;
322     newimage();
323     break;
324     case 't': /* trace a ray */
325     if (badcom("trace"))
326     goto commerr;
327     traceray(args);
328     break;
329     case 'a': /* aim camera */
330     if (badcom("aim"))
331     goto commerr;
332     getaim(args);
333     break;
334 greg 2.10 case 'm': /* move camera (or memstats) */
335 greg 1.1 if (badcom("move"))
336 greg 2.8 #ifdef MSTATS
337 greg 2.2 {
338     if (badcom("memory"))
339     goto commerr;
340     printmemstats(stderr);
341     break;
342     }
343     #else
344 greg 1.1 goto commerr;
345 greg 2.2 #endif
346 greg 1.1 getmove(args);
347     break;
348 greg 1.8 case 'r': /* rotate/repaint */
349     if (badcom("rotate")) {
350 greg 2.13 if (badcom("repaint")) {
351     if (badcom("redraw"))
352     goto commerr;
353     redraw();
354     break;
355     }
356 greg 1.8 getrepaint(args);
357     break;
358     }
359 greg 1.1 getrotate(args);
360     break;
361     case 'p': /* pivot view */
362 greg 2.13 if (badcom("pivot")) {
363     if (badcom("pause"))
364     goto commerr;
365     goto again;
366     }
367 greg 1.1 getpivot(args);
368     break;
369 greg 2.4 case CTRL('R'): /* redraw */
370 greg 1.1 redraw();
371     break;
372     case 'w': /* write */
373     if (badcom("write"))
374     goto commerr;
375     writepict(args);
376     break;
377     case 'q': /* quit */
378     if (badcom("quit"))
379     goto commerr;
380     quit(0);
381 greg 2.4 case CTRL('C'): /* interrupt */
382 greg 1.1 goto again;
383 greg 2.8 #ifdef SIGTSTP
384 greg 2.13 case CTRL('Z'):; /* stop */
385     dostop:
386 greg 1.1 devclose();
387     kill(0, SIGTSTP);
388     /* pc stops here */
389 greg 2.18 devopen(dvcname);
390 greg 1.1 redraw();
391     break;
392     #endif
393     case '\0': /* continue */
394     break;
395     default:;
396     commerr:
397     if (iscntrl(inpbuf[0]))
398     sprintf(errmsg, "^%c: unknown control",
399     inpbuf[0]|0100);
400     else
401     sprintf(errmsg, "%s: unknown command", inpbuf);
402     error(COMMAND, errmsg);
403     break;
404     }
405 greg 2.8 #undef badcom
406 greg 1.1 }
407    
408    
409 greg 2.18 void
410 greg 1.1 rsample() /* sample the image */
411     {
412     int xsiz, ysiz, y;
413     RECT r;
414     PNODE *p;
415     register RECT *rl;
416 greg 2.8 register PNODE **pl;
417 greg 1.1 register int x;
418     /*
419     * We initialize the bottom row in the image at our current
420 greg 2.8 * resolution. During sampling, we check super-pixels to the
421 greg 1.1 * right and above by calling bigdiff(). If there is a significant
422     * difference, we subsample the super-pixels. The testing process
423     * includes initialization of the next row.
424     */
425 greg 2.12 xsiz = (((long)(pframe.r-pframe.l)<<pdepth)+hresolu-1) / hresolu;
426     ysiz = (((long)(pframe.u-pframe.d)<<pdepth)+vresolu-1) / vresolu;
427 greg 1.1 rl = (RECT *)malloc(xsiz*sizeof(RECT));
428 greg 1.12 if (rl == NULL)
429 greg 1.14 return;
430 greg 1.1 pl = (PNODE **)malloc(xsiz*sizeof(PNODE *));
431 greg 2.7 if (pl == NULL) {
432 greg 2.18 free((void *)rl);
433 greg 1.14 return;
434 greg 2.7 }
435 greg 1.1 /*
436     * Initialize the bottom row.
437     */
438     rl[0].l = rl[0].d = 0;
439 greg 1.9 rl[0].r = hresolu; rl[0].u = vresolu;
440 greg 1.1 pl[0] = findrect(pframe.l, pframe.d, &ptrunk, rl, pdepth);
441     for (x = 1; x < xsiz; x++) {
442     rl[x].l = rl[x].d = 0;
443 greg 1.9 rl[x].r = hresolu; rl[x].u = vresolu;
444     pl[x] = findrect(pframe.l+((x*hresolu)>>pdepth),
445 greg 1.1 pframe.d, &ptrunk, rl+x, pdepth);
446     }
447     /* sample the image */
448     for (y = 0; /* y < ysiz */ ; y++) {
449     for (x = 0; x < xsiz-1; x++) {
450 greg 1.20 if (dev->inpready || errno == ENOMEM)
451 greg 1.1 goto escape;
452     /*
453     * Test super-pixel to the right.
454     */
455     if (pl[x] != pl[x+1] && bigdiff(pl[x]->v,
456     pl[x+1]->v, maxdiff)) {
457     refine(pl[x], rl[x].l, rl[x].d,
458     rl[x].r, rl[x].u, 1);
459     refine(pl[x+1], rl[x+1].l, rl[x+1].d,
460     rl[x+1].r, rl[x+1].u, 1);
461     }
462     }
463     if (y >= ysiz-1)
464     break;
465     for (x = 0; x < xsiz; x++) {
466 greg 1.20 if (dev->inpready || errno == ENOMEM)
467 greg 1.1 goto escape;
468     /*
469     * Find super-pixel at this position in next row.
470     */
471     r.l = r.d = 0;
472 greg 1.9 r.r = hresolu; r.u = vresolu;
473     p = findrect(pframe.l+((x*hresolu)>>pdepth),
474     pframe.d+(((y+1)*vresolu)>>pdepth),
475 greg 1.1 &ptrunk, &r, pdepth);
476     /*
477     * Test super-pixel in next row.
478     */
479     if (pl[x] != p && bigdiff(pl[x]->v, p->v, maxdiff)) {
480     refine(pl[x], rl[x].l, rl[x].d,
481     rl[x].r, rl[x].u, 1);
482     refine(p, r.l, r.d, r.r, r.u, 1);
483     }
484     /*
485     * Copy into super-pixel array.
486     */
487     rl[x].l = r.l; rl[x].d = r.d;
488     rl[x].r = r.r; rl[x].u = r.u;
489     pl[x] = p;
490     }
491     }
492     escape:
493 greg 2.18 free((void *)rl);
494     free((void *)pl);
495 greg 1.1 }
496    
497    
498     int
499     refine(p, xmin, ymin, xmax, ymax, pd) /* refine a node */
500 greg 2.8 register PNODE *p;
501 greg 1.1 int xmin, ymin, xmax, ymax;
502     int pd;
503     {
504     int growth;
505     int mx, my;
506     int i;
507    
508     if (dev->inpready) /* quit for input */
509     return(0);
510    
511     if (pd <= 0) /* depth limit */
512     return(0);
513    
514     mx = (xmin + xmax) >> 1;
515     my = (ymin + ymax) >> 1;
516     growth = 0;
517    
518     if (p->kid == NULL) { /* subdivide */
519    
520     if ((p->kid = newptree()) == NULL)
521 greg 1.20 return(0);
522 greg 1.1 /*
523     * The following paint order can leave a black pixel
524 greg 2.7 * if redraw() is called in (*dev->paintr)().
525 greg 1.1 */
526     if (p->x >= mx && p->y >= my)
527     pcopy(p, p->kid+UR);
528     else
529     paint(p->kid+UR, mx, my, xmax, ymax);
530     if (p->x < mx && p->y >= my)
531     pcopy(p, p->kid+UL);
532     else
533     paint(p->kid+UL, xmin, my, mx, ymax);
534     if (p->x >= mx && p->y < my)
535     pcopy(p, p->kid+DR);
536     else
537     paint(p->kid+DR, mx, ymin, xmax, my);
538     if (p->x < mx && p->y < my)
539     pcopy(p, p->kid+DL);
540     else
541     paint(p->kid+DL, xmin, ymin, mx, my);
542    
543     growth++;
544     }
545     /* do children */
546     if (mx > pframe.l) {
547     if (my > pframe.d)
548     growth += refine(p->kid+DL, xmin, ymin, mx, my, pd-1);
549     if (my < pframe.u)
550     growth += refine(p->kid+UL, xmin, my, mx, ymax, pd-1);
551     }
552     if (mx < pframe.r) {
553     if (my > pframe.d)
554     growth += refine(p->kid+DR, mx, ymin, xmax, my, pd-1);
555     if (my < pframe.u)
556     growth += refine(p->kid+UR, mx, my, xmax, ymax, pd-1);
557     }
558     /* recompute sum */
559     if (growth) {
560     setcolor(p->v, 0.0, 0.0, 0.0);
561     for (i = 0; i < 4; i++)
562     addcolor(p->v, p->kid[i].v);
563     scalecolor(p->v, 0.25);
564     }
565     return(growth);
566     }