home *** CD-ROM | disk | FTP | other *** search
- /* Use "lc -Lm -cw 3droll.c" to compile (Lattice) */
-
- /* (C) 1990 Keith Gravlin */
-
- /* Program draws a three-d object which can be manipulated with the mouse. */
- /* Left and right (pick button up) will adjust yaw. */
- /* Up and down (pick button up) adjust pitch. */
- /* Left and right (pick button down) adjust roll. */
- /* Up and down (pick button down) adjust zoom in/out. */
-
- #include "exec/types.h"
- #include "exec/memory.h"
- #include "intuition/intuition.h"
- #include "graphics/gfxmacros.h"
- #include "math.h"
-
- long GfxBase = NULL;
- long IntuitionBase = NULL;
-
- extern struct Screen *OpenScreen();
- extern struct Window *OpenWindow();
-
- struct Screen *MyScreen = NULL;
- struct Window *MyWindow = NULL;
-
- struct IntuiMessage *MyIntuiMessage = NULL;
- struct IntuiMessage IntuiMessageBuffer;
-
- struct RastPort *MyRastPort = NULL;
-
-
- #define SWIDTH 640
- #define SHEIGHT 400
- #define SDEPTH 1
-
- struct NewScreen MyScreenData = {
- 0,0, /* start postion */
- SWIDTH,SHEIGHT,SDEPTH, /* width, height, depth */
- 0,1, /* detail pen, block pen */
- HIRES | LACE, /* viewing mode */
- CUSTOMSCREEN, /* screen type */
- NULL, /* font to use */
- NULL, /* screen title */
- NULL /* pointer to gadgets */
- };
-
- #define WWIDTH SWIDTH
- #define WHEIGHT SHEIGHT
-
- struct NewWindow MyWindowData = {
- 0,0, /* upper left corner of window */
- WWIDTH, WHEIGHT, /* width, height */
- 0,1, /* detail pen, block pen */
- CLOSEWINDOW | MOUSEBUTTONS | MOUSEMOVE | REFRESHWINDOW, /* IDCMP flags */
- REPORTMOUSE | WINDOWCLOSE | BORDERLESS | SIMPLE_REFRESH, /* window flags */
- NULL, /* pointer to first gadget */
- NULL, /* pointer to checkmark */
- "Box Roll", /* window title */
- NULL, /* screen pointer to screen */
- NULL, /* pointer to superbitmap */
- 0,0, /* MinWidth,MinHeight */
- 0,0, /* MaxWidth,MaxHeight */
- CUSTOMSCREEN };
-
- double TransX = 0.0, TransY = 0.0, TransZ = -235.0; /* translation variables */
- double DisplayX = 0.0, DisplayY = 0.0; /* for display coords */
- double Distortion = 1500.0; /* distortion/perspective factor */
- double Yaw = 0.0;
- double Roll = 0.0;
- double Pitch = 0.0;
- double SinYaw, CosYaw; /* intermediate values */
- double SinRoll, CosRoll;
- double SinPitch, CosPitch;
-
- int QuitFlag = FALSE; /* set TRUE to quit */
- int PickButtonDown = FALSE; /* holds current state of pick button */
- int FixedX = NULL, FixedY = NULL; /* holds fixed part of position */
-
- /* Add/delete/change triplets to produce things other than boxes. */
- /* Have fun ! */
- int Triplets[][3] = {
- -5,-5,5,
- -5,5,5,
- 5,5,5,
- 5,-5,5,
- -5,-5,5,
- -5,-5,-5,
- -5,5,-5,
- -5,5,5,
- -5,5,-5,
- 5,5,-5,
- 5,5,5,
- 5,5,-5,
- 5,-5,-5,
- 5,-5,5,
- 5,-5,-5,
- -5,-5,-5,
- 5,5,-5,
- 5,-5,-5,
- -5,5,-5
- };
-
- #define TRIPLETCOUNT sizeof(Triplets)/(3*sizeof(int))
-
-
- void CalcYRP() /* calc values for current rotations */
- {
- SinYaw = sin(Yaw);
- CosYaw = cos(Yaw);
- SinRoll = sin(Roll);
- CosRoll = cos(Roll);
- SinPitch = sin(Pitch);
- CosPitch = cos(Pitch);
- }
-
- void Calc3D(double x,double y,double z) /* here's my work Ma'm */
- {
- double TempX, TempY, TempZ;
-
- TempX = (CosYaw*x)-(SinYaw*z);
- TempY = (CosRoll*y)-(SinRoll*TempX);
- TempZ = (SinYaw*x)+(CosYaw*z);
- x = (CosRoll*TempX)+(SinRoll*y)+TransX;
- y = (SinPitch*TempZ)+(CosPitch*TempY)+TransY;
- z = (CosPitch*TempZ)-(SinPitch*TempY)+TransZ;
-
- DisplayX = ((Distortion*x/z)+319)*WWIDTH/640.0; /* adjust aspect */
- DisplayY = ((Distortion*y/z)+239)*WHEIGHT/480.0;
- }
-
- void CalcBox(boxarray)
- SHORT *boxarray;
- {
- int x;
-
- for (x=0;x<TRIPLETCOUNT;x++) { /* for each corner */
- Calc3D((double)Triplets[x][0],(double)Triplets[x][1],(double)Triplets[x][2]);
- boxarray[x*2] = DisplayX;
- boxarray[x*2+1] = DisplayY;
- }
- }
-
- void HandleEvent()
- {
- switch(MyIntuiMessage->Class) {
- case MOUSEMOVE:
- MouseMove();
- break;
- case MOUSEBUTTONS:
- switch(MyIntuiMessage->Code) {
- case SELECTDOWN:
- PickButtonDown = TRUE;
- break;
- case SELECTUP:
- PickButtonDown = FALSE;
- break;
- default:
- break;
- }
- ReplyMsg(MyIntuiMessage);
- MyIntuiMessage = NULL;
- break;
- case REFRESHWINDOW:
- ReplyMsg(MyIntuiMessage);
- MyIntuiMessage = NULL;
- break;
- case CLOSEWINDOW:
- ReplyMsg(MyIntuiMessage);
- MyIntuiMessage = NULL;
- QuitFlag = TRUE;
- break;
- default:
- ReplyMsg(MyIntuiMessage);
- MyIntuiMessage = NULL;
- break;
- }
- }
-
- #define WIDTHCENTER (WWIDTH-1)/2
- #define HEIGHTCENTER (WHEIGHT-1)/2
-
- MouseMove()
- {
- int MyMouseX = NULL, MyMouseY = NULL;
-
- SwallowMoves(10); /* suck up rapid movements */
-
- MyMouseX = IntuiMessageBuffer.MouseX - WIDTHCENTER;
- MyMouseY = IntuiMessageBuffer.MouseY - HEIGHTCENTER;
-
- /* Uncommenting the following code will fix x or y, whichever goes */
- /* non-zero first. Returning that coord to zero (center of screen) will */
- /* free it and allow the other to become fixed. */
- /* This was just a way to play with one axis at a time. */
- /* if (FixedX && MyMouseX)
- MyMouseX = FixedX;
- else {
- FixedX = NULL;
- if (FixedY && MyMouseY)
- MyMouseY = FixedY;
- else {
- FixedY = NULL;
- FixedX = MyMouseX;
- }
- }
- if (!FixedX)
- FixedY = MyMouseY;
- */
- if (PickButtonDown) {
- Roll = MyMouseX * 6.283 / WWIDTH;
- TransZ = MyMouseY - HEIGHTCENTER - 35;
- }
- else {
- Yaw = MyMouseX * 6.283 / WWIDTH;
- Pitch = -MyMouseY * 6.283 / WHEIGHT;
- }
- }
-
- /* Calling this function with a lower count will decrease jerkyness but */
- /* increase the number of redraws, thus causing slower response. */
- /* Have it your way ! */
- SwallowMoves(count) /* swallow up to 'count' rapid mouse moves */
- int count;
- {
- int i, j;
- UBYTE *source, *dest;
- struct IntuiMessage *NewIntuiMessage = NULL;
-
- for (j=0;j<count;j++) {
- if (NewIntuiMessage = (struct IntuiMessage *)GetMsg(MyWindow->UserPort)) {
- if (NewIntuiMessage->Class == MOUSEMOVE) {
- ReplyMsg(MyIntuiMessage);
- MyIntuiMessage = NewIntuiMessage;
- NewIntuiMessage = NULL;
- }
- else
- break;
- }
- else
- break;
- }
- source = (UBYTE *)MyIntuiMessage;
- dest = (UBYTE *)&IntuiMessageBuffer;
- for (i=0;i<sizeof(struct IntuiMessage);i++)
- *dest++ = *source++;
- ReplyMsg(MyIntuiMessage);
- MyIntuiMessage = NewIntuiMessage;
- }
-
- main() /* street USA */
- {
- SHORT BoxArray1[TRIPLETCOUNT*2], BoxArray2[TRIPLETCOUNT*2];
- SHORT *OldBox, *NewBox;
-
- if (!(GfxBase = OpenLibrary("graphics.library",0))) {
- printf("Unable to open graphics library\n");
- CleanUp(1000);
- }
-
- if (!(IntuitionBase = OpenLibrary("intuition.library",0))) {
- printf("Unable to open intuition library\n");
- CleanUp(1000);
- }
- if (!(MyScreen = OpenScreen(&MyScreenData))) {
- CleanUp(1);
- }
- MyWindowData.Screen = MyScreen;
-
- if (!(MyWindow = OpenWindow(&MyWindowData))) {
- CleanUp(1);
- }
-
- MyRastPort = MyWindow->RPort;
- SetDrMd(MyRastPort,JAM1);
-
- NewBox = BoxArray1;
- OldBox = BoxArray2;
-
- CalcYRP(); /* calc initial rotations */
- CalcBox(OldBox); /* for first erasure */
-
- while (!QuitFlag) {
-
- CalcYRP(); /* calc current rotations */
- CalcBox(NewBox); /* calc corners for rotation */
-
- SetAPen(MyRastPort,0); /* get background for erasure */
- Move(MyRastPort,OldBox[0],OldBox[1]); /* erase old box */
- PolyDraw(MyRastPort,TRIPLETCOUNT-1,&OldBox[2]);
-
- SetAPen(MyRastPort,1); /* get foreground for drawing */
- Move(MyRastPort,NewBox[0],NewBox[1]); /* draw new box */
- PolyDraw(MyRastPort,TRIPLETCOUNT-1,&NewBox[2]);
-
- WritePixel(MyRastPort,WIDTHCENTER,HEIGHTCENTER); /* dot */
-
- if ((OldBox = NewBox) == BoxArray1) /* swap arrays */
- NewBox = BoxArray2;
- else
- NewBox = BoxArray1;
-
- if (!MyIntuiMessage) { /* if no message is waiting */
- WaitPort(MyWindow->UserPort); /* wait for one */
- MyIntuiMessage = (struct IntuiMessage *)GetMsg(MyWindow->UserPort); /* get it */
- }
- HandleEvent(); /* handle it */
- }
- CleanUp(0);
- }
-
- CleanUp(code)
- int code;
- {
- if (MyWindow)
- CloseWindow(MyWindow);
- if (MyScreen)
- CloseScreen(MyScreen);
- if (GfxBase)
- CloseLibrary(GfxBase);
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
-
- exit(code); /* the fat lady is singing */
- }
-