/* * the Rubik's cube. * * Sed - april 1999 / december 2003. * * This program is in the public domain. *-------------------- * The cube related stuff (init, project, rotate, so on) */ #include "cube.h" #include #include #include #include #include #include #include #include #include #include "screen.h" #include "fillpoly.h" #include "line.h" #include "device.h" /* when you see those globals, you are very allowed to think i began to have hard work * with all those angles, rotations, faces and so on. I am definitly not a good graphical * coder. Am i a good coder in something anyway ? */ int nb_facettes; int cur_facette; typedef struct { double z; double x0, y0, x1, y1, x2, y2, x3, y3; int col, cross; } facette; facette f[6*26]; int order[6*26]; int order1[6*26]; double e[8][3]; /* small cube edges */ static void cube_do_rotate(CUBE *); void save_cube(CUBE *c) { static char letter[12] = "XABCDEFI012"; static short order[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 10, 9, 8}; char name[30]; char buffer[80]; int i, j, l; int fd; sprintf(name, "rubix.%s", formats[FORMAT]); name[9] = '\0'; fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (fd==-1) { perror("cube.save_cube.open"); return; } if (write(fd, "%rubix\n\n", 8)!= 8) { write_error: perror("cube.save_cube.write"); close(fd); unlink(name); return; } if (write(fd, "%colors\n", 8)!= 8) goto write_error; for (i=0; i<11; i++) { sprintf(buffer, "%c = %s\n", letter[i], palette[order[i]]); l = strlen(buffer); if (write(fd, buffer, l)!= l) goto write_error; } if (write(fd, "\n%matrix\n\n", 9)!= 9) goto write_error; for (i=0; i<3; i++) { sprintf(buffer, "%14.10f %14.10f %14.10f\n", c->matrix[i][0], c->matrix[i][1], c->matrix[i][2]); l = strlen(buffer); if (write(fd, buffer, l)!= l) goto write_error; } if (FORMAT == 0) { if (write(fd, "\n%position\n", 11)!= 11) goto write_error; buffer[0] = buffer[1] = buffer[2] = buffer[3] = buffer[11] = ' '; buffer[7] = '\n'; buffer[8] = buffer[9] = '\0'; buffer[4] = '@' + c->cubes[25].colors[1]; buffer[5] = '@' + c->cubes[22].colors[1]; buffer[6] = '@' + c->cubes[20].colors[1]; if (write(fd, buffer, 8)!= 8) goto write_error; buffer[4] = '@' + c->cubes[24].colors[1]; buffer[5] = '@' + c->cubes[1].colors[1]; buffer[6] = '@' + c->cubes[19].colors[1]; if (write(fd, buffer, 8)!= 8) goto write_error; buffer[4] = '@' + c->cubes[23].colors[1]; buffer[5] = '@' + c->cubes[21].colors[1]; buffer[6] = '@' + c->cubes[18].colors[1]; buffer[8] = '\n'; if (write(fd, buffer, 9)!= 9) goto write_error; buffer[7] = ' '; buffer[15] = '\n' ; buffer[16] = buffer[17] = '\0'; buffer[0] = '@' + c->cubes[25].colors[2]; buffer[1] = '@' + c->cubes[24].colors[2]; buffer[2] = '@' + c->cubes[23].colors[2]; buffer[4] = '@' + c->cubes[23].colors[4]; buffer[5] = '@' + c->cubes[21].colors[4]; buffer[6] = '@' + c->cubes[18].colors[4]; buffer[8] = '@' + c->cubes[18].colors[3]; buffer[9] = '@' + c->cubes[19].colors[3]; buffer[10]= '@' + c->cubes[20].colors[3]; buffer[12]= '@' + c->cubes[20].colors[5]; buffer[13]= '@' + c->cubes[22].colors[5]; buffer[14]= '@' + c->cubes[25].colors[5]; if (write(fd, buffer, 16)!= 16) goto write_error; buffer[0] = '@' + c->cubes[17].colors[2]; buffer[1] = '@' + c->cubes[2].colors[2]; buffer[2] = '@' + c->cubes[16].colors[2]; buffer[4] = '@' + c->cubes[16].colors[4]; buffer[5] = '@' + c->cubes[4].colors[4]; buffer[6] = '@' + c->cubes[14].colors[4]; buffer[8] = '@' + c->cubes[14].colors[3]; buffer[9] = '@' + c->cubes[3].colors[3]; buffer[10]= '@' + c->cubes[15].colors[3]; buffer[12]= '@' + c->cubes[15].colors[5]; buffer[13]= '@' + c->cubes[5].colors[5]; buffer[14]= '@' + c->cubes[17].colors[5]; if (write(fd, buffer, 16)!= 16) goto write_error; buffer[0] = '@' + c->cubes[13].colors[2]; buffer[1] = '@' + c->cubes[12].colors[2]; buffer[2] = '@' + c->cubes[11].colors[2]; buffer[4] = '@' + c->cubes[11].colors[4]; buffer[5] = '@' + c->cubes[9].colors[4]; buffer[6] = '@' + c->cubes[6].colors[4]; buffer[8] = '@' + c->cubes[6].colors[3]; buffer[9] = '@' + c->cubes[7].colors[3]; buffer[10]= '@' + c->cubes[8].colors[3]; buffer[12]= '@' + c->cubes[8].colors[5]; buffer[13]= '@' + c->cubes[10].colors[5]; buffer[14]= '@' + c->cubes[13].colors[5]; buffer[16] = '\n'; if (write(fd, buffer, 17)!= 17) goto write_error; buffer[0] = buffer[1] = buffer[2] = ' '; buffer[7] = '\n'; buffer[8] = buffer[9] = '\0'; buffer[4] = '@' + c->cubes[11].colors[0]; buffer[5] = '@' + c->cubes[9].colors[0]; buffer[6] = '@' + c->cubes[6].colors[0]; if (write(fd, buffer, 8)!= 8) goto write_error; buffer[4] = '@' + c->cubes[12].colors[0]; buffer[5] = '@' + c->cubes[0].colors[0]; buffer[6] = '@' + c->cubes[7].colors[0]; if (write(fd, buffer, 8)!= 8) goto write_error; buffer[4] = '@' + c->cubes[13].colors[0]; buffer[5] = '@' + c->cubes[10].colors[0]; buffer[6] = '@' + c->cubes[8].colors[0]; if (write(fd, buffer, 8)!= 8) goto write_error; } if (FORMAT == 1) { if (write(fd, "\n%numeric\n", 10)!= 10) goto write_error; buffer[6] ='\n'; buffer[7] = 0; for (i=0; i<26; i++) { for (j=0; j<6; j++) buffer[j] = '0'+c->cubes[i].colors[j]; if (write(fd, buffer, 7)!= 7) goto write_error; } } if (FORMAT == 2) { if (write(fd, "\n%generators\n", 13)!= 13) goto write_error; if (write(fd, ".\n", 2)!= 2) goto write_error; } if (close(fd)==-1) { perror("cube.save_cube.close"); unlink(name); return; } } void reset_cube(CUBE *c) { static double initmatrix[3][3]={ {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; memcpy(c->matrix, initmatrix, 9*sizeof(double)); c->center = 4; } int get_string(int fd, char *buffer, int max) { int i; i = 0; while (i=80) { read_error: perror("cube.load_cube.read"); close(fd); return; } if (strncmp(buffer, "%rubix", 6)) goto read_error; FORMAT = -1; iter: i = 0; buffer[0] = ' '; while (i>=0 && buffer[0]!='%') i = get_string(fd, buffer, 80); finish: if (i==-1) { if (FORMAT==-1) goto read_error; goto end_parsing; } new_section: if (!strncmp(buffer, "%colors", 7)) { iter_colors: i = 0; buffer[0] = ' '; while (i>=0 && isspace(buffer[0])) i = get_string(fd, buffer, 80); if (i==-1) goto finish; if (buffer[0]=='%') goto new_section; buffer[0]=toupper(buffer[0]); ptr = index(buffer, '='); if (ptr) { ++ptr; while (isspace(*ptr)) ++ptr; if (buffer[0]>='A' && buffer[0]<='F') { i = buffer[0] - 'A' + 1; palette[i] = strdup(ptr); } if (buffer[0]=='X') palette[0] = strdup(ptr); if (buffer[0]=='I') palette[7] = strdup(ptr); if (buffer[0]>='0' && buffer[0]<='2') { i = '9' - buffer[0] + 1; palette[i] = strdup(ptr); } } goto iter_colors; } else if (!strncmp(buffer, "%position", 9)) { FORMAT = 0; i = 0; while (i>=0 && i<7) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[25].colors[1] = buffer[4] - '@'; c->cubes[22].colors[1] = buffer[5] - '@'; c->cubes[20].colors[1] = buffer[6] - '@'; i = 0; while (i>=0 && i<7) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[24].colors[1] = buffer[4] - '@'; c->cubes[1].colors[1] = buffer[5] - '@'; c->cubes[19].colors[1] = buffer[6] - '@'; i = 0; while (i>=0 && i<7) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[23].colors[1] = buffer[4] - '@'; c->cubes[21].colors[1] = buffer[5] - '@'; c->cubes[18].colors[1] = buffer[6] - '@'; i = 0; while (i>=0 && i<15) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[25].colors[2] = buffer[0] - '@'; c->cubes[24].colors[2] = buffer[1] - '@'; c->cubes[23].colors[2] = buffer[2] - '@'; c->cubes[23].colors[4] = buffer[4] - '@'; c->cubes[21].colors[4] = buffer[5] - '@'; c->cubes[18].colors[4] = buffer[6] - '@'; c->cubes[18].colors[3] = buffer[8] - '@'; c->cubes[19].colors[3] = buffer[9] - '@'; c->cubes[20].colors[3] = buffer[10] - '@'; c->cubes[20].colors[5] = buffer[12] - '@'; c->cubes[22].colors[5] = buffer[13] - '@'; c->cubes[25].colors[5] = buffer[14] - '@'; i = 0; while (i>=0 && i<15) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[17].colors[2] = buffer[0] - '@'; c->cubes[2].colors[2] = buffer[1] - '@'; c->cubes[16].colors[2] = buffer[2] - '@'; c->cubes[16].colors[4] = buffer[4] - '@'; c->cubes[4].colors[4] = buffer[5] - '@'; c->cubes[14].colors[4] = buffer[6] - '@'; c->cubes[14].colors[3] = buffer[8] - '@'; c->cubes[3].colors[3] = buffer[9] - '@'; c->cubes[15].colors[3] = buffer[10] - '@'; c->cubes[15].colors[5] = buffer[12] - '@'; c->cubes[5].colors[5] = buffer[13] - '@'; c->cubes[17].colors[5] = buffer[14] - '@'; i = 0; while (i>=0 && i<15) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[13].colors[2] = buffer[0] - '@'; c->cubes[12].colors[2] = buffer[1] - '@'; c->cubes[11].colors[2] = buffer[2] - '@'; c->cubes[11].colors[4] = buffer[4] - '@'; c->cubes[9].colors[4] = buffer[5] - '@'; c->cubes[6].colors[4] = buffer[6] - '@'; c->cubes[6].colors[3] = buffer[8] - '@'; c->cubes[7].colors[3] = buffer[9] - '@'; c->cubes[8].colors[3] = buffer[10] - '@'; c->cubes[8].colors[5] = buffer[12] - '@'; c->cubes[10].colors[5] = buffer[13] - '@'; c->cubes[13].colors[5] = buffer[14] - '@'; i = 0; while (i>=0 && i<7) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[11].colors[0] = buffer[4] - '@'; c->cubes[9].colors[0] = buffer[5] - '@'; c->cubes[6].colors[0] = buffer[6] - '@'; i = 0; while (i>=0 && i<7) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[12].colors[0] = buffer[4] - '@'; c->cubes[0].colors[0] = buffer[5] - '@'; c->cubes[7].colors[0] = buffer[6] - '@'; i = 0; while (i>=0 && i<7) i = get_string(fd, buffer, 80); if (i==-1) goto finish; c->cubes[13].colors[0] = buffer[4] - '@'; c->cubes[10].colors[0] = buffer[5] - '@'; c->cubes[8].colors[0] = buffer[6] - '@'; } else if (!strncmp(buffer, "%numeric", 8)) { FORMAT = 1; k = 0; while (k<26) { i = 0; while (i>=0 && i<6) i = get_string(fd, buffer, 80); if (i>=6) { for (j=0; j<6; j++) c->cubes[k].colors[j] = buffer[j] - '0'; k++; } } } else if (!strncmp(buffer, "%generators", 11)) { FORMAT = 2; while (read(fd, &ch, 1)==1) { c->orient = -1; if (ch=='.') break; if ((ch>='a') && (ch<='f')) { c->center = ch-'a'; c->orient = 0; } else if ((ch>='A') && (ch<='F')) { c->center = ch-'A'; c->orient = 0; } else if (!isspace(ch)) fprintf(stderr, "Invalid character : %c\n", ch); if (c->orient>=0) cube_do_rotate(c); } c->orient = 0; } else if (!strncmp(buffer, "%matrix", 7)) { i = 0; while (i>=0 && i<5) i = get_string(fd, buffer, 80); if (i==-1) goto finish; if (sscanf(buffer, "%lg %lg %lg", &c->matrix[0][0],&c->matrix[0][1],&c->matrix[0][2])!=3) goto read_error; i = 0; while (i>=0 && i<5) i = get_string(fd, buffer, 80); if (i==-1) goto finish; if (sscanf(buffer, "%lg %lg %lg", &c->matrix[1][0],&c->matrix[1][1],&c->matrix[1][2])!=3) goto read_error; i = 0; while (i>=0 && i<5) i = get_string(fd, buffer, 80); if (i==-1) goto finish; if (sscanf(buffer, "%lg %lg %lg", &c->matrix[2][0],&c->matrix[2][1],&c->matrix[2][2])!=3) goto read_error; } else goto read_error; goto iter; end_parsing: if (close(fd)==-1) { perror("cube.load_cube.close"); return; } } void init_cube(CUBE *c, char *file, int random) { int i, j; static short initedge[8][3] = { {-1, -1, -1}, /* 0 */ {-1, -1, 1}, /* 1 */ {-1, 1, -1}, /* 2 */ {-1, 1, 1}, /* 3 */ { 1, -1, -1}, /* 4 */ { 1, -1, 1}, /* 5 */ { 1, 1, -1}, /* 6 */ { 1, 1, 1}};/* 7 */ #define X -1 static small_cube initsmallcube[26]= {{x: 0, y: -1, z: 0, colors:{1,X,X,X,X,X}}, /* 0 */ {x: 0, y: 1, z: 0, colors:{X,2,X,X,X,X}}, /* 1 */ {x: -1, y: 0, z: 0, colors:{X,X,3,X,X,X}}, /* 2 */ {x: 1, y: 0, z: 0, colors:{X,X,X,4,X,X}}, /* 3 */ {x: 0, y: 0, z: 1, colors:{X,X,X,X,5,X}}, /* 4 */ {x: 0, y: 0, z: -1, colors:{X,X,X,X,X,6}}, /* 5 */ {x: 1, y: -1, z: 1, colors:{1,X,X,4,5,X}}, /* 6 */ {x: 1, y: -1, z: 0, colors:{1,X,X,4,X,X}}, /* 7 */ {x: 1, y: -1, z: -1, colors:{1,X,X,4,X,6}}, /* 8 */ {x: 0, y: -1, z: 1, colors:{1,X,X,X,5,X}}, /* 9 */ {x: 0, y: -1, z: -1, colors:{1,X,X,X,X,6}}, /* 10 */ {x: -1, y: -1, z: 1, colors:{1,X,3,X,5,X}}, /* 11 */ {x: -1, y: -1, z: 0, colors:{1,X,3,X,X,X}}, /* 12 */ {x: -1, y: -1, z: -1, colors:{1,X,3,X,X,6}}, /* 13 */ {x: 1, y: 0, z: 1, colors:{X,X,X,4,5,X}}, /* 14 */ {x: 1, y: 0, z: -1, colors:{X,X,X,4,X,6}}, /* 15 */ {x: -1, y: 0, z: 1, colors:{X,X,3,X,5,X}}, /* 16 */ {x: -1, y: 0, z: -1, colors:{X,X,3,X,X,6}}, /* 17 */ {x: 1, y: 1, z: 1, colors:{X,2,X,4,5,X}}, /* 18 */ {x: 1, y: 1, z: 0, colors:{X,2,X,4,X,X}}, /* 19 */ {x: 1, y: 1, z: -1, colors:{X,2,X,4,X,6}}, /* 20 */ {x: 0, y: 1, z: 1, colors:{X,2,X,X,5,X}}, /* 21 */ {x: 0, y: 1, z: -1, colors:{X,2,X,X,X,6}}, /* 22 */ {x: -1, y: 1, z: 1, colors:{X,2,3,X,5,X}}, /* 23 */ {x: -1, y: 1, z: 0, colors:{X,2,3,X,X,X}}, /* 24 */ {x: -1, y: 1, z: -1, colors:{X,2,3,X,X,6}}};/* 25 */ #undef X memcpy(c->cubes, initsmallcube, 26*sizeof(small_cube)); c->anim = 0; c->orient = 0; c->letters = 0; c->angle = 0; memset(&c->time, 0, sizeof(struct timeval)); for (i=0; i<26*6; i++) order1[i]=i; /* set small cube sizes */ for (i=0; i<8; i++) for (j=0; j<3; j++) e[i][j] = EDGE * initedge[i][j]; /* let's randomize the cube */ if (random>0) { struct timeval tt=get_time(); srand(tt.tv_sec-c->time.tv_sec+tt.tv_usec-c->time.tv_usec); for (i=0; i<1000; i++) { c->orient=2.0*rand()/(RAND_MAX+1.0); c->center=6.0*rand()/(RAND_MAX+1.0); cube_do_rotate(c); } } else if (random==0) { if (file) { load_cube(c, file); return; } } } void mulm(double a[3][3], double b[3][3]) { int i, j; double r[3][3]; for (i=0; i<3; i++) for (j=0; j<3; j++) r[i][j]=(a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j]); memcpy(a, r, 9*sizeof(double)); } void xmat(double x, double m[3][3]) { double p[3][3]={{1.0, 0.0, 0.0}, {0.0, cos(x),sin(x)}, {0.0,-sin(x),cos(x)}}; mulm(m, p); } void ymat(double y, double m[3][3]) { double p[3][3]={{cos(y),0.0,-sin(y)}, {0.0, 1.0, 0.0}, {sin(y),0.0, cos(y)}}; mulm(m, p); } void zmat(double z, double m[3][3]) { double p[3][3]={{cos(z),sin(z),0}, {-sin(z),cos(z),0}, {0,0,1}}; mulm(m, p); } void clear_facette(void) { nb_facettes=0; memcpy(order, order1, sizeof(order)); } void put_facette(double z, double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, int color, int cross) { int i; cur_facette++; if ((x1-x0)*(y2-y0)-(y1-y0)*(x2-x0)>0) return; i=nb_facettes++; f[i].z=z; f[i].x0=x0; f[i].y0=y0; f[i].x1=x1; f[i].y1=y1; f[i].x2=x2; f[i].y2=y2; f[i].x3=x3; f[i].y3=y3; f[i].col=color; f[i].cross=cross; } void tri_facette(void) { /* hehe, the very first time of my i use this gcc feature, the inline function ! Crazy */ int cmp(const void *u1, const void *u2) { double z1=f[*(int *)u1].z, z2=f[*(int *)u2].z; if (z1z2; } qsort(order, nb_facettes, sizeof(int), cmp); } void show_facette(SCREEN *s) { extern device d; int i; poly p; line l; p.nb_points=4; l.color=pixel[10]; for(i=0; imatrix small_cube *c; static Pixmap textpix; static int bigendian; XImage *xim = NULL; int i, j, n, u, v, du, dv, dm, dw, dh; char face[2]; char p=0, test; double x, y, z, size, ratio; if (!big->letters) return; face[1] = '\0'; dm = ((XTextWidth(s->font, "M", 1)+7)/8)*8; dh = s->font->max_bounds.ascent+s->font->max_bounds.descent; if (!xim) { GC gc; textpix = XCreatePixmap(s->d, s->w, 6*dm, dh, 1); gc = XCreateGC(s->d, textpix, 0, 0); bigendian = (ImageByteOrder(s->d) == MSBFirst); XSetForeground(s->d, gc, 1); XSetBackground(s->d, gc, 0); XSetFont(s->d, gc, s->font->fid); v = s->font->max_bounds.ascent; for (n=0; n<6; n++) { face[0] = 'A' + n; XDrawImageString(s->d, textpix, gc, n*dm, v, face, 1); } XFreeGC(s->d, gc); xim = XGetImage(s->d, textpix, 0, 0, 6*dm, dh, 1, XYPixmap); XFreePixmap(s->d, textpix); } du = XTextWidth(s->font, "A", 1)/2; dv = s->font->max_bounds.ascent/2; size = 1.0 + EDGE; for (n=0; n<6; n++) { c = &big->cubes[n]; z = size*(c->x*M[0][2]+ c->y*M[1][2]+ c->z*M[2][2]); if (z>0.5*PERSPECTIVE) { face[0] = 'A' + n; dw = XTextWidth(s->font, face, 1); x = size*(c->x*M[0][0]+ c->y*M[1][0]+ c->z*M[2][0]); y = size*(c->x*M[0][1]+ c->y*M[1][1]+ c->z*M[2][1]); ratio = CUBE_SIZE/(5.0-PERSPECTIVE*z); u = 0.5*SCREEN_X + ratio*x - du; v = 0.5*SCREEN_Y - ratio*y + dv - s->font->max_bounds.ascent; test = (bigendian)? 128 : 1; for (j=0; jdata[j*xim->bytes_per_line+(i+n*dm)/8]; if (p&test) XPutPixel(s->im, u+i, v+j, pixel[8]); p = (bigendian)? p<<1 : p>>1; } } } } void display_small_cube(CUBE *big, SCREEN *s, int i) { static short u[6] = { 0, 2, 2, 1, 0, 1}; static short v[6] = { 2, 0, 1, 2, 1, 0}; // static short opposite[6] = { 1, 0, 3, 2, 5, 4}; static short face[6][4]={{0,4,5,1}, {2,3,7,6}, {0,1,3,2}, {4,6,7,5}, {1,5,7,3}, {0,2,6,4}}; static short layers[6][26]={ /*0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25*/ { 1,-1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1}, {-1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, { 0, 0, 1,-1, 0, 0,-1,-1,-1, 0, 0, 1, 1, 1,-1,-1, 1, 1,-1,-1,-1, 0, 0, 1, 1, 1}, { 0, 0,-1, 1, 0, 0, 1, 1, 1, 0, 0,-1,-1,-1, 1, 1,-1,-1, 1, 1, 1, 0, 0,-1,-1,-1}, { 0, 0, 0, 0, 1,-1, 1, 0,-1, 1,-1, 1, 0,-1, 1,-1, 1,-1, 1, 0,-1, 1,-1, 1, 0,-1}, { 0, 0, 0, 0,-1, 1,-1, 0, 1,-1, 1,-1, 0, 1,-1, 1,-1, 1,-1, 0, 1,-1, 1,-1, 0, 1}}; double m[3][3]; double m1[3][3]={{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; double p1[8][3]; double p2[8][3]; double pp[8][2]; double ratio; double zm; small_cube *c; int n; //int k; memcpy(m, big->matrix, 9*sizeof(double)); if (big->anim) { n = big->rotated; if (layers[n][i]==1) { m1[u[n]][u[n]] = m1[v[n]][v[n]] = cos(big->angle); m1[u[n]][v[n]] = sin(big->angle); m1[v[n]][u[n]] = -m1[u[n]][v[n]]; } } c = &big->cubes[i]; for (n=0; n<8; n++) { p1[n][0]=(((e[n][0]+c->x)*m1[0][0]+ (e[n][1]+c->y)*m1[1][0]+ (e[n][2]+c->z)*m1[2][0])); p1[n][1]=(((e[n][0]+c->x)*m1[0][1]+ (e[n][1]+c->y)*m1[1][1]+ (e[n][2]+c->z)*m1[2][1])); p1[n][2]=(((e[n][0]+c->x)*m1[0][2]+ (e[n][1]+c->y)*m1[1][2]+ (e[n][2]+c->z)*m1[2][2])); p2[n][0]=((p1[n][0]*m[0][0]+ p1[n][1]*m[1][0]+ p1[n][2]*m[2][0])); p2[n][1]=((p1[n][0]*m[0][1]+ p1[n][1]*m[1][1]+ p1[n][2]*m[2][1])); p2[n][2]=((p1[n][0]*m[0][2]+ p1[n][1]*m[1][2]+ p1[n][2]*m[2][2])); #define x (p2[n][0]) #define y (p2[n][1]) #define z (p2[n][2]) #define Xp (pp[n][0]) #define Yp (pp[n][1]) /* Xp=320./2.+320./2.*x/(5.*(1.)-z); Yp=120.-240./(2.*240./320.)*y/(5.*(1.)-z); */ ratio = CUBE_SIZE/(5.0-PERSPECTIVE*z); Xp = 0.5*SCREEN_X + ratio*x; Yp = 0.5*SCREEN_Y - ratio*y; #undef x #undef y #undef z #undef Xp #undef Yp } /* if animation, draw in color 0 any visible internal face from medium layer -- added by J.P. Demailly */ if (big->anim==1) { n = big->rotated; if (layers[n][i]==0 && c->colors[n]<0) { zm=p2[face[n][0]][2]+p2[face[n][1]][2]+p2[face[n][2]][2]+p2[face[n][3]][2]; put_facette(zm, pp[face[n][0]][0], pp[face[n][0]][1], pp[face[n][1]][0], pp[face[n][1]][1], pp[face[n][2]][0], pp[face[n][2]][1], pp[face[n][3]][0], pp[face[n][3]][1], 7, 0); } } if (big->anim==-1) { for (n=0; n<6; n++) if (c->colors[n]>=0) { zm=p2[face[n][0]][2]+p2[face[n][1]][2]+p2[face[n][2]][2]+p2[face[n][3]][2]; put_facette(zm, pp[face[n][0]][0], pp[face[n][0]][1], pp[face[n][1]][0], pp[face[n][1]][1], pp[face[n][2]][0], pp[face[n][2]][1], pp[face[n][3]][0], pp[face[n][3]][1], 7, 0); } } /* draw visible faces */ for (n=0; n<6; n++) { /* those tests WILL fail if you move the cube with the mouse while a face rotates */ /* so let's go back to the previous situation, where everything was fine */ //k = opposite[big->anim ? big->rotated : big->center]; //k = opposite[big->center]; //if ((n!=k || big->anim==-1) && c->colors[n]>=0) { if (c->colors[n]>=0) { zm=p2[face[n][0]][2]+p2[face[n][1]][2]+p2[face[n][2]][2]+p2[face[n][3]][2]; put_facette(zm, pp[face[n][0]][0], pp[face[n][0]][1], pp[face[n][1]][0], pp[face[n][1]][1], pp[face[n][2]][0], pp[face[n][2]][1], pp[face[n][3]][0], pp[face[n][3]][1], c->colors[n], //(big->anim ? i==big->rotated : i==big->center) && (!big->letters)); (i==big->center) && (!big->letters)); } } } double z_middle(CUBE *c, int n) { #define m c->matrix #define x (c->cubes[n].x) #define y (c->cubes[n].y) #define z (c->cubes[n].z) /* well, well, well, i must have done something wrong, it should be * m[2][0]*x+m[2][1]*y+m[2][2]*z, nope ? Well... */ return m[0][2]*x+m[1][2]*y+m[2][2]*z; #undef x #undef y #undef z #undef m } void place_cross(CUBE *c) { int i=1; int n=0; double z=z_middle(c, 0); while(i<6) { double z1=z_middle(c, i); if (z1>z) { n=i; z=z1; } i++; } if (c->anim!=-1) c->center=n; } void display_cube(CUBE *c, SCREEN *s) { int i; if (c->anim) cube_event(c); place_cross(c); clear_facette(); for (i=0; i<26; i++) display_small_cube(c, s, i); tri_facette(); clear_screen(s); show_facette(s); if (c->anim == 0) show_letters(c, s); put_screen(c, s); } /* c->orient and c->rotated are used so they must be set to their correct value */ static void cube_do_rotate(CUBE *c) { CUBE old; memcpy(&old, c, sizeof(CUBE)); /* gotta change colors, woo woo woo */ if (c->orient==0) switch(c->rotated) { case 0 : c->cubes[11].colors[0]=old.cubes[6].colors[0]; c->cubes[11].colors[2]=old.cubes[6].colors[4]; c->cubes[11].colors[4]=old.cubes[6].colors[3]; c->cubes[12].colors[0]=old.cubes[9].colors[0]; c->cubes[12].colors[2]=old.cubes[9].colors[4]; c->cubes[13].colors[0]=old.cubes[11].colors[0]; c->cubes[13].colors[2]=old.cubes[11].colors[4]; c->cubes[13].colors[5]=old.cubes[11].colors[2]; c->cubes[10].colors[0]=old.cubes[12].colors[0]; c->cubes[10].colors[5]=old.cubes[12].colors[2]; c->cubes[8].colors[0]=old.cubes[13].colors[0]; c->cubes[8].colors[5]=old.cubes[13].colors[2]; c->cubes[8].colors[3]=old.cubes[13].colors[5]; c->cubes[7].colors[0]=old.cubes[10].colors[0]; c->cubes[7].colors[3]=old.cubes[10].colors[5]; c->cubes[6].colors[0]=old.cubes[8].colors[0]; c->cubes[6].colors[3]=old.cubes[8].colors[5]; c->cubes[6].colors[4]=old.cubes[8].colors[3]; c->cubes[9].colors[0]=old.cubes[7].colors[0]; c->cubes[9].colors[4]=old.cubes[7].colors[3]; break; case 1 : c->cubes[18].colors[1]=old.cubes[23].colors[1]; c->cubes[18].colors[3]=old.cubes[23].colors[4]; c->cubes[18].colors[4]=old.cubes[23].colors[2]; c->cubes[21].colors[1]=old.cubes[24].colors[1]; c->cubes[21].colors[4]=old.cubes[24].colors[2]; c->cubes[23].colors[1]=old.cubes[25].colors[1]; c->cubes[23].colors[4]=old.cubes[25].colors[2]; c->cubes[23].colors[2]=old.cubes[25].colors[5]; c->cubes[24].colors[1]=old.cubes[22].colors[1]; c->cubes[24].colors[2]=old.cubes[22].colors[5]; c->cubes[25].colors[1]=old.cubes[20].colors[1]; c->cubes[25].colors[2]=old.cubes[20].colors[5]; c->cubes[25].colors[5]=old.cubes[20].colors[3]; c->cubes[22].colors[1]=old.cubes[19].colors[1]; c->cubes[22].colors[5]=old.cubes[19].colors[3]; c->cubes[20].colors[1]=old.cubes[18].colors[1]; c->cubes[20].colors[5]=old.cubes[18].colors[3]; c->cubes[20].colors[3]=old.cubes[18].colors[4]; c->cubes[19].colors[1]=old.cubes[21].colors[1]; c->cubes[19].colors[3]=old.cubes[21].colors[4]; break; case 2 : c->cubes[25].colors[2]=old.cubes[23].colors[2]; c->cubes[25].colors[1]=old.cubes[23].colors[4]; c->cubes[25].colors[5]=old.cubes[23].colors[1]; c->cubes[24].colors[2]=old.cubes[16].colors[2]; c->cubes[24].colors[1]=old.cubes[16].colors[4]; c->cubes[23].colors[2]=old.cubes[11].colors[2]; c->cubes[23].colors[1]=old.cubes[11].colors[4]; c->cubes[23].colors[4]=old.cubes[11].colors[0]; c->cubes[16].colors[2]=old.cubes[12].colors[2]; c->cubes[16].colors[4]=old.cubes[12].colors[0]; c->cubes[11].colors[2]=old.cubes[13].colors[2]; c->cubes[11].colors[4]=old.cubes[13].colors[0]; c->cubes[11].colors[0]=old.cubes[13].colors[5]; c->cubes[12].colors[2]=old.cubes[17].colors[2]; c->cubes[12].colors[0]=old.cubes[17].colors[5]; c->cubes[13].colors[2]=old.cubes[25].colors[2]; c->cubes[13].colors[0]=old.cubes[25].colors[5]; c->cubes[13].colors[5]=old.cubes[25].colors[1]; c->cubes[17].colors[2]=old.cubes[24].colors[2]; c->cubes[17].colors[5]=old.cubes[24].colors[1]; break; case 3 : c->cubes[6].colors[3]=old.cubes[18].colors[3]; c->cubes[6].colors[0]=old.cubes[18].colors[4]; c->cubes[6].colors[4]=old.cubes[18].colors[1]; c->cubes[7].colors[3]=old.cubes[14].colors[3]; c->cubes[7].colors[0]=old.cubes[14].colors[4]; c->cubes[8].colors[3]=old.cubes[6].colors[3]; c->cubes[8].colors[0]=old.cubes[6].colors[4]; c->cubes[8].colors[5]=old.cubes[6].colors[0]; c->cubes[15].colors[3]=old.cubes[7].colors[3]; c->cubes[15].colors[5]=old.cubes[7].colors[0]; c->cubes[20].colors[3]=old.cubes[8].colors[3]; c->cubes[20].colors[5]=old.cubes[8].colors[0]; c->cubes[20].colors[1]=old.cubes[8].colors[5]; c->cubes[19].colors[3]=old.cubes[15].colors[3]; c->cubes[19].colors[1]=old.cubes[15].colors[5]; c->cubes[18].colors[3]=old.cubes[20].colors[3]; c->cubes[18].colors[1]=old.cubes[20].colors[5]; c->cubes[18].colors[4]=old.cubes[20].colors[1]; c->cubes[14].colors[3]=old.cubes[19].colors[3]; c->cubes[14].colors[4]=old.cubes[19].colors[1]; break; case 4 : c->cubes[11].colors[4]=old.cubes[23].colors[4]; c->cubes[11].colors[0]=old.cubes[23].colors[2]; c->cubes[11].colors[2]=old.cubes[23].colors[1]; c->cubes[9].colors[4]=old.cubes[16].colors[4]; c->cubes[9].colors[0]=old.cubes[16].colors[2]; c->cubes[6].colors[4]=old.cubes[11].colors[4]; c->cubes[6].colors[0]=old.cubes[11].colors[2]; c->cubes[6].colors[3]=old.cubes[11].colors[0]; c->cubes[14].colors[4]=old.cubes[9].colors[4]; c->cubes[14].colors[3]=old.cubes[9].colors[0]; c->cubes[18].colors[4]=old.cubes[6].colors[4]; c->cubes[18].colors[3]=old.cubes[6].colors[0]; c->cubes[18].colors[1]=old.cubes[6].colors[3]; c->cubes[21].colors[4]=old.cubes[14].colors[4]; c->cubes[21].colors[1]=old.cubes[14].colors[3]; c->cubes[23].colors[4]=old.cubes[18].colors[4]; c->cubes[23].colors[1]=old.cubes[18].colors[3]; c->cubes[23].colors[2]=old.cubes[18].colors[1]; c->cubes[16].colors[4]=old.cubes[21].colors[4]; c->cubes[16].colors[2]=old.cubes[21].colors[1]; break; case 5 : c->cubes[25].colors[5]=old.cubes[13].colors[5]; c->cubes[25].colors[1]=old.cubes[13].colors[2]; c->cubes[25].colors[2]=old.cubes[13].colors[0]; c->cubes[22].colors[5]=old.cubes[17].colors[5]; c->cubes[22].colors[1]=old.cubes[17].colors[2]; c->cubes[20].colors[5]=old.cubes[25].colors[5]; c->cubes[20].colors[1]=old.cubes[25].colors[2]; c->cubes[20].colors[3]=old.cubes[25].colors[1]; c->cubes[15].colors[5]=old.cubes[22].colors[5]; c->cubes[15].colors[3]=old.cubes[22].colors[1]; c->cubes[8].colors[5]=old.cubes[20].colors[5]; c->cubes[8].colors[3]=old.cubes[20].colors[1]; c->cubes[8].colors[0]=old.cubes[20].colors[3]; c->cubes[10].colors[5]=old.cubes[15].colors[5]; c->cubes[10].colors[0]=old.cubes[15].colors[3]; c->cubes[13].colors[5]=old.cubes[8].colors[5]; c->cubes[13].colors[0]=old.cubes[8].colors[3]; c->cubes[13].colors[2]=old.cubes[8].colors[0]; c->cubes[17].colors[5]=old.cubes[10].colors[5]; c->cubes[17].colors[2]=old.cubes[10].colors[0]; break; } else switch(c->rotated) { case 0 : c->cubes[6].colors[0]=old.cubes[11].colors[0]; c->cubes[6].colors[4]=old.cubes[11].colors[2]; c->cubes[6].colors[3]=old.cubes[11].colors[4]; c->cubes[9].colors[0]=old.cubes[12].colors[0]; c->cubes[9].colors[4]=old.cubes[12].colors[2]; c->cubes[11].colors[0]=old.cubes[13].colors[0]; c->cubes[11].colors[4]=old.cubes[13].colors[2]; c->cubes[11].colors[2]=old.cubes[13].colors[5]; c->cubes[12].colors[0]=old.cubes[10].colors[0]; c->cubes[12].colors[2]=old.cubes[10].colors[5]; c->cubes[13].colors[0]=old.cubes[8].colors[0]; c->cubes[13].colors[2]=old.cubes[8].colors[5]; c->cubes[13].colors[5]=old.cubes[8].colors[3]; c->cubes[10].colors[0]=old.cubes[7].colors[0]; c->cubes[10].colors[5]=old.cubes[7].colors[3]; c->cubes[8].colors[0]=old.cubes[6].colors[0]; c->cubes[8].colors[5]=old.cubes[6].colors[3]; c->cubes[8].colors[3]=old.cubes[6].colors[4]; c->cubes[7].colors[0]=old.cubes[9].colors[0]; c->cubes[7].colors[3]=old.cubes[9].colors[4]; break; case 1 : c->cubes[23].colors[1]=old.cubes[18].colors[1]; c->cubes[23].colors[4]=old.cubes[18].colors[3]; c->cubes[23].colors[2]=old.cubes[18].colors[4]; c->cubes[24].colors[1]=old.cubes[21].colors[1]; c->cubes[24].colors[2]=old.cubes[21].colors[4]; c->cubes[25].colors[1]=old.cubes[23].colors[1]; c->cubes[25].colors[2]=old.cubes[23].colors[4]; c->cubes[25].colors[5]=old.cubes[23].colors[2]; c->cubes[22].colors[1]=old.cubes[24].colors[1]; c->cubes[22].colors[5]=old.cubes[24].colors[2]; c->cubes[20].colors[1]=old.cubes[25].colors[1]; c->cubes[20].colors[5]=old.cubes[25].colors[2]; c->cubes[20].colors[3]=old.cubes[25].colors[5]; c->cubes[19].colors[1]=old.cubes[22].colors[1]; c->cubes[19].colors[3]=old.cubes[22].colors[5]; c->cubes[18].colors[1]=old.cubes[20].colors[1]; c->cubes[18].colors[3]=old.cubes[20].colors[5]; c->cubes[18].colors[4]=old.cubes[20].colors[3]; c->cubes[21].colors[1]=old.cubes[19].colors[1]; c->cubes[21].colors[4]=old.cubes[19].colors[3]; break; case 2 : c->cubes[23].colors[2]=old.cubes[25].colors[2]; c->cubes[23].colors[4]=old.cubes[25].colors[1]; c->cubes[23].colors[1]=old.cubes[25].colors[5]; c->cubes[16].colors[2]=old.cubes[24].colors[2]; c->cubes[16].colors[4]=old.cubes[24].colors[1]; c->cubes[11].colors[2]=old.cubes[23].colors[2]; c->cubes[11].colors[4]=old.cubes[23].colors[1]; c->cubes[11].colors[0]=old.cubes[23].colors[4]; c->cubes[12].colors[2]=old.cubes[16].colors[2]; c->cubes[12].colors[0]=old.cubes[16].colors[4]; c->cubes[13].colors[2]=old.cubes[11].colors[2]; c->cubes[13].colors[0]=old.cubes[11].colors[4]; c->cubes[13].colors[5]=old.cubes[11].colors[0]; c->cubes[17].colors[2]=old.cubes[12].colors[2]; c->cubes[17].colors[5]=old.cubes[12].colors[0]; c->cubes[25].colors[2]=old.cubes[13].colors[2]; c->cubes[25].colors[5]=old.cubes[13].colors[0]; c->cubes[25].colors[1]=old.cubes[13].colors[5]; c->cubes[24].colors[2]=old.cubes[17].colors[2]; c->cubes[24].colors[1]=old.cubes[17].colors[5]; break; case 3 : c->cubes[18].colors[3]=old.cubes[6].colors[3]; c->cubes[18].colors[4]=old.cubes[6].colors[0]; c->cubes[18].colors[1]=old.cubes[6].colors[4]; c->cubes[14].colors[3]=old.cubes[7].colors[3]; c->cubes[14].colors[4]=old.cubes[7].colors[0]; c->cubes[6].colors[3]=old.cubes[8].colors[3]; c->cubes[6].colors[4]=old.cubes[8].colors[0]; c->cubes[6].colors[0]=old.cubes[8].colors[5]; c->cubes[7].colors[3]=old.cubes[15].colors[3]; c->cubes[7].colors[0]=old.cubes[15].colors[5]; c->cubes[8].colors[3]=old.cubes[20].colors[3]; c->cubes[8].colors[0]=old.cubes[20].colors[5]; c->cubes[8].colors[5]=old.cubes[20].colors[1]; c->cubes[15].colors[3]=old.cubes[19].colors[3]; c->cubes[15].colors[5]=old.cubes[19].colors[1]; c->cubes[20].colors[3]=old.cubes[18].colors[3]; c->cubes[20].colors[5]=old.cubes[18].colors[1]; c->cubes[20].colors[1]=old.cubes[18].colors[4]; c->cubes[19].colors[3]=old.cubes[14].colors[3]; c->cubes[19].colors[1]=old.cubes[14].colors[4]; break; case 4 : c->cubes[23].colors[4]=old.cubes[11].colors[4]; c->cubes[23].colors[2]=old.cubes[11].colors[0]; c->cubes[23].colors[1]=old.cubes[11].colors[2]; c->cubes[16].colors[4]=old.cubes[9].colors[4]; c->cubes[16].colors[2]=old.cubes[9].colors[0]; c->cubes[11].colors[4]=old.cubes[6].colors[4]; c->cubes[11].colors[2]=old.cubes[6].colors[0]; c->cubes[11].colors[0]=old.cubes[6].colors[3]; c->cubes[9].colors[4]=old.cubes[14].colors[4]; c->cubes[9].colors[0]=old.cubes[14].colors[3]; c->cubes[6].colors[4]=old.cubes[18].colors[4]; c->cubes[6].colors[0]=old.cubes[18].colors[3]; c->cubes[6].colors[3]=old.cubes[18].colors[1]; c->cubes[14].colors[4]=old.cubes[21].colors[4]; c->cubes[14].colors[3]=old.cubes[21].colors[1]; c->cubes[18].colors[4]=old.cubes[23].colors[4]; c->cubes[18].colors[3]=old.cubes[23].colors[1]; c->cubes[18].colors[1]=old.cubes[23].colors[2]; c->cubes[21].colors[4]=old.cubes[16].colors[4]; c->cubes[21].colors[1]=old.cubes[16].colors[2]; break; case 5 : c->cubes[13].colors[5]=old.cubes[25].colors[5]; c->cubes[13].colors[2]=old.cubes[25].colors[1]; c->cubes[13].colors[0]=old.cubes[25].colors[2]; c->cubes[17].colors[5]=old.cubes[22].colors[5]; c->cubes[17].colors[2]=old.cubes[22].colors[1]; c->cubes[25].colors[5]=old.cubes[20].colors[5]; c->cubes[25].colors[2]=old.cubes[20].colors[1]; c->cubes[25].colors[1]=old.cubes[20].colors[3]; c->cubes[22].colors[5]=old.cubes[15].colors[5]; c->cubes[22].colors[1]=old.cubes[15].colors[3]; c->cubes[20].colors[5]=old.cubes[8].colors[5]; c->cubes[20].colors[1]=old.cubes[8].colors[3]; c->cubes[20].colors[3]=old.cubes[8].colors[0]; c->cubes[15].colors[5]=old.cubes[10].colors[5]; c->cubes[15].colors[3]=old.cubes[10].colors[0]; c->cubes[8].colors[5]=old.cubes[13].colors[5]; c->cubes[8].colors[3]=old.cubes[13].colors[0]; c->cubes[8].colors[0]=old.cubes[13].colors[2]; c->cubes[10].colors[5]=old.cubes[17].colors[5]; c->cubes[10].colors[0]=old.cubes[17].colors[2]; break; } } void cube_event(CUBE *c) { #define MAX 300. struct timeval tt=get_time(); double t=(float)(tt.tv_sec-c->time.tv_sec)*1000.+(float)(tt.tv_usec-c->time.tv_usec)/1000.; if (t>MAX) { c->anim = 0; c->angle = 0.0; cube_do_rotate(c); return; } else c->angle = M_PI/2.*(t/MAX); if (c->orient!=0) c->angle = -c->angle; } void cube_rotate(SCREEN *s, CUBE *c, double dx, double dy) { if (dx) xmat(dx, c->matrix); if (dy) ymat(dy, c->matrix); } void cube_generate_rotate(CUBE *c, SCREEN *s, int orient) { if (c->anim) return; if (s->pause) return; c->rotated = c->center; c->orient=orient; c->anim=1; c->time=get_time(); }