home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 120.lha / AnimBalls / animballs.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  10KB  |  485 lines

  1. /* animballs.c -- code to handle actual rotating images */
  2. #include <exec/types.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include <intuition/intuition.h>
  6.  
  7. #include "globals.h"
  8.  
  9. #include <proto/exec.h>
  10. #include <proto/graphics.h>
  11. #include <proto/intuition.h>
  12.  
  13. int woffset = WOFFSET;
  14. #define SETANDBOUND(ii,ff)    {ii = 0.5 + ff * 15; \
  15.                  if (ii > 15) ii = 15; \
  16.                  else if (ii < 0) ii = 0;}
  17.  
  18. float ka, kd, ks, lx, ly, lz, n, r;    /* coloring parameters */
  19. long int ix,iy,iz, jx,jy,jz, kx,ky,kz;
  20. static char title[81];
  21. int bgcolor = 0;
  22.  
  23. int scx = WIDTH / 2, scy = SMHEIGHT / 2;
  24. int xstart = -1; ystart = -1;
  25.  
  26. #define ISIZE 14
  27. #define FTOI(x) ((long int) (x * (1 << ISIZE)))
  28. #define MULT(x,y) ((x * y) >> ISIZE)
  29. #define LSIZE 10
  30.  
  31. #define MAKEL(x) ((long int) x * (1 << LSIZE))
  32.  
  33. struct Ball {
  34.     long int x,y,z;
  35.     float r,g,b,rad;
  36.     long int xp,yp,zp;
  37.     int y1,y2,intr,size;
  38.     int dup;
  39.     };
  40.  
  41. int nball;
  42. struct Ball **ballptr;
  43. struct Ball *balls;
  44. int maxsize = 0;
  45. int maskw = 0, maskh = 1;
  46. int maxextent = 0;
  47.  
  48. long int intsin[360];
  49. long int intcos[360];
  50.  
  51. void
  52. readballs(name)
  53. char *name;
  54. {
  55.     int i, j, extent;
  56.     int c;
  57.     float x,y,z,rad,r,g,b;
  58.     FILE *fp, *fopen();
  59.     int ir,ig,ib;
  60.  
  61.     if ((fp = fopen(name,"r")) == NULL) {
  62.         fprintf(stderr,"Can't open balls file - '%s'",name);
  63.         panic("");
  64.     }
  65.     strcpy(title,"Drag Mouse to Rotate");
  66.     if ((c = getc(fp)) != '"') ungetc(c,fp);
  67.     else {
  68.         i = 0;
  69.         c = getc(fp);
  70.         while ((c != '"') && (c != EOF)) {
  71.             if (i < 80) title[i++] = c;
  72.             c = getc(fp);
  73.         }
  74.         if (c == EOF) panic("Error - title lacks final \"");
  75.         title[i] = 0;
  76.     }
  77.     if ((c = fscanf(fp,"%f %f %f",&r,&g,&b)) != 3) {
  78.         fprintf(stderr,"Error reading background color %d",c+1);
  79.         panic("");
  80.     } else {
  81.         SETANDBOUND(ir,r);
  82.         SETANDBOUND(ig,g);
  83.         SETANDBOUND(ib,b);
  84.         bgcolor = match(ir,ig,ib);
  85.     }
  86.     if (fscanf(fp,"%d",&nball) != 1)
  87.         panic("Error - Can't read number of balls");
  88.     balls = (struct Ball *) malloc(sizeof(struct Ball)*nball);
  89.     if (balls == 0) panic("Not enough memory for balls");
  90.     ballptr = (struct Ball **) malloc(sizeof(long int)*nball);
  91.     if (ballptr == 0) panic("Not enough memory for ballptr");
  92.     for (i = 0; i < nball; i++) {
  93.         if ((c=fscanf(fp,"%f %f %f %f %f %f %f",&x,&y,&z,&rad,&r,&g,&b))!=7)
  94.             {fprintf(stderr,
  95.             "Error in reading item %d in ball description %d",
  96.             c+1,i+1);
  97.          panic("");
  98.         }
  99.         balls[i].x = MAKEL(x);
  100.         balls[i].y = MAKEL(y);
  101.         balls[i].z = MAKEL(z);
  102.         balls[i].rad = rad;
  103.         balls[i].r = r;
  104.         balls[i].g = g;
  105.         balls[i].b = b;
  106.         balls[i].intr = rad + 0.5;
  107.         balls[i].size = 2 * balls[i].intr + 1;
  108.         extent = 0.9 + sqrt(x*x + y*y +z*z) + balls[i].intr;
  109.         if (extent > maxextent) maxextent = extent;
  110.         if (balls[i].size > maxsize) maxsize = balls[i].size;
  111.         balls[i].dup = -1;
  112.  
  113.         for (j = 0; j < i; j++)     /* check for duplicate entries */
  114.         if ((balls[j].rad == rad) && (balls[j].r == r) &&
  115.             (balls[j].g == g) && (balls[j].b == b)) {
  116.                 balls[i].dup = j;
  117.             break;
  118.         }
  119.         if (balls[i].dup != -1) {
  120.             balls[i].y1 = balls[balls[i].dup].y1;
  121.         balls[i].y2 = balls[balls[i].dup].y2;
  122.         } else {
  123.         balls[i].y1 = maskh;
  124.         maskh += balls[i].size;
  125.         if (!bw) {
  126.                 balls[i].y2 = maskh;
  127.                 maskh += balls[i].size;
  128.         } else balls[i].y2 = 0;
  129.         }
  130.     }
  131.     maskw = ((maxsize + 15) & ~15) + 16;
  132.     fclose(fp);
  133.     checkextent();
  134. }
  135.  
  136. void
  137. checkextent()
  138. {
  139.     int largest,i;
  140.     long int scale;
  141.     double fscale;
  142.  
  143.     largest = scy - 10;
  144.     if (scx < largest) largest = scx;
  145.     if (maxextent > largest) {
  146.     fprintf(stderr,"Warning, balls are too far apart, I will re-scale.\n");
  147.     Delay(250);
  148.     fscale = (((double) largest) / ((double) maxextent));
  149.     scale = FTOI(fscale);
  150.     maxsize = 0;
  151.     maskw = 0;
  152.     maskh = 1;
  153.     for (i=0; i < nball; i++) {
  154.         balls[i].x = MULT(balls[i].x,scale);
  155.         balls[i].y = MULT(balls[i].y,scale);
  156.         balls[i].z = MULT(balls[i].z,scale);
  157.         balls[i].rad *= fscale;
  158.         balls[i].intr = balls[i].rad + 0.5;
  159.         balls[i].size = 2 * balls[i].intr + 1;
  160.         if (balls[i].size > maxsize) maxsize = balls[i].size;
  161.         if (balls[i].dup != -1 ) {
  162.             balls[i].y1 = balls[balls[i].dup].y1;
  163.             balls[i].y2 = balls[balls[i].dup].y2;
  164.         } else {
  165.             balls[i].y1 = maskh;
  166.             maskh += balls[i].size;
  167.             if (!bw) {
  168.                 balls[i].y2 = maskh;
  169.                 maskh += balls[i].size;
  170.             } else balls[i].y2 = 0;
  171.         }
  172.     }
  173.     maskw = ((maxsize + 15) & ~15) + 16;
  174.     }
  175. }
  176.  
  177. void
  178. initsin()
  179. {
  180.     int i;
  181.     float r,s;
  182.  
  183.     for (i=0; i < 360; i++) {
  184.         r = i * (3.14159/180.0);
  185.         s = sin(r);
  186.         intsin[i] = FTOI(s);
  187.         s = cos(r);
  188.         intcos[i] = FTOI(s);
  189.     }
  190. }
  191.  
  192. void
  193. isin(x,c,s)
  194. int x;        /* x is degrees */
  195. long int *c,*s;
  196. {
  197.     while (x >= 360) x -=360;
  198.     while (x < 0) x += 360;
  199.     *c = intcos[x];
  200.     *s = intsin[x];
  201. }
  202.  
  203. void
  204. initrender()
  205. {
  206.     float m;
  207.  
  208.     initsin();
  209.     ka = .2; kd = .5; ks = .65;
  210.     lx = ly = lz = 1;
  211.     m = sqrt(lx*lx + ly*ly + lz*lz);
  212.     lx /= m;
  213.     ly /= m;
  214.     lz /= m;
  215.     n = 10; r = 9.5;
  216.  
  217.     ix = FTOI(1); iy = iz = 0;
  218.     jy = FTOI(1); jx = jz = 0;
  219.     kz = FTOI(1); kx = ky = 0;
  220. }
  221.  
  222. void
  223. render()
  224. {
  225.     int i;
  226.     int x, y;
  227.     int cont, MouseMoved;
  228.     struct IntuiMessage *message;
  229.     ULONG class;
  230.     USHORT code,qual;
  231.     
  232.     for (i = 0; i < nball; i++) renderball(i);
  233.  
  234.     SetWindowTitles(mywindow,title,((char *)(-1)));
  235.     mylinecopy(sbitmap,0,10,WOFFSET);
  236.  
  237.     showballs();
  238.  
  239.     cont = 1;
  240.     while(cont) {
  241.         Wait(1 << (mywindow->UserPort->mp_SigBit));
  242.         MouseMoved = FALSE;
  243.         while(message = (struct IntuiMessage *)
  244.                 GetMsg(mywindow->UserPort)) {
  245.             class = message->Class;
  246.             code  = message->Code;
  247.             x     = message->MouseX;
  248.             y     = message->MouseY;
  249.             qual  = message->Qualifier;
  250.             ReplyMsg((struct Message *)message);
  251.  
  252.             if (class == MOUSEMOVE) MouseMoved = TRUE;
  253.             else if (class == CLOSEWINDOW) {
  254.                 cont = 0;
  255.                 break;
  256.             } else if (class == MOUSEBUTTONS)
  257.                 mbutton(code,x,y);
  258.         }
  259.         if (MouseMoved && cont) mmove(x,y,qual);
  260.     }
  261. }
  262.  
  263. void
  264. showballs()
  265. {
  266.     int i,j,sx,sy;
  267.     struct Ball *ball;
  268.     long int x,y;
  269.  
  270.     for (i = 0; i < nball; i++) {
  271.         ball = ballptr[i] = &(balls[i]);
  272.         ball->xp = ((ball->x)*ix + (ball->y)*jx + (ball->z)*kx) >> ISIZE;
  273.         ball->yp = ((ball->x)*iy + (ball->y)*jy + (ball->z)*ky) >> ISIZE;
  274.         ball->zp = ((ball->x)*iz + (ball->y)*jz + (ball->z)*kz) >> ISIZE;
  275.     }
  276.     for (i = nball-1; i > 0; i--)
  277.         for (j = 0; j < i; j++) {
  278.         if (ballptr[i]->zp < ballptr[j]->zp) {
  279.             ball = ballptr[i];
  280.             ballptr[i]=ballptr[j];
  281.             ballptr[j]=ball;
  282.         }
  283.         }
  284.  
  285.     myblankc(sbitmap,10+woffset,190+woffset,bgcolor);
  286.     if (!bw) myblankc(&tbitmap,0,SMHEIGHT-1,bgcolor);
  287.  
  288.     for (i = 0; i < nball; i++) {
  289.         ball = ballptr[i];
  290.         x = (ball->xp + (1 << (LSIZE - 1))) >> LSIZE;
  291.         y = (ball->yp + (1 << (LSIZE - 1))) >> LSIZE;
  292.         sx = scx + x - ball->intr;
  293.         sy = scy - y - ball->intr;
  294.  
  295.              BltBitMask(&ibitmap,0,ball->y1,
  296.                  sbitmap,sx,sy+woffset,
  297.                 &mbitmap,0,ball->y1,0,
  298.                 ball->size,ball->size);
  299.         if (!bw) {
  300.              BltBitMask(&ibitmap,0,ball->y2,
  301.                 &tbitmap,sx,sy,
  302.                 &mbitmap,0,ball->y1,0,
  303.                 ball->size,ball->size);
  304.              BltBitMask(&tbitmap,sx+ball->intr+1,sy,
  305.                  sbitmap,sx+ball->intr+1,sy+woffset,
  306.                 &mbitmap,ball->intr,ball->y2,0,
  307.                 ball->intr+1,ball->size);
  308.         }
  309.     }
  310.     flip();
  311. }
  312.  
  313. void
  314. scrollx(d)
  315. int d;
  316. {
  317.     long int c,s;
  318.     long int t;
  319.  
  320.     isin(-d,&c,&s);
  321.  
  322.     t  = (c * ix  -  s * iz) >> ISIZE;
  323.     iz = (s * ix  +  c * iz) >> ISIZE;
  324.     ix = t;
  325.     t  = (c * jx  -  s * jz) >> ISIZE;
  326.     jz = (s * jx  +  c * jz) >> ISIZE;
  327.     jx = t;
  328.     t  = (c * kx  -  s * kz) >> ISIZE;
  329.     kz = (s * kx  +  c * kz) >> ISIZE;
  330.     kx = t;
  331. }
  332. void
  333. scrolly(d)
  334. int d;
  335. {
  336.     long int c,s;
  337.     long int t;
  338.  
  339.     isin(d,&c,&s);
  340.  
  341.     t  = (c * iy  -  s * iz) >> ISIZE;
  342.     iz = (s * iy  +  c * iz) >> ISIZE;
  343.     iy = t;
  344.     t  = (c * jy  -  s * jz) >> ISIZE;
  345.     jz = (s * jy  +  c * jz) >> ISIZE;
  346.     jy = t;
  347.     t  = (c * ky  -  s * kz) >> ISIZE;
  348.     kz = (s * ky  +  c * kz) >> ISIZE;
  349.     ky = t;
  350. }
  351. void
  352. scrollz(d)
  353. int d;
  354. {
  355.     long int c,s;
  356.     long int t;
  357.  
  358.     isin(d,&c,&s);
  359.  
  360.     t  = (c * iy  -  s * ix) >> ISIZE;
  361.     ix = (s * iy  +  c * ix) >> ISIZE;
  362.     iy = t;
  363.     t  = (c * jy  -  s * jx) >> ISIZE;
  364.     jx = (s * jy  +  c * jx) >> ISIZE;
  365.     jy = t;
  366.     t  = (c * ky  -  s * kx) >> ISIZE;
  367.     kx = (s * ky  +  c * kx) >> ISIZE;
  368.     ky = t;
  369. }
  370.  
  371. void
  372. mbutton(code,x,y)
  373. int code, x, y;
  374. {
  375.     if (code == SELECTDOWN) {
  376.         xstart = x;
  377.         ystart = y;
  378.     } else if (code == SELECTUP) {
  379.         xstart = ystart = -1;
  380.     }
  381. }
  382.  
  383. void
  384. mmove(x,y,qual)
  385. int x,y;
  386. USHORT qual;
  387. {
  388.     register int shift;
  389.  
  390.     if (qual & 0x30) shift = 2;        /* L-ALT, R-ALT */
  391.     else if (qual & 0x07) shift = 0;    /* SHIFT */
  392.     else shift = 1;
  393.  
  394.     if (xstart != -1) {
  395.         if (qual & 0x08)        /* CNTL */
  396.             scrollz((x - xstart)<<shift);
  397.         else {
  398.             scrolly((y - ystart)<<shift);
  399.             scrollx((x - xstart)<<shift);
  400.         }
  401.  
  402.         xstart = x;
  403.         ystart = y;
  404.  
  405.         showballs();
  406.     }
  407. }
  408.  
  409. void
  410. flip()
  411. {
  412.     Forbid();
  413.     WaitTOF();
  414.     WaitBlit();
  415.     Disable();
  416.     if (woffset) {
  417.         vp->RasInfo->RyOffset = WOFFSET;
  418.     } else {
  419.         vp->RasInfo->RyOffset = 0;
  420.     }
  421.     ScrollVPort(vp);
  422.     Enable();
  423.     Permit();
  424.     if (woffset) {
  425.         woffset = 0;
  426.     } else {
  427.         woffset = WOFFSET;
  428.     } 
  429. }
  430.  
  431. void
  432. renderball(j)
  433. int j;
  434. {
  435.     struct Ball *ball;
  436.     int intr, size, y1, y2;
  437.     int x, y, xp, yp, ired, igreen, iblue;
  438.     int start;
  439.     float nx, ny, nz, rz, id, is;
  440.     
  441.     ball = balls+j;
  442.  
  443.     if (ball->dup != -1) return;
  444.  
  445.     y1 = ball->y1;
  446.     y2 = ball->y2;
  447.     intr = ball->intr;
  448.     size = ball->size;
  449.  
  450. /* special mask is offset -1 in x */
  451.  
  452.     for (y = 0; y < size; y++) {
  453.         start = 0;
  454.         for (x = 0; x < size; x++) {
  455.         xp = x - intr;
  456.         yp = intr - y;
  457.         nz = (ball->rad * ball->rad) - (xp * xp) - (yp * yp);
  458.         if (nz >= 0.0) {
  459.             mywritepixel1(&mbitmap,x,y+y1);
  460.             nx = xp / ball->rad;
  461.             ny = yp / ball->rad;
  462.             nz = sqrt(nz) / ball->rad;
  463.             id = lx*nx + ly*ny + lz*nz;    /* diffuse intensity */
  464.             rz = (nz + nz) * id - lz;
  465.             if (rz < 0) rz = 0;
  466.             is = ks * pow(rz,n);
  467.             id = ka + kd * id;
  468.             SETANDBOUND(ired,  (id * ball->r + is));
  469.             SETANDBOUND(igreen,(id * ball->g + is));
  470.             SETANDBOUND(iblue, (id * ball->b + is));
  471.             setcolor(x,y+y1,y+y2,ired,iblue,igreen,!start);
  472.             if (start == 0) start = 1;
  473.         } else if (start == 1) {
  474.             dolast();
  475.             if (!bw) mywritepixel1(&mbitmap,x-1,y+y2);
  476.             start = 2;
  477.         }
  478.         }
  479.         if (start == 1) {
  480.         dolast();
  481.         if (!bw) mywritepixel1(&mbitmap,x-1,y+y2);
  482.         }
  483.     }
  484. }
  485.