home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / atomart.tar.gz / atomart.tar / main.c < prev    next >
C/C++ Source or Header  |  1990-06-22  |  7KB  |  338 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <sys/types.h>
  4. #ifdef MSC
  5. #include <fcntl.h>
  6. #include <string.h>
  7. #define rindex strrchr
  8. #else
  9. #ifdef SYSV
  10. #include <fcntl.h>
  11. #else
  12. #include <sys/file.h>
  13. #endif
  14. #endif
  15. #include "atomart.h"
  16. #include "macro.h"
  17. #include "gram.h"
  18. #include "random.h"
  19.  
  20. extern char    *rindex();
  21. extern hlist    *trace();
  22. extern void    shade();
  23. extern time_t    time();
  24.  
  25. FILE    *logfile = stdout;
  26.  
  27. int    linecount;        /* line counter for parser */
  28.  
  29. object    *oblist;        /* object list */
  30. light    *lights;        /* lights list */
  31. attr    astack[20], *astackp;    /* attribute stack */
  32. char    *title;            /* title of picture */
  33.  
  34. short    raynumber = 1;        /* index number of ray */
  35. int    raysperpix = 1;        /* number of rays per pixel */
  36. int    maxhitlevel = 6;    /* max number of rays traced in reflection */
  37. long    filetype = PIX_RLE;    /* output file format */
  38.  
  39. object    *treeinit();
  40.  
  41. static object    *objlist;    /* list used to reset raynumber field */
  42.  
  43. /*
  44.  * ambient colour and background pixel stuff
  45.  */
  46. colour    ambient;
  47. colour    backcol = { 0.0, 0.0, 0.0 };
  48.  
  49. /*
  50.  * pointer to the free list for hit structures
  51.  */
  52. hlist    *fhlist;
  53.  
  54. /*
  55.  * details for the primary rays
  56.  */
  57. vector    org;
  58.  
  59. vector    up = { 0.0, 1.0, 0.0 };
  60.  
  61. float    focallength = -1.0;
  62.  
  63. matrix    trans = {
  64.     1.0, 0.0, 0.0, 0.0,
  65.     0.0, 1.0, 0.0, 0.0,
  66.     0.0, 0.0, 1.0, 0.0,
  67.     0.0, 0.0, 0.0, 1.0
  68. };
  69.  
  70. /*
  71.  * random number pointers
  72.  */
  73. float    *randp = randtable,
  74.     *erandp = &randtable[sizeof(randtable) / sizeof(float)];
  75.  
  76. /*
  77.  * x, y offsets, scale, and sampleing
  78.  */
  79. static int    xoff, yoff;
  80. static float    xscale, yscale;
  81. static int    ysperpix, xsperpix;
  82.  
  83. /*
  84.  * main driver
  85.  */
  86. main(ac, av)
  87.     int    ac;
  88.     char    *av[];
  89. {
  90.     int        y, x, chatty, indx;
  91.     char        *p, name[BUFSIZ], buf[BUFSIZ];
  92.     FILE        *f;
  93.     image        *im;
  94.     object        *o, *polyobjs, *sphereobjs, *nxtobj, *lastobjs;
  95.     unsigned short    xsize, ysize;
  96.     unsigned char    *red, *green, *blue, *alpha;
  97.  
  98.     if (ac < 4)
  99.         fatal("atomart: usage atomart [-v] fname xsize ysize\n");
  100.  
  101.     if (strcmp(av[1], "-v") == 0) {
  102.         indx = 2;
  103.         chatty = TRUE;
  104.         if (ac != 5)
  105.             fatal("atomart: usage atomart [-v] fname xsize ysize\n");
  106.     } else {
  107.         chatty = FALSE;
  108.         indx = 1;
  109.     }
  110.  
  111.     mident4(astack[0].m);
  112.     astack[0].scales.x = astack[0].scales.y = astack[0].scales.z = 1.0;
  113.     astack[0].maxscale = 1.0;
  114.     astack[0].s.txtlist = (tlist *)NULL;
  115.     astackp = astack;
  116.     linecount = 1;
  117.  
  118.     strcpy(name, av[indx]);
  119.  
  120.     if ((p = rindex(name, '.')) == (char *)NULL)
  121.         fatal("atomart: input file should end with \".scn\".\n");
  122.  
  123.     strcpy(p, ".log");
  124.     if ((logfile = fopen(name, "w")) == NULL) {
  125.         sprintf(buf, "atomart: unable to open %s for writing.\n", name);
  126.         fatal(buf);
  127.     }
  128.  
  129. #ifdef MSC
  130.     if ((f = freopen(av[indx], "rt", stdin)) == NULL) {
  131. #else
  132.     if ((f = freopen(av[indx], "r", stdin)) == NULL) {
  133. #endif
  134.         sprintf(buf, "atomart: unable to open file %s.\n", av[1]);
  135.         fatal(buf);
  136.     }
  137.  
  138.     yyparse();        /* read in model and set oblist */
  139.  
  140.     polyobjs = (object *)NULL;
  141.     sphereobjs = (object *)NULL;
  142.  
  143.     for (o = oblist; o != (object *)NULL; o = nxtobj) {
  144.         nxtobj = o->nxt;
  145.         if (o->type == POLYGON) {
  146.             o->nxt = polyobjs;
  147.             polyobjs = o;
  148.         } else {
  149.             o->nxt = sphereobjs;
  150.             sphereobjs = o;
  151.         }
  152.     }
  153.  
  154.     objlist = sphereobjs;
  155.  
  156.     oblist = treeinit(sphereobjs);
  157.  
  158.     oblist->nxt = polyobjs;
  159.  
  160.     strcpy(rindex(name, '.'), PIX_SUFFIX);
  161.  
  162.     xsize = (unsigned short)atoi(av[indx + 1]);
  163.     ysize = (unsigned short)atoi(av[indx + 2]);
  164.  
  165.     trans[0][0] *= xsize / (double)ysize;
  166.  
  167.     if ((im = openimage(name, "w")) == (image *)NULL) {
  168.         sprintf(buf, "atomart: unable to open %s for writing\n", name);
  169.         fatal(buf);
  170.     }
  171.  
  172.     imagetype(im) = filetype;
  173.  
  174.     imagewidth(im) = xsize;
  175.     imageheight(im) = ysize;
  176.  
  177.     imagedepth(im) = 24;
  178.  
  179.     imagedate(im) = time((time_t *)NULL);
  180.  
  181.     imagebackgnd(im).r = backcol.r * 255.0;
  182.     imagebackgnd(im).g = backcol.g * 255.0;
  183.     imagebackgnd(im).b = backcol.b * 255.0;
  184.  
  185.     if (title == (char *)NULL)
  186.         titlelength(im) = 0;
  187.     else {
  188.         titlelength(im) = strlen(title) + 1;
  189.         imagetitle(im) = title;
  190.     }
  191.  
  192.     writeheader(im);
  193.  
  194.     switch (raysperpix) {
  195.     case 1:
  196.         xsperpix = 1;
  197.         ysperpix = 1;
  198.         break;
  199.     case 2:
  200.         xsperpix = 2;
  201.         ysperpix = 1;
  202.         break;
  203.     case 4:
  204.         xsperpix = 2;
  205.         ysperpix = 2;
  206.         break;
  207.     case 8:
  208.         xsperpix = 4;
  209.         ysperpix = 2;
  210.         break;
  211.     case 16:
  212.         xsperpix = 4;
  213.         ysperpix = 4;
  214.         break;
  215.     case 32:
  216.         xsperpix = 8;
  217.         ysperpix = 4;
  218.         break;
  219.     default:
  220.         fatal("atomart: bad number of rays per pixel - must be power of two\n");
  221.     }
  222.     
  223.     xoff = xsize / 2;
  224.     yoff = ysize / 2;
  225.  
  226.     if (xsize > ysize)
  227.         xscale = yscale = ysize / 2;
  228.     else
  229.         xscale = yscale = xsize / 2;
  230.  
  231.     red = (unsigned char *)smalloc(xsize);
  232.     green = (unsigned char *)smalloc(xsize);
  233.     blue = (unsigned char *)smalloc(xsize);
  234.     alpha = (unsigned char *)smalloc(xsize);
  235.  
  236.     if (chatty)
  237.         for (y = ysize - 1; y >= 0; y--) {
  238.             for (x = 0; x != xsize; x++) {
  239.                 printf("\r((%03d), (%03d))", x, y);
  240.                 dotrace(x, y, &red[x], &green[x], &blue[x], &alpha[x]);
  241.             }
  242.             if (alphachannel(im))
  243.                 writergbaline(im, red, green, blue, alpha);
  244.             else
  245.                 writergbline(im, red, green, blue);
  246.         }
  247.     else
  248.         for (y = ysize - 1; y >= 0; y--) {
  249.             for (x = 0; x != xsize; x++)
  250.                 dotrace(x, y, &red[x], &green[x], &blue[x], &alpha[x]);
  251.             if (alphachannel(im))
  252.                 writergbaline(im, red, green, blue, alpha);
  253.             else
  254.                 writergbline(im, red, green, blue);
  255.         }
  256.  
  257.     closeimage(im);
  258.  
  259.     exit(0);
  260. }
  261.  
  262. /*
  263.  * dotrace
  264.  *
  265.  *    traces the neccessary number of rays and calculates r, g, b, and
  266.  * alpha info
  267.  */
  268. dotrace(x, y, r, g, b, a)
  269.     int    x, y;
  270.     char    *r, *g, *b, *a;
  271. {
  272.     int    i, j;
  273.     float    red, green, blue, alpha;
  274.     float    k1, k2;
  275.     hlist    *hit, *p, *lp, *end;
  276.     pixel    pix;
  277.     ray    ir;
  278.     object    *o;
  279.  
  280.     red = green = blue = alpha = 0.0;
  281.  
  282.     for (i = 0; i != xsperpix; i++)
  283.         for (j = 0; j != ysperpix; j++) {
  284.  
  285.             if (raysperpix != 1) {
  286.                 k1 = ((x - xoff) + (i + randnum()) / xsperpix) / xscale;
  287.                 k2 = ((y - yoff) + (j + randnum()) / ysperpix) / yscale;
  288.             } else {
  289.                 k1 = (x - xoff) / xscale;
  290.                 k2 = (y - yoff) / yscale;
  291.             }
  292.  
  293.             ir.org.x = k1;
  294.             ir.org.y = k2;
  295.             ir.org.z = 0;
  296.  
  297.             ir.dir.x = k1;
  298.             ir.dir.y = k2;
  299.             ir.dir.z = focallength;
  300.  
  301.             if (raynumber < 0) {
  302.                 for (o = objlist; o != (object *)NULL; o = o->nxt)
  303.                     o->raynumber = 0;
  304.                 raynumber = 1;
  305.             }
  306.  
  307.             ir.raynumber = raynumber++;
  308.  
  309.             normalise(ir.dir);
  310.  
  311.             if ((hit = trace(&ir, oblist)) != (hlist *)NULL) {
  312.                 shade(&pix, &ir, hit, 0);
  313.                 red += pix.r;
  314.                 green += pix.g;
  315.                 blue += pix.b;
  316.                 alpha++;
  317.  
  318.                 release(hit);
  319.             } else {
  320.                 red += backcol.r;
  321.                 green += backcol.g;
  322.                 blue += backcol.b;
  323.             }
  324.     }
  325.  
  326.     if (alpha != 0.0) {
  327.         *r = (red / raysperpix) * 255.0 + randnum();
  328.         *g = (green / raysperpix) * 255.0 + randnum();
  329.         *b = (blue / raysperpix) * 255.0 + randnum();
  330.         *a = alpha * 255.0 / raysperpix;
  331.     } else {
  332.         *r = (red / raysperpix) * 255.0;
  333.         *g = (green / raysperpix) * 255.0;
  334.         *b = (blue / raysperpix) * 255.0;
  335.         *a = 0;
  336.     }
  337. }
  338.