home *** CD-ROM | disk | FTP | other *** search
- /* drawing stuff for rubik.c M.J.Round 3rd Feb 90 */
-
- int twistlist[21];
- int x1,y1,x2,y2,x3,y3;
-
- char tr [120] = /* transformations for 90 degree side rotates */
- {
- 0,2,8,6,
- 1,5,7,3,
- 18,45,29,42,
- 19,48,28,39,
- 20,51,27,36,
-
- 9,11,17,15,
- 10,14,16,12,
- 24,47,35,44,
- 25,50,34,41,
- 26,53,33,38,
-
- 18,20,26,24,
- 19,23,25,21,
- 0,45,11,38,
- 1,46,10,37,
- 2,47,9,36,
-
- 27,29,35,33,
- 28,32,34,30,
- 6,51,17,44,
- 7,52,16,43,
- 8,53,15,42,
-
- 36,38,44,42,
- 37,41,43,39,
- 18,9,33,6,
- 21,12,30,3,
- 24,15,27,0,
-
- 45,47,53,51,
- 46,50,52,48,
- 20,11,35,8,
- 23,14,32,5,
- 26,17,29,2
- };
-
- extern struct points point; /* holds posn.s of all points */
- extern struct points start;
- extern struct one_square square[56];
- extern struct Window *wnd1;
- extern struct Window *wnd2;
- extern struct Window *window;
- extern struct Screen *scr1;
- extern struct Screen *scr2;
- extern struct Screen *screen;
-
- extern int viewdist;
- extern short xcent,ycent;
- extern short angle(short, short, unsigned short);
- extern unsigned short hypot (short, short);
- extern unsigned short scaling;
-
- extern void roll (short);
- extern void yaw (short);
- extern void pitch (short);
- extern void fb (short, short);
- extern void bt (short, short);
- extern void lr (short, short);
-
- void twist (short ident, short amount)
- /* ident = 0 to 5 for front,back,(bottom),(top),left,right */
- /* amount = -1, +1 or +2 (90 degree twists) */
- {
- short c;
- unsigned short i,j,k;
-
- if (amount > 0)
- {
- for (i = 0; i<amount; i++)
- {
- for (j = ident * 20; j < ident * 20 + 20; j += 4)
- {
- c = (square[tr[j]]).colour;
- for (k = j; k < (j + 3); k++)
- (square[tr[k]]).colour = (square[tr[k+1]]).colour;
- (square[tr[j+3]]).colour = c;
- }
- }
- }
- else
- {
- for (i = 0; i < (-amount); i++)
- {
- for (j = ident * 20; j < ident * 20 + 20; j += 4)
- {
- c = (square[tr[j+3]]).colour;
- for (k = j + 3; k > j; k--)
- (square[tr[k]]).colour = (square[tr[k-1]]).colour;
- (square[tr[j]]).colour = c;
- }
- }
- }
- }
-
- /* return true if a square is clockwise else false */
- int clockwise(register int i)
- {
- register int d;
- short x,y,ang1,ang2;
- unsigned short r;
-
- d=(viewdist+(square[i].corner[0]->z)) << scaling;
- x1 = xcent+(viewdist*square[i].corner[0]->x)/d;
- y1 = ycent+(viewdist*square[i].corner[0]->y)/d;
-
- d=(viewdist+(square[i].corner[1]->z)) << scaling;
- x2 = xcent+(viewdist*square[i].corner[1]->x)/d;
- y2 = ycent+(viewdist*square[i].corner[1]->y)/d;
-
- d=(viewdist+(square[i].corner[2]->z)) << scaling;
- x3 = xcent+(viewdist*square[i].corner[2]->x)/d;
- y3 = ycent+(viewdist*square[i].corner[2]->y)/d;
-
- x = x2-x1;
- y = y2-y1;
-
- ang1 = ang2 = 0;
-
- if (x || y)
- ang1 = angle(x, y, (r = hypot (x, y)));
-
- x = x3-x2;
- y = y3-y2;
-
- if (x || y)
- ang2 = angle(x, y, (r = hypot (x, y)));
-
- d = ang1-ang2;
-
- if (d > 180)
- d -= 360;
-
- if (d < -179)
- d += 360;
-
- return (d > 0);
- }
-
- void draw_square(register int i)
- {
- register int d;
- SetAPen (window->RPort,square[i].colour);
- AreaMove (window->RPort,x1,y1);
- AreaDraw (window->RPort,x2,y2);
- AreaDraw (window->RPort,x3,y3);
- d=(viewdist+(square[i].corner[3]->z)) << scaling;
- AreaDraw
- (
- window->RPort,
- xcent+(viewdist*square[i].corner[3]->x)/d,
- ycent+(viewdist*square[i].corner[3]->y)/d
- );
- AreaEnd (window->RPort);
- }
-
- /* this routine renders the cube with roll, yaw and pitch alpha, beta, gamma
- if twists is non-zero, <layer> is rotated delta degrees at a time, through
- <twists> 90 degree twists.
- */
- void showcube
- (
- short alpha,
- short beta,
- short gamma,
- short layer,
- short twists,
- short delta
- )
- {
- int i,j;
- short theta = 0;
-
- do
- {
- point = start; /* this copies the 'zeroed' cube to the workspace */
-
- if (twists)
- {
- theta += (twists > 0) ? -delta : delta;
-
- if ((theta <= -90) || (theta >= 90))
- {
- theta = (twists > 0) ? 1 : -1;
- twist (layer,theta);
- twists -= theta;
- theta = 0;
- }
- else
- {
- switch (layer)
- {
- case 0:
- case 1:
- fb(layer,theta);
- break;
- case 2:
- case 3:
- bt((short)(layer-2),theta);
- break;
- default:
- lr((short)(layer-4),theta);
- break;
- }
- }
- }
-
- if (alpha)
- roll (alpha);
- if (beta)
- yaw (beta);
- if (gamma)
- pitch (gamma);
-
- SetAPen(window->RPort,7);
- RectFill(window->RPort,2,10,190,198);
-
- if (theta == 0)
- {
- for (i=0; i<54; i++)
- if (clockwise(i))
- draw_square(i);
- else if ((i % 3) == 0)
- i += 2;
- }
- else if (clockwise(54))
- {
- draw_square(54);
-
- for (i=0; i<21; i++)
- if (clockwise(twistlist[i]))
- draw_square(twistlist[i]);
- else if ((i % 3) == 0)
- i += 2;
-
- j = 0;
-
- for (i=0; i<54; i++)
- {
- while ((j < 21) && ((twistlist[j]) < i))
- j++;
-
- if ((j > 20) || (i != twistlist[j]))
- {
- if (clockwise(i))
- draw_square(i);
- else if ((i % 3) == 0)
- i += 2;
- }
- }
- }
- else
- {
- if (clockwise(55)) /* need this to get corners */
- draw_square(55);
-
- j = 0;
-
- for (i=0; i<54; i++)
- {
- while ((j < 21) && ((twistlist[j]) < i))
- j++;
-
- if ((j > 20) || (i != twistlist[j]))
- {
- if (clockwise(i))
- draw_square(i);
- else if ((i % 3) == 0)
- i += 2;
- }
- }
-
- for (i=0; i<21; i++)
- if (clockwise(twistlist[i]))
- draw_square(twistlist[i]);
- else if ((i % 3) == 0)
- i += 2;
- }
-
- ScreenToFront(screen);
-
- if (screen == scr1)
- {
- screen = scr2;
- window = wnd2;
- }
- else
- {
- screen = scr1;
- window = wnd1;
- }
- } while (twists);
- }
-
-
- int whatsquare(int x, int y) /* returns square number, or -1 */
- {
- struct Window *viswindow;
- int colour,i;
-
- if (y<12 || x>190)
- return(-1);
-
- if (window == wnd1)
- viswindow = wnd2;
- else
- viswindow = wnd1;
-
- for (i = 0; i < 4 && (colour = ReadPixel(viswindow->RPort,x,y)) == 0; i++)
- {
- switch (i)
- {
- case 0:
- x += 2;
- break;
- case 1:
- y += 2;
- break;
- case 3:
- x -= 2;
- break;
- }
- } /* find a nearby square if they click on the lines */
-
- if (colour <= 0 || colour == 7)
- return (-1);
-
- ClipBlit
- (
- viswindow->RPort,2,10, /* source posn */
- window->RPort,2,10, /* dest posn */
- 188,188, /* size */
- 0xc0 /* direct copy */
- );
-
- SetAPen(window->RPort,7);
- Flood (window->RPort,1,x,y);
-
- for (i=0; i<54; i++)
- if (clockwise(i))
- {
- draw_square(i);
- if (ReadPixel(window->RPort,x,y) != 7)
- return(i);
-
- }
-
- return (-1);
- }
-
- int paints(int x, int y, int pen) /* returns square number, or -1 */
- {
- struct Window *viswindow;
- int colour,i;
-
- if (y<12 || x>190)
- return(-1);
-
- if (window == wnd1)
- viswindow = wnd2;
- else
- viswindow = wnd1;
-
- for (i = 0; i < 4 && (colour = ReadPixel(viswindow->RPort,x,y)) == 0; i++)
- {
- switch (i)
- {
- case 0:
- x += 2;
- break;
- case 1:
- y += 2;
- break;
- case 3:
- x -= 2;
- break;
- }
- } /* find a nearby square if they click on the lines */
-
- if (colour <= 0 || colour == 7)
- return (-1);
-
- SetAPen(viswindow->RPort,pen);
- Flood (viswindow->RPort,1,x,y);
-
- return (whatsquare(x,y));
- }
-
- void findangles (short *alpha, short *beta, short *gamma)
- {
- short x,y,z;
-
- y = ((point.xyz [0] [0] [5]).y + (point.xyz [5] [5] [5]).y)/2;
- z = ((point.xyz [0] [0] [5]).z + (point.xyz [5] [5] [5]).z)/2;
-
- pitch ((short) -(*gamma = -angle (z,y,hypot (z,y))));
-
- x = ((point.xyz [0] [0] [5]).x + (point.xyz [5] [5] [5]).x)/2;
- z = ((point.xyz [0] [0] [5]).z + (point.xyz [5] [5] [5]).z)/2;
-
- yaw ((short) -(*beta = -angle (z,x,hypot (z,x))));
-
- x = ((point.xyz [0] [5] [0]).x + (point.xyz [5] [5] [5]).x)/2;
- y = ((point.xyz [0] [5] [0]).y + (point.xyz [5] [5] [5]).y)/2;
-
- *alpha = -angle (y,x,hypot (y,x));
- }
-