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 # define release_chess 0
25 # include "xlockmore.h"
36 #include "gltrackball.h"
37 #include "chessmodels.h"
38 #include "chessgames.h"
41 #define countof(x) (sizeof((x))/sizeof((*x)))
43 #define DEF_ROTATE "True"
44 #define DEF_REFLECTIONS "True"
45 #define DEF_SHADOWS "True"
46 #define DEF_SMOOTH "True"
47 #define DEF_CLASSIC "False"
50 static XrmOptionDescRec opts[] = {
51 {"+rotate", ".chess.rotate", XrmoptionNoArg, "false" },
52 {"-rotate", ".chess.rotate", XrmoptionNoArg, "true" },
53 {"+reflections", ".chess.reflections", XrmoptionNoArg, "false" },
54 {"-reflections", ".chess.reflections", XrmoptionNoArg, "true" },
55 {"+shadows", ".chess.shadows", XrmoptionNoArg, "false" },
56 {"-shadows", ".chess.shadows", XrmoptionNoArg, "true" },
57 {"+smooth", ".chess.smooth", XrmoptionNoArg, "false" },
58 {"-smooth", ".chess.smooth", XrmoptionNoArg, "true" },
59 {"+classic", ".chess.classic", XrmoptionNoArg, "false" },
60 {"-classic", ".chess.classic", XrmoptionNoArg, "true" },
63 static int rotate, reflections, smooth, shadows, classic;
65 static argtype vars[] = {
66 {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool},
67 {&reflections, "reflections", "Reflections", DEF_REFLECTIONS, t_Bool},
68 {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool},
69 {&smooth, "smooth", "Smooth", DEF_SMOOTH, t_Bool},
70 {&classic, "classic", "Classic", DEF_CLASSIC, t_Bool},
73 ENTRYPOINT ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, NULL};
76 ModStruct chess_description =
77 {"chess", "init_chess", "draw_chess", NULL,
78 "draw_chess", "init_chess", NULL, &chess_opts,
79 1000, 1, 2, 1, 4, 1.0, "",
84 #define checkImageWidth 16
85 #define checkImageHeight 16
88 GLXContext *glx_context;
90 trackball_state *trackball;
96 /** definition of white/black (orange/gray) colors */
99 GLubyte checkImage[checkImageWidth][checkImageHeight][3];
100 GLuint piecetexture, boardtexture;
102 int mpiece, tpiece, steps, done;
103 double from[2], to[2];
105 int moving, take, mc, count, wire;
109 GLfloat position2[4];
117 int poly_counts[PIECES]; /* polygon count of each type of piece */
122 static Chesscreen *qs = NULL;
124 static const GLfloat MaterialShadow[] = {0.0, 0.0, 0.0, 0.3};
127 /* i prefer silvertip */
128 static const GLfloat whites[WHITES][3] =
137 static void build_colors(Chesscreen *cs)
141 int newwhite = cs->oldwhite;
142 while(newwhite == cs->oldwhite)
143 newwhite = random()%WHITES;
144 cs->oldwhite = newwhite;
146 cs->colors[0][0] = whites[cs->oldwhite][0];
147 cs->colors[0][1] = whites[cs->oldwhite][1];
148 cs->colors[0][2] = whites[cs->oldwhite][2];
151 /* build piece texture */
152 static void make_piece_texture(Chesscreen *cs)
156 for (i = 0; i < checkImageWidth; i++) {
157 for (j = 0; j < checkImageHeight; j++) {
158 c = ((j%2) == 0 || i%2 == 0) ? 240 : 180+random()%16;
159 cs->checkImage[i][j][0] = (GLubyte) c;
160 cs->checkImage[i][j][1] = (GLubyte) c;
161 cs->checkImage[i][j][2] = (GLubyte) c;
165 glGenTextures(1, &cs->piecetexture);
166 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
168 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
169 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
170 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
171 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
172 glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth,
173 checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
174 &cs->checkImage[0][0]);
177 /* build board texture (uniform noise in [180,180+50]) */
178 static void make_board_texture(Chesscreen *cs)
182 for (i = 0; i < checkImageWidth; i++) {
183 for (j = 0; j < checkImageHeight; j++) {
184 c = 180 + random()%51;
185 cs->checkImage[i][j][0] = (GLubyte) c;
186 cs->checkImage[i][j][1] = (GLubyte) c;
187 cs->checkImage[i][j][2] = (GLubyte) c;
191 glGenTextures(1, &cs->boardtexture);
192 glBindTexture(GL_TEXTURE_2D, cs->boardtexture);
194 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
195 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
196 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
197 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
198 glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth,
199 checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
200 &cs->checkImage[0][0]);
203 /** handle X event (trackball) */
204 ENTRYPOINT Bool chess_handle_event (ModeInfo *mi, XEvent *event)
206 Chesscreen *cs = &qs[MI_SCREEN(mi)];
208 if (gltrackball_event_handler (event, cs->trackball,
209 MI_WIDTH (mi), MI_HEIGHT (mi),
212 else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
221 static const GLfloat diffuse2[] = {1.0, 1.0, 1.0, 1.0};
222 /*static const GLfloat ambient2[] = {0.7, 0.7, 0.7, 1.0};*/
223 static const GLfloat shininess[] = {60.0};
224 static const GLfloat specular[] = {0.4, 0.4, 0.4, 1.0};
226 /* configure lighting */
227 static void setup_lights(Chesscreen *cs)
229 glEnable(GL_LIGHTING);
230 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
231 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse2);
234 /* glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient2); */
236 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
237 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
239 glLightfv(GL_LIGHT1, GL_SPECULAR, diffuse2);
240 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse2);
245 static void drawPieces(ModeInfo *mi, Chesscreen *cs)
249 for(i = 0; i < BOARDSIZE; ++i) {
250 for(j = 0; j < BOARDSIZE; ++j) {
251 if(cs->game.board[i][j]) {
252 int c = cs->game.board[i][j]/PIECES;
253 glColor3fv(cs->colors[c]);
254 glCallList(cs->game.board[i][j]%PIECES);
255 mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES];
258 glTranslatef(1.0, 0.0, 0.0);
261 glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0);
264 glTranslatef(0.0, 0.0, -1.0*BOARDSIZE);
268 static void drawPiecesShadow(ModeInfo *mi, Chesscreen *cs)
272 for(i = 0; i < BOARDSIZE; ++i) {
273 for(j = 0; j < BOARDSIZE; ++j) {
274 if(cs->game.board[i][j]) {
275 glColor4f(0.0, 0.0, 0.0, 0.4);
276 glCallList(cs->game.board[i][j]%PIECES);
277 mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES];
280 glTranslatef(1.0, 0.0, 0.0);
283 glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0);
286 glTranslatef(0.0, 0.0, -1.0*BOARDSIZE);
289 /* draw a moving piece */
290 static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow)
292 int piece = cs->mpiece % PIECES;
294 if (piece == NONE) return;
298 if(shadow) glColor4fv(MaterialShadow);
299 else glColor3fv(cs->colors[cs->mpiece/PIECES]);
301 /** assume a queening. should be more general */
302 if((cs->mpiece == PAWN && fabs(cs->to[0]) < 0.01) ||
303 (cs->mpiece == BPAWN && fabs(cs->to[0]-7.0) < 0.01)) {
304 glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz);
306 glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->mpiece/7][0],
307 shadow ? MaterialShadow[1] : cs->colors[cs->mpiece/7][1],
308 shadow ? MaterialShadow[2] : cs->colors[cs->mpiece/7][2],
309 (fabs(50.0-cs->steps))/50.0);
311 piece = cs->steps < 50 ? PAWN : QUEEN;
315 cs->mpiece = cs->mpiece == PAWN ? QUEEN : BQUEEN;
317 else if(cs->mpiece % PIECES == KNIGHT) {
318 /* If there is nothing in the path of a knight, move it by sliding,
319 just like the other pieces. But if there are any pieces on the
320 middle two squares in its path, the knight would intersect them,
321 so in that case, move it in an airborne arc. */
324 Bool blocked_p = False;
325 int fromx = MIN(cs->from[1], cs->to[1]);
326 int fromy = MIN(cs->from[0], cs->to[0]);
327 int tox = MAX(cs->from[1], cs->to[1]);
328 int toy = MAX(cs->from[0], cs->to[0]);
329 if (fromx == tox-2) fromx = tox = fromx+1;
330 if (fromy == toy-2) fromy = toy = fromy+1;
331 for (i = fromy; i <= toy; i++) {
332 for (j = fromx; j <= tox; j++) {
333 if (cs->game.board[i][j]) {
343 /* Move by hopping. */
344 y = 1.5 * sin (M_PI * cs->steps / 100.0);
345 glTranslatef(cs->from[1]+cs->steps*cs->dx, y,
346 cs->from[0]+cs->steps*cs->dz);
350 /* Move by sliding. */
351 glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz);
359 mi->polygon_count += cs->poly_counts[cs->mpiece % PIECES];
361 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
362 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
370 /** code to squish a taken piece */
371 static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow)
376 glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][0],
377 shadow ? MaterialShadow[1] : cs->colors[cs->tpiece/7][1],
378 shadow ? MaterialShadow[2] : cs->colors[cs->tpiece/7][2],
379 (100-1.6*cs->steps)/100.0);
381 glTranslatef(cs->to[1], 0.0, cs->to[0]);
383 if(cs->mpiece % PIECES == KNIGHT)
384 glScalef(1.0+cs->steps/100.0, 1.0, 1.0+cs->steps/100.0);
386 glScalef(1.0, 1 - cs->steps/50.0 > 0.01 ? 1 - cs->steps/50.0 : 0.01, 1.0);
387 glCallList(cs->tpiece % 7);
388 mi->polygon_count += cs->poly_counts[cs->tpiece % PIECES];
395 static void drawBoard(ModeInfo *mi, Chesscreen *cs)
401 for(i = 0; i < BOARDSIZE; ++i)
402 for(j = 0; j < BOARDSIZE; ++j) {
403 double ma1 = (i+j)%2 == 0 ? cs->mod*i : 0.0;
404 double mb1 = (i+j)%2 == 0 ? cs->mod*j : 0.0;
405 double ma2 = (i+j)%2 == 0 ? cs->mod*(i+1.0) : 0.01;
406 double mb2 = (i+j)%2 == 0 ? cs->mod*(j+1.0) : 0.01;
408 /*glColor3fv(colors[(i+j)%2]);*/
409 glColor4f(cs->colors[(i+j)%2][0], cs->colors[(i+j)%2][1],
410 cs->colors[(i+j)%2][2], 0.65);
412 glNormal3f(0.0, 1.0, 0.0);
413 /* glTexCoord2f(mod*i, mod*(j+1.0)); */
414 glTexCoord2f(ma1, mb2);
415 glVertex3f(i, 0.0, j + 1.0);
416 /* glTexCoord2f(mod*(i+1.0), mod*(j+1.0)); */
417 glTexCoord2f(ma2, mb2);
418 glVertex3f(i + 1.0, 0.0, j + 1.0);
419 glTexCoord2f(ma2, mb1);
420 /* glTexCoord2f(mod*(i+1.0), mod*j); */
421 glVertex3f(i + 1.0, 0.0, j);
422 glTexCoord2f(ma1, mb1);
423 /* glTexCoord2f(mod*i, mod*j); */
424 glVertex3f(i, 0.0, j);
432 GLfloat w = BOARDSIZE;
435 /* Give the board a slight lip. */
436 /* #### oops, normals are wrong here, but you can't tell */
438 glColor3f(0.3, 0.3, 0.3);
440 glVertex3f (0, 0, 0);
441 glVertex3f (0, -h, 0);
442 glVertex3f (0, -h, w);
443 glVertex3f (0, 0, w);
445 glVertex3f (0, 0, w);
446 glVertex3f (0, -h, w);
447 glVertex3f (w, -h, w);
448 glVertex3f (w, 0, w);
450 glVertex3f (w, 0, w);
451 glVertex3f (w, -h, w);
452 glVertex3f (w, -h, 0);
453 glVertex3f (w, 0, 0);
455 glVertex3f (w, 0, 0);
456 glVertex3f (w, -h, 0);
457 glVertex3f (0, -h, 0);
458 glVertex3f (0, 0, 0);
460 glVertex3f (0, -h, 0);
461 glVertex3f (w, -h, 0);
462 glVertex3f (w, -h, w);
463 glVertex3f (0, -h, w);
465 mi->polygon_count += 4;
467 /* Fill in the underside of the board with an invisible black box
468 to hide the reflections that are not on tiles. Probably there's
469 a way to do this with stencils instead.
475 glTranslatef (off, 0, off);
476 glDisable(GL_LIGHTING);
479 glVertex3f (0, 0, 0);
480 glVertex3f (0, -h, 0);
481 glVertex3f (0, -h, w);
482 glVertex3f (0, 0, w);
484 glVertex3f (0, 0, w);
485 glVertex3f (0, -h, w);
486 glVertex3f (w, -h, w);
487 glVertex3f (w, 0, w);
489 glVertex3f (w, 0, w);
490 glVertex3f (w, -h, w);
491 glVertex3f (w, -h, 0);
492 glVertex3f (w, 0, 0);
494 glVertex3f (w, 0, 0);
495 glVertex3f (w, -h, 0);
496 glVertex3f (0, -h, 0);
497 glVertex3f (0, 0, 0);
499 glVertex3f (0, -h, 0);
500 glVertex3f (w, -h, 0);
501 glVertex3f (w, -h, w);
502 glVertex3f (0, -h, w);
504 mi->polygon_count += 4;
507 glEnable(GL_LIGHTING);
511 static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire)
514 glEnable(GL_TEXTURE_2D);
515 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
516 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
518 glColor4f(0.5, 0.5, 0.5, 1.0);
519 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
523 if(cs->moving) drawMovingPiece(mi, cs, 0);
524 if(cs->take) drawTakePiece(mi, cs, 0);
525 glDisable(GL_TEXTURE_2D);
528 static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire)
531 glEnable(GL_TEXTURE_2D);
532 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
533 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
536 /* use the stencil */
537 glDisable(GL_LIGHTING);
538 glDisable(GL_COLOR_MATERIAL);
539 glDisable(GL_DEPTH_TEST);
540 glDisable(GL_TEXTURE_2D);
543 glClear(GL_STENCIL_BUFFER_BIT);
544 glColorMask(0,0,0,0);
545 glEnable(GL_STENCIL_TEST);
547 glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL);
548 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
552 glTranslatef(0.0, 0.001, 0.0);
554 /* draw the pieces */
555 drawPiecesShadow(mi, cs);
556 if(cs->moving) drawMovingPiece(mi, cs, shadows);
557 if(cs->take) drawTakePiece(mi, cs, shadows);
562 /* turn on drawing into colour buffer */
563 glColorMask(1,1,1,1);
565 /* programming with effect */
566 glDisable(GL_LIGHTING);
567 glDisable(GL_COLOR_MATERIAL);
568 glDisable(GL_TEXTURE_2D);
570 /* now draw the union of the shadows */
574 want to keep alpha values (alpha is involved in transition
575 effects of the active pieces).
578 glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL);
579 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
583 glColor4fv(MaterialShadow);
585 /* draw the board generously to fill the shadows */
588 glVertex3f(-1.0, 0.0, -1.0);
589 glVertex3f(-1.0, 0.0, BOARDSIZE + 1.0);
590 glVertex3f(1.0 + BOARDSIZE, 0.0, BOARDSIZE + 1.0);
591 glVertex3f(1.0 + BOARDSIZE, 0.0, -1.0);
595 glDisable(GL_STENCIL_TEST);
597 /* "pop" attributes */
598 glEnable(GL_TEXTURE_2D);
599 glEnable(GL_COLOR_MATERIAL);
600 glEnable(GL_LIGHTING);
601 glEnable(GL_CULL_FACE);
610 /* create a matrix that will project the desired shadow */
611 static void shadowmatrix(GLfloat shadowMat[4][4],
612 GLfloat groundplane[4],
617 /* find dot product between light position vector and ground plane normal */
618 dot = groundplane[X] * lightpos[X] +
619 groundplane[Y] * lightpos[Y] +
620 groundplane[Z] * lightpos[Z] +
621 groundplane[W] * lightpos[W];
623 shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
624 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
625 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
626 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
628 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
629 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
630 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
631 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
633 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
634 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
635 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
636 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
638 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
639 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
640 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
641 shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
644 /** reflectionboard */
645 static void draw_reflections(ModeInfo *mi, Chesscreen *cs)
649 glEnable(GL_STENCIL_TEST);
650 glStencilFunc(GL_ALWAYS, 1, 1);
651 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
652 glColorMask(0,0,0,0);
653 glDisable(GL_CULL_FACE);
655 glDisable(GL_DEPTH_TEST);
658 /* only draw white squares */
659 for(i = 0; i < BOARDSIZE; ++i) {
660 for(j = (BOARDSIZE+i) % 2; j < BOARDSIZE; j += 2) {
661 glVertex3f(i, 0.0, j + 1.0);
662 glVertex3f(i + 1.0, 0.0, j + 1.0);
663 glVertex3f(i + 1.0, 0.0, j);
664 glVertex3f(i, 0.0, j);
669 glEnable(GL_DEPTH_TEST);
671 glColorMask(1, 1, 1, 1);
672 glStencilFunc(GL_EQUAL, 1, 1);
673 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
676 glScalef(1.0, -1.0, 1.0);
677 glTranslatef(0.5, 0.0, 0.5);
679 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
680 draw_pieces(mi, cs, cs->wire);
683 glDisable(GL_STENCIL_TEST);
684 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
686 glEnable(GL_CULL_FACE);
688 glColorMask(1,1,1,1);
691 /** draws the scene */
692 static void display(ModeInfo *mi, Chesscreen *cs)
694 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
696 mi->polygon_count = 0;
698 glMatrixMode(GL_MODELVIEW);
700 glRotatef(current_device_rotation(), 0, 0, 1);
702 /** setup perspectiv */
703 glTranslatef(0.0, 0.0, -1.5*BOARDSIZE);
704 glRotatef(30.0, 1.0, 0.0, 0.0);
705 gltrackball_rotate (cs->trackball);
708 glRotatef(cs->theta*100, 0.0, 1.0, 0.0);
709 glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE);
711 /* cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */
712 /* cs->position[2] = 4.0 + 1.0* cos(cs->theta*100*M_PI/180.0); */
713 /* cs->position[1] = 5.0; */
715 /* this is the lone light that the shadow matrix is generated from */
716 cs->position[0] = 1.0;
717 cs->position[2] = 1.0;
718 cs->position[1] = 16.0;
720 cs->position2[0] = 4.0 + 8.0*-sin(cs->theta*100*M_PI/180.0);
721 cs->position2[2] = 4.0 + 8.0* cos(cs->theta*100*M_PI/180.0);
724 glEnable(GL_LIGHTING);
725 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
726 glLightfv(GL_LIGHT1, GL_POSITION, cs->position2);
730 /** draw board, pieces */
732 glEnable(GL_LIGHTING);
733 glEnable(GL_COLOR_MATERIAL);
735 if(reflections && !cs->wire) {
736 draw_reflections(mi, cs);
740 glEnable(GL_TEXTURE_2D);
741 glBindTexture(GL_TEXTURE_2D, cs->boardtexture);
743 glDisable(GL_TEXTURE_2D);
748 shadowmatrix(m, cs->ground, cs->position);
750 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
752 glDisable(GL_LIGHTING);
753 glDisable(GL_DEPTH_TEST);
755 /* display ant shadow */
757 glTranslatef(0.0, 0.001, 0.0);
759 glTranslatef(0.5, 0.01, 0.5);
760 draw_shadow_pieces(mi, cs, cs->wire);
763 glEnable(GL_LIGHTING);
765 glEnable(GL_DEPTH_TEST);
774 glTranslatef(0.5, 0.0, 0.5);
775 draw_pieces(mi, cs, cs->wire);
778 glDisable(GL_COLOR_MATERIAL);
779 glDisable(GL_LIGHTING);
782 if (!cs->button_down_p)
786 /** reshape handler */
787 ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height)
789 GLfloat h = (GLfloat) height / (GLfloat) width;
790 glViewport(0,0, width, height);
791 glMatrixMode(GL_PROJECTION);
793 gluPerspective(45, 1/h, 2.0, 30.0);
794 glMatrixMode(GL_MODELVIEW);
797 /** initialization handler */
798 ENTRYPOINT void init_chess(ModeInfo *mi)
801 int screen = MI_SCREEN(mi);
803 MI_INIT(mi, qs, NULL);
806 cs->window = MI_WINDOW(mi);
807 cs->wire = MI_IS_WIREFRAME(mi);
808 cs->trackball = gltrackball_init (False);
812 cs->colors[0][0] = 1.0;
813 cs->colors[0][1] = 0.5;
814 cs->colors[0][2] = 0.0;
816 cs->colors[1][0] = 0.6;
817 cs->colors[1][1] = 0.6;
818 cs->colors[1][2] = 0.6;
824 /* cs->position[0] = 0.0; */
825 /* cs->position[1] = 5.0; */
826 /* cs->position[2] = 5.0; */
827 /* cs->position[3] = 1.0; */
829 cs->position[0] = 0.0;
830 cs->position[1] = 24.0;
831 cs->position[2] = 2.0;
832 cs->position[3] = 1.0;
835 cs->position2[0] = 5.0;
836 cs->position2[1] = 5.0;
837 cs->position2[2] = 5.0;
838 cs->position2[3] = 1.0;
843 cs->ground[3] = -0.00001;
848 if((cs->glx_context = init_GL(mi)))
849 reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
854 glDepthFunc(GL_LEQUAL);
856 glEnable(GL_CULL_FACE);
859 make_piece_texture(cs);
860 make_board_texture(cs);
862 chessmodels_gen_lists( classic, cs->poly_counts);
864 # ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */
870 glColorMaterial(GL_FRONT, GL_DIFFUSE);
871 glShadeModel(smooth ? GL_SMOOTH : GL_FLAT);
872 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
873 glEnable(GL_DEPTH_TEST);
876 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
879 /** does dirty work drawing scene, moving pieces */
880 ENTRYPOINT void draw_chess(ModeInfo *mi)
882 Chesscreen *cs = &qs[MI_SCREEN(mi)];
883 Window w = MI_WINDOW(mi);
884 Display *disp = MI_DISPLAY(mi);
889 glXMakeCurrent(disp, w, *(cs->glx_context));
891 /** code for moving a piece */
892 if(cs->moving && ++cs->steps == 100) {
893 cs->moving = cs->count = cs->steps = cs->take = 0;
894 cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = cs->mpiece;
897 if(cs->mc == cs->game.movecount) {
903 if(++cs->count == 100) {
905 cs->mpiece = cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]];
906 cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]] = NONE;
908 if((cs->tpiece = cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]])) {
909 cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = NONE;
913 cs->from[0] = cs->game.moves[cs->mc][0];
914 cs->from[1] = cs->game.moves[cs->mc][1];
915 cs->to[0] = cs->game.moves[cs->mc][2];
916 cs->to[1] = cs->game.moves[cs->mc][3];
918 cs->dz = (cs->to[0] - cs->from[0]) / 100;
919 cs->dx = (cs->to[1] - cs->from[1]) / 100;
923 else if(cs->done == 1) {
924 int newgame = cs->oldgame;
925 while(newgame == cs->oldgame)
926 newgame = random()%GAMES;
929 cs->mod = 0.6 + (random()%20)/10.0;
932 cs->oldgame = newgame;
933 cs->game = games[cs->oldgame];
946 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION,
947 cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count);
948 glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION,
949 cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count);
950 glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.14);
951 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.14);
956 if(mi->fps_p) do_fps(mi);
958 glXSwapBuffers(disp, w);
961 XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess)