ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rv3.c
Revision: 2.22
Committed: Thu Aug 21 07:05:59 2008 UTC (15 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.21: +146 -88 lines
Log Message:
Added -n option to rvu for multiple rendering processes

File Contents

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