home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / devel5 / plgx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-14  |  20.5 KB  |  857 lines

  1. /*  PLG file processing package
  2. /*  by Dave Stampe 13/5/93
  3. /*
  4. /*  PLGX.EXE
  5. /*  type PLG /? for instructions
  6. /*
  7. /*  center, size, scale, rotate, translate
  8. /*  merge duplicate vertices (IRIT and NorthCad)
  9. /*  renumber vertex comments in file
  10. /*  attempts to preserve original comments in new file
  11. /*
  12. */
  13.  
  14.  
  15.  
  16. #include <stdio.h>
  17. #include <math.h>
  18. #include <dos.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22.  
  23. #define MAXVERTS 2000
  24. #define MAXPOLYS 2000
  25.                           /* vertex, poly storage */
  26. typedef struct { float x, y, z;         } VERT;
  27. typedef struct { char color[20];
  28.          unsigned nverts;
  29.          unsigned vtx[20];       } POLY;
  30.  
  31. #define DEL 1e10    /* flags deleted vertex */
  32.  
  33. VERT v[MAXVERTS];       /* array of vertices */
  34. int vmap[MAXVERTS];     /* maps vertices for combination */
  35. POLY *p[MAXPOLYS];      /* pointers to polygons */
  36. int nlines;             /* total lines in PLG file */
  37. int nameline;           /* original file line numbers of PLG */
  38. int vtxline;            /* sections: so comments will be in  */
  39. int polyline;           /* the right places */
  40.  
  41. char fin[80] = "";      /* in, out filennames */
  42. char fout[80] = "";
  43.  
  44. FILE *in, *out;
  45.  
  46. char plgname[100];      /* PLG object name */
  47.  
  48. int hasverts = 0;    /* when reading the #MULTI tag is valid */
  49.  
  50. int nverts, npolys;     /* old, new vertex counts to/from processing */
  51. int overts, opolys;
  52.  
  53. char line[300];        /* line from PLG file */
  54.  
  55. float sx = 1.0, sy = 1.0, sz = 1.0; /* scale   */
  56. float tx = 0.0, ty = 0.0, tz = 0.0; /* xlat    */
  57. float rx = 0.0, ry = 0.0, rz = 0.0; /* rotate  */
  58. float bx = 0.0, by = 0.0, bz = 0.0; /* box fit */
  59. float clim = -1.0;                  /* combine delta */
  60.  
  61. int centerx = 0;
  62. int centery = 0;
  63. int centerz = 0;    /* action flags */
  64. int groundx = 0;
  65. int groundy = 0;
  66. int groundz = 0;
  67. int gcenter = 0;
  68. int info = 0;
  69. int multi = 0;
  70. int renverts = 0;
  71. int reverse = 0;
  72. int whole = 0;
  73. int integrated = 0;
  74. int rrecolor = 0;
  75. float laxis = 0;
  76.  
  77. char newcolor[20] = "";
  78.  
  79. float maxx, maxy, maxz;        /* box size/center statistics */
  80. float minx, miny, minz;
  81. float sumx, sumy, sumz;
  82.  
  83. long plgpos;
  84. int abssumverts;
  85.  
  86. read_plg()        /* reads data from PLG file, checks */
  87. {
  88.  int i,j,k;
  89.  char *c;
  90.  float x, y, z;
  91.  POLY p1;
  92.  POLY *pp;
  93.  
  94.  plgpos = ftell(in);        /* record for file rewind */
  95.  
  96.  if(!integrated)
  97.   {
  98.    maxx = maxy = maxz = -1e9;    /* initialize for object-by-object data */
  99.    minx = miny = minz =  1e9;
  100.    sumx = sumy = sumz =  0.0;
  101.    abssumverts = 0;
  102.   }
  103.  nlines = 0;
  104.  nameline = vtxline = polyline = -1;
  105.  
  106.  while(!feof(in))        /* read till name */
  107.   {
  108.    nameline = nlines++;
  109.    fgets(line, 300, in);
  110.    c=strchr(line,'#');
  111.    if(c)
  112.     {
  113.      if(strstr(c,"#MULTI")) multi++;    /* detect multi-res type */
  114.      *c = 0;
  115.     }
  116.  
  117.    if(sscanf(line, "%s %d %d", plgname, &nverts, &npolys)==3) break;
  118.   }
  119.  if(feof(in))
  120.   {
  121.    nameline = -1;    /* EOF before new object */
  122.    return 0;
  123.   }
  124.  
  125.  overts = nverts;        /* process vertex count */
  126.  opolys = npolys;
  127.  if(integrated>=0) abssumverts += nverts;
  128.  
  129.  for(i=0;i<nverts;i++)      /* read vertices */
  130.   {
  131.    while(1)
  132.     {
  133.      if(feof(in))
  134.       {
  135.        fprintf(stderr, "Early EOF in input file\n");
  136.        fcloseall();
  137.        exit(-1);
  138.       }
  139.  
  140.      fgets(line, 300, in);    /* delete comments */
  141.      nlines++;
  142.      c=strchr(line,'#');
  143.      if(c)
  144.       {
  145.        *c = 0;
  146.       }
  147.  
  148.      j=sscanf(line, "%f %f %f", &x, &y, &z);    /* get vertex */
  149.      if(j==0 || j==EOF) continue;
  150.      if(j<3)
  151.       {
  152.        fprintf(stderr, "Syntax error on line %d of input file\n", nlines);
  153.        fcloseall();
  154.        exit(-1);
  155.       }
  156.      if(j==3) break;
  157.     }
  158.    if(vtxline<0) vtxline = nlines;
  159.    v[i].x = x;  v[i].y = y; v[i].z = z;
  160.    sumx += x;  sumy += y;  sumz += z;
  161.    if(x>maxx) maxx = x;            /* box statistics */
  162.    if(y>maxy) maxy = y;
  163.    if(z>maxz) maxz = z;
  164.    if(x<minx) minx = x;
  165.    if(y<miny) miny = y;
  166.    if(z<minz) minz = z;
  167.   }
  168.  
  169.  for(i=0;i<npolys;i++)        /* read polygons */
  170.   {
  171.    while(1)
  172.     {
  173.      if(feof(in))
  174.       {
  175.        fprintf(stderr, "Early EOF in input file\n");
  176.        fcloseall();
  177.        exit(-1);
  178.       }
  179.  
  180.      fgets(line, 300, in);
  181.      nlines++;
  182.      c=strchr(line,'#');    /* skip comments */
  183.      if(c)
  184.       {
  185.        *c = 0;
  186.       }
  187.  
  188.      c = strtok(line," \t");
  189.      if(c==NULL || c[0]==0 || c[0]=='\n') continue;
  190.      else break;
  191.     }
  192.  
  193.    if(vtxline<0) vtxline = nlines;
  194.    strcpy(p1.color, line);        /* color as string */
  195.    c = strtok(NULL," \t");
  196.    p1.nverts = atoi(c);
  197.    if(p1.nverts<1)
  198.     {
  199.      fprintf(stderr, "Syntax error on line %d of input file\n", nlines);
  200.      fcloseall();
  201.      exit(-1);
  202.     }
  203.    if(p1.nverts>20)    /* max. 20 vertices for REND386 */
  204.     {
  205.      fprintf(stderr, "Too many vertices in poly on line %d of input file\n", nlines);
  206.      fcloseall();
  207.      exit(-1);
  208.     }
  209.    for (j = 0; j < p1.nverts; ++j)    /* read vertex indices */
  210.     {
  211.      c = strtok(NULL," \t");
  212.      k = atoi(c);
  213.      if(k<0 || k>nverts)
  214.       {
  215.        fprintf(stderr, "Bad vertex number on line %d of input file\n", nlines);
  216.        fcloseall();
  217.        exit(-1);
  218.       }
  219.      p1.vtx[j] = k;
  220.      pp = (POLY *) calloc(sizeof(POLY), 1);
  221.      if(!pp)
  222.       {
  223.        fprintf(stderr, "Out of memory at line %d of input file\n", nlines);
  224.        fcloseall();
  225.        exit(-1);
  226.       }
  227.      memcpy(pp, &p1, sizeof(POLY));    /* store new poly */
  228.      p[i] = pp;
  229.     }
  230.   }
  231.  return 1;
  232. }
  233.  
  234.  
  235. char *trcomments(char * line)    /* extract comments from line */
  236. {
  237.  char *c;        /* c == line if nothing but comments or blank */
  238.  
  239.  c=strchr(line,'#');
  240.  if (!c) c = line+strlen(line);
  241.  while(c>line && isspace(*(c-1))) c--;    /* include leading space */
  242.  return c;
  243. }
  244.  
  245.  
  246. write_plg()     /* writes PLG file, tries to preserve comments */
  247. {
  248.  int i,j,k, ln;
  249.  int vtxn, plyn;
  250.  char *c;
  251.  char lbuff[300];
  252.  
  253.  fseek(in, plgpos, SEEK_SET);    /* rewind to get PLG comments */
  254.  
  255.  for(ln=0;ln<nameline;ln++)    /* copy leading comments */
  256.   {
  257.    fgets(line, 300, in);
  258.    fputs(trcomments(line), out);
  259.   }
  260.  
  261.  k = sprintf(lbuff,"%s %d %d",     /* name line with comments */
  262.        plgname, nverts, npolys);
  263.  fgets(line, 300, in);
  264.  ln++;
  265.  c=strchr(line,'#');
  266.  strcpy(lbuff+k, trcomments(line));
  267.  fputs(lbuff, out);
  268.  
  269.  for(;ln<vtxline-1;ln++)    /* lines to start of vertices */
  270.   {
  271.    fgets(line, 300, in);
  272.    fputs(trcomments(line), out);
  273.   }
  274.  
  275.  vtxn = 0;
  276.  for(i=0;i<overts;i++)     /* lines containing vertices */
  277.   {
  278.    while(1)
  279.     {
  280.      fgets(line, 300, in);
  281.      ln++;
  282.      if(trcomments(line) == line)
  283.       {
  284.        fputs(trcomments(line), out);
  285.        continue;    /* blank/comment line */
  286.       }
  287.      else break;
  288.     }
  289.    if(v[i].x == DEL)    /* maark vertices deleted by combining */
  290.     {
  291.      if(!renverts) k = 0;
  292.      else k = sprintf(lbuff, "# DELETED\t ");
  293.     }
  294.    else
  295.     {
  296.      if(maxx-minx>1 || maxy-miny>1 || maxz-minz>1)
  297.       {
  298.        if(fabs(v[i].x)<0.01) v[i].x = 0.0;   /* delete tiny numbers */
  299.        if(fabs(v[i].y)<0.01) v[i].y = 0.0;   /* for better formatting */
  300.        if(fabs(v[i].z)<0.01) v[i].z = 0.0;
  301.       }
  302.      if(!renverts)
  303.        k = sprintf(lbuff,"% 6g % 6g % 6g ", v[i].x, v[i].y, v[i].z);
  304.      else
  305.        k = sprintf(lbuff,"% 6g % 6g % 6g\t #VTX %d\t ", v[i].x, v[i].y, v[i].z, vtxn);
  306.  
  307.      if(vtxn != i)    /* renumber poly vertices too */
  308.       {                 /* after recombination */
  309.        int j,k;
  310.        for(j=0;j<opolys;j++)
  311.     {
  312.      if(p[j]==NULL) continue;
  313.      for(k=0;k<p[j]->nverts;k++)
  314.        if(p[j]->vtx[k]==i) p[j]->vtx[k] = vtxn;
  315.     }
  316.       }
  317.      vtxn++;
  318.     }
  319.    strcpy(lbuff+k, trcomments(line));    /* add comments to vertex line */
  320.    fputs(lbuff, out);
  321.   }
  322.  
  323.  for(;ln<polyline-1;ln++)    /* lines to start of polyss */
  324.   {
  325.    fgets(line, 300, in);
  326.    fputs(trcomments(line), out);
  327.   }
  328.  
  329.  for(i=0;i<opolys;i++)     /* lines containing polys */
  330.   {
  331.    while(1)
  332.     {
  333.      fgets(line, 300, in);
  334.      ln++;
  335.      if(trcomments(line) == line)
  336.       {
  337.        fputs(trcomments(line), out);
  338.        continue;    /* blank/comment line */
  339.       }
  340.      else break;
  341.     }
  342.    if(p[i] == NULL)
  343.     {
  344.      k = sprintf(lbuff, "# DELETED ");    /* mark deleted polys */
  345.     }
  346.    else
  347.     {
  348.      k = sprintf(lbuff,"%s % 3d", p[i]->color, p[i]->nverts);
  349.      for(j=0;j<p[i]->nverts;j++)
  350.        k += sprintf(lbuff+k, "% 3d", p[i]->vtx[j]);
  351.      free(p[i]);
  352.     }
  353.    strcpy(lbuff+k, trcomments(line));
  354.    fputs(lbuff, out);
  355.   }
  356. }
  357.          /* ascii to color number for information */
  358.  
  359. unsigned convert_color(char *s, char **ptr)
  360. {
  361.  int hue, value;
  362.  if (isdigit(*s)) return (unsigned) strtoul(s, ptr, 0);
  363.  if (ptr) for (*ptr = s; isalnum(**ptr) || **ptr == '_'; ++*ptr);
  364.  if (!strnicmp(s, "shaded", 6))
  365.   {
  366.    sscanf(s, "shaded_%d_%d", &hue, &value);
  367.    return 0x1000 | ((hue & 0x0F) << 8) | (value & 0xFF);
  368.   }
  369.  else if (!strnicmp(s, "metal", 5))
  370.   {
  371.    sscanf(s, "metal_%d_%d", &hue, &value);
  372.    return 0x2000 | ((hue & 0x0F) << 8) | ((value & 0x1F) << 3);
  373.   }
  374.  else if (!strnicmp(s, "glass", 5))
  375.   {
  376.    sscanf(s, "glass_%d_%d", &hue, &value);
  377.    return 0x3000 | ((hue & 0x0F) << 8) | ((value & 0x1F) << 3);
  378.   }
  379.  return 0;
  380. }
  381.  
  382.  
  383. print_info()    /* info on poly object */
  384. {
  385.  int i;
  386.  unsigned c;
  387.  int hasabs = 0;
  388.  int hasstd = 0;
  389.  int hasmap = 0;
  390.  
  391.  if(multi) printf("PLG file type: MULTI resolution\n");
  392.  printf("PLG file name: \t%s\n", fin);
  393.  printf("PLG object name: \t%s\n", plgname);
  394.  printf("Vertices: \t%d\n", nverts);
  395.  printf("Polygons: \t%d\n", npolys);
  396.  
  397.  for(i=0;i<npolys;i++)
  398.   {
  399.    c = convert_color(p[i]->color, NULL);
  400.    if(c & 0x8000)
  401.     {
  402.      if((c&0x0FFF)>hasmap) hasmap = c & 0x0FFF;
  403.     }
  404.    else if ((c&0xFF00)==0) hasabs++;
  405.    else hasstd++;
  406.   }
  407.  
  408.  printf("Color types: \n");
  409.  if(hasabs) printf("\tDirect palette mapped colors\n");
  410.  if(hasstd) printf("\tCosine lit, glass, metal types\n");
  411.  if(hasmap) printf("\tSurface mapped, 1 to %d\n", hasmap);
  412.  
  413.  printf("Bounding box: (%g, %g, %g) - (%g, %g, %g)\n",
  414.    minx, miny, minz, maxx, maxy, maxz);
  415.  printf("Centered at: (%g, %g, %g)\n", (maxx+minx)/2.0,
  416.               (maxy+miny)/2.0,(maxz+minz)/2.0  );
  417.  printf("Size: (%g, %g, %g)\n", maxx-minx, maxy-miny,maxz-minz );
  418.  printf("\n");
  419. }
  420.  
  421.  
  422. reverse_order()   /* reverse order of all poly vertex lists */
  423. {
  424.  int i, j, k, n;
  425.  
  426.  for(i=0;i<npolys;i++)
  427.   {
  428.    n =p[i]->nverts;
  429.    for(j=0;j<n/2;j++)
  430.     {
  431.      k = p[i]->vtx[j];
  432.      k = p[i]->vtx[j] = p[i]->vtx[n-j-1];
  433.      p[i]->vtx[n-j-1] = k;
  434.     }
  435.   }
  436. }
  437.  
  438.  
  439. mmult(float A, float B, float C,    /* matrix to vertex apply */
  440.       float D, float E, float F,
  441.       float G, float H, float I,
  442.       float *x, float *y, float *z)
  443. {
  444.  float xx = *x, yy= *y, zz = *z;
  445.  
  446.  *x = A*xx + B*yy + C*zz;
  447.  *y = D*xx + E*yy + F*zz;
  448.  *z = G*xx + H*yy + I*zz;
  449. }
  450.  
  451.  
  452. char rndcolor[] = "0x10FF";
  453.  
  454. process_plg()        /* pocess all polys in object */
  455. {
  456.  int i, j, k;
  457.  
  458.  float ox, oy, oz;
  459.  float snx, csx, sny, csy, snz, csz;
  460.  float cx, cy, cz;
  461.  
  462.  if (reverse) reverse_order();    /* reverse visibility */
  463.  
  464.  if(gcenter)    /* center of gravity */
  465.   {
  466.    cx = sumx/abssumverts;
  467.    cy = sumy/abssumverts;
  468.    cz = sumz/abssumverts;
  469.   }
  470.  else
  471.   {
  472.    cx = (maxx+minx)/2.0;    /* box center */
  473.    cy = (maxy+miny)/2.0;
  474.    cz = (maxz+minz)/2.0;
  475.   }
  476.  
  477.  if(centerx || centery || centerz ||
  478.     groundx || groundy || groundz    )   /* precenter or shift vertices */
  479.    for(i=0;i<nverts;i++)
  480.     {
  481.      if(centerx) v[i].x -= cx;
  482.      if(centery) v[i].y -= cy;
  483.      if(centerz) v[i].z -= cz;
  484.      if(groundx) v[i].x -= minx;
  485.      if(groundy) v[i].y -= miny;
  486.      if(groundz) v[i].z -= minz;
  487.     }
  488.  
  489.  if(rx+ry+rz > 0.0001)        /* rotation */
  490.   {
  491.    float x,y,z;
  492.  
  493.    snx = sin(rx/57.296);    /* precompute for speed */
  494.    csx = cos(rx/57.296);
  495.    sny = sin(ry/57.296);
  496.    csy = cos(ry/57.296);
  497.    snz = sin(rz/57.296);
  498.    csz = cos(rz/57.296);
  499.  
  500.    for(i=0;i<nverts;i++)
  501.     {
  502.      x = v[i].x;
  503.      y = v[i].y;               /* rotate in Y, X, Z order */
  504.      z = v[i].z;
  505.      mmult(csy, 0, sny, 0, 1, 0, -sny, 0, csy, &x, &y, &z);
  506.      mmult(1, 0, 0, 0, csx, -snx, 0, snx, csx, &x, &y, &z);
  507.      mmult(csz, -snz, 0, snz, csz, 0, 0, 0, 1, &x, &y, &z);
  508.      v[i].x = x;
  509.      v[i].y = y;
  510.      v[i].z = z;
  511.     }
  512.   }
  513.  
  514.  if(laxis)    /* longest-axis fit scaling */
  515.   {
  516.    float l = 0;
  517.    sx = sy =sz = 1.0;
  518.  
  519.    if(fabs(maxx-minx)>l)
  520.     {
  521.      l = maxx-minx;
  522.      if(maxx-minx>0.0001) sx = laxis/(maxx-minx); else sx = 1.0;
  523.      sy = sz = sx;
  524.     }
  525.    if(fabs(maxy-miny)>l)
  526.     {
  527.      l = maxy-miny;
  528.      if(maxy-miny>0.0001) sy = laxis/(maxy-miny); else sy = 1.0;
  529.      sx = sz = sy;
  530.     }
  531.    if(fabs(maxz-minz)>l)
  532.     {
  533.      if(maxz-minz>0.0001) sz = laxis/(maxz-minz); else sz = 1.0;
  534.      sx = sy = sz;
  535.     }
  536.   }
  537.  
  538.  if(bx)     /* compute box scaling */
  539.   {
  540.    if(maxx-minx>0.0001) sx = bx/(maxx-minx); else sx = 1.0;
  541.    if(maxy-miny>0.0001) sy = by/(maxy-miny); else sy = 1.0;
  542.    if(maxz-minz>0.0001) sz = bz/(maxz-minz); else sz = 1.0;
  543.   }
  544.  
  545.  if(sx!=1.0 || sy!=1.0 || sz!=1.0)   /* scale object */
  546.    for(i=0;i<nverts;i++)
  547.     {
  548.      v[i].x *= sx;
  549.      v[i].y *= sy;
  550.      v[i].z *= sz;
  551.     }
  552.  
  553.  if(tx || ty || tz)   /* translate object */
  554.    for(i=0;i<nverts;i++)
  555.     {
  556.      v[i].x += tx;
  557.      v[i].y += ty;
  558.      v[i].z += tz;
  559.     }
  560.  
  561.  if(whole)   /* integerize object */
  562.    for(i=0;i<nverts;i++)
  563.     {
  564.      v[i].x = floor(v[i].x);
  565.      v[i].y = floor(v[i].y);
  566.      v[i].z = floor(v[i].z);
  567.     }
  568.  
  569.  if(clim>0.0)               /* delete duplicte vertices */
  570.   {
  571.    int nvtx = nverts;
  572.    float x,y,z;
  573.  
  574.    for(i=0;i<nverts;i++) vmap[i] = -1;
  575.  
  576.    for(i=0;i<nverts;i++)
  577.     {
  578.      if(v[i].x == DEL) continue;
  579.      x = v[i].x;
  580.      y = v[i].y;
  581.      z = v[i].z;
  582.  
  583.      for(j=i+1;j<nverts;j++)   /* duplicate test */
  584.       {
  585.        if ( v[j].x == DEL) continue;
  586.        if ( fabs(x-v[j].x)<clim &&
  587.         fabs(y-v[j].y)<clim &&
  588.         fabs(z-v[j].z)<clim   )
  589.          {
  590.           v[j].x = DEL;
  591.           vmap[j] = i;
  592.           nvtx--;
  593.          }
  594.       }
  595.     }
  596.  
  597.    fprintf(stderr," %d duplicate vetrices found: deleted!\n", nverts-nvtx);
  598.    nverts = nvtx;
  599.  
  600.    if(nverts != overts)
  601.      for(i=0;i<npolys;i++)    /* update polygons */
  602.       {
  603.        if(p[i]==NULL) continue;
  604.        for(j=0;j<p[i]->nverts;j++)
  605.      if((k=vmap[p[i]->vtx[j]])>=0) p[i]->vtx[j] = k;
  606.       }
  607.   }
  608.  
  609.  
  610.  
  611.  if(newcolor[0])
  612.   for(i=0;i<npolys;i++)    /* update polygon colors */
  613.    {
  614.     if(p[i]==NULL) continue;
  615.     strcpy(p[i]->color, newcolor);
  616.    }
  617.  
  618.  if(rrecolor)
  619.   {
  620.    for(i=0;i<npolys;i++)    /* update polygon colors randomly */
  621.     {
  622.      if(p[i]==NULL) continue;
  623.      rndcolor[3]++;
  624.      if(rndcolor[3]>'F') rndcolor[3] = '1';
  625.      if(rndcolor[3]>'9' && rndcolor[3]<'A') rndcolor[3] = 'A';
  626.      strcpy(p[i]->color, rndcolor);
  627.     }
  628.   }
  629. }
  630.  
  631.  
  632. syntax()
  633. {
  634.  fprintf(stderr,"PLGX.EXE PLG file processor (c) 1993 by Dave STampe\n");
  635.  fprintf(stderr,"USE: PLGX <infile> <outfile> <commands>\n");
  636.  fprintf(stderr,"Commands: <angle brackets> enclose a numeric argument\n");
  637.  fprintf(stderr,"\n");
  638.  fprintf(stderr," /I information on objects\n");
  639.  fprintf(stderr," /?  this help screen\n");
  640.  fprintf(stderr," /C or /CXYZ center object in x,y,z overall\n");
  641.  fprintf(stderr," /G or /GXYZ ground (bottom y default) or other axis\n");
  642.  fprintf(stderr," /Z  use center of gravity instead of box center\n");
  643.  fprintf(stderr," /V or /V <delta> combines duplicate vertices (IRIT, NorthCad, etc)\n");
  644.  fprintf(stderr," /N  renumber vertices in comments (use with /V or new files)\n");
  645.  fprintf(stderr," /W  integer (whole) numbers only in output\n");
  646.  fprintf(stderr," /T <tx,ty,tz> translate PLG objects\n");
  647.  fprintf(stderr," /R  <rx,ry,rz> left-handed, degrees: rotate PLG objects about (0,0,0)\n");
  648.  fprintf(stderr," /S  <scale> or /S <sx,sy,sz> scale PLG\n");
  649.  fprintf(stderr," /B  <size> or /B <sx,sy,sz> scale PLG to given size bounding box\n");
  650.  fprintf(stderr," /L  or /L <size> sets ize of longest axis, default 1000\n");
  651.  fprintf(stderr," /D  default size box, equivalent to /B 1000\n");
  652.  fprintf(stderr," /P <color> repaints all polys in given color\n");
  653.  fprintf(stderr," /Q  repaints polys to random colors for debugging\n");
  654.  fprintf(stderr," /F reverse vertex order of all polygons\n");
  655.  fprintf(stderr," /O  object in file to process\n");
  656.  fprintf(stderr," /Y  all objects in file are considered one for /B, /D, /C, /G, /I\n");
  657. }
  658.  
  659.  
  660. int add_extension(char *fname, char *ext)
  661. {
  662.  int i,j;
  663.  
  664.  if(fname[0] == 0) return(-1);         /* error: no string */
  665.  for(i=0;i<70;i++)
  666.   {
  667.    if(fname[i] == '.') return(1);    /* already has valid extension */
  668.    if(fname[i] == 0)
  669.     {
  670.      fname[i] = '.';                 /* add default extension */
  671.      fname[i+1] = ext[0];
  672.      fname[i+2] = ext[1];
  673.      fname[i+3] = ext[2];
  674.      fname[i+4] = 0;
  675.      return(0);
  676.     }
  677.   }
  678.  return(-1);            /* error: string too long */
  679. }
  680.  
  681.  
  682. int obj = 0;
  683.  
  684. void main(int argc, char *argv[])
  685. {
  686.  int i,c;
  687.  
  688.  if(argc<2)
  689.   {
  690.    syntax();
  691.    exit(-1);
  692.   }
  693.  
  694.  for (i = 1; i < argc; ++i)
  695.   {
  696.    if (argv[i][0] == '/' || argv[i][0] == '-')
  697.     {
  698.      switch(toupper(argv[i][1]))
  699.       {
  700.        case 'C':/* center overall */
  701.         if(!argv[i][2]) centerx = centery = centerz = 1;
  702.         else
  703.          {
  704.           centerx = strchr(argv[i]+2,'x') ? 1 : 0;
  705.           centery = strchr(argv[i]+2,'y') ? 1 : 0;
  706.           centerz = strchr(argv[i]+2,'z') ? 1 : 0;
  707.          }
  708.         break;
  709.        case 'G':/* ground  */
  710.         if(!argv[i][2]) groundx = groundy = groundz = 1;
  711.         else
  712.          {
  713.           groundx = strchr(argv[i]+2,'x') ? 1 : 0;
  714.           groundy = strchr(argv[i]+2,'y') ? 1 : 0;
  715.           groundz = strchr(argv[i]+2,'z') ? 1 : 0;
  716.          }
  717.         break;
  718.        case 'I':/* information on object */
  719.         info = 1;
  720.         break;
  721.        case 'F':/* reverse vertex order */
  722.         reverse = 1;
  723.         break;
  724.        case 'N':/* renumber vertices in comments */
  725.         renverts = 1;
  726.         break;
  727.        case 'Q':/* recolor all polys randomly */
  728.         rrecolor = 1;
  729.         break;
  730.        case 'W':/* integer (whole) numbers only */
  731.         whole = 1;
  732.         break;
  733.        case 'Y':/* all objects in file are one for size/center */
  734.         integrated = 1;
  735.         break;
  736.        case 'Z':/* avg. center */
  737.         gcenter = 1;
  738.         break;
  739.        case '?':/* syntax */
  740.         syntax();
  741.         exit(0);
  742.         break;
  743.  
  744.        case 'S':/* scale PLG */
  745.         c=sscanf(argv[++i],"%f,%f,%f",&sx,&sy,&sz);
  746.         if (c<3) sy = sz = sx;
  747.         if(sx<0 || sy<0 || sz<0)
  748.          {
  749.           fprintf(stderr, "Negative scaling not allowed: will cause visibility errors\n");
  750.           fprintf(stderr, "Please use rotation instead\n");
  751.           exit(-1);
  752.          }
  753.         break;
  754.        case 'P':/* recolor all polys */
  755.         strcpy(newcolor, argv[++i]);
  756.         break;
  757.        case 'T':/* translate PLG */
  758.         c=sscanf(argv[++i],"%f,%f,%f",&tx,&ty,&tz);
  759.         break;
  760.        case 'R':/* rotate PLG */
  761.         c=sscanf(argv[++i],"%f,%f,%f",&rx,&ry,&rz);
  762.         break;
  763.        case 'B':/* abs box size PLG */
  764.         c=sscanf(argv[++i],"%f,%f,%f",&bx,&by,&bz);
  765.         if (c<3) by = bz = bx;
  766.         break;
  767.  
  768.        case 'O':/* object in file to process */
  769.         obj = 1;
  770.         if(isdigit(argv[i+1][0]))
  771.            c=sscanf(argv[++i],"%d",&obj);
  772.         break;
  773.        case 'V':/* vertex recombine */
  774.         clim = 0.0001;
  775.         if(isdigit(argv[i+1][0]))
  776.            c=sscanf(argv[++i],"%f",&clim);
  777.         break;
  778.        case 'L':/* longest axis */
  779.         laxis = 1000.0;
  780.         if(isdigit(argv[i+1][0]))
  781.            c=sscanf(argv[++i],"%f",&laxis);
  782.         break;
  783.        case 'D':/* default size box */
  784.         {
  785.          float ds = 1000.0;
  786.          if(isdigit(argv[i+1][0]))
  787.              c=sscanf(argv[++i],"%f",&ds);
  788.          bx = by = bz = ds;
  789.         }
  790.         break;
  791.       }
  792.     }
  793.    else
  794.     {
  795.      if(!fin[0]) strcpy(fin,argv[i]);      /* copy in, out filename */
  796.      else        strcpy(fout,argv[i]);
  797.     }
  798.   }
  799.  if(fin[0]==0 && fout[0]==0) syntax();
  800.  
  801.  if(strchr(fout, '$'))    /* '$' in out name replaced by in name */
  802.   {
  803.    char t[100];
  804.    char *p = strchr(fout, '$');
  805.    *p++ = 0;
  806.    strcpy(t, fout);
  807.    strcat(t, fin);
  808.    strcat(t, p);
  809.    strcpy(fout,t);
  810.   }
  811.  
  812.  add_extension(fin, "plg");
  813.  add_extension(fout, "plg");
  814.  if((in=fopen(fin,"r"))==NULL)
  815.   {
  816.    fprintf(stderr, "Can't open %s for input.\n", fin);
  817.    exit(-1);
  818.   }
  819.  if(fout[0])
  820.   if((out=fopen(fout,"w"))==NULL)
  821.     {
  822.      fprintf(stderr, "Can't open %s for output.\n", fout);
  823.      exit(-1);
  824.     }
  825.  
  826.  maxx = maxy = maxz = -1e9;
  827.  minx = miny = minz =  1e9;
  828.  sumx = sumy = sumz =  0.0;
  829.  abssumverts = 0;
  830.  
  831.  i = 0;
  832.  
  833.  if(integrated)
  834.   {
  835.    while(!feof(in))
  836.     {
  837.      read_plg();
  838.      if(nameline<0) break;
  839.     }
  840.    fseek(in,0,0);
  841.    integrated = -1;
  842.   }
  843.  
  844.  while(!feof(in))
  845.   {
  846.    i++;
  847.    read_plg();
  848.    if(nameline<0) break;
  849.    if(info) print_info();
  850.    if(obj==0 || obj == i) process_plg();
  851.    if(fout[0]) write_plg();
  852.   }
  853.  fcloseall();
  854.  fprintf(stderr, "Sucessful completion.\n");
  855.  exit(0);
  856. }
  857.