home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff314.lha / zc / zc.lzh / Examples / Amiga / Balls / balls.c < prev    next >
C/C++ Source or Header  |  1989-06-06  |  14KB  |  505 lines

  1. #include <exec/types.h>
  2. #include <graphics/gfxbase.h>
  3. #include <intuition/intuition.h>
  4. #undef   NULL
  5. #include <math.h>
  6. #include <stdio.h>
  7.  
  8. void *OpenLibrary();
  9. struct Screen *OpenScreen();
  10. struct Window *OpenWindow();
  11. struct IntuiMessage *GetMsg();
  12. double sin(), cos(), abs(), sqrt(), pow();
  13.  
  14. /*
  15. **    balls - a simulation of that kinetic thingy with three-d
  16. **            smooth shaded  spheres with diffuse and specular
  17. **            reflections. It'd be  nice if someone could  add
  18. **            sound. A good demonstration  of  using  the  ffp
  19. **            math subroutines.  I plan to add texture mapping
  20. **            to the spheres in the future.
  21. **
  22. **
  23. **    perry s. kivolowitz - ihnp4!ptsfa!well!perry
  24. **
  25. **    not to be distributed for commercial purposes. any
  26. **    distribution must include this notice, please.
  27. **
  28. */
  29.  
  30. #ifdef   MY_DEBUG
  31. FILE *dfp;
  32. #endif
  33.  
  34. #define  RADIUS   20       /* radius of the balls ve are goink to draw */
  35. #define  DEPTH    5L        /* number of pixel planes */
  36. #define  NMAP     32       /* 2 to the DEPTH power   */
  37. #define  AMBIENT  2        /* how much light on the dark side ofthe moon */
  38. #define  NSTEPS   6        /* how many discreet frames in bouncers */
  39.  
  40. #define  SH       200      /* screen height */
  41. #define  SW       320      /* screen width  */
  42. #define  WH       (SH-10)  /* window height */
  43. #define  WW       SW       /* window width  */
  44. #define  MW       (WW / 2) /* middle of window */
  45.  
  46. #define  D        (2 * RADIUS)
  47. #define  DL          (2L * RADIUS)
  48.  
  49. struct IntuitionBase *IntuitionBase;
  50. struct GfxBase *GfxBase;
  51. long    MathBase;
  52. long    MathTransBase;
  53.  
  54. int is_cli = 0;
  55.  
  56. struct Window *w;                  /* window structure returned by exec */
  57. struct Screen *s;                  /* screen structure returned by exec */
  58. struct ColorMap *color_map;        /* pointer to c_map returned by exec */
  59. short  displacements[D];           /* place for sphere's scanline dx's  */
  60. short  surface[D];                 /* place for spehre's scanline dz's  */
  61.  
  62. struct bouncer {
  63.     struct RastPort rp;
  64.     struct BitMap   bm;
  65.     long sx , sy;
  66. } left[NSTEPS] , right[NSTEPS];
  67.  
  68. struct point {
  69.     double x;
  70.     double y;
  71.     double z;
  72. } light;
  73.  
  74. /*
  75. ** mask is a bit mask of things that I should close or deallocate
  76. ** when the program terminates for  any reason.  after opening or
  77. ** allocating some resource set the appropriate bit in mask.
  78. */
  79.  
  80. unsigned int mask = 0;
  81.  
  82. #define  INTUITION   0x00000001
  83. #define  GRAPHICS    0x00000002
  84. #define  SCREEN      0x00000004
  85. #define  WINDOW      0x00000008
  86. #define  COLORMAP    0x00000010
  87. #define  MATH        0x00000020
  88. #define  MATHTRANS   0x00000040
  89.  
  90. int rastcount = 0;      /* easy way to free rasters at termination */
  91.  
  92. struct NewScreen ns = {    /*****************/
  93.     0 ,                     /* LeftEdge      */
  94.     0 ,                     /* TopEdge       */
  95.     SW ,                    /* Width         */
  96.     SH ,                    /* Height        */
  97.     DEPTH ,                 /* Depth         */
  98.     0 ,                     /* DetailPen     */
  99.     1 ,                     /* BlockPen      */
  100.     0 ,                     /* ViewModes     */
  101.     CUSTOMSCREEN ,          /* Type          */
  102.     NULL ,                  /* *Font         */
  103.     (UBYTE *)" spheres by p.s.kivolowitz" ,       /* *DefaultTitle */
  104.     NULL ,                  /* *Gadgets      */
  105.     NULL                    /* *CustomBitMap */
  106. };                         /*****************/
  107.  
  108. struct NewWindow nw = {    /*****************/
  109.     0 ,                     /* LeftEdge      */
  110.     10 ,                    /* TopEdge       */
  111.     WW ,                    /* Width         */
  112.     WH ,                    /* Height        */
  113.     -1 ,                    /* DetailPen     */
  114.     -1 ,                    /* BlockPen      */
  115.     CLOSEWINDOW ,           /* IDCMP---Flags */
  116.     WINDOWCLOSE             /*   F           */
  117.     | BACKDROP              /*     l         */
  118.     | BORDERLESS            /*       a       */
  119.     | NOCAREREFRESH         /*         g     */
  120.     | ACTIVATE ,            /*           s   */
  121.     NULL ,                  /* *FirstGadget  */
  122.     NULL ,                  /* *CheckMark    */
  123.     (UBYTE *)"(still under development)" ,/* *Title        */
  124.     NULL ,                  /* *Screen       */ /* to be filled in */
  125.     NULL ,                  /* *BitMap       */
  126.     0 ,                     /* MinWidth      */
  127.     0 ,                     /* MinHeight     */
  128.     0 ,                     /* MaxWidth      */
  129.     0 ,                     /* MaxHeight     */
  130.     CUSTOMSCREEN            /* Type          */
  131. };                         /*****phew!!!*****/
  132.  
  133. double
  134. degrad(degrees)
  135. double degrees;
  136. {
  137.     double pi;
  138.  
  139.     pi = 335.0 / 113.0;   /* chinese approximation */
  140.     pi *= degrees;
  141.     return(pi/180.0);
  142. }
  143.  
  144. main(argc , argv)
  145. char *argv[];
  146. {
  147.     int i;
  148.     struct IntuiMessage *message;
  149.     if (argc) is_cli = 1;
  150.  
  151. #ifdef   MY_DEBUG
  152.     if ((dfp = fopen("debug.file" , "w")) == NULL) {
  153.        if (is_cli) printf("can't open debugging file\n");
  154.        exit(1);
  155.     }
  156.     fprintf(dfp,"debugging information\n");
  157.     fflush(dfp);
  158. #endif
  159.  
  160.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L)))
  161.     {
  162.        if (is_cli) printf("no graphics library!!!\n");
  163.        close_things();
  164.        exit(1);
  165.     }
  166.     mask |= GRAPHICS;
  167.  
  168.  if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0L)))
  169.     {
  170.        if (is_cli) printf("no intuition here!!\n");
  171.        close_things();
  172.        exit(1);
  173.     }
  174.     mask |= INTUITION;
  175.  
  176.     if ((MathBase = (long)OpenLibrary("mathffp.library" , 0L)) == NULL) {
  177.        if (is_cli) printf("couldn't open mathffp library\n");
  178.        close_things();
  179.        exit(1);
  180.     }
  181.     mask |= MATH;
  182.  
  183.     if ((MathTransBase = (long)OpenLibrary("mathtrans.library" , 0L)) == NULL) {
  184.        if (is_cli) printf("couldn't open mathtrans library\n");
  185.        close_things();
  186.        exit(1);
  187.     }
  188.     mask |= MATHTRANS;
  189.  
  190.     allocate_rasters();
  191.  
  192.     if ((s = (struct Screen *) OpenScreen(&ns)) == (struct Screen *) NULL) {
  193.        if (is_cli) printf("could not open the screen!\n");
  194.        close_things();
  195.        exit(2);
  196.     }
  197.     mask |= SCREEN;
  198.     nw.Screen = s;
  199.  
  200.     if((w = (struct Window *)OpenWindow(&nw)) == (struct Window *) NULL) {
  201.        if (is_cli) printf("could not open the window!\n");
  202.        close_things();
  203.        exit(2);
  204.     }
  205.     mask |= WINDOW;
  206.  
  207.     init_color_map();
  208.  
  209.     light.x = 0.0;
  210.     light.y = light.x + 150.0 - light.x;
  211.     light.z = light.x + 25.0 - light.x;
  212.  
  213.     bres(RADIUS , displacements);
  214.  
  215.     /*
  216.     ** make the three bottom balls
  217.     */
  218.  
  219.     make_ball(w->RPort , MW - D , WH - RADIUS , -D , 0, 0);
  220.     make_ball(w->RPort , MW     , WH - RADIUS ,  0 , 0, 0);
  221.     make_ball(w->RPort , MW + D , WH - RADIUS ,  D , 0, 0);
  222.  
  223.     make_rotated_ball(&left[0] , -15 , MW - 2 * D , 10 , WH - 10 - RADIUS);
  224.     make_rotated_ball(&right[0] , 15 , MW + 2 * D , 10 , WH - 10 - RADIUS);
  225.     make_rotated_ball(&left[1] , -14 , MW - 2 * D , 10 , WH - 10 - RADIUS);
  226.     make_rotated_ball(&right[1] , 14 , MW + 2 * D , 10 , WH - 10 - RADIUS);
  227.     make_rotated_ball(&left[2] , -12 , MW - 2 * D , 10 , WH - 10 - RADIUS);
  228.     make_rotated_ball(&right[2] , 12 , MW + 2 * D , 10 , WH - 10 - RADIUS);
  229.     make_rotated_ball(&left[3] , -9  , MW - 2 * D , 10 , WH - 10 - RADIUS);
  230.     make_rotated_ball(&right[3],  9  , MW + 2 * D , 10 , WH - 10 - RADIUS);
  231.     make_rotated_ball(&left[4] , -5  , MW - 2 * D , 10 , WH - 10 - RADIUS);
  232.     make_rotated_ball(&right[4],  5  , MW + 2 * D , 10 , WH - 10 - RADIUS);
  233.     make_rotated_ball(&left[5] ,  0  , MW - 2 * D , 10 , WH - 10 - RADIUS);
  234.     make_rotated_ball(&right[5],  0  , MW + 2 * D , 10 , WH - 10 - RADIUS);
  235.  
  236.     ClipBlit(&left[0].rp,0L,0L,w->RPort,left[0].sx,left[0].sy,DL,DL,0xC0L);
  237.     ClipBlit(&right[NSTEPS-1].rp,0L,0L,w->RPort,right[NSTEPS-1].sx,
  238.                right[NSTEPS-1].sy,DL,DL,0xC0L);
  239.  
  240.     message = (struct IntuiMessage *) GetMsg(w->UserPort);
  241.     while (!message || (message->Class != CLOSEWINDOW)) {
  242.        for (i = 1; i < NSTEPS; i++) {
  243.           Delay(2L);
  244.           WaitBOVP(&s->ViewPort);
  245.           clear_rect(w->RPort,left[i-1].sx,left[i-1].sy,D,D);
  246.           ClipBlit(&left[i].rp,0L,0L,w->RPort,left[i].sx,left[i].sy,
  247.                                                       DL,DL,0xC0L);
  248.        }
  249.        for (i = NSTEPS-2; i >= 0; i--) {
  250.           WaitBOVP(&s->ViewPort);
  251.           clear_rect(w->RPort,right[i+1].sx,right[i+1].sy,D,D);
  252.           ClipBlit(&right[i].rp,0L,0L,w->RPort,right[i].sx,right[i].sy,
  253.                                                       DL,DL,0xC0L);
  254.           Delay(2L);
  255.        }
  256.        Delay(1L);
  257.        for (i = 1; i < NSTEPS; i++) {
  258.           Delay(2L);
  259.           WaitBOVP(&s->ViewPort);
  260.           clear_rect(w->RPort,right[i-1].sx,right[i-1].sy,D,D);
  261.           ClipBlit(&right[i].rp,0L,0L,w->RPort,right[i].sx,right[i].sy,
  262.                                                       DL,DL,0xC0L);
  263.        }
  264.        for (i = NSTEPS-2; i >= 0; i--) {
  265.           WaitBOVP(&s->ViewPort);
  266.           clear_rect(w->RPort,left[i+1].sx,left[i+1].sy,D,D);
  267.           ClipBlit(&left[i].rp,0L,0L,w->RPort,left[i].sx,left[i].sy,
  268.                                                       DL,DL,0xC0L);
  269.           Delay(2L);
  270.        }
  271.        Delay(1L);
  272.        message = (struct IntuiMessage *) GetMsg(w->UserPort);
  273.     }
  274.  
  275. #ifdef   MY_DEBUG
  276.     fclose(dfp);
  277. #endif
  278.  
  279.     close_things();
  280.     exit(0);
  281. }
  282.  
  283. clear_rect(rp , sx , sy , dx , dy)
  284. struct RastPort *rp;
  285. long sx,sy;
  286. short dx,dy;
  287. {
  288.     ClipBlit(rp,sx,sy,rp,sx,sy,(long)dx,(long)dy,0x20L);
  289. }
  290.  
  291. make_rotated_ball(b , degrees , cx , cy , length)
  292. struct bouncer *b;
  293. short degrees , cx , cy , length;
  294. {
  295.     int dx , dy;
  296.  
  297.     dx = length * sin(degrad(abs((double)degrees)));
  298.     dy = length * cos(degrad(abs((double)degrees)));
  299.     b->sx = cx + (degrees < 0 ? -dx : dx);
  300.     b->sy = cy + dy;
  301.     make_ball(&b->rp, RADIUS, RADIUS, (short)(b->sx-MW),
  302.                                             (short)(WH-RADIUS-b->sy), 0);
  303.     b->sx -= RADIUS;
  304.     b->sy -= RADIUS;
  305. }
  306.  
  307. close_things()
  308. {
  309.     if (rastcount) deallocate_rasters();
  310.     if (mask & WINDOW)    CloseWindow(w);
  311.     if (mask & SCREEN)    CloseScreen(s);
  312.     if (mask & GRAPHICS)  CloseLibrary(GfxBase);
  313.     OpenWorkBench();
  314.     if (mask & INTUITION) CloseLibrary(IntuitionBase);
  315. }
  316.  
  317. init_color_map()
  318. {
  319.     static short map_values[NMAP] = {
  320.        /* format 0x0RGB */   /* ooooooooh ychhhhhh! fix this later! */
  321.        /* 0  */  0x0430 ,
  322.        /* 1  */  0x0FFF ,
  323.        /* 2  */  0x0F01 ,
  324.        /* 3  */  0x0F11 ,
  325.        /* 4  */  0x0F12 ,
  326.        /* 5  */  0x0F22 ,
  327.        /* 6  */  0x0F23 ,
  328.        /* 7  */  0x0F33 ,
  329.        /* 8  */  0x0F34 ,
  330.        /* 9  */  0x0F44 ,
  331.        /* 10 */  0x0F45 ,
  332.        /* 11 */  0x0F55 ,
  333.        /* 12 */  0x0F56 ,
  334.        /* 13 */  0x0F66 ,
  335.        /* 14 */  0x0F67 ,
  336.        /* 15 */  0x0F77 ,
  337.        /* 16 */  0x0F78 ,
  338.        /* 17 */  0x0F88 ,
  339.        /* 18 */  0x0F89 ,
  340.        /* 19 */  0x0F99 ,
  341.        /* 20 */  0x0F9A ,
  342.        /* 21 */  0x0FAA ,
  343.        /* 22 */  0x0FAB ,
  344.        /* 23 */  0x0FBB ,
  345.        /* 24 */  0x0FBC ,
  346.        /* 25 */  0x0FCC ,
  347.        /* 26 */  0x0FCD ,
  348.        /* 27 */  0x0FDD ,
  349.        /* 28 */  0x0FDE ,
  350.        /* 29 */  0x0FEE ,
  351.        /* 30 */  0x0FEF ,
  352.        /* 31 */  0x0FFF
  353. };
  354.     LoadRGB4(&s->ViewPort , map_values , (long)NMAP);
  355. }
  356.  
  357. normalize(p)
  358. struct point *p;
  359. {
  360.     double length;
  361.  
  362.     length = sqrt((p->x * p->x) + (p->y * p->y) + (p->z * p->z));
  363.     p->x /= length;
  364.     p->y /= length;
  365.     p->z /= length;
  366. }
  367.  
  368.  
  369. make_ball(rp , basex , basey , cx , cy , cz)
  370. struct RastPort *rp;
  371. short basex, basey, cx, cy, cz;
  372. {
  373.     long I;
  374.     int scanline;
  375.     long x , y;
  376.     struct point H , l;
  377.     struct point pnt;
  378.     double tmp , rad , d;
  379.  
  380.  
  381.     rad = 1.0/RADIUS;
  382.  
  383.     basex -= RADIUS;
  384.     basey -= RADIUS;
  385.     l.x = light.x-(double)cx;  /* translate light source to */
  386.     l.y = light.y-(double)cy;  /* make center of sphere the */
  387.     l.z = light.z-(double)cz;  /* origin relative to light  */
  388.     normalize(&l);
  389.  
  390.     for (scanline = 0; scanline < 2 * RADIUS; scanline++) {
  391.        register short r;
  392.        register short i;
  393.  
  394.        r = displacements[scanline];
  395.        y = scanline + basey;
  396.        pnt.y = (RADIUS - scanline) * rad;
  397.        bres(r , surface);
  398.        for (i = 0; i < 2 * r; i++) {
  399.           pnt.x = (-r + i) * rad;
  400.           pnt.z = surface[i] * rad;
  401.           d = (pnt.z * l.z) + (pnt.y * l.y) + (pnt.x * l.x);
  402.           I = AMBIENT;
  403.           if (d > 0.0) {
  404.              I += d * (NMAP - AMBIENT);
  405.              H.x = l.x;
  406.              H.y = l.y;
  407.              H.z = l.z + 1.0;
  408.              normalize(&H);
  409.              /* reusing d */
  410.              d = (H.x * pnt.x) + (H.y * pnt.y) + (H.z * pnt.z);
  411.              d = pow(d, 12.0);
  412.              if (d > 0.0)
  413.                  I += d * 12.0;
  414.           }
  415.           x = RADIUS - r + i + basex;
  416.           if (I >= NMAP) I = NMAP - 1;
  417.           SetAPen(rp , I);
  418.           WritePixel(rp , x , y);
  419.        }
  420.     }
  421. }
  422.  
  423. allocate_rasters()
  424. {
  425.     int i , j;
  426.     void *AllocRaster();
  427.  
  428.     for (i = 0; i < NSTEPS; i++) {
  429.        InitRastPort(&left[i].rp);
  430.        InitRastPort(&right[i].rp);
  431.        InitBitMap(&left[i].bm , DEPTH , DL , DL);
  432.        InitBitMap(&right[i].bm , DEPTH , DL , DL);
  433.        for (j = 0; j < DEPTH; j++) {
  434.           left[i].bm.Planes[j] = AllocRaster(DL , DL);
  435.           if (left[i].bm.Planes[j] == NULL) {
  436. outer:      if (is_cli) printf("cannot allocate raster space\n");
  437.              close_things();
  438.              exit(1);
  439.           }
  440.           rastcount++;
  441.           right[i].bm.Planes[j] = AllocRaster(DL , DL);
  442.           if (right[i].bm.Planes[j] == NULL) goto outer;
  443.           rastcount++;
  444.        }
  445.        left[i].rp.BitMap = &left[i].bm;
  446.        right[i].rp.BitMap = &right[i].bm;
  447.        SetRast(&left[i].rp , 0L);
  448.        SetRast(&right[i].rp , 0L);
  449.     }
  450. }
  451.  
  452. deallocate_rasters()
  453. {
  454.     int i , j;
  455.  
  456.     for (i = 0; i < NSTEPS && rastcount >= 0; i++) {
  457.        for (j = 0; j < DEPTH && rastcount >= 0; j++) {
  458.           if (rastcount-- == 0) continue;
  459.           FreeRaster(left[i].bm.Planes[j] , DL , DL);
  460.           if (rastcount-- == 0) continue;
  461.           FreeRaster(right[i].bm.Planes[j] , DL , DL);
  462.        }
  463.     }
  464. }
  465.  
  466. /*
  467. ** b r e s . c
  468. **
  469. ** perry s. kivolowitz - ihnp4!ptsfa!well!perry
  470. **
  471. ** not to be distritbuted for commercial use. any distribution
  472. ** must included this notice, please.
  473. **
  474. ** generate radial  displacements according to bresenham's circle
  475. ** algorithm. suitable for running twice, giving a fast spherical
  476. ** surface.
  477. **
  478. */
  479.  
  480. bres(r , array)
  481. register short *array;
  482. register short r;
  483. {
  484.     register short x , y , d;
  485.  
  486.     x = 0;
  487.     y = r;
  488.     d = 3 - 2 * r;
  489.     while (x < y) {
  490.         *(array + r - y) = x;
  491.         *(array + r - x) = y;
  492.         *(array + r + y - 1) = x;
  493.         *(array + r + x - 1) = y;
  494.         if (d < 0) d += 4 * x + 6;
  495.         else d += 4 * (x - y--) + 10;
  496.         x++;
  497.     }
  498.     if (x == y) {
  499.         *(array + r - y) = x;
  500.         *(array + r + y - 1) = x;
  501.     }
  502. }
  503.  
  504.  
  505.