ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rv3.c
Revision: 2.38
Committed: Thu Sep 6 00:07:43 2012 UTC (11 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad4R2, rad4R2P1
Changes since 2.37: +4 -7 lines
Log Message:
Created geodesic() function for vector rotation along great circles

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rv3.c,v 2.37 2012/03/20 03:37:08 greg Exp $";
3 #endif
4 /*
5 * rv3.c - miscellaneous routines for rview.
6 *
7 * External symbols declared in rpaint.h
8 */
9
10 #include "copyright.h"
11
12 #include <string.h>
13
14 #include "ray.h"
15 #include "rpaint.h"
16 #include "random.h"
17
18 #ifndef WFLUSH
19 #define WFLUSH 64 /* flush after this many primary rays */
20 #endif
21 #ifndef WFLUSH1
22 #define WFLUSH1 512 /* or this many total rays */
23 #endif
24
25
26 #ifdef SMLFLT
27 #define sscanvec(s,v) (sscanf(s,"%f %f %f",v,v+1,v+2)==3)
28 #else
29 #define sscanvec(s,v) (sscanf(s,"%lf %lf %lf",v,v+1,v+2)==3)
30 #endif
31
32 extern int ray_pnprocs;
33
34 static RNUMBER niflush; /* flushes since newimage() */
35
36 int
37 getrect( /* get a box */
38 char *s,
39 RECT *r
40 )
41 {
42 int x0, y0, x1, y1;
43
44 if (*s && !strncmp(s, "all", strlen(s))) {
45 r->l = r->d = 0;
46 r->r = hresolu;
47 r->u = vresolu;
48 return(0);
49 }
50 if (sscanf(s, "%d %d %d %d", &x0, &y0, &x1, &y1) != 4) {
51 if (dev->getcur == NULL)
52 return(-1);
53 (*dev->comout)("Pick first corner\n");
54 if ((*dev->getcur)(&x0, &y0) == ABORT)
55 return(-1);
56 (*dev->comout)("Pick second corner\n");
57 if ((*dev->getcur)(&x1, &y1) == ABORT)
58 return(-1);
59 }
60 if (x0 < x1) {
61 r->l = x0;
62 r->r = x1;
63 } else {
64 r->l = x1;
65 r->r = x0;
66 }
67 if (y0 < y1) {
68 r->d = y0;
69 r->u = y1;
70 } else {
71 r->d = y1;
72 r->u = y0;
73 }
74 if (r->l < 0) r->l = 0;
75 if (r->d < 0) r->d = 0;
76 if (r->r > hresolu) r->r = hresolu;
77 if (r->u > vresolu) r->u = vresolu;
78 if (r->l > r->r) r->l = r->r;
79 if (r->d > r->u) r->d = r->u;
80 return(0);
81 }
82
83
84 int
85 getinterest( /* get area of interest */
86 char *s,
87 int direc,
88 FVECT vec,
89 double *mp
90 )
91 {
92 int x, y;
93 RAY thisray;
94 int i;
95
96 if (sscanf(s, "%lf", mp) != 1)
97 *mp = 1.0;
98 else if (*mp < -FTINY) /* negative zoom is reduction */
99 *mp = -1.0 / *mp;
100 else if (*mp <= FTINY) { /* too small */
101 error(COMMAND, "illegal magnification");
102 return(-1);
103 }
104 if (!sscanvec(sskip(s), vec)) {
105 if (dev->getcur == NULL)
106 return(-1);
107 (*dev->comout)("Pick view center\n");
108 if ((*dev->getcur)(&x, &y) == ABORT)
109 return(-1);
110 if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir,
111 &ourview, (x+.5)/hresolu, (y+.5)/vresolu)) < -FTINY) {
112 error(COMMAND, "not on image");
113 return(-1);
114 }
115 if (!direc || ourview.type == VT_PAR) {
116 rayorigin(&thisray, PRIMARY, NULL, NULL);
117 if (!localhit(&thisray, &thescene)) {
118 error(COMMAND, "not a local object");
119 return(-1);
120 }
121 }
122 if (direc)
123 if (ourview.type == VT_PAR)
124 for (i = 0; i < 3; i++)
125 vec[i] = thisray.rop[i] - ourview.vp[i];
126 else
127 VCOPY(vec, thisray.rdir);
128 else
129 VCOPY(vec, thisray.rop);
130 } else if (direc) {
131 for (i = 0; i < 3; i++)
132 vec[i] -= ourview.vp[i];
133 if (normalize(vec) == 0.0) {
134 error(COMMAND, "point at view origin");
135 return(-1);
136 }
137 }
138 return(0);
139 }
140
141
142 float * /* keep consistent with COLOR typedef */
143 greyof( /* convert color to greyscale */
144 COLOR col
145 )
146 {
147 static COLOR gcol;
148 double b;
149
150 b = bright(col);
151 setcolor(gcol, b, b, b);
152 return(gcol);
153 }
154
155 static void
156 recolor( /* recolor the given node */
157 PNODE *p
158 )
159 {
160 while (p->kid != NULL) { /* need to propogate down */
161 int mx = (p->xmin + p->xmax) >> 1;
162 int my = (p->ymin + p->ymax) >> 1;
163 int ki;
164 if (p->x >= mx)
165 ki = (p->y >= my) ? UR : DR;
166 else
167 ki = (p->y >= my) ? UL : DL;
168 pcopy(p, p->kid+ki);
169 p = p->kid + ki;
170 }
171
172 (*dev->paintr)(greyscale?greyof(p->v):p->v,
173 p->xmin, p->ymin, p->xmax, p->ymax);
174 }
175
176 int
177 paint( /* compute and paint a rectangle */
178 PNODE *p
179 )
180 {
181 static RAY thisray;
182 double h, v;
183
184 if ((p->xmax <= p->xmin) | (p->ymax <= p->ymin)) { /* empty */
185 p->x = p->xmin;
186 p->y = p->ymin;
187 setcolor(p->v, 0.0, 0.0, 0.0);
188 return(0);
189 }
190 /* jitter ray direction */
191 p->x = h = p->xmin + (p->xmax-p->xmin)*frandom();
192 p->y = v = p->ymin + (p->ymax-p->ymin)*frandom();
193
194 if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir, &ourview,
195 h/hresolu, v/vresolu)) < -FTINY) {
196 setcolor(thisray.rcol, 0.0, 0.0, 0.0);
197 } else if (!ray_pnprocs) { /* immediate mode */
198 ray_trace(&thisray);
199 } else { /* queuing mode */
200 int rval;
201 rayorigin(&thisray, PRIMARY, NULL, NULL);
202 thisray.rno = (RNUMBER)p;
203 rval = ray_pqueue(&thisray);
204 if (!rval)
205 return(0);
206 if (rval < 0)
207 return(-1);
208 /* get node for returned ray */
209 p = (PNODE *)thisray.rno;
210 }
211
212 copycolor(p->v, thisray.rcol);
213 scalecolor(p->v, exposure);
214
215 recolor(p); /* paint it */
216
217 if (dev->flush != NULL) { /* shall we check for input? */
218 static RNUMBER lastflush = 0;
219 RNUMBER counter = raynum;
220 int flushintvl;
221 if (!ray_pnprocs) {
222 counter = nrays;
223 flushintvl = WFLUSH1;
224 } else if (ambounce == 0)
225 flushintvl = ray_pnprocs*WFLUSH;
226 else if (niflush < WFLUSH)
227 flushintvl = ray_pnprocs*niflush/(ambounce+1);
228 else
229 flushintvl = ray_pnprocs*WFLUSH/(ambounce+1);
230 if (lastflush > counter)
231 lastflush = 0; /* counter wrapped */
232
233 if (counter - lastflush >= flushintvl) {
234 lastflush = counter;
235 (*dev->flush)();
236 niflush++;
237 }
238 }
239 return(1);
240 }
241
242
243 int
244 waitrays(void) /* finish up pending rays */
245 {
246 int nwaited = 0;
247 int rval;
248 RAY raydone;
249
250 if (!ray_pnprocs) /* immediate mode? */
251 return(0);
252 while ((rval = ray_presult(&raydone, 0)) > 0) {
253 PNODE *p = (PNODE *)raydone.rno;
254 copycolor(p->v, raydone.rcol);
255 scalecolor(p->v, exposure);
256 recolor(p);
257 nwaited++;
258 }
259 if (rval < 0)
260 return(-1);
261 return(nwaited);
262 }
263
264
265 void
266 newimage( /* start a new image */
267 char *s
268 )
269 {
270 int newnp = 0;
271 /* # rendering procs arg? */
272 if (s != NULL)
273 sscanf(s, "%d", &newnp);
274 /* free old image */
275 freepkids(&ptrunk);
276 /* compute resolution */
277 hresolu = dev->xsiz;
278 vresolu = dev->ysiz;
279 normaspect(viewaspect(&ourview), &dev->pixaspect, &hresolu, &vresolu);
280 ptrunk.xmin = ptrunk.ymin = pframe.l = pframe.d = 0;
281 ptrunk.xmax = pframe.r = hresolu;
282 ptrunk.ymax = pframe.u = vresolu;
283 pdepth = 0;
284 /* clear device */
285 (*dev->clear)(hresolu, vresolu);
286
287 if (newparam) { /* (re)start rendering procs */
288 if (ray_pnprocs)
289 ray_pclose(0); /* should already be closed */
290 if (newnp > 0)
291 nproc = newnp;
292 if (nproc > 1)
293 ray_popen(nproc);
294 newparam = 0;
295 } else if ((newnp > 0) & (newnp != nproc)) {
296 if (newnp == 1) /* change # rendering procs */
297 ray_pclose(0);
298 else if (newnp < ray_pnprocs)
299 ray_pclose(ray_pnprocs - newnp);
300 else
301 ray_popen(newnp - ray_pnprocs);
302 nproc = newnp;
303 }
304 niflush = 0; /* get first value */
305 paint(&ptrunk);
306 }
307
308
309 void
310 redraw(void) /* redraw the image */
311 {
312 (*dev->clear)(hresolu, vresolu);
313 (*dev->comout)("redrawing...\n");
314 repaint(0, 0, hresolu, vresolu);
315 (*dev->comout)("\n");
316 }
317
318
319 void
320 repaint( /* repaint a region */
321 int xmin,
322 int ymin,
323 int xmax,
324 int ymax
325 )
326 {
327 RECT reg;
328
329 reg.l = xmin; reg.r = xmax;
330 reg.d = ymin; reg.u = ymax;
331
332 paintrect(&ptrunk, &reg);
333 }
334
335
336 void
337 paintrect( /* paint picture rectangle */
338 PNODE *p,
339 RECT *r
340 )
341 {
342 int mx, my;
343
344 if (p->xmax - p->xmin <= 0 || p->ymax - p->ymin <= 0)
345 return;
346
347 if (p->kid == NULL) {
348 (*dev->paintr)(greyscale?greyof(p->v):p->v,
349 p->xmin, p->ymin, p->xmax, p->ymax); /* do this */
350 return;
351 }
352 mx = (p->xmin + p->xmax) >> 1; /* do kids */
353 my = (p->ymin + p->ymax) >> 1;
354 if (mx > r->l) {
355 if (my > r->d)
356 paintrect(p->kid+DL, r);
357 if (my < r->u)
358 paintrect(p->kid+UL, r);
359 }
360 if (mx < r->r) {
361 if (my > r->d)
362 paintrect(p->kid+DR, r);
363 if (my < r->u)
364 paintrect(p->kid+UR, r);
365 }
366 }
367
368
369 PNODE *
370 findrect( /* find a rectangle */
371 int x,
372 int y,
373 PNODE *p,
374 int pd
375 )
376 {
377 int mx, my;
378
379 while (p->kid != NULL && pd--) {
380
381 mx = (p->xmin + p->xmax) >> 1;
382 my = (p->ymin + p->ymax) >> 1;
383
384 if (x < mx) {
385 if (y < my) {
386 p = p->kid+DL;
387 } else {
388 p = p->kid+UL;
389 }
390 } else {
391 if (y < my) {
392 p = p->kid+DR;
393 } else {
394 p = p->kid+UR;
395 }
396 }
397 }
398 return(p);
399 }
400
401
402 void
403 compavg( /* recompute averages */
404 PNODE *p
405 )
406 {
407 int i, navg;
408
409 if (p->kid == NULL)
410 return;
411
412 setcolor(p->v, .0, .0, .0);
413 navg = 0;
414 for (i = 0; i < 4; i++) {
415 if (p->kid[i].xmin >= p->kid[i].xmax) continue;
416 if (p->kid[i].ymin >= p->kid[i].ymax) continue;
417 compavg(p->kid+i);
418 addcolor(p->v, p->kid[i].v);
419 navg++;
420 }
421 if (navg > 1)
422 scalecolor(p->v, 1./navg);
423 }
424
425
426 void
427 scalepict( /* scale picture values */
428 PNODE *p,
429 double sf
430 )
431 {
432 scalecolor(p->v, sf); /* do this node */
433
434 if (p->kid == NULL)
435 return;
436 /* do children */
437 scalepict(p->kid+DL, sf);
438 scalepict(p->kid+DR, sf);
439 scalepict(p->kid+UL, sf);
440 scalepict(p->kid+UR, sf);
441 }
442
443
444 void
445 getpictcolrs( /* get scanline from picture */
446 int yoff,
447 COLR *scan,
448 PNODE *p,
449 int xsiz,
450 int ysiz
451 )
452 {
453 int mx;
454 int my;
455
456 if (p->kid == NULL) { /* do this node */
457 setcolr(scan[0], colval(p->v,RED),
458 colval(p->v,GRN),
459 colval(p->v,BLU));
460 for (mx = 1; mx < xsiz; mx++)
461 copycolr(scan[mx], scan[0]);
462 return;
463 }
464 /* do kids */
465 mx = xsiz >> 1;
466 my = ysiz >> 1;
467 if (yoff < my) {
468 getpictcolrs(yoff, scan, p->kid+DL, mx, my);
469 getpictcolrs(yoff, scan+mx, p->kid+DR, xsiz-mx, my);
470 } else {
471 getpictcolrs(yoff-my, scan, p->kid+UL, mx, ysiz-my);
472 getpictcolrs(yoff-my, scan+mx, p->kid+UR, xsiz-mx, ysiz-my);
473 }
474 }
475
476
477 void
478 freepkids( /* free pnode's children */
479 PNODE *p
480 )
481 {
482 if (p->kid == NULL)
483 return;
484 freepkids(p->kid+DL);
485 freepkids(p->kid+DR);
486 freepkids(p->kid+UL);
487 freepkids(p->kid+UR);
488 free((void *)p->kid);
489 p->kid = NULL;
490 }
491
492
493 void
494 newview( /* change viewing parameters */
495 VIEW *vp
496 )
497 {
498 char *err;
499
500 if ((err = setview(vp)) != NULL) {
501 sprintf(errmsg, "view not set - %s", err);
502 error(COMMAND, errmsg);
503 } else if (memcmp((char *)vp, (char *)&ourview, sizeof(VIEW))) {
504 oldview = ourview;
505 ourview = *vp;
506 newimage(NULL);
507 }
508 }
509
510
511 void
512 moveview( /* move viewpoint */
513 double angle,
514 double elev,
515 double mag,
516 FVECT vc
517 )
518 {
519 double d;
520 VIEW nv = ourview;
521 int i;
522
523 spinvector(nv.vdir, ourview.vdir, ourview.vup, angle*(PI/180.));
524 if (elev != 0.0)
525 geodesic(nv.vdir, nv.vdir, nv.vup, elev*(-PI/180.), GEOD_RAD);
526
527 if (nv.type == VT_PAR) {
528 nv.horiz /= mag;
529 nv.vert /= mag;
530 d = 0.0; /* don't move closer */
531 for (i = 0; i < 3; i++)
532 d += (vc[i] - ourview.vp[i])*ourview.vdir[i];
533 } else {
534 d = sqrt(dist2(ourview.vp, vc)) / mag;
535 if (nv.vfore > FTINY) {
536 nv.vfore += d - d*mag;
537 if (nv.vfore < 0.0) nv.vfore = 0.0;
538 }
539 if (nv.vaft > FTINY) {
540 nv.vaft += d - d*mag;
541 if (nv.vaft <= nv.vfore) nv.vaft = 0.0;
542 }
543 nv.vdist /= mag;
544 }
545 for (i = 0; i < 3; i++)
546 nv.vp[i] = vc[i] - d*nv.vdir[i];
547 newview(&nv);
548 }
549
550
551 void
552 pcopy( /* copy paint node p1 into p2 */
553 PNODE *p1,
554 PNODE *p2
555 )
556 {
557 copycolor(p2->v, p1->v);
558 p2->x = p1->x;
559 p2->y = p1->y;
560 }
561
562
563 void
564 zoomview( /* zoom in or out */
565 VIEW *vp,
566 double zf
567 )
568 {
569 switch (vp->type) {
570 case VT_PAR: /* parallel view */
571 vp->horiz /= zf;
572 vp->vert /= zf;
573 return;
574 case VT_ANG: /* angular fisheye */
575 vp->horiz /= zf;
576 if (vp->horiz > 360.)
577 vp->horiz = 360.;
578 vp->vert /= zf;
579 if (vp->vert > 360.)
580 vp->vert = 360.;
581 return;
582 case VT_PLS: /* planisphere fisheye */
583 vp->horiz = sin((PI/180./2.)*vp->horiz) /
584 (1.0 + cos((PI/180./2.)*vp->horiz)) / zf;
585 vp->horiz *= vp->horiz;
586 vp->horiz = (2.*180./PI)*acos((1. - vp->horiz) /
587 (1. + vp->horiz));
588 vp->vert = sin((PI/180./2.)*vp->vert) /
589 (1.0 + cos((PI/180./2.)*vp->vert)) / zf;
590 vp->vert *= vp->vert;
591 vp->vert = (2.*180./PI)*acos((1. - vp->vert) /
592 (1. + vp->vert));
593 return;
594 case VT_CYL: /* cylindrical panorama */
595 vp->horiz /= zf;
596 if (vp->horiz > 360.)
597 vp->horiz = 360.;
598 vp->vert = atan(tan(vp->vert*(PI/180./2.))/zf) / (PI/180./2.);
599 return;
600 case VT_PER: /* perspective view */
601 vp->horiz = atan(tan(vp->horiz*(PI/180./2.))/zf) /
602 (PI/180./2.);
603 vp->vert = atan(tan(vp->vert*(PI/180./2.))/zf) /
604 (PI/180./2.);
605 return;
606 case VT_HEM: /* hemispherical fisheye */
607 vp->horiz = sin(vp->horiz*(PI/180./2.))/zf;
608 if (vp->horiz >= 1.0-FTINY)
609 vp->horiz = 180.;
610 else
611 vp->horiz = asin(vp->horiz) / (PI/180./2.);
612 vp->vert = sin(vp->vert*(PI/180./2.))/zf;
613 if (vp->vert >= 1.0-FTINY)
614 vp->vert = 180.;
615 else
616 vp->vert = asin(vp->vert) / (PI/180./2.);
617 return;
618 }
619 }