Back to index

radiance  4R0+20100331
rview.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rview.c,v 2.33 2009/12/12 23:08:13 greg Exp $";
00003 #endif
00004 /*
00005  *  rview.c - routines and variables for interactive view generation.
00006  *
00007  *  External symbols declared in rpaint.h
00008  */
00009 
00010 #include "copyright.h"
00011 
00012 #include  <signal.h>
00013 #include  <ctype.h>
00014 
00015 #include  "ray.h"
00016 #include  "rpaint.h"
00017 
00018 #define        CTRL(c)      ((c)-'@')
00019 
00020 
00021 void
00022 quit(code)                  /* quit program */
00023 int  code;
00024 {
00025 #ifdef MSTATS
00026        if (code == 2 && errno == ENOMEM)
00027               printmemstats(stderr);
00028 #endif
00029        if (ray_pnprocs > 0) /* close children if any */
00030               ray_pclose(0);
00031        else if (!ray_pnprocs)      /* in parent */
00032               devclose();
00033        exit(code);
00034 }
00035 
00036 
00037 void
00038 devopen(                           /* open device driver */
00039        char  *dname
00040 )
00041 {
00042        extern char  *progname, *octname;
00043        char  *id;
00044        int  i;
00045 
00046        id = octname!=NULL ? octname : progname;
00047                                           /* check device table */
00048        for (i = 0; devtable[i].name; i++)
00049               if (!strcmp(dname, devtable[i].name)) {
00050                      if ((dev = (*devtable[i].init)(dname, id)) == NULL) {
00051                             sprintf(errmsg, "cannot initialize %s", dname);
00052                             error(USER, errmsg);
00053                      } else
00054                             return;
00055               }
00056                                           /* not there, try exec */
00057        if ((dev = comm_init(dname, id)) == NULL) {
00058               sprintf(errmsg, "cannot start device \"%s\"", dname);
00059               error(USER, errmsg);
00060        }
00061 }
00062 
00063 
00064 void
00065 devclose(void)                            /* close our device */
00066 {
00067        if (dev != NULL)
00068               (*dev->close)();
00069        dev = NULL;
00070 }
00071 
00072 
00073 void
00074 printdevices(void)                 /* print list of output devices */
00075 {
00076        int  i;
00077 
00078        for (i = 0; devtable[i].name; i++)
00079               printf("%-16s # %s\n", devtable[i].name, devtable[i].descrip);
00080 }
00081 
00082 
00083 void
00084 rview(void)                        /* do a view */
00085 {
00086        char  buf[32];
00087 
00088        devopen(dvcname);           /* open device */
00089        newimage(NULL);                    /* start image */
00090 
00091        for ( ; ; ) {               /* quit in command() */
00092               while (hresolu <= 1<<pdepth && vresolu <= 1<<pdepth)
00093                      command("done: ");
00094               errno = 0;
00095               if (hresolu <= psample<<pdepth && vresolu <= psample<<pdepth) {
00096                      sprintf(buf, "%d sampling...\n", 1<<pdepth);
00097                      (*dev->comout)(buf);
00098                      rsample();
00099               } else {
00100                      sprintf(buf, "%d refining...\n", 1<<pdepth);
00101                      (*dev->comout)(buf);
00102                      refine(&ptrunk, pdepth+1);
00103               }
00104               if (dev->inpready)          /* noticed some input */
00105                      command(": ");
00106               else                        /* finished this depth */
00107                      pdepth++;
00108        }
00109 }
00110 
00111 
00112 void
00113 command(                    /* get/execute command */
00114        char  *prompt
00115 )
00116 {
00117 #define        badcom(s)    strncmp(s, inpbuf, args-inpbuf-1)
00118        char  inpbuf[256];
00119        char  *args;
00120 again:
00121        (*dev->comin)(inpbuf, prompt);            /* get command + arguments */
00122        for (args = inpbuf; *args && *args != ' '; args++)
00123               ;
00124        if (*args) *args++ = '\0';
00125        else *++args = '\0';
00126 
00127        if (waitrays() < 0)                /* clear ray queue */
00128               quit(1);
00129        
00130        switch (inpbuf[0]) {
00131        case 'f':                          /* new frame (|focus|free) */
00132               if (badcom("frame")) {
00133                      if (badcom("focus")) {
00134                             if (badcom("free"))
00135                                    goto commerr;
00136                             free_objmem();
00137                             break;
00138                      }
00139                      getfocus(args);
00140                      break;
00141               }
00142               getframe(args);
00143               break;
00144        case 'v':                          /* view */
00145               if (badcom("view"))
00146                      goto commerr;
00147               getview(args);
00148               break;
00149        case 'l':                          /* last view */
00150               if (badcom("last"))
00151                      goto commerr;
00152               lastview(args);
00153               break;
00154        case 'V':                          /* save view */
00155               if (badcom("V"))
00156                      goto commerr;
00157               saveview(args);
00158               break;
00159        case 'L':                          /* load view */
00160               if (badcom("L"))
00161                      goto commerr;
00162               loadview(args);
00163               break;
00164        case 'e':                          /* exposure */
00165               if (badcom("exposure"))
00166                      goto commerr;
00167               getexposure(args);
00168               break;
00169        case 's':                          /* set a parameter */
00170               if (badcom("set")) {
00171 #ifdef SIGTSTP
00172                      if (!badcom("stop"))
00173                             goto dostop;
00174 #endif
00175                      goto commerr;
00176               }
00177               setparam(args);
00178               break;
00179        case 'n':                          /* new picture */
00180               if (badcom("new"))
00181                      goto commerr;
00182               newimage(args);
00183               break;
00184        case 't':                          /* trace a ray */
00185               if (badcom("trace"))
00186                      goto commerr;
00187               traceray(args);
00188               break;
00189        case 'a':                          /* aim camera */
00190               if (badcom("aim"))
00191                      goto commerr;
00192               getaim(args);
00193               break;
00194        case 'm':                          /* move camera (or memstats) */
00195               if (badcom("move"))
00196 #ifdef MSTATS
00197               {
00198                      if (badcom("memory"))
00199                             goto commerr;
00200                      printmemstats(stderr);
00201                      break;
00202               }
00203 #else
00204                      goto commerr;
00205 #endif
00206               getmove(args);
00207               break;
00208        case 'r':                          /* rotate/repaint */
00209               if (badcom("rotate")) {
00210                      if (badcom("repaint")) {
00211                             if (badcom("redraw"))
00212                                    goto commerr;
00213                             redraw();
00214                             break;
00215                      }
00216                      getrepaint(args);
00217                      break;
00218               }
00219               getrotate(args);
00220               break;
00221        case 'p':                          /* pivot view */
00222               if (badcom("pivot")) {
00223                      if (badcom("pause"))
00224                             goto commerr;
00225                      goto again;
00226               }
00227               getpivot(args);
00228               break;
00229        case CTRL('R'):                           /* redraw */
00230               redraw();
00231               break;
00232        case 'w':                          /* write */
00233               if (badcom("write"))
00234                      goto commerr;
00235               writepict(args);
00236               break;
00237        case 'q':                          /* quit */
00238               if (badcom("quit"))
00239                      goto commerr;
00240               quit(0);
00241        case CTRL('C'):                           /* interrupt */
00242               goto again;
00243 #ifdef SIGTSTP
00244        case CTRL('Z'):;                   /* stop */
00245 dostop:
00246               devclose();
00247               kill(0, SIGTSTP);
00248               /* pc stops here */
00249               devopen(dvcname);
00250               redraw();
00251               break;
00252 #endif
00253        case '\0':                         /* continue */
00254               break;
00255        default:;
00256 commerr:
00257               if (iscntrl(inpbuf[0]))
00258                      sprintf(errmsg, "^%c: unknown control",
00259                                    inpbuf[0]|0100);
00260               else
00261                      sprintf(errmsg, "%s: unknown command", inpbuf);
00262               error(COMMAND, errmsg);
00263               break;
00264        }
00265 #undef badcom
00266 }
00267 
00268 
00269 void
00270 rsample(void)               /* sample the image */
00271 {
00272        int  xsiz, ysiz, y;
00273        PNODE  *p;
00274        PNODE  **pl;
00275        int  x;
00276        /*
00277         *     We initialize the bottom row in the image at our current
00278         * resolution.       During sampling, we check super-pixels to the
00279         * right and above by calling bigdiff().  If there is a significant
00280         * difference, we subsample the super-pixels.  The testing process
00281         * includes initialization of the next row.
00282         */
00283        xsiz = (((long)(pframe.r-pframe.l)<<pdepth)+hresolu-1) / hresolu;
00284        ysiz = (((long)(pframe.u-pframe.d)<<pdepth)+vresolu-1) / vresolu;
00285        pl = (PNODE **)malloc(xsiz*sizeof(PNODE *));
00286        if (pl == NULL)
00287               return;
00288        /*
00289         * Initialize the bottom row.
00290         */
00291        pl[0] = findrect(pframe.l, pframe.d, &ptrunk, pdepth);
00292        for (x = 1; x < xsiz; x++) {
00293               pl[x] = findrect(pframe.l+((x*hresolu)>>pdepth),
00294                             pframe.d, &ptrunk, pdepth);
00295        }
00296                                           /* sample the image */
00297        for (y = 0; /* y < ysiz */ ; y++) {
00298               for (x = 0; x < xsiz-1; x++) {
00299                      if (dev->inpready || errno == ENOMEM)
00300                             goto escape;
00301                      /*
00302                       * Test super-pixel to the right.
00303                       */
00304                      if (pl[x] != pl[x+1] && bigdiff(pl[x]->v,
00305                                    pl[x+1]->v, maxdiff)) {
00306                             refine(pl[x], 1);
00307                             refine(pl[x+1], 1);
00308                      }
00309               }
00310               if (y >= ysiz-1)
00311                      break;
00312               for (x = 0; x < xsiz; x++) {
00313                      if (dev->inpready || errno == ENOMEM)
00314                             goto escape;
00315                      /*
00316                       * Find super-pixel at this position in next row.
00317                       */
00318                      p = findrect(pframe.l+((x*hresolu)>>pdepth),
00319                             pframe.d+(((y+1)*vresolu)>>pdepth),
00320                                    &ptrunk, pdepth);
00321                      /*
00322                       * Test super-pixel in next row.
00323                       */
00324                      if (pl[x] != p && bigdiff(pl[x]->v, p->v, maxdiff)) {
00325                             refine(pl[x], 1);
00326                             refine(p, 1);
00327                      }
00328                      /*
00329                       * Copy into super-pixel array.
00330                       */
00331                      pl[x] = p;
00332               }
00333        }
00334 escape:
00335        free((void *)pl);
00336 }
00337 
00338 
00339 int
00340 refine(                            /* refine a node */
00341        PNODE  *p,
00342        int  pd
00343 )
00344 {
00345        int  growth;
00346        int  mx, my;
00347        int  i;
00348 
00349        if (dev->inpready)                 /* quit for input */
00350               return(0);
00351 
00352        if (pd <= 0)                       /* depth limit */
00353               return(0);
00354 
00355        mx = (p->xmin + p->xmax) >> 1;
00356        my = (p->ymin + p->ymax) >> 1;
00357        growth = 0;
00358 
00359        if (p->kid == NULL) {                     /* subdivide */
00360 
00361               if ((p->kid = newptree()) == NULL)
00362                      return(0);
00363 
00364               p->kid[UR].xmin = mx;
00365               p->kid[UR].ymin = my;
00366               p->kid[UR].xmax = p->xmax;
00367               p->kid[UR].ymax = p->ymax;
00368               p->kid[UL].xmin = p->xmin;
00369               p->kid[UL].ymin = my;
00370               p->kid[UL].xmax = mx;
00371               p->kid[UL].ymax = p->ymax;
00372               p->kid[DR].xmin = mx;
00373               p->kid[DR].ymin = p->ymin;
00374               p->kid[DR].xmax = p->xmax;
00375               p->kid[DR].ymax = my;
00376               p->kid[DL].xmin = p->xmin;
00377               p->kid[DL].ymin = p->ymin;
00378               p->kid[DL].xmax = mx;
00379               p->kid[DL].ymax = my;
00380               /*
00381                *  The following paint order can leave a black pixel
00382                *  if redraw() is called in (*dev->paintr)().
00383                */
00384               if (p->x >= mx && p->y >= my)
00385                      pcopy(p, p->kid+UR);
00386               else if (paint(p->kid+UR) < 0)
00387                      quit(1);
00388               if (p->x < mx && p->y >= my)
00389                      pcopy(p, p->kid+UL);
00390               else if (paint(p->kid+UL) < 0)
00391                      quit(1);
00392               if (p->x >= mx && p->y < my)
00393                      pcopy(p, p->kid+DR);
00394               else if (paint(p->kid+DR) < 0)
00395                      quit(1);
00396               if (p->x < mx && p->y < my)
00397                      pcopy(p, p->kid+DL);
00398               else if (paint(p->kid+DL) < 0)
00399                      quit(1);
00400 
00401               growth++;
00402        }
00403                                           /* do children */
00404        if (mx > pframe.l) {
00405               if (my > pframe.d)
00406                      growth += refine(p->kid+DL, pd-1);
00407               if (my < pframe.u)
00408                      growth += refine(p->kid+UL, pd-1);
00409        }
00410        if (mx < pframe.r) {
00411               if (my > pframe.d)
00412                      growth += refine(p->kid+DR, pd-1);
00413               if (my < pframe.u)
00414                      growth += refine(p->kid+UR, pd-1);
00415        }
00416        return(growth);
00417 }