/************************************************************************* * Version 0.0 MULTIDIM.C - Multi-dimensional rotation 12-Mar-86 * * Commodore Amiga Main Module MULTIDIM.C * ************************************************************************* * Copyright (c) 1986, Robert S. French * * --------------------------------------------------------------------- * * This program has been placed in the public domain. A limited * * license is hereby granted for the unlimited use and distribution of * * this program, provided it is not used for commercial or profit- * * making purposes. Thank you. * ************************************************************************* * Author information: | Disclaimer: * * | * * Name: Robert S. French | The author takes no responsibil- * * USnail: 2740 Frankfort Avenue | ity for damages incurred during * * Louisville, KY 40206 | the use of this program. * * Phone: (502) 897-5096 \-----------------------------------* * ARPA: French#Robert%d@LLL-MFE UUCP: ihnp4!ptsfa!well!french * ************************************************************************* * Please send any comments, suggestions, or bugs to one of the above * * addresses. * ************************************************************************* * Comments * * ======== * * * * Please note that I have very little background in multi-dimensional * * theory. This program is not meant to be a scientific representation * * of higher universes, just something kinda neat to look at. I'm sure * * that there are mathematical problems, such as rotational direction * * in the higher planes. "A" etc. are used for lack of better names. * * Hold the joystick right and press the button to end, or left and * * press for automatic demo. Feel free to hack this program up as much * * as you like. One of the things I'd like to add is double-buffering. * *************************************************************************/ /* Lots of include files! */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Some definitions... */ #define MAXDIM 6 #define MAXPOINTS 64 #define MAXEDGES 250 #define XSCALE 145 #define YSCALE 60 #define XCENTER 320 #define YCENTER 100 /* Fast-Floating-Point Definitions... */ extern int SPFix(); extern int SPFlt(); extern int SPCmp(); extern int SPTst(); extern int SPAbs(); extern int SPNeg(); extern int SPAdd(); extern int SPSub(); extern int SPMul(); extern int SPDiv(); extern int SPAtan(); extern int SPSin(); extern int SPCos(); extern int SPTan(); extern int SPSincos(); extern int SPSinh(); extern int SPCosh(); extern int SPTanh(); extern int SPExp(); extern int SPLog(); extern int SPPow(); extern int SPSqrt(); extern int SPTieee(); extern int SPFieee(); /* Other external functions... */ extern struct MsgPort *CreatePort(); extern struct IOStdReq *CreateStdIO(); /* And some global graphics stuff... */ struct GfxBase *GfxBase = NULL; struct IntuitionBase *IntuitionBase = NULL; struct Screen *scrn = NULL; struct NewScreen newscreen; struct RastPort *rp = NULL; struct ViewPort *vp = NULL; /* And some more global stuff... */ int MathBase = NULL, MathTransBase = NULL; struct IOStdReq *joystick_io_request = NULL; struct InputEvent joystick_data; union kludge { float f; int i; } points[MAXPOINTS][MAXDIM], xscale, yscale, sqrt2, const2, const15, recip2sqrt2; int st_edge[MAXEDGES], end_edge[MAXEDGES], xpoints[MAXPOINTS], ypoints[MAXPOINTS]; int num_points,num_edges,num_dim,alldim; /* And the real thing... */ main(argc,argv) int argc; char *argv[]; { int i,j,k,num_change,axis1,axis2,autorot,autocount; union kludge angle,nangle,pi; char *s; if (argc < 2) abort("Usage: multidim n {D} where n is the number of dimensions"); num_dim = atoi(argv[1]); if (num_dim < 2 || num_dim > MAXDIM) abort("Illegal number of dimensions"); alldim = 1; if (argc == 3 && toupper(argv[2][0]) == 'D') alldim = 0; if ((MathBase = OpenLibrary("mathffp.library")) == NULL) abort("Can't open mathffp.library!"); if ((MathTransBase = OpenLibrary("mathtrans.library")) == NULL) abort("Can't open mathtrans.library!"); xscale.i = SPFlt(XSCALE); yscale.i = SPFlt(YSCALE); const2.i = SPFlt(2); const15.i = SPDiv(SPFlt(2),SPFlt(3)); sqrt2.i = SPSqrt(const2.i); recip2sqrt2.i = SPDiv(SPMul(SPFlt(2),sqrt2.i),SPFlt(1)); num_points = 1 << num_dim; /* Figure out vertices of n-dimensional "cube" */ for (i=0;iViewPort); rp = &(scrn->RastPort); SetAPen(rp,0); RectFill(rp,0,0,639,199); SetRGB4(vp,0,0,0,0); SetRGB4(vp,1,0xb,0,0); SetAPen(rp,1); SetBPen(rp,0); SetDrMd(rp,JAM2); Move(rp,0,9); Text(rp,"Plane: X Y",10); Move(rp,550,9); Text(rp,"R. French",9); pi.f = 3.1415926535; pi.i = SPFieee(pi.i); angle.i = SPMul(SPDiv(SPFlt(180),pi.i),SPFlt(5)); nangle.i = SPNeg(angle.i); axis1 = 0; axis2 = 1; autorot = autocount = 0; s = " "; draw(); while(1) { DoIO(joystick_io_request); if (joystick_data.ie_Y == 1 && !autorot) { rotate(axis1,axis2,nangle.i); draw(); } else if (joystick_data.ie_Y == -1 || autorot) { rotate(axis1,axis2,angle.i); draw(); } if (autorot) autocount = (autocount + 1) % 33; if (joystick_data.ie_Code == IECODE_LBUTTON || autocount == 32) { if (joystick_data.ie_Code == IECODE_LBUTTON) autorot = autocount = 0; if (joystick_data.ie_X == 1) abort("All done!"); if (joystick_data.ie_X == -1) autorot = 1; axis2++; if (axis2 > num_dim-1) { axis1++; if (axis1 > num_dim-2) axis1 = 0; axis2 = axis1 + 1; } SetAPen(rp,0); RectFill(rp,56,0,85,9); SetAPen(rp,1); Move(rp,56,9); s[0] = (axis1 < 3) ? 'X'+axis1 : 'A'+axis1-3; s[2] = (axis2 < 3) ? 'X'+axis2 : 'A'+axis2-3; Text(rp,s,3); } } } abort(s) char *s; { puts(s); if (joystick_io_request) close_joystick(); if (scrn) CloseScreen(scrn); if (GfxBase) CloseLibrary(GfxBase); if (IntuitionBase) CloseLibrary(IntuitionBase); if (MathTransBase) CloseLibrary(MathTransBase); if (MathBase) CloseLibrary(MathBase); exit(20); } draw() { int i,dim; union kludge z; for (i=0;i 2) if (alldim) for (dim=num_dim-1;dim>=2;--dim) z.i = SPMul(SPAdd(SPMul(points[i][dim].i,recip2sqrt2.i), const15.i),z.i); else z.i = SPAdd(SPMul(points[i][num_dim-1].i,recip2sqrt2.i), const15.i); xpoints[i] = SPFix(SPMul(SPDiv(z.i,points[i][0].i),xscale.i))+XCENTER; ypoints[i] = SPFix(SPMul(SPDiv(z.i,points[i][1].i),yscale.i))+YCENTER; } SetAPen(rp,0); RectFill(rp,0,10,639,199); SetAPen(rp,1); SetDrMd(rp,JAM1); for (i=0;iio_Message.mn_ReplyPort = joystick_msg_port; /* from now on, just read input events */ joystick_io_request->io_Command = GPD_READEVENT; /* into the input buffer, one at a time. */ joystick_io_request->io_Data = (APTR)&joystick_data; /* read num events each time we go back to the joystickport */ joystick_io_request->io_Length = sizeof(joystick_data); } close_joystick() { /* close up joystick device */ CloseDevice(joystick_io_request); /* clean up */ DeletePort(joystick_io_request->io_Message.mn_ReplyPort); DeleteStdIO(joystick_io_request); } int set_controller_type(type) BYTE type; { joystick_io_request->io_Command = GPD_SETCTYPE; joystick_io_request->io_Length = 1; /* set type of controller to "type" */ joystick_io_request->io_Data = (APTR)&type; return(DoIO(joystick_io_request)); } int set_controller_trigger(keys,timeout,xdelta,ydelta) UWORD keys,timeout,xdelta,ydelta; { struct GamePortTrigger gpt; joystick_io_request->io_Command = GPD_SETTRIGGER; joystick_io_request->io_Length = sizeof(gpt); joystick_io_request->io_Data = (APTR)&gpt; gpt.gpt_Keys = keys; gpt.gpt_Timeout = timeout; gpt.gpt_XDelta = xdelta; gpt.gpt_YDelta = ydelta; return(DoIO(joystick_io_request)); }