home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 420.lha / 3droll.c < prev    next >
C/C++ Source or Header  |  1990-09-20  |  8KB  |  325 lines

  1. /* Use "lc -Lm -cw 3droll.c" to compile (Lattice) */
  2.  
  3. /* (C) 1990 Keith Gravlin */
  4.  
  5. /* Program draws a three-d object which can be manipulated with the mouse. */
  6. /* Left and right (pick button up) will adjust yaw. */
  7. /* Up and down (pick button up) adjust pitch. */
  8. /* Left and right (pick button down) adjust roll. */
  9. /* Up and down (pick button down) adjust zoom in/out. */
  10.  
  11. #include "exec/types.h"
  12. #include "exec/memory.h"
  13. #include "intuition/intuition.h"
  14. #include "graphics/gfxmacros.h"
  15. #include "math.h"
  16.  
  17. long GfxBase = NULL;
  18. long IntuitionBase = NULL;
  19.  
  20. extern struct Screen *OpenScreen();
  21. extern struct Window *OpenWindow();
  22.  
  23. struct Screen *MyScreen = NULL;
  24. struct Window *MyWindow = NULL;
  25.  
  26. struct IntuiMessage *MyIntuiMessage = NULL;
  27. struct IntuiMessage IntuiMessageBuffer;
  28.  
  29. struct RastPort *MyRastPort = NULL;
  30.  
  31.  
  32. #define SWIDTH 640
  33. #define SHEIGHT 400
  34. #define SDEPTH 1
  35.  
  36. struct NewScreen MyScreenData = {
  37. 0,0,                /* start postion */
  38. SWIDTH,SHEIGHT,SDEPTH,        /* width, height, depth */
  39. 0,1,                /* detail pen, block pen */
  40. HIRES | LACE,            /* viewing mode */
  41. CUSTOMSCREEN,            /* screen type */
  42. NULL,                /* font to use */
  43. NULL,                /* screen title */
  44. NULL                /* pointer to gadgets */
  45. };
  46.  
  47. #define    WWIDTH SWIDTH
  48. #define    WHEIGHT SHEIGHT
  49.  
  50. struct    NewWindow MyWindowData = {
  51. 0,0,                /* upper left corner of window */
  52. WWIDTH, WHEIGHT,        /* width, height */
  53. 0,1,                /* detail pen, block pen */
  54. CLOSEWINDOW | MOUSEBUTTONS | MOUSEMOVE | REFRESHWINDOW,    /* IDCMP flags */
  55. REPORTMOUSE | WINDOWCLOSE | BORDERLESS | SIMPLE_REFRESH, /* window flags */
  56. NULL,                /* pointer to first gadget */
  57. NULL,                /* pointer to checkmark */
  58. "Box Roll",            /* window title */
  59. NULL,                /* screen pointer to screen */
  60. NULL,                /* pointer to superbitmap */
  61. 0,0,                /* MinWidth,MinHeight */
  62. 0,0,                /* MaxWidth,MaxHeight */
  63. CUSTOMSCREEN };
  64.  
  65. double    TransX = 0.0, TransY = 0.0, TransZ = -235.0;    /* translation variables */
  66. double    DisplayX = 0.0, DisplayY = 0.0;    /* for display coords */
  67. double    Distortion = 1500.0;    /* distortion/perspective factor */
  68. double    Yaw = 0.0;
  69. double    Roll = 0.0;
  70. double    Pitch = 0.0;
  71. double    SinYaw, CosYaw;        /* intermediate values */
  72. double    SinRoll, CosRoll;
  73. double    SinPitch, CosPitch;
  74.  
  75. int QuitFlag = FALSE;        /* set TRUE to quit */
  76. int PickButtonDown = FALSE;    /* holds current state of pick button */
  77. int FixedX = NULL, FixedY = NULL;    /* holds fixed part of position */
  78.  
  79. /* Add/delete/change triplets to produce things other than boxes. */
  80. /* Have fun ! */
  81. int Triplets[][3] = {
  82.     -5,-5,5,
  83.     -5,5,5,
  84.     5,5,5,
  85.     5,-5,5,
  86.     -5,-5,5,
  87.     -5,-5,-5,
  88.     -5,5,-5,
  89.     -5,5,5,
  90.     -5,5,-5,
  91.     5,5,-5,
  92.     5,5,5,
  93.     5,5,-5,
  94.     5,-5,-5,
  95.     5,-5,5,
  96.     5,-5,-5,
  97.     -5,-5,-5,
  98.     5,5,-5,
  99.     5,-5,-5,
  100.     -5,5,-5
  101. };
  102.  
  103. #define    TRIPLETCOUNT sizeof(Triplets)/(3*sizeof(int))
  104.  
  105.  
  106. void    CalcYRP()    /* calc values for current rotations */
  107. {
  108.     SinYaw = sin(Yaw);
  109.     CosYaw = cos(Yaw);
  110.     SinRoll = sin(Roll);
  111.     CosRoll = cos(Roll);
  112.     SinPitch = sin(Pitch);
  113.     CosPitch = cos(Pitch);
  114. }
  115.  
  116. void    Calc3D(double x,double y,double z)    /* here's my work Ma'm */
  117. {
  118.     double TempX, TempY, TempZ;
  119.     
  120.     TempX = (CosYaw*x)-(SinYaw*z);
  121.     TempY = (CosRoll*y)-(SinRoll*TempX);
  122.     TempZ = (SinYaw*x)+(CosYaw*z);
  123.     x = (CosRoll*TempX)+(SinRoll*y)+TransX;
  124.     y = (SinPitch*TempZ)+(CosPitch*TempY)+TransY;
  125.     z = (CosPitch*TempZ)-(SinPitch*TempY)+TransZ;
  126.     
  127.     DisplayX = ((Distortion*x/z)+319)*WWIDTH/640.0;    /* adjust aspect */
  128.     DisplayY = ((Distortion*y/z)+239)*WHEIGHT/480.0;
  129. }
  130.  
  131. void    CalcBox(boxarray)
  132. SHORT    *boxarray;
  133. {
  134.     int    x;
  135.  
  136.     for (x=0;x<TRIPLETCOUNT;x++) {        /* for each corner */
  137.         Calc3D((double)Triplets[x][0],(double)Triplets[x][1],(double)Triplets[x][2]);
  138.         boxarray[x*2] = DisplayX;
  139.         boxarray[x*2+1] = DisplayY;
  140.     }        
  141. }
  142.  
  143. void    HandleEvent()
  144. {
  145.     switch(MyIntuiMessage->Class) {
  146.         case MOUSEMOVE:
  147.             MouseMove();
  148.             break;
  149.         case MOUSEBUTTONS:
  150.             switch(MyIntuiMessage->Code) {
  151.                 case SELECTDOWN:
  152.                     PickButtonDown = TRUE;
  153.                     break;
  154.                 case SELECTUP:
  155.                     PickButtonDown = FALSE;
  156.                     break;
  157.                 default:
  158.                     break;
  159.             }
  160.             ReplyMsg(MyIntuiMessage);
  161.             MyIntuiMessage = NULL;
  162.             break;
  163.         case REFRESHWINDOW:
  164.             ReplyMsg(MyIntuiMessage);
  165.             MyIntuiMessage = NULL;
  166.             break;        
  167.         case CLOSEWINDOW:
  168.             ReplyMsg(MyIntuiMessage);
  169.             MyIntuiMessage = NULL;
  170.             QuitFlag = TRUE;
  171.             break;
  172.         default:
  173.             ReplyMsg(MyIntuiMessage);
  174.             MyIntuiMessage = NULL;
  175.             break;
  176.     }
  177. }
  178.  
  179. #define WIDTHCENTER (WWIDTH-1)/2
  180. #define    HEIGHTCENTER (WHEIGHT-1)/2
  181.  
  182. MouseMove()
  183. {
  184.     int MyMouseX = NULL, MyMouseY = NULL;
  185.     
  186.     SwallowMoves(10);    /* suck up rapid movements */
  187.  
  188.     MyMouseX = IntuiMessageBuffer.MouseX - WIDTHCENTER;
  189.     MyMouseY = IntuiMessageBuffer.MouseY - HEIGHTCENTER;
  190.  
  191. /* Uncommenting the following code will fix x or y, whichever goes */
  192. /* non-zero first. Returning that coord to zero (center of screen) will */
  193. /* free it and allow the other to become fixed. */
  194. /* This was just a way to play with one axis at a time. */
  195. /*    if (FixedX && MyMouseX)
  196.         MyMouseX = FixedX;
  197.     else {
  198.         FixedX = NULL;
  199.         if (FixedY && MyMouseY)
  200.             MyMouseY = FixedY;
  201.         else {
  202.             FixedY = NULL;
  203.             FixedX = MyMouseX;
  204.         }
  205.     }
  206.     if (!FixedX)
  207.         FixedY = MyMouseY;
  208. */
  209.     if (PickButtonDown) {
  210.         Roll = MyMouseX * 6.283 / WWIDTH;
  211.         TransZ = MyMouseY - HEIGHTCENTER - 35;
  212.     }
  213.     else {
  214.         Yaw = MyMouseX * 6.283 / WWIDTH;
  215.         Pitch = -MyMouseY * 6.283 / WHEIGHT;
  216.     }
  217. }
  218.  
  219. /* Calling this function with a lower count will decrease jerkyness but */
  220. /* increase the number of redraws, thus causing slower response. */
  221. /* Have it your way ! */
  222. SwallowMoves(count)    /* swallow up to 'count' rapid mouse moves */
  223. int    count;
  224. {
  225.     int i, j;
  226.     UBYTE *source, *dest;
  227.     struct IntuiMessage *NewIntuiMessage = NULL;
  228.  
  229.     for (j=0;j<count;j++) {
  230.         if (NewIntuiMessage = (struct IntuiMessage *)GetMsg(MyWindow->UserPort)) {
  231.             if (NewIntuiMessage->Class == MOUSEMOVE) {
  232.                 ReplyMsg(MyIntuiMessage);
  233.                 MyIntuiMessage = NewIntuiMessage;
  234.                 NewIntuiMessage = NULL;
  235.             }
  236.             else
  237.                 break;
  238.         }
  239.         else
  240.             break;
  241.     }                
  242.     source = (UBYTE *)MyIntuiMessage;
  243.     dest = (UBYTE *)&IntuiMessageBuffer;
  244.     for (i=0;i<sizeof(struct IntuiMessage);i++)
  245.         *dest++ = *source++;
  246.     ReplyMsg(MyIntuiMessage);
  247.     MyIntuiMessage = NewIntuiMessage;
  248. }
  249.  
  250. main()    /* street USA */
  251. {
  252.     SHORT    BoxArray1[TRIPLETCOUNT*2], BoxArray2[TRIPLETCOUNT*2];
  253.     SHORT    *OldBox, *NewBox;
  254.  
  255.     if (!(GfxBase = OpenLibrary("graphics.library",0))) {
  256.         printf("Unable to open graphics library\n");
  257.         CleanUp(1000);
  258.     }
  259.  
  260.     if (!(IntuitionBase = OpenLibrary("intuition.library",0))) {
  261.         printf("Unable to open intuition library\n");
  262.         CleanUp(1000);
  263.     }
  264.     if (!(MyScreen = OpenScreen(&MyScreenData))) {
  265.         CleanUp(1);
  266.     }
  267.     MyWindowData.Screen = MyScreen;
  268.  
  269.     if (!(MyWindow = OpenWindow(&MyWindowData))) {
  270.         CleanUp(1);
  271.     }
  272.     
  273.     MyRastPort = MyWindow->RPort;
  274.     SetDrMd(MyRastPort,JAM1);
  275.  
  276.     NewBox = BoxArray1;
  277.     OldBox = BoxArray2;
  278.  
  279.     CalcYRP();            /* calc initial rotations */
  280.     CalcBox(OldBox);        /* for first erasure */
  281.  
  282.     while (!QuitFlag) {
  283.  
  284.         CalcYRP();        /* calc current rotations */
  285.         CalcBox(NewBox);    /* calc corners for rotation */
  286.  
  287.         SetAPen(MyRastPort,0);    /* get background for erasure */
  288.         Move(MyRastPort,OldBox[0],OldBox[1]);    /* erase old box */
  289.         PolyDraw(MyRastPort,TRIPLETCOUNT-1,&OldBox[2]);
  290.  
  291.         SetAPen(MyRastPort,1);    /* get foreground for drawing */
  292.         Move(MyRastPort,NewBox[0],NewBox[1]);    /* draw new box */
  293.         PolyDraw(MyRastPort,TRIPLETCOUNT-1,&NewBox[2]);
  294.  
  295.         WritePixel(MyRastPort,WIDTHCENTER,HEIGHTCENTER); /* dot */
  296.  
  297.         if ((OldBox = NewBox) == BoxArray1)    /* swap arrays */
  298.             NewBox = BoxArray2;
  299.         else
  300.             NewBox = BoxArray1;
  301.  
  302.         if (!MyIntuiMessage) {    /* if no message is waiting */
  303.             WaitPort(MyWindow->UserPort);    /* wait for one */
  304.             MyIntuiMessage = (struct IntuiMessage *)GetMsg(MyWindow->UserPort);    /* get it */
  305.         }
  306.         HandleEvent();        /* handle it */
  307.     }
  308.     CleanUp(0);
  309. }
  310.  
  311. CleanUp(code)
  312. int    code;
  313. {
  314.     if (MyWindow)
  315.         CloseWindow(MyWindow);
  316.     if (MyScreen)
  317.         CloseScreen(MyScreen);
  318.     if (GfxBase)
  319.         CloseLibrary(GfxBase);
  320.     if (IntuitionBase)
  321.         CloseLibrary(IntuitionBase);
  322.  
  323.     exit(code);        /* the fat lady is singing */
  324. }
  325.