french@caip.RUTGERS.EDU (03/18/86)
From: "french robert%d.mfenet"@LLL-MFE.ARPA What follows is a little strange program I wrote the other day that lets you rotate a 2 to 6 dimensional "cube" on the screen using the joystick. Please note that it has NOT been refined or made terribly efficient. It IS interesting to watch though. ENJOY! ---------------------------Cut, cut, cut!---------------------------------- /************************************************************************* * 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 <exec/types.h> #include <exec/tasks.h> #include <exec/libraries.h> #include <exec/devices.h> #include <devices/keymap.h> #include <devices/gameport.h> #include <devices/inputevent.h> #include <graphics/copper.h> #include <graphics/display.h> #include <graphics/gfxbase.h> #include <graphics/text.h> #include <graphics/view.h> #include <graphics/gels.h> #include <graphics/regions.h> #include <hardware/blit.h> #include <intuition/intuition.h> #include <intuition/intuitionbase.h> #include <stdio.h> /* 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;i<num_points;i++) for (j=0;j<num_dim;j++) if (i & (1 << j)) points[i][j].i = SPFlt(1); else points[i][j].i = SPFlt(-1); /* Figure out edges */ num_edges = 0; for (i=0;i<num_points-1;i++) for (j=i+1;j<num_points;j++) { num_change = 0; for (k=0;k<num_dim;k++) if (points[i][k].i != points[j][k].i) num_change++; if (num_change == 1) { st_edge[num_edges] = i; end_edge[num_edges] = j; num_edges++; } } if ((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0)) == NULL) abort("Can't open Intuition.Library!\n"); if ((GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0)) == NULL) abort("Can't open Graphics.Library!\n"); open_joystick(); /* values for new screen */ newscreen.LeftEdge = 0; newscreen.TopEdge = 0; newscreen.Width = 640; newscreen.Height = 200; newscreen.Depth = 1; newscreen.DetailPen = 0; newscreen.BlockPen = 1; newscreen.ViewModes = HIRES; newscreen.Type = CUSTOMSCREEN; newscreen.Font = NULL; newscreen.DefaultTitle = ""; newscreen.Gadgets = NULL; scrn = (struct Screen *)OpenScreen(&newscreen); if (scrn == 0) abort("Can't open new screen!\n"); vp = &(scrn->ViewPort); 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<num_points;i++) { z.i = SPFlt(1); if (num_dim >})h2) 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;i<num_edges;i++) { Move(rp,xpoints[st_edge[i]],ypoints[st_edge[i]]); Draw(rp,xpoints[end_edge[i]],ypoints[end_edge[i]]); } } rotate(p1,p2,a) int p1,p2,a; { int i; union kludge ang,thesin,thecos,temp1,temp2; ang.i = a; thesin.i = SPSin(ang.i); thecos.i = SPCos(ang.i); for (i=0;i<num_points;i++) { temp1.i = SPSub(SPMul(points[i][p2].i,thesin.i), SPMul(points[i][p1].i,thecos.i)); temp2.i = SPAdd(SPMul(points[i][p2].i,thecos.i), SPMul(points[i][p1].i,thesin.i)); points[i][p1].i = temp1.i; points[i][p2].i = temp2.i; } } open_joystick() { struct MsgPort *joystick_msg_port; /* provide a port for the IO request/response */ joystick_msg_port = CreatePort("thejoystickport",0); if(joystick_msg_port == 0) abort("Can't create joystick port"); /* make an io request block for communicating with the joystick device */ joystick_io_request = CreateStdIO(joystick_msg_port); if(joystick_io_request == 0) abort("Can't create joystick I/O request block"); /* open the gameport device for access, unit 1 is right port */ if(OpenDevice("gameport.device",1,joystick_io_request,0)) abort("Can't open joystick device"); /* set the device type to absolute joystick */ if (set_controller_type(GPCT_ABSJOYSTICK) != 0) abort("Can't set controller type"); /* trigger on button-down, button-up, front, back, left, right, center */ if (set_controller_trigger(GPTF_UPKEYS+GPTF_DOWNKEYS,1,1,1) != 0) abort("Can't set controller trigger"); /* SETUP THE IO MESSAGE BLOCK FOR THE ACTUAL DATA READ */ /* gameport.device replies to this task */ joystick_io_request->io_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)); }
mikel@ccvaxa.UUCP (04/01/86)
I just replaced the line with if (num_dim > 2) The program runs fine and works up to 6 dims.