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(event->xany.type == ButtonPress && event->xbutton.button == Button1) {
208 cs->button_down_p = True;
209 gltrackball_start (cs->trackball,
210 event->xbutton.x, event->xbutton.y,
211 MI_WIDTH (mi), MI_HEIGHT (mi));
214 else if(event->xany.type == ButtonRelease
215 && event->xbutton.button == Button1) {
216 cs->button_down_p = False;
219 else if (event->xany.type == ButtonPress &&
220 (event->xbutton.button == Button4 ||
221 event->xbutton.button == Button5 ||
222 event->xbutton.button == Button6 ||
223 event->xbutton.button == Button7))
225 gltrackball_mousewheel (cs->trackball, event->xbutton.button, 5,
226 !event->xbutton.state);
229 else if(event->xany.type == MotionNotify && cs->button_down_p) {
230 gltrackball_track (cs->trackball,
231 event->xmotion.x, event->xmotion.y,
232 MI_WIDTH (mi), MI_HEIGHT (mi));
239 static const GLfloat diffuse2[] = {1.0, 1.0, 1.0, 1.0};
240 /*static const GLfloat ambient2[] = {0.7, 0.7, 0.7, 1.0};*/
241 static const GLfloat shininess[] = {60.0};
242 static const GLfloat specular[] = {0.4, 0.4, 0.4, 1.0};
244 /* configure lighting */
245 static void setup_lights(Chesscreen *cs)
247 glEnable(GL_LIGHTING);
248 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
249 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse2);
252 /* glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient2); */
254 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
255 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
257 glLightfv(GL_LIGHT1, GL_SPECULAR, diffuse2);
258 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse2);
263 static void drawPieces(ModeInfo *mi, Chesscreen *cs)
267 for(i = 0; i < BOARDSIZE; ++i) {
268 for(j = 0; j < BOARDSIZE; ++j) {
269 if(cs->game.board[i][j]) {
270 int c = cs->game.board[i][j]/PIECES;
271 glColor3fv(cs->colors[c]);
272 glCallList(cs->game.board[i][j]%PIECES);
273 mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES];
276 glTranslatef(1.0, 0.0, 0.0);
279 glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0);
282 glTranslatef(0.0, 0.0, -1.0*BOARDSIZE);
286 static void drawPiecesShadow(ModeInfo *mi, Chesscreen *cs)
290 for(i = 0; i < BOARDSIZE; ++i) {
291 for(j = 0; j < BOARDSIZE; ++j) {
292 if(cs->game.board[i][j]) {
293 glColor4f(0.0, 0.0, 0.0, 0.4);
294 glCallList(cs->game.board[i][j]%PIECES);
295 mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES];
298 glTranslatef(1.0, 0.0, 0.0);
301 glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0);
304 glTranslatef(0.0, 0.0, -1.0*BOARDSIZE);
307 /* draw a moving piece */
308 static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow)
310 int piece = cs->mpiece % PIECES;
312 if (piece == NONE) return;
316 if(shadow) glColor4fv(MaterialShadow);
317 else glColor3fv(cs->colors[cs->mpiece/PIECES]);
319 /** assume a queening. should be more general */
320 if((cs->mpiece == PAWN && fabs(cs->to[0]) < 0.01) ||
321 (cs->mpiece == BPAWN && fabs(cs->to[0]-7.0) < 0.01)) {
322 glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz);
324 glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->mpiece/7][0],
325 shadow ? MaterialShadow[1] : cs->colors[cs->mpiece/7][1],
326 shadow ? MaterialShadow[2] : cs->colors[cs->mpiece/7][2],
327 (fabs(50.0-cs->steps))/50.0);
329 piece = cs->steps < 50 ? PAWN : QUEEN;
333 cs->mpiece = cs->mpiece == PAWN ? QUEEN : BQUEEN;
335 else if(cs->mpiece % PIECES == KNIGHT) {
336 /* If there is nothing in the path of a knight, move it by sliding,
337 just like the other pieces. But if there are any pieces on the
338 middle two squares in its path, the knight would intersect them,
339 so in that case, move it in an airborne arc. */
342 Bool blocked_p = False;
343 int fromx = MIN(cs->from[1], cs->to[1]);
344 int fromy = MIN(cs->from[0], cs->to[0]);
345 int tox = MAX(cs->from[1], cs->to[1]);
346 int toy = MAX(cs->from[0], cs->to[0]);
347 if (fromx == tox-2) fromx = tox = fromx+1;
348 if (fromy == toy-2) fromy = toy = fromy+1;
349 for (i = fromy; i <= toy; i++) {
350 for (j = fromx; j <= tox; j++) {
351 if (cs->game.board[i][j]) {
361 /* Move by hopping. */
362 y = 1.5 * sin (M_PI * cs->steps / 100.0);
363 glTranslatef(cs->from[1]+cs->steps*cs->dx, y,
364 cs->from[0]+cs->steps*cs->dz);
368 /* Move by sliding. */
369 glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz);
377 mi->polygon_count += cs->poly_counts[cs->mpiece % PIECES];
379 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
380 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
388 /** code to squish a taken piece */
389 static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow)
394 glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][0],
395 shadow ? MaterialShadow[1] : cs->colors[cs->tpiece/7][1],
396 shadow ? MaterialShadow[2] : cs->colors[cs->tpiece/7][2],
397 (100-1.6*cs->steps)/100.0);
399 glTranslatef(cs->to[1], 0.0, cs->to[0]);
401 if(cs->mpiece % PIECES == KNIGHT)
402 glScalef(1.0+cs->steps/100.0, 1.0, 1.0+cs->steps/100.0);
404 glScalef(1.0, 1 - cs->steps/50.0 > 0.01 ? 1 - cs->steps/50.0 : 0.01, 1.0);
405 glCallList(cs->tpiece % 7);
406 mi->polygon_count += cs->poly_counts[cs->tpiece % PIECES];
413 static void drawBoard(ModeInfo *mi, Chesscreen *cs)
419 for(i = 0; i < BOARDSIZE; ++i)
420 for(j = 0; j < BOARDSIZE; ++j) {
421 double ma1 = (i+j)%2 == 0 ? cs->mod*i : 0.0;
422 double mb1 = (i+j)%2 == 0 ? cs->mod*j : 0.0;
423 double ma2 = (i+j)%2 == 0 ? cs->mod*(i+1.0) : 0.01;
424 double mb2 = (i+j)%2 == 0 ? cs->mod*(j+1.0) : 0.01;
426 /*glColor3fv(colors[(i+j)%2]);*/
427 glColor4f(cs->colors[(i+j)%2][0], cs->colors[(i+j)%2][1],
428 cs->colors[(i+j)%2][2], 0.65);
430 glNormal3f(0.0, 1.0, 0.0);
431 /* glTexCoord2f(mod*i, mod*(j+1.0)); */
432 glTexCoord2f(ma1, mb2);
433 glVertex3f(i, 0.0, j + 1.0);
434 /* glTexCoord2f(mod*(i+1.0), mod*(j+1.0)); */
435 glTexCoord2f(ma2, mb2);
436 glVertex3f(i + 1.0, 0.0, j + 1.0);
437 glTexCoord2f(ma2, mb1);
438 /* glTexCoord2f(mod*(i+1.0), mod*j); */
439 glVertex3f(i + 1.0, 0.0, j);
440 glTexCoord2f(ma1, mb1);
441 /* glTexCoord2f(mod*i, mod*j); */
442 glVertex3f(i, 0.0, j);
450 GLfloat w = BOARDSIZE;
453 /* Give the board a slight lip. */
454 /* #### oops, normals are wrong here, but you can't tell */
456 glColor3f(0.3, 0.3, 0.3);
458 glVertex3f (0, 0, 0);
459 glVertex3f (0, -h, 0);
460 glVertex3f (0, -h, w);
461 glVertex3f (0, 0, w);
463 glVertex3f (0, 0, w);
464 glVertex3f (0, -h, w);
465 glVertex3f (w, -h, w);
466 glVertex3f (w, 0, w);
468 glVertex3f (w, 0, w);
469 glVertex3f (w, -h, w);
470 glVertex3f (w, -h, 0);
471 glVertex3f (w, 0, 0);
473 glVertex3f (w, 0, 0);
474 glVertex3f (w, -h, 0);
475 glVertex3f (0, -h, 0);
476 glVertex3f (0, 0, 0);
478 glVertex3f (0, -h, 0);
479 glVertex3f (w, -h, 0);
480 glVertex3f (w, -h, w);
481 glVertex3f (0, -h, w);
483 mi->polygon_count += 4;
485 /* Fill in the underside of the board with an invisible black box
486 to hide the reflections that are not on tiles. Probably there's
487 a way to do this with stencils instead.
493 glTranslatef (off, 0, off);
494 glDisable(GL_LIGHTING);
497 glVertex3f (0, 0, 0);
498 glVertex3f (0, -h, 0);
499 glVertex3f (0, -h, w);
500 glVertex3f (0, 0, w);
502 glVertex3f (0, 0, w);
503 glVertex3f (0, -h, w);
504 glVertex3f (w, -h, w);
505 glVertex3f (w, 0, w);
507 glVertex3f (w, 0, w);
508 glVertex3f (w, -h, w);
509 glVertex3f (w, -h, 0);
510 glVertex3f (w, 0, 0);
512 glVertex3f (w, 0, 0);
513 glVertex3f (w, -h, 0);
514 glVertex3f (0, -h, 0);
515 glVertex3f (0, 0, 0);
517 glVertex3f (0, -h, 0);
518 glVertex3f (w, -h, 0);
519 glVertex3f (w, -h, w);
520 glVertex3f (0, -h, w);
522 mi->polygon_count += 4;
525 glEnable(GL_LIGHTING);
529 static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire)
532 glEnable(GL_TEXTURE_2D);
533 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
534 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
536 glColor4f(0.5, 0.5, 0.5, 1.0);
537 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
541 if(cs->moving) drawMovingPiece(mi, cs, 0);
542 if(cs->take) drawTakePiece(mi, cs, 0);
543 glDisable(GL_TEXTURE_2D);
546 static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire)
549 glEnable(GL_TEXTURE_2D);
550 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
551 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
554 /* use the stencil */
555 glDisable(GL_LIGHTING);
556 glDisable(GL_COLOR_MATERIAL);
557 glDisable(GL_DEPTH_TEST);
558 glDisable(GL_TEXTURE_2D);
561 glClear(GL_STENCIL_BUFFER_BIT);
562 glColorMask(0,0,0,0);
563 glEnable(GL_STENCIL_TEST);
565 glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL);
566 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
570 glTranslatef(0.0, 0.001, 0.0);
572 /* draw the pieces */
573 drawPiecesShadow(mi, cs);
574 if(cs->moving) drawMovingPiece(mi, cs, shadows);
575 if(cs->take) drawTakePiece(mi, cs, shadows);
580 /* turn on drawing into colour buffer */
581 glColorMask(1,1,1,1);
583 /* programming with effect */
584 glDisable(GL_LIGHTING);
585 glDisable(GL_COLOR_MATERIAL);
586 glDisable(GL_TEXTURE_2D);
588 /* now draw the union of the shadows */
592 want to keep alpha values (alpha is involved in transition
593 effects of the active pieces).
596 glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL);
597 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
601 glColor4fv(MaterialShadow);
603 /* draw the board generously to fill the shadows */
606 glVertex3f(-1.0, 0.0, -1.0);
607 glVertex3f(-1.0, 0.0, BOARDSIZE + 1.0);
608 glVertex3f(1.0 + BOARDSIZE, 0.0, BOARDSIZE + 1.0);
609 glVertex3f(1.0 + BOARDSIZE, 0.0, -1.0);
613 glDisable(GL_STENCIL_TEST);
615 /* "pop" attributes */
616 glEnable(GL_TEXTURE_2D);
617 glEnable(GL_COLOR_MATERIAL);
618 glEnable(GL_LIGHTING);
619 glEnable(GL_CULL_FACE);
628 /* create a matrix that will project the desired shadow */
629 static void shadowmatrix(GLfloat shadowMat[4][4],
630 GLfloat groundplane[4],
635 /* find dot product between light position vector and ground plane normal */
636 dot = groundplane[X] * lightpos[X] +
637 groundplane[Y] * lightpos[Y] +
638 groundplane[Z] * lightpos[Z] +
639 groundplane[W] * lightpos[W];
641 shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
642 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
643 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
644 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
646 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
647 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
648 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
649 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
651 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
652 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
653 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
654 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
656 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
657 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
658 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
659 shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
662 /** reflectionboard */
663 static void draw_reflections(ModeInfo *mi, Chesscreen *cs)
667 glEnable(GL_STENCIL_TEST);
668 glStencilFunc(GL_ALWAYS, 1, 1);
669 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
670 glColorMask(0,0,0,0);
671 glDisable(GL_CULL_FACE);
673 glDisable(GL_DEPTH_TEST);
676 /* only draw white squares */
677 for(i = 0; i < BOARDSIZE; ++i) {
678 for(j = (BOARDSIZE+i) % 2; j < BOARDSIZE; j += 2) {
679 glVertex3f(i, 0.0, j + 1.0);
680 glVertex3f(i + 1.0, 0.0, j + 1.0);
681 glVertex3f(i + 1.0, 0.0, j);
682 glVertex3f(i, 0.0, j);
687 glEnable(GL_DEPTH_TEST);
689 glColorMask(1, 1, 1, 1);
690 glStencilFunc(GL_EQUAL, 1, 1);
691 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
694 glScalef(1.0, -1.0, 1.0);
695 glTranslatef(0.5, 0.0, 0.5);
697 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
698 draw_pieces(mi, cs, cs->wire);
701 glDisable(GL_STENCIL_TEST);
702 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
704 glEnable(GL_CULL_FACE);
706 glColorMask(1,1,1,1);
709 /** draws the scene */
710 static void display(ModeInfo *mi, Chesscreen *cs)
712 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
714 mi->polygon_count = 0;
716 glMatrixMode(GL_MODELVIEW);
718 glRotatef(current_device_rotation(), 0, 0, 1);
720 /** setup perspectiv */
721 glTranslatef(0.0, 0.0, -1.5*BOARDSIZE);
722 glRotatef(30.0, 1.0, 0.0, 0.0);
723 gltrackball_rotate (cs->trackball);
726 glRotatef(cs->theta*100, 0.0, 1.0, 0.0);
727 glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE);
729 /* cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */
730 /* cs->position[2] = 4.0 + 1.0* cos(cs->theta*100*M_PI/180.0); */
731 /* cs->position[1] = 5.0; */
733 /* this is the lone light that the shadow matrix is generated from */
734 cs->position[0] = 1.0;
735 cs->position[2] = 1.0;
736 cs->position[1] = 16.0;
738 cs->position2[0] = 4.0 + 8.0*-sin(cs->theta*100*M_PI/180.0);
739 cs->position2[2] = 4.0 + 8.0* cos(cs->theta*100*M_PI/180.0);
742 glEnable(GL_LIGHTING);
743 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
744 glLightfv(GL_LIGHT1, GL_POSITION, cs->position2);
748 /** draw board, pieces */
750 glEnable(GL_LIGHTING);
751 glEnable(GL_COLOR_MATERIAL);
753 if(reflections && !cs->wire) {
754 draw_reflections(mi, cs);
758 glEnable(GL_TEXTURE_2D);
759 glBindTexture(GL_TEXTURE_2D, cs->boardtexture);
761 glDisable(GL_TEXTURE_2D);
766 shadowmatrix(m, cs->ground, cs->position);
768 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
770 glDisable(GL_LIGHTING);
771 glDisable(GL_DEPTH_TEST);
773 /* display ant shadow */
775 glTranslatef(0.0, 0.001, 0.0);
777 glTranslatef(0.5, 0.01, 0.5);
778 draw_shadow_pieces(mi, cs, cs->wire);
781 glEnable(GL_LIGHTING);
783 glEnable(GL_DEPTH_TEST);
792 glTranslatef(0.5, 0.0, 0.5);
793 draw_pieces(mi, cs, cs->wire);
796 glDisable(GL_COLOR_MATERIAL);
797 glDisable(GL_LIGHTING);
800 if (!cs->button_down_p)
804 /** reshape handler */
805 ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height)
807 GLfloat h = (GLfloat) height / (GLfloat) width;
808 glViewport(0,0, width, height);
809 glMatrixMode(GL_PROJECTION);
811 gluPerspective(45, 1/h, 2.0, 30.0);
812 glMatrixMode(GL_MODELVIEW);
815 /** initialization handler */
816 ENTRYPOINT void init_chess(ModeInfo *mi)
819 int screen = MI_SCREEN(mi);
822 !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen))))
826 cs->window = MI_WINDOW(mi);
827 cs->wire = MI_IS_WIREFRAME(mi);
828 cs->trackball = gltrackball_init ();
832 cs->colors[0][0] = 1.0;
833 cs->colors[0][1] = 0.5;
834 cs->colors[0][2] = 0.0;
836 cs->colors[1][0] = 0.6;
837 cs->colors[1][1] = 0.6;
838 cs->colors[1][2] = 0.6;
844 /* cs->position[0] = 0.0; */
845 /* cs->position[1] = 5.0; */
846 /* cs->position[2] = 5.0; */
847 /* cs->position[3] = 1.0; */
849 cs->position[0] = 0.0;
850 cs->position[1] = 24.0;
851 cs->position[2] = 2.0;
852 cs->position[3] = 1.0;
855 cs->position2[0] = 5.0;
856 cs->position2[1] = 5.0;
857 cs->position2[2] = 5.0;
858 cs->position2[3] = 1.0;
863 cs->ground[3] = -0.00001;
868 if((cs->glx_context = init_GL(mi)))
869 reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
874 glDepthFunc(GL_LEQUAL);
876 glEnable(GL_CULL_FACE);
879 make_piece_texture(cs);
880 make_board_texture(cs);
882 chessmodels_gen_lists( classic, cs->poly_counts);
886 glColorMaterial(GL_FRONT, GL_DIFFUSE);
887 glShadeModel(smooth ? GL_SMOOTH : GL_FLAT);
888 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
889 glEnable(GL_DEPTH_TEST);
892 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
895 /** does dirty work drawing scene, moving pieces */
896 ENTRYPOINT void draw_chess(ModeInfo *mi)
898 Chesscreen *cs = &qs[MI_SCREEN(mi)];
899 Window w = MI_WINDOW(mi);
900 Display *disp = MI_DISPLAY(mi);
905 glXMakeCurrent(disp, w, *(cs->glx_context));
907 /** code for moving a piece */
908 if(cs->moving && ++cs->steps == 100) {
909 cs->moving = cs->count = cs->steps = cs->take = 0;
910 cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = cs->mpiece;
913 if(cs->mc == cs->game.movecount) {
919 if(++cs->count == 100) {
921 cs->mpiece = cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]];
922 cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]] = NONE;
924 if((cs->tpiece = cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]])) {
925 cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = NONE;
929 cs->from[0] = cs->game.moves[cs->mc][0];
930 cs->from[1] = cs->game.moves[cs->mc][1];
931 cs->to[0] = cs->game.moves[cs->mc][2];
932 cs->to[1] = cs->game.moves[cs->mc][3];
934 cs->dz = (cs->to[0] - cs->from[0]) / 100;
935 cs->dx = (cs->to[1] - cs->from[1]) / 100;
939 else if(cs->done == 1) {
940 int newgame = cs->oldgame;
941 while(newgame == cs->oldgame)
942 newgame = random()%GAMES;
945 cs->mod = 0.6 + (random()%20)/10.0;
948 cs->oldgame = newgame;
949 cs->game = games[cs->oldgame];
962 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION,
963 cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count);
964 glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION,
965 cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count);
966 glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.14);
967 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.14);
972 if(mi->fps_p) do_fps(mi);
974 glXSwapBuffers(disp, w);
978 ENTRYPOINT void release_chess(ModeInfo *mi)
987 XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess)