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