home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / preview.c < prev    next >
C/C++ Source or Header  |  1990-08-06  |  10KB  |  551 lines

  1. /*
  2.  * Previewer or NFF files using VOGLE.
  3.  * 
  4.  * One and only real option -p<n> for the precision with which the cylinders
  5.  * and cones are drawn (ie they are made up of approximating straight lines).
  6.  * (Plus a -d<n> for debugging - but you won't want that will you?)
  7.  *
  8.  * Any comments queries etc to echidna@gondwana.ecr.mu.OZ.AU
  9.  * or echidna@munnari.OZ.AU
  10.  *
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <math.h>
  15. #include "vogle.h"
  16.  
  17. /*
  18.  * The viewing parameters....
  19.  */
  20. struct {
  21.     float    Fx, Fy, Fz;
  22.     float    Ax, Ay, Az;
  23.     float    Ux, Uy, Uz;
  24.     float    angle;
  25.     float    hither, yon;
  26.     int    xres, yres;
  27. } view;
  28.  
  29. /*
  30.  * Could have done something with the actual colours but didn't...
  31.  * (they're currently ignored)
  32.  */
  33. struct    {
  34.     float    r, g, b;
  35. } bg, fc;
  36.  
  37. int    pr = 12;    /* Precision of cones and spheres */
  38. int    line = 1;    /* Line number in nff file */
  39. int    debug = 0;
  40.  
  41. FILE    *fp;
  42.  
  43. char    *filename;
  44. char    buf[128];
  45.  
  46. main(argc, argv)
  47.     int    argc;
  48.     char    **argv;
  49. {
  50.     int    c;
  51.     float    dum, Kd, Ks, Shine, T, i_of_r;
  52.  
  53.     if (argc < 2) {
  54.         fprintf(stderr, "usage: %s [-p<n>] nfffile\n", argv[0]);
  55.         exit(1);
  56.     }
  57.     
  58.     for (c = 1; c < argc; c++) {
  59.         if (strncmp(argv[c], "-p", 2) == 0)
  60.             pr = atoi(&argv[c][2]);
  61.         else if (strncmp(argv[c], "-d", 2) == 0) {
  62.             debug = atoi(&argv[c][2]);
  63.             fprintf(stderr, "debug: %d\n", debug);
  64.         } else
  65.             filename = argv[c];
  66.     }
  67.     
  68.  
  69.     if ((fp = fopen(filename, "r")) == (FILE *)NULL) {
  70.         fprintf(stderr, "Couldn't open %s for reading.\n", filename);
  71.         exit(1);
  72.     }
  73.  
  74.  
  75.     while ((c = getc(fp)) != EOF) {
  76.         switch (c) {
  77.         case '\t':
  78.             break;
  79.  
  80.         case 'v':
  81.             read_view();
  82.             break;
  83.  
  84.         case 'l':    /* Lights - ignore them */
  85.             read_three("%g %g %g\n", &dum, &dum, &dum);
  86.             break;
  87.  
  88.         case 'b':    /* Background color */
  89.             read_three("%g %g %g\n", &bg.r, &bg.r, &bg.r);
  90.             break;
  91.  
  92.         case 'f':    /* Fill color and shading stuff */
  93.             if (fscanf(fp, "%g %g %g %g %g %g %g %g\n", 
  94.                 &fc.r, &fc.b, &fc.b,
  95.                 &Kd, &Ks, &Shine, &T, &i_of_r) != 8)
  96.                 thunk("what happened");
  97.  
  98.             line++;
  99.             break;
  100.         case 'c':    /* Cylinder or Cone */
  101.             read_cone();
  102.             break;
  103.  
  104.         case 's':    /* Sphere */
  105.             read_sphere();
  106.             break;
  107.  
  108.         case 'p':    /* Polygon or polygonal patch */
  109.             c = getc(fp);
  110.             if (c == 'p')
  111.                 read_polypatch();
  112.             else
  113.                 read_poly();
  114.  
  115.             break;
  116.  
  117.         case '#':    /* Comment */
  118.             while ((c = getc(fp)) != '\n' && c != EOF)
  119.                 /* VOID */ ;
  120.  
  121.                 if (c == EOF)
  122.                     exit(0);
  123.  
  124.                 line++;
  125.  
  126.             break;
  127.  
  128.         default:
  129.             sprintf(buf, "Unknown  key character '%c'.", c);
  130.             thunk(buf);
  131.         }
  132.     }
  133.  
  134.     getkey();
  135.  
  136.     vexit();
  137. }
  138.  
  139. /*
  140.  * read_view
  141.  *
  142.  *    Read in the viewing parameters
  143.  */
  144. read_view()
  145. {
  146.     read_three("\nfrom %g %g %g", &view.Fx, &view.Fy, &view.Fz);
  147.     read_three("\nat %g %g %g", &view.Ax, &view.Ay, &view.Az);
  148.     read_three("\nup %g %g %g", &view.Ux, &view.Uy, &view.Uz);
  149.  
  150.     if (fscanf(fp, "\nangle %g", &view.angle) != 1)
  151.         thunk("wanted a number for fov");
  152.  
  153.     line++;
  154.     if (fscanf(fp, "\nhither %g", &view.hither) != 1)
  155.         thunk("wanted a number for hither");
  156.  
  157.     line++;
  158.     if (fscanf(fp, "\nresolution %d %d\n", &view.xres, &view.yres) != 2)
  159.         thunk("wanted two numbers for resolution");
  160.  
  161.     line++;
  162.     view.yon = 1.0e38;
  163.  
  164.     if (debug) {
  165.         fprintf(stderr, "View is:\n");
  166.         fprintf(stderr, "from %g %g %g\n", view.Fx, view.Fy, view.Fz);
  167.         fprintf(stderr, "at %g %g %g\n", view.Ax, view.Ay, view.Az);
  168.         fprintf(stderr, "up %g %g %g\n", view.Ux, view.Uy, view.Uz);
  169.         fprintf(stderr, "angle %g\n", view.angle);
  170.         fprintf(stderr, "hither %g\n", view.hither);
  171.         fprintf(stderr, "resolution %d %d\n", view.xres, view.yres);
  172.     }
  173.  
  174.     /*
  175.      * Open vogle .....
  176.      */
  177.  
  178.     prefsize(view.xres, view.yres);    /* If we can - do it */
  179.  
  180.     vinit(0);    /* Get device from environment variable VDEVICE */
  181.     color(BLACK);
  182.     clear();
  183.  
  184.     /*
  185.      * Set up view ....
  186.      */
  187.     up(view.Ux, view.Uy, view.Uz);
  188.     perspective(view.angle, 1.0, view.hither, view.yon);
  189.     lookat(view.Fx, view.Fy, view.Fz, view.Ax, view.Ay, view.Az, 0.0);
  190.  
  191.     /*
  192.      * Set precision ...
  193.      */
  194.     circleprecision(pr);
  195. }
  196.  
  197. /*
  198.  * read_sphere
  199.  *
  200.  *    Read in and draw a sphere.
  201.  */
  202. read_sphere()
  203. {
  204.     float    i, x, y, z, r, a;
  205.     float    delta = 180.0 / pr;
  206.  
  207.     color(RED);
  208.  
  209.     read_four("%g %g %g %g\n", &x, &y, &z, &r);
  210.  
  211.     if (debug == 2 || debug == 5) 
  212.         fprintf(stderr, "sphere: %g %g %g %g\n", x, y, z, r);
  213.  
  214.     pushmatrix();
  215.         translate(x, y, z);
  216.         /*
  217.          * create the longitudinal rings
  218.          */
  219.         for (i = 0; i < 180; i += delta) {
  220.             pushmatrix();
  221.                 rotate(i, 'y');
  222.                 circle(0.0, 0.0, r);
  223.             popmatrix();
  224.         }
  225.         
  226.         /*
  227.          * create the latitudinal rings
  228.          */
  229.         pushmatrix();
  230.             rotate(90.0, 'x');
  231.             for (i = -90.0; i < 90.0; i += delta) {
  232.                 a = r * cos((double)i * PI / 180.0);
  233.                 z = r * sin((double)i * PI / 180.0);
  234.                 pushmatrix();
  235.                     translate(0.0, 0.0, -z);
  236.                     circle(0.0, 0.0, a);
  237.                 popmatrix();    
  238.             }
  239.         popmatrix();
  240.     popmatrix();
  241.  
  242. }
  243.  
  244. /*
  245.  * read_cone
  246.  *
  247.  *    Read in and draw a cone or a cylinder
  248.  */
  249. read_cone()
  250. {
  251.     float    apex_x, apex_y, apex_z, apex_r;
  252.     float    base_x, base_y, base_z, base_r;
  253.     float    len0, len1,  len_x, len_y, len_z;
  254.     float    cosine, sine, dx1, dy1, dx2, dy2, delta;
  255.     float    cx1, cy1, cx2, cy2;
  256.     int    i;
  257.     Matrix    m;
  258.  
  259.     read_four("%g %g %g %g\n", &base_x, &base_y, &base_z, &base_r);
  260.     read_four("%g %g %g %g\n", &apex_x, &apex_y, &apex_z, &apex_r);
  261.  
  262.     if (debug == 2 || debug == 5) {
  263.         fprintf(stderr, "cone: %g %g %g $g\n", base_x, base_y, base_z, base_r);
  264.         fprintf(stderr, "cone: %g %g %g $g\n", apex_x, apex_y, apex_z, apex_r);
  265.     }
  266.  
  267.     len_x = apex_x - base_x;
  268.     len_y = apex_y - base_y;
  269.     len_z = apex_z - base_z;
  270.  
  271.     if ((len0 = sqrt(len_x * len_x + len_y * len_y + len_z * len_z)) < 1.0e-20)
  272.         warn("c: zero length cone or cylinder");
  273.  
  274.     len1 = sqrt(len_x * len_x + len_z * len_z);
  275.  
  276.     /*
  277.      * Draw the axis center line in YELLOW
  278.      */
  279.     color(YELLOW);
  280.     move(base_x, base_y, base_z);
  281.     draw(apex_x, apex_y, apex_z);
  282.  
  283.     /*
  284.      * And the rest in GREEN...
  285.      */
  286.     color(GREEN);
  287.  
  288.     pushmatrix();
  289.  
  290.         translate(base_x, base_y, base_z);
  291.  
  292.         identmatrix(m);
  293.  
  294.         if (len1 == 0.0) {
  295.             cosine = 0.0;
  296.             sine = 1.0;
  297.         } else {
  298.             cosine = len_z / len1;
  299.             sine = len_x / len1;
  300.         }
  301.  
  302.         /* rotate about y */
  303.         m[0][0] = cosine;
  304.         m[0][2] = -sine;
  305.         m[2][0] = sine;
  306.         m[2][2] = cosine;
  307.         multmatrix(m);
  308.  
  309.         identmatrix(m);
  310.  
  311.         if (len0 == 0.0) {
  312.             cosine = 0.0;
  313.             sine = 1.0;
  314.         } else {
  315.             cosine = len1 / len0;
  316.             sine = -len_y / len0;
  317.         }
  318.  
  319.         /* rotate about x */
  320.         m[1][1] = cosine;
  321.         m[1][2] = sine;
  322.         m[2][1] = -sine;
  323.         m[2][2] = cosine;
  324.         multmatrix(m);
  325.  
  326.         /*
  327.          * Draw the end circles...
  328.          */
  329.         circle (0.0, 0.0, base_r);
  330.         pushmatrix();
  331.             translate(0.0, 0.0, len0);
  332.             circle (0.0, 0.0, apex_r);
  333.         popmatrix();
  334.  
  335.  
  336.  
  337.         /*
  338.          * Draw the logitudinal lines...
  339.          */
  340.         delta = 2 * PI / pr;
  341.  
  342.         cosine = cos(delta);
  343.         sine = sin(delta);
  344.  
  345.         cx1 = base_r;
  346.         cy1 = 0.0;
  347.         cx2 = apex_r;
  348.         cy2 = 0.0;
  349.  
  350.         move(cx1, cy1, 0.0);
  351.         draw(cx2, cy2, len0);
  352.  
  353.         for (i = 0; i < pr; i++) {
  354.             dx1 = cx1;
  355.             dy1 = cy1;
  356.             cx1 = dx1 * cosine - dy1 * sine;
  357.             cy1 = dx1 * sine + dy1 * cosine;
  358.             dx2 = cx2;
  359.             dy2 = cy2;
  360.             cx2 = dx2 * cosine - dy2 * sine;
  361.             cy2 = dx2 * sine + dy2 * cosine;
  362.             move(cx1, cy1, 0.0);
  363.             draw(cx2, cy2, len0);
  364.         }
  365.     popmatrix();
  366. }
  367.  
  368. /*
  369.  * read_poly
  370.  *
  371.  *     Read in and draw a polygon.
  372.  */
  373. read_poly()
  374. {
  375.     float    x, y, z, xp, yp, zp, x0, y0, z0;
  376.     int    i, nv;
  377.  
  378.     if (fscanf(fp, "%d\n", &nv) != 1)
  379.         thunk("wanted an integer for number of verticies");
  380.  
  381.     line++;
  382.  
  383.     if (nv <= 0)
  384.         thunk("p: silly value for number of verticies");
  385.     
  386.     color(CYAN);
  387.  
  388.     read_three("%g %g %g\n", &x0, &y0, &z0);
  389.  
  390.     if (debug == 3 || debug == 5) 
  391.         fprintf(stderr, "poly: %g %g %g\n", x0, y0, z0);
  392.  
  393.     move(x0, y0, z0);
  394.  
  395.     xp = x0;
  396.     yp = y0;
  397.     zp = z0;
  398.  
  399.     for (i = 1; i < nv; i++) {
  400.         read_three("%g %g %g\n", &x, &y, &z);
  401.  
  402.         if (debug == 3 || debug == 5) 
  403.             fprintf(stderr, "poly: %g %g %g\n", x, y, z);
  404.  
  405.         draw(x, y, z);
  406.         if (xp == x && yp == y && zp == z) {
  407.             warn("p: point same as previous point");
  408.             sprintf(buf, "%g %g %g = %g %g %g", xp, yp, zp, x, y, z);
  409.             warn(buf);
  410.         }
  411.  
  412.         xp = x;
  413.         yp = y;
  414.         zp = z;
  415.     }
  416.     /*
  417.      * Connect last to first...
  418.      */
  419.     draw(x0, y0, z0);
  420. }
  421.  
  422. /*
  423.  * read_polypatch
  424.  *
  425.  *    Read in and draw a "poly patch" thingo (ie a polygon with
  426.  *    vertex normals)
  427.  */
  428. read_polypatch()
  429. {
  430.     float    x, y, z, x0, y0, z0, xp, yp, zp, nx, ny, nz;
  431.     int    i, nv;
  432.  
  433.     color(MAGENTA);
  434.  
  435.     if (fscanf(fp, "%d\n", &nv) != 1)
  436.         thunk("wanted an integer for number of verticies");
  437.  
  438.     if (nv <= 0)
  439.         thunk("pp: silly value for number of verticies");
  440.  
  441.     line++;
  442.     
  443.     read_six("%g %g %g %g %g %g\n", &x0, &y0, &z0, &nx, &ny, &nz);
  444.  
  445.     if (debug == 4 || debug == 5) 
  446.         fprintf(stderr, "poly_patch: %g %g %g %g %g %g\n", x0, y0, z0, nx, ny, nz);
  447.  
  448.     if (nx == 0.0 && ny == 0.0 && nz == 0.0)
  449.         warn("pp: zero length normal vector");
  450.  
  451.     xp = x0;
  452.     yp = y0;
  453.     zp = z0;
  454.  
  455.     move(x0, y0, z0);
  456.     for (i = 1; i < nv; i++) {
  457.         read_six("%g %g %g %g %g %g\n", &x, &y, &z, &nx, &ny, &nz);
  458.  
  459.         if (debug == 4 || debug == 5) 
  460.             fprintf(stderr, "poly_patch: %g %g %g %g %g %g\n", x, y, z, nx, ny, nz);
  461.  
  462.  
  463.         draw(x, y, z);
  464.  
  465.         if (nx == 0.0 && ny == 0.0 && nz == 0.0)
  466.             warn("pp: zero length normal vector");
  467.  
  468.         if (xp == x && yp == y && zp == z) {
  469.             warn("pp: point same as previous point");
  470.             sprintf(buf, "%g %g %g = %g %g %g", xp, yp, zp, x, y, z);
  471.             warn(buf);
  472.         }
  473.  
  474.         xp = x;
  475.         yp = y;
  476.         zp = z;
  477.     }
  478.     /*
  479.      * Connect last to first...
  480.      */
  481.     draw(x0, y0, z0);
  482. }
  483.  
  484. /*
  485.  * warn
  486.  *
  487.  *    Print a warning
  488.  */
  489. warn(s)
  490.     char    *s;
  491. {
  492.     fprintf(stderr, "%s: line %d: %s\n", filename, line, s);
  493. }
  494.  
  495. /*
  496.  * thunk
  497.  *
  498.  *    Go thunk! (die)
  499.  */
  500. thunk(s)
  501.     char    *s;
  502. {
  503.     fprintf(stderr, "%s: line %d: %s\n", filename, line, s);
  504.     exit(1);
  505. }
  506.  
  507. /*
  508.  * We seem to be reading lots of sets of 3 or 4 or 6 numbers....
  509.  */
  510. read_three(f, a, b, c)
  511.     char    *f;
  512.     float    *a, *b, *c;
  513. {
  514.     int    n;
  515.  
  516.     if ((n = fscanf(fp, f, a, b, c)) != 3) {
  517.         sprintf(buf, "expected to read 3 numbers with '%s' format but got %d\n", f, n);
  518.         thunk(buf);
  519.     }
  520.  
  521.     line++;
  522. }
  523.  
  524. read_four(f, a, b, c, d)
  525.     char    *f;
  526.     float    *a, *b, *c, *d;
  527. {
  528.     int    n;
  529.  
  530.     if ((n = fscanf(fp, f, a, b, c, d)) != 4) {
  531.         sprintf(buf, "expected to read 4 numbers with '%s' format but got %d\n", f, n);
  532.         thunk(buf);
  533.     }
  534.  
  535.     line++;
  536. }
  537.  
  538. read_six(f, a, b, c, d, e, g)
  539.     char    *f;
  540.     float    *a, *b, *c, *d, *e, *g;
  541. {
  542.     int    n;
  543.  
  544.     if ((n = fscanf(fp, f, a, b, c, d, e, g)) != 6) {
  545.         sprintf(buf, "expected to read 6 numbers with '%s' format but got %d\n", f, n);
  546.         thunk(buf);
  547.     }
  548.  
  549.     line++;
  550. }
  551.