home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / atomart.tar.gz / atomart.tar / util.c < prev   
C/C++ Source or Header  |  1990-06-17  |  6KB  |  357 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include "atomart.h"
  4. #include "macro.h"
  5.  
  6. extern attr    *astackp;
  7. extern matrix    trans;
  8. extern vector    org;
  9.  
  10. /*
  11.  * utility routines for adjusting transformations, general calcs and other
  12.  * things.
  13.  */
  14.  
  15. /*
  16.  * power
  17.  *
  18.  *    raise x to the integer power e
  19.  */
  20. double 
  21. power(x, e)
  22.     double    x;
  23.     register int    e;
  24. {
  25.     register double    a, b;
  26.  
  27.     b = x;
  28.  
  29.     switch (e) {
  30.     case 0:
  31.         return(1.0);
  32.     case 1:
  33.         return(b);
  34.     case 2:
  35.         return(b * b);
  36.     case 3:
  37.         return(b * b * b);
  38.     case 4:
  39.         b *= b;
  40.         return(b * b);
  41.     case 5:
  42.         b *= b;
  43.         return(b * b * x);
  44.     case 6:
  45.         b *= b;
  46.         return(b * b * b);
  47.     default:
  48.         e -= 6;
  49.         a = b * b;
  50.         a = a * a * a;
  51.         for (;;) {
  52.             if (e & 1) {
  53.                 a *= b;
  54.                 if ((e /= 2) == 0)
  55.                     return(a);
  56.             } else 
  57.                 e /= 2;
  58.             b *= b;
  59.         }
  60.     }
  61.  
  62.     /* NOTREACHED */
  63. }
  64.  
  65. /*
  66.  * rotate
  67.  *
  68.  *     adjust the transformation matrix for a rotate - done in reverse
  69.  * as it is done to the ray.
  70.  */
  71. rotate(ang, axis)
  72.     float    ang;
  73.     char    axis;
  74. {
  75.     matrix    mat, tmp;
  76.     float    sinval, cosval;
  77.  
  78.     mident4(mat);
  79.     sinval = sin(-ang * M_PI / 180.0);
  80.     cosval = cos(-ang * M_PI / 180.0);
  81.  
  82.     switch (axis) {
  83.     case 'x':
  84.         mat[1][1] = cosval;
  85.         mat[1][2] = sinval;
  86.         mat[2][2] = cosval;
  87.         mat[2][1] = -sinval;
  88.         break;
  89.     case 'y':
  90.         mat[0][0] = cosval;
  91.         mat[0][2] = sinval;
  92.         mat[2][0] = -sinval;
  93.         mat[2][2] = cosval;
  94.         break;
  95.     case 'z':
  96.         mat[0][0] = cosval;
  97.         mat[0][1] = sinval;
  98.         mat[1][0] = -sinval;
  99.         mat[1][1] = cosval;
  100.         break;
  101.     default:
  102.         fatal("atomart: bad axis name in rotate.\n");
  103.     }
  104.  
  105.     mcpy4(tmp, astackp->m);
  106.     mmult4(astackp->m, mat, tmp);
  107.  
  108.     astackp->mcopy = TRUE;
  109. }
  110.  
  111. /*
  112.  * translate
  113.  *
  114.  *    translate - done in reverse as we do this to the ray.
  115.  */
  116. translate(x, y, z)
  117.     float    x, y, z;
  118. {
  119.     matrix    mat, tmp;
  120.  
  121.     mident4(mat);
  122.  
  123.     mat[3][0] = -x;
  124.     mat[3][1] = -y;
  125.     mat[3][2] = -z;
  126.  
  127.     mcpy4(tmp, astackp->m);
  128.     mmult4(astackp->m, mat, tmp);
  129. }
  130.  
  131. /*
  132.  * objtranslate
  133.  *
  134.  *    translate done through the current transformation matrix. 
  135.  */
  136. objtranslate(x, y, z)
  137.     float    x, y, z;
  138. {
  139.     matrix    mat, tmp;
  140.  
  141.     mident4(mat);
  142.  
  143.     mat[3][0] = -x / astackp->scales.x;
  144.     mat[3][1] = -y / astackp->scales.y;
  145.     mat[3][2] = -z / astackp->scales.z;
  146.  
  147.     mcpy4(tmp, astackp->m);
  148.     mmult4(astackp->m, tmp, mat);
  149. }
  150.  
  151. /*
  152.  * scale
  153.  *
  154.  *    scale routine - done in reverse as we do this to the ray.
  155.  */
  156. scale(x, y, z)
  157.     float    x, y, z;
  158. {
  159.     astackp->scales.x /= x;
  160.     astackp->scales.y /= y;
  161.     astackp->scales.z /= z;
  162.  
  163.     if (astackp->scales.x < astackp->scales.y)
  164.         astackp->maxscale = astackp->scales.x;
  165.     else
  166.         astackp->maxscale = astackp->scales.y;
  167.     
  168.     if (astackp->scales.z < astackp->maxscale)
  169.         astackp->maxscale = astackp->scales.z;
  170.     
  171.     astackp->maxscale = 1.0 / astackp->maxscale;
  172. }
  173.  
  174. /*
  175.  * qtransform
  176.  *
  177.  *    set up the appropriate rotations, scaling, and translations for
  178.  * a cylinder, cone, or general quadric. This routine needs to be 
  179.  * called before radii, etc... are taken into account.
  180.  */
  181. qtransform(cent1, cent2)
  182.     vector    cent1, cent2;
  183. {
  184.     float    sinval, cosval, d1, d2, d3;
  185.     matrix    m, tmp;
  186.  
  187.     /*
  188.      * translate it
  189.      */
  190.     mident4(m);
  191.     m[3][0] = -cent1.x / astackp->scales.x;
  192.     m[3][1] = -cent1.y / astackp->scales.y;
  193.     m[3][2] = -cent1.z / astackp->scales.z;
  194.     mcpy4(tmp, astackp->m);
  195.     mmult4(astackp->m, tmp, m);
  196.  
  197.     /*
  198.      * fix the quadric's height 
  199.      */
  200.     scale(1.0, 1.0, sqrt(sqr(cent2.x - cent1.x) + sqr(cent2.y - cent1.y) + sqr(cent2.z - cent1.z)));
  201.  
  202.     /*
  203.      * calculate the rotations to align the ray
  204.      * with the quadric's axis 
  205.      */
  206.     d1 = cent1.x - cent2.x;
  207.     d2 = cent1.y - cent2.y;
  208.     d3 = cent1.z - cent2.z;
  209.  
  210.     if (d1 != 0.0 || d3 != 0.0) {    /* rotate about y */
  211.         sinval = -d1 / sqrt(d1 * d1 + d3 * d3);
  212.  
  213.         cosval = d3 / sqrt(d1 * d1 + d3 * d3);
  214.  
  215.         if (fabs(sinval) > 1.0)
  216.             sinval = (sinval > 0.0) ? 1.0 : -1.0;
  217.  
  218.         if (fabs(cosval) > 1.0)
  219.             cosval = (cosval > 0.0) ? 1.0 : -1.0;
  220.  
  221.         mident4(m);
  222.         m[0][0] = cosval;
  223.         m[2][0] = sinval;
  224.         m[0][2] = -sinval;
  225.         m[2][2] = cosval;
  226.         mcpy4(tmp, astackp->m);
  227.         mmult4(astackp->m, tmp, m);
  228.     }
  229.  
  230.     if (d2 != 0.0) {        /* rotate about x */
  231.         sinval = d2 / sqrt(d1 * d1 + d2 * d2 + d3 * d3);
  232.  
  233.         if (fabs(sinval) > 1.0)
  234.             sinval = (sinval > 0.0) ? 1.0 : -1.0;
  235.  
  236.         cosval = sqrt(1.0 - sinval * sinval);
  237.  
  238.         mident4(m);
  239.         m[1][1] = cosval;
  240.         m[1][2] = sinval;
  241.         m[2][2] = cosval;
  242.         m[2][1] = -sinval;
  243.         mcpy4(tmp, astackp->m);
  244.         mmult4(astackp->m, tmp, m);
  245.     }
  246.  
  247.     /*
  248.      * twist around y to align with positive in z
  249.      * (the transformations above align us in negative z)
  250.      */
  251.     mident4(m);
  252.     m[0][0] = -1.0;
  253.     m[2][2] = -1.0;
  254.     mcpy4(tmp, astackp->m);
  255.     mmult4(astackp->m, tmp, m);
  256.  
  257.     astackp->mcopy = TRUE;
  258. }
  259.  
  260. /*
  261.  * setattributes
  262.  *
  263.  *    set the attributes and transformations for an object.
  264.  */
  265. setattributes(o)
  266.     object    *o;
  267. {
  268.     matrix    tmp;
  269.     tlist    *tl, *tlnxt;
  270.  
  271.     o->s = astackp->s;
  272.  
  273.     /*
  274.      * put textures into correct order and set some parameters
  275.      */
  276.     o->s.txtlist = (tlist *)NULL;
  277.  
  278.     for (tl = astackp->s.txtlist; tl != (tlist *)NULL; tl = tlnxt) {
  279.         tlnxt = tl->nxt;
  280.         tl->nxt = o->s.txtlist;
  281.         o->s.txtlist = tl;
  282.         o->s.txtlist->txt.c = astackp->s.c;
  283.         o->s.txtlist->txt.a = astackp->s.a;
  284.     }
  285. }
  286.  
  287. /*
  288.  * readascmap
  289.  *
  290.  *    read in an ascii texture/bump map.
  291.  */
  292. readascmap(txt, name)
  293.     texture    *txt;
  294.     char    *name;
  295. {
  296.     FILE    *f;
  297.     int    c, noheader, x, y, tot;
  298.     float    val1, val2, val3;
  299.     char    buf[BUFSIZ];
  300.  
  301.     if ((f = fopen(name, "r")) == (FILE *)NULL) {
  302.         sprintf(buf, "atomart: can't open ascii map file %s.\n", name);
  303.         fatal(buf);
  304.     }
  305.     
  306.     noheader = TRUE;
  307.  
  308.     while (noheader && (c = getc(f)) != EOF) {
  309.         if (c == '#')        /* comment */
  310.             while ((c = getc(f)) != '\n' && c != EOF)
  311.                 ;
  312.         else {
  313.             ungetc(c, f);
  314.             if (fscanf(f, "%d %d ", &x, &y) != 2) {
  315.                 sprintf(buf, "atomart: improper header in ascii map file %s.\n", name);
  316.                 fatal(buf);
  317.             }
  318.             noheader = FALSE;
  319.         }
  320.     }
  321.  
  322.     txt->pixw = x;
  323.     txt->pixh = y;
  324.  
  325.     txt->map = (char *)smalloc(x * y * 3);
  326.  
  327.     if (noheader) {
  328.         sprintf(buf, "atomart: no header in ascii map file %s.\n", name);
  329.         fatal(buf);
  330.     }
  331.  
  332.     tot = 0;
  333.     while (tot < x * y && (c = getc(f)) != EOF) {
  334.         if (c == '#')        /* comment */
  335.             while ((c = getc(f)) != '\n' && c != EOF)
  336.                 ;
  337.         else {
  338.             ungetc(c, f);
  339.             if (fscanf(f, "%f %f %f ", &val1, &val2, &val3) != 3) {
  340.                 sprintf(buf, "atomart: improper data in ascii map file %s.\n", name);
  341.                 fatal(buf);
  342.             }
  343.             txt->map[tot * 3] = val1 * 255.0;
  344.             txt->map[tot * 3 + 1] = val2 * 255.0;
  345.             txt->map[tot * 3 + 2] = val3 * 255.0;
  346.             tot++;
  347.         }
  348.     }
  349.  
  350.     if (tot != x * y) {
  351.         sprintf(buf, "atomart: ascii map file %s too short.\n", name);
  352.         warning(buf);
  353.     }
  354.  
  355.     fclose(f);
  356. }
  357.