home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / radsrc22 / src / rt / rview / rview.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-08  |  11.9 KB  |  452 lines

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)rview.c 2.9 9/22/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  rview.c - routines and variables for interactive view generation.
  9.  *
  10.  *     3/24/87
  11.  */
  12.  
  13. #include  "ray.h"
  14.  
  15. #include  "rpaint.h"
  16.  
  17. #include  <signal.h>
  18.  
  19. #include  <ctype.h>
  20.  
  21. VIEW  ourview = STDVIEW;                /* viewing parameters */
  22. int  hresolu, vresolu;                  /* image resolution */
  23.  
  24. int  dimlist[MAXDIM];                   /* sampling dimensions */
  25. int  ndims = 0;                         /* number of sampling dimensions */
  26. int  samplendx = 0;                     /* index for this sample */
  27.  
  28. int  psample = 8;                       /* pixel sample size */
  29. double  maxdiff = .15;                  /* max. sample difference */
  30.  
  31. double  exposure = 1.0;                 /* exposure for scene */
  32.  
  33. double  dstrsrc = 0.0;                  /* square source distribution */
  34. double  shadthresh = .1;                /* shadow threshold */
  35. double  shadcert = .25;                 /* shadow certainty */
  36. int  directrelay = 0;                   /* number of source relays */
  37. int  vspretest = 128;                   /* virtual source pretest density */
  38. int  directinvis = 0;                   /* sources invisible? */
  39. double  srcsizerat = 0.;                /* maximum ratio source size/dist. */
  40.  
  41. double  specthresh = .3;                /* specular sampling threshold */
  42. double  specjitter = 1.;                /* specular sampling jitter */
  43.  
  44. int  maxdepth = 4;                      /* maximum recursion depth */
  45. double  minweight = 1e-2;               /* minimum ray weight */
  46.  
  47. COLOR  ambval = BLKCOLOR;               /* ambient value */
  48. double  ambacc = 0.2;                   /* ambient accuracy */
  49. int  ambres = 8;                        /* ambient resolution */
  50. int  ambdiv = 32;                       /* ambient divisions */
  51. int  ambssamp = 0;                      /* ambient super-samples */
  52. int  ambounce = 0;                      /* ambient bounces */
  53. char  *amblist[128];                    /* ambient include/exclude list */
  54. int  ambincl = -1;                      /* include == 1, exclude == 0 */
  55.  
  56. int  greyscale = 0;                     /* map colors to brightness? */
  57. char  *devname = dev_default;           /* output device name */
  58.  
  59. struct driver  *dev = NULL;             /* driver functions */
  60.  
  61. VIEW  oldview;                          /* previous view parameters */
  62.  
  63. PNODE  ptrunk;                          /* the base of our image */
  64. RECT  pframe;                           /* current frame boundaries */
  65. int  pdepth;                            /* image depth in current frame */
  66.  
  67. static char  *reserve_mem = NULL;       /* pre-allocated reserve memory */
  68.  
  69. #define RESERVE_AMT     32768           /* amount of memory to reserve */
  70.  
  71. #define  CTRL(c)        ((c)-'@')
  72.  
  73.  
  74. quit(code)                      /* quit program */
  75. int  code;
  76. {
  77.     devclose();
  78.     exit(code);
  79. }
  80.  
  81.  
  82. devopen(dname)                          /* open device driver */
  83. char  *dname;
  84. {
  85.     extern char  *progname, *octname;
  86.     char  *id;
  87.     register int  i;
  88.  
  89.     id = octname!=NULL ? octname : progname;
  90.                         /* check device table */
  91.     for (i = 0; devtable[i].name; i++)
  92.         if (!strcmp(dname, devtable[i].name))
  93.             if ((dev = (*devtable[i].init)(dname, id)) == NULL) {
  94.                 sprintf(errmsg, "cannot initialize %s", dname);
  95.                 error(USER, errmsg);
  96.             } else
  97.                 return;
  98. #ifndef NIX
  99.                         /* not there, try exec */
  100.     if ((dev = comm_init(dname, id)) == NULL) {
  101.         sprintf(errmsg, "cannot start device \"%s\"", dname);
  102.         error(USER, errmsg);
  103.     }
  104. #endif
  105. }
  106.  
  107.  
  108. devclose()                              /* close our device */
  109. {
  110.     if (dev != NULL)
  111.         (*dev->close)();
  112.     dev = NULL;
  113. }
  114.  
  115.  
  116. printdevices()                          /* print list of output devices */
  117. {
  118.     register int  i;
  119.  
  120.     for (i = 0; devtable[i].name; i++)
  121.         printf("%-16s # %s\n", devtable[i].name, devtable[i].descrip);
  122. }
  123.  
  124.  
  125. rview()                         /* do a view */
  126. {
  127.     char  buf[32];
  128.  
  129.     devopen(devname);               /* open device */
  130.     newimage();                     /* start image (calls fillreserves) */
  131.  
  132.     for ( ; ; ) {                   /* quit in command() */
  133.         while (hresolu <= 1<<pdepth && vresolu <= 1<<pdepth)
  134.             command("done: ");
  135.         while (reserve_mem == NULL)
  136.             command("out of memory: ");
  137.         errno = 0;
  138.         if (hresolu <= psample<<pdepth && vresolu <= psample<<pdepth) {
  139.             sprintf(buf, "%d sampling...\n", 1<<pdepth);
  140.             (*dev->comout)(buf);
  141.             rsample();
  142.         } else {
  143.             sprintf(buf, "%d refining...\n", 1<<pdepth);
  144.             (*dev->comout)(buf);
  145.             refine(&ptrunk, 0, 0, hresolu, vresolu, pdepth+1);
  146.         }
  147.         if (errno == ENOMEM)            /* ran out of memory */
  148.             freereserves();
  149.         else if (dev->inpready)         /* noticed some input */
  150.             command(": ");
  151.         else                            /* finished this depth */
  152.             pdepth++;
  153.     }
  154. }
  155.  
  156.  
  157. fillreserves()                  /* fill memory reserves */
  158. {
  159.     if (reserve_mem != NULL)
  160.         return;
  161.     reserve_mem = malloc(RESERVE_AMT);
  162. }
  163.  
  164.  
  165. freereserves()                  /* free memory reserves */
  166. {
  167.     if (reserve_mem == NULL)
  168.         return;
  169.     free(reserve_mem);
  170.     reserve_mem = NULL;
  171. }
  172.  
  173.  
  174. command(prompt)                 /* get/execute command */
  175. char  *prompt;
  176. {
  177. #define  badcom(s)      strncmp(s, inpbuf, args-inpbuf-1)
  178.     char  inpbuf[256];
  179.     char  *args;
  180. again:
  181.     (*dev->comin)(inpbuf, prompt);          /* get command + arguments */
  182.     for (args = inpbuf; *args && *args != ' '; args++)
  183.         ;
  184.     if (*args) *args++ = '\0';
  185.     else *++args = '\0';
  186.     
  187.     switch (inpbuf[0]) {
  188.     case 'f':                               /* new frame */
  189.         if (badcom("frame"))
  190.             goto commerr;
  191.         getframe(args);
  192.         break;
  193.     case 'v':                               /* view */
  194.         if (badcom("view"))
  195.             goto commerr;
  196.         getview(args);
  197.         break;
  198.     case 'l':                               /* last view */
  199.         if (badcom("last"))
  200.             goto commerr;
  201.         lastview(args);
  202.         break;
  203.     case 'e':                               /* exposure */
  204.         if (badcom("exposure"))
  205.             goto commerr;
  206.         getexposure(args);
  207.         break;
  208.     case 's':                               /* set a parameter */
  209.         if (badcom("set"))
  210.             goto commerr;
  211.         setparam(args);
  212.         break;
  213.     case 'n':                               /* new picture */
  214.         if (badcom("new"))
  215.             goto commerr;
  216.         newimage();
  217.         break;
  218.     case 't':                               /* trace a ray */
  219.         if (badcom("trace"))
  220.             goto commerr;
  221.         traceray(args);
  222.         break;
  223.     case 'a':                               /* aim camera */
  224.         if (badcom("aim"))
  225.             goto commerr;
  226.         getaim(args);
  227.         break;
  228.     case 'm':                               /* move camera */
  229.         if (badcom("move"))
  230. #ifdef  MSTATS
  231.         {
  232.             if (badcom("memory"))
  233.                 goto commerr;
  234.             printmemstats(stderr);
  235.             break;
  236.         }
  237. #else
  238.             goto commerr;
  239. #endif
  240.         getmove(args);
  241.         break;
  242.     case 'r':                               /* rotate/repaint */
  243.         if (badcom("rotate")) {
  244.             if (badcom("repaint"))
  245.                 goto commerr;
  246.             getrepaint(args);
  247.             break;
  248.         }
  249.         getrotate(args);
  250.         break;
  251.     case 'p':                               /* pivot view */
  252.         if (badcom("pivot"))
  253.             goto commerr;
  254.         getpivot(args);
  255.         break;
  256.     case CTRL('R'):                         /* redraw */
  257.         redraw();
  258.         break;
  259.     case 'w':                               /* write */
  260.         if (badcom("write"))
  261.             goto commerr;
  262.         writepict(args);
  263.         break;
  264.     case 'q':                               /* quit */
  265.         if (badcom("quit"))
  266.             goto commerr;
  267.         quit(0);
  268.     case CTRL('C'):                         /* interrupt */
  269.         goto again;
  270. #ifdef  SIGTSTP
  271.     case CTRL('Z'):                         /* stop */
  272.         devclose();
  273.         kill(0, SIGTSTP);
  274.         /* pc stops here */
  275.         devopen(devname);
  276.         redraw();
  277.         break;
  278. #endif
  279.     case '\0':                              /* continue */
  280.         break;
  281.     default:;
  282. commerr:
  283.         if (iscntrl(inpbuf[0]))
  284.             sprintf(errmsg, "^%c: unknown control",
  285.                     inpbuf[0]|0100);
  286.         else
  287.             sprintf(errmsg, "%s: unknown command", inpbuf);
  288.         error(COMMAND, errmsg);
  289.         break;
  290.     }
  291. #undef  badcom
  292. }
  293.  
  294.  
  295. rsample()                       /* sample the image */
  296. {
  297.     int  xsiz, ysiz, y;
  298.     RECT  r;
  299.     PNODE  *p;
  300.     register RECT  *rl;
  301.     register PNODE  **pl;
  302.     register int  x;
  303.     /*
  304.      *     We initialize the bottom row in the image at our current
  305.      * resolution.  During sampling, we check super-pixels to the
  306.      * right and above by calling bigdiff().  If there is a significant
  307.      * difference, we subsample the super-pixels.  The testing process
  308.      * includes initialization of the next row.
  309.      */
  310.     xsiz = (((pframe.r-pframe.l)<<pdepth)+hresolu-1) / hresolu;
  311.     ysiz = (((pframe.u-pframe.d)<<pdepth)+vresolu-1) / vresolu;
  312.     rl = (RECT *)malloc(xsiz*sizeof(RECT));
  313.     if (rl == NULL)
  314.         return;
  315.     pl = (PNODE **)malloc(xsiz*sizeof(PNODE *));
  316.     if (pl == NULL) {
  317.         free((char *)rl);
  318.         return;
  319.     }
  320.     /*
  321.      * Initialize the bottom row.
  322.      */
  323.     rl[0].l = rl[0].d = 0;
  324.     rl[0].r = hresolu; rl[0].u = vresolu;
  325.     pl[0] = findrect(pframe.l, pframe.d, &ptrunk, rl, pdepth);
  326.     for (x = 1; x < xsiz; x++) {
  327.         rl[x].l = rl[x].d = 0;
  328.         rl[x].r = hresolu; rl[x].u = vresolu;
  329.         pl[x] = findrect(pframe.l+((x*hresolu)>>pdepth),
  330.                 pframe.d, &ptrunk, rl+x, pdepth);
  331.     }
  332.                         /* sample the image */
  333.     for (y = 0; /* y < ysiz */ ; y++) {
  334.         for (x = 0; x < xsiz-1; x++) {
  335.             if (dev->inpready || errno == ENOMEM)
  336.                 goto escape;
  337.             /*
  338.              * Test super-pixel to the right.
  339.              */
  340.             if (pl[x] != pl[x+1] && bigdiff(pl[x]->v,
  341.                     pl[x+1]->v, maxdiff)) {
  342.                 refine(pl[x], rl[x].l, rl[x].d,
  343.                         rl[x].r, rl[x].u, 1);
  344.                 refine(pl[x+1], rl[x+1].l, rl[x+1].d,
  345.                         rl[x+1].r, rl[x+1].u, 1);
  346.             }
  347.         }
  348.         if (y >= ysiz-1)
  349.             break;
  350.         for (x = 0; x < xsiz; x++) {
  351.             if (dev->inpready || errno == ENOMEM)
  352.                 goto escape;
  353.             /*
  354.              * Find super-pixel at this position in next row.
  355.              */
  356.             r.l = r.d = 0;
  357.             r.r = hresolu; r.u = vresolu;
  358.             p = findrect(pframe.l+((x*hresolu)>>pdepth),
  359.                 pframe.d+(((y+1)*vresolu)>>pdepth),
  360.                     &ptrunk, &r, pdepth);
  361.             /*
  362.              * Test super-pixel in next row.
  363.              */
  364.             if (pl[x] != p && bigdiff(pl[x]->v, p->v, maxdiff)) {
  365.                 refine(pl[x], rl[x].l, rl[x].d,
  366.                         rl[x].r, rl[x].u, 1);
  367.                 refine(p, r.l, r.d, r.r, r.u, 1);
  368.             }
  369.             /*
  370.              * Copy into super-pixel array.
  371.              */
  372.             rl[x].l = r.l; rl[x].d = r.d;
  373.             rl[x].r = r.r; rl[x].u = r.u;
  374.             pl[x] = p;
  375.         }
  376.     }
  377. escape:
  378.     free((char *)rl);
  379.     free((char *)pl);
  380. }
  381.  
  382.  
  383. int
  384. refine(p, xmin, ymin, xmax, ymax, pd)           /* refine a node */
  385. register PNODE  *p;
  386. int  xmin, ymin, xmax, ymax;
  387. int  pd;
  388. {
  389.     int  growth;
  390.     int  mx, my;
  391.     int  i;
  392.  
  393.     if (dev->inpready)                      /* quit for input */
  394.         return(0);
  395.  
  396.     if (pd <= 0)                            /* depth limit */
  397.         return(0);
  398.  
  399.     mx = (xmin + xmax) >> 1;
  400.     my = (ymin + ymax) >> 1;
  401.     growth = 0;
  402.  
  403.     if (p->kid == NULL) {                   /* subdivide */
  404.  
  405.         if ((p->kid = newptree()) == NULL)
  406.             return(0);
  407.         /*
  408.          *  The following paint order can leave a black pixel
  409.          *  if redraw() is called in (*dev->paintr)().
  410.          */
  411.         if (p->x >= mx && p->y >= my)
  412.             pcopy(p, p->kid+UR);
  413.         else
  414.             paint(p->kid+UR, mx, my, xmax, ymax);
  415.         if (p->x < mx && p->y >= my)
  416.             pcopy(p, p->kid+UL);
  417.         else
  418.             paint(p->kid+UL, xmin, my, mx, ymax);
  419.         if (p->x >= mx && p->y < my)
  420.             pcopy(p, p->kid+DR);
  421.         else
  422.             paint(p->kid+DR, mx, ymin, xmax, my);
  423.         if (p->x < mx && p->y < my)
  424.             pcopy(p, p->kid+DL);
  425.         else
  426.             paint(p->kid+DL, xmin, ymin, mx, my);
  427.  
  428.         growth++;
  429.     }
  430.                         /* do children */
  431.     if (mx > pframe.l) {
  432.         if (my > pframe.d)
  433.             growth += refine(p->kid+DL, xmin, ymin, mx, my, pd-1);
  434.         if (my < pframe.u)
  435.             growth += refine(p->kid+UL, xmin, my, mx, ymax, pd-1);
  436.     }
  437.     if (mx < pframe.r) {
  438.         if (my > pframe.d)
  439.             growth += refine(p->kid+DR, mx, ymin, xmax, my, pd-1);
  440.         if (my < pframe.u)
  441.             growth += refine(p->kid+UR, mx, my, xmax, ymax, pd-1);
  442.     }
  443.                         /* recompute sum */
  444.     if (growth) {
  445.         setcolor(p->v, 0.0, 0.0, 0.0);
  446.         for (i = 0; i < 4; i++)
  447.             addcolor(p->v, p->kid[i].v);
  448.         scalecolor(p->v, 0.25);
  449.     }
  450.     return(growth);
  451. }
  452.