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

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)replmarks.c 2.2 3/3/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  * Replace markers in Radiance scene description with objects or instances.
  9.  *
  10.  *    Created:    17 Feb 1991    Greg Ward
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <math.h>
  16.  
  17. #include "fvect.h"
  18.  
  19. #ifdef  M_PI
  20. #define  PI        M_PI
  21. #else
  22. #define  PI        3.14159265358979323846
  23. #endif
  24.  
  25. #define  FEQ(a,b)    ((a)-(b) <= 1e-7 && (b)-(a) <= 1e-7)
  26.  
  27. #define  MAXVERT    6    /* maximum number of vertices for markers */
  28. #define  MAXMARK    32    /* maximum number of markers */
  29.  
  30. typedef struct {
  31.     short    beg, end;        /* beginning and ending vertex */
  32.     float    len2;            /* length squared */
  33. }  EDGE;            /* a marker edge */
  34.  
  35. struct mrkr {
  36.     char    *modout;        /* output modifier */
  37.     double    mscale;            /* scale by this to get unit */
  38.     char    *modin;            /* input modifier indicating marker */
  39.     char    *objname;        /* output object file or octree */
  40.     int    doxform;        /* true if xform, false if instance */
  41. }  marker[MAXMARK];        /* array of markers */
  42. int    nmarkers = 0;        /* number of markers */
  43.  
  44. int    expand;            /* expand commands? */
  45.  
  46. char    *progname;
  47.  
  48.  
  49. main(argc, argv)
  50. int    argc;
  51. char    *argv[];
  52. {
  53.     FILE    *fp;
  54.     int    i, j;
  55.  
  56.     progname = argv[0];
  57.     i = 1;
  58.     while (i < argc && argv[i][0] == '-') {
  59.         do {
  60.             switch (argv[i][1]) {
  61.             case 'i':
  62.                 marker[nmarkers].doxform = 0;
  63.                 marker[nmarkers].objname = argv[++i];
  64.                 break;
  65.             case 'x':
  66.                 marker[nmarkers].doxform = 1;
  67.                 marker[nmarkers].objname = argv[++i];
  68.                 break;
  69.             case 'e':
  70.                 expand = 1;
  71.                 break;
  72.             case 'm':
  73.                 marker[nmarkers].modout = argv[++i];
  74.                 break;
  75.             case 's':
  76.                 marker[nmarkers].mscale = atof(argv[++i]);
  77.                 break;
  78.             default:
  79.                 goto userr;
  80.             }
  81.             if (++i >= argc)
  82.                 goto userr;
  83.         } while (argv[i][0] == '-');
  84.         if (marker[nmarkers].objname == NULL)
  85.             goto userr;
  86.         marker[nmarkers++].modin = argv[i++];
  87.         if (nmarkers >= MAXMARK)
  88.             break;
  89.         marker[nmarkers].mscale = marker[nmarkers-1].mscale;
  90.     }
  91.     if (nmarkers == 0)
  92.         goto userr;
  93.                     /* simple header */
  94.     putchar('#');
  95.     for (j = 0; j < i; j++) {
  96.         putchar(' ');
  97.         fputs(argv[j], stdout);
  98.     }
  99.     putchar('\n');
  100.     if (i == argc)
  101.         convert("<stdin>", stdin);
  102.     else
  103.         for ( ; i < argc; i++) {
  104.             if ((fp = fopen(argv[i], "r")) == NULL) {
  105.                 perror(argv[i]);
  106.                 exit(1);
  107.             }
  108.             convert(argv[i], fp);
  109.             fclose(fp);
  110.         }
  111.     exit(0);
  112. userr:
  113.     fprintf(stderr,
  114. "Usage: %s [-e][-s size][-m modout] {-x objfile|-i octree} modname .. [file ..]\n",
  115.         progname);
  116.     exit(1);
  117. }
  118.  
  119.  
  120. convert(name, fin)        /* replace marks in a stream */
  121. char    *name;
  122. register FILE    *fin;
  123. {
  124.     register int    c;
  125.  
  126.     while ((c = getc(fin)) != EOF) {
  127.         if (isspace(c))                /* blank */
  128.             continue;
  129.         if (c == '#') {                /* comment */
  130.             putchar(c);
  131.             do {
  132.                 if ((c = getc(fin)) == EOF)
  133.                     return;
  134.                 putchar(c);
  135.             } while (c != '\n');
  136.         } else if (c == '!') {            /* command */
  137.             ungetc(c, fin);
  138.             cvcomm(name, fin);
  139.         } else {                /* object */
  140.             ungetc(c, fin);
  141.             cvobject(name, fin);
  142.         }
  143.     }
  144. }
  145.  
  146.  
  147. cvcomm(fname, fin)        /* convert a command */
  148. char    *fname;
  149. FILE    *fin;
  150. {
  151.     FILE    *pin, *popen();
  152.     char    buf[512], *fgetline();
  153.  
  154.     fgetline(buf, sizeof(buf), fin);
  155.     if (expand) {
  156.         if ((pin = popen(buf+1, "r")) == NULL) {
  157.             fprintf(stderr,
  158.             "%s: (%s): cannot execute \"%s\"\n",
  159.                     progname, fname, buf);
  160.             exit(1);
  161.         }
  162.         convert(buf, pin);
  163.         pclose(pin);
  164.     } else
  165.         printf("\n%s\n", buf);
  166. }
  167.  
  168.  
  169. cvobject(fname, fin)        /* convert an object */
  170. char    *fname;
  171. FILE    *fin;
  172. {
  173.     char    buf[128], typ[16], nam[128];
  174.     int    i, n;
  175.     register int    j;
  176.  
  177.     if (fscanf(fin, "%s %s %s", buf, typ, nam) != 3)
  178.         goto readerr;
  179.     if (!strcmp(typ, "polygon"))
  180.         for (j = 0; j < nmarkers; j++)
  181.             if (!strcmp(buf, marker[j].modin)) {
  182.                 replace(fname, &marker[j], nam, fin);
  183.                 return;
  184.             }
  185.     printf("\n%s %s %s\n", buf, typ, nam);
  186.     if (!strcmp(typ, "alias")) {        /* alias special case */
  187.         if (fscanf(fin, "%s", buf) != 1)
  188.             goto readerr;
  189.         printf("\t%s\n", buf);
  190.         return;
  191.     }
  192.     for (i = 0; i < 3; i++) {        /* pass along arguments */
  193.         if (fscanf(fin, "%d", &n) != 1)
  194.             goto readerr;
  195.         printf("%d", n);
  196.         for (j = 0; j < n; j++) {
  197.             if (fscanf(fin, "%s", buf) != 1)
  198.                 goto readerr;
  199.             if (j%3 == 0)
  200.                 putchar('\n');
  201.             printf("\t%s", buf);
  202.         }
  203.         putchar('\n');
  204.     }
  205.     return;
  206. readerr:
  207.     fprintf(stderr, "%s: (%s): read error for %s \"%s\"\n",
  208.             progname, fname, typ, nam);
  209. }
  210.  
  211.  
  212. replace(fname, m, mark, fin)        /* replace marker */
  213. char    *fname;
  214. register struct mrkr    *m;
  215. char    *mark;
  216. FILE    *fin;
  217. {
  218.     int    n;
  219.     char    buf[256];
  220.  
  221.     if (m->doxform) {
  222.         sprintf(buf, "xform -e -n %s", mark);
  223.         if (m->modout != NULL)
  224.             sprintf(buf+strlen(buf), " -m %s", m->modout);
  225.         if (buildxf(buf+strlen(buf), m->mscale, fin) < 0)
  226.             goto badxf;
  227.         sprintf(buf+strlen(buf), " %s", m->objname);
  228.         if (expand) {
  229.             fflush(stdout);
  230.             system(buf);
  231.         } else
  232.             printf("\n!%s\n", buf);
  233.     } else {
  234.         if ((n = buildxf(buf, m->mscale, fin)) < 0)
  235.             goto badxf;
  236.         printf("\n%s instance %s\n",
  237.                 m->modout==NULL?"void":m->modout, mark);
  238.         printf("%d %s%s\n0\n0\n", n+1, m->objname, buf);
  239.     }
  240.     return;
  241. badxf:
  242.     fprintf(stderr, "%s: (%s): bad arguments for marker \"%s\"\n",
  243.             progname, fname, mark);
  244.     exit(1);
  245. }
  246.  
  247.  
  248. edgecmp(e1, e2)            /* compare two edges, descending order */
  249. EDGE    *e1, *e2;
  250. {
  251.     if (e1->len2 > e2->len2)
  252.         return(-1);
  253.     if (e1->len2 < e2->len2)
  254.         return(1);
  255.     return(0);
  256. }
  257.  
  258.  
  259. int
  260. buildxf(xf, markscale, fin)        /* build transform for marker */
  261. char    *xf;
  262. double    markscale;
  263. FILE    *fin;
  264. {
  265.     static FVECT    vlist[MAXVERT];
  266.     static EDGE    elist[MAXVERT];
  267.     FVECT    xvec, yvec, zvec;
  268.     double    xlen;
  269.     int    n;
  270.     register int    i;
  271.     /*
  272.      * Read and sort vectors:  longest is hypotenuse,
  273.      *    second longest is x' axis,
  274.      *    third longest is y' axis (approximate),
  275.      *    other vectors are ignored.
  276.      * It is an error if the x' and y' axes do
  277.      *    not share a common vertex (their origin).
  278.      */
  279.     if (fscanf(fin, "%*d %*d %d", &n) != 1)
  280.         return(-1);
  281.     if (n%3 != 0)
  282.         return(-1);
  283.     n /= 3;
  284.     if (n < 3 || n > MAXVERT)
  285.         return(-1);
  286.                     /* sort edges in descending order */
  287.     for (i = 0; i < n; i++) {
  288.         if (fscanf(fin, "%lf %lf %lf", &vlist[i][0],
  289.                 &vlist[i][1], &vlist[i][2]) != 3)
  290.             return(-1);
  291.         if (i) {
  292.             elist[i].beg = i-1;
  293.             elist[i].end = i;
  294.             elist[i].len2 = dist2(vlist[i-1],vlist[i]);
  295.         }
  296.     }
  297.     elist[0].beg = n-1;
  298.     elist[0].end = 0;
  299.     elist[0].len2 = dist2(vlist[n-1],vlist[0]);
  300.     qsort(elist, n, sizeof(EDGE), edgecmp);
  301.                     /* find x' and y' */
  302.     if (elist[1].end == elist[2].beg || elist[1].end == elist[2].end) {
  303.         i = elist[1].beg;
  304.         elist[1].beg = elist[1].end;
  305.         elist[1].end = i;
  306.     }
  307.     if (elist[2].end == elist[1].beg) {
  308.         i = elist[2].beg;
  309.         elist[2].beg = elist[2].end;
  310.         elist[2].end = i;
  311.     }
  312.     if (elist[1].beg != elist[2].beg)
  313.         return(-1);        /* x' and y' not connected! */
  314.     for (i = 0; i < 3; i++) {
  315.         xvec[i] = vlist[elist[1].end][i] - vlist[elist[1].beg][i];
  316.         yvec[i] = vlist[elist[2].end][i] - vlist[elist[2].beg][i];
  317.     }
  318.     if ((xlen = normalize(xvec)) == 0.0)
  319.         return(-1);
  320.     fcross(zvec, xvec, yvec);
  321.     if (normalize(zvec) == 0.0)
  322.         return(-1);
  323.     fcross(yvec, zvec, xvec);
  324.     n = 0;                /* start transformation... */
  325.     if (markscale > 0.0) {        /* add scale factor */
  326.         sprintf(xf, " -s %f", xlen*markscale);
  327.         n += 2;
  328.         xf += strlen(xf);
  329.     }
  330.                     /* add rotation */
  331.     n += addrot(xf, xvec, yvec, zvec);
  332.     xf += strlen(xf);
  333.                     /* add translation */
  334.     n += 4;
  335.     sprintf(xf, " -t %f %f %f", vlist[elist[1].beg][0],
  336.             vlist[elist[1].beg][1], vlist[elist[1].beg][2]);
  337.     return(n);            /* all done */
  338. }
  339.  
  340.  
  341. addrot(xf, xp, yp, zp)        /* compute rotation (x,y,z) => (xp,yp,zp) */
  342. char    *xf;
  343. FVECT    xp, yp, zp;
  344. {
  345.     int    n;
  346.     double    theta;
  347.  
  348.     n = 0;
  349.     theta = atan2(yp[2], zp[2]);
  350.     if (!FEQ(theta,0.0)) {
  351.         sprintf(xf, " -rx %f", theta*(180./PI));
  352.         xf += strlen(xf);
  353.         n += 2;
  354.     }
  355.     theta = asin(-xp[2]);
  356.     if (!FEQ(theta,0.0)) {
  357.         sprintf(xf, " -ry %f", theta*(180./PI));
  358.         xf += strlen(xf);
  359.         n += 2;
  360.     }
  361.     theta = atan2(xp[1], xp[0]);
  362.     if (!FEQ(theta,0.0)) {
  363.         sprintf(xf, " -rz %f", theta*(180./PI));
  364.         /* xf += strlen(xf); */
  365.         n += 2;
  366.     }
  367.     return(n);
  368. }
  369.