1 /*
2  * the Rubik's cube.
3  *
4  * Sed - april 1999 / december 2003.
5  *
6  * This program is in the public domain.
7  *--------------------
8  * The cube related stuff (init, project, rotate, so on)
9  */
10 
11 #include "cube.h"
12 
13 #include <ctype.h>
14 #include <string.h>
15 #include <math.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 
23 #include "screen.h"
24 #include "fillpoly.h"
25 #include "line.h"
26 #include "device.h"
27 
28 /* when you see those globals, you are very allowed to think i began to have hard work
29  * with all those angles, rotations, faces and so on. I am definitly not a good graphical
30  * coder. Am i a good coder in something anyway ?
31  */
32 
33 int nb_facettes;
34 int cur_facette;
35 
36 typedef struct {
37   double z;
38   double x0, y0, x1, y1, x2, y2, x3, y3;
39   int col, cross;
40 } facette;
41 
42 facette f[6*26];
43 int order[6*26];
44 int order1[6*26];
45 double e[8][3]; /* small cube edges */
46 
47 static void cube_do_rotate(CUBE *);
48 
save_cube(CUBE * c)49 void save_cube(CUBE *c)
50 {
51   static char letter[12] = "XABCDEFI012";
52   static short order[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 10, 9, 8};
53   char name[30];
54   char buffer[80];
55   int i, j, l;
56   int fd;
57 
58   sprintf(name, "rubix.%s", formats[FORMAT]);
59   name[9] = '\0';
60   fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644);
61 
62   if (fd==-1) {
63     perror("cube.save_cube.open");
64     return;
65   }
66 
67   if (write(fd, "%rubix\n\n", 8)!= 8) {
68      write_error:
69     perror("cube.save_cube.write");
70     close(fd);
71     unlink(name);
72     return;
73   }
74 
75   if (write(fd, "%colors\n", 8)!= 8) goto write_error;
76   for (i=0; i<11; i++) {
77     sprintf(buffer, "%c = %s\n", letter[i], palette[order[i]]);
78     l = strlen(buffer);
79     if (write(fd, buffer, l)!= l) goto write_error;
80   }
81 
82   if (write(fd, "\n%matrix\n\n", 9)!= 9) goto write_error;
83   for (i=0; i<3; i++) {
84     sprintf(buffer, "%14.10f %14.10f %14.10f\n",
85             c->matrix[i][0], c->matrix[i][1], c->matrix[i][2]);
86     l = strlen(buffer);
87     if (write(fd, buffer, l)!= l) goto write_error;
88   }
89 
90   if (FORMAT == 0) {
91     if (write(fd, "\n%position\n", 11)!= 11) goto write_error;
92     buffer[0] = buffer[1] = buffer[2] = buffer[3] = buffer[11] = ' ';
93     buffer[7] = '\n'; buffer[8] = buffer[9] = '\0';
94     buffer[4] = '@' + c->cubes[25].colors[1];
95     buffer[5] = '@' + c->cubes[22].colors[1];
96     buffer[6] = '@' + c->cubes[20].colors[1];
97     if (write(fd, buffer, 8)!= 8) goto write_error;
98     buffer[4] = '@' + c->cubes[24].colors[1];
99     buffer[5] = '@' + c->cubes[1].colors[1];
100     buffer[6] = '@' + c->cubes[19].colors[1];
101     if (write(fd, buffer, 8)!= 8) goto write_error;
102     buffer[4] = '@' + c->cubes[23].colors[1];
103     buffer[5] = '@' + c->cubes[21].colors[1];
104     buffer[6] = '@' + c->cubes[18].colors[1];
105     buffer[8] = '\n';
106     if (write(fd, buffer, 9)!= 9) goto write_error;
107     buffer[7] = ' '; buffer[15] = '\n' ; buffer[16] = buffer[17] = '\0';
108     buffer[0] = '@' + c->cubes[25].colors[2];
109     buffer[1] = '@' + c->cubes[24].colors[2];
110     buffer[2] = '@' + c->cubes[23].colors[2];
111     buffer[4] = '@' + c->cubes[23].colors[4];
112     buffer[5] = '@' + c->cubes[21].colors[4];
113     buffer[6] = '@' + c->cubes[18].colors[4];
114     buffer[8] = '@' + c->cubes[18].colors[3];
115     buffer[9] = '@' + c->cubes[19].colors[3];
116     buffer[10]= '@' + c->cubes[20].colors[3];
117     buffer[12]= '@' + c->cubes[20].colors[5];
118     buffer[13]= '@' + c->cubes[22].colors[5];
119     buffer[14]= '@' + c->cubes[25].colors[5];
120     if (write(fd, buffer, 16)!= 16) goto write_error;
121     buffer[0] = '@' + c->cubes[17].colors[2];
122     buffer[1] = '@' + c->cubes[2].colors[2];
123     buffer[2] = '@' + c->cubes[16].colors[2];
124     buffer[4] = '@' + c->cubes[16].colors[4];
125     buffer[5] = '@' + c->cubes[4].colors[4];
126     buffer[6] = '@' + c->cubes[14].colors[4];
127     buffer[8] = '@' + c->cubes[14].colors[3];
128     buffer[9] = '@' + c->cubes[3].colors[3];
129     buffer[10]= '@' + c->cubes[15].colors[3];
130     buffer[12]= '@' + c->cubes[15].colors[5];
131     buffer[13]= '@' + c->cubes[5].colors[5];
132     buffer[14]= '@' + c->cubes[17].colors[5];
133     if (write(fd, buffer, 16)!= 16) goto write_error;
134     buffer[0] = '@' + c->cubes[13].colors[2];
135     buffer[1] = '@' + c->cubes[12].colors[2];
136     buffer[2] = '@' + c->cubes[11].colors[2];
137     buffer[4] = '@' + c->cubes[11].colors[4];
138     buffer[5] = '@' + c->cubes[9].colors[4];
139     buffer[6] = '@' + c->cubes[6].colors[4];
140     buffer[8] = '@' + c->cubes[6].colors[3];
141     buffer[9] = '@' + c->cubes[7].colors[3];
142     buffer[10]= '@' + c->cubes[8].colors[3];
143     buffer[12]= '@' + c->cubes[8].colors[5];
144     buffer[13]= '@' + c->cubes[10].colors[5];
145     buffer[14]= '@' + c->cubes[13].colors[5];
146     buffer[16] = '\n';
147     if (write(fd, buffer, 17)!= 17) goto write_error;
148     buffer[0] = buffer[1] = buffer[2] = ' ';
149     buffer[7] = '\n'; buffer[8] = buffer[9] = '\0';
150     buffer[4] = '@' + c->cubes[11].colors[0];
151     buffer[5] = '@' + c->cubes[9].colors[0];
152     buffer[6] = '@' + c->cubes[6].colors[0];
153     if (write(fd, buffer, 8)!= 8) goto write_error;
154     buffer[4] = '@' + c->cubes[12].colors[0];
155     buffer[5] = '@' + c->cubes[0].colors[0];
156     buffer[6] = '@' + c->cubes[7].colors[0];
157     if (write(fd, buffer, 8)!= 8) goto write_error;
158     buffer[4] = '@' + c->cubes[13].colors[0];
159     buffer[5] = '@' + c->cubes[10].colors[0];
160     buffer[6] = '@' + c->cubes[8].colors[0];
161     if (write(fd, buffer, 8)!= 8) goto write_error;
162   }
163 
164   if (FORMAT == 1) {
165     if (write(fd, "\n%numeric\n", 10)!= 10) goto write_error;
166     buffer[6] ='\n';
167     buffer[7] = 0;
168     for (i=0; i<26; i++) {
169       for (j=0; j<6; j++)
170 	buffer[j] = '0'+c->cubes[i].colors[j];
171       if (write(fd, buffer, 7)!= 7) goto write_error;
172     }
173   }
174 
175   if (FORMAT == 2) {
176     if (write(fd, "\n%generators\n", 13)!= 13) goto write_error;
177     if (write(fd, ".\n", 2)!= 2) goto write_error;
178   }
179 
180   if (close(fd)==-1) {
181     perror("cube.save_cube.close");
182     unlink(name);
183     return;
184   }
185 }
186 
reset_cube(CUBE * c)187 void reset_cube(CUBE *c)
188 {
189   static double initmatrix[3][3]={
190     {1.0, 0.0, 0.0},
191     {0.0, 1.0, 0.0},
192     {0.0, 0.0, 1.0}};
193   memcpy(c->matrix, initmatrix, 9*sizeof(double));
194   c->center = 4;
195 }
196 
get_string(int fd,char * buffer,int max)197 int get_string(int fd, char *buffer, int max)
198 {
199   int i;
200   i = 0;
201   while (i<max) {
202     if (read(fd, buffer+i, 1)!=1) return (i==0)?-1:i;
203     if (buffer[i]==0) break;
204     if (buffer[i]=='\n') break;
205     ++i;
206   }
207   buffer[i] = '\0';
208   return i;
209 }
210 
load_cube(CUBE * c,char * name)211 void load_cube(CUBE *c, char *name)
212 {
213   int fd;
214   char buffer[96];
215   char *ptr;
216   char ch;
217   int i, j, k;
218 
219   fprintf(stderr, "Trying to load \"%s\"\n", name);
220 
221   FORMAT = 0;
222   reset_cube(c);
223   init_cube(c, NULL, 0);
224 
225   fd=open(name, O_RDONLY);
226   if (fd==-1) {
227     perror("cube.load_cube.open");
228     return;
229   }
230 
231   i = get_string(fd, buffer, 80);
232   if (i==-1 || i>=80) {
233    read_error:
234     perror("cube.load_cube.read");
235     close(fd);
236     return;
237   }
238 
239   if (strncmp(buffer, "%rubix", 6)) goto read_error;
240 
241   FORMAT = -1;
242 iter:
243   i = 0;
244   buffer[0] = ' ';
245   while (i>=0 && buffer[0]!='%') i = get_string(fd, buffer, 80);
246 finish:
247   if (i==-1) {
248     if (FORMAT==-1) goto read_error;
249     goto end_parsing;
250   }
251 new_section:
252   if (!strncmp(buffer, "%colors", 7)) {
253 iter_colors:
254     i = 0;
255     buffer[0] = ' ';
256     while (i>=0 && isspace(buffer[0])) i = get_string(fd, buffer, 80);
257     if (i==-1) goto finish;
258     if (buffer[0]=='%') goto new_section;
259     buffer[0]=toupper(buffer[0]);
260     ptr = index(buffer, '=');
261     if (ptr) {
262       ++ptr;
263       while (isspace(*ptr)) ++ptr;
264       if (buffer[0]>='A' && buffer[0]<='F') {
265         i = buffer[0] - 'A' + 1;
266 	palette[i] = strdup(ptr);
267       }
268       if (buffer[0]=='X')
269 	palette[0] = strdup(ptr);
270       if (buffer[0]=='I')
271 	palette[7] = strdup(ptr);
272       if (buffer[0]>='0' && buffer[0]<='2') {
273 	i = '9' - buffer[0] + 1;
274 	palette[i] = strdup(ptr);
275       }
276     }
277     goto iter_colors;
278   } else
279   if (!strncmp(buffer, "%position", 9)) {
280     FORMAT = 0;
281     i = 0;
282     while (i>=0 && i<7) i = get_string(fd, buffer, 80);
283     if (i==-1) goto finish;
284     c->cubes[25].colors[1] = buffer[4] - '@';
285     c->cubes[22].colors[1] = buffer[5] - '@';
286     c->cubes[20].colors[1] = buffer[6] - '@';
287     i = 0;
288     while (i>=0 && i<7) i = get_string(fd, buffer, 80);
289     if (i==-1) goto finish;
290     c->cubes[24].colors[1] = buffer[4] - '@';
291     c->cubes[1].colors[1] = buffer[5] - '@';
292     c->cubes[19].colors[1] = buffer[6] - '@';
293     i = 0;
294     while (i>=0 && i<7) i = get_string(fd, buffer, 80);
295     if (i==-1) goto finish;
296     c->cubes[23].colors[1] = buffer[4] - '@';
297     c->cubes[21].colors[1] = buffer[5] - '@';
298     c->cubes[18].colors[1] = buffer[6] - '@';
299     i = 0;
300     while (i>=0 && i<15) i = get_string(fd, buffer, 80);
301     if (i==-1) goto finish;
302     c->cubes[25].colors[2] = buffer[0] - '@';
303     c->cubes[24].colors[2] = buffer[1] - '@';
304     c->cubes[23].colors[2] = buffer[2] - '@';
305     c->cubes[23].colors[4] = buffer[4] - '@';
306     c->cubes[21].colors[4] = buffer[5] - '@';
307     c->cubes[18].colors[4] = buffer[6] - '@';
308     c->cubes[18].colors[3] = buffer[8] - '@';
309     c->cubes[19].colors[3] = buffer[9] - '@';
310     c->cubes[20].colors[3] = buffer[10] - '@';
311     c->cubes[20].colors[5] = buffer[12] - '@';
312     c->cubes[22].colors[5] = buffer[13] - '@';
313     c->cubes[25].colors[5] = buffer[14] - '@';
314     i = 0;
315     while (i>=0 && i<15) i = get_string(fd, buffer, 80);
316     if (i==-1) goto finish;
317     c->cubes[17].colors[2] = buffer[0] - '@';
318     c->cubes[2].colors[2] = buffer[1] - '@';
319     c->cubes[16].colors[2] = buffer[2] - '@';
320     c->cubes[16].colors[4] = buffer[4] - '@';
321     c->cubes[4].colors[4] = buffer[5] - '@';
322     c->cubes[14].colors[4] = buffer[6] - '@';
323     c->cubes[14].colors[3] = buffer[8] - '@';
324     c->cubes[3].colors[3] = buffer[9] - '@';
325     c->cubes[15].colors[3] = buffer[10] - '@';
326     c->cubes[15].colors[5] = buffer[12] - '@';
327     c->cubes[5].colors[5] = buffer[13] - '@';
328     c->cubes[17].colors[5] = buffer[14] - '@';
329     i = 0;
330     while (i>=0 && i<15) i = get_string(fd, buffer, 80);
331     if (i==-1) goto finish;
332     c->cubes[13].colors[2] = buffer[0] - '@';
333     c->cubes[12].colors[2] = buffer[1] - '@';
334     c->cubes[11].colors[2] = buffer[2] - '@';
335     c->cubes[11].colors[4] = buffer[4] - '@';
336     c->cubes[9].colors[4] = buffer[5] - '@';
337     c->cubes[6].colors[4] = buffer[6] - '@';
338     c->cubes[6].colors[3] = buffer[8] - '@';
339     c->cubes[7].colors[3] = buffer[9] - '@';
340     c->cubes[8].colors[3] = buffer[10] - '@';
341     c->cubes[8].colors[5] = buffer[12] - '@';
342     c->cubes[10].colors[5] = buffer[13] - '@';
343     c->cubes[13].colors[5] = buffer[14] - '@';
344     i = 0;
345     while (i>=0 && i<7) i = get_string(fd, buffer, 80);
346     if (i==-1) goto finish;
347     c->cubes[11].colors[0] = buffer[4] - '@';
348     c->cubes[9].colors[0] = buffer[5] - '@';
349     c->cubes[6].colors[0] = buffer[6] - '@';
350     i = 0;
351     while (i>=0 && i<7) i = get_string(fd, buffer, 80);
352     if (i==-1) goto finish;
353     c->cubes[12].colors[0] = buffer[4] - '@';
354     c->cubes[0].colors[0] = buffer[5] - '@';
355     c->cubes[7].colors[0] = buffer[6] - '@';
356     i = 0;
357     while (i>=0 && i<7) i = get_string(fd, buffer, 80);
358     if (i==-1) goto finish;
359     c->cubes[13].colors[0] = buffer[4] - '@';
360     c->cubes[10].colors[0] = buffer[5] - '@';
361     c->cubes[8].colors[0] = buffer[6] - '@';
362   } else
363   if (!strncmp(buffer, "%numeric", 8)) {
364     FORMAT = 1;
365     k = 0;
366     while (k<26) {
367       i = 0;
368       while (i>=0 && i<6) i = get_string(fd, buffer, 80);
369       if (i>=6) {
370 	for (j=0; j<6; j++)
371 	  c->cubes[k].colors[j] = buffer[j] - '0';
372 	k++;
373       }
374     }
375   } else
376   if (!strncmp(buffer, "%generators", 11)) {
377     FORMAT = 2;
378     while (read(fd, &ch, 1)==1) {
379       c->orient = -1;
380       if (ch=='.') break;
381       if ((ch>='a') && (ch<='f')) {
382         c->center = ch-'a';
383 	c->orient = 0;
384       } else
385       if ((ch>='A') && (ch<='F')) {
386 	c->center = ch-'A';
387 	c->orient = 0;
388       }
389       else if (!isspace(ch))
390 	fprintf(stderr, "Invalid character : %c\n", ch);
391       if (c->orient>=0)
392 	cube_do_rotate(c);
393     }
394     c->orient = 0;
395   } else
396   if (!strncmp(buffer, "%matrix", 7)) {
397     i = 0;
398     while (i>=0 && i<5) i = get_string(fd, buffer, 80);
399     if (i==-1) goto finish;
400     if (sscanf(buffer, "%lg %lg %lg",
401                &c->matrix[0][0],&c->matrix[0][1],&c->matrix[0][2])!=3)
402       goto read_error;
403     i = 0;
404     while (i>=0 && i<5) i = get_string(fd, buffer, 80);
405     if (i==-1) goto finish;
406     if (sscanf(buffer, "%lg %lg %lg",
407         &c->matrix[1][0],&c->matrix[1][1],&c->matrix[1][2])!=3)
408       goto read_error;
409     i = 0;
410     while (i>=0 && i<5) i = get_string(fd, buffer, 80);
411     if (i==-1) goto finish;
412     if (sscanf(buffer, "%lg %lg %lg",
413                &c->matrix[2][0],&c->matrix[2][1],&c->matrix[2][2])!=3)
414       goto read_error;
415   } else goto read_error;
416   goto iter;
417 
418 end_parsing:
419   if (close(fd)==-1) {
420     perror("cube.load_cube.close");
421     return;
422   }
423 }
424 
425 
init_cube(CUBE * c,char * file,int random)426 void init_cube(CUBE *c, char *file, int random)
427 {
428   int i, j;
429   static short initedge[8][3] = {
430                  {-1, -1, -1}, /* 0 */
431 		 {-1, -1,  1}, /* 1 */
432 		 {-1,  1, -1}, /* 2 */
433 		 {-1,  1,  1}, /* 3 */
434 		 { 1, -1, -1}, /* 4 */
435 		 { 1, -1,  1}, /* 5 */
436 		 { 1,  1, -1}, /* 6 */
437 		 { 1,  1,  1}};/* 7 */
438 #define X -1
439   static small_cube initsmallcube[26]=
440   {{x:  0, y: -1, z:  0, colors:{1,X,X,X,X,X}}, /*  0 */
441    {x:  0, y:  1, z:  0, colors:{X,2,X,X,X,X}}, /*  1 */
442    {x: -1, y:  0, z:  0, colors:{X,X,3,X,X,X}}, /*  2 */
443    {x:  1, y:  0, z:  0, colors:{X,X,X,4,X,X}}, /*  3 */
444    {x:  0, y:  0, z:  1, colors:{X,X,X,X,5,X}}, /*  4 */
445    {x:  0, y:  0, z: -1, colors:{X,X,X,X,X,6}}, /*  5 */
446    {x:  1, y: -1, z:  1, colors:{1,X,X,4,5,X}}, /*  6 */
447    {x:  1, y: -1, z:  0, colors:{1,X,X,4,X,X}}, /*  7 */
448    {x:  1, y: -1, z: -1, colors:{1,X,X,4,X,6}}, /*  8 */
449    {x:  0, y: -1, z:  1, colors:{1,X,X,X,5,X}}, /*  9 */
450    {x:  0, y: -1, z: -1, colors:{1,X,X,X,X,6}}, /* 10 */
451    {x: -1, y: -1, z:  1, colors:{1,X,3,X,5,X}}, /* 11 */
452    {x: -1, y: -1, z:  0, colors:{1,X,3,X,X,X}}, /* 12 */
453    {x: -1, y: -1, z: -1, colors:{1,X,3,X,X,6}}, /* 13 */
454    {x:  1, y:  0, z:  1, colors:{X,X,X,4,5,X}}, /* 14 */
455    {x:  1, y:  0, z: -1, colors:{X,X,X,4,X,6}}, /* 15 */
456    {x: -1, y:  0, z:  1, colors:{X,X,3,X,5,X}}, /* 16 */
457    {x: -1, y:  0, z: -1, colors:{X,X,3,X,X,6}}, /* 17 */
458    {x:  1, y:  1, z:  1, colors:{X,2,X,4,5,X}}, /* 18 */
459    {x:  1, y:  1, z:  0, colors:{X,2,X,4,X,X}}, /* 19 */
460    {x:  1, y:  1, z: -1, colors:{X,2,X,4,X,6}}, /* 20 */
461    {x:  0, y:  1, z:  1, colors:{X,2,X,X,5,X}}, /* 21 */
462    {x:  0, y:  1, z: -1, colors:{X,2,X,X,X,6}}, /* 22 */
463    {x: -1, y:  1, z:  1, colors:{X,2,3,X,5,X}}, /* 23 */
464    {x: -1, y:  1, z:  0, colors:{X,2,3,X,X,X}}, /* 24 */
465    {x: -1, y:  1, z: -1, colors:{X,2,3,X,X,6}}};/* 25 */
466 #undef X
467 
468   memcpy(c->cubes, initsmallcube, 26*sizeof(small_cube));
469   c->anim = 0;
470   c->orient = 0;
471   c->letters = 0;
472   c->angle = 0;
473   memset(&c->time, 0, sizeof(struct timeval));
474 
475   for (i=0; i<26*6; i++)
476     order1[i]=i;
477 
478   /* set small cube sizes */
479   for (i=0; i<8; i++)
480   for (j=0; j<3; j++)
481     e[i][j] = EDGE * initedge[i][j];
482 
483   /* let's randomize the cube */
484   if (random>0) {
485     struct timeval tt=get_time();
486     srand(tt.tv_sec-c->time.tv_sec+tt.tv_usec-c->time.tv_usec);
487     for (i=0; i<1000; i++) {
488       c->orient=2.0*rand()/(RAND_MAX+1.0);
489       c->rotated=6.0*rand()/(RAND_MAX+1.0);
490       cube_do_rotate(c);
491     }
492   } else if (random==0) {
493     if (file) {
494       load_cube(c, file);
495       return;
496     }
497   }
498 }
499 
mulm(double a[3][3],double b[3][3])500 void mulm(double a[3][3], double b[3][3])
501 {
502   int i, j;
503   double r[3][3];
504 
505   for (i=0; i<3; i++)
506     for (j=0; j<3; j++)
507       r[i][j]=(a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j]);
508   memcpy(a, r, 9*sizeof(double));
509 }
510 
xmat(double x,double m[3][3])511 void xmat(double x, double m[3][3])
512 {
513   double p[3][3]={{1.0,    0.0,   0.0},
514 		  {0.0, cos(x),sin(x)},
515 		  {0.0,-sin(x),cos(x)}};
516   mulm(m, p);
517 }
518 
ymat(double y,double m[3][3])519 void ymat(double y, double m[3][3])
520 {
521   double p[3][3]={{cos(y),0.0,-sin(y)},
522 		  {0.0,   1.0,    0.0},
523 		  {sin(y),0.0, cos(y)}};
524   mulm(m, p);
525 }
526 
zmat(double z,double m[3][3])527 void zmat(double z, double m[3][3])
528 {
529   double p[3][3]={{cos(z),sin(z),0},
530 		 {-sin(z),cos(z),0},
531 		 {0,0,1}};
532   mulm(m, p);
533 }
534 
clear_facette(void)535 void clear_facette(void)
536 {
537   nb_facettes=0;
538   memcpy(order, order1, sizeof(order));
539 }
540 
put_facette(double z,double x0,double y0,double x1,double y1,double x2,double y2,double x3,double y3,int color,int cross)541 void put_facette(double z, double x0, double y0, double x1, double y1,
542 		 double x2, double y2, double x3, double y3, int color,
543 		 int cross)
544 {
545   int i;
546 
547   cur_facette++;
548 
549   if ((x1-x0)*(y2-y0)-(y1-y0)*(x2-x0)>0)
550     return;
551 
552   i=nb_facettes++;
553   f[i].z=z;
554   f[i].x0=x0;
555   f[i].y0=y0;
556   f[i].x1=x1;
557   f[i].y1=y1;
558   f[i].x2=x2;
559   f[i].y2=y2;
560   f[i].x3=x3;
561   f[i].y3=y3;
562   f[i].col=color;
563   f[i].cross=cross;
564 }
565 
tri_facette(void)566 void tri_facette(void)
567 {
568   /* hehe, the very first time of my i use this gcc feature, the inline function ! Crazy */
569   int cmp(const void *u1, const void *u2) {
570     double z1=f[*(int *)u1].z, z2=f[*(int *)u2].z;
571     if (z1<z2)
572       return -1;
573     return z1>z2;
574   }
575   qsort(order, nb_facettes, sizeof(int), cmp);
576 }
577 
show_facette(SCREEN * s)578 void show_facette(SCREEN *s)
579 {
580   extern device d;
581   int i;
582   poly p;
583   line l;
584 
585   p.nb_points=4;
586   l.color=pixel[10];
587 
588   for(i=0; i<nb_facettes; i++) {
589     p.points[0].x=f[order[i]].x0;
590     p.points[0].y=f[order[i]].y0;
591     p.points[1].x=f[order[i]].x1;
592     p.points[1].y=f[order[i]].y1;
593     p.points[2].x=f[order[i]].x2;
594     p.points[2].y=f[order[i]].y2;
595     p.points[3].x=f[order[i]].x3;
596     p.points[3].y=f[order[i]].y3;
597     p.color = pixel[f[order[i]].col];
598     fillpoly(&d, &p);
599 #if 0
600     fill_triangle_8bpp(f[order[i]].x0, f[order[i]].y0, f[order[i]].x1, f[order[i]].y1,
601 		       f[order[i]].x2, f[order[i]].y2, f[order[i]].col);
602     fill_triangle_8bpp(f[order[i]].x0, f[order[i]].y0, f[order[i]].x2, f[order[i]].y2,
603 		       f[order[i]].x3, f[order[i]].y3, f[order[i]].col);
604 #endif
605 
606     l.p1.x=f[order[i]].x0;    l.p1.y=f[order[i]].y0;
607     l.p2.x=f[order[i]].x1;    l.p2.y=f[order[i]].y1;
608     drawline(&d, &l);
609     /* putline_8bpp(f[order[i]].x0, f[order[i]].y0, f[order[i]].x1, f[order[i]].y1, 0); */
610     l.p1.x=f[order[i]].x2;    l.p1.y=f[order[i]].y2;
611     l.p2.x=f[order[i]].x1;    l.p2.y=f[order[i]].y1;
612     drawline(&d, &l);
613     /* putline_8bpp(f[order[i]].x2, f[order[i]].y2, f[order[i]].x1, f[order[i]].y1, 0); */
614     l.p1.x=f[order[i]].x2;    l.p1.y=f[order[i]].y2;
615     l.p2.x=f[order[i]].x3;    l.p2.y=f[order[i]].y3;
616     drawline(&d, &l);
617     /* putline_8bpp(f[order[i]].x2, f[order[i]].y2, f[order[i]].x3, f[order[i]].y3, 0); */
618     l.p1.x=f[order[i]].x0;    l.p1.y=f[order[i]].y0;
619     l.p2.x=f[order[i]].x3;    l.p2.y=f[order[i]].y3;
620     drawline(&d, &l);
621     /* putline_8bpp(f[order[i]].x0, f[order[i]].y0, f[order[i]].x3, f[order[i]].y3, 0); */
622 
623     if (f[order[i]].cross) {
624       l.color = pixel[8];
625       l.p1.x=f[order[i]].x0;    l.p1.y=f[order[i]].y0;
626       l.p2.x=f[order[i]].x2;    l.p2.y=f[order[i]].y2;
627       l.p2.x = (l.p1.x+2*l.p2.x)/3;
628       l.p2.y = (l.p1.y+2*l.p2.y)/3;
629       l.p1.x = (l.p1.x+l.p2.x)/2;
630       l.p1.y = (l.p1.y+l.p2.y)/2;
631       drawline(&d, &l);
632       ++l.p1.x; ++l.p2.x;
633       drawline(&d, &l);
634       ++l.p1.y; ++l.p2.y;
635       drawline(&d, &l);
636       //putline_8bpp(f[order[i]].x0, f[order[i]].y0, f[order[i]].x2, f[order[i]].y2, /*f[order[i]].cross*/0);
637       l.p1.x=f[order[i]].x1;    l.p1.y=f[order[i]].y1;
638       l.p2.x=f[order[i]].x3;    l.p2.y=f[order[i]].y3;
639       l.p2.x = (l.p1.x+2*l.p2.x)/3;
640       l.p2.y = (l.p1.y+2*l.p2.y)/3;
641       l.p1.x = (l.p1.x+l.p2.x)/2;
642       l.p1.y = (l.p1.y+l.p2.y)/2;
643       drawline(&d, &l);
644       ++l.p1.x; ++l.p2.x;
645       drawline(&d, &l);
646       ++l.p1.y; ++l.p2.y;
647       drawline(&d, &l);
648       //putline_8bpp(f[order[i]].x1, f[order[i]].y1, f[order[i]].x3, f[order[i]].y3, /*f[order[i]].cross*/0);
649       l.color=pixel[10];
650     }
651   }
652 }
653 
show_letters(CUBE * big,SCREEN * s)654 void show_letters(CUBE *big, SCREEN *s)
655 {
656 #define M big->matrix
657   small_cube *c;
658   static Pixmap textpix;
659   static int bigendian;
660   XImage *xim = NULL;
661   int i, j, n, u, v, du, dv, dm, dw, dh;
662   char face[2];
663   char p=0, test;
664   double x, y, z, size, ratio;
665 
666   if (!big->letters) return;
667   face[1] = '\0';
668   dm = ((XTextWidth(s->font, "M", 1)+7)/8)*8;
669   dh = s->font->max_bounds.ascent+s->font->max_bounds.descent;
670   if (!xim) {
671      GC gc;
672      textpix = XCreatePixmap(s->d, s->w, 6*dm, dh, 1);
673      gc = XCreateGC(s->d, textpix, 0, 0);
674      bigendian = (ImageByteOrder(s->d) == MSBFirst);
675      XSetForeground(s->d, gc, 1);
676      XSetBackground(s->d, gc, 0);
677      XSetFont(s->d, gc, s->font->fid);
678      v = s->font->max_bounds.ascent;
679      for (n=0; n<6; n++) {
680        face[0] = 'A' + n;
681        XDrawImageString(s->d, textpix, gc, n*dm, v, face, 1);
682      }
683      XFreeGC(s->d, gc);
684      xim = XGetImage(s->d, textpix, 0, 0, 6*dm, dh, 1, XYPixmap);
685      XFreePixmap(s->d, textpix);
686   }
687 
688   du = XTextWidth(s->font, "A", 1)/2;
689   dv = s->font->max_bounds.ascent/2;
690   size = 1.0 + EDGE;
691   for (n=0; n<6; n++) {
692     c = &big->cubes[n];
693     z = size*(c->x*M[0][2]+ c->y*M[1][2]+ c->z*M[2][2]);
694     if (z>0.5*PERSPECTIVE)  {
695       face[0] = 'A' + n;
696       dw = XTextWidth(s->font, face, 1);
697       x = size*(c->x*M[0][0]+ c->y*M[1][0]+ c->z*M[2][0]);
698       y = size*(c->x*M[0][1]+ c->y*M[1][1]+ c->z*M[2][1]);
699       ratio = CUBE_SIZE/(5.0-PERSPECTIVE*z);
700       u = 0.5*SCREEN_X + ratio*x - du;
701       v = 0.5*SCREEN_Y - ratio*y + dv - s->font->max_bounds.ascent;
702       test = (bigendian)? 128 : 1;
703       for (j=0; j<dh; ++j)
704         for (i=0; i<dw; ++i) {
705           if ((i&7) == 0)
706 	    p = xim->data[j*xim->bytes_per_line+(i+n*dm)/8];
707           if (p&test)
708 	    XPutPixel(s->im, u+i, v+j, pixel[8]);
709 	  p = (bigendian)? p<<1 : p>>1;
710 	}
711     }
712   }
713 }
714 
display_small_cube(CUBE * big,SCREEN * s,int i)715 void display_small_cube(CUBE *big, SCREEN *s, int i)
716 {
717   static short u[6] = { 0, 2, 2, 1, 0, 1};
718   static short v[6] = { 2, 0, 1, 2, 1, 0};
719 //  static short opposite[6] = { 1, 0, 3, 2, 5, 4};
720   static short face[6][4]={{0,4,5,1},
721 			 {2,3,7,6},
722 			 {0,1,3,2},
723 			 {4,6,7,5},
724 			 {1,5,7,3},
725 			 {0,2,6,4}};
726   static short layers[6][26]={
727 /*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*/
728 { 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},
729 {-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},
730 { 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},
731 { 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},
732 { 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},
733 { 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}};
734 
735   double m[3][3];
736   double m1[3][3]={{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
737   double p1[8][3];
738   double p2[8][3];
739   double pp[8][2];
740   double ratio;
741   double zm;
742   small_cube *c;
743   int n;
744   //int k;
745 
746   memcpy(m, big->matrix, 9*sizeof(double));
747 
748   if (big->anim) {
749     n = big->rotated;
750     if (layers[n][i]==1) {
751       m1[u[n]][u[n]] = m1[v[n]][v[n]] = cos(big->angle);
752       m1[u[n]][v[n]] = sin(big->angle);
753       m1[v[n]][u[n]] = -m1[u[n]][v[n]];
754     }
755   }
756 
757   c = &big->cubes[i];
758   for (n=0; n<8; n++) {
759     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]));
760     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]));
761     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]));
762     p2[n][0]=((p1[n][0]*m[0][0]+ p1[n][1]*m[1][0]+ p1[n][2]*m[2][0]));
763     p2[n][1]=((p1[n][0]*m[0][1]+ p1[n][1]*m[1][1]+ p1[n][2]*m[2][1]));
764     p2[n][2]=((p1[n][0]*m[0][2]+ p1[n][1]*m[1][2]+ p1[n][2]*m[2][2]));
765     #define x (p2[n][0])
766     #define y (p2[n][1])
767     #define z (p2[n][2])
768     #define Xp (pp[n][0])
769     #define Yp (pp[n][1])
770 /*
771     Xp=320./2.+320./2.*x/(5.*(1.)-z);
772     Yp=120.-240./(2.*240./320.)*y/(5.*(1.)-z);
773 */
774     ratio = CUBE_SIZE/(5.0-PERSPECTIVE*z);
775     Xp = 0.5*SCREEN_X + ratio*x;
776     Yp = 0.5*SCREEN_Y - ratio*y;
777     #undef x
778     #undef y
779     #undef z
780     #undef Xp
781     #undef Yp
782   }
783 
784   /* if animation, draw in color 0 any visible internal face
785      from medium layer -- added by J.P. Demailly */
786   if (big->anim==1) {
787     n = big->rotated;
788     if (layers[n][i]==0 && c->colors[n]<0) {
789       zm=p2[face[n][0]][2]+p2[face[n][1]][2]+p2[face[n][2]][2]+p2[face[n][3]][2];
790       put_facette(zm, pp[face[n][0]][0], pp[face[n][0]][1], pp[face[n][1]][0], pp[face[n][1]][1],
791 		  pp[face[n][2]][0], pp[face[n][2]][1], pp[face[n][3]][0], pp[face[n][3]][1], 7, 0);
792     }
793   }
794 
795   if (big->anim==-1) {
796     for (n=0; n<6; n++)
797     if (c->colors[n]>=0) {
798       zm=p2[face[n][0]][2]+p2[face[n][1]][2]+p2[face[n][2]][2]+p2[face[n][3]][2];
799       put_facette(zm, pp[face[n][0]][0], pp[face[n][0]][1], pp[face[n][1]][0], pp[face[n][1]][1],
800 		  pp[face[n][2]][0], pp[face[n][2]][1], pp[face[n][3]][0], pp[face[n][3]][1], 7, 0);
801     }
802   }
803 
804 
805   /* draw visible faces */
806   for (n=0; n<6; n++) {
807     /* those tests WILL fail if you move the cube with the mouse while a face rotates */
808     /* so let's go back to the previous situation, where everything was fine */
809     //k = opposite[big->anim ? big->rotated : big->center];
810     //k = opposite[big->center];
811     //if ((n!=k || big->anim==-1) && c->colors[n]>=0) {
812     if (c->colors[n]>=0) {
813       zm=p2[face[n][0]][2]+p2[face[n][1]][2]+p2[face[n][2]][2]+p2[face[n][3]][2];
814       put_facette(zm, pp[face[n][0]][0], pp[face[n][0]][1], pp[face[n][1]][0], pp[face[n][1]][1],
815  	          pp[face[n][2]][0], pp[face[n][2]][1], pp[face[n][3]][0], pp[face[n][3]][1], c->colors[n],
816 		  //(big->anim ? i==big->rotated : i==big->center) && (!big->letters));
817 		  (i==big->center) && (!big->letters));
818     }
819   }
820 }
821 
z_middle(CUBE * c,int n)822 double z_middle(CUBE *c, int n)
823 {
824   #define m c->matrix
825   #define x (c->cubes[n].x)
826   #define y (c->cubes[n].y)
827   #define z (c->cubes[n].z)
828   /* well, well, well, i must have done something wrong, it should be
829    * m[2][0]*x+m[2][1]*y+m[2][2]*z, nope ? Well...
830    */
831   return m[0][2]*x+m[1][2]*y+m[2][2]*z;
832   #undef x
833   #undef y
834   #undef z
835   #undef m
836 }
837 
place_cross(CUBE * c)838 void place_cross(CUBE *c)
839 {
840   int i=1;
841   int n=0;
842   double z=z_middle(c, 0);
843 
844   while(i<6) {
845     double z1=z_middle(c, i);
846     if (z1>z) {
847       n=i;
848       z=z1;
849     }
850     i++;
851   }
852   if (c->anim!=-1)
853      c->center=n;
854 }
855 
display_cube(CUBE * c,SCREEN * s)856 void display_cube(CUBE *c, SCREEN *s)
857 {
858   int i;
859 
860   if (c->anim)
861     cube_event(c);
862 
863   place_cross(c);
864 
865   clear_facette();
866 
867   for (i=0; i<26; i++)
868     display_small_cube(c, s, i);
869 
870   tri_facette();
871   clear_screen(s);
872   show_facette(s);
873   if (c->anim == 0)
874      show_letters(c, s);
875   put_screen(c, s);
876 }
877 
878 /* c->orient and c->rotated are used so they must be set to their correct value */
cube_do_rotate(CUBE * c)879 static void cube_do_rotate(CUBE *c)
880 {
881   CUBE old;
882   memcpy(&old, c, sizeof(CUBE));
883   /* gotta change colors, woo woo woo */
884   if (c->orient==0)
885     switch(c->rotated) {
886       case 0 :
887 	c->cubes[11].colors[0]=old.cubes[6].colors[0];
888 	c->cubes[11].colors[2]=old.cubes[6].colors[4];
889 	c->cubes[11].colors[4]=old.cubes[6].colors[3];
890 	c->cubes[12].colors[0]=old.cubes[9].colors[0];
891 	c->cubes[12].colors[2]=old.cubes[9].colors[4];
892 	c->cubes[13].colors[0]=old.cubes[11].colors[0];
893 	c->cubes[13].colors[2]=old.cubes[11].colors[4];
894 	c->cubes[13].colors[5]=old.cubes[11].colors[2];
895 	c->cubes[10].colors[0]=old.cubes[12].colors[0];
896 	c->cubes[10].colors[5]=old.cubes[12].colors[2];
897 	c->cubes[8].colors[0]=old.cubes[13].colors[0];
898 	c->cubes[8].colors[5]=old.cubes[13].colors[2];
899 	c->cubes[8].colors[3]=old.cubes[13].colors[5];
900 	c->cubes[7].colors[0]=old.cubes[10].colors[0];
901 	c->cubes[7].colors[3]=old.cubes[10].colors[5];
902 	c->cubes[6].colors[0]=old.cubes[8].colors[0];
903 	c->cubes[6].colors[3]=old.cubes[8].colors[5];
904 	c->cubes[6].colors[4]=old.cubes[8].colors[3];
905 	c->cubes[9].colors[0]=old.cubes[7].colors[0];
906 	c->cubes[9].colors[4]=old.cubes[7].colors[3];
907 	break;
908       case 1 :
909 	c->cubes[18].colors[1]=old.cubes[23].colors[1];
910 	c->cubes[18].colors[3]=old.cubes[23].colors[4];
911 	c->cubes[18].colors[4]=old.cubes[23].colors[2];
912 	c->cubes[21].colors[1]=old.cubes[24].colors[1];
913 	c->cubes[21].colors[4]=old.cubes[24].colors[2];
914 	c->cubes[23].colors[1]=old.cubes[25].colors[1];
915 	c->cubes[23].colors[4]=old.cubes[25].colors[2];
916 	c->cubes[23].colors[2]=old.cubes[25].colors[5];
917 	c->cubes[24].colors[1]=old.cubes[22].colors[1];
918 	c->cubes[24].colors[2]=old.cubes[22].colors[5];
919 	c->cubes[25].colors[1]=old.cubes[20].colors[1];
920 	c->cubes[25].colors[2]=old.cubes[20].colors[5];
921 	c->cubes[25].colors[5]=old.cubes[20].colors[3];
922 	c->cubes[22].colors[1]=old.cubes[19].colors[1];
923 	c->cubes[22].colors[5]=old.cubes[19].colors[3];
924 	c->cubes[20].colors[1]=old.cubes[18].colors[1];
925 	c->cubes[20].colors[5]=old.cubes[18].colors[3];
926 	c->cubes[20].colors[3]=old.cubes[18].colors[4];
927 	c->cubes[19].colors[1]=old.cubes[21].colors[1];
928 	c->cubes[19].colors[3]=old.cubes[21].colors[4];
929 	break;
930       case 2 :
931 	c->cubes[25].colors[2]=old.cubes[23].colors[2];
932 	c->cubes[25].colors[1]=old.cubes[23].colors[4];
933 	c->cubes[25].colors[5]=old.cubes[23].colors[1];
934 	c->cubes[24].colors[2]=old.cubes[16].colors[2];
935 	c->cubes[24].colors[1]=old.cubes[16].colors[4];
936 	c->cubes[23].colors[2]=old.cubes[11].colors[2];
937 	c->cubes[23].colors[1]=old.cubes[11].colors[4];
938 	c->cubes[23].colors[4]=old.cubes[11].colors[0];
939 	c->cubes[16].colors[2]=old.cubes[12].colors[2];
940 	c->cubes[16].colors[4]=old.cubes[12].colors[0];
941 	c->cubes[11].colors[2]=old.cubes[13].colors[2];
942 	c->cubes[11].colors[4]=old.cubes[13].colors[0];
943 	c->cubes[11].colors[0]=old.cubes[13].colors[5];
944 	c->cubes[12].colors[2]=old.cubes[17].colors[2];
945 	c->cubes[12].colors[0]=old.cubes[17].colors[5];
946 	c->cubes[13].colors[2]=old.cubes[25].colors[2];
947 	c->cubes[13].colors[0]=old.cubes[25].colors[5];
948 	c->cubes[13].colors[5]=old.cubes[25].colors[1];
949 	c->cubes[17].colors[2]=old.cubes[24].colors[2];
950 	c->cubes[17].colors[5]=old.cubes[24].colors[1];
951 	break;
952       case 3 :
953 	c->cubes[6].colors[3]=old.cubes[18].colors[3];
954 	c->cubes[6].colors[0]=old.cubes[18].colors[4];
955 	c->cubes[6].colors[4]=old.cubes[18].colors[1];
956 	c->cubes[7].colors[3]=old.cubes[14].colors[3];
957 	c->cubes[7].colors[0]=old.cubes[14].colors[4];
958 	c->cubes[8].colors[3]=old.cubes[6].colors[3];
959 	c->cubes[8].colors[0]=old.cubes[6].colors[4];
960 	c->cubes[8].colors[5]=old.cubes[6].colors[0];
961 	c->cubes[15].colors[3]=old.cubes[7].colors[3];
962 	c->cubes[15].colors[5]=old.cubes[7].colors[0];
963 	c->cubes[20].colors[3]=old.cubes[8].colors[3];
964 	c->cubes[20].colors[5]=old.cubes[8].colors[0];
965 	c->cubes[20].colors[1]=old.cubes[8].colors[5];
966 	c->cubes[19].colors[3]=old.cubes[15].colors[3];
967 	c->cubes[19].colors[1]=old.cubes[15].colors[5];
968 	c->cubes[18].colors[3]=old.cubes[20].colors[3];
969 	c->cubes[18].colors[1]=old.cubes[20].colors[5];
970 	c->cubes[18].colors[4]=old.cubes[20].colors[1];
971 	c->cubes[14].colors[3]=old.cubes[19].colors[3];
972 	c->cubes[14].colors[4]=old.cubes[19].colors[1];
973 	break;
974       case 4 :
975 	c->cubes[11].colors[4]=old.cubes[23].colors[4];
976 	c->cubes[11].colors[0]=old.cubes[23].colors[2];
977 	c->cubes[11].colors[2]=old.cubes[23].colors[1];
978 	c->cubes[9].colors[4]=old.cubes[16].colors[4];
979 	c->cubes[9].colors[0]=old.cubes[16].colors[2];
980 	c->cubes[6].colors[4]=old.cubes[11].colors[4];
981 	c->cubes[6].colors[0]=old.cubes[11].colors[2];
982 	c->cubes[6].colors[3]=old.cubes[11].colors[0];
983 	c->cubes[14].colors[4]=old.cubes[9].colors[4];
984 	c->cubes[14].colors[3]=old.cubes[9].colors[0];
985 	c->cubes[18].colors[4]=old.cubes[6].colors[4];
986 	c->cubes[18].colors[3]=old.cubes[6].colors[0];
987 	c->cubes[18].colors[1]=old.cubes[6].colors[3];
988 	c->cubes[21].colors[4]=old.cubes[14].colors[4];
989 	c->cubes[21].colors[1]=old.cubes[14].colors[3];
990 	c->cubes[23].colors[4]=old.cubes[18].colors[4];
991 	c->cubes[23].colors[1]=old.cubes[18].colors[3];
992 	c->cubes[23].colors[2]=old.cubes[18].colors[1];
993 	c->cubes[16].colors[4]=old.cubes[21].colors[4];
994 	c->cubes[16].colors[2]=old.cubes[21].colors[1];
995 	break;
996       case 5 :
997 	c->cubes[25].colors[5]=old.cubes[13].colors[5];
998 	c->cubes[25].colors[1]=old.cubes[13].colors[2];
999 	c->cubes[25].colors[2]=old.cubes[13].colors[0];
1000 	c->cubes[22].colors[5]=old.cubes[17].colors[5];
1001 	c->cubes[22].colors[1]=old.cubes[17].colors[2];
1002 	c->cubes[20].colors[5]=old.cubes[25].colors[5];
1003 	c->cubes[20].colors[1]=old.cubes[25].colors[2];
1004 	c->cubes[20].colors[3]=old.cubes[25].colors[1];
1005 	c->cubes[15].colors[5]=old.cubes[22].colors[5];
1006 	c->cubes[15].colors[3]=old.cubes[22].colors[1];
1007 	c->cubes[8].colors[5]=old.cubes[20].colors[5];
1008 	c->cubes[8].colors[3]=old.cubes[20].colors[1];
1009 	c->cubes[8].colors[0]=old.cubes[20].colors[3];
1010 	c->cubes[10].colors[5]=old.cubes[15].colors[5];
1011 	c->cubes[10].colors[0]=old.cubes[15].colors[3];
1012 	c->cubes[13].colors[5]=old.cubes[8].colors[5];
1013 	c->cubes[13].colors[0]=old.cubes[8].colors[3];
1014 	c->cubes[13].colors[2]=old.cubes[8].colors[0];
1015 	c->cubes[17].colors[5]=old.cubes[10].colors[5];
1016 	c->cubes[17].colors[2]=old.cubes[10].colors[0];
1017 	break;
1018     }
1019   else
1020     switch(c->rotated) {
1021       case 0 :
1022 	c->cubes[6].colors[0]=old.cubes[11].colors[0];
1023 	c->cubes[6].colors[4]=old.cubes[11].colors[2];
1024 	c->cubes[6].colors[3]=old.cubes[11].colors[4];
1025 	c->cubes[9].colors[0]=old.cubes[12].colors[0];
1026 	c->cubes[9].colors[4]=old.cubes[12].colors[2];
1027 	c->cubes[11].colors[0]=old.cubes[13].colors[0];
1028 	c->cubes[11].colors[4]=old.cubes[13].colors[2];
1029 	c->cubes[11].colors[2]=old.cubes[13].colors[5];
1030 	c->cubes[12].colors[0]=old.cubes[10].colors[0];
1031 	c->cubes[12].colors[2]=old.cubes[10].colors[5];
1032 	c->cubes[13].colors[0]=old.cubes[8].colors[0];
1033 	c->cubes[13].colors[2]=old.cubes[8].colors[5];
1034 	c->cubes[13].colors[5]=old.cubes[8].colors[3];
1035 	c->cubes[10].colors[0]=old.cubes[7].colors[0];
1036 	c->cubes[10].colors[5]=old.cubes[7].colors[3];
1037 	c->cubes[8].colors[0]=old.cubes[6].colors[0];
1038 	c->cubes[8].colors[5]=old.cubes[6].colors[3];
1039 	c->cubes[8].colors[3]=old.cubes[6].colors[4];
1040 	c->cubes[7].colors[0]=old.cubes[9].colors[0];
1041 	c->cubes[7].colors[3]=old.cubes[9].colors[4];
1042 	break;
1043       case 1 :
1044 	c->cubes[23].colors[1]=old.cubes[18].colors[1];
1045 	c->cubes[23].colors[4]=old.cubes[18].colors[3];
1046 	c->cubes[23].colors[2]=old.cubes[18].colors[4];
1047 	c->cubes[24].colors[1]=old.cubes[21].colors[1];
1048 	c->cubes[24].colors[2]=old.cubes[21].colors[4];
1049 	c->cubes[25].colors[1]=old.cubes[23].colors[1];
1050 	c->cubes[25].colors[2]=old.cubes[23].colors[4];
1051 	c->cubes[25].colors[5]=old.cubes[23].colors[2];
1052 	c->cubes[22].colors[1]=old.cubes[24].colors[1];
1053 	c->cubes[22].colors[5]=old.cubes[24].colors[2];
1054 	c->cubes[20].colors[1]=old.cubes[25].colors[1];
1055 	c->cubes[20].colors[5]=old.cubes[25].colors[2];
1056 	c->cubes[20].colors[3]=old.cubes[25].colors[5];
1057 	c->cubes[19].colors[1]=old.cubes[22].colors[1];
1058 	c->cubes[19].colors[3]=old.cubes[22].colors[5];
1059 	c->cubes[18].colors[1]=old.cubes[20].colors[1];
1060 	c->cubes[18].colors[3]=old.cubes[20].colors[5];
1061 	c->cubes[18].colors[4]=old.cubes[20].colors[3];
1062 	c->cubes[21].colors[1]=old.cubes[19].colors[1];
1063 	c->cubes[21].colors[4]=old.cubes[19].colors[3];
1064 	break;
1065       case 2 :
1066 	c->cubes[23].colors[2]=old.cubes[25].colors[2];
1067 	c->cubes[23].colors[4]=old.cubes[25].colors[1];
1068 	c->cubes[23].colors[1]=old.cubes[25].colors[5];
1069 	c->cubes[16].colors[2]=old.cubes[24].colors[2];
1070 	c->cubes[16].colors[4]=old.cubes[24].colors[1];
1071 	c->cubes[11].colors[2]=old.cubes[23].colors[2];
1072 	c->cubes[11].colors[4]=old.cubes[23].colors[1];
1073 	c->cubes[11].colors[0]=old.cubes[23].colors[4];
1074 	c->cubes[12].colors[2]=old.cubes[16].colors[2];
1075 	c->cubes[12].colors[0]=old.cubes[16].colors[4];
1076 	c->cubes[13].colors[2]=old.cubes[11].colors[2];
1077 	c->cubes[13].colors[0]=old.cubes[11].colors[4];
1078 	c->cubes[13].colors[5]=old.cubes[11].colors[0];
1079 	c->cubes[17].colors[2]=old.cubes[12].colors[2];
1080 	c->cubes[17].colors[5]=old.cubes[12].colors[0];
1081 	c->cubes[25].colors[2]=old.cubes[13].colors[2];
1082 	c->cubes[25].colors[5]=old.cubes[13].colors[0];
1083 	c->cubes[25].colors[1]=old.cubes[13].colors[5];
1084 	c->cubes[24].colors[2]=old.cubes[17].colors[2];
1085 	c->cubes[24].colors[1]=old.cubes[17].colors[5];
1086 	break;
1087       case 3 :
1088 	c->cubes[18].colors[3]=old.cubes[6].colors[3];
1089 	c->cubes[18].colors[4]=old.cubes[6].colors[0];
1090 	c->cubes[18].colors[1]=old.cubes[6].colors[4];
1091 	c->cubes[14].colors[3]=old.cubes[7].colors[3];
1092 	c->cubes[14].colors[4]=old.cubes[7].colors[0];
1093 	c->cubes[6].colors[3]=old.cubes[8].colors[3];
1094 	c->cubes[6].colors[4]=old.cubes[8].colors[0];
1095 	c->cubes[6].colors[0]=old.cubes[8].colors[5];
1096 	c->cubes[7].colors[3]=old.cubes[15].colors[3];
1097 	c->cubes[7].colors[0]=old.cubes[15].colors[5];
1098 	c->cubes[8].colors[3]=old.cubes[20].colors[3];
1099 	c->cubes[8].colors[0]=old.cubes[20].colors[5];
1100 	c->cubes[8].colors[5]=old.cubes[20].colors[1];
1101 	c->cubes[15].colors[3]=old.cubes[19].colors[3];
1102 	c->cubes[15].colors[5]=old.cubes[19].colors[1];
1103 	c->cubes[20].colors[3]=old.cubes[18].colors[3];
1104 	c->cubes[20].colors[5]=old.cubes[18].colors[1];
1105 	c->cubes[20].colors[1]=old.cubes[18].colors[4];
1106 	c->cubes[19].colors[3]=old.cubes[14].colors[3];
1107 	c->cubes[19].colors[1]=old.cubes[14].colors[4];
1108 	break;
1109       case 4 :
1110 	c->cubes[23].colors[4]=old.cubes[11].colors[4];
1111 	c->cubes[23].colors[2]=old.cubes[11].colors[0];
1112 	c->cubes[23].colors[1]=old.cubes[11].colors[2];
1113 	c->cubes[16].colors[4]=old.cubes[9].colors[4];
1114 	c->cubes[16].colors[2]=old.cubes[9].colors[0];
1115 	c->cubes[11].colors[4]=old.cubes[6].colors[4];
1116 	c->cubes[11].colors[2]=old.cubes[6].colors[0];
1117 	c->cubes[11].colors[0]=old.cubes[6].colors[3];
1118 	c->cubes[9].colors[4]=old.cubes[14].colors[4];
1119 	c->cubes[9].colors[0]=old.cubes[14].colors[3];
1120 	c->cubes[6].colors[4]=old.cubes[18].colors[4];
1121 	c->cubes[6].colors[0]=old.cubes[18].colors[3];
1122 	c->cubes[6].colors[3]=old.cubes[18].colors[1];
1123 	c->cubes[14].colors[4]=old.cubes[21].colors[4];
1124 	c->cubes[14].colors[3]=old.cubes[21].colors[1];
1125 	c->cubes[18].colors[4]=old.cubes[23].colors[4];
1126 	c->cubes[18].colors[3]=old.cubes[23].colors[1];
1127 	c->cubes[18].colors[1]=old.cubes[23].colors[2];
1128 	c->cubes[21].colors[4]=old.cubes[16].colors[4];
1129 	c->cubes[21].colors[1]=old.cubes[16].colors[2];
1130 	break;
1131       case 5 :
1132 	c->cubes[13].colors[5]=old.cubes[25].colors[5];
1133 	c->cubes[13].colors[2]=old.cubes[25].colors[1];
1134 	c->cubes[13].colors[0]=old.cubes[25].colors[2];
1135 	c->cubes[17].colors[5]=old.cubes[22].colors[5];
1136 	c->cubes[17].colors[2]=old.cubes[22].colors[1];
1137 	c->cubes[25].colors[5]=old.cubes[20].colors[5];
1138 	c->cubes[25].colors[2]=old.cubes[20].colors[1];
1139 	c->cubes[25].colors[1]=old.cubes[20].colors[3];
1140 	c->cubes[22].colors[5]=old.cubes[15].colors[5];
1141 	c->cubes[22].colors[1]=old.cubes[15].colors[3];
1142 	c->cubes[20].colors[5]=old.cubes[8].colors[5];
1143 	c->cubes[20].colors[1]=old.cubes[8].colors[3];
1144 	c->cubes[20].colors[3]=old.cubes[8].colors[0];
1145 	c->cubes[15].colors[5]=old.cubes[10].colors[5];
1146 	c->cubes[15].colors[3]=old.cubes[10].colors[0];
1147 	c->cubes[8].colors[5]=old.cubes[13].colors[5];
1148 	c->cubes[8].colors[3]=old.cubes[13].colors[0];
1149 	c->cubes[8].colors[0]=old.cubes[13].colors[2];
1150 	c->cubes[10].colors[5]=old.cubes[17].colors[5];
1151 	c->cubes[10].colors[0]=old.cubes[17].colors[2];
1152 	break;
1153     }
1154 }
1155 
cube_event(CUBE * c)1156 void cube_event(CUBE *c)
1157 {
1158 #define MAX	300.
1159   struct timeval tt=get_time();
1160   double t=(float)(tt.tv_sec-c->time.tv_sec)*1000.+(float)(tt.tv_usec-c->time.tv_usec)/1000.;
1161 
1162   if (t>MAX) {
1163     c->anim = 0;
1164     c->angle = 0.0;
1165     cube_do_rotate(c);
1166     return;
1167   } else
1168     c->angle = M_PI/2.*(t/MAX);
1169 
1170   if (c->orient!=0)
1171     c->angle = -c->angle;
1172 }
1173 
cube_rotate(SCREEN * s,CUBE * c,double dx,double dy)1174 void cube_rotate(SCREEN *s, CUBE *c, double dx, double dy)
1175 {
1176   if (dx)
1177     xmat(dx, c->matrix);
1178   if (dy)
1179     ymat(dy, c->matrix);
1180 }
1181 
cube_generate_rotate(CUBE * c,SCREEN * s,int orient)1182 void cube_generate_rotate(CUBE *c, SCREEN *s, int orient)
1183 {
1184   if (c->anim)
1185     return;
1186 
1187   if (s->pause)
1188     return;
1189 
1190   c->rotated = c->center;
1191   c->orient=orient;
1192   c->anim=1;
1193   c->time=get_time();
1194 }
1195