ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rv3.c
Revision: 2.10
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.9: +83 -18 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 * rv3.c - miscellaneous routines for rview.
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 "random.h"
72
73 #ifndef WFLUSH
74 #ifdef SPEED
75 #define WFLUSH (5*SPEED)
76 #else
77 #define WFLUSH 100 /* flush after this many rays */
78 #endif
79 #endif
80
81 #ifdef SMLFLT
82 #define sscanvec(s,v) (sscanf(s,"%f %f %f",v,v+1,v+2)==3)
83 #else
84 #define sscanvec(s,v) (sscanf(s,"%lf %lf %lf",v,v+1,v+2)==3)
85 #endif
86
87
88 int
89 getrect(s, r) /* get a box */
90 char *s;
91 register RECT *r;
92 {
93 int x0, y0, x1, y1;
94
95 if (*s && !strncmp(s, "all", strlen(s))) {
96 r->l = r->d = 0;
97 r->r = hresolu;
98 r->u = vresolu;
99 return(0);
100 }
101 if (sscanf(s, "%d %d %d %d", &x0, &y0, &x1, &y1) != 4) {
102 if (dev->getcur == NULL)
103 return(-1);
104 (*dev->comout)("Pick first corner\n");
105 if ((*dev->getcur)(&x0, &y0) == ABORT)
106 return(-1);
107 (*dev->comout)("Pick second corner\n");
108 if ((*dev->getcur)(&x1, &y1) == ABORT)
109 return(-1);
110 }
111 if (x0 < x1) {
112 r->l = x0;
113 r->r = x1;
114 } else {
115 r->l = x1;
116 r->r = x0;
117 }
118 if (y0 < y1) {
119 r->d = y0;
120 r->u = y1;
121 } else {
122 r->d = y1;
123 r->u = y0;
124 }
125 if (r->l < 0) r->l = 0;
126 if (r->d < 0) r->d = 0;
127 if (r->r > hresolu) r->r = hresolu;
128 if (r->u > vresolu) r->u = vresolu;
129 if (r->l > r->r) r->l = r->r;
130 if (r->d > r->u) r->d = r->u;
131 return(0);
132 }
133
134
135 int
136 getinterest(s, direc, vec, mp) /* get area of interest */
137 char *s;
138 int direc;
139 FVECT vec;
140 double *mp;
141 {
142 int x, y;
143 RAY thisray;
144 register int i;
145
146 if (sscanf(s, "%lf", mp) != 1)
147 *mp = 1.0;
148 else if (*mp < -FTINY) /* negative zoom is reduction */
149 *mp = -1.0 / *mp;
150 else if (*mp <= FTINY) { /* too small */
151 error(COMMAND, "illegal magnification");
152 return(-1);
153 }
154 if (!sscanvec(sskip(s), vec)) {
155 if (dev->getcur == NULL)
156 return(-1);
157 (*dev->comout)("Pick view center\n");
158 if ((*dev->getcur)(&x, &y) == ABORT)
159 return(-1);
160 if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir,
161 &ourview, (x+.5)/hresolu, (y+.5)/vresolu)) < -FTINY) {
162 error(COMMAND, "not on image");
163 return(-1);
164 }
165 if (!direc || ourview.type == VT_PAR) {
166 rayorigin(&thisray, NULL, PRIMARY, 1.0);
167 if (!localhit(&thisray, &thescene)) {
168 error(COMMAND, "not a local object");
169 return(-1);
170 }
171 }
172 if (direc)
173 if (ourview.type == VT_PAR)
174 for (i = 0; i < 3; i++)
175 vec[i] = thisray.rop[i] - ourview.vp[i];
176 else
177 VCOPY(vec, thisray.rdir);
178 else
179 VCOPY(vec, thisray.rop);
180 } else if (direc)
181 for (i = 0; i < 3; i++)
182 vec[i] -= ourview.vp[i];
183 return(0);
184 }
185
186
187 float * /* keep consistent with COLOR typedef */
188 greyof(col) /* convert color to greyscale */
189 register COLOR col;
190 {
191 static COLOR gcol;
192 double b;
193
194 b = bright(col);
195 setcolor(gcol, b, b, b);
196 return(gcol);
197 }
198
199
200 void
201 paint(p, xmin, ymin, xmax, ymax) /* compute and paint a rectangle */
202 register PNODE *p;
203 int xmin, ymin, xmax, ymax;
204 {
205 static unsigned long lastflush = 0;
206 static RAY thisray;
207 double h, v;
208
209 if (xmax - xmin <= 0 || ymax - ymin <= 0) { /* empty */
210 p->x = xmin;
211 p->y = ymin;
212 setcolor(p->v, 0.0, 0.0, 0.0);
213 return;
214 }
215 /* jitter ray direction */
216 h = xmin + (xmax-xmin)*frandom();
217 v = ymin + (ymax-ymin)*frandom();
218
219 if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir, &ourview,
220 h/hresolu, v/vresolu)) < -FTINY) {
221 setcolor(thisray.rcol, 0.0, 0.0, 0.0);
222 } else {
223 rayorigin(&thisray, NULL, PRIMARY, 1.0);
224 samplendx++;
225 rayvalue(&thisray);
226 }
227
228 p->x = h;
229 p->y = v;
230 copycolor(p->v, thisray.rcol);
231 scalecolor(p->v, exposure);
232
233 (*dev->paintr)(greyscale?greyof(p->v):p->v, xmin, ymin, xmax, ymax);
234
235 if (dev->flush != NULL && nrays - lastflush >= WFLUSH) {
236 lastflush = nrays;
237 (*dev->flush)();
238 }
239 }
240
241
242 void
243 newimage() /* start a new image */
244 {
245 /* free old image */
246 freepkids(&ptrunk);
247 /* save reserve memory */
248 fillreserves();
249 /* compute resolution */
250 hresolu = dev->xsiz;
251 vresolu = dev->ysiz;
252 normaspect(viewaspect(&ourview), &dev->pixaspect, &hresolu, &vresolu);
253 pframe.l = pframe.d = 0;
254 pframe.r = hresolu; pframe.u = vresolu;
255 pdepth = 0;
256 /* clear device */
257 (*dev->clear)(hresolu, vresolu);
258 /* get first value */
259 paint(&ptrunk, 0, 0, hresolu, vresolu);
260 }
261
262
263 void
264 redraw() /* redraw the image */
265 {
266 (*dev->clear)(hresolu, vresolu);
267 (*dev->comout)("redrawing...\n");
268 repaint(0, 0, hresolu, vresolu);
269 (*dev->comout)("\n");
270 }
271
272
273 void
274 repaint(xmin, ymin, xmax, ymax) /* repaint a region */
275 int xmin, ymin, xmax, ymax;
276 {
277 RECT reg;
278
279 reg.l = xmin; reg.r = xmax;
280 reg.d = ymin; reg.u = ymax;
281
282 paintrect(&ptrunk, 0, 0, hresolu, vresolu, &reg);
283 }
284
285
286 void
287 paintrect(p, xmin, ymin, xmax, ymax, r) /* paint picture rectangle */
288 register PNODE *p;
289 int xmin, ymin, xmax, ymax;
290 register RECT *r;
291 {
292 int mx, my;
293
294 if (xmax - xmin <= 0 || ymax - ymin <= 0)
295 return;
296
297 if (p->kid == NULL) {
298 (*dev->paintr)(greyscale?greyof(p->v):p->v,
299 xmin, ymin, xmax, ymax); /* do this */
300 return;
301 }
302 mx = (xmin + xmax) >> 1; /* do kids */
303 my = (ymin + ymax) >> 1;
304 if (mx > r->l) {
305 if (my > r->d)
306 paintrect(p->kid+DL, xmin, ymin, mx, my, r);
307 if (my < r->u)
308 paintrect(p->kid+UL, xmin, my, mx, ymax, r);
309 }
310 if (mx < r->r) {
311 if (my > r->d)
312 paintrect(p->kid+DR, mx, ymin, xmax, my, r);
313 if (my < r->u)
314 paintrect(p->kid+UR, mx, my, xmax, ymax, r);
315 }
316 }
317
318
319 PNODE *
320 findrect(x, y, p, r, pd) /* find a rectangle */
321 int x, y;
322 register PNODE *p;
323 register RECT *r;
324 int pd;
325 {
326 int mx, my;
327
328 while (p->kid != NULL && pd--) {
329
330 mx = (r->l + r->r) >> 1;
331 my = (r->d + r->u) >> 1;
332
333 if (x < mx) {
334 r->r = mx;
335 if (y < my) {
336 r->u = my;
337 p = p->kid+DL;
338 } else {
339 r->d = my;
340 p = p->kid+UL;
341 }
342 } else {
343 r->l = mx;
344 if (y < my) {
345 r->u = my;
346 p = p->kid+DR;
347 } else {
348 r->d = my;
349 p = p->kid+UR;
350 }
351 }
352 }
353 return(p);
354 }
355
356
357 void
358 scalepict(p, sf) /* scale picture values */
359 register PNODE *p;
360 double sf;
361 {
362 scalecolor(p->v, sf); /* do this node */
363
364 if (p->kid == NULL)
365 return;
366 /* do children */
367 scalepict(p->kid+DL, sf);
368 scalepict(p->kid+DR, sf);
369 scalepict(p->kid+UL, sf);
370 scalepict(p->kid+UR, sf);
371 }
372
373
374 void
375 getpictcolrs(yoff, scan, p, xsiz, ysiz) /* get scanline from picture */
376 int yoff;
377 register COLR *scan;
378 register PNODE *p;
379 int xsiz, ysiz;
380 {
381 register int mx;
382 int my;
383
384 if (p->kid == NULL) { /* do this node */
385 setcolr(scan[0], colval(p->v,RED),
386 colval(p->v,GRN),
387 colval(p->v,BLU));
388 for (mx = 1; mx < xsiz; mx++)
389 copycolr(scan[mx], scan[0]);
390 return;
391 }
392 /* do kids */
393 mx = xsiz >> 1;
394 my = ysiz >> 1;
395 if (yoff < my) {
396 getpictcolrs(yoff, scan, p->kid+DL, mx, my);
397 getpictcolrs(yoff, scan+mx, p->kid+DR, xsiz-mx, my);
398 } else {
399 getpictcolrs(yoff-my, scan, p->kid+UL, mx, ysiz-my);
400 getpictcolrs(yoff-my, scan+mx, p->kid+UR, xsiz-mx, ysiz-my);
401 }
402 }
403
404
405 void
406 freepkids(p) /* free pnode's children */
407 register PNODE *p;
408 {
409 if (p->kid == NULL)
410 return;
411 freepkids(p->kid+DL);
412 freepkids(p->kid+DR);
413 freepkids(p->kid+UL);
414 freepkids(p->kid+UR);
415 free((void *)p->kid);
416 p->kid = NULL;
417 }
418
419
420 void
421 newview(vp) /* change viewing parameters */
422 register VIEW *vp;
423 {
424 char *err;
425
426 if ((err = setview(vp)) != NULL) {
427 sprintf(errmsg, "view not set - %s", err);
428 error(COMMAND, errmsg);
429 } else if (bcmp((char *)vp, (char *)&ourview, sizeof(VIEW))) {
430 copystruct(&oldview, &ourview);
431 copystruct(&ourview, vp);
432 newimage();
433 }
434 }
435
436
437 void
438 moveview(angle, elev, mag, vc) /* move viewpoint */
439 double angle, elev, mag;
440 FVECT vc;
441 {
442 double d;
443 FVECT v1;
444 VIEW nv;
445 register int i;
446
447 VCOPY(nv.vup, ourview.vup);
448 nv.hoff = ourview.hoff; nv.voff = ourview.voff;
449 spinvector(nv.vdir, ourview.vdir, ourview.vup, angle*(PI/180.));
450 if (elev != 0.0) {
451 fcross(v1, ourview.vup, nv.vdir);
452 normalize(v1);
453 spinvector(nv.vdir, nv.vdir, v1, elev*(PI/180.));
454 }
455 if ((nv.type = ourview.type) == VT_PAR) {
456 nv.horiz = ourview.horiz / mag;
457 nv.vert = ourview.vert / mag;
458 d = 0.0; /* don't move closer */
459 for (i = 0; i < 3; i++)
460 d += (vc[i] - ourview.vp[i])*ourview.vdir[i];
461 nv.vfore = ourview.vfore;
462 nv.vaft = ourview.vaft;
463 } else {
464 nv.horiz = ourview.horiz;
465 nv.vert = ourview.vert;
466 d = sqrt(dist2(ourview.vp, vc)) / mag;
467 if ((nv.vfore = ourview.vfore) > FTINY) {
468 nv.vfore += d - d*mag;
469 if (nv.vfore < 0.0) nv.vfore = 0.0;
470 }
471 if ((nv.vaft = ourview.vaft) > FTINY) {
472 nv.vaft += d - d*mag;
473 if (nv.vaft <= nv.vfore) nv.vaft = 0.0;
474 }
475 }
476 for (i = 0; i < 3; i++)
477 nv.vp[i] = vc[i] - d*nv.vdir[i];
478 newview(&nv);
479 }
480
481
482 void
483 pcopy(p1, p2) /* copy paint node p1 into p2 */
484 register PNODE *p1, *p2;
485 {
486 copycolor(p2->v, p1->v);
487 p2->x = p1->x;
488 p2->y = p1->y;
489 }
490
491
492 void
493 zoomview(vp, zf) /* zoom in or out */
494 register VIEW *vp;
495 double zf;
496 {
497 switch (vp->type) {
498 case VT_PAR: /* parallel view */
499 vp->horiz /= zf;
500 vp->vert /= zf;
501 return;
502 case VT_ANG: /* angular fisheye */
503 vp->horiz /= zf;
504 if (vp->horiz > 360.)
505 vp->horiz = 360.;
506 vp->vert /= zf;
507 if (vp->vert > 360.)
508 vp->vert = 360.;
509 return;
510 case VT_CYL: /* cylindrical panorama */
511 vp->horiz /= zf;
512 if (vp->horiz > 360.)
513 vp->horiz = 360.;
514 vp->vert = atan(tan(vp->vert*(PI/180./2.))/zf) / (PI/180./2.);
515 return;
516 case VT_PER: /* perspective view */
517 vp->horiz = atan(tan(vp->horiz*(PI/180./2.))/zf) /
518 (PI/180./2.);
519 vp->vert = atan(tan(vp->vert*(PI/180./2.))/zf) /
520 (PI/180./2.);
521 return;
522 case VT_HEM: /* hemispherical fisheye */
523 vp->horiz = sin(vp->horiz*(PI/180./2.))/zf;
524 if (vp->horiz >= 1.0-FTINY)
525 vp->horiz = 180.;
526 else
527 vp->horiz = asin(vp->horiz) / (PI/180./2.);
528 vp->vert = sin(vp->vert*(PI/180./2.))/zf;
529 if (vp->vert >= 1.0-FTINY)
530 vp->vert = 180.;
531 else
532 vp->vert = asin(vp->vert) / (PI/180./2.);
533 return;
534 }
535 }