3 * plays through a chess game ending. enjoy.
5 * version 1.0 - June 6, 2002
7 * Copyright (C) 2002-2008 Blair Tennessy (tennessb@unbc.ca)
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appear in all copies and that both that
12 * copyright notice and this permission notice appear in supporting
13 * documentation. No representations are made about the suitability of this
14 * software for any purpose. It is provided "as is" without express or
19 #define DEFAULTS "*delay: 20000 \n" \
20 "*showFPS: False \n" \
21 "*wireframe: False \n" \
23 # define refresh_chess 0
24 # include "xlockmore.h"
35 #include "gltrackball.h"
36 #include "chessmodels.h"
37 #include "chessgames.h"
40 #define countof(x) (sizeof((x))/sizeof((*x)))
42 #define DEF_ROTATE "True"
43 #define DEF_REFLECTIONS "True"
44 #define DEF_SHADOWS "True"
45 #define DEF_SMOOTH "True"
46 #define DEF_CLASSIC "False"
49 static XrmOptionDescRec opts[] = {
50 {"+rotate", ".chess.rotate", XrmoptionNoArg, "false" },
51 {"-rotate", ".chess.rotate", XrmoptionNoArg, "true" },
52 {"+reflections", ".chess.reflections", XrmoptionNoArg, "false" },
53 {"-reflections", ".chess.reflections", XrmoptionNoArg, "true" },
54 {"+shadows", ".chess.shadows", XrmoptionNoArg, "false" },
55 {"-shadows", ".chess.shadows", XrmoptionNoArg, "true" },
56 {"+smooth", ".chess.smooth", XrmoptionNoArg, "false" },
57 {"-smooth", ".chess.smooth", XrmoptionNoArg, "true" },
58 {"+classic", ".chess.classic", XrmoptionNoArg, "false" },
59 {"-classic", ".chess.classic", XrmoptionNoArg, "true" },
62 static int rotate, reflections, smooth, shadows, classic;
64 static argtype vars[] = {
65 {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool},
66 {&reflections, "reflections", "Reflections", DEF_REFLECTIONS, t_Bool},
67 {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool},
68 {&smooth, "smooth", "Smooth", DEF_SMOOTH, t_Bool},
69 {&classic, "classic", "Classic", DEF_CLASSIC, t_Bool},
72 ENTRYPOINT ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, NULL};
75 ModStruct chess_description =
76 {"chess", "init_chess", "draw_chess", "release_chess",
77 "draw_chess", "init_chess", NULL, &chess_opts,
78 1000, 1, 2, 1, 4, 1.0, "",
83 #define checkImageWidth 16
84 #define checkImageHeight 16
87 GLXContext *glx_context;
89 trackball_state *trackball;
95 /** definition of white/black (orange/gray) colors */
98 GLubyte checkImage[checkImageWidth][checkImageHeight][3];
99 GLuint piecetexture, boardtexture;
101 int mpiece, tpiece, steps, done;
102 double from[2], to[2];
104 int moving, take, mc, count, wire;
108 GLfloat position2[4];
116 int poly_counts[PIECES]; /* polygon count of each type of piece */
121 static Chesscreen *qs = NULL;
123 static const GLfloat MaterialShadow[] = {0.0, 0.0, 0.0, 0.3};
126 /* i prefer silvertip */
127 static const GLfloat whites[WHITES][3] =
136 static void build_colors(Chesscreen *cs)
140 int newwhite = cs->oldwhite;
141 while(newwhite == cs->oldwhite)
142 newwhite = random()%WHITES;
143 cs->oldwhite = newwhite;
145 cs->colors[0][0] = whites[cs->oldwhite][0];
146 cs->colors[0][1] = whites[cs->oldwhite][1];
147 cs->colors[0][2] = whites[cs->oldwhite][2];
150 /* build piece texture */
151 static void make_piece_texture(Chesscreen *cs)
155 for (i = 0; i < checkImageWidth; i++) {
156 for (j = 0; j < checkImageHeight; j++) {
157 c = ((j%2) == 0 || i%2 == 0) ? 240 : 180+random()%16;
158 cs->checkImage[i][j][0] = (GLubyte) c;
159 cs->checkImage[i][j][1] = (GLubyte) c;
160 cs->checkImage[i][j][2] = (GLubyte) c;
164 glGenTextures(1, &cs->piecetexture);
165 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
167 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
168 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
169 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
170 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
171 glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth,
172 checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
173 &cs->checkImage[0][0]);
176 /* build board texture (uniform noise in [180,180+50]) */
177 static void make_board_texture(Chesscreen *cs)
181 for (i = 0; i < checkImageWidth; i++) {
182 for (j = 0; j < checkImageHeight; j++) {
183 c = 180 + random()%51;
184 cs->checkImage[i][j][0] = (GLubyte) c;
185 cs->checkImage[i][j][1] = (GLubyte) c;
186 cs->checkImage[i][j][2] = (GLubyte) c;
190 glGenTextures(1, &cs->boardtexture);
191 glBindTexture(GL_TEXTURE_2D, cs->boardtexture);
193 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
194 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
195 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
196 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
197 glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth,
198 checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
199 &cs->checkImage[0][0]);
202 /** handle X event (trackball) */
203 ENTRYPOINT Bool chess_handle_event (ModeInfo *mi, XEvent *event)
205 Chesscreen *cs = &qs[MI_SCREEN(mi)];
207 if (gltrackball_event_handler (event, cs->trackball,
208 MI_WIDTH (mi), MI_HEIGHT (mi),
211 else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
220 static const GLfloat diffuse2[] = {1.0, 1.0, 1.0, 1.0};
221 /*static const GLfloat ambient2[] = {0.7, 0.7, 0.7, 1.0};*/
222 static const GLfloat shininess[] = {60.0};
223 static const GLfloat specular[] = {0.4, 0.4, 0.4, 1.0};
225 /* configure lighting */
226 static void setup_lights(Chesscreen *cs)
228 glEnable(GL_LIGHTING);
229 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
230 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse2);
233 /* glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient2); */
235 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
236 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
238 glLightfv(GL_LIGHT1, GL_SPECULAR, diffuse2);
239 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse2);
244 static void drawPieces(ModeInfo *mi, Chesscreen *cs)
248 for(i = 0; i < BOARDSIZE; ++i) {
249 for(j = 0; j < BOARDSIZE; ++j) {
250 if(cs->game.board[i][j]) {
251 int c = cs->game.board[i][j]/PIECES;
252 glColor3fv(cs->colors[c]);
253 glCallList(cs->game.board[i][j]%PIECES);
254 mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES];
257 glTranslatef(1.0, 0.0, 0.0);
260 glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0);
263 glTranslatef(0.0, 0.0, -1.0*BOARDSIZE);
267 static void drawPiecesShadow(ModeInfo *mi, Chesscreen *cs)
271 for(i = 0; i < BOARDSIZE; ++i) {
272 for(j = 0; j < BOARDSIZE; ++j) {
273 if(cs->game.board[i][j]) {
274 glColor4f(0.0, 0.0, 0.0, 0.4);
275 glCallList(cs->game.board[i][j]%PIECES);
276 mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES];
279 glTranslatef(1.0, 0.0, 0.0);
282 glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0);
285 glTranslatef(0.0, 0.0, -1.0*BOARDSIZE);
288 /* draw a moving piece */
289 static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow)
291 int piece = cs->mpiece % PIECES;
293 if (piece == NONE) return;
297 if(shadow) glColor4fv(MaterialShadow);
298 else glColor3fv(cs->colors[cs->mpiece/PIECES]);
300 /** assume a queening. should be more general */
301 if((cs->mpiece == PAWN && fabs(cs->to[0]) < 0.01) ||
302 (cs->mpiece == BPAWN && fabs(cs->to[0]-7.0) < 0.01)) {
303 glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz);
305 glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->mpiece/7][0],
306 shadow ? MaterialShadow[1] : cs->colors[cs->mpiece/7][1],
307 shadow ? MaterialShadow[2] : cs->colors[cs->mpiece/7][2],
308 (fabs(50.0-cs->steps))/50.0);
310 piece = cs->steps < 50 ? PAWN : QUEEN;
314 cs->mpiece = cs->mpiece == PAWN ? QUEEN : BQUEEN;
316 else if(cs->mpiece % PIECES == KNIGHT) {
317 /* If there is nothing in the path of a knight, move it by sliding,
318 just like the other pieces. But if there are any pieces on the
319 middle two squares in its path, the knight would intersect them,
320 so in that case, move it in an airborne arc. */
323 Bool blocked_p = False;
324 int fromx = MIN(cs->from[1], cs->to[1]);
325 int fromy = MIN(cs->from[0], cs->to[0]);
326 int tox = MAX(cs->from[1], cs->to[1]);
327 int toy = MAX(cs->from[0], cs->to[0]);
328 if (fromx == tox-2) fromx = tox = fromx+1;
329 if (fromy == toy-2) fromy = toy = fromy+1;
330 for (i = fromy; i <= toy; i++) {
331 for (j = fromx; j <= tox; j++) {
332 if (cs->game.board[i][j]) {
342 /* Move by hopping. */
343 y = 1.5 * sin (M_PI * cs->steps / 100.0);
344 glTranslatef(cs->from[1]+cs->steps*cs->dx, y,
345 cs->from[0]+cs->steps*cs->dz);
349 /* Move by sliding. */
350 glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz);
358 mi->polygon_count += cs->poly_counts[cs->mpiece % PIECES];
360 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
361 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
369 /** code to squish a taken piece */
370 static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow)
375 glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][0],
376 shadow ? MaterialShadow[1] : cs->colors[cs->tpiece/7][1],
377 shadow ? MaterialShadow[2] : cs->colors[cs->tpiece/7][2],
378 (100-1.6*cs->steps)/100.0);
380 glTranslatef(cs->to[1], 0.0, cs->to[0]);
382 if(cs->mpiece % PIECES == KNIGHT)
383 glScalef(1.0+cs->steps/100.0, 1.0, 1.0+cs->steps/100.0);
385 glScalef(1.0, 1 - cs->steps/50.0 > 0.01 ? 1 - cs->steps/50.0 : 0.01, 1.0);
386 glCallList(cs->tpiece % 7);
387 mi->polygon_count += cs->poly_counts[cs->tpiece % PIECES];
394 static void drawBoard(ModeInfo *mi, Chesscreen *cs)
400 for(i = 0; i < BOARDSIZE; ++i)
401 for(j = 0; j < BOARDSIZE; ++j) {
402 double ma1 = (i+j)%2 == 0 ? cs->mod*i : 0.0;
403 double mb1 = (i+j)%2 == 0 ? cs->mod*j : 0.0;
404 double ma2 = (i+j)%2 == 0 ? cs->mod*(i+1.0) : 0.01;
405 double mb2 = (i+j)%2 == 0 ? cs->mod*(j+1.0) : 0.01;
407 /*glColor3fv(colors[(i+j)%2]);*/
408 glColor4f(cs->colors[(i+j)%2][0], cs->colors[(i+j)%2][1],
409 cs->colors[(i+j)%2][2], 0.65);
411 glNormal3f(0.0, 1.0, 0.0);
412 /* glTexCoord2f(mod*i, mod*(j+1.0)); */
413 glTexCoord2f(ma1, mb2);
414 glVertex3f(i, 0.0, j + 1.0);
415 /* glTexCoord2f(mod*(i+1.0), mod*(j+1.0)); */
416 glTexCoord2f(ma2, mb2);
417 glVertex3f(i + 1.0, 0.0, j + 1.0);
418 glTexCoord2f(ma2, mb1);
419 /* glTexCoord2f(mod*(i+1.0), mod*j); */
420 glVertex3f(i + 1.0, 0.0, j);
421 glTexCoord2f(ma1, mb1);
422 /* glTexCoord2f(mod*i, mod*j); */
423 glVertex3f(i, 0.0, j);
431 GLfloat w = BOARDSIZE;
434 /* Give the board a slight lip. */
435 /* #### oops, normals are wrong here, but you can't tell */
437 glColor3f(0.3, 0.3, 0.3);
439 glVertex3f (0, 0, 0);
440 glVertex3f (0, -h, 0);
441 glVertex3f (0, -h, w);
442 glVertex3f (0, 0, w);
444 glVertex3f (0, 0, w);
445 glVertex3f (0, -h, w);
446 glVertex3f (w, -h, w);
447 glVertex3f (w, 0, w);
449 glVertex3f (w, 0, w);
450 glVertex3f (w, -h, w);
451 glVertex3f (w, -h, 0);
452 glVertex3f (w, 0, 0);
454 glVertex3f (w, 0, 0);
455 glVertex3f (w, -h, 0);
456 glVertex3f (0, -h, 0);
457 glVertex3f (0, 0, 0);
459 glVertex3f (0, -h, 0);
460 glVertex3f (w, -h, 0);
461 glVertex3f (w, -h, w);
462 glVertex3f (0, -h, w);
464 mi->polygon_count += 4;
466 /* Fill in the underside of the board with an invisible black box
467 to hide the reflections that are not on tiles. Probably there's
468 a way to do this with stencils instead.
474 glTranslatef (off, 0, off);
475 glDisable(GL_LIGHTING);
478 glVertex3f (0, 0, 0);
479 glVertex3f (0, -h, 0);
480 glVertex3f (0, -h, w);
481 glVertex3f (0, 0, w);
483 glVertex3f (0, 0, w);
484 glVertex3f (0, -h, w);
485 glVertex3f (w, -h, w);
486 glVertex3f (w, 0, w);
488 glVertex3f (w, 0, w);
489 glVertex3f (w, -h, w);
490 glVertex3f (w, -h, 0);
491 glVertex3f (w, 0, 0);
493 glVertex3f (w, 0, 0);
494 glVertex3f (w, -h, 0);
495 glVertex3f (0, -h, 0);
496 glVertex3f (0, 0, 0);
498 glVertex3f (0, -h, 0);
499 glVertex3f (w, -h, 0);
500 glVertex3f (w, -h, w);
501 glVertex3f (0, -h, w);
503 mi->polygon_count += 4;
506 glEnable(GL_LIGHTING);
510 static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire)
513 glEnable(GL_TEXTURE_2D);
514 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
515 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
517 glColor4f(0.5, 0.5, 0.5, 1.0);
518 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
522 if(cs->moving) drawMovingPiece(mi, cs, 0);
523 if(cs->take) drawTakePiece(mi, cs, 0);
524 glDisable(GL_TEXTURE_2D);
527 static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire)
530 glEnable(GL_TEXTURE_2D);
531 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
532 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
535 /* use the stencil */
536 glDisable(GL_LIGHTING);
537 glDisable(GL_COLOR_MATERIAL);
538 glDisable(GL_DEPTH_TEST);
539 glDisable(GL_TEXTURE_2D);
542 glClear(GL_STENCIL_BUFFER_BIT);
543 glColorMask(0,0,0,0);
544 glEnable(GL_STENCIL_TEST);
546 glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL);
547 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
551 glTranslatef(0.0, 0.001, 0.0);
553 /* draw the pieces */
554 drawPiecesShadow(mi, cs);
555 if(cs->moving) drawMovingPiece(mi, cs, shadows);
556 if(cs->take) drawTakePiece(mi, cs, shadows);
561 /* turn on drawing into colour buffer */
562 glColorMask(1,1,1,1);
564 /* programming with effect */
565 glDisable(GL_LIGHTING);
566 glDisable(GL_COLOR_MATERIAL);
567 glDisable(GL_TEXTURE_2D);
569 /* now draw the union of the shadows */
573 want to keep alpha values (alpha is involved in transition
574 effects of the active pieces).
577 glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL);
578 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
582 glColor4fv(MaterialShadow);
584 /* draw the board generously to fill the shadows */
587 glVertex3f(-1.0, 0.0, -1.0);
588 glVertex3f(-1.0, 0.0, BOARDSIZE + 1.0);
589 glVertex3f(1.0 + BOARDSIZE, 0.0, BOARDSIZE + 1.0);
590 glVertex3f(1.0 + BOARDSIZE, 0.0, -1.0);
594 glDisable(GL_STENCIL_TEST);
596 /* "pop" attributes */
597 glEnable(GL_TEXTURE_2D);
598 glEnable(GL_COLOR_MATERIAL);
599 glEnable(GL_LIGHTING);
600 glEnable(GL_CULL_FACE);
609 /* create a matrix that will project the desired shadow */
610 static void shadowmatrix(GLfloat shadowMat[4][4],
611 GLfloat groundplane[4],
616 /* find dot product between light position vector and ground plane normal */
617 dot = groundplane[X] * lightpos[X] +
618 groundplane[Y] * lightpos[Y] +
619 groundplane[Z] * lightpos[Z] +
620 groundplane[W] * lightpos[W];
622 shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
623 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
624 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
625 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
627 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
628 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
629 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
630 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
632 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
633 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
634 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
635 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
637 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
638 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
639 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
640 shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
643 /** reflectionboard */
644 static void draw_reflections(ModeInfo *mi, Chesscreen *cs)
648 glEnable(GL_STENCIL_TEST);
649 glStencilFunc(GL_ALWAYS, 1, 1);
650 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
651 glColorMask(0,0,0,0);
652 glDisable(GL_CULL_FACE);
654 glDisable(GL_DEPTH_TEST);
657 /* only draw white squares */
658 for(i = 0; i < BOARDSIZE; ++i) {
659 for(j = (BOARDSIZE+i) % 2; j < BOARDSIZE; j += 2) {
660 glVertex3f(i, 0.0, j + 1.0);
661 glVertex3f(i + 1.0, 0.0, j + 1.0);
662 glVertex3f(i + 1.0, 0.0, j);
663 glVertex3f(i, 0.0, j);
668 glEnable(GL_DEPTH_TEST);
670 glColorMask(1, 1, 1, 1);
671 glStencilFunc(GL_EQUAL, 1, 1);
672 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
675 glScalef(1.0, -1.0, 1.0);
676 glTranslatef(0.5, 0.0, 0.5);
678 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
679 draw_pieces(mi, cs, cs->wire);
682 glDisable(GL_STENCIL_TEST);
683 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
685 glEnable(GL_CULL_FACE);
687 glColorMask(1,1,1,1);
690 /** draws the scene */
691 static void display(ModeInfo *mi, Chesscreen *cs)
693 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
695 mi->polygon_count = 0;
697 glMatrixMode(GL_MODELVIEW);
699 glRotatef(current_device_rotation(), 0, 0, 1);
701 /** setup perspectiv */
702 glTranslatef(0.0, 0.0, -1.5*BOARDSIZE);
703 glRotatef(30.0, 1.0, 0.0, 0.0);
704 gltrackball_rotate (cs->trackball);
707 glRotatef(cs->theta*100, 0.0, 1.0, 0.0);
708 glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE);
710 /* cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */
711 /* cs->position[2] = 4.0 + 1.0* cos(cs->theta*100*M_PI/180.0); */
712 /* cs->position[1] = 5.0; */
714 /* this is the lone light that the shadow matrix is generated from */
715 cs->position[0] = 1.0;
716 cs->position[2] = 1.0;
717 cs->position[1] = 16.0;
719 cs->position2[0] = 4.0 + 8.0*-sin(cs->theta*100*M_PI/180.0);
720 cs->position2[2] = 4.0 + 8.0* cos(cs->theta*100*M_PI/180.0);
723 glEnable(GL_LIGHTING);
724 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
725 glLightfv(GL_LIGHT1, GL_POSITION, cs->position2);
729 /** draw board, pieces */
731 glEnable(GL_LIGHTING);
732 glEnable(GL_COLOR_MATERIAL);
734 if(reflections && !cs->wire) {
735 draw_reflections(mi, cs);
739 glEnable(GL_TEXTURE_2D);
740 glBindTexture(GL_TEXTURE_2D, cs->boardtexture);
742 glDisable(GL_TEXTURE_2D);
747 shadowmatrix(m, cs->ground, cs->position);
749 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
751 glDisable(GL_LIGHTING);
752 glDisable(GL_DEPTH_TEST);
754 /* display ant shadow */
756 glTranslatef(0.0, 0.001, 0.0);
758 glTranslatef(0.5, 0.01, 0.5);
759 draw_shadow_pieces(mi, cs, cs->wire);
762 glEnable(GL_LIGHTING);
764 glEnable(GL_DEPTH_TEST);
773 glTranslatef(0.5, 0.0, 0.5);
774 draw_pieces(mi, cs, cs->wire);
777 glDisable(GL_COLOR_MATERIAL);
778 glDisable(GL_LIGHTING);
781 if (!cs->button_down_p)
785 /** reshape handler */
786 ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height)
788 GLfloat h = (GLfloat) height / (GLfloat) width;
789 glViewport(0,0, width, height);
790 glMatrixMode(GL_PROJECTION);
792 gluPerspective(45, 1/h, 2.0, 30.0);
793 glMatrixMode(GL_MODELVIEW);
796 /** initialization handler */
797 ENTRYPOINT void init_chess(ModeInfo *mi)
800 int screen = MI_SCREEN(mi);
803 !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen))))
807 cs->window = MI_WINDOW(mi);
808 cs->wire = MI_IS_WIREFRAME(mi);
809 cs->trackball = gltrackball_init (False);
813 cs->colors[0][0] = 1.0;
814 cs->colors[0][1] = 0.5;
815 cs->colors[0][2] = 0.0;
817 cs->colors[1][0] = 0.6;
818 cs->colors[1][1] = 0.6;
819 cs->colors[1][2] = 0.6;
825 /* cs->position[0] = 0.0; */
826 /* cs->position[1] = 5.0; */
827 /* cs->position[2] = 5.0; */
828 /* cs->position[3] = 1.0; */
830 cs->position[0] = 0.0;
831 cs->position[1] = 24.0;
832 cs->position[2] = 2.0;
833 cs->position[3] = 1.0;
836 cs->position2[0] = 5.0;
837 cs->position2[1] = 5.0;
838 cs->position2[2] = 5.0;
839 cs->position2[3] = 1.0;
844 cs->ground[3] = -0.00001;
849 if((cs->glx_context = init_GL(mi)))
850 reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
855 glDepthFunc(GL_LEQUAL);
857 glEnable(GL_CULL_FACE);
860 make_piece_texture(cs);
861 make_board_texture(cs);
863 chessmodels_gen_lists( classic, cs->poly_counts);
865 # ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */
871 glColorMaterial(GL_FRONT, GL_DIFFUSE);
872 glShadeModel(smooth ? GL_SMOOTH : GL_FLAT);
873 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
874 glEnable(GL_DEPTH_TEST);
877 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
880 /** does dirty work drawing scene, moving pieces */
881 ENTRYPOINT void draw_chess(ModeInfo *mi)
883 Chesscreen *cs = &qs[MI_SCREEN(mi)];
884 Window w = MI_WINDOW(mi);
885 Display *disp = MI_DISPLAY(mi);
890 glXMakeCurrent(disp, w, *(cs->glx_context));
892 /** code for moving a piece */
893 if(cs->moving && ++cs->steps == 100) {
894 cs->moving = cs->count = cs->steps = cs->take = 0;
895 cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = cs->mpiece;
898 if(cs->mc == cs->game.movecount) {
904 if(++cs->count == 100) {
906 cs->mpiece = cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]];
907 cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]] = NONE;
909 if((cs->tpiece = cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]])) {
910 cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = NONE;
914 cs->from[0] = cs->game.moves[cs->mc][0];
915 cs->from[1] = cs->game.moves[cs->mc][1];
916 cs->to[0] = cs->game.moves[cs->mc][2];
917 cs->to[1] = cs->game.moves[cs->mc][3];
919 cs->dz = (cs->to[0] - cs->from[0]) / 100;
920 cs->dx = (cs->to[1] - cs->from[1]) / 100;
924 else if(cs->done == 1) {
925 int newgame = cs->oldgame;
926 while(newgame == cs->oldgame)
927 newgame = random()%GAMES;
930 cs->mod = 0.6 + (random()%20)/10.0;
933 cs->oldgame = newgame;
934 cs->game = games[cs->oldgame];
947 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION,
948 cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count);
949 glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION,
950 cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count);
951 glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.14);
952 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.14);
957 if(mi->fps_p) do_fps(mi);
959 glXSwapBuffers(disp, w);
963 ENTRYPOINT void release_chess(ModeInfo *mi)
972 XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess)