home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / COMMON / IMAGE.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  10KB  |  446 lines

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)image.c 2.5 9/8/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  image.c - routines for image generation.
  9.  *
  10.  *     10/17/85
  11.  */
  12.  
  13. #include  "standard.h"
  14.  
  15. #include  "view.h"
  16.  
  17. #include  "resolu.h"
  18.  
  19. #include  "paths.h"
  20.  
  21. VIEW  stdview = STDVIEW;        /* default view parameters */
  22.  
  23.  
  24. char *
  25. setview(v)        /* set hvec and vvec, return message on error */
  26. register VIEW  *v;
  27. {
  28.     static char  ill_horiz[] = "illegal horizontal view size";
  29.     static char  ill_vert[] = "illegal vertical view size";
  30.     
  31.     if (normalize(v->vdir) == 0.0)        /* normalize direction */
  32.         return("zero view direction");
  33.  
  34.     if (normalize(v->vup) == 0.0)        /* normalize view up */
  35.         return("zero view up vector");
  36.  
  37.     fcross(v->hvec, v->vdir, v->vup);    /* compute horiz dir */
  38.  
  39.     if (normalize(v->hvec) == 0.0)
  40.         return("view up parallel to view direction");
  41.  
  42.     fcross(v->vvec, v->hvec, v->vdir);    /* compute vert dir */
  43.  
  44.     if (v->horiz <= FTINY)
  45.         return(ill_horiz);
  46.     if (v->vert <= FTINY)
  47.         return(ill_vert);
  48.  
  49.     switch (v->type) {
  50.     case VT_PAR:                /* parallel view */
  51.         v->hn2 = v->horiz;
  52.         v->vn2 = v->vert;
  53.         break;
  54.     case VT_PER:                /* perspective view */
  55.         if (v->horiz >= 180.0-FTINY)
  56.             return(ill_horiz);
  57.         if (v->vert >= 180.0-FTINY)
  58.             return(ill_vert);
  59.         v->hn2 = 2.0 * tan(v->horiz*(PI/180.0/2.0));
  60.         v->vn2 = 2.0 * tan(v->vert*(PI/180.0/2.0));
  61.         break;
  62.     case VT_ANG:                /* angular fisheye */
  63.         if (v->horiz > 360.0+FTINY)
  64.             return(ill_horiz);
  65.         if (v->vert > 360.0+FTINY)
  66.             return(ill_vert);
  67.         v->hn2 = v->horiz / 90.0;
  68.         v->vn2 = v->vert / 90.0;
  69.         break;
  70.     case VT_HEM:                /* hemispherical fisheye */
  71.         if (v->horiz > 180.0+FTINY)
  72.             return(ill_horiz);
  73.         if (v->vert > 180.0+FTINY)
  74.             return(ill_vert);
  75.         v->hn2 = 2.0 * sin(v->horiz*(PI/180.0/2.0));
  76.         v->vn2 = 2.0 * sin(v->vert*(PI/180.0/2.0));
  77.         break;
  78.     default:
  79.         return("unknown view type");
  80.     }
  81.     if (v->type != VT_ANG) {
  82.         v->hvec[0] *= v->hn2;
  83.         v->hvec[1] *= v->hn2;
  84.         v->hvec[2] *= v->hn2;
  85.         v->vvec[0] *= v->vn2;
  86.         v->vvec[1] *= v->vn2;
  87.         v->vvec[2] *= v->vn2;
  88.     }
  89.     v->hn2 *= v->hn2;
  90.     v->vn2 *= v->vn2;
  91.  
  92.     return(NULL);
  93. }
  94.  
  95.  
  96. normaspect(va, ap, xp, yp)        /* fix pixel aspect or resolution */
  97. double  va;            /* view aspect ratio */
  98. double  *ap;            /* pixel aspect in (or out if 0) */
  99. int  *xp, *yp;            /* x and y resolution in (or out if *ap!=0) */
  100. {
  101.     if (*ap <= FTINY)
  102.         *ap = va * *xp / *yp;        /* compute pixel aspect */
  103.     else if (va * *xp > *ap * *yp)
  104.         *xp = *yp / va * *ap + .5;    /* reduce x resolution */
  105.     else
  106.         *yp = *xp * va / *ap + .5;    /* reduce y resolution */
  107. }
  108.  
  109.  
  110. viewray(orig, direc, v, x, y)        /* compute ray origin and direction */
  111. FVECT  orig, direc;
  112. register VIEW  *v;
  113. double  x, y;
  114. {
  115.     double    d, z;
  116.     
  117.     x += v->hoff - 0.5;
  118.     y += v->voff - 0.5;
  119.  
  120.     switch(v->type) {
  121.     case VT_PAR:            /* parallel view */
  122.         orig[0] = v->vp[0] + x*v->hvec[0] + y*v->vvec[0];
  123.         orig[1] = v->vp[1] + x*v->hvec[1] + y*v->vvec[1];
  124.         orig[2] = v->vp[2] + x*v->hvec[2] + y*v->vvec[2];
  125.         VCOPY(direc, v->vdir);
  126.         return(0);
  127.     case VT_PER:            /* perspective view */
  128.         VCOPY(orig, v->vp);
  129.         direc[0] = v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
  130.         direc[1] = v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
  131.         direc[2] = v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
  132.         normalize(direc);
  133.         return(0);
  134.     case VT_HEM:            /* hemispherical fisheye */
  135.         z = 1.0 - x*x*v->hn2 - y*y*v->vn2;
  136.         if (z < 0.0)
  137.             return(-1);
  138.         z = sqrt(z);
  139.         VCOPY(orig, v->vp);
  140.         direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
  141.         direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
  142.         direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
  143.         return(0);
  144.     case VT_ANG:            /* angular fisheye */
  145.         x *= v->horiz/180.0;
  146.         y *= v->vert/180.0;
  147.         d = x*x + y*y;
  148.         if (d > 1.0)
  149.             return(-1);
  150.         VCOPY(orig, v->vp);
  151.         if (d <= FTINY) {
  152.             VCOPY(direc, v->vdir);
  153.             return(0);
  154.         }
  155.         d = sqrt(d);
  156.         z = cos(PI*d);
  157.         d = sqrt(1 - z*z)/d;
  158.         x *= d;
  159.         y *= d;
  160.         direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
  161.         direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
  162.         direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
  163.         return(0);
  164.     }
  165.     return(-1);
  166. }
  167.  
  168.  
  169. viewloc(ip, v, p)        /* find image location for point */
  170. FVECT  ip;
  171. register VIEW  *v;
  172. FVECT  p;
  173. {
  174.     double  d;
  175.     FVECT  disp;
  176.  
  177.     disp[0] = p[0] - v->vp[0];
  178.     disp[1] = p[1] - v->vp[1];
  179.     disp[2] = p[2] - v->vp[2];
  180.  
  181.     switch (v->type) {
  182.     case VT_PAR:            /* parallel view */
  183.         ip[2] = DOT(disp,v->vdir);
  184.         break;
  185.     case VT_PER:            /* perspective view */
  186.         d = DOT(disp,v->vdir);
  187.         ip[2] = sqrt(DOT(disp,disp));
  188.         if (d < 0.0) {        /* fold pyramid */
  189.             ip[2] = -ip[2];
  190.             d = -d;
  191.         } else if (d > FTINY) {
  192.             d = 1.0/d;
  193.             disp[0] *= d;
  194.             disp[1] *= d;
  195.             disp[2] *= d;
  196.         }
  197.         break;
  198.     case VT_HEM:            /* hemispherical fisheye */
  199.         d = normalize(disp);
  200.         if (DOT(disp,v->vdir) < 0.0)
  201.             ip[2] = -d;
  202.         else
  203.             ip[2] = d;
  204.         break;
  205.     case VT_ANG:            /* angular fisheye */
  206.         ip[0] = 0.5 - v->hoff;
  207.         ip[1] = 0.5 - v->voff;
  208.         ip[2] = normalize(disp);
  209.         d = DOT(disp,v->vdir);
  210.         if (d >= 1.0-FTINY)
  211.             return;
  212.         if (d <= -(1.0-FTINY)) {
  213.             ip[1] += 180.0/v->horiz;
  214.             ip[2] += 180.0/v->vert;
  215.             return;
  216.         }
  217.         d = acos(d)/PI / sqrt(1.0 - d*d);
  218.         ip[0] += DOT(disp,v->hvec)*d*180.0/v->horiz;
  219.         ip[1] += DOT(disp,v->vvec)*d*180.0/v->vert;
  220.         return;
  221.     }
  222.     ip[0] = DOT(disp,v->hvec)/v->hn2 + 0.5 - v->hoff;
  223.     ip[1] = DOT(disp,v->vvec)/v->vn2 + 0.5 - v->voff;
  224. }
  225.  
  226.  
  227. pix2loc(loc, rp, px, py)    /* compute image location from pixel pos. */
  228. FLOAT  loc[2];
  229. register RESOLU  *rp;
  230. int  px, py;
  231. {
  232.     register int  x, y;
  233.  
  234.     if (rp->or & YMAJOR) {
  235.         x = px;
  236.         y = py;
  237.     } else {
  238.         x = py;
  239.         y = px;
  240.     }
  241.     if (rp->or & XDECR)
  242.         x = rp->xr-1 - x;
  243.     if (rp->or & YDECR)
  244.         y = rp->yr-1 - y;
  245.     loc[0] = (x+.5)/rp->xr;
  246.     loc[1] = (y+.5)/rp->yr;
  247. }
  248.  
  249.  
  250. loc2pix(pp, rp, lx, ly)        /* compute pixel pos. from image location */
  251. int  pp[2];
  252. register RESOLU  *rp;
  253. double  lx, ly;
  254. {
  255.     register int  x, y;
  256.  
  257.     x = lx * rp->xr;
  258.     y = ly * rp->yr;
  259.     if (rp->or & XDECR)
  260.         x = rp->xr-1 - x;
  261.     if (rp->or & YDECR)
  262.         y = rp->yr-1 - y;
  263.     if (rp->or & YMAJOR) {
  264.         pp[0] = x;
  265.         pp[1] = y;
  266.     } else {
  267.         pp[0] = y;
  268.         pp[1] = x;
  269.     }
  270. }
  271.  
  272.  
  273. int
  274. getviewopt(v, ac, av)            /* process view argument */
  275. register VIEW  *v;
  276. int  ac;
  277. register char  *av[];
  278. {
  279. #define check(c,l)    if ((av[0][c]&&av[0][c]!=' ') || \
  280.             badarg(ac-1,av+1,l)) return(-1)
  281.  
  282.     if (ac <= 0 || av[0][0] != '-' || av[0][1] != 'v')
  283.         return(-1);
  284.     switch (av[0][2]) {
  285.     case 't':            /* type */
  286.         if (!av[0][3] || av[0][3]==' ')
  287.             return(-1);
  288.         check(4,"");
  289.         v->type = av[0][3];
  290.         return(0);
  291.     case 'p':            /* point */
  292.         check(3,"fff");
  293.         v->vp[0] = atof(av[1]);
  294.         v->vp[1] = atof(av[2]);
  295.         v->vp[2] = atof(av[3]);
  296.         return(3);
  297.     case 'd':            /* direction */
  298.         check(3,"fff");
  299.         v->vdir[0] = atof(av[1]);
  300.         v->vdir[1] = atof(av[2]);
  301.         v->vdir[2] = atof(av[3]);
  302.         return(3);
  303.     case 'u':            /* up */
  304.         check(3,"fff");
  305.         v->vup[0] = atof(av[1]);
  306.         v->vup[1] = atof(av[2]);
  307.         v->vup[2] = atof(av[3]);
  308.         return(3);
  309.     case 'h':            /* horizontal size */
  310.         check(3,"f");
  311.         v->horiz = atof(av[1]);
  312.         return(1);
  313.     case 'v':            /* vertical size */
  314.         check(3,"f");
  315.         v->vert = atof(av[1]);
  316.         return(1);
  317.     case 's':            /* shift */
  318.         check(3,"f");
  319.         v->hoff = atof(av[1]);
  320.         return(1);
  321.     case 'l':            /* lift */
  322.         check(3,"f");
  323.         v->voff = atof(av[1]);
  324.         return(1);
  325.     default:
  326.         return(-1);
  327.     }
  328. #undef check
  329. }
  330.  
  331.  
  332. int
  333. sscanview(vp, s)            /* get view parameters from string */
  334. VIEW  *vp;
  335. register char  *s;
  336. {
  337.     int  ac;
  338.     char  *av[4];
  339.     int  na;
  340.     int  nvopts = 0;
  341.  
  342.     if (*s != '-')
  343.         s = sskip(s);
  344.     while (*s) {
  345.         ac = 0;
  346.         do {
  347.             av[ac++] = s;
  348.             while (*s && *s != ' ')
  349.                 s++;
  350.             while (*s == ' ')
  351.                 s++;
  352.         } while (*s && ac < 4);
  353.         if ((na = getviewopt(vp, ac, av)) >= 0) {
  354.             if (na+1 < ac)
  355.                 s = av[na+1];
  356.             nvopts++;
  357.         } else if (ac > 1)
  358.             s = av[1];
  359.     }
  360.     return(nvopts);
  361. }
  362.  
  363.  
  364. fprintview(vp, fp)            /* write out view parameters */
  365. register VIEW  *vp;
  366. FILE  *fp;
  367. {
  368.     fprintf(fp, " -vt%c", vp->type);
  369.     fprintf(fp, " -vp %.6g %.6g %.6g", vp->vp[0], vp->vp[1], vp->vp[2]);
  370.     fprintf(fp, " -vd %.6g %.6g %.6g", vp->vdir[0], vp->vdir[1], vp->vdir[2]);
  371.     fprintf(fp, " -vu %.6g %.6g %.6g", vp->vup[0], vp->vup[1], vp->vup[2]);
  372.     fprintf(fp, " -vh %.6g -vv %.6g", vp->horiz, vp->vert);
  373.     fprintf(fp, " -vs %.6g -vl %.6g", vp->hoff, vp->voff);
  374. }
  375.  
  376.  
  377. int
  378. isview(s)                /* is this a view string? */
  379. char  *s;
  380. {
  381.     static char  *altname[]={NULL,VIEWSTR,"rpict","rview","pinterp",NULL};
  382.     extern char  *progname;
  383.     register char  *cp;
  384.     register char  **an;
  385.                     /* add program name to list */
  386.     if (altname[0] == NULL) {
  387.         for (cp = progname; *cp; cp++)
  388.             ;
  389.         while (cp > progname && !ISDIRSEP(cp[-1]))
  390.             cp--;
  391.         altname[0] = cp;
  392.     }
  393.                     /* skip leading path */
  394.     cp = s;
  395.     while (*cp && *cp != ' ')
  396.         cp++;
  397.     while (cp > s && !ISDIRSEP(cp[-1]))
  398.         cp--;
  399.     for (an = altname; *an != NULL; an++)
  400.         if (!strncmp(*an, cp, strlen(*an)))
  401.             return(1);
  402.     return(0);
  403. }
  404.  
  405.  
  406. struct myview {
  407.     VIEW    *hv;
  408.     int    ok;
  409. };
  410.  
  411.  
  412. static
  413. gethview(s, v)                /* get view from header */
  414. char  *s;
  415. register struct myview  *v;
  416. {
  417.     if (isview(s) && sscanview(v->hv, s) > 0)
  418.         v->ok++;
  419. }
  420.  
  421.  
  422. int
  423. viewfile(fname, vp, rp)            /* get view from file */
  424. char  *fname;
  425. VIEW  *vp;
  426. RESOLU  *rp;
  427. {
  428.     struct myview    mvs;
  429.     FILE  *fp;
  430.  
  431.     if ((fp = fopen(fname, "r")) == NULL)
  432.         return(-1);
  433.  
  434.     mvs.hv = vp;
  435.     mvs.ok = 0;
  436.  
  437.     getheader(fp, gethview, &mvs);
  438.  
  439.     if (rp != NULL && !fgetsresolu(rp, fp))
  440.         mvs.ok = 0;
  441.  
  442.     fclose(fp);
  443.  
  444.     return(mvs.ok);
  445. }
  446.