/*************************************************************************** * * * SKEWB by Raymond S. Brand * * * ***************************************************************************/ /*************************************************************************** * * * The weird looking constants are because this program is actually a * * 'C' version written for the Amiga of the original Pascal program that * * was written for a Tektronics 4113 Color Raster Display Terminal. * * * * RSBX * * * ***************************************************************************/ #include #include #include #define MAXMODE 1 /* Highres-Interlace ( 640 x 400 ) */ #define TALLMODE 2 /* Interlace ( 320 x 400 ) */ #define WIDEMODE 3 /* Highres ( 640 x 200 ) */ #define MINMODE 4 /* ( 320 x 200 ) */ #define DEFAULTMODE MAXMODE #ifndef DISPLAYMODE #define DISPLAYMODE DEFAULTMODE #endif #if (DISPLAYMODE == MAXMODE) #define DISPLAYWIDTH 640 #define DISPLAYHEIGHT 400 #define DISPLAYVIEWMODE HIRES | LACE #endif #if (DISPLAYMODE == TALLMODE) #define DISPLAYWIDTH 320 #define DISPLAYHEIGHT 400 #define DISPLAYVIEWMODE LACE #endif #if (DISPLAYMODE == WIDEMODE) #define DISPLAYWIDTH 640 #define DISPLAYHEIGHT 200 #define DISPLAYVIEWMODE HIRES #endif #if (DISPLAYMODE == MINMODE) #define DISPLAYWIDTH 320 #define DISPLAYHEIGHT 200 #define DISPLAYVIEWMODE NULL #endif struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; #define INTUITION_REV 29 #define GRAPHICS_REV 29 struct TextAttr MyFont = { "topaz.font", /* Font Name */ TOPAZ_SIXTY, /* Font Height */ FS_NORMAL, /* Style */ FPF_ROMFONT, /* Preferences */ }; struct NewScreen NewScreen = { 0, /* LeftEdge */ 0, /* TopEdge */ DISPLAYWIDTH, /* Width */ DISPLAYHEIGHT, /* Height */ 4, /* Depth (4 planes = 16 colors) */ 1, /* DetailPen */ 2, /* BlockPen */ DISPLAYVIEWMODE, /* ViewModes */ CUSTOMSCREEN, /* Type */ &MyFont, /* *Font */ "Skewb by Raymond S. Brand", /* *DefaultTitle */ NULL, /* *Gadgets */ NULL, /* *CustomBitMap */ }; struct Screen *Screen; struct NewWindow NewWindow; struct Window *Window1; struct Window *Window2; struct Verticies { SHORT X; SHORT Y; }; struct TileRecord { SHORT Color; struct Verticies TileVert[4]; }; struct TileRecord Tiles[6][11][11]; WORD areaverts[25]; struct TmpRas arearas; struct AreaInfo areadata; VOID OpenDisplay(); VOID CloseDisplay(); VOID SetColors(); SHORT Order(); SHORT Sign(); SHORT CubeCorr_to_ArrayCorr(); SHORT ArrayCorr_to_CubeCorr(); SHORT Tile(); VOID ChangeDisplay(); VOID CreateCube(); VOID RotateSlice(); VOID MoveSlice(); VOID ChangeTile(); VOID InitSkewb(); SHORT Norm_to_Axis(); SHORT Norm_to_Face(); VOID Swap(); VOID RotateVector(); VOID RotatePlane(); VOID RotateFace(); VOID RotateSlice(); SHORT Cube_Order; #define Cos1 0.7071067811865 #define Sin1 -0.7071067811865 #define Cos2 0.8164965809282 #define Sin2 0.57735026919 #define Distance -0.125 DOUBLE M1X = ( ( 700.0 / 4096.0 ) * DISPLAYWIDTH ); DOUBLE M1Y = ( ( 700.0 / 3048.0 ) * DISPLAYHEIGHT ); DOUBLE M2X = -( ( 200.0 / 4096.0 ) * DISPLAYWIDTH ); DOUBLE M2Y = -( ( 200.0 / 3048.0 ) * DISPLAYHEIGHT ); SHORT X1 = ( ( 1648.0 / 4096.0 ) * DISPLAYWIDTH ); SHORT Y1 = ( ( 1606.0 / 3048.0 ) * DISPLAYHEIGHT ); SHORT Z1 = 1; SHORT X2 = ( ( 462.0 / 4096.0 ) * DISPLAYWIDTH ); SHORT Y2 = ( ( 2618.0 / 3048.0 ) * DISPLAYHEIGHT ); SHORT Z2 = -1; SHORT X3 = ( ( 2836.0 / 4096.0 ) * DISPLAYWIDTH ); SHORT Y3 = ( ( 2608.0 / 3048.0 ) * DISPLAYHEIGHT ); SHORT Z3 = 1; main () { struct IntuiMessage *message; ULONG class; USHORT code; SHORT GoodBye; SHORT Axis; SHORT Plane; OpenDisplay(); InitSkewb(); GoodBye = FALSE; Axis = 1; Plane = 0; FOREVER { while (message = (struct IntuiMessage *)GetMsg(Window2->UserPort)) { class = message->Class; code = message->Code; ReplyMsg(message); if(class == CLOSEWINDOW) { GoodBye = TRUE; break; }; if(class == MOUSEBUTTONS) { if(code == SELECTDOWN) { Cube_Order = (Cube_Order - 1) % 9 + 2; CreateCube(); Plane = 0; Axis = 1; }; }; }; if(GoodBye) break; Delay(25); RotateSlice(Axis,Plane,1); Axis += Sign(Axis); if(Axis > 3) Axis = -1; if(Axis < -3) { Axis = 1; Plane = (Plane + 1) % Cube_Order; }; }; CloseDisplay(); exit(TRUE); } VOID OpenDisplay() { IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",INTUITION_REV); if (IntuitionBase == NULL) exit(20); GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV); if (GfxBase == NULL) exit(20); if ((Screen = (struct Screen *)OpenScreen(&NewScreen)) == NULL) exit(20); ShowTitle(Screen,FALSE); /* Put the Screen title behind any backdrop window that may exist */ /* Define Vanilla backdrop window for drawing onto */ NewWindow.LeftEdge = 0; NewWindow.TopEdge = 0; NewWindow.Width = DISPLAYWIDTH; NewWindow.Height = DISPLAYHEIGHT; NewWindow.DetailPen = 1; NewWindow.BlockPen = 2; NewWindow.IDCMPFlags = NULL; NewWindow.Flags = SMART_REFRESH | BACKDROP | ACTIVATE; NewWindow.FirstGadget = NULL; NewWindow.CheckMark = NULL; NewWindow.Title = NULL; NewWindow.Screen = Screen; NewWindow.BitMap = NULL; NewWindow.MinWidth = DISPLAYWIDTH; NewWindow.MinHeight = DISPLAYHEIGHT; NewWindow.MaxWidth = DISPLAYWIDTH; NewWindow.MaxHeight = DISPLAYHEIGHT; NewWindow.Type = CUSTOMSCREEN; if ((Window1 = (struct Window *)OpenWindow(&NewWindow)) == NULL) { CloseScreen(Screen); exit(20); }; /* Define a window with a close gadget so that we can exit this program */ NewWindow.LeftEdge = DISPLAYWIDTH - 100; NewWindow.TopEdge = DISPLAYHEIGHT - 50; NewWindow.Width = 100; NewWindow.Height = 50; NewWindow.DetailPen = 1; NewWindow.BlockPen = 2; NewWindow.IDCMPFlags = CLOSEWINDOW | MOUSEBUTTONS; NewWindow.Flags = SMART_REFRESH | WINDOWDRAG | WINDOWCLOSE; NewWindow.FirstGadget = NULL; NewWindow.CheckMark = NULL; NewWindow.Title = "Skewb"; NewWindow.Screen = Screen; NewWindow.BitMap = NULL; NewWindow.MinWidth = 100; NewWindow.MinHeight = 50; NewWindow.MaxWidth = 100; NewWindow.MaxHeight = 50; NewWindow.Type = CUSTOMSCREEN; if ((Window2 = (struct Window *)OpenWindow(&NewWindow)) == NULL) { CloseWindow(Window1); CloseScreen(Screen); exit(20); }; SetColors(); InitArea(&areadata,areaverts,10); Window1->RPort->AreaInfo=&areadata; if((arearas.RasPtr = (BYTE *)AllocRaster(DISPLAYWIDTH,DISPLAYHEIGHT)) == NULL) { CloseWindow(Window2); CloseWindow(Window1); CloseScreen(Screen); exit(20); }; arearas.Size=RASSIZE(DISPLAYWIDTH,DISPLAYHEIGHT); Window1->RPort->TmpRas=&arearas; SetRast(Window1->RPort,0); SetOPen(Window1->RPort,15); } VOID CloseDisplay() { FreeRaster(arearas.RasPtr,DISPLAYWIDTH,DISPLAYHEIGHT); CloseWindow(Window1); CloseWindow(Window2); CloseScreen(Screen); } VOID SetColors() { SetRGB4(&Screen->ViewPort, 0, 8, 8, 8); /* background */ SetRGB4(&Screen->ViewPort, 1,15,15,15); /* detail */ SetRGB4(&Screen->ViewPort, 2, 0, 0, 0); /* block */ SetRGB4(&Screen->ViewPort, 3, 6, 6, 6); SetRGB4(&Screen->ViewPort, 4, 6, 6, 6); SetRGB4(&Screen->ViewPort, 5, 6, 6, 6); SetRGB4(&Screen->ViewPort, 6, 6, 6, 6); SetRGB4(&Screen->ViewPort, 7, 6, 6, 6); SetRGB4(&Screen->ViewPort, 8,15, 0, 0); /* red */ SetRGB4(&Screen->ViewPort, 9, 0,15, 0); /* green */ SetRGB4(&Screen->ViewPort,10, 0, 0,15); /* blue */ SetRGB4(&Screen->ViewPort,11,15,15,15); /* white */ SetRGB4(&Screen->ViewPort,12,15, 9, 0); /* orange */ SetRGB4(&Screen->ViewPort,13,15,15, 0); /* yellow */ SetRGB4(&Screen->ViewPort,14, 6, 6, 6); SetRGB4(&Screen->ViewPort,15, 0, 0, 0); /* outline */ } SHORT Order() { return(Cube_Order); } SHORT Sign(number) SHORT number; { if (number == 0) return(0); if (number > 0) return(1); return(-1); } SHORT CubeCorr_to_ArrayCorr(Cube_Corr) SHORT Cube_Corr; { if ((Cube_Order % 2) == 0) /* even */ return( (SHORT)( Cube_Order / 2 - Cube_Corr - ( Cube_Order + 2 - 2 * Cube_Corr ) / ( Cube_Order + 2 ) ) ); else /* odd */ return( (SHORT)( ( Cube_Order - 1 - 2 * Cube_Corr ) / 2 ) ); } SHORT ArrayCorr_to_CubeCorr(Array_Corr) SHORT Array_Corr; { if ((Cube_Order % 2) == 0) /* even */ return( (SHORT)( Cube_Order / 2 - Array_Corr - ( 2 * Array_Corr + 2 ) / ( Cube_Order + 1 ) ) ); else /* odd */ return( (SHORT)( ( Cube_Order - 1 - 2 * Array_Corr ) / 2 ) ); } SHORT Tile() { } VOID ChangeTile(tileptr,x,y,z) struct TileRecord *tileptr; SHORT x; SHORT y; SHORT z; { SHORT i; SetAPen(Window1->RPort,tileptr->Color+8); AreaMove(Window1->RPort,tileptr->TileVert[0].X*z+x, DISPLAYHEIGHT - (tileptr->TileVert[0].Y*z+y)); for (i = 1; i < 4; i++) AreaDraw(Window1->RPort,tileptr->TileVert[i].X*z+x, DISPLAYHEIGHT - (tileptr->TileVert[i].Y*z+y)); AreaEnd(Window1->RPort); } VOID ChangeDisplay(face,x,y) SHORT face; SHORT x; SHORT y; { struct TileRecord *TileData; TileData = &Tiles[face][x][y]; /* should point to the tile structure */ if (face < 3) ChangeTile(TileData,X1,Y1,Z1); else { ChangeTile(TileData,X2,Y2,Z2); ChangeTile(TileData,X3,Y3,Z3); }; } VOID CreateCube() { SHORT Direction; SHORT Plane; SHORT Index1; SHORT Index2; SHORT Index3; SHORT Index4; DOUBLE Temp; struct { DOUBLE X; DOUBLE Y; } Matrix[11][11]; struct TileRecord *withtile; DOUBLE Vector[3]; DOUBLE MultX; DOUBLE MultY; MultX = M1X; MultY = M1Y; for(Direction=0;Direction<2;Direction++) { for(Plane=0;Plane<3;Plane++) { for(Index1=0;Index1<=Cube_Order;Index1++) { for(Index2=0;Index2<=Cube_Order;Index2++) { Vector[Plane]=(1.0 - 2.0 * Direction); Vector[(Plane+1) % 3]=((Cube_Order - 2.0 * Index1) / Cube_Order); Vector[(Plane+2) % 3]=((Cube_Order - 2.0 * Index2) / Cube_Order); Temp=(1.0 + Distance * (1.0 - 2.0 * Direction) * ( -Vector[0] * Sin1 * Cos2 +Vector[1] * Sin2 +Vector[2] * Cos1 * Cos2 )); Matrix[Index1][Index2].X=( Vector[0] * Cos1 +Vector[2] * Sin1 ) / Temp; Matrix[Index1][Index2].Y=( Vector[0] * Sin1 * Sin2 +Vector[1] * Cos2 -Vector[2] * Cos1 * Sin2 ) / Temp; } }; for(Index1=0;Index1Color=Plane + 3 * Direction; for(Index3=0;Index3<2;Index3++) { for(Index4=0;Index4<2;Index4++) { withtile->TileVert[Index3 * 2 + Index4].X = (Matrix[Index1 + Index3] [Index2 + Index3 + Index4 -2 * Index3 * Index4].X * (1.0 - 2.0 * Direction) * MultX); withtile->TileVert[Index3 * 2 + Index4].Y = (Matrix[Index1 + Index3] [Index2 + Index3 + Index4 -2 * Index3 * Index4].Y * MultY); }; }; ChangeDisplay(Plane + 3 * Direction,Index1,Index2); }; }; }; MultX = M2X; MultY = M2Y; }; } VOID InitSkewb() { Cube_Order = 2; CreateCube(); } SHORT Norm_to_Axis(Vector) SHORT *Vector; { SHORT Temp; SHORT Index; Temp = 0; for(Index=0 ; Index<3 ; Index++) Temp += Sign(Vector[Index]) * (Index + 1); return(Temp); } SHORT Norm_to_Face(Vector) SHORT *Vector; { SHORT Temp; Temp = Norm_to_Axis(Vector); if(Temp<0) Temp = 3 - Temp; Temp -= 1; return(Temp); } VOID Swap_Short(a,b) SHORT *a; SHORT *b; { SHORT Temp; Temp = *a; *a = *b; *b = Temp; } VOID RotateVector(Vector,Axis,Direction) SHORT *Vector; SHORT Axis; SHORT Direction; { SHORT Rotate; Rotate = Sign(Axis) * Sign(Direction); Axis = Sign(Axis) * Axis; Swap_Short(&Vector[Axis % 3],&Vector[(Axis + 1) % 3]); if(Rotate>0) Vector[(Axis + 1) % 3] *= -1; else Vector[Axis % 3] *= -1; } VOID RotatePlane(Axis,Plane,Direction) SHORT Axis; SHORT Plane; SHORT Direction; { SHORT Norm[3]; SHORT Tile[3]; SHORT n; SHORT x; SHORT y; SHORT z; SHORT Color; SHORT Index1; SHORT Index2; x = Sign(Axis) * Axis - 1; y = (x + 1) % 3; z = (y + 1) % 3; Norm[x] = 0; Norm[y] = ArrayCorr_to_CubeCorr(0); Norm[z] = 0; Tile[x] = Sign(Axis) * ArrayCorr_to_CubeCorr(Plane); for(Index1=0 ; Index1