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

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)rv2.c 2.12 10/15/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  rv2.c - command routines used in tracing a view.
  9.  *
  10.  *     3/24/87
  11.  */
  12.  
  13. #include  "ray.h"
  14.  
  15. #include  "octree.h"
  16.  
  17. #include  "otypes.h"
  18.  
  19. #include  "rpaint.h"
  20.  
  21. #include  "resolu.h"
  22.  
  23. #include  <ctype.h>
  24.  
  25. #define  CTRL(c)    ((c)-'@')
  26.  
  27. #ifdef  SMLFLT
  28. #define  sscanvec(s,v)    (sscanf(s,"%f %f %f",v,v+1,v+2)==3)
  29. #else
  30. #define  sscanvec(s,v)    (sscanf(s,"%lf %lf %lf",v,v+1,v+2)==3)
  31. #endif
  32.  
  33.  
  34. extern char  VersionID[];
  35. extern char  *progname;
  36. extern char  *octname;
  37.  
  38.  
  39. getframe(s)                /* get a new frame */
  40. char  *s;
  41. {
  42.     if (getrect(s, &pframe) < 0)
  43.         return;
  44.     pdepth = 0;
  45. }
  46.  
  47.  
  48. getrepaint(s)                /* get area and repaint */
  49. char  *s;
  50. {
  51.     RECT  box;
  52.  
  53.     if (getrect(s, &box) < 0)
  54.         return;
  55.     paintrect(&ptrunk, 0, 0, hresolu, vresolu, &box);
  56. }
  57.  
  58.  
  59. getview(s)                /* get/show view parameters */
  60. char  *s;
  61. {
  62.     FILE  *fp;
  63.     char  buf[128];
  64.     char  *fname;
  65.     int  change = 0;
  66.     VIEW  nv;
  67.  
  68.     while (isspace(*s))
  69.         s++;
  70.     if (*s == '-') {            /* command line parameters */
  71.         copystruct(&nv, &ourview);
  72.         if (sscanview(&nv, s))
  73.             newview(&nv);
  74.         else
  75.             error(COMMAND, "bad view option(s)");
  76.         return;
  77.     }
  78.     if (sscanf(s, "%s", buf) == 1) {    /* write parameters to a file */
  79.         if ((fname = getpath(buf, NULL, 0)) == NULL ||
  80.                 (fp = fopen(fname, "a")) == NULL) {
  81.             sprintf(errmsg, "cannot open \"%s\"", buf);
  82.             error(COMMAND, errmsg);
  83.             return;
  84.         }
  85.         fputs(progname, fp);
  86.         fprintview(&ourview, fp);
  87.         fputs(sskip(s), fp);
  88.         fputs("\n", fp);
  89.         fclose(fp);
  90.         return;
  91.     }
  92.     sprintf(buf, "view type (%c): ", ourview.type);
  93.     (*dev->comout)(buf);
  94.     (*dev->comin)(buf, NULL);
  95.     if (buf[0] == CTRL('C')) return;
  96.     if (buf[0] && buf[0] != ourview.type) {
  97.         nv.type = buf[0];
  98.         change++;
  99.     } else
  100.         nv.type = ourview.type;
  101.     sprintf(buf, "view point (%.6g %.6g %.6g): ",
  102.             ourview.vp[0], ourview.vp[1], ourview.vp[2]);
  103.     (*dev->comout)(buf);
  104.     (*dev->comin)(buf, NULL);
  105.     if (buf[0] == CTRL('C')) return;
  106.     if (sscanvec(buf, nv.vp))
  107.         change++;
  108.     else
  109.         VCOPY(nv.vp, ourview.vp);
  110.     sprintf(buf, "view direction (%.6g %.6g %.6g): ",
  111.             ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
  112.     (*dev->comout)(buf);
  113.     (*dev->comin)(buf, NULL);
  114.     if (buf[0] == CTRL('C')) return;
  115.     if (sscanvec(buf, nv.vdir))
  116.         change++;
  117.     else
  118.         VCOPY(nv.vdir, ourview.vdir);
  119.     sprintf(buf, "view up (%.6g %.6g %.6g): ",
  120.             ourview.vup[0], ourview.vup[1], ourview.vup[2]);
  121.     (*dev->comout)(buf);
  122.     (*dev->comin)(buf, NULL);
  123.     if (buf[0] == CTRL('C')) return;
  124.     if (sscanvec(buf, nv.vup))
  125.         change++;
  126.     else
  127.         VCOPY(nv.vup, ourview.vup);
  128.     sprintf(buf, "view horiz and vert size (%.6g %.6g): ",
  129.             ourview.horiz, ourview.vert);
  130.     (*dev->comout)(buf);
  131.     (*dev->comin)(buf, NULL);
  132.     if (buf[0] == CTRL('C')) return;
  133.     if (sscanf(buf, "%lf %lf", &nv.horiz, &nv.vert) == 2)
  134.         change++;
  135.     else {
  136.         nv.horiz = ourview.horiz; nv.vert = ourview.vert;
  137.     }
  138.     sprintf(buf, "view shift and lift (%.6g %.6g): ",
  139.             ourview.hoff, ourview.voff);
  140.     (*dev->comout)(buf);
  141.     (*dev->comin)(buf, NULL);
  142.     if (buf[0] == CTRL('C')) return;
  143.     if (sscanf(buf, "%lf %lf", &nv.hoff, &nv.voff) == 2)
  144.         change++;
  145.     else {
  146.         nv.hoff = ourview.hoff; nv.voff = ourview.voff;
  147.     }
  148.     if (change)
  149.         newview(&nv);
  150. }
  151.  
  152.  
  153. lastview(s)                /* return to a previous view */
  154. char  *s;
  155. {
  156.     char  buf[128];
  157.     char  *fname;
  158.     int  success;
  159.     VIEW  nv;
  160.  
  161.     if (sscanf(s, "%s", buf) == 1) {    /* get parameters from a file */
  162.         copystruct(&nv, &stdview);
  163.         if ((fname = getpath(buf, NULL, 0)) == NULL ||
  164.                 (success = viewfile(fname, &nv, NULL)) == -1) {
  165.             sprintf(errmsg, "cannot open \"%s\"", buf);
  166.             error(COMMAND, errmsg);
  167.             return;
  168.         }
  169.         if (!success)
  170.             error(COMMAND, "wrong file format");
  171.         else
  172.             newview(&nv);
  173.         return;
  174.     }
  175.     if (oldview.type == 0) {    /* no old view! */
  176.         error(COMMAND, "no previous view");
  177.         return;
  178.     }
  179.     copystruct(&nv, &ourview);
  180.     copystruct(&ourview, &oldview);
  181.     copystruct(&oldview, &nv);
  182.     newimage();
  183. }
  184.  
  185.  
  186. getaim(s)                /* aim camera */
  187. char  *s;
  188. {
  189.     double  zfact;
  190.     VIEW  nv;
  191.  
  192.     if (getinterest(s, 1, nv.vdir, &zfact) < 0)
  193.         return;
  194.     nv.type = ourview.type;
  195.     VCOPY(nv.vp, ourview.vp);
  196.     VCOPY(nv.vup, ourview.vup);
  197.     nv.hoff = ourview.hoff; nv.voff = ourview.voff;
  198.     nv.horiz = ourview.horiz; nv.vert = ourview.vert;
  199.     zoomview(&nv, zfact);
  200.     newview(&nv);
  201. }
  202.  
  203.  
  204. getmove(s)                /* move camera */
  205. char  *s;
  206. {
  207.     FVECT  vc;
  208.     double  mag;
  209.  
  210.     if (getinterest(s, 0, vc, &mag) < 0)
  211.         return;
  212.     moveview(0.0, 0.0, mag, vc);
  213. }
  214.  
  215.  
  216. getrotate(s)                /* rotate camera */
  217. char  *s;
  218. {
  219.     VIEW  nv;
  220.     FVECT  v1;
  221.     double  angle, elev, zfact;
  222.     
  223.     elev = 0.0; zfact = 1.0;
  224.     if (sscanf(s, "%lf %lf %lf", &angle, &elev, &zfact) < 1) {
  225.         error(COMMAND, "missing angle");
  226.         return;
  227.     }
  228.     nv.type = ourview.type;
  229.     VCOPY(nv.vp, ourview.vp);
  230.     VCOPY(nv.vup, ourview.vup);
  231.     nv.hoff = ourview.hoff; nv.voff = ourview.voff;
  232.     spinvector(nv.vdir, ourview.vdir, ourview.vup, angle*(PI/180.));
  233.     if (elev != 0.0) {
  234.         fcross(v1, nv.vdir, ourview.vup);
  235.         normalize(v1);
  236.         spinvector(nv.vdir, nv.vdir, v1, elev*(PI/180.));
  237.     }
  238.     nv.horiz = ourview.horiz; nv.vert = ourview.vert;
  239.     zoomview(&nv, zfact);
  240.     newview(&nv);
  241. }
  242.  
  243.  
  244. getpivot(s)                /* pivot viewpoint */
  245. register char  *s;
  246. {
  247.     FVECT  vc;
  248.     double  angle, elev, mag;
  249.  
  250.     elev = 0.0;
  251.     if (sscanf(s, "%lf %lf", &angle, &elev) < 1) {
  252.         error(COMMAND, "missing angle");
  253.         return;
  254.     }
  255.     if (getinterest(sskip(sskip(s)), 0, vc, &mag) < 0)
  256.         return;
  257.     moveview(angle, elev, mag, vc);
  258. }
  259.  
  260.  
  261. getexposure(s)                /* get new exposure */
  262. char  *s;
  263. {
  264.     char  buf[128];
  265.     register char  *cp;
  266.     register PNODE  *p;
  267.     RECT  r;
  268.     int  x, y;
  269.     double  e;
  270.  
  271.     for (cp = s; isspace(*cp); cp++)
  272.         ;
  273.     if (*cp == '\0') {        /* normalize to point */
  274.         if (dev->getcur == NULL)
  275.             return;
  276.         (*dev->comout)("Pick point for exposure\n");
  277.         if ((*dev->getcur)(&x, &y) == ABORT)
  278.             return;
  279.         r.l = r.d = 0;
  280.         r.r = hresolu; r.u = vresolu;
  281.         p = findrect(x, y, &ptrunk, &r, -1);
  282.         e = 1.0;
  283.     } else {
  284.         if (*cp == '=') {    /* absolute setting */
  285.             p = NULL;
  286.             e = 1.0/exposure;
  287.             for (cp++; isspace(*cp); cp++)
  288.                 ;
  289.             if (*cp == '\0') {    /* interactive */
  290.                 sprintf(buf, "exposure (%lf): ", exposure);
  291.                 (*dev->comout)(buf);
  292.                 (*dev->comin)(buf, NULL);
  293.                 for (cp = buf; isspace(*cp); cp++)
  294.                     ;
  295.                 if (*cp == '\0')
  296.                     return;
  297.             }
  298.         } else {        /* normalize to average */
  299.             p = &ptrunk;
  300.             e = 1.0;
  301.         }
  302.         if (*cp == '+' || *cp == '-')    /* f-stops */
  303.             e *= pow(2.0, atof(cp));
  304.         else                /* multiplier */
  305.             e *= atof(cp);
  306.     }
  307.     if (p != NULL) {        /* relative setting */
  308.         if (bright(p->v) < 1e-25) {
  309.             error(COMMAND, "cannot normalize to zero");
  310.             return;
  311.         }
  312.         e *= 0.5 / bright(p->v);
  313.     }
  314.     if (e <= FTINY || fabs(1.0 - e) <= FTINY)
  315.         return;
  316.     scalepict(&ptrunk, e);
  317.     exposure *= e;
  318.     redraw();
  319. }
  320.  
  321.  
  322. getparam(str, dsc, typ, ptr)        /* get variable from user */
  323. char  *str, *dsc;
  324. int  typ;
  325. register union {int i; double d; COLOR C;}  *ptr;
  326. {
  327.     extern char  *index();
  328.     int  i0;
  329.     double  d0, d1, d2;
  330.     char  buf[48];
  331.  
  332.     switch (typ) {
  333.     case 'i':            /* integer */
  334.         if (sscanf(str, "%d", &i0) != 1) {
  335.             (*dev->comout)(dsc);
  336.             sprintf(buf, " (%d): ", ptr->i);
  337.             (*dev->comout)(buf);
  338.             (*dev->comin)(buf, NULL);
  339.             if (sscanf(buf, "%d", &i0) != 1)
  340.                 return(0);
  341.         }
  342.         ptr->i = i0;
  343.         return(1);
  344.     case 'r':            /* real */
  345.         if (sscanf(str, "%lf", &d0) != 1) {
  346.             (*dev->comout)(dsc);
  347.             sprintf(buf, " (%.6g): ", ptr->d);
  348.             (*dev->comout)(buf);
  349.             (*dev->comin)(buf, NULL);
  350.             if (sscanf(buf, "%lf", &d0) != 1)
  351.                 return(0);
  352.         }
  353.         ptr->d = d0;
  354.         return(1);
  355.     case 'b':            /* boolean */
  356.         if (sscanf(str, "%1s", buf) != 1) {
  357.             (*dev->comout)(dsc);
  358.             sprintf(buf, "? (%c): ", ptr->i ? 'y' : 'n');
  359.             (*dev->comout)(buf);
  360.             (*dev->comin)(buf, NULL);
  361.             if (buf[0] == '\0' ||
  362.                     index("yY+1tTnN-0fF", buf[0]) == NULL)
  363.                 return(0);
  364.         }
  365.         ptr->i = index("yY+1tT", buf[0]) != NULL;
  366.         return(1);
  367.     case 'C':            /* color */
  368.         if (sscanf(str, "%lf %lf %lf", &d0, &d1, &d2) != 3) {
  369.             (*dev->comout)(dsc);
  370.             sprintf(buf, " (%.6g %.6g %.6g): ",
  371.                     colval(ptr->C,RED),
  372.                     colval(ptr->C,GRN),
  373.                     colval(ptr->C,BLU));
  374.             (*dev->comout)(buf);
  375.             (*dev->comin)(buf, NULL);
  376.             if (sscanf(buf, "%lf %lf %lf", &d0, &d1, &d2) != 3)
  377.                 return(0);
  378.         }
  379.         setcolor(ptr->C, d0, d1, d2);
  380.         return(1);
  381.     }
  382. }
  383.  
  384.  
  385. setparam(s)                /* get/set program parameter */
  386. register char  *s;
  387. {
  388.     extern int  psample;
  389.     extern double  maxdiff;
  390.     extern double  minweight;
  391.     extern int  maxdepth;
  392.     extern double  dstrsrc;
  393.     extern double  shadthresh;
  394.     extern double  shadcert;
  395.     extern COLOR  ambval;
  396.     extern double  ambacc;
  397.     extern int  ambres;
  398.     extern int  ambdiv;
  399.     extern int  ambssamp;
  400.     extern int  ambounce;
  401.     extern int  directinvis;
  402.     extern double  srcsizerat;
  403.     extern int  do_irrad;
  404.     extern double  specjitter;
  405.     extern double  specthresh;
  406.     char  buf[128];
  407.     
  408.     if (s[0] == '\0') {
  409.         (*dev->comout)(
  410.         "aa ab ad ar as av b dc di dj ds dt i lr lw ps pt sj st: ");
  411.         (*dev->comin)(buf, NULL);
  412.         s = buf;
  413.     }
  414.     switch (s[0]) {
  415.     case 'l':            /* limit */
  416.         switch (s[1]) {
  417.         case 'w':            /* weight */
  418.             getparam(s+2, "limit weight", 'r', &minweight);
  419.             break;
  420.         case 'r':            /* reflection */
  421.             getparam(s+2, "limit reflection", 'i', &maxdepth);
  422.             break;
  423.         default:
  424.             goto badparam;
  425.         }
  426.         break;
  427.     case 'd':            /* direct */
  428.         switch (s[1]) {
  429.         case 'j':            /* jitter */
  430.             getparam(s+2, "direct jitter", 'r', &dstrsrc);
  431.             break;
  432.         case 'c':            /* certainty */
  433.             getparam(s+2, "direct certainty", 'r', &shadcert);
  434.             break;
  435.         case 't':            /* threshold */
  436.             getparam(s+2, "direct threshold", 'r', &shadthresh);
  437.             break;
  438.         case 'i':            /* invisibility */
  439.             getparam(s+2, "direct invisibility",
  440.                     'b', &directinvis);
  441.             break;
  442.         case 's':            /* sampling */
  443.             getparam(s+2, "direct sampling", 'r', &srcsizerat);
  444.             break;
  445.         default:
  446.             goto badparam;
  447.         }
  448.         break;
  449.     case 'b':            /* black and white */
  450.         getparam(s+1, "black and white", 'b', &greyscale);
  451.         break;
  452.     case 'i':            /* irradiance */
  453.         getparam(s+1, "irradiance", 'b', &do_irrad);
  454.         break;
  455.     case 'a':            /* ambient */
  456.         switch (s[1]) {
  457.         case 'v':            /* value */
  458.             getparam(s+2, "ambient value", 'C', (COLOR *)ambval);
  459.             break;
  460.         case 'a':            /* accuracy */
  461.             getparam(s+2, "ambient accuracy", 'r', &ambacc);
  462.             break;
  463.         case 'd':            /* divisions */
  464.             getparam(s+2, "ambient divisions", 'i', &ambdiv);
  465.             break;
  466.         case 's':            /* samples */
  467.             getparam(s+2, "ambient super-samples", 'i', &ambssamp);
  468.             break;
  469.         case 'b':            /* bounces */
  470.             getparam(s+2, "ambient bounces", 'i', &ambounce);
  471.             break;
  472.         case 'r':
  473.             if (getparam(s+2, "ambient resolution", 'i', &ambres))
  474.                 setambres(ambres);
  475.             break;
  476.         default:
  477.             goto badparam;
  478.         }
  479.         break;
  480.     case 'p':            /* pixel */
  481.         switch (s[1]) {
  482.         case 's':            /* sample */
  483.             if (getparam(s+2, "pixel sample", 'i', &psample))
  484.                 pdepth = 0;
  485.             break;
  486.         case 't':            /* threshold */
  487.             if (getparam(s+2, "pixel threshold", 'r', &maxdiff))
  488.                 pdepth = 0;
  489.             break;
  490.         default:
  491.             goto badparam;
  492.         }
  493.         break;
  494.     case 's':            /* specular */
  495.         switch (s[1]) {
  496.         case 'j':            /* jitter */
  497.             getparam(s+2, "specular jitter", 'r', &specjitter);
  498.             break;
  499.         case 't':            /* threshold */
  500.             getparam(s+2, "specular threshold", 'r', &specthresh);
  501.             break;
  502.         default:
  503.             goto badparam;
  504.         }
  505.         break;
  506.     case '\0':            /* nothing */
  507.         break;
  508.     default:;
  509. badparam:
  510.         *sskip(s) = '\0';
  511.         sprintf(errmsg, "%s: unknown variable", s);
  512.         error(COMMAND, errmsg);
  513.         break;
  514.     }
  515. }
  516.  
  517.  
  518. traceray(s)                /* trace a single ray */
  519. char  *s;
  520. {
  521.     char  buf[128];
  522.     int  x, y;
  523.     RAY  thisray;
  524.  
  525.     if (!sscanvec(s, thisray.rorg) ||
  526.             !sscanvec(sskip(sskip(sskip(s))), thisray.rdir)) {
  527.  
  528.         if (dev->getcur == NULL)
  529.             return;
  530.         (*dev->comout)("Pick ray\n");
  531.         if ((*dev->getcur)(&x, &y) == ABORT)
  532.             return;
  533.  
  534.         if (viewray(thisray.rorg, thisray.rdir, &ourview,
  535.                 (x+.5)/hresolu, (y+.5)/vresolu) < 0) {
  536.             error(COMMAND, "not on image");
  537.             return;
  538.         }
  539.  
  540.     } else if (normalize(thisray.rdir) == 0.0) {
  541.         error(COMMAND, "zero ray direction");
  542.         return;
  543.     }
  544.  
  545.     rayorigin(&thisray, NULL, PRIMARY, 1.0);
  546.     
  547.     rayvalue(&thisray);
  548.  
  549.     if (thisray.ro == NULL)
  550.         (*dev->comout)("ray hit nothing");
  551.     else {
  552.         sprintf(buf, "ray hit %s %s \"%s\"",
  553.                 objptr(thisray.ro->omod)->oname,
  554.                 ofun[thisray.ro->otype].funame,
  555.                 thisray.ro->oname);
  556.         (*dev->comout)(buf);
  557.         (*dev->comin)(buf, NULL);
  558.         if (thisray.rot >= FHUGE)
  559.             (*dev->comout)("at infinity");
  560.         else {
  561.             sprintf(buf, "at (%.6g %.6g %.6g)", thisray.rop[0],
  562.                     thisray.rop[1], thisray.rop[2]);
  563.             (*dev->comout)(buf);
  564.         }
  565.         (*dev->comin)(buf, NULL);
  566.         sprintf(buf, "value (%.5g %.5g %.5g) (%.1fL)",
  567.                 colval(thisray.rcol,RED),
  568.                 colval(thisray.rcol,GRN),
  569.                 colval(thisray.rcol,BLU),
  570.                 luminance(thisray.rcol));
  571.         (*dev->comout)(buf);
  572.     }
  573.     (*dev->comin)(buf, NULL);
  574. }
  575.  
  576.  
  577. writepict(s)                /* write the picture to a file */
  578. char  *s;
  579. {
  580.     static char  buf[128];
  581.     char  *fname;
  582.     FILE  *fp;
  583.     COLR  *scanline;
  584.     int  y;
  585.  
  586.     if (sscanf(s, "%s", buf) != 1 && buf[0] == '\0') {
  587.         error(COMMAND, "no file");
  588.         return;
  589.     }
  590.     if ((fname = getpath(buf, NULL, 0)) == NULL ||
  591.             (fp = fopen(fname, "w")) == NULL) {
  592.         sprintf(errmsg, "cannot open \"%s\"", buf);
  593.         error(COMMAND, errmsg);
  594.         return;
  595.     }
  596. #ifdef MSDOS
  597.     setmode(fileno(fp), O_BINARY);
  598. #endif
  599.     (*dev->comout)("writing \"");
  600.     (*dev->comout)(fname);
  601.     (*dev->comout)("\"...\n");
  602.                         /* write header */
  603.     fputs(progname, fp);
  604.     fprintview(&ourview, fp);
  605.     if (octname != NULL)
  606.         fprintf(fp, " %s\n", octname);
  607.     else
  608.         putc('\n', fp);
  609.     fprintf(fp, "SOFTWARE= %s\n", VersionID);
  610.     if (exposure != 1.0)
  611.         fputexpos(exposure, fp);
  612.     if (dev->pixaspect != 1.0)
  613.         fputaspect(dev->pixaspect, fp);
  614.     fputformat(COLRFMT, fp);
  615.     putc('\n', fp);
  616.     fprtresolu(hresolu, vresolu, fp);
  617.  
  618.     scanline = (COLR *)malloc(hresolu*sizeof(COLR));
  619.     if (scanline == NULL) {
  620.         error(COMMAND, "not enough memory!");
  621.         fclose(fp);
  622.         unlink(fname);
  623.         return;
  624.     }
  625.     for (y = vresolu-1; y >= 0; y--) {
  626.         getpictcolrs(y, scanline, &ptrunk, hresolu, vresolu);
  627.         if (fwritecolrs(scanline, hresolu, fp) < 0)
  628.             break;
  629.     }
  630.     free((char *)scanline);
  631.     if (fclose(fp) < 0)
  632.         error(COMMAND, "write error");
  633. }
  634.