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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * rview.c - routines and variables for interactive view generation.
6 *
7 * 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 */
66
67 #include "ray.h"
68
69 #include "rpaint.h"
70
71 #include <signal.h>
72
73 #include <ctype.h>
74
75 CUBE thescene; /* our scene */
76 OBJECT nsceneobjs; /* number of objects in our scene */
77
78 int dimlist[MAXDIM]; /* sampling dimensions */
79 int ndims = 0; /* number of sampling dimensions */
80 int samplendx = 0; /* index for this sample */
81
82 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 int psample = 8; /* pixel sample size */
93 double maxdiff = .15; /* max. sample difference */
94
95 double exposure = 1.0; /* exposure for scene */
96
97 double dstrsrc = 0.0; /* square source distribution */
98 double shadthresh = .1; /* shadow threshold */
99 double shadcert = .25; /* shadow certainty */
100 int directrelay = 0; /* number of source relays */
101 int vspretest = 128; /* virtual source pretest density */
102 int directvis = 1; /* sources visible? */
103 double srcsizerat = 0.; /* maximum ratio source size/dist. */
104
105 COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
106 COLOR salbedo = BLKCOLOR; /* global scattering albedo */
107 double seccg = 0.; /* global scattering eccentricity */
108 double ssampdist = 0.; /* scatter sampling distance */
109
110 double specthresh = .3; /* specular sampling threshold */
111 double specjitter = 1.; /* specular sampling jitter */
112
113 int backvis = 1; /* back face visibility */
114
115 int maxdepth = 4; /* maximum recursion depth */
116 double minweight = 1e-2; /* minimum ray weight */
117
118 char *ambfile = NULL; /* ambient file name */
119 COLOR ambval = BLKCOLOR; /* ambient value */
120 int ambvwt = 0; /* initial weight for ambient value */
121 double ambacc = 0.2; /* ambient accuracy */
122 int ambres = 8; /* ambient resolution */
123 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 char *dvcname = dev_default; /* output device name */
131
132 struct driver *dev = NULL; /* driver functions */
133
134 char rifname[128]; /* rad input file name */
135
136 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 static char *reserve_mem = NULL; /* pre-allocated reserve memory */
143
144 #define RESERVE_AMT 32768 /* amount of memory to reserve */
145
146 #define CTRL(c) ((c)-'@')
147
148
149 void
150 quit(code) /* quit program */
151 int code;
152 {
153 #ifdef MSTATS
154 if (code == 2 && errno == ENOMEM)
155 printmemstats(stderr);
156 #endif
157 devclose();
158 exit(code);
159 }
160
161
162 void
163 devopen(dname) /* open device driver */
164 char *dname;
165 {
166 extern char *progname, *octname;
167 char *id;
168 register int i;
169
170 id = octname!=NULL ? octname : progname;
171 /* check device table */
172 for (i = 0; devtable[i].name; i++)
173 if (!strcmp(dname, devtable[i].name))
174 if ((dev = (*devtable[i].init)(dname, id)) == NULL) {
175 sprintf(errmsg, "cannot initialize %s", dname);
176 error(USER, errmsg);
177 } else
178 return;
179 #ifndef NIX
180 /* not there, try exec */
181 if ((dev = comm_init(dname, id)) == NULL) {
182 sprintf(errmsg, "cannot start device \"%s\"", dname);
183 error(USER, errmsg);
184 }
185 #endif
186 }
187
188
189 void
190 devclose() /* close our device */
191 {
192 if (dev != NULL)
193 (*dev->close)();
194 dev = NULL;
195 }
196
197
198 void
199 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 void
209 rview() /* do a view */
210 {
211 char buf[32];
212
213 devopen(dvcname); /* open device */
214 newimage(); /* start image (calls fillreserves) */
215
216 for ( ; ; ) { /* quit in command() */
217 while (hresolu <= 1<<pdepth && vresolu <= 1<<pdepth)
218 command("done: ");
219 while (reserve_mem == NULL)
220 command("out of memory: ");
221 errno = 0;
222 if (hresolu <= psample<<pdepth && vresolu <= psample<<pdepth) {
223 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 refine(&ptrunk, 0, 0, hresolu, vresolu, pdepth+1);
230 }
231 if (errno == ENOMEM) /* ran out of memory */
232 freereserves();
233 else if (dev->inpready) /* noticed some input */
234 command(": ");
235 else /* finished this depth */
236 pdepth++;
237 }
238 }
239
240
241 void
242 fillreserves() /* fill memory reserves */
243 {
244 if (reserve_mem != NULL)
245 return;
246 reserve_mem = (char *)malloc(RESERVE_AMT);
247 }
248
249
250 void
251 freereserves() /* free memory reserves */
252 {
253 if (reserve_mem == NULL)
254 return;
255 free(reserve_mem);
256 reserve_mem = NULL;
257 }
258
259
260 void
261 command(prompt) /* get/execute command */
262 char *prompt;
263 {
264 #define badcom(s) strncmp(s, inpbuf, args-inpbuf-1)
265 char inpbuf[256];
266 char *args;
267 again:
268 (*dev->comin)(inpbuf, prompt); /* get command + arguments */
269 for (args = inpbuf; *args && *args != ' '; args++)
270 ;
271 if (*args) *args++ = '\0';
272 else *++args = '\0';
273
274 switch (inpbuf[0]) {
275 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 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 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 break;
304 case 'e': /* exposure */
305 if (badcom("exposure"))
306 goto commerr;
307 getexposure(args);
308 break;
309 case 's': /* set a parameter */
310 if (badcom("set")) {
311 #ifdef SIGTSTP
312 if (!badcom("stop"))
313 goto dostop;
314 #endif
315 goto commerr;
316 }
317 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 case 'm': /* move camera (or memstats) */
335 if (badcom("move"))
336 #ifdef MSTATS
337 {
338 if (badcom("memory"))
339 goto commerr;
340 printmemstats(stderr);
341 break;
342 }
343 #else
344 goto commerr;
345 #endif
346 getmove(args);
347 break;
348 case 'r': /* rotate/repaint */
349 if (badcom("rotate")) {
350 if (badcom("repaint")) {
351 if (badcom("redraw"))
352 goto commerr;
353 redraw();
354 break;
355 }
356 getrepaint(args);
357 break;
358 }
359 getrotate(args);
360 break;
361 case 'p': /* pivot view */
362 if (badcom("pivot")) {
363 if (badcom("pause"))
364 goto commerr;
365 goto again;
366 }
367 getpivot(args);
368 break;
369 case CTRL('R'): /* redraw */
370 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 case CTRL('C'): /* interrupt */
382 goto again;
383 #ifdef SIGTSTP
384 case CTRL('Z'):; /* stop */
385 dostop:
386 devclose();
387 kill(0, SIGTSTP);
388 /* pc stops here */
389 devopen(dvcname);
390 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 #undef badcom
406 }
407
408
409 void
410 rsample() /* sample the image */
411 {
412 int xsiz, ysiz, y;
413 RECT r;
414 PNODE *p;
415 register RECT *rl;
416 register PNODE **pl;
417 register int x;
418 /*
419 * We initialize the bottom row in the image at our current
420 * resolution. During sampling, we check super-pixels to the
421 * 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 xsiz = (((long)(pframe.r-pframe.l)<<pdepth)+hresolu-1) / hresolu;
426 ysiz = (((long)(pframe.u-pframe.d)<<pdepth)+vresolu-1) / vresolu;
427 rl = (RECT *)malloc(xsiz*sizeof(RECT));
428 if (rl == NULL)
429 return;
430 pl = (PNODE **)malloc(xsiz*sizeof(PNODE *));
431 if (pl == NULL) {
432 free((void *)rl);
433 return;
434 }
435 /*
436 * Initialize the bottom row.
437 */
438 rl[0].l = rl[0].d = 0;
439 rl[0].r = hresolu; rl[0].u = vresolu;
440 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 rl[x].r = hresolu; rl[x].u = vresolu;
444 pl[x] = findrect(pframe.l+((x*hresolu)>>pdepth),
445 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 if (dev->inpready || errno == ENOMEM)
451 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 if (dev->inpready || errno == ENOMEM)
467 goto escape;
468 /*
469 * Find super-pixel at this position in next row.
470 */
471 r.l = r.d = 0;
472 r.r = hresolu; r.u = vresolu;
473 p = findrect(pframe.l+((x*hresolu)>>pdepth),
474 pframe.d+(((y+1)*vresolu)>>pdepth),
475 &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 free((void *)rl);
494 free((void *)pl);
495 }
496
497
498 int
499 refine(p, xmin, ymin, xmax, ymax, pd) /* refine a node */
500 register PNODE *p;
501 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 return(0);
522 /*
523 * The following paint order can leave a black pixel
524 * if redraw() is called in (*dev->paintr)().
525 */
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 }