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